733 lines
24 KiB
C++
733 lines
24 KiB
C++
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2008 by Sun Microsystems, Inc.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: SlsSelectionManager.cxx,v $
|
|
*
|
|
* $Revision: 1.4 $
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
#include "precompiled_sd.hxx"
|
|
|
|
#include "controller/SlsSelectionManager.hxx"
|
|
|
|
#include "SlideSorter.hxx"
|
|
#include "SlsSelectionCommand.hxx"
|
|
#include "controller/SlideSorterController.hxx"
|
|
#include "controller/SlsAnimator.hxx"
|
|
#include "controller/SlsAnimationFunction.hxx"
|
|
#include "controller/SlsCurrentSlideManager.hxx"
|
|
#include "controller/SlsFocusManager.hxx"
|
|
#include "controller/SlsProperties.hxx"
|
|
#include "controller/SlsScrollBarManager.hxx"
|
|
#include "controller/SlsSlotManager.hxx"
|
|
#include "model/SlideSorterModel.hxx"
|
|
#include "model/SlsPageEnumerationProvider.hxx"
|
|
#include "model/SlsPageDescriptor.hxx"
|
|
#include "view/SlideSorterView.hxx"
|
|
#include "view/SlsLayouter.hxx"
|
|
#include "drawdoc.hxx"
|
|
#include "Window.hxx"
|
|
#include <svx/svxids.hrc>
|
|
#include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
|
|
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
|
|
|
|
#include "res_bmp.hrc"
|
|
#include "sdresid.hxx"
|
|
#include "strings.hrc"
|
|
#include "app.hrc"
|
|
#include "glob.hrc"
|
|
|
|
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::drawing;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::sd::slidesorter::model;
|
|
using namespace ::sd::slidesorter::view;
|
|
using namespace ::sd::slidesorter::controller;
|
|
|
|
namespace sd { namespace slidesorter { namespace controller {
|
|
|
|
|
|
namespace {
|
|
class VerticalVisibleAreaScroller
|
|
{
|
|
public:
|
|
VerticalVisibleAreaScroller (SlideSorter& rSlideSorter,
|
|
const double nStart, const double nEnd);
|
|
void operator() (const double nValue);
|
|
private:
|
|
SlideSorter& mrSlideSorter;
|
|
double mnStart;
|
|
const double mnEnd;
|
|
const ::boost::function<double(double)> maAccelerationFunction;
|
|
};
|
|
class HorizontalVisibleAreaScroller
|
|
{
|
|
public:
|
|
HorizontalVisibleAreaScroller (SlideSorter& rSlideSorter,
|
|
const double nStart, const double nEnd);
|
|
void operator() (const double nValue);
|
|
private:
|
|
SlideSorter& mrSlideSorter;
|
|
double mnStart;
|
|
const double mnEnd;
|
|
const ::boost::function<double(double)> maAccelerationFunction;
|
|
};
|
|
}
|
|
|
|
|
|
|
|
|
|
SelectionManager::SelectionManager (SlideSorter& rSlideSorter)
|
|
: mrSlideSorter(rSlideSorter),
|
|
mrController(rSlideSorter.GetController()),
|
|
maSelectionBeforeSwitch(),
|
|
mbIsMakeSelectionVisiblePending(true),
|
|
mnInsertionPosition(-1),
|
|
mnAnimationId(Animator::NotAnAnimationId)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
SelectionManager::~SelectionManager (void)
|
|
{
|
|
if (mnAnimationId != Animator::NotAnAnimationId)
|
|
mrController.GetAnimator()->RemoveAnimation(mnAnimationId);
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionManager::DeleteSelectedPages (void)
|
|
{
|
|
// Create some locks to prevent updates of the model, view, selection
|
|
// state while modifying any of them.
|
|
SlideSorterController::ModelChangeLock aLock (mrController);
|
|
SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
|
|
PageSelector::UpdateLock aSelectionLock (mrSlideSorter);
|
|
|
|
// Hide focus.
|
|
bool bIsFocusShowing = mrController.GetFocusManager().IsFocusShowing();
|
|
if (bIsFocusShowing)
|
|
mrController.GetFocusManager().ToggleFocus();
|
|
|
|
// Store pointers to all selected page descriptors. This is necessary
|
|
// because the pages get deselected when the first one is deleted.
|
|
model::PageEnumeration aPageEnumeration (
|
|
PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel()));
|
|
::std::vector<SdPage*> aSelectedPages;
|
|
sal_Int32 nLastPageIndex (-1);
|
|
while (aPageEnumeration.HasMoreElements())
|
|
{
|
|
SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
|
|
aSelectedPages.push_back(pDescriptor->GetPage());
|
|
nLastPageIndex = pDescriptor->GetPageIndex();
|
|
}
|
|
if (aSelectedPages.empty())
|
|
return;
|
|
|
|
// Determine the slide to select (and thereby make the current slide)
|
|
// after the deletion.
|
|
sal_Int32 nNewCurrentSlide (nLastPageIndex - aSelectedPages.size() + 1);
|
|
|
|
// The actual deletion of the selected pages is done in one of two
|
|
// helper functions. They are specialized for normal respectively for
|
|
// master pages.
|
|
mrSlideSorter.GetView().BegUndo (SdResId(STR_UNDO_DELETEPAGES));
|
|
if (mrSlideSorter.GetModel().GetEditMode() == EM_PAGE)
|
|
DeleteSelectedNormalPages(aSelectedPages);
|
|
else
|
|
DeleteSelectedMasterPages(aSelectedPages);
|
|
mrSlideSorter.GetView().EndUndo ();
|
|
|
|
mrController.HandleModelChange();
|
|
aLock.Release();
|
|
|
|
// Show focus and move it to next valid location.
|
|
if (bIsFocusShowing)
|
|
mrController.GetFocusManager().ToggleFocus();
|
|
|
|
// Set the new current slide.
|
|
if (nNewCurrentSlide >= mrSlideSorter.GetModel().GetPageCount())
|
|
nNewCurrentSlide = mrSlideSorter.GetModel().GetPageCount()-1;
|
|
mrController.GetPageSelector().SelectPage(nNewCurrentSlide);
|
|
mrController.GetFocusManager().SetFocusedPage(nNewCurrentSlide);
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionManager::DeleteSelectedNormalPages (const ::std::vector<SdPage*>& rSelectedPages)
|
|
{
|
|
// Prepare the deletion via the UNO API.
|
|
OSL_ASSERT(mrSlideSorter.GetModel().GetEditMode() == EM_PAGE);
|
|
|
|
try
|
|
{
|
|
Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier( mrSlideSorter.GetModel().GetDocument()->getUnoModel(), UNO_QUERY_THROW );
|
|
Reference<drawing::XDrawPages> xPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY_THROW );
|
|
|
|
// Iterate over all pages that where seleted when this method was called
|
|
// and delete the draw page the notes page. The iteration is done in
|
|
// reverse order so that when one slide is not deleted (to avoid an
|
|
// empty document) the remaining slide is the first one.
|
|
::std::vector<SdPage*>::const_reverse_iterator aI;
|
|
for (aI=rSelectedPages.rbegin(); aI!=rSelectedPages.rend(); aI++)
|
|
{
|
|
// Do not delete the last slide in the document.
|
|
if (xPages->getCount() <= 1)
|
|
break;
|
|
|
|
USHORT nPage = ((*aI)->GetPageNum()-1) / 2;
|
|
|
|
Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW );
|
|
xPages->remove(xPage);
|
|
}
|
|
}
|
|
catch( Exception& )
|
|
{
|
|
DBG_ERROR("SelectionManager::DeleteSelectedNormalPages(), exception caught!");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionManager::DeleteSelectedMasterPages (const ::std::vector<SdPage*>& rSelectedPages)
|
|
{
|
|
// Prepare the deletion via the UNO API.
|
|
OSL_ASSERT(mrSlideSorter.GetModel().GetEditMode() == EM_MASTERPAGE);
|
|
|
|
try
|
|
{
|
|
Reference<drawing::XMasterPagesSupplier> xDrawPagesSupplier( mrSlideSorter.GetModel().GetDocument()->getUnoModel(), UNO_QUERY_THROW );
|
|
Reference<drawing::XDrawPages> xPages( xDrawPagesSupplier->getMasterPages(), UNO_QUERY_THROW );
|
|
|
|
// Iterate over all pages that where seleted when this method was called
|
|
// and delete the draw page the notes page. The iteration is done in
|
|
// reverse order so that when one slide is not deleted (to avoid an
|
|
// empty document) the remaining slide is the first one.
|
|
::std::vector<SdPage*>::const_reverse_iterator aI;
|
|
for (aI=rSelectedPages.rbegin(); aI!=rSelectedPages.rend(); aI++)
|
|
{
|
|
// Do not delete the last slide in the document.
|
|
if (xPages->getCount() <= 1)
|
|
break;
|
|
|
|
USHORT nPage = ((*aI)->GetPageNum()-1) / 2;
|
|
|
|
Reference< XDrawPage > xPage( xPages->getByIndex( nPage ), UNO_QUERY_THROW );
|
|
xPages->remove(xPage);
|
|
}
|
|
}
|
|
catch( Exception& )
|
|
{
|
|
DBG_ERROR("SelectionManager::DeleteSelectedMasterPages(), exception caught!");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SelectionManager::MoveSelectedPages (const sal_Int32 nTargetPageIndex)
|
|
{
|
|
bool bMoved (false);
|
|
PageSelector& rSelector (mrController.GetPageSelector());
|
|
|
|
view::SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
|
|
SlideSorterController::ModelChangeLock aLock (mrController);
|
|
|
|
// Transfer selection of the slide sorter to the document.
|
|
mrSlideSorter.GetModel().SynchronizeDocumentSelection ();
|
|
|
|
// Detect how many pages lie between document start and insertion
|
|
// position.
|
|
sal_Int32 nPageCountBeforeTarget (0);
|
|
::boost::shared_ptr<PageSelector::PageSelection> pSelection (rSelector.GetPageSelection());
|
|
PageSelector::PageSelection::const_iterator iSelectedPage (pSelection->begin());
|
|
PageSelector::PageSelection::const_iterator iSelectionEnd (pSelection->end());
|
|
for ( ; iSelectedPage!=iSelectionEnd; ++iSelectedPage)
|
|
{
|
|
if (*iSelectedPage==NULL)
|
|
continue;
|
|
if (((*iSelectedPage)->GetPageNum()-1)/2 <= nTargetPageIndex)
|
|
++nPageCountBeforeTarget;
|
|
else
|
|
break;
|
|
}
|
|
|
|
// Prepare to select the moved pages.
|
|
SelectionCommand* pCommand = new SelectionCommand(
|
|
rSelector,mrController.GetCurrentSlideManager(),mrSlideSorter.GetModel());
|
|
sal_Int32 nSelectedPageCount (rSelector.GetSelectedPageCount());
|
|
for (sal_Int32 nOffset=0; nOffset<nSelectedPageCount; ++nOffset)
|
|
pCommand->AddSlide(sal::static_int_cast<USHORT>(
|
|
nTargetPageIndex + nOffset - nPageCountBeforeTarget + 1));
|
|
|
|
// At the moment we can not move master pages.
|
|
if (nTargetPageIndex>=0)
|
|
{
|
|
if (mrSlideSorter.GetModel().GetEditMode() == EM_PAGE)
|
|
bMoved = mrSlideSorter.GetModel().GetDocument()->MovePages(
|
|
sal::static_int_cast<sal_uInt16>(nTargetPageIndex));
|
|
}
|
|
if (bMoved)
|
|
mrController.GetSlotManager()->ExecuteCommandAsynchronously(
|
|
::std::auto_ptr<controller::Command>(pCommand));
|
|
|
|
return bMoved;
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionManager::SelectionHasChanged (const bool bMakeSelectionVisible)
|
|
{
|
|
if (bMakeSelectionVisible)
|
|
mbIsMakeSelectionVisiblePending = true;
|
|
|
|
ViewShell* pViewShell = mrSlideSorter.GetViewShell();
|
|
if (pViewShell != NULL)
|
|
{
|
|
pViewShell->Invalidate (SID_EXPAND_PAGE);
|
|
pViewShell->Invalidate (SID_SUMMARY_PAGE);
|
|
pViewShell->Invalidate(SID_SHOW_SLIDE);
|
|
pViewShell->Invalidate(SID_HIDE_SLIDE);
|
|
pViewShell->Invalidate(SID_DELETE_PAGE);
|
|
pViewShell->Invalidate(SID_DELETE_MASTER_PAGE);
|
|
|
|
// StatusBar
|
|
pViewShell->Invalidate (SID_STATUS_PAGE);
|
|
pViewShell->Invalidate (SID_STATUS_LAYOUT);
|
|
|
|
OSL_ASSERT(mrController.GetCurrentSlideManager());
|
|
SharedPageDescriptor pDescriptor(mrController.GetCurrentSlideManager()->GetCurrentSlide());
|
|
if (pDescriptor.get() != NULL)
|
|
pViewShell->UpdatePreview(pDescriptor->GetPage());
|
|
|
|
// Tell the slection change listeners that the selection has changed.
|
|
::std::vector<Link>::iterator iListener (maSelectionChangeListeners.begin());
|
|
::std::vector<Link>::iterator iEnd (maSelectionChangeListeners.end());
|
|
for (; iListener!=iEnd; ++iListener)
|
|
{
|
|
iListener->Call(NULL);
|
|
}
|
|
|
|
// Reset the insertion position: until set again it is calculated from
|
|
// the current selection.
|
|
mnInsertionPosition = -1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SelectionManager::IsMakeSelectionVisiblePending (void) const
|
|
{
|
|
return mbIsMakeSelectionVisiblePending;
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionManager::ResetMakeSelectionVisiblePending (void)
|
|
{
|
|
mbIsMakeSelectionVisiblePending = false;
|
|
}
|
|
|
|
|
|
|
|
|
|
/** We have to distinguish three cases: 1) the selection is empty, 2) the
|
|
selection fits completely into the visible area, 3) it does not.
|
|
1) The visible area is not modified.
|
|
2) When the selection fits completely into the visible area we have to
|
|
decide how to align it. It is done by scrolling it there and thus when
|
|
we scoll up the (towards the end of the document) the bottom of the
|
|
selection is aligned with the bottom of the window. When we scroll
|
|
down (towards the beginning of the document) the top of the selection is
|
|
aligned with the top of the window.
|
|
3) We have to decide what part of the selection to make visible. Here
|
|
we use the eSelectionHint and concentrate on either the first, the last,
|
|
or the most recently selected page. We then again apply the algorithm
|
|
of a).
|
|
|
|
*/
|
|
Size SelectionManager::MakeSelectionVisible (const SelectionHint eSelectionHint)
|
|
{
|
|
SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
|
|
if (pWindow == NULL)
|
|
return Size(0,0);
|
|
|
|
mbIsMakeSelectionVisiblePending = false;
|
|
|
|
// Determine the descriptors of the first and last selected page and the
|
|
// bounding box that encloses their page objects.
|
|
model::SharedPageDescriptor pFirst;
|
|
model::SharedPageDescriptor pLast;
|
|
Rectangle aSelectionBox;
|
|
const view::Layouter& rLayouter (mrSlideSorter.GetView().GetLayouter());
|
|
model::PageEnumeration aSelectedPages (
|
|
PageEnumerationProvider::CreateSelectedPagesEnumeration(mrSlideSorter.GetModel()));
|
|
while (aSelectedPages.HasMoreElements())
|
|
{
|
|
model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
|
|
|
|
if (pFirst.get() == NULL)
|
|
pFirst = pDescriptor;
|
|
pLast = pDescriptor;
|
|
|
|
aSelectionBox.Union(rLayouter.GetPageObjectBox(pDescriptor->GetPageIndex(), true));
|
|
}
|
|
|
|
if (pFirst != NULL)
|
|
{
|
|
// Determine scroll direction and the position in model coordinates
|
|
// that will be aligned with the top/left or bottom/right window
|
|
// border.
|
|
if (DoesSelectionExceedVisibleArea(aSelectionBox))
|
|
{
|
|
// We can show only a part of the selection.
|
|
aSelectionBox = ResolveLargeSelection(pFirst,pLast, eSelectionHint);
|
|
}
|
|
|
|
return MakeRectangleVisible(aSelectionBox);
|
|
}
|
|
|
|
return Size(0,0);
|
|
}
|
|
|
|
|
|
|
|
|
|
Size SelectionManager::MakeRectangleVisible (const Rectangle& rBox)
|
|
{
|
|
SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
|
|
if (pWindow == NULL)
|
|
return Size(0,0);
|
|
|
|
Rectangle aVisibleArea (pWindow->PixelToLogic(
|
|
Rectangle(
|
|
Point(0,0),
|
|
pWindow->GetOutputSizePixel())));
|
|
|
|
if (mrSlideSorter.GetView().GetOrientation() == SlideSorterView::VERTICAL)
|
|
{
|
|
// Scroll the visible area to make aSelectionBox visible.
|
|
sal_Int32 nNewTop (aVisibleArea.Top());
|
|
if (mrSlideSorter.GetProperties()->IsCenterSelection())
|
|
{
|
|
nNewTop = rBox.Top() - (aVisibleArea.GetHeight() - rBox.GetHeight()) / 2;
|
|
}
|
|
else
|
|
{
|
|
if (rBox.Top() < aVisibleArea.Top())
|
|
nNewTop = rBox.Top();
|
|
else if (rBox.Bottom() > aVisibleArea.Bottom())
|
|
nNewTop = rBox.Bottom() - aVisibleArea.GetHeight();
|
|
// otherwise we do not modify the visible area.
|
|
}
|
|
|
|
// Make some corrections of the new visible area.
|
|
Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea());
|
|
if (nNewTop + aVisibleArea.GetHeight() > aModelArea.Bottom())
|
|
nNewTop = aModelArea.GetHeight() - aVisibleArea.GetHeight();
|
|
if (nNewTop < aModelArea.Top())
|
|
nNewTop = aModelArea.Top();
|
|
|
|
// Scroll.
|
|
if (nNewTop != aVisibleArea.Top())
|
|
{
|
|
if (mrSlideSorter.GetProperties()->IsSmoothSelectionScrolling())
|
|
{
|
|
if (mnAnimationId != Animator::NotAnAnimationId)
|
|
mrController.GetAnimator()->RemoveAnimation(mnAnimationId);
|
|
mnAnimationId = mrController.GetAnimator()->AddAnimation(
|
|
VerticalVisibleAreaScroller(mrSlideSorter, aVisibleArea.Top(), nNewTop),
|
|
0,
|
|
300);
|
|
}
|
|
else
|
|
VerticalVisibleAreaScroller(mrSlideSorter, aVisibleArea.Top(), nNewTop)(1.0);
|
|
}
|
|
|
|
return Size(0,aVisibleArea.Top() - nNewTop);
|
|
}
|
|
else
|
|
{
|
|
// Scroll the visible area to make aSelectionBox visible.
|
|
sal_Int32 nNewLeft (aVisibleArea.Left());
|
|
if (mrSlideSorter.GetProperties()->IsCenterSelection())
|
|
{
|
|
nNewLeft = rBox.Left() - (aVisibleArea.GetWidth() - rBox.GetWidth()) / 2;
|
|
}
|
|
else
|
|
{
|
|
if (rBox.Left() < aVisibleArea.Left())
|
|
nNewLeft = rBox.Left();
|
|
else if (rBox.Right() > aVisibleArea.Right())
|
|
nNewLeft = rBox.Right() - aVisibleArea.GetWidth();
|
|
// otherwise we do not modify the visible area.
|
|
}
|
|
|
|
// Make some corrections of the new visible area.
|
|
Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea());
|
|
if (nNewLeft + aVisibleArea.GetWidth() > aModelArea.Right())
|
|
nNewLeft = aModelArea.GetWidth() - aVisibleArea.GetWidth();
|
|
if (nNewLeft < aModelArea.Left())
|
|
nNewLeft = aModelArea.Left();
|
|
|
|
// Scroll.
|
|
if (nNewLeft != aVisibleArea.Left())
|
|
{
|
|
if (mrSlideSorter.GetProperties()->IsSmoothSelectionScrolling())
|
|
mrController.GetAnimator()->AddAnimation(
|
|
HorizontalVisibleAreaScroller(mrSlideSorter, aVisibleArea.Left(), nNewLeft),
|
|
0,
|
|
300);
|
|
else
|
|
HorizontalVisibleAreaScroller(mrSlideSorter, aVisibleArea.Left(), nNewLeft)(1.0);
|
|
}
|
|
|
|
return Size(aVisibleArea.Left() - nNewLeft, 0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionManager::AddSelectionChangeListener (const Link& rListener)
|
|
{
|
|
if (::std::find (
|
|
maSelectionChangeListeners.begin(),
|
|
maSelectionChangeListeners.end(),
|
|
rListener) == maSelectionChangeListeners.end())
|
|
{
|
|
maSelectionChangeListeners.push_back (rListener);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionManager::RemoveSelectionChangeListener(const Link&rListener)
|
|
{
|
|
maSelectionChangeListeners.erase (
|
|
::std::find (
|
|
maSelectionChangeListeners.begin(),
|
|
maSelectionChangeListeners.end(),
|
|
rListener));
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SelectionManager::DoesSelectionExceedVisibleArea (const Rectangle& rSelectionBox) const
|
|
{
|
|
SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
|
|
if (pWindow == NULL)
|
|
return true;
|
|
|
|
Rectangle aVisibleArea (pWindow->PixelToLogic(
|
|
Rectangle(
|
|
Point(0,0),
|
|
pWindow->GetOutputSizePixel())));
|
|
if (mrSlideSorter.GetView().GetOrientation() == SlideSorterView::VERTICAL)
|
|
return rSelectionBox.GetHeight() > aVisibleArea.GetHeight();
|
|
else
|
|
return rSelectionBox.GetWidth() > aVisibleArea.GetWidth();
|
|
}
|
|
|
|
|
|
|
|
|
|
Rectangle SelectionManager::ResolveLargeSelection (
|
|
const SharedPageDescriptor& rpFirst,
|
|
const SharedPageDescriptor& rpLast,
|
|
const SelectionHint eSelectionHint)
|
|
{
|
|
OSL_ASSERT(rpFirst.get()!=NULL);
|
|
OSL_ASSERT(rpLast.get()!=NULL);
|
|
|
|
// The mose recently selected page is assumed to lie in the range
|
|
// between first and last selected page. Therefore the bounding box is
|
|
// not modified.
|
|
model::SharedPageDescriptor pRecent (
|
|
mrController.GetPageSelector().GetMostRecentlySelectedPage());
|
|
|
|
// Get the bounding box of the page object on which to concentrate.
|
|
model::SharedPageDescriptor pRepresentative;
|
|
switch (eSelectionHint)
|
|
{
|
|
case SH_FIRST:
|
|
pRepresentative = rpFirst;
|
|
break;
|
|
|
|
case SH_LAST:
|
|
pRepresentative = rpLast;
|
|
break;
|
|
|
|
case SH_RECENT:
|
|
default:
|
|
if (pRecent.get() == NULL)
|
|
pRepresentative = rpFirst;
|
|
else
|
|
pRepresentative = pRecent;
|
|
break;
|
|
}
|
|
OSL_ASSERT(pRepresentative.get() != NULL);
|
|
|
|
return mrSlideSorter.GetView().GetLayouter().GetPageObjectBox(
|
|
pRepresentative->GetPageIndex(),
|
|
true);
|
|
}
|
|
|
|
|
|
|
|
|
|
sal_Int32 SelectionManager::GetInsertionPosition (void) const
|
|
{
|
|
sal_Int32 nInsertionPosition (mnInsertionPosition);
|
|
if (nInsertionPosition < 0)
|
|
{
|
|
model::PageEnumeration aSelectedPages
|
|
(model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
|
|
mrSlideSorter.GetModel()));
|
|
// Initialize (for the case of an empty selection) with the position
|
|
// at the end of the document.
|
|
nInsertionPosition = mrSlideSorter.GetModel().GetPageCount();
|
|
while (aSelectedPages.HasMoreElements())
|
|
{
|
|
const sal_Int32 nPosition (aSelectedPages.GetNextElement()->GetPage()->GetPageNum());
|
|
// Convert *2+1 index to straight index (n-1)/2 after the page
|
|
// (+1).
|
|
nInsertionPosition = (nPosition-1)/2 + 1;
|
|
}
|
|
|
|
}
|
|
return nInsertionPosition;
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionManager::SetInsertionPosition (const sal_Int32 nInsertionPosition)
|
|
{
|
|
if (nInsertionPosition < 0)
|
|
mnInsertionPosition = -1;
|
|
else if (nInsertionPosition > mrSlideSorter.GetModel().GetPageCount())
|
|
{
|
|
// Assert but then ignore invalid values.
|
|
OSL_ASSERT(nInsertionPosition<=mrSlideSorter.GetModel().GetPageCount());
|
|
return;
|
|
}
|
|
else
|
|
mnInsertionPosition = nInsertionPosition;
|
|
}
|
|
|
|
|
|
|
|
|
|
//===== VerticalVisibleAreaScroller ===========================================
|
|
|
|
namespace {
|
|
|
|
const static sal_Int32 gnMaxScrollDistance = 300;
|
|
|
|
VerticalVisibleAreaScroller::VerticalVisibleAreaScroller (
|
|
SlideSorter& rSlideSorter,
|
|
const double nStart,
|
|
const double nEnd)
|
|
: mrSlideSorter(rSlideSorter),
|
|
mnStart(nStart),
|
|
mnEnd(nEnd),
|
|
maAccelerationFunction(
|
|
controller::AnimationParametricFunction(
|
|
controller::AnimationBezierFunction (0.1,0.6)))
|
|
{
|
|
// When the distance to scroll is larger than a threshold then first
|
|
// jump to within this distance of the final value and start the
|
|
// animation from there.
|
|
if (abs(nStart-nEnd) > gnMaxScrollDistance)
|
|
if (nStart < nEnd)
|
|
mnStart = nEnd-gnMaxScrollDistance;
|
|
else
|
|
mnStart = nEnd+gnMaxScrollDistance;
|
|
}
|
|
|
|
|
|
|
|
void VerticalVisibleAreaScroller::operator() (const double nTime)
|
|
{
|
|
const double nLocalTime (maAccelerationFunction(nTime));
|
|
const sal_Int32 nNewTop (mnStart * (1.0 - nLocalTime) + mnEnd * nLocalTime);
|
|
mrSlideSorter.GetController().GetScrollBarManager().SetTop(nNewTop);
|
|
/*
|
|
mrSlideSorter.GetViewShell()->Scroll(
|
|
0,
|
|
nNewTop - mrSlideSorter.GetController().GetScrollBarManager().GetTop());
|
|
mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
|
|
*/
|
|
}
|
|
|
|
|
|
|
|
|
|
//===== HorizontalVisibleAreaScroller =========================================
|
|
|
|
HorizontalVisibleAreaScroller::HorizontalVisibleAreaScroller (
|
|
SlideSorter& rSlideSorter,
|
|
const double nStart,
|
|
const double nEnd)
|
|
: mrSlideSorter(rSlideSorter),
|
|
mnStart(nStart),
|
|
mnEnd(nEnd),
|
|
maAccelerationFunction(
|
|
controller::AnimationParametricFunction(
|
|
controller::AnimationBezierFunction (0.1,0.6)))
|
|
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
void HorizontalVisibleAreaScroller::operator() (const double nTime)
|
|
{
|
|
const double nLocalTime (maAccelerationFunction(nTime));
|
|
const sal_Int32 nNewLeft (mnStart * (1.0 - nLocalTime) + mnEnd * nLocalTime);
|
|
mrSlideSorter.GetViewShell()->Scroll(
|
|
nNewLeft - mrSlideSorter.GetController().GetScrollBarManager().GetLeft(),
|
|
0);
|
|
mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
|
|
}
|
|
|
|
} // end of anonymous namespace
|
|
|
|
} } } // end of namespace ::sd::slidesorter
|