1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <sal/config.h>
23 #include <controller/SlsSelectionFunction.hxx>
25 #include <SlideSorter.hxx>
26 #include <SlideSorterViewShell.hxx>
27 #include "SlsDragAndDropContext.hxx"
28 #include <controller/SlideSorterController.hxx>
29 #include <controller/SlsPageSelector.hxx>
30 #include <controller/SlsFocusManager.hxx>
31 #include <controller/SlsScrollBarManager.hxx>
32 #include <controller/SlsClipboard.hxx>
33 #include <controller/SlsCurrentSlideManager.hxx>
34 #include <controller/SlsInsertionIndicatorHandler.hxx>
35 #include <controller/SlsSelectionManager.hxx>
36 #include <controller/SlsProperties.hxx>
37 #include <controller/SlsVisibleAreaManager.hxx>
38 #include <model/SlideSorterModel.hxx>
39 #include <model/SlsPageDescriptor.hxx>
40 #include <model/SlsPageEnumerationProvider.hxx>
41 #include <view/SlideSorterView.hxx>
42 #include <view/SlsLayouter.hxx>
43 #include <framework/FrameworkHelper.hxx>
44 #include <osl/diagnose.h>
47 #include <drawdoc.hxx>
49 #include <ViewShell.hxx>
50 #include <FrameView.hxx>
52 #include <o3tl/deleter.hxx>
53 #include <sfx2/dispatch.hxx>
54 #include <vcl/ptrstyle.hxx>
59 const sal_uInt32
SINGLE_CLICK (0x00000001);
60 const sal_uInt32
DOUBLE_CLICK (0x00000002);
61 const sal_uInt32
LEFT_BUTTON (0x00000010);
62 const sal_uInt32
RIGHT_BUTTON (0x00000020);
63 const sal_uInt32
MIDDLE_BUTTON (0x00000040);
64 const sal_uInt32
BUTTON_DOWN (0x00000100);
65 const sal_uInt32
BUTTON_UP (0x00000200);
66 const sal_uInt32
MOUSE_MOTION (0x00000400);
67 const sal_uInt32
MOUSE_DRAG (0x00000800);
68 // The rest leaves the lower 16 bit untouched so that it can be used with
70 const sal_uInt32
OVER_SELECTED_PAGE (0x00010000);
71 const sal_uInt32
OVER_UNSELECTED_PAGE (0x00020000);
72 const sal_uInt32
SHIFT_MODIFIER (0x00200000);
73 const sal_uInt32
CONTROL_MODIFIER (0x00400000);
75 // Some absent events are defined so they can be expressed explicitly.
76 const sal_uInt32
NO_MODIFIER (0x00000000);
77 const sal_uInt32
NOT_OVER_PAGE (0x00000000);
80 const sal_uInt32
MODIFIER_MASK (SHIFT_MODIFIER
| CONTROL_MODIFIER
);
82 } // end of anonymous namespace
84 // Define some macros to make the following switch statement more readable.
85 #define ANY_MODIFIER(code) \
87 case code|SHIFT_MODIFIER: \
88 case code|CONTROL_MODIFIER
90 namespace sd::slidesorter::controller
{
92 //===== SelectionFunction::EventDescriptor ====================================
94 class SelectionFunction::EventDescriptor
97 Point maMousePosition
;
98 Point maMouseModelPosition
;
99 model::SharedPageDescriptor mpHitDescriptor
;
101 sal_uInt32 mnEventCode
;
102 InsertionIndicatorHandler::Mode meDragMode
;
106 sal_uInt32 nEventType
,
107 const MouseEvent
& rEvent
,
108 SlideSorter
const & rSlideSorter
);
110 sal_uInt32 nEventType
,
111 const AcceptDropEvent
& rEvent
,
112 const sal_Int8 nDragAction
,
113 SlideSorter
const & rSlideSorter
);
116 /** Compute a numerical code that describes a mouse event and that can
117 be used for fast look up of the appropriate reaction.
119 sal_uInt32
EncodeMouseEvent (const MouseEvent
& rEvent
) const;
121 /** Compute a numerical code that describes the current state like
122 whether the selection rectangle is visible or whether the page under
123 the mouse or the one that has the focus is selected.
125 sal_uInt32
EncodeState() const;
128 //===== SelectionFunction::ModeHandler ========================================
130 class SelectionFunction::ModeHandler
134 SlideSorter
& rSlideSorter
,
135 SelectionFunction
& rSelectionFunction
,
136 const bool bIsMouseOverIndicatorAllowed
);
137 virtual ~ModeHandler() COVERITY_NOEXCEPT_FALSE
;
139 virtual Mode
GetMode() const = 0;
140 virtual void Abort() = 0;
141 virtual void ProcessEvent (EventDescriptor
& rDescriptor
);
143 /** Set the selection to exactly the specified page and also set it as
146 void SetCurrentPage (const model::SharedPageDescriptor
& rpDescriptor
);
148 /// Deselect all pages.
149 void DeselectAllPages();
150 void SelectOnePage (const model::SharedPageDescriptor
& rpDescriptor
);
152 /** When the view on which this selection function is working is the
153 main view then the view is switched to the regular editing view.
155 void SwitchView (const model::SharedPageDescriptor
& rpDescriptor
);
158 const Point
& rMousePosition
);
160 bool IsMouseOverIndicatorAllowed() const { return mbIsMouseOverIndicatorAllowed
;}
163 SlideSorter
& mrSlideSorter
;
164 SelectionFunction
& mrSelectionFunction
;
166 virtual bool ProcessButtonDownEvent (EventDescriptor
& rDescriptor
);
167 virtual bool ProcessButtonUpEvent (EventDescriptor
& rDescriptor
);
168 virtual bool ProcessMotionEvent (EventDescriptor
& rDescriptor
);
169 virtual bool ProcessDragEvent (EventDescriptor
& rDescriptor
);
170 virtual bool HandleUnprocessedEvent (EventDescriptor
& rDescriptor
);
172 void ReprocessEvent (EventDescriptor
& rDescriptor
);
175 const bool mbIsMouseOverIndicatorAllowed
;
180 /** This is the default handler for processing events. It activates the
181 multi selection or drag-and-drop when the right conditions are met.
183 class NormalModeHandler
: public SelectionFunction::ModeHandler
187 SlideSorter
& rSlideSorter
,
188 SelectionFunction
& rSelectionFunction
);
190 virtual SelectionFunction::Mode
GetMode() const override
;
191 virtual void Abort() override
;
193 void ResetButtonDownLocation();
196 virtual bool ProcessButtonDownEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
197 virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
198 virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
199 virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
202 ::std::optional
<Point
> maButtonDownLocation
;
204 /** Select all pages between and including the selection anchor and the
207 void RangeSelect (const model::SharedPageDescriptor
& rpDescriptor
);
210 /** Handle events during a multi selection, which typically is started by
211 pressing the left mouse button when not over a page.
213 class MultiSelectionModeHandler
: public SelectionFunction::ModeHandler
216 /** Start a rectangle selection at the given position.
218 MultiSelectionModeHandler (
219 SlideSorter
& rSlideSorter
,
220 SelectionFunction
& rSelectionFunction
,
221 const Point
& rMouseModelPosition
,
222 const sal_uInt32 nEventCode
);
224 virtual ~MultiSelectionModeHandler() override
;
226 virtual SelectionFunction::Mode
GetMode() const override
;
227 virtual void Abort() override
;
228 virtual void ProcessEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
230 enum SelectionMode
{ SM_Normal
, SM_Add
, SM_Toggle
};
232 void SetSelectionMode (const SelectionMode eSelectionMode
);
233 void SetSelectionModeFromModifier (const sal_uInt32 nEventCode
);
236 virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
237 virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
238 virtual bool HandleUnprocessedEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
241 SelectionMode meSelectionMode
;
242 Point maSecondCorner
;
243 PointerStyle maSavedPointer
;
244 bool mbAutoScrollInstalled
;
245 sal_Int32 mnAnchorIndex
;
246 sal_Int32 mnSecondIndex
;
248 void UpdateModelPosition (const Point
& rMouseModelPosition
);
249 void UpdateSelection();
251 /** Update the rectangle selection so that the given position becomes
252 the new second point of the selection rectangle.
254 void UpdatePosition (
255 const Point
& rMousePosition
,
256 const bool bAllowAutoScroll
);
258 void UpdateSelectionState (
259 const model::SharedPageDescriptor
& rpDescriptor
,
260 const bool bIsInSelection
) const;
263 /** Handle events during drag-and-drop.
265 class DragAndDropModeHandler
: public SelectionFunction::ModeHandler
268 DragAndDropModeHandler (
269 SlideSorter
& rSlideSorter
,
270 SelectionFunction
& rSelectionFunction
,
271 const Point
& rMousePosition
,
272 vcl::Window
* pWindow
);
273 virtual ~DragAndDropModeHandler() override
;
275 virtual SelectionFunction::Mode
GetMode() const override
;
276 virtual void Abort() override
;
279 virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
280 virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
283 std::unique_ptr
<DragAndDropContext
, o3tl::default_delete
<DragAndDropContext
>> mpDragAndDropContext
;
288 //===== SelectionFunction =====================================================
291 SelectionFunction::SelectionFunction (
292 SlideSorter
& rSlideSorter
,
293 SfxRequest
& rRequest
)
295 rSlideSorter
.GetViewShell(),
296 rSlideSorter
.GetContentWindow(),
297 &rSlideSorter
.GetView(),
298 rSlideSorter
.GetModel().GetDocument(),
300 mrSlideSorter(rSlideSorter
),
301 mrController(mrSlideSorter
.GetController()),
302 mnShiftKeySelectionAnchor(-1),
303 mpModeHandler(std::make_shared
<NormalModeHandler
>(rSlideSorter
, *this))
307 SelectionFunction::~SelectionFunction()
309 mpModeHandler
.reset();
312 rtl::Reference
<FuPoor
> SelectionFunction::Create(
313 SlideSorter
& rSlideSorter
,
314 SfxRequest
& rRequest
)
316 rtl::Reference
<FuPoor
> xFunc( new SelectionFunction( rSlideSorter
, rRequest
) );
320 bool SelectionFunction::MouseButtonDown (const MouseEvent
& rEvent
)
322 // remember button state for creation of own MouseEvents
323 SetMouseButtonCode (rEvent
.GetButtons());
324 aMDPos
= rEvent
.GetPosPixel();
326 // mpWindow->CaptureMouse();
328 ProcessMouseEvent(BUTTON_DOWN
, rEvent
);
333 bool SelectionFunction::MouseMove (const MouseEvent
& rEvent
)
335 ProcessMouseEvent(MOUSE_MOTION
, rEvent
);
339 bool SelectionFunction::MouseButtonUp (const MouseEvent
& rEvent
)
341 mrController
.GetScrollBarManager().StopAutoScroll ();
343 ProcessMouseEvent(BUTTON_UP
, rEvent
);
348 void SelectionFunction::NotifyDragFinished()
350 SwitchToNormalMode();
353 bool SelectionFunction::KeyInput (const KeyEvent
& rEvent
)
355 view::SlideSorterView::DrawLock
aDrawLock (mrSlideSorter
);
356 PageSelector::BroadcastLock
aBroadcastLock (mrSlideSorter
);
357 PageSelector::UpdateLock
aLock (mrSlideSorter
);
358 FocusManager
& rFocusManager (mrController
.GetFocusManager());
359 bool bResult
= false;
361 const vcl::KeyCode
& rCode (rEvent
.GetKeyCode());
362 switch (rCode
.GetCode())
366 model::SharedPageDescriptor
pDescriptor (rFocusManager
.GetFocusedPageDescriptor());
367 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
368 if (rFocusManager
.HasFocus() && pDescriptor
&& pViewShell
!=nullptr)
370 // The Return key triggers different functions depending on
371 // whether the slide sorter is the main view or displayed in
373 if (pViewShell
->IsMainViewShell())
375 mpModeHandler
->SetCurrentPage(pDescriptor
);
376 mpModeHandler
->SwitchView(pDescriptor
);
378 else if (pViewShell
->GetDispatcher() != nullptr)
380 pViewShell
->GetDispatcher()->Execute(
382 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
390 if ( ! rFocusManager
.IsFocusShowing())
392 rFocusManager
.ShowFocus();
398 // When there is an active multiselection or drag-and-drop
399 // operation then stop that.
400 mpModeHandler
->Abort();
401 SwitchToNormalMode();
407 // Toggle the selection state.
408 model::SharedPageDescriptor
pDescriptor (rFocusManager
.GetFocusedPageDescriptor());
409 if (pDescriptor
&& rCode
.IsMod1())
411 if (pDescriptor
->HasState(model::PageDescriptor::ST_Selected
))
412 mrController
.GetPageSelector().DeselectPage(pDescriptor
, false);
414 mrController
.GetPageSelector().SelectPage(pDescriptor
);
420 // Move the focus indicator left.
422 MoveFocus(FocusManager::FocusMoveDirection::Left
, rCode
.IsShift(), rCode
.IsMod1());
426 // Move the focus indicator right.
428 MoveFocus(FocusManager::FocusMoveDirection::Right
, rCode
.IsShift(), rCode
.IsMod1());
432 // Move the focus indicator up.
434 MoveFocus(FocusManager::FocusMoveDirection::Up
, rCode
.IsShift(), rCode
.IsMod1());
438 // Move the focus indicator down.
440 MoveFocus(FocusManager::FocusMoveDirection::Down
, rCode
.IsShift(), rCode
.IsMod1());
444 // Go to previous page. No wrap around.
450 // Go to next page. No wrap around...
462 GotoPage(mrSlideSorter
.GetModel().GetPageCount()-1);
469 if (mrSlideSorter
.GetProperties()->IsUIReadOnly())
472 mrController
.GetSelectionManager()->DeleteSelectedPages(rCode
.GetCode()==KEY_DELETE
);
474 mnShiftKeySelectionAnchor
= -1;
482 mpModeHandler
->SelectOnePage(
483 mrSlideSorter
.GetController().GetFocusManager().GetFocusedPageDescriptor());
492 bResult
= FuPoor::KeyInput(rEvent
);
497 void SelectionFunction::MoveFocus (
498 const FocusManager::FocusMoveDirection eDirection
,
499 const bool bIsShiftDown
,
500 const bool bIsControlDown
)
502 // Remember the anchor of shift key multi selection.
505 if (mnShiftKeySelectionAnchor
<0)
507 model::SharedPageDescriptor
pFocusedDescriptor (
508 mrController
.GetFocusManager().GetFocusedPageDescriptor());
509 mnShiftKeySelectionAnchor
= pFocusedDescriptor
->GetPageIndex();
512 else if ( ! bIsControlDown
)
513 ResetShiftKeySelectionAnchor();
515 mrController
.GetFocusManager().MoveFocus(eDirection
);
517 PageSelector
& rSelector (mrController
.GetPageSelector());
518 model::SharedPageDescriptor
pFocusedDescriptor (
519 mrController
.GetFocusManager().GetFocusedPageDescriptor());
522 // When shift is pressed then select all pages in the range between
523 // the currently and the previously focused pages, including them.
524 if (pFocusedDescriptor
)
526 sal_Int32
nPageRangeEnd (pFocusedDescriptor
->GetPageIndex());
527 model::PageEnumeration
aPages (
528 model::PageEnumerationProvider::CreateAllPagesEnumeration(
529 mrSlideSorter
.GetModel()));
530 while (aPages
.HasMoreElements())
532 model::SharedPageDescriptor
pDescriptor (aPages
.GetNextElement());
535 const sal_Int32
nPageIndex(pDescriptor
->GetPageIndex());
536 if ((nPageIndex
>=mnShiftKeySelectionAnchor
&& nPageIndex
<=nPageRangeEnd
)
537 || (nPageIndex
<=mnShiftKeySelectionAnchor
&& nPageIndex
>=nPageRangeEnd
))
539 rSelector
.SelectPage(pDescriptor
);
543 rSelector
.DeselectPage(pDescriptor
);
549 else if (bIsControlDown
)
551 // When control is pressed then do not alter the selection or the
552 // current page, just move the focus.
556 // Without shift just select the focused page.
557 mpModeHandler
->SelectOnePage(pFocusedDescriptor
);
561 void SelectionFunction::DoCut()
563 if ( ! mrSlideSorter
.GetProperties()->IsUIReadOnly())
565 mrController
.GetClipboard().DoCut();
569 void SelectionFunction::DoCopy()
571 mrController
.GetClipboard().DoCopy();
574 void SelectionFunction::DoPaste()
576 if ( ! mrSlideSorter
.GetProperties()->IsUIReadOnly())
578 mrController
.GetClipboard().DoPaste();
582 bool SelectionFunction::cancel()
584 mrController
.GetFocusManager().ToggleFocus();
588 void SelectionFunction::GotoNextPage (int nOffset
)
590 model::SharedPageDescriptor pDescriptor
591 = mrController
.GetCurrentSlideManager()->GetCurrentSlide();
594 SdPage
* pPage
= pDescriptor
->GetPage();
595 OSL_ASSERT(pPage
!=nullptr);
596 sal_Int32 nIndex
= (pPage
->GetPageNum()-1) / 2;
597 GotoPage(nIndex
+ nOffset
);
599 ResetShiftKeySelectionAnchor();
602 void SelectionFunction::GotoPage (int nIndex
)
604 sal_uInt16 nPageCount
= static_cast<sal_uInt16
>(mrSlideSorter
.GetModel().GetPageCount());
606 if (nIndex
>= nPageCount
)
607 nIndex
= nPageCount
- 1;
611 mrController
.GetFocusManager().SetFocusedPage(nIndex
);
612 model::SharedPageDescriptor
pNextPageDescriptor (
613 mrSlideSorter
.GetModel().GetPageDescriptor (nIndex
));
614 if (pNextPageDescriptor
)
615 mpModeHandler
->SetCurrentPage(pNextPageDescriptor
);
618 OSL_ASSERT(pNextPageDescriptor
);
620 ResetShiftKeySelectionAnchor();
623 void SelectionFunction::ProcessMouseEvent (sal_uInt32 nEventType
, const MouseEvent
& rEvent
)
625 // #95491# remember button state for creation of own MouseEvents
626 SetMouseButtonCode (rEvent
.GetButtons());
628 EventDescriptor
aEventDescriptor (nEventType
, rEvent
, mrSlideSorter
);
629 ProcessEvent(aEventDescriptor
);
632 void SelectionFunction::MouseDragged (
633 const AcceptDropEvent
& rEvent
,
634 const sal_Int8 nDragAction
)
636 EventDescriptor
aEventDescriptor (MOUSE_DRAG
, rEvent
, nDragAction
, mrSlideSorter
);
637 ProcessEvent(aEventDescriptor
);
640 void SelectionFunction::ProcessEvent (EventDescriptor
& rDescriptor
)
642 // The call to ProcessEvent may switch to another mode handler.
643 // Prevent the untimely destruction of the called handler by acquiring a
644 // temporary reference here.
645 std::shared_ptr
<ModeHandler
> pModeHandler (mpModeHandler
);
646 pModeHandler
->ProcessEvent(rDescriptor
);
650 const sal_uInt32 nEventCode
,
651 const sal_uInt32 nPositivePattern
)
653 return (nEventCode
& nPositivePattern
)==nPositivePattern
;
656 void SelectionFunction::SwitchToNormalMode()
658 if (mpModeHandler
->GetMode() != NormalMode
)
659 SwitchMode(std::make_shared
<NormalModeHandler
>(mrSlideSorter
, *this));
662 void SelectionFunction::SwitchToDragAndDropMode (const Point
& rMousePosition
)
664 if (mpModeHandler
->GetMode() == DragAndDropMode
)
667 SwitchMode(std::make_shared
<DragAndDropModeHandler
>(mrSlideSorter
, *this, rMousePosition
, mpWindow
));
670 void SelectionFunction::SwitchToMultiSelectionMode (
671 const Point
& rMousePosition
,
672 const sal_uInt32 nEventCode
)
674 if (mpModeHandler
->GetMode() != MultiSelectionMode
)
675 SwitchMode(std::make_shared
<MultiSelectionModeHandler
>(mrSlideSorter
, *this, rMousePosition
, nEventCode
));
678 void SelectionFunction::SwitchMode (const std::shared_ptr
<ModeHandler
>& rpHandler
)
680 // Not all modes allow mouse over indicator.
681 if (mpModeHandler
->IsMouseOverIndicatorAllowed() != rpHandler
->IsMouseOverIndicatorAllowed())
683 if ( ! rpHandler
->IsMouseOverIndicatorAllowed())
685 mrSlideSorter
.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
688 mrSlideSorter
.GetView().UpdatePageUnderMouse();
691 mpModeHandler
= rpHandler
;
694 void SelectionFunction::ResetShiftKeySelectionAnchor()
696 mnShiftKeySelectionAnchor
= -1;
699 void SelectionFunction::ResetMouseAnchor()
701 if (mpModeHandler
&& mpModeHandler
->GetMode() == NormalMode
)
703 std::shared_ptr
<NormalModeHandler
> pHandler (
704 std::dynamic_pointer_cast
<NormalModeHandler
>(mpModeHandler
));
706 pHandler
->ResetButtonDownLocation();
710 //===== EventDescriptor =======================================================
712 SelectionFunction::EventDescriptor::EventDescriptor (
713 const sal_uInt32 nEventType
,
714 const MouseEvent
& rEvent
,
715 SlideSorter
const & rSlideSorter
)
716 : maMousePosition(rEvent
.GetPosPixel()),
718 mnEventCode(nEventType
),
719 meDragMode(InsertionIndicatorHandler::MoveMode
),
722 maMouseModelPosition
= rSlideSorter
.GetContentWindow()->PixelToLogic(maMousePosition
);
723 mpHitDescriptor
= rSlideSorter
.GetController().GetPageAt(maMousePosition
);
726 mpHitPage
= mpHitDescriptor
->GetPage();
729 mnEventCode
|= EncodeMouseEvent(rEvent
);
730 mnEventCode
|= EncodeState();
732 // Detect the mouse leaving the window. When not button is pressed then
733 // we can call IsLeaveWindow at the event. Otherwise we have to make an
735 mbIsLeaving
= rEvent
.IsLeaveWindow()
736 || ! ::tools::Rectangle(Point(0,0),
737 rSlideSorter
.GetContentWindow()->GetOutputSizePixel()).Contains(maMousePosition
);
740 SelectionFunction::EventDescriptor::EventDescriptor (
741 const sal_uInt32 nEventType
,
742 const AcceptDropEvent
& rEvent
,
743 const sal_Int8 nDragAction
,
744 SlideSorter
const & rSlideSorter
)
745 : maMousePosition(rEvent
.maPosPixel
),
747 mnEventCode(nEventType
),
748 meDragMode(InsertionIndicatorHandler::GetModeFromDndAction(nDragAction
)),
751 maMouseModelPosition
= rSlideSorter
.GetContentWindow()->PixelToLogic(maMousePosition
);
752 mpHitDescriptor
= rSlideSorter
.GetController().GetPageAt(maMousePosition
);
755 mpHitPage
= mpHitDescriptor
->GetPage();
758 mnEventCode
|= EncodeState();
760 // Detect the mouse leaving the window. When not button is pressed then
761 // we can call IsLeaveWindow at the event. Otherwise we have to make an
763 mbIsLeaving
= rEvent
.mbLeaving
764 || ! ::tools::Rectangle(Point(0,0),
765 rSlideSorter
.GetContentWindow()->GetOutputSizePixel()).Contains(maMousePosition
);
768 sal_uInt32
SelectionFunction::EventDescriptor::EncodeMouseEvent (
769 const MouseEvent
& rEvent
) const
771 // Initialize with the type of mouse event.
772 sal_uInt32
nEventCode (mnEventCode
& (BUTTON_DOWN
| BUTTON_UP
| MOUSE_MOTION
));
774 // Detect the affected button.
775 switch (rEvent
.GetButtons())
777 case MOUSE_LEFT
: nEventCode
|= LEFT_BUTTON
; break;
778 case MOUSE_RIGHT
: nEventCode
|= RIGHT_BUTTON
; break;
779 case MOUSE_MIDDLE
: nEventCode
|= MIDDLE_BUTTON
; break;
782 // Detect the number of clicks.
783 switch (rEvent
.GetClicks())
785 case 1: nEventCode
|= SINGLE_CLICK
; break;
786 case 2: nEventCode
|= DOUBLE_CLICK
; break;
789 // Detect pressed modifier keys.
790 if (rEvent
.IsShift())
791 nEventCode
|= SHIFT_MODIFIER
;
793 nEventCode
|= CONTROL_MODIFIER
;
798 sal_uInt32
SelectionFunction::EventDescriptor::EncodeState() const
800 sal_uInt32
nEventCode (0);
802 // Detect whether the event has happened over a page object.
803 if (mpHitPage
!=nullptr && mpHitDescriptor
)
805 if (mpHitDescriptor
->HasState(model::PageDescriptor::ST_Selected
))
806 nEventCode
|= OVER_SELECTED_PAGE
;
808 nEventCode
|= OVER_UNSELECTED_PAGE
;
814 //===== SelectionFunction::ModeHandler ========================================
816 SelectionFunction::ModeHandler::ModeHandler (
817 SlideSorter
& rSlideSorter
,
818 SelectionFunction
& rSelectionFunction
,
819 const bool bIsMouseOverIndicatorAllowed
)
820 : mrSlideSorter(rSlideSorter
),
821 mrSelectionFunction(rSelectionFunction
),
822 mbIsMouseOverIndicatorAllowed(bIsMouseOverIndicatorAllowed
)
826 SelectionFunction::ModeHandler::~ModeHandler() COVERITY_NOEXCEPT_FALSE
830 void SelectionFunction::ModeHandler::ReprocessEvent (EventDescriptor
& rDescriptor
)
832 mrSelectionFunction
.ProcessEvent(rDescriptor
);
835 void SelectionFunction::ModeHandler::ProcessEvent (
836 SelectionFunction::EventDescriptor
& rDescriptor
)
838 PageSelector::BroadcastLock
aBroadcastLock (mrSlideSorter
);
839 PageSelector::UpdateLock
aUpdateLock (mrSlideSorter
);
841 bool bIsProcessed (false);
842 switch (rDescriptor
.mnEventCode
& (BUTTON_DOWN
| BUTTON_UP
| MOUSE_MOTION
| MOUSE_DRAG
))
845 bIsProcessed
= ProcessButtonDownEvent(rDescriptor
);
849 bIsProcessed
= ProcessButtonUpEvent(rDescriptor
);
853 bIsProcessed
= ProcessMotionEvent(rDescriptor
);
857 bIsProcessed
= ProcessDragEvent(rDescriptor
);
862 HandleUnprocessedEvent(rDescriptor
);
865 bool SelectionFunction::ModeHandler::ProcessButtonDownEvent (EventDescriptor
&)
870 bool SelectionFunction::ModeHandler::ProcessButtonUpEvent (EventDescriptor
&)
872 mrSelectionFunction
.SwitchToNormalMode();
876 bool SelectionFunction::ModeHandler::ProcessMotionEvent (EventDescriptor
& rDescriptor
)
878 if (mbIsMouseOverIndicatorAllowed
)
879 mrSlideSorter
.GetView().UpdatePageUnderMouse(rDescriptor
.maMousePosition
);
881 if (rDescriptor
.mbIsLeaving
)
883 mrSelectionFunction
.SwitchToNormalMode();
884 mrSlideSorter
.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
892 bool SelectionFunction::ModeHandler::ProcessDragEvent (EventDescriptor
&)
897 bool SelectionFunction::ModeHandler::HandleUnprocessedEvent (EventDescriptor
&)
902 void SelectionFunction::ModeHandler::SetCurrentPage (
903 const model::SharedPageDescriptor
& rpDescriptor
)
905 SelectOnePage(rpDescriptor
);
906 mrSlideSorter
.GetController().GetCurrentSlideManager()->SwitchCurrentSlide(rpDescriptor
);
909 void SelectionFunction::ModeHandler::DeselectAllPages()
911 mrSlideSorter
.GetController().GetPageSelector().DeselectAllPages();
912 mrSelectionFunction
.ResetShiftKeySelectionAnchor();
915 void SelectionFunction::ModeHandler::SelectOnePage (
916 const model::SharedPageDescriptor
& rpDescriptor
)
919 mrSlideSorter
.GetController().GetPageSelector().SelectPage(rpDescriptor
);
922 void SelectionFunction::ModeHandler::SwitchView (const model::SharedPageDescriptor
& rpDescriptor
)
924 // Switch to the draw view. This is done only when the current
925 // view is the main view.
926 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
927 if (pViewShell
==nullptr || !pViewShell
->IsMainViewShell())
930 if (rpDescriptor
&& rpDescriptor
->GetPage()!=nullptr)
932 mrSlideSorter
.GetModel().GetDocument()->SetSelected(rpDescriptor
->GetPage(), true);
933 pViewShell
->GetFrameView()->SetSelectedPage(
934 (rpDescriptor
->GetPage()->GetPageNum()-1)/2);
936 if (mrSlideSorter
.GetViewShellBase() != nullptr)
937 framework::FrameworkHelper::Instance(*mrSlideSorter
.GetViewShellBase())->RequestView(
938 framework::FrameworkHelper::msImpressViewURL
,
939 framework::FrameworkHelper::msCenterPaneURL
);
942 void SelectionFunction::ModeHandler::StartDrag (
943 const Point
& rMousePosition
)
945 // Do not start a drag-and-drop operation when one is already active.
946 // (when dragging pages from one document into another, pressing a
947 // modifier key can trigger a MouseMotion event in the originating
948 // window (focus still in there). Together with the mouse button pressed
949 // (drag-and-drop is active) this triggers the start of drag-and-drop.)
950 if (SD_MOD()->pTransferDrag
!= nullptr)
953 if ( ! mrSlideSorter
.GetProperties()->IsUIReadOnly())
955 mrSelectionFunction
.SwitchToDragAndDropMode(rMousePosition
);
959 //===== NormalModeHandler =====================================================
961 NormalModeHandler::NormalModeHandler (
962 SlideSorter
& rSlideSorter
,
963 SelectionFunction
& rSelectionFunction
)
964 : ModeHandler(rSlideSorter
, rSelectionFunction
, true)
968 SelectionFunction::Mode
NormalModeHandler::GetMode() const
970 return SelectionFunction::NormalMode
;
973 void NormalModeHandler::Abort()
977 bool NormalModeHandler::ProcessButtonDownEvent (
978 SelectionFunction::EventDescriptor
& rDescriptor
)
980 // Remember the location where the left button is pressed. With
981 // that we can filter away motion events that are caused by key
982 // presses. We also can tune the minimal motion distance that
983 // triggers a drag-and-drop operation.
984 if ((rDescriptor
.mnEventCode
& BUTTON_DOWN
) != 0)
985 maButtonDownLocation
= rDescriptor
.maMousePosition
;
987 switch (rDescriptor
.mnEventCode
)
989 case BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
:
990 SetCurrentPage(rDescriptor
.mpHitDescriptor
);
993 case BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
:
996 case BUTTON_DOWN
| LEFT_BUTTON
| DOUBLE_CLICK
| OVER_SELECTED_PAGE
:
997 case BUTTON_DOWN
| LEFT_BUTTON
| DOUBLE_CLICK
| OVER_UNSELECTED_PAGE
:
998 // A double click always shows the selected slide in the center
999 // pane in an edit view.
1000 SetCurrentPage(rDescriptor
.mpHitDescriptor
);
1001 SwitchView(rDescriptor
.mpHitDescriptor
);
1004 case BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
| SHIFT_MODIFIER
:
1005 case BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
| SHIFT_MODIFIER
:
1006 // Range selection with the shift modifier.
1007 RangeSelect(rDescriptor
.mpHitDescriptor
);
1010 // Right button for context menu.
1011 case BUTTON_DOWN
| RIGHT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
:
1012 // Single right click and shift+F10 select as preparation to
1013 // show the context menu. Change the selection only when the
1014 // page under the mouse is not selected. In this case the
1015 // selection is set to this single page. Otherwise the
1016 // selection is not modified.
1017 SetCurrentPage(rDescriptor
.mpHitDescriptor
);
1020 case BUTTON_DOWN
| RIGHT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
:
1021 // Do not change the selection. Just adjust the insertion indicator.
1024 case BUTTON_DOWN
| RIGHT_BUTTON
| SINGLE_CLICK
| NOT_OVER_PAGE
:
1025 // Remember the current selection so that when a multi selection
1026 // is started, we can restore the previous selection.
1027 mrSlideSorter
.GetModel().SaveCurrentSelection();
1031 case ANY_MODIFIER(BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| NOT_OVER_PAGE
):
1032 // Remember the current selection so that when a multi selection
1033 // is started, we can restore the previous selection.
1034 mrSlideSorter
.GetModel().SaveCurrentSelection();
1038 case BUTTON_DOWN
| LEFT_BUTTON
| DOUBLE_CLICK
| NOT_OVER_PAGE
:
1040 // Insert a new slide:
1041 // First of all we need to set the insertion indicator which sets the
1042 // position where the new slide will be inserted.
1043 std::shared_ptr
<InsertionIndicatorHandler
> pInsertionIndicatorHandler
1044 = mrSlideSorter
.GetController().GetInsertionIndicatorHandler();
1046 pInsertionIndicatorHandler
->Start(false);
1047 pInsertionIndicatorHandler
->UpdatePosition(
1048 rDescriptor
.maMousePosition
,
1049 InsertionIndicatorHandler::MoveMode
);
1051 mrSlideSorter
.GetController().GetSelectionManager()->SetInsertionPosition(
1052 pInsertionIndicatorHandler
->GetInsertionPageIndex());
1054 mrSlideSorter
.GetViewShell()->GetDispatcher()->Execute(
1056 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
1058 pInsertionIndicatorHandler
->End(Animator::AM_Immediate
);
1069 bool NormalModeHandler::ProcessButtonUpEvent (
1070 SelectionFunction::EventDescriptor
& rDescriptor
)
1072 bool bIsProcessed (true);
1073 switch (rDescriptor
.mnEventCode
)
1075 case BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
:
1076 SetCurrentPage(rDescriptor
.mpHitDescriptor
);
1079 // Multi selection with the control modifier.
1080 case BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
| CONTROL_MODIFIER
:
1081 mrSlideSorter
.GetController().GetPageSelector().DeselectPage(
1082 rDescriptor
.mpHitDescriptor
);
1085 case BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
| CONTROL_MODIFIER
:
1086 mrSlideSorter
.GetController().GetPageSelector().SelectPage(
1087 rDescriptor
.mpHitDescriptor
);
1088 mrSlideSorter
.GetView().SetPageUnderMouse(rDescriptor
.mpHitDescriptor
);
1090 case BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
| NOT_OVER_PAGE
:
1094 bIsProcessed
= false;
1097 mrSelectionFunction
.SwitchToNormalMode();
1098 return bIsProcessed
;
1101 bool NormalModeHandler::ProcessMotionEvent (
1102 SelectionFunction::EventDescriptor
& rDescriptor
)
1104 if (ModeHandler::ProcessMotionEvent(rDescriptor
))
1107 bool bIsProcessed (true);
1108 switch (rDescriptor
.mnEventCode
)
1110 // A mouse motion without visible substitution starts that.
1111 case ANY_MODIFIER(MOUSE_MOTION
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
):
1112 case ANY_MODIFIER(MOUSE_MOTION
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
):
1114 if (maButtonDownLocation
)
1116 const sal_Int32
nDistance(std::max(
1117 std::abs(maButtonDownLocation
->X() - rDescriptor
.maMousePosition
.X()),
1118 std::abs(maButtonDownLocation
->Y() - rDescriptor
.maMousePosition
.Y())));
1120 StartDrag(rDescriptor
.maMousePosition
);
1125 // A mouse motion not over a page starts a rectangle selection.
1126 case ANY_MODIFIER(MOUSE_MOTION
| LEFT_BUTTON
| SINGLE_CLICK
| NOT_OVER_PAGE
):
1127 mrSelectionFunction
.SwitchToMultiSelectionMode(
1128 rDescriptor
.maMouseModelPosition
,
1129 rDescriptor
.mnEventCode
);
1133 bIsProcessed
= false;
1136 return bIsProcessed
;
1139 bool NormalModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor
& rDescriptor
)
1141 mrSelectionFunction
.SwitchToDragAndDropMode(rDescriptor
.maMousePosition
);
1142 ReprocessEvent(rDescriptor
);
1146 void NormalModeHandler::RangeSelect (const model::SharedPageDescriptor
& rpDescriptor
)
1148 PageSelector::UpdateLock
aLock (mrSlideSorter
);
1149 PageSelector
& rSelector (mrSlideSorter
.GetController().GetPageSelector());
1151 model::SharedPageDescriptor
pAnchor (rSelector
.GetSelectionAnchor());
1157 // Select all pages between the anchor and the given one, including
1159 const sal_uInt16
nAnchorIndex ((pAnchor
->GetPage()->GetPageNum()-1) / 2);
1160 const sal_uInt16
nOtherIndex ((rpDescriptor
->GetPage()->GetPageNum()-1) / 2);
1162 // Iterate over all pages in the range. Start with the anchor
1163 // page. This way the PageSelector will recognize it again as
1164 // anchor (the first selected page after a DeselectAllPages()
1165 // becomes the anchor.)
1166 const sal_uInt16
nStep ((nAnchorIndex
< nOtherIndex
) ? +1 : -1);
1167 sal_uInt16
nIndex (nAnchorIndex
);
1170 rSelector
.SelectPage(nIndex
);
1171 if (nIndex
== nOtherIndex
)
1173 nIndex
= nIndex
+ nStep
;
1177 void NormalModeHandler::ResetButtonDownLocation()
1179 maButtonDownLocation
= ::std::optional
<Point
>();
1182 //===== MultiSelectionModeHandler =============================================
1184 MultiSelectionModeHandler::MultiSelectionModeHandler (
1185 SlideSorter
& rSlideSorter
,
1186 SelectionFunction
& rSelectionFunction
,
1187 const Point
& rMouseModelPosition
,
1188 const sal_uInt32 nEventCode
)
1189 : ModeHandler(rSlideSorter
, rSelectionFunction
, false),
1190 meSelectionMode(SM_Normal
),
1191 maSecondCorner(rMouseModelPosition
),
1192 maSavedPointer(mrSlideSorter
.GetContentWindow()->GetPointer()),
1193 mbAutoScrollInstalled(false),
1198 mrSlideSorter
.GetContentWindow()->SetPointer(PointerStyle::Text
);
1199 SetSelectionModeFromModifier(nEventCode
);
1202 MultiSelectionModeHandler::~MultiSelectionModeHandler()
1204 if (mbAutoScrollInstalled
)
1206 //a call to this handler's MultiSelectionModeHandler::UpdatePosition
1207 //may be still waiting to be called back
1208 mrSlideSorter
.GetController().GetScrollBarManager().clearAutoScrollFunctor();
1210 mrSlideSorter
.GetContentWindow()->SetPointer(maSavedPointer
);
1213 SelectionFunction::Mode
MultiSelectionModeHandler::GetMode() const
1215 return SelectionFunction::MultiSelectionMode
;
1218 void MultiSelectionModeHandler::Abort()
1220 mrSlideSorter
.GetView().RequestRepaint(mrSlideSorter
.GetModel().RestoreSelection());
1223 void MultiSelectionModeHandler::ProcessEvent (
1224 SelectionFunction::EventDescriptor
& rDescriptor
)
1226 // During a multi selection we do not want sudden jumps of the
1227 // visible area caused by moving newly selected pages into view.
1228 // Therefore disable that temporarily. The disabled object is
1229 // released at the end of the event processing, after the focus and
1230 // current slide have been updated.
1231 VisibleAreaManager::TemporaryDisabler
aDisabler (mrSlideSorter
);
1233 ModeHandler::ProcessEvent(rDescriptor
);
1236 bool MultiSelectionModeHandler::ProcessButtonUpEvent (
1237 SelectionFunction::EventDescriptor
& rDescriptor
)
1239 if (mbAutoScrollInstalled
)
1241 //a call to this handler's MultiSelectionModeHandler::UpdatePosition
1242 //may be still waiting to be called back
1243 mrSlideSorter
.GetController().GetScrollBarManager().clearAutoScrollFunctor();
1244 mbAutoScrollInstalled
= false;
1247 if (Match(rDescriptor
.mnEventCode
, BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
))
1249 mrSelectionFunction
.SwitchToNormalMode();
1256 bool MultiSelectionModeHandler::ProcessMotionEvent (
1257 SelectionFunction::EventDescriptor
& rDescriptor
)
1259 // The selection rectangle is visible. Handle events accordingly.
1260 if (Match(rDescriptor
.mnEventCode
, MOUSE_MOTION
| LEFT_BUTTON
| SINGLE_CLICK
))
1262 SetSelectionModeFromModifier(rDescriptor
.mnEventCode
);
1263 UpdatePosition(rDescriptor
.maMousePosition
, true);
1270 bool MultiSelectionModeHandler::HandleUnprocessedEvent (
1271 SelectionFunction::EventDescriptor
& rDescriptor
)
1273 if ( ! ModeHandler::HandleUnprocessedEvent(rDescriptor
))
1275 // If the event has not been processed then stop multi selection.
1276 mrSelectionFunction
.SwitchToNormalMode();
1277 ReprocessEvent(rDescriptor
);
1282 void MultiSelectionModeHandler::UpdatePosition (
1283 const Point
& rMousePosition
,
1284 const bool bAllowAutoScroll
)
1286 VisibleAreaManager::TemporaryDisabler
aDisabler (mrSlideSorter
);
1288 // Convert window coordinates into model coordinates (we need the
1289 // window coordinates for auto-scrolling because that remains
1290 // constant while scrolling.)
1291 sd::Window
*pWindow (mrSlideSorter
.GetContentWindow().get());
1292 const Point
aMouseModelPosition (pWindow
->PixelToLogic(rMousePosition
));
1294 bool bDoAutoScroll
= bAllowAutoScroll
&& mrSlideSorter
.GetController().GetScrollBarManager().AutoScroll(
1296 [this, &rMousePosition
] () { return this->UpdatePosition(rMousePosition
, false); });
1299 UpdateModelPosition(aMouseModelPosition
);
1301 mbAutoScrollInstalled
|= bDoAutoScroll
;
1304 void MultiSelectionModeHandler::SetSelectionModeFromModifier (
1305 const sal_uInt32 nEventCode
)
1307 switch (nEventCode
& MODIFIER_MASK
)
1310 SetSelectionMode(SM_Normal
);
1313 case SHIFT_MODIFIER
:
1314 SetSelectionMode(SM_Add
);
1317 case CONTROL_MODIFIER
:
1318 SetSelectionMode(SM_Toggle
);
1323 void MultiSelectionModeHandler::SetSelectionMode (const SelectionMode eSelectionMode
)
1325 if (meSelectionMode
!= eSelectionMode
)
1327 meSelectionMode
= eSelectionMode
;
1332 void MultiSelectionModeHandler::UpdateSelectionState (
1333 const model::SharedPageDescriptor
& rpDescriptor
,
1334 const bool bIsInSelection
) const
1336 // Determine whether the page was selected before the rectangle
1337 // selection was started.
1338 const bool bWasSelected (rpDescriptor
->HasState(model::PageDescriptor::ST_WasSelected
));
1340 // Combine the two selection states depending on the selection mode.
1341 bool bSelect (false);
1342 switch(meSelectionMode
)
1345 bSelect
= bIsInSelection
;
1349 bSelect
= bIsInSelection
|| bWasSelected
;
1354 bSelect
= !bWasSelected
;
1356 bSelect
= bWasSelected
;
1360 // Set the new selection state.
1362 mrSlideSorter
.GetController().GetPageSelector().SelectPage(rpDescriptor
);
1364 mrSlideSorter
.GetController().GetPageSelector().DeselectPage(rpDescriptor
);
1367 void MultiSelectionModeHandler::UpdateModelPosition (const Point
& rMouseModelPosition
)
1369 maSecondCorner
= rMouseModelPosition
;
1373 void MultiSelectionModeHandler::UpdateSelection()
1375 view::SlideSorterView::DrawLock
aLock (mrSlideSorter
);
1377 model::SlideSorterModel
& rModel (mrSlideSorter
.GetModel());
1378 const sal_Int32
nPageCount (rModel
.GetPageCount());
1380 const sal_Int32
nIndexUnderMouse (
1381 mrSlideSorter
.GetView().GetLayouter().GetIndexAtPoint (
1385 if (nIndexUnderMouse
< 0 || nIndexUnderMouse
>= nPageCount
)
1388 if (mnAnchorIndex
< 0)
1389 mnAnchorIndex
= nIndexUnderMouse
;
1390 mnSecondIndex
= nIndexUnderMouse
;
1392 Range
aRange (mnAnchorIndex
, mnSecondIndex
);
1395 for (sal_Int32 nIndex
=0; nIndex
<nPageCount
; ++nIndex
)
1397 UpdateSelectionState(rModel
.GetPageDescriptor(nIndex
), aRange
.Contains(nIndex
));
1401 //===== DragAndDropModeHandler ================================================
1403 DragAndDropModeHandler::DragAndDropModeHandler (
1404 SlideSorter
& rSlideSorter
,
1405 SelectionFunction
& rSelectionFunction
,
1406 const Point
& rMousePosition
,
1407 vcl::Window
* pWindow
)
1408 : ModeHandler(rSlideSorter
, rSelectionFunction
, false)
1410 SdTransferable
* pDragTransferable
= SD_MOD()->pTransferDrag
;
1411 if (pDragTransferable
==nullptr && mrSlideSorter
.GetViewShell() != nullptr)
1413 SlideSorterViewShell
* pSlideSorterViewShell
1414 = dynamic_cast<SlideSorterViewShell
*>(mrSlideSorter
.GetViewShell());
1415 if (pSlideSorterViewShell
!= nullptr)
1416 pSlideSorterViewShell
->StartDrag(rMousePosition
, pWindow
);
1417 pDragTransferable
= SD_MOD()->pTransferDrag
;
1420 mpDragAndDropContext
.reset(new DragAndDropContext(mrSlideSorter
));
1421 mrSlideSorter
.GetController().GetInsertionIndicatorHandler()->Start(
1422 pDragTransferable
!= nullptr
1423 && pDragTransferable
->GetView()==&mrSlideSorter
.GetView());
1426 DragAndDropModeHandler::~DragAndDropModeHandler()
1428 if (mpDragAndDropContext
)
1430 // Disconnect the substitution handler from this selection function.
1431 mpDragAndDropContext
->SetTargetSlideSorter();
1432 mpDragAndDropContext
.reset();
1434 mrSlideSorter
.GetController().GetInsertionIndicatorHandler()->End(Animator::AM_Animated
);
1437 SelectionFunction::Mode
DragAndDropModeHandler::GetMode() const
1439 return SelectionFunction::DragAndDropMode
;
1442 void DragAndDropModeHandler::Abort()
1444 mrSlideSorter
.GetController().GetClipboard().Abort();
1445 if (mpDragAndDropContext
)
1446 mpDragAndDropContext
->Dispose();
1447 // mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection());
1450 bool DragAndDropModeHandler::ProcessButtonUpEvent (
1451 SelectionFunction::EventDescriptor
& rDescriptor
)
1453 if (Match(rDescriptor
.mnEventCode
, BUTTON_UP
| LEFT_BUTTON
))
1455 // The following Process() call may lead to the destruction
1456 // of rDescriptor.mpHitDescriptor so release our reference to it.
1457 rDescriptor
.mpHitDescriptor
.reset();
1458 mrSelectionFunction
.SwitchToNormalMode();
1465 bool DragAndDropModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor
& rDescriptor
)
1467 OSL_ASSERT(mpDragAndDropContext
);
1469 if (rDescriptor
.mbIsLeaving
)
1471 mrSelectionFunction
.SwitchToNormalMode();
1473 else if (mpDragAndDropContext
)
1475 mpDragAndDropContext
->UpdatePosition(
1476 rDescriptor
.maMousePosition
,
1477 rDescriptor
.meDragMode
, true);
1483 } // end of namespace ::sd::slidesorter::controller
1485 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */