From 3c7bf4b67dbe92880d3cb8b7fb24a882651a7ba1 Mon Sep 17 00:00:00 2001 From: Andre Fischer Date: Tue, 23 Feb 2010 16:56:05 +0100 Subject: [PATCH] renaissance1: #i107215# Improved drag and drop. --- .../controller/SlideSorterController.cxx | 15 +- .../ui/slidesorter/controller/SlsAnimator.cxx | 8 +- .../slidesorter/controller/SlsClipboard.cxx | 37 ++- .../controller/SlsCurrentSlideManager.cxx | 2 +- .../SlsInsertionIndicatorHandler.cxx | 65 +++- .../controller/SlsPageSelector.cxx | 60 ++-- .../controller/SlsSelectionFunction.cxx | 291 +++++++----------- .../controller/SlsSubstitutionHandler.cxx | 240 +++++++++++++++ .../controller/SlsSubstitutionHandler.hxx | 104 +++++++ .../controller/SlsTransferable.cxx | 15 +- .../controller/SlsTransferable.hxx | 9 +- .../ui/slidesorter/controller/makefile.mk | 4 +- .../inc/controller/SlideSorterController.hxx | 7 + .../SlsInsertionIndicatorHandler.hxx | 24 +- .../inc/controller/SlsPageSelector.hxx | 3 +- .../inc/controller/SlsSelectionFunction.hxx | 16 +- .../inc/model/SlsPageDescriptor.hxx | 16 +- .../ui/slidesorter/inc/view/SlsTheme.hxx | 3 +- .../slidesorter/inc/view/SlsViewOverlay.hxx | 26 +- .../slidesorter/model/SlsPageDescriptor.cxx | 6 +- .../shell/SlideSorterViewShell.cxx | 2 +- sd/source/ui/slidesorter/view/SlsLayouter.cxx | 28 +- .../view/SlsPageObjectLayouter.cxx | 2 +- .../slidesorter/view/SlsPageObjectPainter.cxx | 6 +- sd/source/ui/slidesorter/view/SlsTheme.cxx | 3 - .../ui/slidesorter/view/SlsViewOverlay.cxx | 128 ++++++-- 26 files changed, 800 insertions(+), 320 deletions(-) create mode 100644 sd/source/ui/slidesorter/controller/SlsSubstitutionHandler.cxx create mode 100644 sd/source/ui/slidesorter/controller/SlsSubstitutionHandler.hxx diff --git a/sd/source/ui/slidesorter/controller/SlideSorterController.cxx b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx index a48fb568577b..67a08fcd41ee 100644 --- a/sd/source/ui/slidesorter/controller/SlideSorterController.cxx +++ b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx @@ -440,7 +440,9 @@ bool SlideSorterController::Command ( // indicator so that the user knows where a page insertion // would take place. GetInsertionIndicatorHandler()->Start( - pWindow->PixelToLogic(rEvent.GetMousePosPixel())); + pWindow->PixelToLogic(rEvent.GetMousePosPixel()), + InsertionIndicatorHandler::MoveMode, + false); } pWindow->ReleaseMouse(); @@ -863,6 +865,15 @@ FunctionReference SlideSorterController::CreateSelectionFunction (SfxRequest& rR +::rtl::Reference SlideSorterController::GetCurrentSelectionFunction (void) +{ + FunctionReference pFunction (mrSlideSorter.GetViewShell()->GetCurrentFunction()); + return ::rtl::Reference(dynamic_cast(pFunction.get())); +} + + + + void SlideSorterController::PrepareEditModeChange (void) { // Before we throw away the page descriptors we prepare for selecting @@ -1041,6 +1052,8 @@ void SlideSorterController::SetDocumentSlides (const Reference we do not have to suppress painting + // anymore. + mpDrawLock.reset(); + } } diff --git a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx index 2c44ffc6d754..2f9397c7e8fe 100644 --- a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx +++ b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx @@ -367,11 +367,17 @@ void Clipboard::CreateSlideTransferable ( { mrSlideSorter.GetView().BrkAction(); SdDrawDocument* pDocument = mrSlideSorter.GetModel().GetDocument(); + ::boost::shared_ptr pSubstitutionHandler; + ::rtl::Reference pSelectionFunction ( + mrSlideSorter.GetController().GetCurrentSelectionFunction()); + if (pSelectionFunction.is()) + pSubstitutionHandler = pSelectionFunction->GetSubstitutionHandler(); SdTransferable* pTransferable = new Transferable ( pDocument, NULL, FALSE, - dynamic_cast(mrSlideSorter.GetViewShell())); + dynamic_cast(mrSlideSorter.GetViewShell()), + pSubstitutionHandler); if (bDrag) SD_MOD()->pTransferDrag = pTransferable; @@ -433,7 +439,9 @@ void Clipboard::StartDrag ( mbUpdateSelectionPending = false; CreateSlideTransferable(pWindow, TRUE); - mrController.GetInsertionIndicatorHandler()->UpdatePosition(rPosition); + mrController.GetInsertionIndicatorHandler()->UpdatePosition( + rPosition, + InsertionIndicatorHandler::UnknownMode); } @@ -442,8 +450,9 @@ void Clipboard::StartDrag ( void Clipboard::DragFinished (sal_Int8 nDropAction) { // Hide the substitution display and insertion indicator. - mrSlideSorter.GetView().GetOverlay().GetSubstitutionOverlay()->SetIsVisible(false); - mrSlideSorter.GetController().GetInsertionIndicatorHandler()->End(); + ::rtl::Reference pFunction (mrController.GetCurrentSelectionFunction()); + if (pFunction.is()) + pFunction->NotifyDragFinished(); SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; @@ -467,7 +476,8 @@ void Clipboard::DragFinished (sal_Int8 nDropAction) mrController.GetSelectionManager()->DeleteSelectedPages (); } - SelectPages(); + if (nDropAction != DND_ACTION_NONE) + SelectPages(); } @@ -527,7 +537,9 @@ sal_Int8 Clipboard::AcceptDrop ( // Show the insertion marker and the substitution for a drop. Point aPosition = pTargetWindow->PixelToLogic (rEvent.maPosPixel); view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); - mrController.GetInsertionIndicatorHandler()->UpdatePosition(aPosition); + mrController.GetInsertionIndicatorHandler()->UpdatePosition( + aPosition, + rEvent.maDragEvent.DropAction); rOverlay.GetSubstitutionOverlay()->SetPosition(aPosition); // Scroll the window when the mouse reaches the window border. @@ -580,10 +592,10 @@ sal_Int8 Clipboard::ExecuteDrop ( || ( nXOffset >= 2 && nYOffset >= 2 ); // Get insertion position and then turn off the insertion indicator. - mrController.GetInsertionIndicatorHandler()->UpdatePosition(aEventModelPosition); + mrController.GetInsertionIndicatorHandler()->UpdatePosition( + aEventModelPosition, + rEvent.mnAction); USHORT nIndex = DetermineInsertPosition(*pDragTransferable); - OSL_TRACE ("Clipboard::AcceptDrop() called for index %d", - nIndex); mrController.GetInsertionIndicatorHandler()->End(); if (bContinue) @@ -617,6 +629,13 @@ sal_Int8 Clipboard::ExecuteDrop ( nResult = rEvent.mnAction; } } + + // Notify the receiving selection function that drag-and-drop is + // finished and the substitution handler can be released. + ::rtl::Reference pFunction ( + mrController.GetCurrentSelectionFunction()); + if (pFunction.is()) + pFunction->NotifyDragFinished(); } break; diff --git a/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx b/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx index 2f97124d8576..e2ed42cb9aee 100644 --- a/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx +++ b/sd/source/ui/slidesorter/controller/SlsCurrentSlideManager.cxx @@ -134,7 +134,7 @@ void CurrentSlideManager::SwitchCurrentSlide (const sal_Int32 nSlideIndex) void CurrentSlideManager::SwitchCurrentSlide (const SharedPageDescriptor& rpDescriptor) { - if (rpDescriptor.get() != NULL) + if (rpDescriptor.get() != NULL && mpCurrentSlide!=rpDescriptor) { ReleaseCurrentSlide(); AcquireCurrentSlide((rpDescriptor->GetPage()->GetPageNum()-1)/2); diff --git a/sd/source/ui/slidesorter/controller/SlsInsertionIndicatorHandler.cxx b/sd/source/ui/slidesorter/controller/SlsInsertionIndicatorHandler.cxx index 04c505d72b5c..5dd7cf359490 100644 --- a/sd/source/ui/slidesorter/controller/SlsInsertionIndicatorHandler.cxx +++ b/sd/source/ui/slidesorter/controller/SlsInsertionIndicatorHandler.cxx @@ -37,9 +37,11 @@ #include "view/SlsLayouter.hxx" #include "model/SlideSorterModel.hxx" #include "model/SlsPageEnumerationProvider.hxx" +#include #include "SlideSorter.hxx" +using namespace ::com::sun::star::datatransfer::dnd::DNDConstants; namespace sd { namespace slidesorter { namespace controller { @@ -51,8 +53,10 @@ InsertionIndicatorHandler::InsertionIndicatorHandler (SlideSorter& rSlideSorter) mrSlideSorter.GetView().GetOverlay().GetInsertionIndicatorOverlay()), mnInsertionIndex(-1), mbIsBeforePage(false), + meMode(MoveMode), mbIsActive(false), - mbIsReadOnly(mrSlideSorter.GetModel().IsReadOnly()) + mbIsReadOnly(mrSlideSorter.GetModel().IsReadOnly()), + mbIsOverSourceView(true) { } @@ -66,7 +70,10 @@ InsertionIndicatorHandler::~InsertionIndicatorHandler (void) -void InsertionIndicatorHandler::Start (const Point& rMouseModelPosition) +void InsertionIndicatorHandler::Start ( + const Point& rMouseModelPosition, + const Mode eMode, + const bool bIsOverSourceView) { if (mbIsActive) { @@ -77,15 +84,32 @@ void InsertionIndicatorHandler::Start (const Point& rMouseModelPosition) if (mbIsReadOnly) return; - SetPosition(rMouseModelPosition); + SetPosition(rMouseModelPosition, eMode); mbIsActive = true; + mbIsOverSourceView = bIsOverSourceView; } -void InsertionIndicatorHandler::UpdatePosition (const Point& rMouseModelPosition) +InsertionIndicatorHandler::Mode InsertionIndicatorHandler::GetModeFromDndAction ( + const sal_Int8 nDndAction) +{ + switch (nDndAction & (ACTION_COPY | ACTION_MOVE | ACTION_LINK)) + { + case ACTION_COPY: return CopyMode; + case ACTION_MOVE: return MoveMode; + default: return UnknownMode; + } +} + + + + +void InsertionIndicatorHandler::UpdatePosition ( + const Point& rMouseModelPosition, + const Mode eMode) { if ( ! mbIsActive) return; @@ -93,7 +117,17 @@ void InsertionIndicatorHandler::UpdatePosition (const Point& rMouseModelPosition if (mbIsReadOnly) return; - SetPosition(rMouseModelPosition); + SetPosition(rMouseModelPosition, eMode); +} + + + + +void InsertionIndicatorHandler::UpdatePosition ( + const Point& rMouseModelPosition, + const sal_Int8 nDndAction) +{ + UpdatePosition(rMouseModelPosition, GetModeFromDndAction(nDndAction)); } @@ -136,7 +170,9 @@ sal_Int32 InsertionIndicatorHandler::GetInsertionPageIndex (void) const -void InsertionIndicatorHandler::SetPosition (const Point& rPoint) +void InsertionIndicatorHandler::SetPosition ( + const Point& rPoint, + const Mode eMode) { static const bool bAllowHorizontalInsertMarker = true; view::Layouter& rLayouter (mrSlideSorter.GetView().GetLayouter()); @@ -183,11 +219,14 @@ void InsertionIndicatorHandler::SetPosition (const Point& rPoint) nInsertionIndex += 1; } - if (mnInsertionIndex!=nInsertionIndex || mbIsBeforePage!=bIsBeforePage) + if (mnInsertionIndex!=nInsertionIndex + || mbIsBeforePage!=bIsBeforePage + || meMode!=eMode) { mnInsertionIndex = nInsertionIndex; mbIsBeforePage = bIsBeforePage; - mbIsInsertionTrivial = IsInsertionTrivial(); + meMode = eMode; + mbIsInsertionTrivial = IsInsertionTrivial(eMode); mpInsertionIndicatorOverlay->SetLocation( rLayouter.GetInsertionMarkerLocation ( @@ -223,8 +262,16 @@ void InsertionIndicatorHandler::SetPosition (const Point& rPoint) -bool InsertionIndicatorHandler::IsInsertionTrivial (void) const +bool InsertionIndicatorHandler::IsInsertionTrivial (const Mode eMode) const { + if (eMode == CopyMode) + return false; + else if (eMode == UnknownMode) + return true; + + if ( ! mbIsOverSourceView) + return false; + // Iterate over all selected pages and check whether there are // holes. While we do this we remember the indices of the first and // last selected page as preparation for the next step. diff --git a/sd/source/ui/slidesorter/controller/SlsPageSelector.cxx b/sd/source/ui/slidesorter/controller/SlsPageSelector.cxx index 73b5048b1615..25767bee7b9a 100644 --- a/sd/source/ui/slidesorter/controller/SlsPageSelector.cxx +++ b/sd/source/ui/slidesorter/controller/SlsPageSelector.cxx @@ -57,6 +57,7 @@ using namespace ::com::sun::star::uno; using namespace ::sd::slidesorter::model; using namespace ::sd::slidesorter::view; + namespace sd { namespace slidesorter { namespace controller { PageSelector::PageSelector (SlideSorter& rSlideSorter) @@ -69,7 +70,8 @@ PageSelector::PageSelector (SlideSorter& rSlideSorter) mpMostRecentlySelectedPage(), mpSelectionAnchor(), mpCurrentPage(), - mnUpdateLockCount(0) + mnUpdateLockCount(0), + mbIsUpdateCurrentPagePending(false) { CountSelectedPages (); } @@ -82,7 +84,6 @@ void PageSelector::SelectAllPages (void) int nPageCount = mrModel.GetPageCount(); for (int nPageIndex=0; nPageIndex 0) { - const sal_Int32 nPageCount (GetPageCount()); - for (sal_Int32 nIndex=0; nIndexHasState(PageDescriptor::ST_Selected)) { - SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex)); - if (pDescriptor && pDescriptor->HasState(PageDescriptor::ST_Selected)) - { - // Switching the current slide normally sets also the - // selection to just the new current slide. To prevent that - // here we store and at the end of this scope restore the - // current selection. - ::boost::shared_ptr pSelection (GetPageSelection()); - SharedPageDescriptor pRecentSelection (GetMostRecentlySelectedPage()); + // Switching the current slide normally sets also the selection + // to just the new current slide. To prevent that here we store + // and at the end of this scope restore the current selection. + ::boost::shared_ptr pSelection (GetPageSelection()); + SharedPageDescriptor pRecentSelection (GetMostRecentlySelectedPage()); - mrController.GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor); + mrController.GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor); - // Restore the selection and prevent a recursive call to - // UpdateCurrentPage(). - SetPageSelection(pSelection, false); - // Restore the most recently selected page. Important for - // making the right part of the selection visible. - mpMostRecentlySelectedPage = pRecentSelection; - return; - } + // Restore the selection and prevent a recursive call to + // UpdateCurrentPage(). + SetPageSelection(pSelection, false); + // Restore the most recently selected page. Important for + // making the right part of the selection visible. + mpMostRecentlySelectedPage = pRecentSelection; + return; } } @@ -412,7 +420,7 @@ PageSelector::UpdateLock::~UpdateLock (void) --mrSelector.mnUpdateLockCount; OSL_ASSERT(mrSelector.mnUpdateLockCount >= 0); if (mrSelector.mnUpdateLockCount == 0) - mrSelector.UpdateCurrentPage(); + mrSelector.UpdateCurrentPage(true); } diff --git a/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx b/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx index 620c8efca908..203cc087df56 100644 --- a/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx +++ b/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx @@ -34,6 +34,8 @@ #include "SlideSorter.hxx" #include "SlideSorterViewShell.hxx" +#include "SlsSubstitutionHandler.hxx" +#include "SlsTransferable.hxx" #include "controller/SlideSorterController.hxx" #include "controller/SlsPageSelector.hxx" #include "controller/SlsFocusManager.hxx" @@ -43,6 +45,7 @@ #include "controller/SlsInsertionIndicatorHandler.hxx" #include "controller/SlsSelectionManager.hxx" #include "controller/SlsProperties.hxx" +#include "controller/SlsProperties.hxx" #include "model/SlideSorterModel.hxx" #include "model/SlsPageDescriptor.hxx" #include "model/SlsPageEnumerationProvider.hxx" @@ -57,6 +60,8 @@ #include "Window.hxx" #include "sdpage.hxx" #include "drawdoc.hxx" +#include "DrawDocShell.hxx" +#include "sdxfer.hxx" #include "ViewShell.hxx" #include "ViewShellBase.hxx" #include "FrameView.hxx" @@ -108,49 +113,6 @@ static const sal_uInt32 MODIFIER_MASK (SHIFT_MODIFIER | CONTROL_MODIF namespace sd { namespace slidesorter { namespace controller { -/** A SubstitutionHandler object handles the display of a number of selected - slides at the mouse position and the insertion or (with or without - removing the pages at their original position) when the object is - destoyed. -*/ -class SelectionFunction::SubstitutionHandler -{ -public: - /** Create a substitution display of the currently selected pages and - use the given position as the anchor point. - */ - SubstitutionHandler ( - SlideSorter& rSlideSorter, - const model::SharedPageDescriptor& rpHitDescriptor, - const Point& rMouseModelPosition); - ~SubstitutionHandler (void); - - /** Call this method (for example as reaction to ESC key press) to avoid - processing (ie moving or inserting) the substition when the called - SubstitutionHandler object is destroyed. - */ - void Dispose (void); - - /** Move the substitution display by the distance the mouse has - travelled since the last call to this method or to - CreateSubstitution(). The given point becomes the new anchor. - */ - void UpdatePosition ( - const Point& rMousePosition, - const bool bAllowAutoScroll = true); - -private: - SlideSorter& mrSlideSorter; - model::SharedPageDescriptor mpHitDescriptor; - sal_Int32 mnInsertionIndex; - - /** Move the substitution display of the currently selected pages. - */ - void Process (void); -}; - - - class SelectionFunction::MouseMultiSelector { @@ -241,13 +203,13 @@ namespace { class SelectionFunction::EventDescriptor { public: - Point maMousePosition; Point maMouseModelPosition; ::boost::weak_ptr mpHitDescriptor; SdrPage* mpHitPage; sal_uInt32 mnEventCode; sal_Int32 mnButtonIndex; + InsertionIndicatorHandler::Mode meDragMode; EventDescriptor ( sal_uInt32 nEventType, @@ -260,6 +222,8 @@ public: const AcceptDropEvent& rEvent, SlideSorter& rSlideSorter); EventDescriptor (const EventDescriptor& rDescriptor); + + void SetDragMode (const InsertionIndicatorHandler::Mode eMode); }; @@ -290,6 +254,9 @@ SelectionFunction::SelectionFunction ( aDragTimer.SetTimeoutHdl(LINK(this, SelectionFunction, DragSlideHdl)); } + + + SelectionFunction::~SelectionFunction (void) { aDragTimer.Stop(); @@ -353,14 +320,18 @@ BOOL SelectionFunction::MouseMove (const MouseEvent& rEvent) (rEvent.GetButtons() & MOUSE_LEFT)!=0); } - if (rEvent.IsLeaveWindow()) + // Detect the mouse leaving the window. When not button is pressed then + // we can call IsLeaveWindow at the event. Otherwise we have to make an + // explicit test. + if (rEvent.IsLeaveWindow() + || ! Rectangle(Point(0,0),mpWindow->GetOutputSizePixel()).IsInside(aMousePosition)) { - // Rectangle aRectangle (Point(0,0),mpWindow->GetOutputSizePixel()); - // if ( ! aRectangle.IsInside(aMousePosition) if (mpSubstitutionHandler) { // Mouse left the window with pressed left button. Make it a drag. - StartDrag(aMousePosition); + StartDrag(aMousePosition, InsertionIndicatorHandler::MoveMode); + mpSubstitutionHandler->Hide(); + mpSubstitutionHandler.reset(); } mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor()); } @@ -404,18 +375,59 @@ BOOL SelectionFunction::MouseButtonUp (const MouseEvent& rEvent) void SelectionFunction::MouseDragged (const AcceptDropEvent& rEvent) { + if (rEvent.mbLeaving) + { + if (mpSubstitutionHandler) + { + // Disconnect the substitution handler from this selection function. + mpSubstitutionHandler->Hide(); + mpSubstitutionHandler->SetTargetSlideSorter(); + mpSubstitutionHandler.reset(); + } + } + else if ( ! mpSubstitutionHandler) + { + const SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; + const Transferable* pSlideSorterTransferable + = dynamic_cast(pDragTransferable); + if (pSlideSorterTransferable != NULL) + { + // Connect the substitution handler to this selection function. + mpSubstitutionHandler = pSlideSorterTransferable->GetSubstitutionHandler(); + if (mpSubstitutionHandler) + { + mpSubstitutionHandler->SetTargetSlideSorter( + &mrSlideSorter, + rEvent.maPosPixel, + InsertionIndicatorHandler::GetModeFromDndAction(rEvent.mnAction), + pSlideSorterTransferable->GetView() == &mrSlideSorter.GetView()); + mpSubstitutionHandler->Show(); + } + } + else + mpSubstitutionHandler.reset( + new SubstitutionHandler( + mrSlideSorter, + mrSlideSorter.GetController().GetPageAt(rEvent.maPosPixel), + rEvent.maPosPixel)); + } + // 1. Compute some frequently used values relating to the event. ::std::auto_ptr pEventDescriptor ( new EventDescriptor(rEvent, mrSlideSorter)); // 2. Detect whether we are dragging pages or dragging a selection rectangle. view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); - if (rOverlay.GetSubstitutionOverlay()->IsVisible()) + if (mpSubstitutionHandler) pEventDescriptor->mnEventCode |= SUBSTITUTION_VISIBLE; if (mpMouseMultiSelector) pEventDescriptor->mnEventCode |= RECTANGLE_VISIBLE; - // 3. Process the event. + // 3. Set the drag mode. + pEventDescriptor->SetDragMode( + InsertionIndicatorHandler::GetModeFromDndAction(rEvent.mnAction)); + + // 4. Process the event. EventPreprocessing(*pEventDescriptor); if ( ! EventProcessing(*pEventDescriptor)) { @@ -427,6 +439,27 @@ void SelectionFunction::MouseDragged (const AcceptDropEvent& rEvent) +void SelectionFunction::NotifyDragFinished (void) +{ + if (mpSubstitutionHandler) + { + mpSubstitutionHandler->Dispose(); + mpSubstitutionHandler.reset(); + } + mrController.GetInsertionIndicatorHandler()->End(); +} + + + + +::boost::shared_ptr SelectionFunction::GetSubstitutionHandler (void) const +{ + return mpSubstitutionHandler; +} + + + + BOOL SelectionFunction::KeyInput (const KeyEvent& rEvent) { PageSelector::UpdateLock aLock (mrSlideSorter); @@ -717,14 +750,16 @@ void SelectionFunction::StartDragTimer (void) IMPL_LINK( SelectionFunction, DragSlideHdl, Timer*, EMPTYARG ) { - StartDrag(aMDPos); + StartDrag(aMDPos, InsertionIndicatorHandler::MoveMode); return 0; } -void SelectionFunction::StartDrag (const Point& rMousePosition) +void SelectionFunction::StartDrag ( + const Point& rMousePosition, + const InsertionIndicatorHandler::Mode eMode) { if (mbPageHit && ! mrSlideSorter.GetProperties()->IsUIReadOnly()) @@ -736,7 +771,9 @@ void SelectionFunction::StartDrag (const Point& rMousePosition) mrSlideSorter.GetController().GetPageAt(rMousePosition), rMousePosition)); else - mpSubstitutionHandler->UpdatePosition(rMousePosition); + mpSubstitutionHandler->UpdatePosition( + rMousePosition, + eMode); mbPageHit = false; mpWindow->ReleaseMouse(); @@ -1053,16 +1090,21 @@ bool SelectionFunction::EventProcessing (const EventDescriptor& rDescriptor) switch (rDescriptor.mnEventCode & (SUBSTITUTION_VISIBLE | RECTANGLE_VISIBLE)) { case SUBSTITUTION_VISIBLE: + OSL_ASSERT(mpSubstitutionHandler); // The substitution is visible. Handle events accordingly. if (Match(rDescriptor.mnEventCode, MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK)) { if ((rDescriptor.mnEventCode & CONTROL_MODIFIER) != 0) - StartDrag(rDescriptor.maMousePosition); - mpSubstitutionHandler->UpdatePosition(rDescriptor.maMousePosition); + StartDrag(rDescriptor.maMousePosition, InsertionIndicatorHandler::CopyMode); + mpSubstitutionHandler->UpdatePosition( + rDescriptor.maMousePosition, + rDescriptor.meDragMode); } else if (Match(rDescriptor.mnEventCode, MOUSE_DRAG)) { - mpSubstitutionHandler->UpdatePosition(rDescriptor.maMousePosition); + mpSubstitutionHandler->UpdatePosition( + rDescriptor.maMousePosition, + rDescriptor.meDragMode); } else if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON)) { @@ -1395,7 +1437,8 @@ SelectionFunction::EventDescriptor::EventDescriptor ( mpHitDescriptor(), mpHitPage(), mnEventCode(0), - mnButtonIndex(-1) + mnButtonIndex(-1), + meDragMode(InsertionIndicatorHandler::MoveMode) { model::SharedPageDescriptor pHitDescriptor ( rSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor()); @@ -1418,7 +1461,8 @@ SelectionFunction::EventDescriptor::EventDescriptor ( mpHitDescriptor(), mpHitPage(), mnEventCode(MOUSE_DRAG), - mnButtonIndex(-1) + mnButtonIndex(-1), + meDragMode(InsertionIndicatorHandler::MoveMode) { SharedSdWindow pWindow (rSlideSorter.GetContentWindow()); @@ -1441,132 +1485,17 @@ SelectionFunction::EventDescriptor::EventDescriptor (const EventDescriptor& rDes mpHitDescriptor(rDescriptor.mpHitDescriptor), mpHitPage(rDescriptor.mpHitPage), mnEventCode(rDescriptor.mnEventCode), - mnButtonIndex(rDescriptor.mnButtonIndex) + mnButtonIndex(rDescriptor.mnButtonIndex), + meDragMode(InsertionIndicatorHandler::MoveMode) { } -//===== SubstitutionHandler =================================================== - -SelectionFunction::SubstitutionHandler::SubstitutionHandler ( - SlideSorter& rSlideSorter, - const model::SharedPageDescriptor& rpHitDescriptor, - const Point& rMouseModelPosition) - : mrSlideSorter(rSlideSorter), - mpHitDescriptor(rpHitDescriptor), - mnInsertionIndex(-1) +void SelectionFunction::EventDescriptor::SetDragMode (const InsertionIndicatorHandler::Mode eMode) { - mnInsertionIndex = -1; - - // No Drag-and-Drop for master pages. - if (mrSlideSorter.GetModel().GetEditMode() != EM_PAGE) - return; - - if (mrSlideSorter.GetProperties()->IsUIReadOnly()) - return; - - view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); - - if ( ! rOverlay.GetSubstitutionOverlay()->IsVisible()) - { - // Show a new substitution for the selected page objects. - model::PageEnumeration aSelectedPages( - model::PageEnumerationProvider::CreateSelectedPagesEnumeration( - mrSlideSorter.GetModel())); - rOverlay.GetSubstitutionOverlay()->Create( - aSelectedPages, - rMouseModelPosition, - mpHitDescriptor); - rOverlay.GetSubstitutionOverlay()->SetIsVisible(true); - mrSlideSorter.GetController().GetInsertionIndicatorHandler()->Start(rMouseModelPosition); - } -} - - - - -SelectionFunction::SubstitutionHandler::~SubstitutionHandler (void) -{ - Process(); - - view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); - rOverlay.GetSubstitutionOverlay()->SetIsVisible(false); - rOverlay.GetSubstitutionOverlay()->Clear(); - mrSlideSorter.GetController().GetInsertionIndicatorHandler()->End(); - mpHitDescriptor.reset(); -} - - - - -void SelectionFunction::SubstitutionHandler::Dispose (void) -{ - mnInsertionIndex = -1; -} - - - - -void SelectionFunction::SubstitutionHandler::UpdatePosition ( - const Point& rMousePosition, - const bool bAllowAutoScroll) -{ - if (mrSlideSorter.GetProperties()->IsUIReadOnly()) - return; - - // Convert window coordinates into model coordinates (we need the - // window coordinates for auto-scrolling because that remains - // constant while scrolling.) - SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); - const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition)); - - if ( ! (bAllowAutoScroll && mrSlideSorter.GetController().GetScrollBarManager().AutoScroll( - rMousePosition, - ::boost::bind( - &SelectionFunction::SubstitutionHandler::UpdatePosition, - this, - rMousePosition, - false)))) - { - view::ViewOverlay& rOverlay (mrSlideSorter.GetView().GetOverlay()); - - // Move the existing substitution to the new position. - rOverlay.GetSubstitutionOverlay()->SetPosition(aMouseModelPosition); - - mrSlideSorter.GetController().GetInsertionIndicatorHandler()->UpdatePosition( - aMouseModelPosition); - - // Remember the new insertion index. - if (mrSlideSorter.GetController().GetInsertionIndicatorHandler()->IsInsertionTrivial()) - mnInsertionIndex = -1; - else - mnInsertionIndex = mrSlideSorter.GetController().GetInsertionIndicatorHandler() - ->GetInsertionPageIndex(); - } -} - - - - -void SelectionFunction::SubstitutionHandler::Process (void) -{ - if (mrSlideSorter.GetProperties()->IsUIReadOnly()) - return; - - if (mnInsertionIndex >= 0) - { - // Tell the model to move the selected pages behind the one with the - // index mnInsertionIndex which first has to transformed into an index - // understandable by the document. - USHORT nDocumentIndex = (USHORT)mnInsertionIndex-1; - mrSlideSorter.GetController().GetSelectionManager()->MoveSelectedPages(nDocumentIndex); - - ViewShell* pViewShell = mrSlideSorter.GetViewShell(); - if (pViewShell != NULL) - pViewShell->GetViewFrame()->GetBindings().Invalidate(SID_STATUS_PAGE); - } + meDragMode = eMode; } @@ -1849,11 +1778,14 @@ void RangeSelector::UpdateSelection (void) { view::SlideSorterView::DrawLock aLock (mrSlideSorter); + model::SlideSorterModel& rModel (mrSlideSorter.GetModel()); + const sal_Int32 nPageCount (rModel.GetPageCount()); + const sal_Int32 nIndexUnderMouse ( mrSlideSorter.GetView().GetLayouter().GetIndexAtPoint ( maSecondCorner, false)); - if (nIndexUnderMouse >= 0) + if (nIndexUnderMouse>=0 && nIndexUnderMouse + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_sd.hxx" + +#include "SlsSubstitutionHandler.hxx" + +#include "SlideSorter.hxx" +#include "model/SlideSorterModel.hxx" +#include "model/SlsPageEnumerationProvider.hxx" +#include "view/SlideSorterView.hxx" +#include "view/SlsViewOverlay.hxx" +#include "controller/SlideSorterController.hxx" +#include "controller/SlsInsertionIndicatorHandler.hxx" +#include "controller/SlsScrollBarManager.hxx" +#include "controller/SlsProperties.hxx" +#include "controller/SlsSelectionFunction.hxx" +#include "controller/SlsSelectionManager.hxx" +#include "app.hrc" +#include +#include + +namespace sd { namespace slidesorter { namespace controller { + +SubstitutionHandler::SubstitutionHandler ( + SlideSorter& rSlideSorter, + const model::SharedPageDescriptor& rpHitDescriptor, + const Point& rMouseModelPosition) + : mpTargetSlideSorter(&rSlideSorter), + mpHitDescriptor(rpHitDescriptor), + mnInsertionIndex(-1) +{ + // No Drag-and-Drop for master pages. + if (rSlideSorter.GetModel().GetEditMode() != EM_PAGE) + return; + + view::ViewOverlay& rOverlay (rSlideSorter.GetView().GetOverlay()); + + if ( ! rOverlay.GetSubstitutionOverlay()->IsVisible()) + { + // Show a new substitution for the selected page objects. + model::PageEnumeration aSelectedPages( + model::PageEnumerationProvider::CreateSelectedPagesEnumeration( + rSlideSorter.GetModel())); + rOverlay.GetSubstitutionOverlay()->Create( + aSelectedPages, + rMouseModelPosition, + mpHitDescriptor); + rOverlay.GetSubstitutionOverlay()->SetIsVisible(true); + rSlideSorter.GetController().GetInsertionIndicatorHandler()->Start( + rMouseModelPosition, + InsertionIndicatorHandler::MoveMode, + true); + } +} + + + + +SubstitutionHandler::~SubstitutionHandler (void) +{ + if (mpTargetSlideSorter != NULL) + mpTargetSlideSorter->GetController().GetScrollBarManager().StopAutoScroll(); + + Process(); + + if (mpTargetSlideSorter != NULL) + { + view::ViewOverlay& rOverlay (mpTargetSlideSorter->GetView().GetOverlay()); + rOverlay.GetSubstitutionOverlay()->SetIsVisible(false); + rOverlay.GetSubstitutionOverlay()->Clear(); + mpTargetSlideSorter->GetController().GetInsertionIndicatorHandler()->End(); + } + mpHitDescriptor.reset(); +} + + + + +void SubstitutionHandler::Dispose (void) +{ + mnInsertionIndex = -1; +} + + + + +void SubstitutionHandler::UpdatePosition ( + const Point& rMousePosition, + const InsertionIndicatorHandler::Mode eMode, + const bool bAllowAutoScroll) +{ + if (mpTargetSlideSorter == NULL) + return; + + if (mpTargetSlideSorter->GetProperties()->IsUIReadOnly()) + return; + + // Convert window coordinates into model coordinates (we need the + // window coordinates for auto-scrolling because that remains + // constant while scrolling.) + SharedSdWindow pWindow (mpTargetSlideSorter->GetContentWindow()); + const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition)); + + if ( ! (bAllowAutoScroll + && mpTargetSlideSorter->GetController().GetScrollBarManager().AutoScroll( + rMousePosition, + ::boost::bind( + &SubstitutionHandler::UpdatePosition, + this, + rMousePosition, + eMode, + false)))) + { + view::ViewOverlay& rOverlay (mpTargetSlideSorter->GetView().GetOverlay()); + + // Move the existing substitution to the new position. + rOverlay.GetSubstitutionOverlay()->SetPosition(aMouseModelPosition); + + mpTargetSlideSorter->GetController().GetInsertionIndicatorHandler()->UpdatePosition( + aMouseModelPosition, + eMode); + + // Remember the new insertion index. + if (mpTargetSlideSorter->GetController().GetInsertionIndicatorHandler()->IsInsertionTrivial(eMode)) + mnInsertionIndex = -1; + else + mnInsertionIndex = mpTargetSlideSorter->GetController().GetInsertionIndicatorHandler() + ->GetInsertionPageIndex(); + } +} + + + + +void SubstitutionHandler::Process (void) +{ + if (mpTargetSlideSorter == NULL) + return; + + if (mpTargetSlideSorter->GetProperties()->IsUIReadOnly()) + return; + + if (mnInsertionIndex >= 0) + { + // Tell the model to move the selected pages behind the one with the + // index mnInsertionIndex which first has to transformed into an index + // understandable by the document. + USHORT nDocumentIndex = (USHORT)mnInsertionIndex-1; + mpTargetSlideSorter->GetController().GetSelectionManager()->MoveSelectedPages(nDocumentIndex); + + ViewShell* pViewShell = mpTargetSlideSorter->GetViewShell(); + if (pViewShell != NULL) + pViewShell->GetViewFrame()->GetBindings().Invalidate(SID_STATUS_PAGE); + } +} + + + + +void SubstitutionHandler::Show (void) +{ + if (mpTargetSlideSorter != NULL) + { + view::ViewOverlay& rOverlay (mpTargetSlideSorter->GetView().GetOverlay()); + rOverlay.GetSubstitutionOverlay()->SetIsVisible(true); + } +} + + + + +void SubstitutionHandler::Hide (void) +{ + if (mpTargetSlideSorter != NULL) + { + view::ViewOverlay& rOverlay (mpTargetSlideSorter->GetView().GetOverlay()); + rOverlay.GetSubstitutionOverlay()->SetIsVisible(false); + } +} + + + + +void SubstitutionHandler::SetTargetSlideSorter ( + SlideSorter* pSlideSorter, + const Point aMousePosition, + const InsertionIndicatorHandler::Mode eMode, + const bool bIsOverSourceView) +{ + if (mpTargetSlideSorter != NULL) + { + mpOverlayState = mpTargetSlideSorter->GetView().GetOverlay().GetSubstitutionOverlay() + ->GetInternalState(); + mpTargetSlideSorter->GetController().GetInsertionIndicatorHandler()->End(); + } + + mpTargetSlideSorter = pSlideSorter; + + if (mpTargetSlideSorter != NULL) + { + mpTargetSlideSorter->GetView().GetOverlay().GetSubstitutionOverlay()->SetInternalState( + mpOverlayState); + mpTargetSlideSorter->GetController().GetInsertionIndicatorHandler()->Start( + aMousePosition, + eMode, + bIsOverSourceView); + } +} + + + +} } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsSubstitutionHandler.hxx b/sd/source/ui/slidesorter/controller/SlsSubstitutionHandler.hxx new file mode 100644 index 000000000000..da1a2ad0bd52 --- /dev/null +++ b/sd/source/ui/slidesorter/controller/SlsSubstitutionHandler.hxx @@ -0,0 +1,104 @@ +/************************************************************************* + * + * 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: SlsSelectionFunction.cxx,v $ + * $Revision: 1.37 $ + * + * 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 + * + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SD_SLIDESORTER_SUBSTITUTION_HANDLER_HXX +#define SD_SLIDESORTER_SUBSTITUTION_HANDLER_HXX + +#include + +#include "model/SlsSharedPageDescriptor.hxx" +#include "view/SlsViewOverlay.hxx" +#include "controller/SlsInsertionIndicatorHandler.hxx" + +namespace sd { namespace slidesorter { +class SlideSorter; +} } + + + +namespace sd { namespace slidesorter { namespace controller { + + +/** A SubstitutionHandler object handles the display of a number of selected + slides at the mouse position and the insertion or (with or without + removing the pages at their original position) when the object is + destoyed. +*/ +class SubstitutionHandler +{ +public: + /** Create a substitution display of the currently selected pages and + use the given position as the anchor point. + */ + SubstitutionHandler ( + SlideSorter& rSlideSorter, + const model::SharedPageDescriptor& rpHitDescriptor, + const Point& rMouseModelPosition); + ~SubstitutionHandler (void); + + /** Call this method (for example as reaction to ESC key press) to avoid + processing (ie moving or inserting) the substition when the called + SubstitutionHandler object is destroyed. + */ + void Dispose (void); + + /** Move the substitution display by the distance the mouse has + travelled since the last call to this method or to + CreateSubstitution(). The given point becomes the new anchor. + */ + void UpdatePosition ( + const Point& rMousePosition, + const InsertionIndicatorHandler::Mode eMode, + const bool bAllowAutoScroll = true); + + void Show (void); + void Hide (void); + void SetTargetSlideSorter ( + SlideSorter* pSlideSorter = NULL, + const Point aMousePosition = Point(0,0), + const InsertionIndicatorHandler::Mode eMode = InsertionIndicatorHandler::UnknownMode, + const bool bIsOverSourceView = false); + +private: + SlideSorter* mpTargetSlideSorter; + view::SubstitutionOverlay::SharedInternalState mpOverlayState; + model::SharedPageDescriptor mpHitDescriptor; + sal_Int32 mnInsertionIndex; + + /** Move the substitution display of the currently selected pages. + */ + void Process (void); +}; + + + +} } } // end of namespace ::sd::slidesorter::controller + +#endif diff --git a/sd/source/ui/slidesorter/controller/SlsTransferable.cxx b/sd/source/ui/slidesorter/controller/SlsTransferable.cxx index f072f6815285..e9c6f58b1289 100644 --- a/sd/source/ui/slidesorter/controller/SlsTransferable.cxx +++ b/sd/source/ui/slidesorter/controller/SlsTransferable.cxx @@ -42,9 +42,11 @@ Transferable::Transferable ( SdDrawDocument* pSrcDoc, ::sd::View* pWorkView, BOOL bInitOnGetData, - SlideSorterViewShell* pViewShell) + SlideSorterViewShell* pViewShell, + const ::boost::shared_ptr& rpSubstitutionHandler) : SdTransferable (pSrcDoc, pWorkView, bInitOnGetData), - mpViewShell(pViewShell) + mpViewShell(pViewShell), + mpSubstitutionHandler(rpSubstitutionHandler) { if (mpViewShell != NULL) StartListening(*mpViewShell); @@ -52,6 +54,7 @@ Transferable::Transferable ( + Transferable::~Transferable (void) { if (mpViewShell != NULL) @@ -65,6 +68,7 @@ void Transferable::DragFinished (sal_Int8 nDropAction) { if (mpViewShell != NULL) mpViewShell->DragFinished(nDropAction); + mpSubstitutionHandler.reset(); } @@ -92,4 +96,11 @@ void Transferable::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) +::boost::shared_ptr Transferable::GetSubstitutionHandler (void) const +{ + return mpSubstitutionHandler; +} + + + } } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/controller/SlsTransferable.hxx b/sd/source/ui/slidesorter/controller/SlsTransferable.hxx index 2dd02e068ade..3929e71176ff 100644 --- a/sd/source/ui/slidesorter/controller/SlsTransferable.hxx +++ b/sd/source/ui/slidesorter/controller/SlsTransferable.hxx @@ -45,6 +45,9 @@ namespace sd namespace sd { namespace slidesorter { namespace controller { +class SubstitutionHandler; + + /** This class exists to have DragFinished call the correct object: the SlideSorterViewShell instead of the old SlideView. */ @@ -56,14 +59,18 @@ public: SdDrawDocument* pSrcDoc, ::sd::View* pWorkView, BOOL bInitOnGetData, - SlideSorterViewShell* pViewShell); + SlideSorterViewShell* pViewShell, + const ::boost::shared_ptr& rpSubstitutionHandler); virtual ~Transferable (void); virtual void DragFinished (sal_Int8 nDropAction); + ::boost::shared_ptr GetSubstitutionHandler (void) const; + private: SlideSorterViewShell* mpViewShell; + ::boost::shared_ptr mpSubstitutionHandler; virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint); }; diff --git a/sd/source/ui/slidesorter/controller/makefile.mk b/sd/source/ui/slidesorter/controller/makefile.mk index be1e56464d59..6f48104fdd9c 100644 --- a/sd/source/ui/slidesorter/controller/makefile.mk +++ b/sd/source/ui/slidesorter/controller/makefile.mk @@ -62,11 +62,9 @@ SLOFILES = \ $(SLO)$/SlsSelectionFunction.obj \ $(SLO)$/SlsSelectionManager.obj \ $(SLO)$/SlsSlotManager.obj \ + $(SLO)$/SlsSubstitutionHandler.obj \ $(SLO)$/SlsTransferable.obj -EXCEPTIONSFILES= \ - $(SLO)$/SlideSorterController.obj - # --- Tagets ------------------------------------------------------- .INCLUDE : target.mk diff --git a/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx b/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx index bffb7d4574ba..ef5b07d8d670 100644 --- a/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx +++ b/sd/source/ui/slidesorter/inc/controller/SlideSorterController.hxx @@ -68,6 +68,7 @@ class InsertionIndicatorHandler; class Listener; class PageSelector; class ScrollBarManager; +class SelectionFunction; class SelectionManager; class SlotManager; @@ -207,6 +208,12 @@ public: */ virtual FunctionReference CreateSelectionFunction (SfxRequest& rRequest); + /** When the current function of the view shell is the slide sorter + selection function then return a reference to it. Otherwise return + an empty reference. + */ + ::rtl::Reference GetCurrentSelectionFunction (void); + /** Prepare for a change of the edit mode. Depending on the current edit mode we may save the selection so that it can be restored when later changing back to the current edit mode. diff --git a/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx b/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx index 006cf0083ed9..e50f7c3234eb 100644 --- a/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx +++ b/sd/source/ui/slidesorter/inc/controller/SlsInsertionIndicatorHandler.hxx @@ -52,13 +52,24 @@ public: InsertionIndicatorHandler (SlideSorter& rSlideSorter); ~InsertionIndicatorHandler (void); + enum Mode { CopyMode, MoveMode, UnknownMode }; + static Mode GetModeFromDndAction (const sal_Int8 nMode); + /** Activate the insertion marker at the given coordinates. */ - void Start (const Point& rMouseModelPosition); + void Start ( + const Point& rMouseModelPosition, + const Mode eMode, + const bool bIsOverSourceView); /** Set the position of the insertion marker to the given coordinates. */ - void UpdatePosition (const Point& rMouseModelPosition); + void UpdatePosition ( + const Point& rMouseModelPosition, + const Mode eMode); + void UpdatePosition ( + const Point& rMouseModelPosition, + const sal_Int8 nDndAction); /** Deactivate the insertion marker. */ @@ -73,12 +84,13 @@ public: */ sal_Int32 GetInsertionPageIndex (void) const; + /** Determine whether moving the current selection to the current position of the insertion marker would alter the document. This would be the case when the selection is not consecutive or would be moved to a position outside and not adjacent to the selection. */ - bool IsInsertionTrivial (void) const; + bool IsInsertionTrivial (const Mode eMode) const; private: SlideSorter& mrSlideSorter; @@ -86,11 +98,15 @@ private: ::boost::shared_ptr mpInsertionIndicatorOverlay; sal_Int32 mnInsertionIndex; bool mbIsBeforePage; + Mode meMode; bool mbIsInsertionTrivial; bool mbIsActive; bool mbIsReadOnly; + bool mbIsOverSourceView; - void SetPosition (const Point& rPoint); + void SetPosition ( + const Point& rPoint, + const Mode eMode); ::boost::shared_ptr GetInsertAnimator (void); }; diff --git a/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx b/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx index d618b1feeb50..0d22127a819e 100644 --- a/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx +++ b/sd/source/ui/slidesorter/inc/controller/SlsPageSelector.hxx @@ -201,9 +201,10 @@ private: model::SharedPageDescriptor mpSelectionAnchor; model::SharedPageDescriptor mpCurrentPage; sal_Int32 mnUpdateLockCount; + bool mbIsUpdateCurrentPagePending; void CountSelectedPages (void); - void UpdateCurrentPage (void); + void UpdateCurrentPage (const bool bUpdateOnlyWhenPending = false); }; } } } // end of namespace ::sd::slidesorter::controller diff --git a/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx b/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx index d1b8fedd1143..0eb5710e8bbd 100644 --- a/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx +++ b/sd/source/ui/slidesorter/inc/controller/SlsSelectionFunction.hxx @@ -33,6 +33,7 @@ #include "model/SlsSharedPageDescriptor.hxx" #include "controller/SlsFocusManager.hxx" +#include "controller/SlsInsertionIndicatorHandler.hxx" #include "fupoor.hxx" #include #include @@ -51,6 +52,8 @@ class SlideSorter; namespace sd { namespace slidesorter { namespace controller { class SlideSorterController; +class SubstitutionHandler; + class SelectionFunction : public FuPoor, @@ -93,6 +96,12 @@ public: void MouseDragged (const AcceptDropEvent& rEvent); + /** Turn of substitution display and insertion indicator. + */ + void NotifyDragFinished (void); + + ::boost::shared_ptr GetSubstitutionHandler (void) const; + class MouseMultiSelector; protected: @@ -106,7 +115,6 @@ protected: virtual ~SelectionFunction(); private: - class SubstitutionHandler; class EventDescriptor; /// Set in MouseButtonDown this flag indicates that a page has been hit. @@ -127,7 +135,7 @@ private: */ bool mbProcessingMouseButtonDown; - ::boost::scoped_ptr mpSubstitutionHandler; + ::boost::shared_ptr mpSubstitutionHandler; ::boost::scoped_ptr mpMouseMultiSelector; /** Remember where the left mouse button was pressed. @@ -143,7 +151,9 @@ private: sal_Int32 mnShiftKeySelectionAnchor; DECL_LINK( DragSlideHdl, Timer* ); - void StartDrag (const Point& rMousePosition); + void StartDrag ( + const Point& rMousePosition, + const InsertionIndicatorHandler::Mode eMode); /** Set the selection to exactly the specified page and also set it as the current page. diff --git a/sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx b/sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx index c7f3eb159899..105f4ca89f13 100644 --- a/sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx +++ b/sd/source/ui/slidesorter/inc/model/SlsPageDescriptor.hxx @@ -40,23 +40,12 @@ #include #include +#include + class SdPage; class SdrPage; -namespace sdr { namespace contact { -class ObjectContact; -} } - -namespace sd { namespace slidesorter { namespace view { -class PageObject; -class PageObjectViewObjectContact; -} } } - -namespace sd { namespace slidesorter { namespace controller { -class PageObjectFactory; -} } } - namespace sd { namespace slidesorter { namespace model { class SlideRenderer; @@ -141,6 +130,7 @@ private: SdPage* mpPage; css::uno::Reference mxPage; SdrPage const* mpMasterPage; + /** This index is displayed as page number in the view. It may or may not be the actual page index. */ diff --git a/sd/source/ui/slidesorter/inc/view/SlsTheme.hxx b/sd/source/ui/slidesorter/inc/view/SlsTheme.hxx index ad6a9ee7b2cb..851f8c4ffc49 100644 --- a/sd/source/ui/slidesorter/inc/view/SlsTheme.hxx +++ b/sd/source/ui/slidesorter/inc/view/SlsTheme.hxx @@ -77,8 +77,7 @@ public: MouseOverColor, PageNumberBorder, PageNumberColor, - Selection, - PreviewBorder + Selection }; ColorData GetColor (const ColorType eType); diff --git a/sd/source/ui/slidesorter/inc/view/SlsViewOverlay.hxx b/sd/source/ui/slidesorter/inc/view/SlsViewOverlay.hxx index 911160501935..b918da47bf8f 100644 --- a/sd/source/ui/slidesorter/inc/view/SlsViewOverlay.hxx +++ b/sd/source/ui/slidesorter/inc/view/SlsViewOverlay.hxx @@ -126,9 +126,11 @@ public: */ void Create ( model::PageEnumeration& rSelection, - const Point& rPosition, + const Point& rAnchor, const model::SharedPageDescriptor& rpHitDescriptor); + void SetAnchor (const Point& rAnchor); + /** Clear the substitution display. Until the next call of Create() no substution is painted. */ @@ -136,7 +138,7 @@ public: /** Move the substitution display by the given amount of pixels. */ - void Move (const Point& rOffset); + void Move (const Point& rPositionOffset); void SetPosition (const Point& rPosition); Point GetPosition (void) const; @@ -144,12 +146,19 @@ public: OutputDevice& rDevice, const Rectangle& rRepaintArea); + class InternalState; + typedef ::boost::shared_ptr SharedInternalState; + SharedInternalState GetInternalState (void) const; + void SetInternalState (const SharedInternalState& rpState); + protected: virtual Rectangle GetBoundingBox (void) const; private: + /** The current position can be set by calling SetPosition() or Move(). + */ Point maPosition; - Point maTranslation; + /** The substitution paints only the page object under the mouse and the 8-neighborhood around it. It uses different levels of transparency for the center and the four elements at its sides and the four @@ -160,16 +169,7 @@ private: static const sal_Int32 mnSideTransparency; static const sal_Int32 mnCornerTransparency; - class ItemDescriptor - { - public: - BitmapEx maImage; - Point maLocation; - double mnTransparency; - basegfx::B2DPolygon maShape; - }; - ::std::vector maItems; - Rectangle maBoundingBox; + SharedInternalState mpState; }; diff --git a/sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx b/sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx index 4977a7faa882..2b7a2832a5f8 100644 --- a/sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx +++ b/sd/source/ui/slidesorter/model/SlsPageDescriptor.cxx @@ -39,12 +39,14 @@ #include #include #include +#include using namespace ::com::sun::star::uno; using namespace ::com::sun::star; namespace sd { namespace slidesorter { namespace model { + PageDescriptor::PageDescriptor ( const Reference& rxPage, SdPage* pPage, @@ -64,7 +66,7 @@ PageDescriptor::PageDescriptor ( { OSL_ASSERT(mpPage); OSL_ASSERT(mpPage == SdPage::getImplementation(rxPage)); - if (mpPage!=NULL && !mpPage->IsMasterPage()) + if (mpPage!=NULL && mpPage->TRG_HasMasterPage()) mpMasterPage = &mpPage->TRG_GetMasterPage(); } @@ -105,7 +107,7 @@ sal_Int32 PageDescriptor::GetPageIndex (void) const bool PageDescriptor::UpdateMasterPage (void) { const SdrPage* pMaster = NULL; - if (mpPage!=NULL && !mpPage->IsMasterPage()) + if (mpPage!=NULL && mpPage->TRG_HasMasterPage()) pMaster = &mpPage->TRG_GetMasterPage(); if (mpMasterPage != pMaster) { diff --git a/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx b/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx index 97d2b563906d..992f65d03692 100644 --- a/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx +++ b/sd/source/ui/slidesorter/shell/SlideSorterViewShell.cxx @@ -601,7 +601,7 @@ void SlideSorterViewShell::ReadFrameViewData (FrameView* pFrameView) // sorter is displayed in a side pane then we ignore the value // of the frame view and adapt the number of columns // automatically to the window width. - rView.GetLayouter().SetColumnCount(1,5); + rView.GetLayouter().SetColumnCount(1,1); } else rView.GetLayouter().SetColumnCount(nSlidesPerRow,nSlidesPerRow); diff --git a/sd/source/ui/slidesorter/view/SlsLayouter.cxx b/sd/source/ui/slidesorter/view/SlsLayouter.cxx index 0f69e892779b..4ad682486f1a 100644 --- a/sd/source/ui/slidesorter/view/SlsLayouter.cxx +++ b/sd/source/ui/slidesorter/view/SlsLayouter.cxx @@ -40,21 +40,21 @@ namespace sd { namespace slidesorter { namespace view { Layouter::Layouter (const SharedSdWindow& rpWindow) : mpWindow(rpWindow), - mnRequestedLeftBorder(35), - mnRequestedRightBorder(35), - mnRequestedTopBorder(10), - mnRequestedBottomBorder(10), - mnLeftBorder(30), - mnRightBorder(30), - mnTopBorder(10), - mnBottomBorder(10), + mnRequestedLeftBorder(5), + mnRequestedRightBorder(5), + mnRequestedTopBorder(5), + mnRequestedBottomBorder(5), + mnLeftBorder(5), + mnRightBorder(5), + mnTopBorder(5), + mnBottomBorder(5), mnVerticalGap (10), - mnHorizontalGap (10), - mnMinimalWidth (100), - mnPreferredWidth (200), - mnMaximalWidth (300), - mnMinimalColumnCount (1), - mnMaximalColumnCount (5), + mnHorizontalGap(10), + mnMinimalWidth(100), + mnPreferredWidth(200), + mnMaximalWidth(300), + mnMinimalColumnCount(1), + mnMaximalColumnCount(1), mnPageCount(0), mnColumnCount(1), mnRowCount(0), diff --git a/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx b/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx index 10cd7ca93ef6..2b89006dc9ea 100644 --- a/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx +++ b/sd/source/ui/slidesorter/view/SlsPageObjectLayouter.cxx @@ -43,7 +43,7 @@ namespace { const static sal_Int32 gnPageNumberOffset = 5; const static sal_Int32 gnPageNumberFrameHorizontalOffset = 2; const static sal_Int32 gnPageNumberFrameVerticalOffset = 1; -const static sal_Int32 gnOuterBorderWidth = 6; +const static sal_Int32 gnOuterBorderWidth = 5; const static sal_Int32 gnInfoAreaMinWidth = 26; const static Size gaButtonSize (32,32); const static sal_Int32 gnButtonGap (5); diff --git a/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx b/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx index 93ef120e21bf..9921e3ca070c 100644 --- a/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx +++ b/sd/source/ui/slidesorter/view/SlsPageObjectPainter.cxx @@ -580,11 +580,9 @@ Bitmap PageObjectPainter::CreateBackgroundBitmap( mpShadowPainter->PaintFrame(aBitmapDevice, aFrameBox); // Clear the area where the preview will later be painted. - /* aBitmapDevice.SetFillColor(mpTheme->GetColor(Theme::Background)); - aBitmapDevice.SetLineColor(mpTheme->GetColor(Theme::PreviewBorder)); - aBitmapDevice.DrawRect(aFrameBox); - */ + aBitmapDevice.SetLineColor(mpTheme->GetColor(Theme::Background)); + aBitmapDevice.DrawRect(aBox); return aBitmapDevice.GetBitmap (Point(0,0),aSize); } diff --git a/sd/source/ui/slidesorter/view/SlsTheme.cxx b/sd/source/ui/slidesorter/view/SlsTheme.cxx index ddc1e4ccd543..a40dda166eee 100644 --- a/sd/source/ui/slidesorter/view/SlsTheme.cxx +++ b/sd/source/ui/slidesorter/view/SlsTheme.cxx @@ -214,9 +214,6 @@ ColorData Theme::GetColor (const ColorType eType) case Selection: return StellaBlue; - - case PreviewBorder: - return 0x000000; } return 0; } diff --git a/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx b/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx index d406a3c866b7..8f8357ffb934 100644 --- a/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx +++ b/sd/source/ui/slidesorter/view/SlsViewOverlay.cxx @@ -105,6 +105,41 @@ Rectangle ConvertRectangle (const B2DRectangle& rBox) namespace sd { namespace slidesorter { namespace view { +//===== SubstitutionOverlay::InternalState ==================================== + +class ItemDescriptor +{ +public: + BitmapEx maImage; + Point maLocation; + double mnTransparency; + basegfx::B2DPolygon maShape; +}; + +class SubstitutionOverlay::InternalState +{ +public: + /** The set of items that is displayed as substitution of the selected + pages. Note that the number of items may differ from the number of + selected pages because only the selected pages in the neighborhood + of the anchor page are included. + */ + ::std::vector maItems; + + /** Bounding box of all items in maItems at their original location. + */ + Rectangle maBoundingBox; + + /** The anchor position of the substitution is the paint that, after + translation, is mapped onto the current position. + */ + Point maAnchor; + +}; + + + + //===== ViewOverlay ========================================================= ViewOverlay::ViewOverlay ( @@ -293,9 +328,7 @@ SubstitutionOverlay::SubstitutionOverlay ( const sal_Int32 nLayerIndex) : OverlayBase(rViewOverlay, nLayerIndex), maPosition(0,0), - maTranslation(0,0), - maItems(), - maBoundingBox() + mpState(new InternalState()) { } @@ -311,11 +344,13 @@ SubstitutionOverlay::~SubstitutionOverlay (void) void SubstitutionOverlay::Create ( model::PageEnumeration& rSelection, - const Point& rPosition, + const Point& rAnchor, const model::SharedPageDescriptor& rpHitDescriptor) { - maPosition = rPosition; - maTranslation = Point(0,0); + OSL_ASSERT(mpState); + + mpState->maAnchor = rAnchor; + maPosition = rAnchor; ::boost::shared_ptr pPreviewCache ( mrViewOverlay.GetSlideSorter().GetView().GetPreviewCache()); @@ -330,7 +365,7 @@ void SubstitutionOverlay::Create ( ? rLayouter.GetColumn(rpHitDescriptor->GetPageIndex()) : -1); - maItems.clear(); + mpState->maItems.clear(); while (rSelection.HasMoreElements()) { model::SharedPageDescriptor pDescriptor (rSelection.GetNextElement()); @@ -357,7 +392,7 @@ void SubstitutionOverlay::Create ( } const Rectangle aBox (pDescriptor->GetBoundingBox()); - maBoundingBox.Union(aBox); + mpState->maBoundingBox.Union(aBox); basegfx::B2DRectangle aB2DBox( aBox.Left(), aBox.Top(), @@ -367,19 +402,20 @@ void SubstitutionOverlay::Create ( const Bitmap aBitmap (pPreviewCache->GetPreviewBitmap(pDescriptor->GetPage()).GetBitmap()); AlphaMask aMask (aBitmap.GetSizePixel()); aMask.Erase(nTransparency); - maItems.push_back(ItemDescriptor()); - maItems.back().maImage = BitmapEx( + mpState->maItems.push_back(ItemDescriptor()); + ItemDescriptor& rNewItem (mpState->maItems.back()); + rNewItem.maImage = BitmapEx( aBitmap, aMask); - maItems.back().maLocation = pPageObjectLayouter->GetBoundingBox( + rNewItem.maLocation = pPageObjectLayouter->GetBoundingBox( pDescriptor, PageObjectLayouter::Preview, PageObjectLayouter::WindowCoordinateSystem).TopLeft(); - maItems.back().mnTransparency = nTransparency/255.0; - maItems.back().maShape = basegfx::tools::createPolygonFromRect(aB2DBox); + rNewItem.mnTransparency = nTransparency/255.0; + rNewItem.maShape = basegfx::tools::createPolygonFromRect(aB2DBox); } - SetIsVisible(maItems.size() > 0); + SetIsVisible(mpState->maItems.size() > 0); } @@ -388,7 +424,20 @@ void SubstitutionOverlay::Create ( void SubstitutionOverlay::Clear (void) { SetIsVisible(false); - maItems.clear(); + mpState.reset(new InternalState()); +} + + + + +void SubstitutionOverlay::SetAnchor (const Point& rAnchor) +{ + OSL_ASSERT(mpState); + if (mpState->maAnchor != rAnchor) + { + Invalidator aInvalidator (*this); + mpState->maAnchor = rAnchor; + } } @@ -396,11 +445,11 @@ void SubstitutionOverlay::Clear (void) void SubstitutionOverlay::Move (const Point& rOffset) { - Invalidator aInvalidator (*this); - - maPosition += rOffset; - maTranslation += rOffset; - maBoundingBox.Move(rOffset.X(), rOffset.Y()); + if (rOffset != Point(0,0)) + { + Invalidator aInvalidator (*this); + maPosition += rOffset; + } } @@ -408,7 +457,11 @@ void SubstitutionOverlay::Move (const Point& rOffset) void SubstitutionOverlay::SetPosition (const Point& rPosition) { - Move(rPosition - GetPosition()); + if (maPosition != rPosition) + { + Invalidator aInvalidator (*this); + maPosition = rPosition; + } } @@ -427,26 +480,28 @@ void SubstitutionOverlay::Paint ( const Rectangle& rRepaintArea) { (void)rRepaintArea; + OSL_ASSERT(mpState); if ( ! IsVisible()) return; + const Point aOffset (maPosition - mpState->maAnchor); basegfx::B2DHomMatrix aTranslation; - aTranslation.translate(maTranslation.X(), maTranslation.Y()); + aTranslation.translate(aOffset.X(), aOffset.Y()); rDevice.SetFillColor(Color(AirForceBlue)); rDevice.SetLineColor(); for (::std::vector::const_iterator - iItem(maItems.begin()), - iEnd(maItems.end()); + iItem(mpState->maItems.begin()), + iEnd(mpState->maItems.end()); iItem!=iEnd; ++iItem) { ::basegfx::B2DPolyPolygon aPolygon (iItem->maShape); aPolygon.transform(aTranslation); rDevice.DrawTransparent(aPolygon, iItem->mnTransparency); - rDevice.DrawBitmapEx(iItem->maLocation+maTranslation, iItem->maImage); + rDevice.DrawBitmapEx(iItem->maLocation+aOffset, iItem->maImage); } } @@ -455,7 +510,28 @@ void SubstitutionOverlay::Paint ( Rectangle SubstitutionOverlay::GetBoundingBox (void) const { - return maBoundingBox; + OSL_ASSERT(mpState); + + Rectangle aBox (mpState->maBoundingBox); + aBox.Move(maPosition.X() - mpState->maAnchor.X(), maPosition.Y() - mpState->maAnchor.Y()); + return aBox; +} + + + + +SubstitutionOverlay::SharedInternalState SubstitutionOverlay::GetInternalState (void) const +{ + return mpState; +} + + + + +void SubstitutionOverlay::SetInternalState (const SharedInternalState& rpState) +{ + if (rpState) + mpState = rpState; }