| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include "precompiled_sd.hxx" |
| |
| #include "controller/SlsSelectionFunction.hxx" |
| |
| #include "SlideSorter.hxx" |
| #include "SlideSorterViewShell.hxx" |
| #include "SlsDragAndDropContext.hxx" |
| #include "controller/SlsTransferableData.hxx" |
| #include "controller/SlideSorterController.hxx" |
| #include "controller/SlsPageSelector.hxx" |
| #include "controller/SlsFocusManager.hxx" |
| #include "controller/SlsScrollBarManager.hxx" |
| #include "controller/SlsClipboard.hxx" |
| #include "controller/SlsCurrentSlideManager.hxx" |
| #include "controller/SlsInsertionIndicatorHandler.hxx" |
| #include "controller/SlsSelectionManager.hxx" |
| #include "controller/SlsProperties.hxx" |
| #include "controller/SlsProperties.hxx" |
| #include "controller/SlsSlotManager.hxx" |
| #include "controller/SlsVisibleAreaManager.hxx" |
| #include "model/SlideSorterModel.hxx" |
| #include "model/SlsPageDescriptor.hxx" |
| #include "model/SlsPageEnumerationProvider.hxx" |
| #include "view/SlideSorterView.hxx" |
| #include "view/SlsLayouter.hxx" |
| #include "view/SlsPageObjectLayouter.hxx" |
| #include "view/SlsButtonBar.hxx" |
| #include "framework/FrameworkHelper.hxx" |
| #include "ViewShellBase.hxx" |
| #include "DrawController.hxx" |
| #include "Window.hxx" |
| #include "sdpage.hxx" |
| #include "drawdoc.hxx" |
| #include "DrawDocShell.hxx" |
| #include "sdxfer.hxx" |
| #include "ViewShell.hxx" |
| #include "ViewShellBase.hxx" |
| #include "FrameView.hxx" |
| #include "app.hrc" |
| #include "sdresid.hxx" |
| #include "strings.hrc" |
| #include <vcl/sound.hxx> |
| #include <sfx2/viewfrm.hxx> |
| #include <sfx2/dispatch.hxx> |
| #include <svx/svdpagv.hxx> |
| #include <vcl/msgbox.hxx> |
| #include <svx/svxids.hrc> |
| #include <boost/bind.hpp> |
| #include <boost/optional.hpp> |
| |
| namespace { |
| static const sal_uInt32 SINGLE_CLICK (0x00000001); |
| static const sal_uInt32 DOUBLE_CLICK (0x00000002); |
| static const sal_uInt32 LEFT_BUTTON (0x00000010); |
| static const sal_uInt32 RIGHT_BUTTON (0x00000020); |
| static const sal_uInt32 MIDDLE_BUTTON (0x00000040); |
| static const sal_uInt32 BUTTON_DOWN (0x00000100); |
| static const sal_uInt32 BUTTON_UP (0x00000200); |
| static const sal_uInt32 MOUSE_MOTION (0x00000400); |
| static const sal_uInt32 MOUSE_DRAG (0x00000800); |
| // The rest leaves the lower 16 bit untouched so that it can be used with |
| // key codes. |
| static const sal_uInt32 OVER_SELECTED_PAGE (0x00010000); |
| static const sal_uInt32 OVER_UNSELECTED_PAGE (0x00020000); |
| static const sal_uInt32 OVER_FADE_INDICATOR (0x00040000); |
| static const sal_uInt32 OVER_BUTTON_AREA (0x00080000); |
| static const sal_uInt32 OVER_BUTTON (0x00100000); |
| static const sal_uInt32 SHIFT_MODIFIER (0x00200000); |
| static const sal_uInt32 CONTROL_MODIFIER (0x00400000); |
| |
| static const sal_uInt32 KEY_EVENT (0x10000000); |
| |
| // Some absent events are defined so they can be expressed explicitly. |
| static const sal_uInt32 NO_MODIFIER (0x00000000); |
| static const sal_uInt32 NOT_OVER_PAGE (0x00000000); |
| |
| // Masks |
| static const sal_uInt32 MODIFIER_MASK (SHIFT_MODIFIER | CONTROL_MODIFIER); |
| static const sal_uInt32 BUTTON_MASK (LEFT_BUTTON | RIGHT_BUTTON | MIDDLE_BUTTON); |
| |
| } // end of anonymous namespace |
| |
| |
| |
| // Define some macros to make the following switch statement more readable. |
| #define ANY_MODIFIER(code) \ |
| code|NO_MODIFIER: \ |
| case code|SHIFT_MODIFIER: \ |
| case code|CONTROL_MODIFIER |
| |
| namespace sd { namespace slidesorter { namespace controller { |
| |
| //===== SelectionFunction::EventDescriptor ==================================== |
| |
| class SelectionFunction::EventDescriptor |
| { |
| public: |
| Point maMousePosition; |
| Point maMouseModelPosition; |
| model::SharedPageDescriptor mpHitDescriptor; |
| SdrPage* mpHitPage; |
| sal_uInt32 mnEventCode; |
| bool mbIsOverButton; |
| InsertionIndicatorHandler::Mode meDragMode; |
| bool mbMakeSelectionVisible; |
| bool mbIsLeaving; |
| |
| EventDescriptor ( |
| sal_uInt32 nEventType, |
| const MouseEvent& rEvent, |
| SlideSorter& rSlideSorter); |
| EventDescriptor ( |
| sal_uInt32 nEventType, |
| const AcceptDropEvent& rEvent, |
| const sal_Int8 nDragAction, |
| SlideSorter& rSlideSorter); |
| EventDescriptor ( |
| const KeyEvent& rEvent, |
| SlideSorter& rSlideSorter); |
| |
| void SetDragMode (const InsertionIndicatorHandler::Mode eMode); |
| |
| private: |
| /** Compute a numerical code that describes a mouse event and that can |
| be used for fast look up of the appropriate reaction. |
| */ |
| sal_uInt32 EncodeMouseEvent (const MouseEvent& rEvent) const; |
| |
| /** Compute a numerical code that describes a key event and that can |
| be used for fast look up of the appropriate reaction. |
| */ |
| sal_uInt32 EncodeKeyEvent (const KeyEvent& rEvent) const; |
| |
| /** Compute a numerical code that describes the current state like |
| whether the selection rectangle is visible or whether the page under |
| the mouse or the one that has the focus is selected. |
| */ |
| sal_uInt32 EncodeState (void) const; |
| }; |
| |
| |
| |
| |
| //===== SelectionFunction::ModeHandler ======================================== |
| |
| class SelectionFunction::ModeHandler |
| { |
| public: |
| ModeHandler ( |
| SlideSorter& rSlideSorter, |
| SelectionFunction& rSelectionFunction, |
| const bool bIsMouseOverIndicatorAllowed); |
| virtual ~ModeHandler (void); |
| |
| virtual Mode GetMode (void) const = 0; |
| virtual void Abort (void) = 0; |
| virtual void ProcessEvent (EventDescriptor& rDescriptor); |
| |
| /** Set the selection to exactly the specified page and also set it as |
| the current page. |
| */ |
| void SetCurrentPage (const model::SharedPageDescriptor& rpDescriptor); |
| |
| /// Deselect all pages. |
| void DeselectAllPages (void); |
| void SelectOnePage (const model::SharedPageDescriptor& rpDescriptor); |
| |
| /** When the view on which this selection function is working is the |
| main view then the view is switched to the regular editing view. |
| */ |
| void SwitchView (const model::SharedPageDescriptor& rpDescriptor); |
| |
| void StartDrag ( |
| const Point& rMousePosition, |
| const InsertionIndicatorHandler::Mode eMode); |
| |
| bool IsMouseOverIndicatorAllowed (void) const; |
| |
| protected: |
| SlideSorter& mrSlideSorter; |
| SelectionFunction& mrSelectionFunction; |
| |
| virtual bool ProcessButtonDownEvent (EventDescriptor& rDescriptor); |
| virtual bool ProcessButtonUpEvent (EventDescriptor& rDescriptor); |
| virtual bool ProcessMotionEvent (EventDescriptor& rDescriptor); |
| virtual bool ProcessDragEvent (EventDescriptor& rDescriptor); |
| virtual bool HandleUnprocessedEvent (EventDescriptor& rDescriptor); |
| |
| void ReprocessEvent (EventDescriptor& rDescriptor); |
| |
| private: |
| const bool mbIsMouseOverIndicatorAllowed; |
| }; |
| |
| |
| /** This is the default handler for processing events. It activates the |
| multi selection or drag-and-drop when the right conditions are met. |
| */ |
| class NormalModeHandler : public SelectionFunction::ModeHandler |
| { |
| public: |
| NormalModeHandler ( |
| SlideSorter& rSlideSorter, |
| SelectionFunction& rSelectionFunction); |
| virtual ~NormalModeHandler (void); |
| |
| virtual SelectionFunction::Mode GetMode (void) const; |
| virtual void Abort (void); |
| |
| void ResetButtonDownLocation (void); |
| |
| protected: |
| virtual bool ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| |
| private: |
| ::boost::optional<Point> maButtonDownLocation; |
| |
| /** Select all pages between and including the selection anchor and the |
| specified page. |
| */ |
| void RangeSelect (const model::SharedPageDescriptor& rpDescriptor); |
| }; |
| |
| |
| /** Handle events during a multi selection, which typically is started by |
| pressing the left mouse button when not over a page. |
| */ |
| class MultiSelectionModeHandler : public SelectionFunction::ModeHandler |
| { |
| public: |
| /** Start a rectangle selection at the given position. |
| */ |
| MultiSelectionModeHandler ( |
| SlideSorter& rSlideSorter, |
| SelectionFunction& rSelectionFunction, |
| const Point& rMouseModelPosition, |
| const sal_uInt32 nEventCode); |
| virtual ~MultiSelectionModeHandler (void); |
| |
| virtual SelectionFunction::Mode GetMode (void) const; |
| virtual void Abort (void); |
| virtual void ProcessEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| |
| enum SelectionMode { SM_Normal, SM_Add, SM_Toggle }; |
| |
| void SetSelectionMode (const SelectionMode eSelectionMode); |
| void SetSelectionModeFromModifier (const sal_uInt32 nEventCode); |
| |
| protected: |
| virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| virtual bool HandleUnprocessedEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| |
| private: |
| SelectionMode meSelectionMode; |
| Point maSecondCorner; |
| Pointer maSavedPointer; |
| sal_Int32 mnAnchorIndex; |
| sal_Int32 mnSecondIndex; |
| view::ButtonBar::Lock maButtonBarLock; |
| |
| virtual void UpdateModelPosition (const Point& rMouseModelPosition); |
| virtual void UpdateSelection (void); |
| |
| /** Update the rectangle selection so that the given position becomes |
| the new second point of the selection rectangle. |
| */ |
| void UpdatePosition ( |
| const Point& rMousePosition, |
| const bool bAllowAutoScroll); |
| |
| void UpdateSelectionState ( |
| const model::SharedPageDescriptor& rpDescriptor, |
| const bool bIsInSelection) const; |
| }; |
| |
| |
| /** Handle events during drag-and-drop. |
| */ |
| class DragAndDropModeHandler : public SelectionFunction::ModeHandler |
| { |
| public: |
| DragAndDropModeHandler ( |
| SlideSorter& rSlideSorter, |
| SelectionFunction& rSelectionFunction, |
| const Point& rMousePosition, |
| ::Window* pWindow); |
| virtual ~DragAndDropModeHandler (void); |
| |
| virtual SelectionFunction::Mode GetMode (void) const; |
| virtual void Abort (void); |
| |
| protected: |
| virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| |
| private: |
| ::boost::scoped_ptr<DragAndDropContext> mpDragAndDropContext; |
| }; |
| |
| |
| /** Handle events while the left mouse button is pressed over the button |
| bar. |
| */ |
| class ButtonModeHandler : public SelectionFunction::ModeHandler |
| { |
| public: |
| ButtonModeHandler ( |
| SlideSorter& rSlideSorter, |
| SelectionFunction& rSelectionFunction); |
| virtual ~ButtonModeHandler (void); |
| virtual void Abort (void); |
| |
| virtual SelectionFunction::Mode GetMode (void) const; |
| |
| protected: |
| virtual bool ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor); |
| }; |
| |
| |
| |
| |
| //===== SelectionFunction ===================================================== |
| |
| |
| |
| SelectionFunction::SelectionFunction ( |
| SlideSorter& rSlideSorter, |
| SfxRequest& rRequest) |
| : FuPoor ( |
| rSlideSorter.GetViewShell(), |
| rSlideSorter.GetContentWindow().get(), |
| &rSlideSorter.GetView(), |
| rSlideSorter.GetModel().GetDocument(), |
| rRequest), |
| mrSlideSorter(rSlideSorter), |
| mrController(mrSlideSorter.GetController()), |
| mbDragSelection(false), |
| maInsertionMarkerBox(), |
| mbProcessingMouseButtonDown(false), |
| mnShiftKeySelectionAnchor(-1), |
| mpModeHandler(new NormalModeHandler(rSlideSorter, *this)) |
| { |
| } |
| |
| |
| |
| |
| SelectionFunction::~SelectionFunction (void) |
| { |
| mpModeHandler.reset(); |
| } |
| |
| |
| |
| |
| FunctionReference SelectionFunction::Create( |
| SlideSorter& rSlideSorter, |
| SfxRequest& rRequest) |
| { |
| FunctionReference xFunc( new SelectionFunction( rSlideSorter, rRequest ) ); |
| return xFunc; |
| } |
| |
| |
| |
| |
| bool SelectionFunction::MouseButtonDown (const MouseEvent& rEvent) |
| { |
| // #95491# remember button state for creation of own MouseEvents |
| SetMouseButtonCode (rEvent.GetButtons()); |
| aMDPos = basegfx::B2DPoint(rEvent.GetPosPixel().X(), rEvent.GetPosPixel().Y()); |
| mbProcessingMouseButtonDown = true; |
| |
| // mpWindow->CaptureMouse(); |
| |
| ProcessMouseEvent(BUTTON_DOWN, rEvent); |
| |
| return true; |
| } |
| |
| |
| |
| |
| bool SelectionFunction::MouseMove (const MouseEvent& rEvent) |
| { |
| ProcessMouseEvent(MOUSE_MOTION, rEvent); |
| return sal_True; |
| } |
| |
| |
| |
| |
| bool SelectionFunction::MouseButtonUp (const MouseEvent& rEvent) |
| { |
| mrController.GetScrollBarManager().StopAutoScroll (); |
| |
| ProcessMouseEvent(BUTTON_UP, rEvent); |
| |
| mbProcessingMouseButtonDown = false; |
| // mpWindow->ReleaseMouse(); |
| |
| return true; |
| } |
| |
| |
| |
| |
| void SelectionFunction::NotifyDragFinished (void) |
| { |
| SwitchToNormalMode(); |
| } |
| |
| |
| |
| |
| bool SelectionFunction::KeyInput (const KeyEvent& rEvent) |
| { |
| view::SlideSorterView::DrawLock aDrawLock (mrSlideSorter); |
| PageSelector::BroadcastLock aBroadcastLock (mrSlideSorter); |
| PageSelector::UpdateLock aLock (mrSlideSorter); |
| FocusManager& rFocusManager (mrController.GetFocusManager()); |
| bool bResult = false; |
| |
| const KeyCode& rCode (rEvent.GetKeyCode()); |
| switch (rCode.GetCode()) |
| { |
| case KEY_RETURN: |
| { |
| model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor()); |
| ViewShell* pViewShell = mrSlideSorter.GetViewShell(); |
| if (rFocusManager.HasFocus() && pDescriptor && pViewShell!=NULL) |
| { |
| // The Return key triggers different functions depending on |
| // whether the slide sorter is the main view or displayed in |
| // the right pane. |
| if (pViewShell->IsMainViewShell()) |
| { |
| mpModeHandler->SetCurrentPage(pDescriptor); |
| mpModeHandler->SwitchView(pDescriptor); |
| } |
| else |
| { |
| pViewShell->GetDispatcher()->Execute( |
| SID_INSERTPAGE, |
| SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD); |
| } |
| bResult = true; |
| } |
| break; |
| } |
| |
| case KEY_TAB: |
| if ( ! rFocusManager.IsFocusShowing()) |
| { |
| rFocusManager.ShowFocus(); |
| bResult = sal_True; |
| } |
| break; |
| |
| case KEY_ESCAPE: |
| // When there is an active multiselection or drag-and-drop |
| // operation then stop that. |
| mpModeHandler->Abort(); |
| SwitchToNormalMode(); |
| bResult = sal_True; |
| break; |
| |
| case KEY_SPACE: |
| { |
| // Toggle the selection state. |
| model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor()); |
| if (pDescriptor && rCode.IsMod1()) |
| { |
| if (pDescriptor->HasState(model::PageDescriptor::ST_Selected)) |
| mrController.GetPageSelector().DeselectPage(pDescriptor, false); |
| else |
| mrController.GetPageSelector().SelectPage(pDescriptor); |
| } |
| bResult = true; |
| } |
| break; |
| |
| |
| // Move the focus indicator left. |
| case KEY_LEFT: |
| MoveFocus(FocusManager::FMD_LEFT, rCode.IsShift(), rCode.IsMod1()); |
| bResult = sal_True; |
| break; |
| |
| // Move the focus indicator right. |
| case KEY_RIGHT: |
| MoveFocus(FocusManager::FMD_RIGHT, rCode.IsShift(), rCode.IsMod1()); |
| bResult = sal_True; |
| break; |
| |
| // Move the focus indicator up. |
| case KEY_UP: |
| MoveFocus(FocusManager::FMD_UP, rCode.IsShift(), rCode.IsMod1()); |
| bResult = sal_True; |
| break; |
| |
| // Move the focus indicator down. |
| case KEY_DOWN: |
| MoveFocus(FocusManager::FMD_DOWN, rCode.IsShift(), rCode.IsMod1()); |
| bResult = sal_True; |
| break; |
| |
| // Go to previous page. No wrap around. |
| case KEY_PAGEUP: |
| GotoNextPage(-1); |
| bResult = true; |
| break; |
| |
| // Go to next page. No wrap around.. |
| case KEY_PAGEDOWN: |
| GotoNextPage(+1); |
| bResult = true; |
| break; |
| |
| case KEY_HOME: |
| GotoPage(0); |
| bResult = sal_True; |
| break; |
| |
| case KEY_END: |
| GotoPage(mrSlideSorter.GetModel().GetPageCount()-1); |
| bResult = sal_True; |
| break; |
| |
| case KEY_DELETE: |
| case KEY_BACKSPACE: |
| { |
| if (mrSlideSorter.GetProperties()->IsUIReadOnly()) |
| break; |
| |
| mrController.GetSelectionManager()->DeleteSelectedPages(rCode.GetCode()==KEY_DELETE); |
| |
| mnShiftKeySelectionAnchor = -1; |
| bResult = sal_True; |
| } |
| break; |
| |
| case KEY_F10: |
| if (rCode.IsShift()) |
| { |
| mpModeHandler->SelectOnePage( |
| mrSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor()); |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| if ( ! bResult) |
| bResult = FuPoor::KeyInput(rEvent); |
| |
| return bResult; |
| } |
| |
| |
| |
| |
| void SelectionFunction::MoveFocus ( |
| const FocusManager::FocusMoveDirection eDirection, |
| const bool bIsShiftDown, |
| const bool bIsControlDown) |
| { |
| // Remember the anchor of shift key multi selection. |
| if (bIsShiftDown) |
| { |
| if (mnShiftKeySelectionAnchor<0) |
| { |
| model::SharedPageDescriptor pFocusedDescriptor ( |
| mrController.GetFocusManager().GetFocusedPageDescriptor()); |
| mnShiftKeySelectionAnchor = pFocusedDescriptor->GetPageIndex(); |
| } |
| } |
| else if ( ! bIsControlDown) |
| ResetShiftKeySelectionAnchor(); |
| |
| mrController.GetFocusManager().MoveFocus(eDirection); |
| |
| PageSelector& rSelector (mrController.GetPageSelector()); |
| model::SharedPageDescriptor pFocusedDescriptor ( |
| mrController.GetFocusManager().GetFocusedPageDescriptor()); |
| if (bIsShiftDown) |
| { |
| // When shift is pressed then select all pages in the range between |
| // the currently and the previously focused pages, including them. |
| if (pFocusedDescriptor) |
| { |
| sal_Int32 nPageRangeEnd (pFocusedDescriptor->GetPageIndex()); |
| model::PageEnumeration aPages ( |
| model::PageEnumerationProvider::CreateAllPagesEnumeration( |
| mrSlideSorter.GetModel())); |
| while (aPages.HasMoreElements()) |
| { |
| model::SharedPageDescriptor pDescriptor (aPages.GetNextElement()); |
| if (pDescriptor) |
| { |
| const sal_Int32 nPageIndex(pDescriptor->GetPageIndex()); |
| if ((nPageIndex>=mnShiftKeySelectionAnchor && nPageIndex<=nPageRangeEnd) |
| || (nPageIndex<=mnShiftKeySelectionAnchor && nPageIndex>=nPageRangeEnd)) |
| { |
| rSelector.SelectPage(pDescriptor); |
| } |
| else |
| { |
| rSelector.DeselectPage(pDescriptor); |
| } |
| } |
| } |
| } |
| } |
| else if (bIsControlDown) |
| { |
| // When control is pressed then do not alter the selection or the |
| // current page, just move the focus. |
| } |
| else |
| { |
| // Without shift just select the focused page. |
| mpModeHandler->SelectOnePage(pFocusedDescriptor); |
| } |
| } |
| |
| |
| |
| |
| void SelectionFunction::Activate() |
| { |
| FuPoor::Activate(); |
| } |
| |
| |
| |
| |
| void SelectionFunction::Deactivate() |
| { |
| FuPoor::Deactivate(); |
| } |
| |
| |
| |
| void SelectionFunction::ScrollStart (void) |
| { |
| } |
| |
| |
| |
| |
| void SelectionFunction::ScrollEnd (void) |
| { |
| } |
| |
| |
| |
| |
| void SelectionFunction::DoCut (void) |
| { |
| if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly()) |
| { |
| mrController.GetClipboard().DoCut(); |
| } |
| } |
| |
| |
| |
| |
| void SelectionFunction::DoCopy (void) |
| { |
| mrController.GetClipboard().DoCopy(); |
| } |
| |
| |
| |
| |
| void SelectionFunction::DoPaste (void) |
| { |
| if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly()) |
| { |
| mrController.GetClipboard().DoPaste(); |
| } |
| } |
| |
| |
| |
| |
| bool SelectionFunction::cancel (void) |
| { |
| mrController.GetFocusManager().ToggleFocus(); |
| return true; |
| } |
| |
| |
| |
| |
| void SelectionFunction::GotoNextPage (int nOffset) |
| { |
| model::SharedPageDescriptor pDescriptor |
| = mrController.GetCurrentSlideManager()->GetCurrentSlide(); |
| if (pDescriptor.get() != NULL) |
| { |
| SdPage* pPage = pDescriptor->GetPage(); |
| OSL_ASSERT(pPage!=NULL); |
| sal_Int32 nIndex = (pPage->GetPageNumber()-1) / 2; |
| GotoPage(nIndex + nOffset); |
| } |
| ResetShiftKeySelectionAnchor(); |
| } |
| |
| |
| |
| |
| void SelectionFunction::GotoPage (sal_uInt32 nIndex) |
| { |
| const sal_uInt32 nPageCount = mrSlideSorter.GetModel().GetPageCount(); |
| |
| if (nIndex >= nPageCount) |
| nIndex = nPageCount - 1; |
| |
| mrController.GetFocusManager().SetFocusedPage(nIndex); |
| model::SharedPageDescriptor pNextPageDescriptor ( |
| mrSlideSorter.GetModel().GetPageDescriptor (nIndex)); |
| if (pNextPageDescriptor.get() != NULL) |
| mpModeHandler->SetCurrentPage(pNextPageDescriptor); |
| else |
| { |
| OSL_ASSERT(pNextPageDescriptor.get() != NULL); |
| } |
| ResetShiftKeySelectionAnchor(); |
| } |
| |
| |
| |
| |
| void SelectionFunction::ProcessMouseEvent (sal_uInt32 nEventType, const MouseEvent& rEvent) |
| { |
| // #95491# remember button state for creation of own MouseEvents |
| SetMouseButtonCode (rEvent.GetButtons()); |
| |
| EventDescriptor aEventDescriptor (nEventType, rEvent, mrSlideSorter); |
| ProcessEvent(aEventDescriptor); |
| } |
| |
| |
| |
| |
| void SelectionFunction::MouseDragged ( |
| const AcceptDropEvent& rEvent, |
| const sal_Int8 nDragAction) |
| { |
| EventDescriptor aEventDescriptor (MOUSE_DRAG, rEvent, nDragAction, mrSlideSorter); |
| ProcessEvent(aEventDescriptor); |
| } |
| |
| |
| |
| |
| void SelectionFunction::ProcessKeyEvent (const KeyEvent& rEvent) |
| { |
| EventDescriptor aEventDescriptor (rEvent, mrSlideSorter); |
| ProcessEvent(aEventDescriptor); |
| } |
| |
| |
| |
| |
| void SelectionFunction::ProcessEvent (EventDescriptor& rDescriptor) |
| { |
| // The call to ProcessEvent may switch to another mode handler. |
| // Prevent the untimely destruction of the called handler by acquiring a |
| // temporary reference here. |
| ::boost::shared_ptr<ModeHandler> pModeHandler (mpModeHandler); |
| pModeHandler->ProcessEvent(rDescriptor); |
| } |
| |
| |
| |
| |
| bool Match ( |
| const sal_uInt32 nEventCode, |
| const sal_uInt32 nPositivePattern) |
| { |
| return (nEventCode & nPositivePattern)==nPositivePattern; |
| } |
| |
| |
| |
| |
| void SelectionFunction::SwitchToNormalMode (void) |
| { |
| if (mpModeHandler->GetMode() != NormalMode) |
| SwitchMode(::boost::shared_ptr<ModeHandler>( |
| new NormalModeHandler(mrSlideSorter, *this))); |
| } |
| |
| |
| |
| |
| void SelectionFunction::SwitchToDragAndDropMode (const Point aMousePosition) |
| { |
| if (mpModeHandler->GetMode() != DragAndDropMode) |
| { |
| SwitchMode(::boost::shared_ptr<ModeHandler>( |
| new DragAndDropModeHandler(mrSlideSorter, *this, aMousePosition, mpWindow))); |
| } |
| } |
| |
| |
| |
| |
| void SelectionFunction::SwitchToMultiSelectionMode ( |
| const Point aMousePosition, |
| const sal_uInt32 nEventCode) |
| { |
| if (mpModeHandler->GetMode() != MultiSelectionMode) |
| SwitchMode(::boost::shared_ptr<ModeHandler>( |
| new MultiSelectionModeHandler(mrSlideSorter, *this, aMousePosition, nEventCode))); |
| } |
| |
| |
| |
| |
| bool SelectionFunction::SwitchToButtonMode (void) |
| { |
| // Do not show the buttons for draw pages. |
| ::boost::shared_ptr<ViewShell> pMainViewShell (mrSlideSorter.GetViewShellBase()->GetMainViewShell()); |
| if (pMainViewShell |
| && pMainViewShell->GetShellType()!=ViewShell::ST_DRAW |
| && mpModeHandler->GetMode() != ButtonMode) |
| { |
| SwitchMode(::boost::shared_ptr<ModeHandler>(new ButtonModeHandler(mrSlideSorter, *this))); |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| |
| |
| |
| void SelectionFunction::SwitchMode (const ::boost::shared_ptr<ModeHandler>& rpHandler) |
| { |
| // Not all modes allow mouse over indicator. |
| if (mpModeHandler->IsMouseOverIndicatorAllowed() != rpHandler->IsMouseOverIndicatorAllowed()) |
| { |
| if ( ! rpHandler->IsMouseOverIndicatorAllowed()) |
| { |
| mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor()); |
| mrSlideSorter.GetView().GetButtonBar().ResetPage(); |
| } |
| else |
| mrSlideSorter.GetView().UpdatePageUnderMouse(false); |
| } |
| |
| mpModeHandler = rpHandler; |
| } |
| |
| |
| |
| |
| void SelectionFunction::ResetShiftKeySelectionAnchor (void) |
| { |
| mnShiftKeySelectionAnchor = -1; |
| } |
| |
| |
| |
| |
| void SelectionFunction::ResetMouseAnchor (void) |
| { |
| if (mpModeHandler && mpModeHandler->GetMode() == NormalMode) |
| { |
| ::boost::shared_ptr<NormalModeHandler> pHandler ( |
| ::boost::dynamic_pointer_cast<NormalModeHandler>(mpModeHandler)); |
| if (pHandler) |
| pHandler->ResetButtonDownLocation(); |
| } |
| } |
| |
| |
| |
| |
| //===== EventDescriptor ======================================================= |
| |
| SelectionFunction::EventDescriptor::EventDescriptor ( |
| const sal_uInt32 nEventType, |
| const MouseEvent& rEvent, |
| SlideSorter& rSlideSorter) |
| : maMousePosition(rEvent.GetPosPixel()), |
| maMouseModelPosition(), |
| mpHitDescriptor(), |
| mpHitPage(), |
| mnEventCode(nEventType), |
| mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()), |
| meDragMode(InsertionIndicatorHandler::MoveMode), |
| mbMakeSelectionVisible(true), |
| mbIsLeaving(false) |
| { |
| maMouseModelPosition = rSlideSorter.GetContentWindow()->PixelToLogic(maMousePosition); |
| mpHitDescriptor = rSlideSorter.GetController().GetPageAt(maMousePosition); |
| if (mpHitDescriptor) |
| { |
| mpHitPage = mpHitDescriptor->GetPage(); |
| } |
| |
| mnEventCode |= EncodeMouseEvent(rEvent); |
| mnEventCode |= EncodeState(); |
| |
| // 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. |
| mbIsLeaving = rEvent.IsLeaveWindow() |
| || ! Rectangle(Point(0,0), |
| rSlideSorter.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition); |
| } |
| |
| |
| |
| |
| SelectionFunction::EventDescriptor::EventDescriptor ( |
| const sal_uInt32 nEventType, |
| const AcceptDropEvent& rEvent, |
| const sal_Int8 nDragAction, |
| SlideSorter& rSlideSorter) |
| : maMousePosition(rEvent.maPosPixel), |
| maMouseModelPosition(), |
| mpHitDescriptor(), |
| mpHitPage(), |
| mnEventCode(nEventType), |
| mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()), |
| meDragMode(InsertionIndicatorHandler::GetModeFromDndAction(nDragAction)), |
| mbMakeSelectionVisible(true), |
| mbIsLeaving(false) |
| { |
| maMouseModelPosition = rSlideSorter.GetContentWindow()->PixelToLogic(maMousePosition); |
| mpHitDescriptor = rSlideSorter.GetController().GetPageAt(maMousePosition); |
| if (mpHitDescriptor) |
| { |
| mpHitPage = mpHitDescriptor->GetPage(); |
| } |
| |
| mnEventCode |= EncodeState(); |
| |
| // 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. |
| mbIsLeaving = rEvent.mbLeaving |
| || ! Rectangle(Point(0,0), |
| rSlideSorter.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition); |
| } |
| |
| |
| |
| |
| SelectionFunction::EventDescriptor::EventDescriptor ( |
| const KeyEvent& rEvent, |
| SlideSorter& rSlideSorter) |
| : maMousePosition(), |
| maMouseModelPosition(), |
| mpHitDescriptor(), |
| mpHitPage(), |
| mnEventCode(KEY_EVENT), |
| mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()), |
| meDragMode(InsertionIndicatorHandler::MoveMode), |
| mbMakeSelectionVisible(true), |
| mbIsLeaving(false) |
| { |
| model::SharedPageDescriptor pHitDescriptor ( |
| rSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor()); |
| if (pHitDescriptor.get() != NULL) |
| { |
| mpHitPage = pHitDescriptor->GetPage(); |
| mpHitDescriptor = pHitDescriptor; |
| } |
| |
| mnEventCode |= EncodeKeyEvent(rEvent) | EncodeState(); |
| } |
| |
| |
| |
| |
| void SelectionFunction::EventDescriptor::SetDragMode (const InsertionIndicatorHandler::Mode eMode) |
| { |
| meDragMode = eMode; |
| } |
| |
| |
| |
| |
| sal_uInt32 SelectionFunction::EventDescriptor::EncodeMouseEvent ( |
| const MouseEvent& rEvent) const |
| { |
| // Initialize with the type of mouse event. |
| sal_uInt32 nEventCode (mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION)); |
| |
| // Detect the affected button. |
| switch (rEvent.GetButtons()) |
| { |
| case MOUSE_LEFT: nEventCode |= LEFT_BUTTON; break; |
| case MOUSE_RIGHT: nEventCode |= RIGHT_BUTTON; break; |
| case MOUSE_MIDDLE: nEventCode |= MIDDLE_BUTTON; break; |
| } |
| |
| // Detect the number of clicks. |
| switch (rEvent.GetClicks()) |
| { |
| case 1: nEventCode |= SINGLE_CLICK; break; |
| case 2: nEventCode |= DOUBLE_CLICK; break; |
| } |
| |
| // Detect pressed modifier keys. |
| if (rEvent.IsShift()) |
| nEventCode |= SHIFT_MODIFIER; |
| if (rEvent.IsMod1()) |
| nEventCode |= CONTROL_MODIFIER; |
| |
| // Detect whether the mouse is over one of the active elements inside a |
| // page object. |
| if (mbIsOverButton) |
| nEventCode |= OVER_BUTTON; |
| |
| return nEventCode; |
| } |
| |
| |
| |
| |
| sal_uInt32 SelectionFunction::EventDescriptor::EncodeKeyEvent (const KeyEvent& rEvent) const |
| { |
| // The key code in the lower 16 bit. |
| sal_uInt32 nEventCode (rEvent.GetKeyCode().GetCode()); |
| |
| // Detect pressed modifier keys. |
| if (rEvent.GetKeyCode().IsShift()) |
| nEventCode |= SHIFT_MODIFIER; |
| if (rEvent.GetKeyCode().IsMod1()) |
| nEventCode |= CONTROL_MODIFIER; |
| |
| return nEventCode; |
| } |
| |
| |
| |
| |
| sal_uInt32 SelectionFunction::EventDescriptor::EncodeState (void) const |
| { |
| sal_uInt32 nEventCode (0); |
| |
| // Detect whether the event has happened over a page object. |
| if (mpHitPage!=NULL && mpHitDescriptor) |
| { |
| if (mpHitDescriptor->HasState(model::PageDescriptor::ST_Selected)) |
| nEventCode |= OVER_SELECTED_PAGE; |
| else |
| nEventCode |= OVER_UNSELECTED_PAGE; |
| |
| // Detect whether the mouse is over one of the active elements |
| // inside a page object. |
| if (mbIsOverButton) |
| nEventCode |= OVER_BUTTON; |
| } |
| |
| return nEventCode; |
| } |
| |
| |
| |
| |
| //===== SelectionFunction::ModeHandler ======================================== |
| |
| SelectionFunction::ModeHandler::ModeHandler ( |
| SlideSorter& rSlideSorter, |
| SelectionFunction& rSelectionFunction, |
| const bool bIsMouseOverIndicatorAllowed) |
| : mrSlideSorter(rSlideSorter), |
| mrSelectionFunction(rSelectionFunction), |
| mbIsMouseOverIndicatorAllowed(bIsMouseOverIndicatorAllowed) |
| { |
| } |
| |
| |
| |
| |
| SelectionFunction::ModeHandler::~ModeHandler (void) |
| { |
| } |
| |
| |
| |
| |
| void SelectionFunction::ModeHandler::ReprocessEvent (EventDescriptor& rDescriptor) |
| { |
| mrSelectionFunction.ProcessEvent(rDescriptor); |
| } |
| |
| |
| |
| |
| void SelectionFunction::ModeHandler::ProcessEvent ( |
| SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| PageSelector::BroadcastLock aBroadcastLock (mrSlideSorter); |
| PageSelector::UpdateLock aUpdateLock (mrSlideSorter); |
| |
| bool bIsProcessed (false); |
| switch (rDescriptor.mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION | MOUSE_DRAG)) |
| { |
| case BUTTON_DOWN: |
| bIsProcessed = ProcessButtonDownEvent(rDescriptor); |
| break; |
| |
| case BUTTON_UP: |
| bIsProcessed = ProcessButtonUpEvent(rDescriptor); |
| break; |
| |
| case MOUSE_MOTION: |
| bIsProcessed = ProcessMotionEvent(rDescriptor); |
| break; |
| |
| case MOUSE_DRAG: |
| bIsProcessed = ProcessDragEvent(rDescriptor); |
| break; |
| } |
| |
| if ( ! bIsProcessed) |
| HandleUnprocessedEvent(rDescriptor); |
| } |
| |
| |
| |
| |
| bool SelectionFunction::ModeHandler::ProcessButtonDownEvent (EventDescriptor&) |
| { |
| return false; |
| } |
| |
| |
| |
| |
| bool SelectionFunction::ModeHandler::ProcessButtonUpEvent (EventDescriptor&) |
| { |
| mrSelectionFunction.SwitchToNormalMode(); |
| return false; |
| } |
| |
| |
| |
| |
| bool SelectionFunction::ModeHandler::ProcessMotionEvent (EventDescriptor& rDescriptor) |
| { |
| if (mbIsMouseOverIndicatorAllowed) |
| mrSlideSorter.GetView().UpdatePageUnderMouse( |
| rDescriptor.maMousePosition, |
| (rDescriptor.mnEventCode & LEFT_BUTTON) != 0, |
| true); |
| |
| if (rDescriptor.mbIsLeaving) |
| { |
| mrSelectionFunction.SwitchToNormalMode(); |
| mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor()); |
| |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| |
| |
| |
| bool SelectionFunction::ModeHandler::ProcessDragEvent (EventDescriptor&) |
| { |
| return false; |
| } |
| |
| |
| |
| |
| bool SelectionFunction::ModeHandler::HandleUnprocessedEvent (EventDescriptor&) |
| { |
| return false; |
| } |
| |
| |
| |
| |
| void SelectionFunction::ModeHandler::SetCurrentPage ( |
| const model::SharedPageDescriptor& rpDescriptor) |
| { |
| SelectOnePage(rpDescriptor); |
| mrSlideSorter.GetController().GetCurrentSlideManager()->SwitchCurrentSlide(rpDescriptor); |
| } |
| |
| |
| |
| |
| void SelectionFunction::ModeHandler::DeselectAllPages (void) |
| { |
| mrSlideSorter.GetController().GetPageSelector().DeselectAllPages(); |
| mrSelectionFunction.ResetShiftKeySelectionAnchor(); |
| } |
| |
| |
| |
| |
| void SelectionFunction::ModeHandler::SelectOnePage ( |
| const model::SharedPageDescriptor& rpDescriptor) |
| { |
| DeselectAllPages(); |
| mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor); |
| } |
| |
| |
| |
| |
| void SelectionFunction::ModeHandler::SwitchView (const model::SharedPageDescriptor& rpDescriptor) |
| { |
| // Switch to the draw view. This is done only when the current |
| // view is the main view. |
| ViewShell* pViewShell = mrSlideSorter.GetViewShell(); |
| if (pViewShell!=NULL && pViewShell->IsMainViewShell()) |
| { |
| if (rpDescriptor.get()!=NULL && rpDescriptor->GetPage()!=NULL) |
| { |
| mrSlideSorter.GetModel().GetDocument()->SetSelected(rpDescriptor->GetPage(), sal_True); |
| pViewShell->GetFrameView()->SetSelectedPage( |
| (rpDescriptor->GetPage()->GetPageNumber()-1)/2); |
| } |
| if (mrSlideSorter.GetViewShellBase() != NULL) |
| framework::FrameworkHelper::Instance(*mrSlideSorter.GetViewShellBase())->RequestView( |
| framework::FrameworkHelper::msImpressViewURL, |
| framework::FrameworkHelper::msCenterPaneURL); |
| } |
| } |
| |
| |
| |
| |
| void SelectionFunction::ModeHandler::StartDrag ( |
| const Point& rMousePosition, |
| const InsertionIndicatorHandler::Mode eMode) |
| { |
| (void)eMode; |
| // Do not start a drag-and-drop operation when one is already active. |
| // (when dragging pages from one document into another, pressing a |
| // modifier key can trigger a MouseMotion event in the originating |
| // window (focus still in there). Together with the mouse button pressed |
| // (drag-and-drop is active) this triggers the start of drag-and-drop.) |
| if (SD_MOD()->pTransferDrag != NULL) |
| return; |
| |
| if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly()) |
| { |
| mrSelectionFunction.SwitchToDragAndDropMode(rMousePosition); |
| } |
| } |
| |
| |
| |
| |
| bool SelectionFunction::ModeHandler::IsMouseOverIndicatorAllowed (void) const |
| { |
| return mbIsMouseOverIndicatorAllowed; |
| } |
| |
| |
| |
| |
| //===== NormalModeHandler ===================================================== |
| |
| NormalModeHandler::NormalModeHandler ( |
| SlideSorter& rSlideSorter, |
| SelectionFunction& rSelectionFunction) |
| : ModeHandler(rSlideSorter, rSelectionFunction, true), |
| maButtonDownLocation() |
| { |
| } |
| |
| |
| |
| |
| NormalModeHandler::~NormalModeHandler (void) |
| { |
| } |
| |
| |
| |
| |
| SelectionFunction::Mode NormalModeHandler::GetMode (void) const |
| { |
| return SelectionFunction::NormalMode; |
| } |
| |
| |
| |
| |
| void NormalModeHandler::Abort (void) |
| { |
| } |
| |
| |
| |
| |
| bool NormalModeHandler::ProcessButtonDownEvent ( |
| SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| // Remember the location where the left button is pressed. With |
| // that we can filter away motion events that are caused by key |
| // presses. We also can tune the minimal motion distance that |
| // triggers a drag-and-drop operation. |
| if ((rDescriptor.mnEventCode & BUTTON_DOWN) != 0) |
| maButtonDownLocation = rDescriptor.maMousePosition; |
| |
| switch (rDescriptor.mnEventCode) |
| { |
| case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE: |
| SetCurrentPage(rDescriptor.mpHitDescriptor); |
| break; |
| |
| case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE: |
| break; |
| |
| case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | OVER_SELECTED_PAGE: |
| case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | OVER_UNSELECTED_PAGE: |
| // A double click allways shows the selected slide in the center |
| // pane in an edit view. |
| SetCurrentPage(rDescriptor.mpHitDescriptor); |
| SwitchView(rDescriptor.mpHitDescriptor); |
| break; |
| |
| case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | SHIFT_MODIFIER: |
| case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | SHIFT_MODIFIER: |
| // Range selection with the shift modifier. |
| RangeSelect(rDescriptor.mpHitDescriptor); |
| break; |
| |
| case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | OVER_BUTTON: |
| case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | OVER_BUTTON: |
| OSL_ASSERT(mrSlideSorter.GetView().GetButtonBar().IsMouseOverButton()); |
| |
| // Switch to button mode only when the buttons are visible |
| // (or being faded in.) |
| if (mrSlideSorter.GetView().GetButtonBar().IsVisible(rDescriptor.mpHitDescriptor)) |
| { |
| if (mrSelectionFunction.SwitchToButtonMode()) |
| ReprocessEvent(rDescriptor); |
| } |
| else |
| { |
| // When the buttons are not (yet) visible then behave like |
| // the left button had been clicked over any other part of |
| // the slide. |
| SetCurrentPage(rDescriptor.mpHitDescriptor); |
| } |
| break; |
| |
| // Right button for context menu. |
| case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE: |
| // Single right click and shift+F10 select as preparation to |
| // show the context menu. Change the selection only when the |
| // page under the mouse is not selected. In this case the |
| // selection is set to this single page. Otherwise the |
| // selection is not modified. |
| SetCurrentPage(rDescriptor.mpHitDescriptor); |
| rDescriptor.mbMakeSelectionVisible = false; |
| break; |
| |
| case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE: |
| // Do not change the selection. Just adjust the insertion indicator. |
| rDescriptor.mbMakeSelectionVisible = false; |
| break; |
| |
| case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE: |
| // Remember the current selection so that when a multi selection |
| // is started, we can restore the previous selection. |
| mrSlideSorter.GetModel().SaveCurrentSelection(); |
| DeselectAllPages(); |
| break; |
| |
| case ANY_MODIFIER(BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE): |
| // Remember the current selection so that when a multi selection |
| // is started, we can restore the previous selection. |
| mrSlideSorter.GetModel().SaveCurrentSelection(); |
| DeselectAllPages(); |
| break; |
| |
| default: |
| return false; |
| } |
| return true; |
| } |
| |
| |
| |
| |
| bool NormalModeHandler::ProcessButtonUpEvent ( |
| SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| bool bIsProcessed (true); |
| switch (rDescriptor.mnEventCode) |
| { |
| case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE: |
| SetCurrentPage(rDescriptor.mpHitDescriptor); |
| break; |
| |
| // Multi selection with the control modifier. |
| case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | CONTROL_MODIFIER: |
| mrSlideSorter.GetController().GetPageSelector().DeselectPage( |
| rDescriptor.mpHitDescriptor); |
| break; |
| |
| case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | CONTROL_MODIFIER: |
| mrSlideSorter.GetController().GetPageSelector().SelectPage( |
| rDescriptor.mpHitDescriptor); |
| mrSlideSorter.GetView().UpdatePageUnderMouse( |
| rDescriptor.mpHitDescriptor, |
| rDescriptor.maMousePosition, |
| false); |
| break; |
| case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE: |
| break; |
| |
| default: |
| bIsProcessed = false; |
| break; |
| } |
| mrSelectionFunction.SwitchToNormalMode(); |
| return bIsProcessed; |
| } |
| |
| |
| |
| |
| |
| bool NormalModeHandler::ProcessMotionEvent ( |
| SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| if (ModeHandler::ProcessMotionEvent(rDescriptor)) |
| return true; |
| |
| bool bIsProcessed (true); |
| switch (rDescriptor.mnEventCode) |
| { |
| case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE): |
| // SetCurrentPage(rDescriptor.mpHitDescriptor); |
| // Fallthrough |
| |
| // A mouse motion without visible substitution starts that. |
| case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE): |
| { |
| if (maButtonDownLocation) |
| { |
| const sal_Int32 nDistance (maButtonDownLocation |
| ? ::std::max ( |
| abs(maButtonDownLocation->X() - rDescriptor.maMousePosition.X()), |
| abs(maButtonDownLocation->Y() - rDescriptor.maMousePosition.Y())) |
| : 0); |
| if (nDistance > 3) |
| StartDrag( |
| rDescriptor.maMousePosition, |
| (rDescriptor.mnEventCode & CONTROL_MODIFIER) != 0 |
| ? InsertionIndicatorHandler::CopyMode |
| : InsertionIndicatorHandler::MoveMode); |
| } |
| } |
| break; |
| |
| // A mouse motion not over a page starts a rectangle selection. |
| case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE): |
| mrSelectionFunction.SwitchToMultiSelectionMode( |
| rDescriptor.maMouseModelPosition, |
| rDescriptor.mnEventCode); |
| break; |
| |
| default: |
| bIsProcessed = false; |
| break; |
| } |
| return bIsProcessed; |
| } |
| |
| |
| |
| |
| bool NormalModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| mrSelectionFunction.SwitchToDragAndDropMode(rDescriptor.maMousePosition); |
| ReprocessEvent(rDescriptor); |
| return true; |
| } |
| |
| |
| |
| |
| void NormalModeHandler::RangeSelect (const model::SharedPageDescriptor& rpDescriptor) |
| { |
| PageSelector::UpdateLock aLock (mrSlideSorter); |
| PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector()); |
| |
| model::SharedPageDescriptor pAnchor (rSelector.GetSelectionAnchor()); |
| DeselectAllPages(); |
| |
| if (pAnchor.get() != NULL) |
| { |
| // Select all pages between the anchor and the given one, including |
| // the two. |
| const sal_uInt32 nAnchorIndex ((pAnchor->GetPage()->GetPageNumber()-1) / 2); |
| const sal_uInt32 nOtherIndex ((rpDescriptor->GetPage()->GetPageNumber()-1) / 2); |
| |
| // Iterate over all pages in the range. Start with the anchor |
| // page. This way the PageSelector will recognize it again as |
| // anchor (the first selected page after a DeselectAllPages() |
| // becomes the anchor.) |
| const sal_uInt32 nStep ((nAnchorIndex < nOtherIndex) ? +1 : -1); |
| sal_uInt32 nIndex (nAnchorIndex); |
| while (true) |
| { |
| rSelector.SelectPage(nIndex); |
| if (nIndex == nOtherIndex) |
| break; |
| nIndex = nIndex + nStep; |
| } |
| } |
| } |
| |
| |
| |
| |
| void NormalModeHandler::ResetButtonDownLocation (void) |
| { |
| maButtonDownLocation = ::boost::optional<Point>(); |
| } |
| |
| |
| |
| |
| //===== MultiSelectionModeHandler ============================================= |
| |
| MultiSelectionModeHandler::MultiSelectionModeHandler ( |
| SlideSorter& rSlideSorter, |
| SelectionFunction& rSelectionFunction, |
| const Point& rMouseModelPosition, |
| const sal_uInt32 nEventCode) |
| : ModeHandler(rSlideSorter, rSelectionFunction, false), |
| meSelectionMode(SM_Normal), |
| maSecondCorner(rMouseModelPosition), |
| maSavedPointer(mrSlideSorter.GetContentWindow()->GetPointer()), |
| mnAnchorIndex(-1), |
| mnSecondIndex(-1), |
| maButtonBarLock(rSlideSorter) |
| { |
| const Pointer aSelectionPointer (POINTER_TEXT); |
| mrSlideSorter.GetContentWindow()->SetPointer(aSelectionPointer); |
| SetSelectionModeFromModifier(nEventCode); |
| } |
| |
| |
| |
| |
| |
| MultiSelectionModeHandler::~MultiSelectionModeHandler (void) |
| { |
| mrSlideSorter.GetContentWindow()->SetPointer(maSavedPointer); |
| } |
| |
| |
| |
| |
| SelectionFunction::Mode MultiSelectionModeHandler::GetMode (void) const |
| { |
| return SelectionFunction::MultiSelectionMode; |
| } |
| |
| |
| |
| |
| void MultiSelectionModeHandler::Abort (void) |
| { |
| mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection()); |
| } |
| |
| |
| |
| |
| void MultiSelectionModeHandler::ProcessEvent ( |
| SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| // During a multi selection we do not want sudden jumps of the |
| // visible area caused by moving newly selected pages into view. |
| // Therefore disable that temporarily. The disabler object is |
| // released at the end of the event processing, after the focus and |
| // current slide have been updated. |
| VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter); |
| |
| ModeHandler::ProcessEvent(rDescriptor); |
| } |
| |
| |
| |
| |
| bool MultiSelectionModeHandler::ProcessButtonUpEvent ( |
| SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK)) |
| { |
| mrSelectionFunction.SwitchToNormalMode(); |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| |
| |
| |
| bool MultiSelectionModeHandler::ProcessMotionEvent ( |
| SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| // The selection rectangle is visible. Handle events accordingly. |
| if (Match(rDescriptor.mnEventCode, MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK)) |
| { |
| SetSelectionModeFromModifier(rDescriptor.mnEventCode); |
| UpdatePosition(rDescriptor.maMousePosition, true); |
| rDescriptor.mbMakeSelectionVisible = false; |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| |
| |
| bool MultiSelectionModeHandler::HandleUnprocessedEvent ( |
| SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| if ( ! ModeHandler::HandleUnprocessedEvent(rDescriptor)) |
| { |
| // If the event has not been processed then stop multi selection. |
| mrSelectionFunction.SwitchToNormalMode(); |
| ReprocessEvent(rDescriptor); |
| } |
| return true; |
| } |
| |
| |
| |
| |
| void MultiSelectionModeHandler::UpdatePosition ( |
| const Point& rMousePosition, |
| const bool bAllowAutoScroll) |
| { |
| VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter); |
| |
| // 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( |
| &MultiSelectionModeHandler::UpdatePosition, |
| this, |
| rMousePosition, |
| false)))) |
| { |
| UpdateModelPosition(aMouseModelPosition); |
| } |
| } |
| |
| |
| |
| |
| void MultiSelectionModeHandler::SetSelectionModeFromModifier ( |
| const sal_uInt32 nEventCode) |
| { |
| switch (nEventCode & MODIFIER_MASK) |
| { |
| case NO_MODIFIER: |
| SetSelectionMode(SM_Normal); |
| break; |
| |
| case SHIFT_MODIFIER: |
| SetSelectionMode(SM_Add); |
| break; |
| |
| case CONTROL_MODIFIER: |
| SetSelectionMode(SM_Toggle); |
| break; |
| } |
| } |
| |
| |
| |
| |
| void MultiSelectionModeHandler::SetSelectionMode (const SelectionMode eSelectionMode) |
| { |
| if (meSelectionMode != eSelectionMode) |
| { |
| meSelectionMode = eSelectionMode; |
| UpdateSelection(); |
| } |
| } |
| |
| |
| |
| |
| void MultiSelectionModeHandler::UpdateSelectionState ( |
| const model::SharedPageDescriptor& rpDescriptor, |
| const bool bIsInSelection) const |
| { |
| // Determine whether the page was selected before the rectangle |
| // selection was started. |
| const bool bWasSelected (rpDescriptor->HasState(model::PageDescriptor::ST_WasSelected)); |
| |
| // Combine the two selection states depending on the selection mode. |
| bool bSelect (false); |
| switch(meSelectionMode) |
| { |
| case SM_Normal: |
| bSelect = bIsInSelection; |
| break; |
| |
| case SM_Add: |
| bSelect = bIsInSelection || bWasSelected; |
| break; |
| |
| case SM_Toggle: |
| if (bIsInSelection) |
| bSelect = !bWasSelected; |
| else |
| bSelect = bWasSelected; |
| break; |
| } |
| |
| // Set the new selection state. |
| if (bSelect) |
| mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor); |
| else |
| mrSlideSorter.GetController().GetPageSelector().DeselectPage(rpDescriptor); |
| } |
| |
| |
| |
| |
| void MultiSelectionModeHandler::UpdateModelPosition (const Point& rMouseModelPosition) |
| { |
| maSecondCorner = rMouseModelPosition; |
| UpdateSelection(); |
| } |
| |
| |
| |
| |
| void MultiSelectionModeHandler::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, |
| false)); |
| if (nIndexUnderMouse>=0 && nIndexUnderMouse<nPageCount) |
| { |
| if (mnAnchorIndex < 0) |
| mnAnchorIndex = nIndexUnderMouse; |
| mnSecondIndex = nIndexUnderMouse; |
| |
| Range aRange (mnAnchorIndex, mnSecondIndex); |
| aRange.Justify(); |
| |
| for (sal_Int32 nIndex=0; nIndex<nPageCount; ++nIndex) |
| { |
| UpdateSelectionState(rModel.GetPageDescriptor(nIndex), aRange.IsInside(nIndex)); |
| } |
| } |
| } |
| |
| |
| |
| |
| //===== DragAndDropModeHandler ================================================ |
| |
| DragAndDropModeHandler::DragAndDropModeHandler ( |
| SlideSorter& rSlideSorter, |
| SelectionFunction& rSelectionFunction, |
| const Point& rMousePosition, |
| ::Window* pWindow) |
| : ModeHandler(rSlideSorter, rSelectionFunction, false) |
| { |
| SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; |
| if (pDragTransferable==NULL && mrSlideSorter.GetViewShell() != NULL) |
| { |
| SlideSorterViewShell* pSlideSorterViewShell |
| = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell()); |
| if (pSlideSorterViewShell != NULL) |
| pSlideSorterViewShell->StartDrag(basegfx::B2DPoint(rMousePosition.X(), rMousePosition.Y()), pWindow); |
| pDragTransferable = SD_MOD()->pTransferDrag; |
| } |
| |
| mpDragAndDropContext.reset(new DragAndDropContext(mrSlideSorter)); |
| mrSlideSorter.GetController().GetInsertionIndicatorHandler()->Start( |
| pDragTransferable != NULL |
| && pDragTransferable->GetView()==&mrSlideSorter.GetView()); |
| } |
| |
| |
| |
| |
| DragAndDropModeHandler::~DragAndDropModeHandler (void) |
| { |
| if (mpDragAndDropContext) |
| { |
| // Disconnect the substitution handler from this selection function. |
| mpDragAndDropContext->SetTargetSlideSorter(); |
| mpDragAndDropContext.reset(); |
| } |
| mrSlideSorter.GetController().GetInsertionIndicatorHandler()->End(Animator::AM_Animated); |
| } |
| |
| |
| |
| |
| SelectionFunction::Mode DragAndDropModeHandler::GetMode (void) const |
| { |
| return SelectionFunction::DragAndDropMode; |
| } |
| |
| |
| |
| |
| void DragAndDropModeHandler::Abort (void) |
| { |
| mrSlideSorter.GetController().GetClipboard().Abort(); |
| if (mpDragAndDropContext) |
| mpDragAndDropContext->Dispose(); |
| // mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection()); |
| } |
| |
| |
| |
| |
| bool DragAndDropModeHandler::ProcessButtonUpEvent ( |
| SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON)) |
| { |
| // The following Process() call may lead to the destruction |
| // of rDescriptor.mpHitDescriptor so release our reference to it. |
| rDescriptor.mpHitDescriptor.reset(); |
| mrSelectionFunction.SwitchToNormalMode(); |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| |
| |
| |
| bool DragAndDropModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| OSL_ASSERT(mpDragAndDropContext); |
| |
| if (rDescriptor.mbIsLeaving) |
| { |
| mrSelectionFunction.SwitchToNormalMode(); |
| } |
| else if (mpDragAndDropContext) |
| { |
| mpDragAndDropContext->UpdatePosition( |
| rDescriptor.maMousePosition, |
| rDescriptor.meDragMode); |
| } |
| |
| return true; |
| } |
| |
| |
| |
| |
| //===== ButtonModeHandler ===================================================== |
| |
| ButtonModeHandler::ButtonModeHandler ( |
| SlideSorter& rSlideSorter, |
| SelectionFunction& rSelectionFunction) |
| : ModeHandler(rSlideSorter, rSelectionFunction, true) |
| { |
| } |
| |
| |
| |
| |
| ButtonModeHandler::~ButtonModeHandler (void) |
| { |
| } |
| |
| |
| |
| |
| SelectionFunction::Mode ButtonModeHandler::GetMode (void) const |
| { |
| return SelectionFunction::ButtonMode; |
| } |
| |
| |
| |
| |
| void ButtonModeHandler::Abort (void) |
| { |
| } |
| |
| |
| |
| |
| bool ButtonModeHandler::ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| switch (rDescriptor.mnEventCode) |
| { |
| case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | OVER_BUTTON: |
| case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | OVER_BUTTON: |
| // Remember page and button index. When mouse button is |
| // released over same page and button then invoke action of that |
| // button. |
| mrSlideSorter.GetView().GetButtonBar().ProcessButtonDownEvent( |
| rDescriptor.mpHitDescriptor, |
| rDescriptor.maMouseModelPosition); |
| return true; |
| |
| default: |
| return false; |
| } |
| } |
| |
| |
| |
| |
| bool ButtonModeHandler::ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| switch (rDescriptor.mnEventCode & BUTTON_MASK) |
| { |
| case LEFT_BUTTON: |
| mrSlideSorter.GetView().GetButtonBar().ProcessButtonUpEvent( |
| rDescriptor.mpHitDescriptor, |
| rDescriptor.maMouseModelPosition); |
| mrSelectionFunction.SwitchToNormalMode(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| |
| |
| |
| bool ButtonModeHandler::ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor) |
| { |
| switch (rDescriptor.mnEventCode & (MOUSE_MOTION | BUTTON_MASK)) |
| { |
| case MOUSE_MOTION | LEFT_BUTTON: |
| mrSlideSorter.GetView().GetButtonBar().ProcessMouseMotionEvent( |
| rDescriptor.mpHitDescriptor, |
| rDescriptor.maMouseModelPosition, |
| true); |
| return true; |
| |
| case MOUSE_MOTION: |
| mrSlideSorter.GetView().GetButtonBar().ProcessMouseMotionEvent( |
| rDescriptor.mpHitDescriptor, |
| rDescriptor.maMouseModelPosition, |
| false); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| |
| |
| } } } // end of namespace ::sd::slidesorter::controller |