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>
25 #include <controller/SlsSelectionFunction.hxx>
27 #include <SlideSorter.hxx>
28 #include <SlideSorterViewShell.hxx>
29 #include "SlsDragAndDropContext.hxx"
30 #include <controller/SlsTransferableData.hxx>
31 #include <controller/SlideSorterController.hxx>
32 #include <controller/SlsPageSelector.hxx>
33 #include <controller/SlsFocusManager.hxx>
34 #include <controller/SlsScrollBarManager.hxx>
35 #include <controller/SlsClipboard.hxx>
36 #include <controller/SlsCurrentSlideManager.hxx>
37 #include <controller/SlsInsertionIndicatorHandler.hxx>
38 #include <controller/SlsSelectionManager.hxx>
39 #include <controller/SlsProperties.hxx>
40 #include <controller/SlsSlotManager.hxx>
41 #include <controller/SlsVisibleAreaManager.hxx>
42 #include <model/SlideSorterModel.hxx>
43 #include <model/SlsPageDescriptor.hxx>
44 #include <model/SlsPageEnumerationProvider.hxx>
45 #include <view/SlideSorterView.hxx>
46 #include <view/SlsLayouter.hxx>
47 #include <view/SlsPageObjectLayouter.hxx>
48 #include <framework/FrameworkHelper.hxx>
49 #include <ViewShellBase.hxx>
50 #include <DrawController.hxx>
53 #include <drawdoc.hxx>
54 #include <DrawDocShell.hxx>
56 #include <ViewShell.hxx>
57 #include <FrameView.hxx>
59 #include <o3tl/deleter.hxx>
60 #include <sfx2/viewfrm.hxx>
61 #include <sfx2/dispatch.hxx>
62 #include <svx/svdpagv.hxx>
63 #include <svx/svxids.hrc>
64 #include <vcl/ptrstyle.hxx>
65 #include <boost/optional.hpp>
69 static const sal_uInt32
SINGLE_CLICK (0x00000001);
70 static const sal_uInt32
DOUBLE_CLICK (0x00000002);
71 static const sal_uInt32
LEFT_BUTTON (0x00000010);
72 static const sal_uInt32
RIGHT_BUTTON (0x00000020);
73 static const sal_uInt32
MIDDLE_BUTTON (0x00000040);
74 static const sal_uInt32
BUTTON_DOWN (0x00000100);
75 static const sal_uInt32
BUTTON_UP (0x00000200);
76 static const sal_uInt32
MOUSE_MOTION (0x00000400);
77 static const sal_uInt32
MOUSE_DRAG (0x00000800);
78 // The rest leaves the lower 16 bit untouched so that it can be used with
80 static const sal_uInt32
OVER_SELECTED_PAGE (0x00010000);
81 static const sal_uInt32
OVER_UNSELECTED_PAGE (0x00020000);
82 static const sal_uInt32
SHIFT_MODIFIER (0x00200000);
83 static const sal_uInt32
CONTROL_MODIFIER (0x00400000);
85 // Some absent events are defined so they can be expressed explicitly.
86 static const sal_uInt32
NO_MODIFIER (0x00000000);
87 static const sal_uInt32
NOT_OVER_PAGE (0x00000000);
90 static const sal_uInt32
MODIFIER_MASK (SHIFT_MODIFIER
| CONTROL_MODIFIER
);
92 } // end of anonymous namespace
94 // Define some macros to make the following switch statement more readable.
95 #define ANY_MODIFIER(code) \
97 case code|SHIFT_MODIFIER: \
98 case code|CONTROL_MODIFIER
100 namespace sd
{ namespace slidesorter
{ namespace controller
{
102 //===== SelectionFunction::EventDescriptor ====================================
104 class SelectionFunction::EventDescriptor
107 Point
const maMousePosition
;
108 Point maMouseModelPosition
;
109 model::SharedPageDescriptor mpHitDescriptor
;
111 sal_uInt32 mnEventCode
;
112 InsertionIndicatorHandler::Mode
const meDragMode
;
116 sal_uInt32 nEventType
,
117 const MouseEvent
& rEvent
,
118 SlideSorter
const & rSlideSorter
);
120 sal_uInt32 nEventType
,
121 const AcceptDropEvent
& rEvent
,
122 const sal_Int8 nDragAction
,
123 SlideSorter
const & rSlideSorter
);
126 /** Compute a numerical code that describes a mouse event and that can
127 be used for fast look up of the appropriate reaction.
129 sal_uInt32
EncodeMouseEvent (const MouseEvent
& rEvent
) const;
131 /** Compute a numerical code that describes the current state like
132 whether the selection rectangle is visible or whether the page under
133 the mouse or the one that has the focus is selected.
135 sal_uInt32
EncodeState() const;
138 //===== SelectionFunction::ModeHandler ========================================
140 class SelectionFunction::ModeHandler
144 SlideSorter
& rSlideSorter
,
145 SelectionFunction
& rSelectionFunction
,
146 const bool bIsMouseOverIndicatorAllowed
);
147 virtual ~ModeHandler() COVERITY_NOEXCEPT_FALSE
;
149 virtual Mode
GetMode() const = 0;
150 virtual void Abort() = 0;
151 virtual void ProcessEvent (EventDescriptor
& rDescriptor
);
153 /** Set the selection to exactly the specified page and also set it as
156 void SetCurrentPage (const model::SharedPageDescriptor
& rpDescriptor
);
158 /// Deselect all pages.
159 void DeselectAllPages();
160 void SelectOnePage (const model::SharedPageDescriptor
& rpDescriptor
);
162 /** When the view on which this selection function is working is the
163 main view then the view is switched to the regular editing view.
165 void SwitchView (const model::SharedPageDescriptor
& rpDescriptor
);
168 const Point
& rMousePosition
);
170 bool IsMouseOverIndicatorAllowed() const { return mbIsMouseOverIndicatorAllowed
;}
173 SlideSorter
& mrSlideSorter
;
174 SelectionFunction
& mrSelectionFunction
;
176 virtual bool ProcessButtonDownEvent (EventDescriptor
& rDescriptor
);
177 virtual bool ProcessButtonUpEvent (EventDescriptor
& rDescriptor
);
178 virtual bool ProcessMotionEvent (EventDescriptor
& rDescriptor
);
179 virtual bool ProcessDragEvent (EventDescriptor
& rDescriptor
);
180 virtual bool HandleUnprocessedEvent (EventDescriptor
& rDescriptor
);
182 void ReprocessEvent (EventDescriptor
& rDescriptor
);
185 const bool mbIsMouseOverIndicatorAllowed
;
188 /** This is the default handler for processing events. It activates the
189 multi selection or drag-and-drop when the right conditions are met.
191 class NormalModeHandler
: public SelectionFunction::ModeHandler
195 SlideSorter
& rSlideSorter
,
196 SelectionFunction
& rSelectionFunction
);
198 virtual SelectionFunction::Mode
GetMode() const override
;
199 virtual void Abort() override
;
201 void ResetButtonDownLocation();
204 virtual bool ProcessButtonDownEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
205 virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
206 virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
207 virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
210 ::boost::optional
<Point
> maButtonDownLocation
;
212 /** Select all pages between and including the selection anchor and the
215 void RangeSelect (const model::SharedPageDescriptor
& rpDescriptor
);
218 /** Handle events during a multi selection, which typically is started by
219 pressing the left mouse button when not over a page.
221 class MultiSelectionModeHandler
: public SelectionFunction::ModeHandler
224 /** Start a rectangle selection at the given position.
226 MultiSelectionModeHandler (
227 SlideSorter
& rSlideSorter
,
228 SelectionFunction
& rSelectionFunction
,
229 const Point
& rMouseModelPosition
,
230 const sal_uInt32 nEventCode
);
232 virtual ~MultiSelectionModeHandler() override
;
234 virtual SelectionFunction::Mode
GetMode() const override
;
235 virtual void Abort() override
;
236 virtual void ProcessEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
238 enum SelectionMode
{ SM_Normal
, SM_Add
, SM_Toggle
};
240 void SetSelectionMode (const SelectionMode eSelectionMode
);
241 void SetSelectionModeFromModifier (const sal_uInt32 nEventCode
);
244 virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
245 virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
246 virtual bool HandleUnprocessedEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
249 SelectionMode meSelectionMode
;
250 Point maSecondCorner
;
251 PointerStyle
const maSavedPointer
;
252 bool mbAutoScrollInstalled
;
253 sal_Int32 mnAnchorIndex
;
254 sal_Int32 mnSecondIndex
;
256 void UpdateModelPosition (const Point
& rMouseModelPosition
);
257 void UpdateSelection();
259 /** Update the rectangle selection so that the given position becomes
260 the new second point of the selection rectangle.
262 void UpdatePosition (
263 const Point
& rMousePosition
,
264 const bool bAllowAutoScroll
);
266 void UpdateSelectionState (
267 const model::SharedPageDescriptor
& rpDescriptor
,
268 const bool bIsInSelection
) const;
271 /** Handle events during drag-and-drop.
273 class DragAndDropModeHandler
: public SelectionFunction::ModeHandler
276 DragAndDropModeHandler (
277 SlideSorter
& rSlideSorter
,
278 SelectionFunction
& rSelectionFunction
,
279 const Point
& rMousePosition
,
280 vcl::Window
* pWindow
);
281 virtual ~DragAndDropModeHandler() override
;
283 virtual SelectionFunction::Mode
GetMode() const override
;
284 virtual void Abort() override
;
287 virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
288 virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor
& rDescriptor
) override
;
291 std::unique_ptr
<DragAndDropContext
, o3tl::default_delete
<DragAndDropContext
>> mpDragAndDropContext
;
294 //===== SelectionFunction =====================================================
297 SelectionFunction::SelectionFunction (
298 SlideSorter
& rSlideSorter
,
299 SfxRequest
& rRequest
)
301 rSlideSorter
.GetViewShell(),
302 rSlideSorter
.GetContentWindow(),
303 &rSlideSorter
.GetView(),
304 rSlideSorter
.GetModel().GetDocument(),
306 mrSlideSorter(rSlideSorter
),
307 mrController(mrSlideSorter
.GetController()),
308 mnShiftKeySelectionAnchor(-1),
309 mpModeHandler(new NormalModeHandler(rSlideSorter
, *this))
313 SelectionFunction::~SelectionFunction()
315 mpModeHandler
.reset();
318 rtl::Reference
<FuPoor
> SelectionFunction::Create(
319 SlideSorter
& rSlideSorter
,
320 SfxRequest
& rRequest
)
322 rtl::Reference
<FuPoor
> xFunc( new SelectionFunction( rSlideSorter
, rRequest
) );
326 bool SelectionFunction::MouseButtonDown (const MouseEvent
& rEvent
)
328 // remember button state for creation of own MouseEvents
329 SetMouseButtonCode (rEvent
.GetButtons());
330 aMDPos
= rEvent
.GetPosPixel();
332 // mpWindow->CaptureMouse();
334 ProcessMouseEvent(BUTTON_DOWN
, rEvent
);
339 bool SelectionFunction::MouseMove (const MouseEvent
& rEvent
)
341 ProcessMouseEvent(MOUSE_MOTION
, rEvent
);
345 bool SelectionFunction::MouseButtonUp (const MouseEvent
& rEvent
)
347 mrController
.GetScrollBarManager().StopAutoScroll ();
349 ProcessMouseEvent(BUTTON_UP
, rEvent
);
354 void SelectionFunction::NotifyDragFinished()
356 SwitchToNormalMode();
359 bool SelectionFunction::KeyInput (const KeyEvent
& rEvent
)
361 view::SlideSorterView::DrawLock
aDrawLock (mrSlideSorter
);
362 PageSelector::BroadcastLock
aBroadcastLock (mrSlideSorter
);
363 PageSelector::UpdateLock
aLock (mrSlideSorter
);
364 FocusManager
& rFocusManager (mrController
.GetFocusManager());
365 bool bResult
= false;
367 const vcl::KeyCode
& rCode (rEvent
.GetKeyCode());
368 switch (rCode
.GetCode())
372 model::SharedPageDescriptor
pDescriptor (rFocusManager
.GetFocusedPageDescriptor());
373 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
374 if (rFocusManager
.HasFocus() && pDescriptor
&& pViewShell
!=nullptr)
376 // The Return key triggers different functions depending on
377 // whether the slide sorter is the main view or displayed in
379 if (pViewShell
->IsMainViewShell())
381 mpModeHandler
->SetCurrentPage(pDescriptor
);
382 mpModeHandler
->SwitchView(pDescriptor
);
384 else if (pViewShell
->GetDispatcher() != nullptr)
386 pViewShell
->GetDispatcher()->Execute(
388 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
396 if ( ! rFocusManager
.IsFocusShowing())
398 rFocusManager
.ShowFocus();
404 // When there is an active multiselection or drag-and-drop
405 // operation then stop that.
406 mpModeHandler
->Abort();
407 SwitchToNormalMode();
413 // Toggle the selection state.
414 model::SharedPageDescriptor
pDescriptor (rFocusManager
.GetFocusedPageDescriptor());
415 if (pDescriptor
&& rCode
.IsMod1())
417 if (pDescriptor
->HasState(model::PageDescriptor::ST_Selected
))
418 mrController
.GetPageSelector().DeselectPage(pDescriptor
, false);
420 mrController
.GetPageSelector().SelectPage(pDescriptor
);
426 // Move the focus indicator left.
428 MoveFocus(FocusManager::FocusMoveDirection::Left
, rCode
.IsShift(), rCode
.IsMod1());
432 // Move the focus indicator right.
434 MoveFocus(FocusManager::FocusMoveDirection::Right
, rCode
.IsShift(), rCode
.IsMod1());
438 // Move the focus indicator up.
440 MoveFocus(FocusManager::FocusMoveDirection::Up
, rCode
.IsShift(), rCode
.IsMod1());
444 // Move the focus indicator down.
446 MoveFocus(FocusManager::FocusMoveDirection::Down
, rCode
.IsShift(), rCode
.IsMod1());
450 // Go to previous page. No wrap around.
456 // Go to next page. No wrap around..
468 GotoPage(mrSlideSorter
.GetModel().GetPageCount()-1);
475 if (mrSlideSorter
.GetProperties()->IsUIReadOnly())
478 mrController
.GetSelectionManager()->DeleteSelectedPages(rCode
.GetCode()==KEY_DELETE
);
480 mnShiftKeySelectionAnchor
= -1;
488 mpModeHandler
->SelectOnePage(
489 mrSlideSorter
.GetController().GetFocusManager().GetFocusedPageDescriptor());
498 bResult
= FuPoor::KeyInput(rEvent
);
503 void SelectionFunction::MoveFocus (
504 const FocusManager::FocusMoveDirection eDirection
,
505 const bool bIsShiftDown
,
506 const bool bIsControlDown
)
508 // Remember the anchor of shift key multi selection.
511 if (mnShiftKeySelectionAnchor
<0)
513 model::SharedPageDescriptor
pFocusedDescriptor (
514 mrController
.GetFocusManager().GetFocusedPageDescriptor());
515 mnShiftKeySelectionAnchor
= pFocusedDescriptor
->GetPageIndex();
518 else if ( ! bIsControlDown
)
519 ResetShiftKeySelectionAnchor();
521 mrController
.GetFocusManager().MoveFocus(eDirection
);
523 PageSelector
& rSelector (mrController
.GetPageSelector());
524 model::SharedPageDescriptor
pFocusedDescriptor (
525 mrController
.GetFocusManager().GetFocusedPageDescriptor());
528 // When shift is pressed then select all pages in the range between
529 // the currently and the previously focused pages, including them.
530 if (pFocusedDescriptor
)
532 sal_Int32
nPageRangeEnd (pFocusedDescriptor
->GetPageIndex());
533 model::PageEnumeration
aPages (
534 model::PageEnumerationProvider::CreateAllPagesEnumeration(
535 mrSlideSorter
.GetModel()));
536 while (aPages
.HasMoreElements())
538 model::SharedPageDescriptor
pDescriptor (aPages
.GetNextElement());
541 const sal_Int32
nPageIndex(pDescriptor
->GetPageIndex());
542 if ((nPageIndex
>=mnShiftKeySelectionAnchor
&& nPageIndex
<=nPageRangeEnd
)
543 || (nPageIndex
<=mnShiftKeySelectionAnchor
&& nPageIndex
>=nPageRangeEnd
))
545 rSelector
.SelectPage(pDescriptor
);
549 rSelector
.DeselectPage(pDescriptor
);
555 else if (bIsControlDown
)
557 // When control is pressed then do not alter the selection or the
558 // current page, just move the focus.
562 // Without shift just select the focused page.
563 mpModeHandler
->SelectOnePage(pFocusedDescriptor
);
567 void SelectionFunction::DoCut()
569 if ( ! mrSlideSorter
.GetProperties()->IsUIReadOnly())
571 mrController
.GetClipboard().DoCut();
575 void SelectionFunction::DoCopy()
577 mrController
.GetClipboard().DoCopy();
580 void SelectionFunction::DoPaste()
582 if ( ! mrSlideSorter
.GetProperties()->IsUIReadOnly())
584 mrController
.GetClipboard().DoPaste();
588 bool SelectionFunction::cancel()
590 mrController
.GetFocusManager().ToggleFocus();
594 void SelectionFunction::GotoNextPage (int nOffset
)
596 model::SharedPageDescriptor pDescriptor
597 = mrController
.GetCurrentSlideManager()->GetCurrentSlide();
598 if (pDescriptor
.get() != nullptr)
600 SdPage
* pPage
= pDescriptor
->GetPage();
601 OSL_ASSERT(pPage
!=nullptr);
602 sal_Int32 nIndex
= (pPage
->GetPageNum()-1) / 2;
603 GotoPage(nIndex
+ nOffset
);
605 ResetShiftKeySelectionAnchor();
608 void SelectionFunction::GotoPage (int nIndex
)
610 sal_uInt16 nPageCount
= static_cast<sal_uInt16
>(mrSlideSorter
.GetModel().GetPageCount());
612 if (nIndex
>= nPageCount
)
613 nIndex
= nPageCount
- 1;
617 mrController
.GetFocusManager().SetFocusedPage(nIndex
);
618 model::SharedPageDescriptor
pNextPageDescriptor (
619 mrSlideSorter
.GetModel().GetPageDescriptor (nIndex
));
620 if (pNextPageDescriptor
.get() != nullptr)
621 mpModeHandler
->SetCurrentPage(pNextPageDescriptor
);
624 OSL_ASSERT(pNextPageDescriptor
.get() != nullptr);
626 ResetShiftKeySelectionAnchor();
629 void SelectionFunction::ProcessMouseEvent (sal_uInt32 nEventType
, const MouseEvent
& rEvent
)
631 // #95491# remember button state for creation of own MouseEvents
632 SetMouseButtonCode (rEvent
.GetButtons());
634 EventDescriptor
aEventDescriptor (nEventType
, rEvent
, mrSlideSorter
);
635 ProcessEvent(aEventDescriptor
);
638 void SelectionFunction::MouseDragged (
639 const AcceptDropEvent
& rEvent
,
640 const sal_Int8 nDragAction
)
642 EventDescriptor
aEventDescriptor (MOUSE_DRAG
, rEvent
, nDragAction
, mrSlideSorter
);
643 ProcessEvent(aEventDescriptor
);
646 void SelectionFunction::ProcessEvent (EventDescriptor
& rDescriptor
)
648 // The call to ProcessEvent may switch to another mode handler.
649 // Prevent the untimely destruction of the called handler by acquiring a
650 // temporary reference here.
651 std::shared_ptr
<ModeHandler
> pModeHandler (mpModeHandler
);
652 pModeHandler
->ProcessEvent(rDescriptor
);
656 const sal_uInt32 nEventCode
,
657 const sal_uInt32 nPositivePattern
)
659 return (nEventCode
& nPositivePattern
)==nPositivePattern
;
662 void SelectionFunction::SwitchToNormalMode()
664 if (mpModeHandler
->GetMode() != NormalMode
)
665 SwitchMode(std::shared_ptr
<ModeHandler
>(
666 new NormalModeHandler(mrSlideSorter
, *this)));
669 void SelectionFunction::SwitchToDragAndDropMode (const Point
& rMousePosition
)
671 if (mpModeHandler
->GetMode() == DragAndDropMode
)
674 SwitchMode(std::shared_ptr
<ModeHandler
>(
675 new DragAndDropModeHandler(mrSlideSorter
, *this, rMousePosition
, mpWindow
)));
678 void SelectionFunction::SwitchToMultiSelectionMode (
679 const Point
& rMousePosition
,
680 const sal_uInt32 nEventCode
)
682 if (mpModeHandler
->GetMode() != MultiSelectionMode
)
683 SwitchMode(std::shared_ptr
<ModeHandler
>(
684 new MultiSelectionModeHandler(mrSlideSorter
, *this, rMousePosition
, nEventCode
)));
687 void SelectionFunction::SwitchMode (const std::shared_ptr
<ModeHandler
>& rpHandler
)
689 // Not all modes allow mouse over indicator.
690 if (mpModeHandler
->IsMouseOverIndicatorAllowed() != rpHandler
->IsMouseOverIndicatorAllowed())
692 if ( ! rpHandler
->IsMouseOverIndicatorAllowed())
694 mrSlideSorter
.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
697 mrSlideSorter
.GetView().UpdatePageUnderMouse();
700 mpModeHandler
= rpHandler
;
703 void SelectionFunction::ResetShiftKeySelectionAnchor()
705 mnShiftKeySelectionAnchor
= -1;
708 void SelectionFunction::ResetMouseAnchor()
710 if (mpModeHandler
&& mpModeHandler
->GetMode() == NormalMode
)
712 std::shared_ptr
<NormalModeHandler
> pHandler (
713 std::dynamic_pointer_cast
<NormalModeHandler
>(mpModeHandler
));
715 pHandler
->ResetButtonDownLocation();
719 //===== EventDescriptor =======================================================
721 SelectionFunction::EventDescriptor::EventDescriptor (
722 const sal_uInt32 nEventType
,
723 const MouseEvent
& rEvent
,
724 SlideSorter
const & rSlideSorter
)
725 : maMousePosition(rEvent
.GetPosPixel()),
726 maMouseModelPosition(),
729 mnEventCode(nEventType
),
730 meDragMode(InsertionIndicatorHandler::MoveMode
),
733 maMouseModelPosition
= rSlideSorter
.GetContentWindow()->PixelToLogic(maMousePosition
);
734 mpHitDescriptor
= rSlideSorter
.GetController().GetPageAt(maMousePosition
);
737 mpHitPage
= mpHitDescriptor
->GetPage();
740 mnEventCode
|= EncodeMouseEvent(rEvent
);
741 mnEventCode
|= EncodeState();
743 // Detect the mouse leaving the window. When not button is pressed then
744 // we can call IsLeaveWindow at the event. Otherwise we have to make an
746 mbIsLeaving
= rEvent
.IsLeaveWindow()
747 || ! ::tools::Rectangle(Point(0,0),
748 rSlideSorter
.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition
);
751 SelectionFunction::EventDescriptor::EventDescriptor (
752 const sal_uInt32 nEventType
,
753 const AcceptDropEvent
& rEvent
,
754 const sal_Int8 nDragAction
,
755 SlideSorter
const & rSlideSorter
)
756 : maMousePosition(rEvent
.maPosPixel
),
757 maMouseModelPosition(),
760 mnEventCode(nEventType
),
761 meDragMode(InsertionIndicatorHandler::GetModeFromDndAction(nDragAction
)),
764 maMouseModelPosition
= rSlideSorter
.GetContentWindow()->PixelToLogic(maMousePosition
);
765 mpHitDescriptor
= rSlideSorter
.GetController().GetPageAt(maMousePosition
);
768 mpHitPage
= mpHitDescriptor
->GetPage();
771 mnEventCode
|= EncodeState();
773 // Detect the mouse leaving the window. When not button is pressed then
774 // we can call IsLeaveWindow at the event. Otherwise we have to make an
776 mbIsLeaving
= rEvent
.mbLeaving
777 || ! ::tools::Rectangle(Point(0,0),
778 rSlideSorter
.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition
);
781 sal_uInt32
SelectionFunction::EventDescriptor::EncodeMouseEvent (
782 const MouseEvent
& rEvent
) const
784 // Initialize with the type of mouse event.
785 sal_uInt32
nEventCode (mnEventCode
& (BUTTON_DOWN
| BUTTON_UP
| MOUSE_MOTION
));
787 // Detect the affected button.
788 switch (rEvent
.GetButtons())
790 case MOUSE_LEFT
: nEventCode
|= LEFT_BUTTON
; break;
791 case MOUSE_RIGHT
: nEventCode
|= RIGHT_BUTTON
; break;
792 case MOUSE_MIDDLE
: nEventCode
|= MIDDLE_BUTTON
; break;
795 // Detect the number of clicks.
796 switch (rEvent
.GetClicks())
798 case 1: nEventCode
|= SINGLE_CLICK
; break;
799 case 2: nEventCode
|= DOUBLE_CLICK
; break;
802 // Detect pressed modifier keys.
803 if (rEvent
.IsShift())
804 nEventCode
|= SHIFT_MODIFIER
;
806 nEventCode
|= CONTROL_MODIFIER
;
811 sal_uInt32
SelectionFunction::EventDescriptor::EncodeState() const
813 sal_uInt32
nEventCode (0);
815 // Detect whether the event has happened over a page object.
816 if (mpHitPage
!=nullptr && mpHitDescriptor
)
818 if (mpHitDescriptor
->HasState(model::PageDescriptor::ST_Selected
))
819 nEventCode
|= OVER_SELECTED_PAGE
;
821 nEventCode
|= OVER_UNSELECTED_PAGE
;
827 //===== SelectionFunction::ModeHandler ========================================
829 SelectionFunction::ModeHandler::ModeHandler (
830 SlideSorter
& rSlideSorter
,
831 SelectionFunction
& rSelectionFunction
,
832 const bool bIsMouseOverIndicatorAllowed
)
833 : mrSlideSorter(rSlideSorter
),
834 mrSelectionFunction(rSelectionFunction
),
835 mbIsMouseOverIndicatorAllowed(bIsMouseOverIndicatorAllowed
)
839 SelectionFunction::ModeHandler::~ModeHandler() COVERITY_NOEXCEPT_FALSE
843 void SelectionFunction::ModeHandler::ReprocessEvent (EventDescriptor
& rDescriptor
)
845 mrSelectionFunction
.ProcessEvent(rDescriptor
);
848 void SelectionFunction::ModeHandler::ProcessEvent (
849 SelectionFunction::EventDescriptor
& rDescriptor
)
851 PageSelector::BroadcastLock
aBroadcastLock (mrSlideSorter
);
852 PageSelector::UpdateLock
aUpdateLock (mrSlideSorter
);
854 bool bIsProcessed (false);
855 switch (rDescriptor
.mnEventCode
& (BUTTON_DOWN
| BUTTON_UP
| MOUSE_MOTION
| MOUSE_DRAG
))
858 bIsProcessed
= ProcessButtonDownEvent(rDescriptor
);
862 bIsProcessed
= ProcessButtonUpEvent(rDescriptor
);
866 bIsProcessed
= ProcessMotionEvent(rDescriptor
);
870 bIsProcessed
= ProcessDragEvent(rDescriptor
);
875 HandleUnprocessedEvent(rDescriptor
);
878 bool SelectionFunction::ModeHandler::ProcessButtonDownEvent (EventDescriptor
&)
883 bool SelectionFunction::ModeHandler::ProcessButtonUpEvent (EventDescriptor
&)
885 mrSelectionFunction
.SwitchToNormalMode();
889 bool SelectionFunction::ModeHandler::ProcessMotionEvent (EventDescriptor
& rDescriptor
)
891 if (mbIsMouseOverIndicatorAllowed
)
892 mrSlideSorter
.GetView().UpdatePageUnderMouse(rDescriptor
.maMousePosition
);
894 if (rDescriptor
.mbIsLeaving
)
896 mrSelectionFunction
.SwitchToNormalMode();
897 mrSlideSorter
.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
905 bool SelectionFunction::ModeHandler::ProcessDragEvent (EventDescriptor
&)
910 bool SelectionFunction::ModeHandler::HandleUnprocessedEvent (EventDescriptor
&)
915 void SelectionFunction::ModeHandler::SetCurrentPage (
916 const model::SharedPageDescriptor
& rpDescriptor
)
918 SelectOnePage(rpDescriptor
);
919 mrSlideSorter
.GetController().GetCurrentSlideManager()->SwitchCurrentSlide(rpDescriptor
);
922 void SelectionFunction::ModeHandler::DeselectAllPages()
924 mrSlideSorter
.GetController().GetPageSelector().DeselectAllPages();
925 mrSelectionFunction
.ResetShiftKeySelectionAnchor();
928 void SelectionFunction::ModeHandler::SelectOnePage (
929 const model::SharedPageDescriptor
& rpDescriptor
)
932 mrSlideSorter
.GetController().GetPageSelector().SelectPage(rpDescriptor
);
935 void SelectionFunction::ModeHandler::SwitchView (const model::SharedPageDescriptor
& rpDescriptor
)
937 // Switch to the draw view. This is done only when the current
938 // view is the main view.
939 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
940 if (pViewShell
==nullptr || !pViewShell
->IsMainViewShell())
943 if (rpDescriptor
.get()!=nullptr && rpDescriptor
->GetPage()!=nullptr)
945 mrSlideSorter
.GetModel().GetDocument()->SetSelected(rpDescriptor
->GetPage(), true);
946 pViewShell
->GetFrameView()->SetSelectedPage(
947 (rpDescriptor
->GetPage()->GetPageNum()-1)/2);
949 if (mrSlideSorter
.GetViewShellBase() != nullptr)
950 framework::FrameworkHelper::Instance(*mrSlideSorter
.GetViewShellBase())->RequestView(
951 framework::FrameworkHelper::msImpressViewURL
,
952 framework::FrameworkHelper::msCenterPaneURL
);
955 void SelectionFunction::ModeHandler::StartDrag (
956 const Point
& rMousePosition
)
958 // Do not start a drag-and-drop operation when one is already active.
959 // (when dragging pages from one document into another, pressing a
960 // modifier key can trigger a MouseMotion event in the originating
961 // window (focus still in there). Together with the mouse button pressed
962 // (drag-and-drop is active) this triggers the start of drag-and-drop.)
963 if (SD_MOD()->pTransferDrag
!= nullptr)
966 if ( ! mrSlideSorter
.GetProperties()->IsUIReadOnly())
968 mrSelectionFunction
.SwitchToDragAndDropMode(rMousePosition
);
972 //===== NormalModeHandler =====================================================
974 NormalModeHandler::NormalModeHandler (
975 SlideSorter
& rSlideSorter
,
976 SelectionFunction
& rSelectionFunction
)
977 : ModeHandler(rSlideSorter
, rSelectionFunction
, true),
978 maButtonDownLocation()
982 SelectionFunction::Mode
NormalModeHandler::GetMode() const
984 return SelectionFunction::NormalMode
;
987 void NormalModeHandler::Abort()
991 bool NormalModeHandler::ProcessButtonDownEvent (
992 SelectionFunction::EventDescriptor
& rDescriptor
)
994 // Remember the location where the left button is pressed. With
995 // that we can filter away motion events that are caused by key
996 // presses. We also can tune the minimal motion distance that
997 // triggers a drag-and-drop operation.
998 if ((rDescriptor
.mnEventCode
& BUTTON_DOWN
) != 0)
999 maButtonDownLocation
= rDescriptor
.maMousePosition
;
1001 switch (rDescriptor
.mnEventCode
)
1003 case BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
:
1004 SetCurrentPage(rDescriptor
.mpHitDescriptor
);
1007 case BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
:
1010 case BUTTON_DOWN
| LEFT_BUTTON
| DOUBLE_CLICK
| OVER_SELECTED_PAGE
:
1011 case BUTTON_DOWN
| LEFT_BUTTON
| DOUBLE_CLICK
| OVER_UNSELECTED_PAGE
:
1012 // A double click always shows the selected slide in the center
1013 // pane in an edit view.
1014 SetCurrentPage(rDescriptor
.mpHitDescriptor
);
1015 SwitchView(rDescriptor
.mpHitDescriptor
);
1018 case BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
| SHIFT_MODIFIER
:
1019 case BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
| SHIFT_MODIFIER
:
1020 // Range selection with the shift modifier.
1021 RangeSelect(rDescriptor
.mpHitDescriptor
);
1024 // Right button for context menu.
1025 case BUTTON_DOWN
| RIGHT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
:
1026 // Single right click and shift+F10 select as preparation to
1027 // show the context menu. Change the selection only when the
1028 // page under the mouse is not selected. In this case the
1029 // selection is set to this single page. Otherwise the
1030 // selection is not modified.
1031 SetCurrentPage(rDescriptor
.mpHitDescriptor
);
1034 case BUTTON_DOWN
| RIGHT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
:
1035 // Do not change the selection. Just adjust the insertion indicator.
1038 case BUTTON_DOWN
| RIGHT_BUTTON
| SINGLE_CLICK
| NOT_OVER_PAGE
:
1039 // Remember the current selection so that when a multi selection
1040 // is started, we can restore the previous selection.
1041 mrSlideSorter
.GetModel().SaveCurrentSelection();
1045 case ANY_MODIFIER(BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| NOT_OVER_PAGE
):
1046 // Remember the current selection so that when a multi selection
1047 // is started, we can restore the previous selection.
1048 mrSlideSorter
.GetModel().SaveCurrentSelection();
1052 case BUTTON_DOWN
| LEFT_BUTTON
| DOUBLE_CLICK
| NOT_OVER_PAGE
:
1054 // Insert a new slide:
1055 // First of all we need to set the insertion indicator which sets the
1056 // position where the new slide will be inserted.
1057 std::shared_ptr
<InsertionIndicatorHandler
> pInsertionIndicatorHandler
1058 = mrSlideSorter
.GetController().GetInsertionIndicatorHandler();
1060 pInsertionIndicatorHandler
->Start(false);
1061 pInsertionIndicatorHandler
->UpdatePosition(
1062 rDescriptor
.maMousePosition
,
1063 InsertionIndicatorHandler::MoveMode
);
1065 mrSlideSorter
.GetController().GetSelectionManager()->SetInsertionPosition(
1066 pInsertionIndicatorHandler
->GetInsertionPageIndex());
1068 mrSlideSorter
.GetViewShell()->GetDispatcher()->Execute(
1070 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
1072 pInsertionIndicatorHandler
->End(Animator::AM_Immediate
);
1083 bool NormalModeHandler::ProcessButtonUpEvent (
1084 SelectionFunction::EventDescriptor
& rDescriptor
)
1086 bool bIsProcessed (true);
1087 switch (rDescriptor
.mnEventCode
)
1089 case BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
:
1090 SetCurrentPage(rDescriptor
.mpHitDescriptor
);
1093 // Multi selection with the control modifier.
1094 case BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
| CONTROL_MODIFIER
:
1095 mrSlideSorter
.GetController().GetPageSelector().DeselectPage(
1096 rDescriptor
.mpHitDescriptor
);
1099 case BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
| CONTROL_MODIFIER
:
1100 mrSlideSorter
.GetController().GetPageSelector().SelectPage(
1101 rDescriptor
.mpHitDescriptor
);
1102 mrSlideSorter
.GetView().SetPageUnderMouse(rDescriptor
.mpHitDescriptor
);
1104 case BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
| NOT_OVER_PAGE
:
1108 bIsProcessed
= false;
1111 mrSelectionFunction
.SwitchToNormalMode();
1112 return bIsProcessed
;
1115 bool NormalModeHandler::ProcessMotionEvent (
1116 SelectionFunction::EventDescriptor
& rDescriptor
)
1118 if (ModeHandler::ProcessMotionEvent(rDescriptor
))
1121 bool bIsProcessed (true);
1122 switch (rDescriptor
.mnEventCode
)
1124 // A mouse motion without visible substitution starts that.
1125 case ANY_MODIFIER(MOUSE_MOTION
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
):
1126 case ANY_MODIFIER(MOUSE_MOTION
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
):
1128 if (maButtonDownLocation
)
1130 const sal_Int32
nDistance(std::max(
1131 std::abs(maButtonDownLocation
->X() - rDescriptor
.maMousePosition
.X()),
1132 std::abs(maButtonDownLocation
->Y() - rDescriptor
.maMousePosition
.Y())));
1134 StartDrag(rDescriptor
.maMousePosition
);
1139 // A mouse motion not over a page starts a rectangle selection.
1140 case ANY_MODIFIER(MOUSE_MOTION
| LEFT_BUTTON
| SINGLE_CLICK
| NOT_OVER_PAGE
):
1141 mrSelectionFunction
.SwitchToMultiSelectionMode(
1142 rDescriptor
.maMouseModelPosition
,
1143 rDescriptor
.mnEventCode
);
1147 bIsProcessed
= false;
1150 return bIsProcessed
;
1153 bool NormalModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor
& rDescriptor
)
1155 mrSelectionFunction
.SwitchToDragAndDropMode(rDescriptor
.maMousePosition
);
1156 ReprocessEvent(rDescriptor
);
1160 void NormalModeHandler::RangeSelect (const model::SharedPageDescriptor
& rpDescriptor
)
1162 PageSelector::UpdateLock
aLock (mrSlideSorter
);
1163 PageSelector
& rSelector (mrSlideSorter
.GetController().GetPageSelector());
1165 model::SharedPageDescriptor
pAnchor (rSelector
.GetSelectionAnchor());
1168 if (pAnchor
.get() == nullptr)
1171 // Select all pages between the anchor and the given one, including
1173 const sal_uInt16
nAnchorIndex ((pAnchor
->GetPage()->GetPageNum()-1) / 2);
1174 const sal_uInt16
nOtherIndex ((rpDescriptor
->GetPage()->GetPageNum()-1) / 2);
1176 // Iterate over all pages in the range. Start with the anchor
1177 // page. This way the PageSelector will recognize it again as
1178 // anchor (the first selected page after a DeselectAllPages()
1179 // becomes the anchor.)
1180 const sal_uInt16
nStep ((nAnchorIndex
< nOtherIndex
) ? +1 : -1);
1181 sal_uInt16
nIndex (nAnchorIndex
);
1184 rSelector
.SelectPage(nIndex
);
1185 if (nIndex
== nOtherIndex
)
1187 nIndex
= nIndex
+ nStep
;
1191 void NormalModeHandler::ResetButtonDownLocation()
1193 maButtonDownLocation
= ::boost::optional
<Point
>();
1196 //===== MultiSelectionModeHandler =============================================
1198 MultiSelectionModeHandler::MultiSelectionModeHandler (
1199 SlideSorter
& rSlideSorter
,
1200 SelectionFunction
& rSelectionFunction
,
1201 const Point
& rMouseModelPosition
,
1202 const sal_uInt32 nEventCode
)
1203 : ModeHandler(rSlideSorter
, rSelectionFunction
, false),
1204 meSelectionMode(SM_Normal
),
1205 maSecondCorner(rMouseModelPosition
),
1206 maSavedPointer(mrSlideSorter
.GetContentWindow()->GetPointer()),
1207 mbAutoScrollInstalled(false),
1212 mrSlideSorter
.GetContentWindow()->SetPointer(PointerStyle::Text
);
1213 SetSelectionModeFromModifier(nEventCode
);
1216 MultiSelectionModeHandler::~MultiSelectionModeHandler()
1218 if (mbAutoScrollInstalled
)
1220 //a call to this handler's MultiSelectionModeHandler::UpdatePosition
1221 //may be still waiting to be called back
1222 mrSlideSorter
.GetController().GetScrollBarManager().clearAutoScrollFunctor();
1224 mrSlideSorter
.GetContentWindow()->SetPointer(maSavedPointer
);
1227 SelectionFunction::Mode
MultiSelectionModeHandler::GetMode() const
1229 return SelectionFunction::MultiSelectionMode
;
1232 void MultiSelectionModeHandler::Abort()
1234 mrSlideSorter
.GetView().RequestRepaint(mrSlideSorter
.GetModel().RestoreSelection());
1237 void MultiSelectionModeHandler::ProcessEvent (
1238 SelectionFunction::EventDescriptor
& rDescriptor
)
1240 // During a multi selection we do not want sudden jumps of the
1241 // visible area caused by moving newly selected pages into view.
1242 // Therefore disable that temporarily. The disabled object is
1243 // released at the end of the event processing, after the focus and
1244 // current slide have been updated.
1245 VisibleAreaManager::TemporaryDisabler
aDisabler (mrSlideSorter
);
1247 ModeHandler::ProcessEvent(rDescriptor
);
1250 bool MultiSelectionModeHandler::ProcessButtonUpEvent (
1251 SelectionFunction::EventDescriptor
& rDescriptor
)
1253 if (mbAutoScrollInstalled
)
1255 //a call to this handler's MultiSelectionModeHandler::UpdatePosition
1256 //may be still waiting to be called back
1257 mrSlideSorter
.GetController().GetScrollBarManager().clearAutoScrollFunctor();
1258 mbAutoScrollInstalled
= false;
1261 if (Match(rDescriptor
.mnEventCode
, BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
))
1263 mrSelectionFunction
.SwitchToNormalMode();
1270 bool MultiSelectionModeHandler::ProcessMotionEvent (
1271 SelectionFunction::EventDescriptor
& rDescriptor
)
1273 // The selection rectangle is visible. Handle events accordingly.
1274 if (Match(rDescriptor
.mnEventCode
, MOUSE_MOTION
| LEFT_BUTTON
| SINGLE_CLICK
))
1276 SetSelectionModeFromModifier(rDescriptor
.mnEventCode
);
1277 UpdatePosition(rDescriptor
.maMousePosition
, true);
1284 bool MultiSelectionModeHandler::HandleUnprocessedEvent (
1285 SelectionFunction::EventDescriptor
& rDescriptor
)
1287 if ( ! ModeHandler::HandleUnprocessedEvent(rDescriptor
))
1289 // If the event has not been processed then stop multi selection.
1290 mrSelectionFunction
.SwitchToNormalMode();
1291 ReprocessEvent(rDescriptor
);
1296 void MultiSelectionModeHandler::UpdatePosition (
1297 const Point
& rMousePosition
,
1298 const bool bAllowAutoScroll
)
1300 VisibleAreaManager::TemporaryDisabler
aDisabler (mrSlideSorter
);
1302 // Convert window coordinates into model coordinates (we need the
1303 // window coordinates for auto-scrolling because that remains
1304 // constant while scrolling.)
1305 sd::Window
*pWindow (mrSlideSorter
.GetContentWindow().get());
1306 const Point
aMouseModelPosition (pWindow
->PixelToLogic(rMousePosition
));
1308 bool bDoAutoScroll
= bAllowAutoScroll
&& mrSlideSorter
.GetController().GetScrollBarManager().AutoScroll(
1310 [this, &rMousePosition
] () { return this->UpdatePosition(rMousePosition
, false); });
1313 UpdateModelPosition(aMouseModelPosition
);
1315 mbAutoScrollInstalled
|= bDoAutoScroll
;
1318 void MultiSelectionModeHandler::SetSelectionModeFromModifier (
1319 const sal_uInt32 nEventCode
)
1321 switch (nEventCode
& MODIFIER_MASK
)
1324 SetSelectionMode(SM_Normal
);
1327 case SHIFT_MODIFIER
:
1328 SetSelectionMode(SM_Add
);
1331 case CONTROL_MODIFIER
:
1332 SetSelectionMode(SM_Toggle
);
1337 void MultiSelectionModeHandler::SetSelectionMode (const SelectionMode eSelectionMode
)
1339 if (meSelectionMode
!= eSelectionMode
)
1341 meSelectionMode
= eSelectionMode
;
1346 void MultiSelectionModeHandler::UpdateSelectionState (
1347 const model::SharedPageDescriptor
& rpDescriptor
,
1348 const bool bIsInSelection
) const
1350 // Determine whether the page was selected before the rectangle
1351 // selection was started.
1352 const bool bWasSelected (rpDescriptor
->HasState(model::PageDescriptor::ST_WasSelected
));
1354 // Combine the two selection states depending on the selection mode.
1355 bool bSelect (false);
1356 switch(meSelectionMode
)
1359 bSelect
= bIsInSelection
;
1363 bSelect
= bIsInSelection
|| bWasSelected
;
1368 bSelect
= !bWasSelected
;
1370 bSelect
= bWasSelected
;
1374 // Set the new selection state.
1376 mrSlideSorter
.GetController().GetPageSelector().SelectPage(rpDescriptor
);
1378 mrSlideSorter
.GetController().GetPageSelector().DeselectPage(rpDescriptor
);
1381 void MultiSelectionModeHandler::UpdateModelPosition (const Point
& rMouseModelPosition
)
1383 maSecondCorner
= rMouseModelPosition
;
1387 void MultiSelectionModeHandler::UpdateSelection()
1389 view::SlideSorterView::DrawLock
aLock (mrSlideSorter
);
1391 model::SlideSorterModel
& rModel (mrSlideSorter
.GetModel());
1392 const sal_Int32
nPageCount (rModel
.GetPageCount());
1394 const sal_Int32
nIndexUnderMouse (
1395 mrSlideSorter
.GetView().GetLayouter().GetIndexAtPoint (
1399 if (!(nIndexUnderMouse
>=0 && nIndexUnderMouse
<nPageCount
))
1402 if (mnAnchorIndex
< 0)
1403 mnAnchorIndex
= nIndexUnderMouse
;
1404 mnSecondIndex
= nIndexUnderMouse
;
1406 Range
aRange (mnAnchorIndex
, mnSecondIndex
);
1409 for (sal_Int32 nIndex
=0; nIndex
<nPageCount
; ++nIndex
)
1411 UpdateSelectionState(rModel
.GetPageDescriptor(nIndex
), aRange
.IsInside(nIndex
));
1415 //===== DragAndDropModeHandler ================================================
1417 DragAndDropModeHandler::DragAndDropModeHandler (
1418 SlideSorter
& rSlideSorter
,
1419 SelectionFunction
& rSelectionFunction
,
1420 const Point
& rMousePosition
,
1421 vcl::Window
* pWindow
)
1422 : ModeHandler(rSlideSorter
, rSelectionFunction
, false)
1424 SdTransferable
* pDragTransferable
= SD_MOD()->pTransferDrag
;
1425 if (pDragTransferable
==nullptr && mrSlideSorter
.GetViewShell() != nullptr)
1427 SlideSorterViewShell
* pSlideSorterViewShell
1428 = dynamic_cast<SlideSorterViewShell
*>(mrSlideSorter
.GetViewShell());
1429 if (pSlideSorterViewShell
!= nullptr)
1430 pSlideSorterViewShell
->StartDrag(rMousePosition
, pWindow
);
1431 pDragTransferable
= SD_MOD()->pTransferDrag
;
1434 mpDragAndDropContext
.reset(new DragAndDropContext(mrSlideSorter
));
1435 mrSlideSorter
.GetController().GetInsertionIndicatorHandler()->Start(
1436 pDragTransferable
!= nullptr
1437 && pDragTransferable
->GetView()==&mrSlideSorter
.GetView());
1440 DragAndDropModeHandler::~DragAndDropModeHandler()
1442 if (mpDragAndDropContext
)
1444 // Disconnect the substitution handler from this selection function.
1445 mpDragAndDropContext
->SetTargetSlideSorter();
1446 mpDragAndDropContext
.reset();
1448 mrSlideSorter
.GetController().GetInsertionIndicatorHandler()->End(Animator::AM_Animated
);
1451 SelectionFunction::Mode
DragAndDropModeHandler::GetMode() const
1453 return SelectionFunction::DragAndDropMode
;
1456 void DragAndDropModeHandler::Abort()
1458 mrSlideSorter
.GetController().GetClipboard().Abort();
1459 if (mpDragAndDropContext
)
1460 mpDragAndDropContext
->Dispose();
1461 // mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection());
1464 bool DragAndDropModeHandler::ProcessButtonUpEvent (
1465 SelectionFunction::EventDescriptor
& rDescriptor
)
1467 if (Match(rDescriptor
.mnEventCode
, BUTTON_UP
| LEFT_BUTTON
))
1469 // The following Process() call may lead to the destruction
1470 // of rDescriptor.mpHitDescriptor so release our reference to it.
1471 rDescriptor
.mpHitDescriptor
.reset();
1472 mrSelectionFunction
.SwitchToNormalMode();
1479 bool DragAndDropModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor
& rDescriptor
)
1481 OSL_ASSERT(mpDragAndDropContext
);
1483 if (rDescriptor
.mbIsLeaving
)
1485 mrSelectionFunction
.SwitchToNormalMode();
1487 else if (mpDragAndDropContext
)
1489 mpDragAndDropContext
->UpdatePosition(
1490 rDescriptor
.maMousePosition
,
1491 rDescriptor
.meDragMode
, true);
1497 } } } // end of namespace ::sd::slidesorter::controller
1499 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */