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 .
20 #include <sal/config.h>
24 #include "controller/SlsSelectionFunction.hxx"
26 #include "SlideSorter.hxx"
27 #include "SlideSorterViewShell.hxx"
28 #include "SlsDragAndDropContext.hxx"
29 #include "controller/SlsTransferableData.hxx"
30 #include "controller/SlideSorterController.hxx"
31 #include "controller/SlsPageSelector.hxx"
32 #include "controller/SlsFocusManager.hxx"
33 #include "controller/SlsScrollBarManager.hxx"
34 #include "controller/SlsClipboard.hxx"
35 #include "controller/SlsCurrentSlideManager.hxx"
36 #include "controller/SlsInsertionIndicatorHandler.hxx"
37 #include "controller/SlsSelectionManager.hxx"
38 #include "controller/SlsProperties.hxx"
39 #include "controller/SlsSlotManager.hxx"
40 #include "controller/SlsVisibleAreaManager.hxx"
41 #include "model/SlideSorterModel.hxx"
42 #include "model/SlsPageDescriptor.hxx"
43 #include "model/SlsPageEnumerationProvider.hxx"
44 #include "view/SlideSorterView.hxx"
45 #include "view/SlsLayouter.hxx"
46 #include "view/SlsPageObjectLayouter.hxx"
47 #include "framework/FrameworkHelper.hxx"
48 #include "ViewShellBase.hxx"
49 #include "DrawController.hxx"
52 #include "drawdoc.hxx"
53 #include "DrawDocShell.hxx"
55 #include "ViewShell.hxx"
56 #include "FrameView.hxx"
58 #include "sdresid.hxx"
59 #include "strings.hrc"
60 #include <sfx2/viewfrm.hxx>
61 #include <sfx2/dispatch.hxx>
62 #include <svx/svdpagv.hxx>
63 #include <vcl/msgbox.hxx>
64 #include <svx/svxids.hrc>
65 #include <boost/bind.hpp>
66 #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 maMousePosition
;
108 Point maMouseModelPosition
;
109 model::SharedPageDescriptor mpHitDescriptor
;
111 sal_uInt32 mnEventCode
;
112 InsertionIndicatorHandler::Mode meDragMode
;
113 bool mbMakeSelectionVisible
;
117 sal_uInt32 nEventType
,
118 const MouseEvent
& rEvent
,
119 SlideSorter
& rSlideSorter
);
121 sal_uInt32 nEventType
,
122 const AcceptDropEvent
& rEvent
,
123 const sal_Int8 nDragAction
,
124 SlideSorter
& rSlideSorter
);
127 /** Compute a numerical code that describes a mouse event and that can
128 be used for fast look up of the appropriate reaction.
130 sal_uInt32
EncodeMouseEvent (const MouseEvent
& rEvent
) const;
132 /** Compute a numerical code that describes the current state like
133 whether the selection rectangle is visible or whether the page under
134 the mouse or the one that has the focus is selected.
136 sal_uInt32
EncodeState() const;
139 //===== SelectionFunction::ModeHandler ========================================
141 class SelectionFunction::ModeHandler
145 SlideSorter
& rSlideSorter
,
146 SelectionFunction
& rSelectionFunction
,
147 const bool bIsMouseOverIndicatorAllowed
);
148 virtual ~ModeHandler();
150 virtual Mode
GetMode() const = 0;
151 virtual void Abort() = 0;
152 virtual void ProcessEvent (EventDescriptor
& rDescriptor
);
154 /** Set the selection to exactly the specified page and also set it as
157 void SetCurrentPage (const model::SharedPageDescriptor
& rpDescriptor
);
159 /// Deselect all pages.
160 void DeselectAllPages();
161 void SelectOnePage (const model::SharedPageDescriptor
& rpDescriptor
);
163 /** When the view on which this selection function is working is the
164 main view then the view is switched to the regular editing view.
166 void SwitchView (const model::SharedPageDescriptor
& rpDescriptor
);
169 const Point
& rMousePosition
,
170 const InsertionIndicatorHandler::Mode eMode
);
172 bool IsMouseOverIndicatorAllowed() const { return mbIsMouseOverIndicatorAllowed
;}
175 SlideSorter
& mrSlideSorter
;
176 SelectionFunction
& mrSelectionFunction
;
178 virtual bool ProcessButtonDownEvent (EventDescriptor
& rDescriptor
);
179 virtual bool ProcessButtonUpEvent (EventDescriptor
& rDescriptor
);
180 virtual bool ProcessMotionEvent (EventDescriptor
& rDescriptor
);
181 virtual bool ProcessDragEvent (EventDescriptor
& rDescriptor
);
182 virtual bool HandleUnprocessedEvent (EventDescriptor
& rDescriptor
);
184 void ReprocessEvent (EventDescriptor
& rDescriptor
);
187 const bool mbIsMouseOverIndicatorAllowed
;
190 /** This is the default handler for processing events. It activates the
191 multi selection or drag-and-drop when the right conditions are met.
193 class NormalModeHandler
: public SelectionFunction::ModeHandler
197 SlideSorter
& rSlideSorter
,
198 SelectionFunction
& rSelectionFunction
);
199 virtual ~NormalModeHandler();
201 virtual SelectionFunction::Mode
GetMode() const SAL_OVERRIDE
;
202 virtual void Abort() SAL_OVERRIDE
;
204 void ResetButtonDownLocation();
207 virtual bool ProcessButtonDownEvent (SelectionFunction::EventDescriptor
& rDescriptor
) SAL_OVERRIDE
;
208 virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor
& rDescriptor
) SAL_OVERRIDE
;
209 virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor
& rDescriptor
) SAL_OVERRIDE
;
210 virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor
& rDescriptor
) SAL_OVERRIDE
;
213 ::boost::optional
<Point
> maButtonDownLocation
;
215 /** Select all pages between and including the selection anchor and the
218 void RangeSelect (const model::SharedPageDescriptor
& rpDescriptor
);
221 /** Handle events during a multi selection, which typically is started by
222 pressing the left mouse button when not over a page.
224 class MultiSelectionModeHandler
: public SelectionFunction::ModeHandler
227 /** Start a rectangle selection at the given position.
229 MultiSelectionModeHandler (
230 SlideSorter
& rSlideSorter
,
231 SelectionFunction
& rSelectionFunction
,
233 const Point
& rMouseModelPosition
);
235 const Point
& rMouseModelPosition
,
236 const sal_uInt32 nEventCode
);
238 virtual ~MultiSelectionModeHandler();
241 void Initialize(const sal_uInt32 nEventCode
);
244 virtual SelectionFunction::Mode
GetMode() const SAL_OVERRIDE
;
245 virtual void Abort() SAL_OVERRIDE
;
246 virtual void ProcessEvent (SelectionFunction::EventDescriptor
& rDescriptor
) SAL_OVERRIDE
;
248 enum SelectionMode
{ SM_Normal
, SM_Add
, SM_Toggle
};
250 void SetSelectionMode (const SelectionMode eSelectionMode
);
251 void SetSelectionModeFromModifier (const sal_uInt32 nEventCode
);
254 virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor
& rDescriptor
) SAL_OVERRIDE
;
255 virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor
& rDescriptor
) SAL_OVERRIDE
;
256 virtual bool HandleUnprocessedEvent (SelectionFunction::EventDescriptor
& rDescriptor
) SAL_OVERRIDE
;
259 SelectionMode meSelectionMode
;
260 Point maSecondCorner
;
261 Pointer maSavedPointer
;
262 bool mbAutoScrollInstalled
;
263 sal_Int32 mnAnchorIndex
;
264 sal_Int32 mnSecondIndex
;
266 void UpdateModelPosition (const Point
& rMouseModelPosition
);
267 void UpdateSelection();
269 /** Update the rectangle selection so that the given position becomes
270 the new second point of the selection rectangle.
272 void UpdatePosition (
273 const Point
& rMousePosition
,
274 const bool bAllowAutoScroll
);
276 void UpdateSelectionState (
277 const model::SharedPageDescriptor
& rpDescriptor
,
278 const bool bIsInSelection
) const;
281 /** Handle events during drag-and-drop.
283 class DragAndDropModeHandler
: public SelectionFunction::ModeHandler
286 DragAndDropModeHandler (
287 SlideSorter
& rSlideSorter
,
289 SelectionFunction
& rSelectionFunction
);
291 SelectionFunction
& rSelectionFunction
,
292 const Point
& rMousePosition
,
293 vcl::Window
* pWindow
);
295 virtual ~DragAndDropModeHandler();
298 void Initialize(const Point
& rMousePosition
, vcl::Window
* pWindow
);
301 virtual SelectionFunction::Mode
GetMode() const SAL_OVERRIDE
;
302 virtual void Abort() SAL_OVERRIDE
;
305 virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor
& rDescriptor
) SAL_OVERRIDE
;
306 virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor
& rDescriptor
) SAL_OVERRIDE
;
309 ::boost::scoped_ptr
<DragAndDropContext
> mpDragAndDropContext
;
312 //===== SelectionFunction =====================================================
314 TYPEINIT1(SelectionFunction
, FuPoor
);
316 SelectionFunction::SelectionFunction (
317 SlideSorter
& rSlideSorter
,
318 SfxRequest
& rRequest
)
320 rSlideSorter
.GetViewShell(),
321 rSlideSorter
.GetContentWindow(),
322 &rSlideSorter
.GetView(),
323 rSlideSorter
.GetModel().GetDocument(),
325 mrSlideSorter(rSlideSorter
),
326 mrController(mrSlideSorter
.GetController()),
327 mbDragSelection(false),
328 maInsertionMarkerBox(),
329 mbProcessingMouseButtonDown(false),
330 mnShiftKeySelectionAnchor(-1),
331 mpModeHandler(new NormalModeHandler(rSlideSorter
, *this))
335 SelectionFunction::~SelectionFunction()
337 mpModeHandler
.reset();
340 rtl::Reference
<FuPoor
> SelectionFunction::Create(
341 SlideSorter
& rSlideSorter
,
342 SfxRequest
& rRequest
)
344 rtl::Reference
<FuPoor
> xFunc( new SelectionFunction( rSlideSorter
, rRequest
) );
348 bool SelectionFunction::MouseButtonDown (const MouseEvent
& rEvent
)
350 // remember button state for creation of own MouseEvents
351 SetMouseButtonCode (rEvent
.GetButtons());
352 aMDPos
= rEvent
.GetPosPixel();
353 mbProcessingMouseButtonDown
= true;
355 // mpWindow->CaptureMouse();
357 ProcessMouseEvent(BUTTON_DOWN
, rEvent
);
362 bool SelectionFunction::MouseMove (const MouseEvent
& rEvent
)
364 ProcessMouseEvent(MOUSE_MOTION
, rEvent
);
368 bool SelectionFunction::MouseButtonUp (const MouseEvent
& rEvent
)
370 mrController
.GetScrollBarManager().StopAutoScroll ();
372 ProcessMouseEvent(BUTTON_UP
, rEvent
);
374 mbProcessingMouseButtonDown
= false;
379 void SelectionFunction::NotifyDragFinished()
381 SwitchToNormalMode();
384 bool SelectionFunction::KeyInput (const KeyEvent
& rEvent
)
386 view::SlideSorterView::DrawLock
aDrawLock (mrSlideSorter
);
387 PageSelector::BroadcastLock
aBroadcastLock (mrSlideSorter
);
388 PageSelector::UpdateLock
aLock (mrSlideSorter
);
389 FocusManager
& rFocusManager (mrController
.GetFocusManager());
390 bool bResult
= false;
392 const vcl::KeyCode
& rCode (rEvent
.GetKeyCode());
393 switch (rCode
.GetCode())
397 model::SharedPageDescriptor
pDescriptor (rFocusManager
.GetFocusedPageDescriptor());
398 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
399 if (rFocusManager
.HasFocus() && pDescriptor
&& pViewShell
!=NULL
)
401 // The Return key triggers different functions depending on
402 // whether the slide sorter is the main view or displayed in
404 if (pViewShell
->IsMainViewShell())
406 mpModeHandler
->SetCurrentPage(pDescriptor
);
407 mpModeHandler
->SwitchView(pDescriptor
);
409 else if (pViewShell
->GetDispatcher() != NULL
)
411 pViewShell
->GetDispatcher()->Execute(
413 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
421 if ( ! rFocusManager
.IsFocusShowing())
423 rFocusManager
.ShowFocus();
429 // When there is an active multiselection or drag-and-drop
430 // operation then stop that.
431 mpModeHandler
->Abort();
432 SwitchToNormalMode();
438 // Toggle the selection state.
439 model::SharedPageDescriptor
pDescriptor (rFocusManager
.GetFocusedPageDescriptor());
440 if (pDescriptor
&& rCode
.IsMod1())
442 if (pDescriptor
->HasState(model::PageDescriptor::ST_Selected
))
443 mrController
.GetPageSelector().DeselectPage(pDescriptor
, false);
445 mrController
.GetPageSelector().SelectPage(pDescriptor
);
451 // Move the focus indicator left.
453 MoveFocus(FocusManager::FMD_LEFT
, rCode
.IsShift(), rCode
.IsMod1());
457 // Move the focus indicator right.
459 MoveFocus(FocusManager::FMD_RIGHT
, rCode
.IsShift(), rCode
.IsMod1());
463 // Move the focus indicator up.
465 MoveFocus(FocusManager::FMD_UP
, rCode
.IsShift(), rCode
.IsMod1());
469 // Move the focus indicator down.
471 MoveFocus(FocusManager::FMD_DOWN
, rCode
.IsShift(), rCode
.IsMod1());
475 // Go to previous page. No wrap around.
481 // Go to next page. No wrap around..
493 GotoPage(mrSlideSorter
.GetModel().GetPageCount()-1);
500 if (mrSlideSorter
.GetProperties()->IsUIReadOnly())
503 mrController
.GetSelectionManager()->DeleteSelectedPages(rCode
.GetCode()==KEY_DELETE
);
505 mnShiftKeySelectionAnchor
= -1;
513 mpModeHandler
->SelectOnePage(
514 mrSlideSorter
.GetController().GetFocusManager().GetFocusedPageDescriptor());
523 bResult
= FuPoor::KeyInput(rEvent
);
528 void SelectionFunction::MoveFocus (
529 const FocusManager::FocusMoveDirection eDirection
,
530 const bool bIsShiftDown
,
531 const bool bIsControlDown
)
533 // Remember the anchor of shift key multi selection.
536 if (mnShiftKeySelectionAnchor
<0)
538 model::SharedPageDescriptor
pFocusedDescriptor (
539 mrController
.GetFocusManager().GetFocusedPageDescriptor());
540 mnShiftKeySelectionAnchor
= pFocusedDescriptor
->GetPageIndex();
543 else if ( ! bIsControlDown
)
544 ResetShiftKeySelectionAnchor();
546 mrController
.GetFocusManager().MoveFocus(eDirection
);
548 PageSelector
& rSelector (mrController
.GetPageSelector());
549 model::SharedPageDescriptor
pFocusedDescriptor (
550 mrController
.GetFocusManager().GetFocusedPageDescriptor());
553 // When shift is pressed then select all pages in the range between
554 // the currently and the previously focused pages, including them.
555 if (pFocusedDescriptor
)
557 sal_Int32
nPageRangeEnd (pFocusedDescriptor
->GetPageIndex());
558 model::PageEnumeration
aPages (
559 model::PageEnumerationProvider::CreateAllPagesEnumeration(
560 mrSlideSorter
.GetModel()));
561 while (aPages
.HasMoreElements())
563 model::SharedPageDescriptor
pDescriptor (aPages
.GetNextElement());
566 const sal_Int32
nPageIndex(pDescriptor
->GetPageIndex());
567 if ((nPageIndex
>=mnShiftKeySelectionAnchor
&& nPageIndex
<=nPageRangeEnd
)
568 || (nPageIndex
<=mnShiftKeySelectionAnchor
&& nPageIndex
>=nPageRangeEnd
))
570 rSelector
.SelectPage(pDescriptor
);
574 rSelector
.DeselectPage(pDescriptor
);
580 else if (bIsControlDown
)
582 // When control is pressed then do not alter the selection or the
583 // current page, just move the focus.
587 // Without shift just select the focused page.
588 mpModeHandler
->SelectOnePage(pFocusedDescriptor
);
592 void SelectionFunction::Activate()
597 void SelectionFunction::Deactivate()
599 FuPoor::Deactivate();
602 void SelectionFunction::DoCut()
604 if ( ! mrSlideSorter
.GetProperties()->IsUIReadOnly())
606 mrController
.GetClipboard().DoCut();
610 void SelectionFunction::DoCopy()
612 mrController
.GetClipboard().DoCopy();
615 void SelectionFunction::DoPaste()
617 if ( ! mrSlideSorter
.GetProperties()->IsUIReadOnly())
619 mrController
.GetClipboard().DoPaste();
623 bool SelectionFunction::cancel()
625 mrController
.GetFocusManager().ToggleFocus();
629 void SelectionFunction::GotoNextPage (int nOffset
)
631 model::SharedPageDescriptor pDescriptor
632 = mrController
.GetCurrentSlideManager()->GetCurrentSlide();
633 if (pDescriptor
.get() != NULL
)
635 SdPage
* pPage
= pDescriptor
->GetPage();
636 OSL_ASSERT(pPage
!=NULL
);
637 sal_Int32 nIndex
= (pPage
->GetPageNum()-1) / 2;
638 GotoPage(nIndex
+ nOffset
);
640 ResetShiftKeySelectionAnchor();
643 void SelectionFunction::GotoPage (int nIndex
)
645 sal_uInt16 nPageCount
= (sal_uInt16
)mrSlideSorter
.GetModel().GetPageCount();
647 if (nIndex
>= nPageCount
)
648 nIndex
= nPageCount
- 1;
652 mrController
.GetFocusManager().SetFocusedPage(nIndex
);
653 model::SharedPageDescriptor
pNextPageDescriptor (
654 mrSlideSorter
.GetModel().GetPageDescriptor (nIndex
));
655 if (pNextPageDescriptor
.get() != NULL
)
656 mpModeHandler
->SetCurrentPage(pNextPageDescriptor
);
659 OSL_ASSERT(pNextPageDescriptor
.get() != NULL
);
661 ResetShiftKeySelectionAnchor();
664 void SelectionFunction::ProcessMouseEvent (sal_uInt32 nEventType
, const MouseEvent
& rEvent
)
666 // #95491# remember button state for creation of own MouseEvents
667 SetMouseButtonCode (rEvent
.GetButtons());
669 EventDescriptor
aEventDescriptor (nEventType
, rEvent
, mrSlideSorter
);
670 ProcessEvent(aEventDescriptor
);
673 void SelectionFunction::MouseDragged (
674 const AcceptDropEvent
& rEvent
,
675 const sal_Int8 nDragAction
)
677 EventDescriptor
aEventDescriptor (MOUSE_DRAG
, rEvent
, nDragAction
, mrSlideSorter
);
678 ProcessEvent(aEventDescriptor
);
681 void SelectionFunction::ProcessEvent (EventDescriptor
& rDescriptor
)
683 // The call to ProcessEvent may switch to another mode handler.
684 // Prevent the untimely destruction of the called handler by acquiring a
685 // temporary reference here.
686 ::boost::shared_ptr
<ModeHandler
> pModeHandler (mpModeHandler
);
687 pModeHandler
->ProcessEvent(rDescriptor
);
691 const sal_uInt32 nEventCode
,
692 const sal_uInt32 nPositivePattern
)
694 return (nEventCode
& nPositivePattern
)==nPositivePattern
;
697 void SelectionFunction::SwitchToNormalMode()
699 if (mpModeHandler
->GetMode() != NormalMode
)
700 SwitchMode(::boost::shared_ptr
<ModeHandler
>(
701 new NormalModeHandler(mrSlideSorter
, *this)));
704 void SelectionFunction::SwitchToDragAndDropMode (const Point
& rMousePosition
)
706 if (mpModeHandler
->GetMode() != DragAndDropMode
)
709 ::boost::shared_ptr
<DragAndDropModeHandler
> handler(
710 new DragAndDropModeHandler(mrSlideSorter
, *this));
712 // Delayed initialization, only after mpModeHanler is set, otherwise DND initialization
713 // could already trigger DND events, which would recursively trigger this code again,
714 // and without mpModeHandler set it would again try to set a new handler.
715 handler
->Initialize(rMousePosition
, mpWindow
);
717 SwitchMode(::boost::shared_ptr
<ModeHandler
>(
718 new DragAndDropModeHandler(mrSlideSorter
, *this, rMousePosition
, mpWindow
)));
723 void SelectionFunction::SwitchToMultiSelectionMode (
724 const Point
& rMousePosition
,
725 const sal_uInt32 nEventCode
)
727 if (mpModeHandler
->GetMode() != MultiSelectionMode
)
730 ::boost::shared_ptr
<MultiSelectionModeHandler
> handler(
731 new MultiSelectionModeHandler(mrSlideSorter
, *this, rMousePosition
));
733 // Delayed initialization, only after mpModeHanler is set, the handle ctor
734 // is non-trivial, so it could possibly recurse just like the DND handler above.
735 handler
->Initialize(nEventCode
);
738 SwitchMode(::boost::shared_ptr
<ModeHandler
>(
739 new MultiSelectionModeHandler(mrSlideSorter
, *this, rMousePosition
, nEventCode
)));
743 void SelectionFunction::SwitchMode (const ::boost::shared_ptr
<ModeHandler
>& rpHandler
)
745 // Not all modes allow mouse over indicator.
746 if (mpModeHandler
->IsMouseOverIndicatorAllowed() != rpHandler
->IsMouseOverIndicatorAllowed())
748 if ( ! rpHandler
->IsMouseOverIndicatorAllowed())
750 mrSlideSorter
.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
753 mrSlideSorter
.GetView().UpdatePageUnderMouse();
756 mpModeHandler
= rpHandler
;
759 void SelectionFunction::ResetShiftKeySelectionAnchor()
761 mnShiftKeySelectionAnchor
= -1;
764 void SelectionFunction::ResetMouseAnchor()
766 if (mpModeHandler
&& mpModeHandler
->GetMode() == NormalMode
)
768 ::boost::shared_ptr
<NormalModeHandler
> pHandler (
769 ::boost::dynamic_pointer_cast
<NormalModeHandler
>(mpModeHandler
));
771 pHandler
->ResetButtonDownLocation();
775 //===== EventDescriptor =======================================================
777 SelectionFunction::EventDescriptor::EventDescriptor (
778 const sal_uInt32 nEventType
,
779 const MouseEvent
& rEvent
,
780 SlideSorter
& rSlideSorter
)
781 : maMousePosition(rEvent
.GetPosPixel()),
782 maMouseModelPosition(),
785 mnEventCode(nEventType
),
786 meDragMode(InsertionIndicatorHandler::MoveMode
),
787 mbMakeSelectionVisible(true),
790 maMouseModelPosition
= rSlideSorter
.GetContentWindow()->PixelToLogic(maMousePosition
);
791 mpHitDescriptor
= rSlideSorter
.GetController().GetPageAt(maMousePosition
);
794 mpHitPage
= mpHitDescriptor
->GetPage();
797 mnEventCode
|= EncodeMouseEvent(rEvent
);
798 mnEventCode
|= EncodeState();
800 // Detect the mouse leaving the window. When not button is pressed then
801 // we can call IsLeaveWindow at the event. Otherwise we have to make an
803 mbIsLeaving
= rEvent
.IsLeaveWindow()
804 || ! Rectangle(Point(0,0),
805 rSlideSorter
.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition
);
808 SelectionFunction::EventDescriptor::EventDescriptor (
809 const sal_uInt32 nEventType
,
810 const AcceptDropEvent
& rEvent
,
811 const sal_Int8 nDragAction
,
812 SlideSorter
& rSlideSorter
)
813 : maMousePosition(rEvent
.maPosPixel
),
814 maMouseModelPosition(),
817 mnEventCode(nEventType
),
818 meDragMode(InsertionIndicatorHandler::GetModeFromDndAction(nDragAction
)),
819 mbMakeSelectionVisible(true),
822 maMouseModelPosition
= rSlideSorter
.GetContentWindow()->PixelToLogic(maMousePosition
);
823 mpHitDescriptor
= rSlideSorter
.GetController().GetPageAt(maMousePosition
);
826 mpHitPage
= mpHitDescriptor
->GetPage();
829 mnEventCode
|= EncodeState();
831 // Detect the mouse leaving the window. When not button is pressed then
832 // we can call IsLeaveWindow at the event. Otherwise we have to make an
834 mbIsLeaving
= rEvent
.mbLeaving
835 || ! Rectangle(Point(0,0),
836 rSlideSorter
.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition
);
839 sal_uInt32
SelectionFunction::EventDescriptor::EncodeMouseEvent (
840 const MouseEvent
& rEvent
) const
842 // Initialize with the type of mouse event.
843 sal_uInt32
nEventCode (mnEventCode
& (BUTTON_DOWN
| BUTTON_UP
| MOUSE_MOTION
));
845 // Detect the affected button.
846 switch (rEvent
.GetButtons())
848 case MOUSE_LEFT
: nEventCode
|= LEFT_BUTTON
; break;
849 case MOUSE_RIGHT
: nEventCode
|= RIGHT_BUTTON
; break;
850 case MOUSE_MIDDLE
: nEventCode
|= MIDDLE_BUTTON
; break;
853 // Detect the number of clicks.
854 switch (rEvent
.GetClicks())
856 case 1: nEventCode
|= SINGLE_CLICK
; break;
857 case 2: nEventCode
|= DOUBLE_CLICK
; break;
860 // Detect pressed modifier keys.
861 if (rEvent
.IsShift())
862 nEventCode
|= SHIFT_MODIFIER
;
864 nEventCode
|= CONTROL_MODIFIER
;
869 sal_uInt32
SelectionFunction::EventDescriptor::EncodeState() const
871 sal_uInt32
nEventCode (0);
873 // Detect whether the event has happened over a page object.
874 if (mpHitPage
!=NULL
&& mpHitDescriptor
)
876 if (mpHitDescriptor
->HasState(model::PageDescriptor::ST_Selected
))
877 nEventCode
|= OVER_SELECTED_PAGE
;
879 nEventCode
|= OVER_UNSELECTED_PAGE
;
885 //===== SelectionFunction::ModeHandler ========================================
887 SelectionFunction::ModeHandler::ModeHandler (
888 SlideSorter
& rSlideSorter
,
889 SelectionFunction
& rSelectionFunction
,
890 const bool bIsMouseOverIndicatorAllowed
)
891 : mrSlideSorter(rSlideSorter
),
892 mrSelectionFunction(rSelectionFunction
),
893 mbIsMouseOverIndicatorAllowed(bIsMouseOverIndicatorAllowed
)
897 SelectionFunction::ModeHandler::~ModeHandler()
901 void SelectionFunction::ModeHandler::ReprocessEvent (EventDescriptor
& rDescriptor
)
903 mrSelectionFunction
.ProcessEvent(rDescriptor
);
906 void SelectionFunction::ModeHandler::ProcessEvent (
907 SelectionFunction::EventDescriptor
& rDescriptor
)
909 PageSelector::BroadcastLock
aBroadcastLock (mrSlideSorter
);
910 PageSelector::UpdateLock
aUpdateLock (mrSlideSorter
);
912 bool bIsProcessed (false);
913 switch (rDescriptor
.mnEventCode
& (BUTTON_DOWN
| BUTTON_UP
| MOUSE_MOTION
| MOUSE_DRAG
))
916 bIsProcessed
= ProcessButtonDownEvent(rDescriptor
);
920 bIsProcessed
= ProcessButtonUpEvent(rDescriptor
);
924 bIsProcessed
= ProcessMotionEvent(rDescriptor
);
928 bIsProcessed
= ProcessDragEvent(rDescriptor
);
933 HandleUnprocessedEvent(rDescriptor
);
936 bool SelectionFunction::ModeHandler::ProcessButtonDownEvent (EventDescriptor
&)
941 bool SelectionFunction::ModeHandler::ProcessButtonUpEvent (EventDescriptor
&)
943 mrSelectionFunction
.SwitchToNormalMode();
947 bool SelectionFunction::ModeHandler::ProcessMotionEvent (EventDescriptor
& rDescriptor
)
949 if (mbIsMouseOverIndicatorAllowed
)
950 mrSlideSorter
.GetView().UpdatePageUnderMouse(rDescriptor
.maMousePosition
);
952 if (rDescriptor
.mbIsLeaving
)
954 mrSelectionFunction
.SwitchToNormalMode();
955 mrSlideSorter
.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
963 bool SelectionFunction::ModeHandler::ProcessDragEvent (EventDescriptor
&)
968 bool SelectionFunction::ModeHandler::HandleUnprocessedEvent (EventDescriptor
&)
973 void SelectionFunction::ModeHandler::SetCurrentPage (
974 const model::SharedPageDescriptor
& rpDescriptor
)
976 SelectOnePage(rpDescriptor
);
977 mrSlideSorter
.GetController().GetCurrentSlideManager()->SwitchCurrentSlide(rpDescriptor
);
980 void SelectionFunction::ModeHandler::DeselectAllPages()
982 mrSlideSorter
.GetController().GetPageSelector().DeselectAllPages();
983 mrSelectionFunction
.ResetShiftKeySelectionAnchor();
986 void SelectionFunction::ModeHandler::SelectOnePage (
987 const model::SharedPageDescriptor
& rpDescriptor
)
990 mrSlideSorter
.GetController().GetPageSelector().SelectPage(rpDescriptor
);
993 void SelectionFunction::ModeHandler::SwitchView (const model::SharedPageDescriptor
& rpDescriptor
)
995 // Switch to the draw view. This is done only when the current
996 // view is the main view.
997 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
998 if (pViewShell
!=NULL
&& pViewShell
->IsMainViewShell())
1000 if (rpDescriptor
.get()!=NULL
&& rpDescriptor
->GetPage()!=NULL
)
1002 mrSlideSorter
.GetModel().GetDocument()->SetSelected(rpDescriptor
->GetPage(), true);
1003 pViewShell
->GetFrameView()->SetSelectedPage(
1004 (rpDescriptor
->GetPage()->GetPageNum()-1)/2);
1006 if (mrSlideSorter
.GetViewShellBase() != NULL
)
1007 framework::FrameworkHelper::Instance(*mrSlideSorter
.GetViewShellBase())->RequestView(
1008 framework::FrameworkHelper::msImpressViewURL
,
1009 framework::FrameworkHelper::msCenterPaneURL
);
1013 void SelectionFunction::ModeHandler::StartDrag (
1014 const Point
& rMousePosition
,
1015 const InsertionIndicatorHandler::Mode eMode
)
1018 // Do not start a drag-and-drop operation when one is already active.
1019 // (when dragging pages from one document into another, pressing a
1020 // modifier key can trigger a MouseMotion event in the originating
1021 // window (focus still in there). Together with the mouse button pressed
1022 // (drag-and-drop is active) this triggers the start of drag-and-drop.)
1023 if (SD_MOD()->pTransferDrag
!= NULL
)
1026 if ( ! mrSlideSorter
.GetProperties()->IsUIReadOnly())
1028 mrSelectionFunction
.SwitchToDragAndDropMode(rMousePosition
);
1032 //===== NormalModeHandler =====================================================
1034 NormalModeHandler::NormalModeHandler (
1035 SlideSorter
& rSlideSorter
,
1036 SelectionFunction
& rSelectionFunction
)
1037 : ModeHandler(rSlideSorter
, rSelectionFunction
, true),
1038 maButtonDownLocation()
1042 NormalModeHandler::~NormalModeHandler()
1046 SelectionFunction::Mode
NormalModeHandler::GetMode() const
1048 return SelectionFunction::NormalMode
;
1051 void NormalModeHandler::Abort()
1055 bool NormalModeHandler::ProcessButtonDownEvent (
1056 SelectionFunction::EventDescriptor
& rDescriptor
)
1058 // Remember the location where the left button is pressed. With
1059 // that we can filter away motion events that are caused by key
1060 // presses. We also can tune the minimal motion distance that
1061 // triggers a drag-and-drop operation.
1062 if ((rDescriptor
.mnEventCode
& BUTTON_DOWN
) != 0)
1063 maButtonDownLocation
= rDescriptor
.maMousePosition
;
1065 switch (rDescriptor
.mnEventCode
)
1067 case BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
:
1068 SetCurrentPage(rDescriptor
.mpHitDescriptor
);
1071 case BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
:
1074 case BUTTON_DOWN
| LEFT_BUTTON
| DOUBLE_CLICK
| OVER_SELECTED_PAGE
:
1075 case BUTTON_DOWN
| LEFT_BUTTON
| DOUBLE_CLICK
| OVER_UNSELECTED_PAGE
:
1076 // A double click always shows the selected slide in the center
1077 // pane in an edit view.
1078 SetCurrentPage(rDescriptor
.mpHitDescriptor
);
1079 SwitchView(rDescriptor
.mpHitDescriptor
);
1082 case BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
| SHIFT_MODIFIER
:
1083 case BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
| SHIFT_MODIFIER
:
1084 // Range selection with the shift modifier.
1085 RangeSelect(rDescriptor
.mpHitDescriptor
);
1088 // Right button for context menu.
1089 case BUTTON_DOWN
| RIGHT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
:
1090 // Single right click and shift+F10 select as preparation to
1091 // show the context menu. Change the selection only when the
1092 // page under the mouse is not selected. In this case the
1093 // selection is set to this single page. Otherwise the
1094 // selection is not modified.
1095 SetCurrentPage(rDescriptor
.mpHitDescriptor
);
1096 rDescriptor
.mbMakeSelectionVisible
= false;
1099 case BUTTON_DOWN
| RIGHT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
:
1100 // Do not change the selection. Just adjust the insertion indicator.
1101 rDescriptor
.mbMakeSelectionVisible
= false;
1104 case BUTTON_DOWN
| RIGHT_BUTTON
| SINGLE_CLICK
| NOT_OVER_PAGE
:
1105 // Remember the current selection so that when a multi selection
1106 // is started, we can restore the previous selection.
1107 mrSlideSorter
.GetModel().SaveCurrentSelection();
1111 case ANY_MODIFIER(BUTTON_DOWN
| LEFT_BUTTON
| SINGLE_CLICK
| NOT_OVER_PAGE
):
1112 // Remember the current selection so that when a multi selection
1113 // is started, we can restore the previous selection.
1114 mrSlideSorter
.GetModel().SaveCurrentSelection();
1118 case BUTTON_DOWN
| LEFT_BUTTON
| DOUBLE_CLICK
| NOT_OVER_PAGE
:
1120 // Insert a new slide:
1121 // First of all we need to set the insertion indicator which sets the
1122 // position where the new slide will be inserted.
1123 ::boost::shared_ptr
<InsertionIndicatorHandler
> pInsertionIndicatorHandler
1124 = mrSlideSorter
.GetController().GetInsertionIndicatorHandler();
1126 pInsertionIndicatorHandler
->Start(false);
1127 pInsertionIndicatorHandler
->UpdatePosition(
1128 rDescriptor
.maMousePosition
,
1129 InsertionIndicatorHandler::MoveMode
);
1130 mrSlideSorter
.GetController().GetSelectionManager()->SetInsertionPosition(
1131 pInsertionIndicatorHandler
->GetInsertionPageIndex());
1133 mrSlideSorter
.GetViewShell()->GetDispatcher()->Execute(
1135 SfxCallMode::ASYNCHRON
| SfxCallMode::RECORD
);
1145 bool NormalModeHandler::ProcessButtonUpEvent (
1146 SelectionFunction::EventDescriptor
& rDescriptor
)
1148 bool bIsProcessed (true);
1149 switch (rDescriptor
.mnEventCode
)
1151 case BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
:
1152 SetCurrentPage(rDescriptor
.mpHitDescriptor
);
1155 // Multi selection with the control modifier.
1156 case BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
| CONTROL_MODIFIER
:
1157 mrSlideSorter
.GetController().GetPageSelector().DeselectPage(
1158 rDescriptor
.mpHitDescriptor
);
1161 case BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
| CONTROL_MODIFIER
:
1162 mrSlideSorter
.GetController().GetPageSelector().SelectPage(
1163 rDescriptor
.mpHitDescriptor
);
1164 mrSlideSorter
.GetView().SetPageUnderMouse(rDescriptor
.mpHitDescriptor
);
1166 case BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
| NOT_OVER_PAGE
:
1170 bIsProcessed
= false;
1173 mrSelectionFunction
.SwitchToNormalMode();
1174 return bIsProcessed
;
1177 bool NormalModeHandler::ProcessMotionEvent (
1178 SelectionFunction::EventDescriptor
& rDescriptor
)
1180 if (ModeHandler::ProcessMotionEvent(rDescriptor
))
1183 bool bIsProcessed (true);
1184 switch (rDescriptor
.mnEventCode
)
1186 case ANY_MODIFIER(MOUSE_MOTION
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_UNSELECTED_PAGE
):
1187 // SetCurrentPage(rDescriptor.mpHitDescriptor);
1190 // A mouse motion without visible substitution starts that.
1191 case ANY_MODIFIER(MOUSE_MOTION
| LEFT_BUTTON
| SINGLE_CLICK
| OVER_SELECTED_PAGE
):
1193 if (maButtonDownLocation
)
1195 const sal_Int32
nDistance (maButtonDownLocation
1197 std::abs(maButtonDownLocation
->X() - rDescriptor
.maMousePosition
.X()),
1198 std::abs(maButtonDownLocation
->Y() - rDescriptor
.maMousePosition
.Y()))
1202 rDescriptor
.maMousePosition
,
1203 (rDescriptor
.mnEventCode
& CONTROL_MODIFIER
) != 0
1204 ? InsertionIndicatorHandler::CopyMode
1205 : InsertionIndicatorHandler::MoveMode
);
1210 // A mouse motion not over a page starts a rectangle selection.
1211 case ANY_MODIFIER(MOUSE_MOTION
| LEFT_BUTTON
| SINGLE_CLICK
| NOT_OVER_PAGE
):
1212 mrSelectionFunction
.SwitchToMultiSelectionMode(
1213 rDescriptor
.maMouseModelPosition
,
1214 rDescriptor
.mnEventCode
);
1218 bIsProcessed
= false;
1221 return bIsProcessed
;
1224 bool NormalModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor
& rDescriptor
)
1226 mrSelectionFunction
.SwitchToDragAndDropMode(rDescriptor
.maMousePosition
);
1227 ReprocessEvent(rDescriptor
);
1231 void NormalModeHandler::RangeSelect (const model::SharedPageDescriptor
& rpDescriptor
)
1233 PageSelector::UpdateLock
aLock (mrSlideSorter
);
1234 PageSelector
& rSelector (mrSlideSorter
.GetController().GetPageSelector());
1236 model::SharedPageDescriptor
pAnchor (rSelector
.GetSelectionAnchor());
1239 if (pAnchor
.get() != NULL
)
1241 // Select all pages between the anchor and the given one, including
1243 const sal_uInt16
nAnchorIndex ((pAnchor
->GetPage()->GetPageNum()-1) / 2);
1244 const sal_uInt16
nOtherIndex ((rpDescriptor
->GetPage()->GetPageNum()-1) / 2);
1246 // Iterate over all pages in the range. Start with the anchor
1247 // page. This way the PageSelector will recognize it again as
1248 // anchor (the first selected page after a DeselectAllPages()
1249 // becomes the anchor.)
1250 const sal_uInt16
nStep ((nAnchorIndex
< nOtherIndex
) ? +1 : -1);
1251 sal_uInt16
nIndex (nAnchorIndex
);
1254 rSelector
.SelectPage(nIndex
);
1255 if (nIndex
== nOtherIndex
)
1257 nIndex
= nIndex
+ nStep
;
1262 void NormalModeHandler::ResetButtonDownLocation()
1264 maButtonDownLocation
= ::boost::optional
<Point
>();
1267 //===== MultiSelectionModeHandler =============================================
1269 MultiSelectionModeHandler::MultiSelectionModeHandler (
1270 SlideSorter
& rSlideSorter
,
1271 SelectionFunction
& rSelectionFunction
,
1273 const Point
& rMouseModelPosition
)
1275 const Point
& rMouseModelPosition
,
1276 const sal_uInt32 nEventCode
)
1278 : ModeHandler(rSlideSorter
, rSelectionFunction
, false),
1279 meSelectionMode(SM_Normal
),
1280 maSecondCorner(rMouseModelPosition
),
1281 maSavedPointer(mrSlideSorter
.GetContentWindow()->GetPointer()),
1282 mbAutoScrollInstalled(false),
1289 void MultiSelectionModeHandler::Initialize(const sal_uInt32 nEventCode
)
1292 const Pointer
aSelectionPointer (PointerStyle::Text
);
1293 mrSlideSorter
.GetContentWindow()->SetPointer(aSelectionPointer
);
1294 SetSelectionModeFromModifier(nEventCode
);
1297 MultiSelectionModeHandler::~MultiSelectionModeHandler()
1299 if (mbAutoScrollInstalled
)
1301 //a call to this handler's MultiSelectionModeHandler::UpdatePosition
1302 //may be still waiting to be called back
1303 mrSlideSorter
.GetController().GetScrollBarManager().clearAutoScrollFunctor();
1305 mrSlideSorter
.GetContentWindow()->SetPointer(maSavedPointer
);
1308 SelectionFunction::Mode
MultiSelectionModeHandler::GetMode() const
1310 return SelectionFunction::MultiSelectionMode
;
1313 void MultiSelectionModeHandler::Abort()
1315 mrSlideSorter
.GetView().RequestRepaint(mrSlideSorter
.GetModel().RestoreSelection());
1318 void MultiSelectionModeHandler::ProcessEvent (
1319 SelectionFunction::EventDescriptor
& rDescriptor
)
1321 // During a multi selection we do not want sudden jumps of the
1322 // visible area caused by moving newly selected pages into view.
1323 // Therefore disable that temporarily. The disabler object is
1324 // released at the end of the event processing, after the focus and
1325 // current slide have been updated.
1326 VisibleAreaManager::TemporaryDisabler
aDisabler (mrSlideSorter
);
1328 ModeHandler::ProcessEvent(rDescriptor
);
1331 bool MultiSelectionModeHandler::ProcessButtonUpEvent (
1332 SelectionFunction::EventDescriptor
& rDescriptor
)
1334 if (mbAutoScrollInstalled
)
1336 //a call to this handler's MultiSelectionModeHandler::UpdatePosition
1337 //may be still waiting to be called back
1338 mrSlideSorter
.GetController().GetScrollBarManager().clearAutoScrollFunctor();
1339 mbAutoScrollInstalled
= false;
1342 if (Match(rDescriptor
.mnEventCode
, BUTTON_UP
| LEFT_BUTTON
| SINGLE_CLICK
))
1344 mrSelectionFunction
.SwitchToNormalMode();
1351 bool MultiSelectionModeHandler::ProcessMotionEvent (
1352 SelectionFunction::EventDescriptor
& rDescriptor
)
1354 // The selection rectangle is visible. Handle events accordingly.
1355 if (Match(rDescriptor
.mnEventCode
, MOUSE_MOTION
| LEFT_BUTTON
| SINGLE_CLICK
))
1357 SetSelectionModeFromModifier(rDescriptor
.mnEventCode
);
1358 UpdatePosition(rDescriptor
.maMousePosition
, true);
1359 rDescriptor
.mbMakeSelectionVisible
= false;
1366 bool MultiSelectionModeHandler::HandleUnprocessedEvent (
1367 SelectionFunction::EventDescriptor
& rDescriptor
)
1369 if ( ! ModeHandler::HandleUnprocessedEvent(rDescriptor
))
1371 // If the event has not been processed then stop multi selection.
1372 mrSelectionFunction
.SwitchToNormalMode();
1373 ReprocessEvent(rDescriptor
);
1378 void MultiSelectionModeHandler::UpdatePosition (
1379 const Point
& rMousePosition
,
1380 const bool bAllowAutoScroll
)
1382 VisibleAreaManager::TemporaryDisabler
aDisabler (mrSlideSorter
);
1384 // Convert window coordinates into model coordinates (we need the
1385 // window coordinates for auto-scrolling because that remains
1386 // constant while scrolling.)
1387 sd::Window
*pWindow (mrSlideSorter
.GetContentWindow());
1388 const Point
aMouseModelPosition (pWindow
->PixelToLogic(rMousePosition
));
1390 bool bDoAutoScroll
= bAllowAutoScroll
&& mrSlideSorter
.GetController().GetScrollBarManager().AutoScroll(
1393 &MultiSelectionModeHandler::UpdatePosition
,
1399 UpdateModelPosition(aMouseModelPosition
);
1401 mbAutoScrollInstalled
|= bDoAutoScroll
;
1404 void MultiSelectionModeHandler::SetSelectionModeFromModifier (
1405 const sal_uInt32 nEventCode
)
1407 switch (nEventCode
& MODIFIER_MASK
)
1410 SetSelectionMode(SM_Normal
);
1413 case SHIFT_MODIFIER
:
1414 SetSelectionMode(SM_Add
);
1417 case CONTROL_MODIFIER
:
1418 SetSelectionMode(SM_Toggle
);
1423 void MultiSelectionModeHandler::SetSelectionMode (const SelectionMode eSelectionMode
)
1425 if (meSelectionMode
!= eSelectionMode
)
1427 meSelectionMode
= eSelectionMode
;
1432 void MultiSelectionModeHandler::UpdateSelectionState (
1433 const model::SharedPageDescriptor
& rpDescriptor
,
1434 const bool bIsInSelection
) const
1436 // Determine whether the page was selected before the rectangle
1437 // selection was started.
1438 const bool bWasSelected (rpDescriptor
->HasState(model::PageDescriptor::ST_WasSelected
));
1440 // Combine the two selection states depending on the selection mode.
1441 bool bSelect (false);
1442 switch(meSelectionMode
)
1445 bSelect
= bIsInSelection
;
1449 bSelect
= bIsInSelection
|| bWasSelected
;
1454 bSelect
= !bWasSelected
;
1456 bSelect
= bWasSelected
;
1460 // Set the new selection state.
1462 mrSlideSorter
.GetController().GetPageSelector().SelectPage(rpDescriptor
);
1464 mrSlideSorter
.GetController().GetPageSelector().DeselectPage(rpDescriptor
);
1467 void MultiSelectionModeHandler::UpdateModelPosition (const Point
& rMouseModelPosition
)
1469 maSecondCorner
= rMouseModelPosition
;
1473 void MultiSelectionModeHandler::UpdateSelection()
1475 view::SlideSorterView::DrawLock
aLock (mrSlideSorter
);
1477 model::SlideSorterModel
& rModel (mrSlideSorter
.GetModel());
1478 const sal_Int32
nPageCount (rModel
.GetPageCount());
1480 const sal_Int32
nIndexUnderMouse (
1481 mrSlideSorter
.GetView().GetLayouter().GetIndexAtPoint (
1485 if (nIndexUnderMouse
>=0 && nIndexUnderMouse
<nPageCount
)
1487 if (mnAnchorIndex
< 0)
1488 mnAnchorIndex
= nIndexUnderMouse
;
1489 mnSecondIndex
= nIndexUnderMouse
;
1491 Range
aRange (mnAnchorIndex
, mnSecondIndex
);
1494 for (sal_Int32 nIndex
=0; nIndex
<nPageCount
; ++nIndex
)
1496 UpdateSelectionState(rModel
.GetPageDescriptor(nIndex
), aRange
.IsInside(nIndex
));
1501 //===== DragAndDropModeHandler ================================================
1503 DragAndDropModeHandler::DragAndDropModeHandler (
1504 SlideSorter
& rSlideSorter
,
1506 SelectionFunction
& rSelectionFunction
)
1508 SelectionFunction
& rSelectionFunction
,
1509 const Point
& rMousePosition
,
1510 vcl::Window
* pWindow
)
1512 : ModeHandler(rSlideSorter
, rSelectionFunction
, false)
1517 void DragAndDropModeHandler::Initialize(const Point
& rMousePosition
, vcl::Window
* pWindow
)
1520 SdTransferable
* pDragTransferable
= SD_MOD()->pTransferDrag
;
1521 if (pDragTransferable
==NULL
&& mrSlideSorter
.GetViewShell() != NULL
)
1523 SlideSorterViewShell
* pSlideSorterViewShell
1524 = dynamic_cast<SlideSorterViewShell
*>(mrSlideSorter
.GetViewShell());
1525 if (pSlideSorterViewShell
!= NULL
)
1526 pSlideSorterViewShell
->StartDrag(rMousePosition
, pWindow
);
1527 pDragTransferable
= SD_MOD()->pTransferDrag
;
1530 mpDragAndDropContext
.reset(new DragAndDropContext(mrSlideSorter
));
1531 mrSlideSorter
.GetController().GetInsertionIndicatorHandler()->Start(
1532 pDragTransferable
!= NULL
1533 && pDragTransferable
->GetView()==&mrSlideSorter
.GetView());
1536 DragAndDropModeHandler::~DragAndDropModeHandler()
1538 if (mpDragAndDropContext
)
1540 // Disconnect the substitution handler from this selection function.
1541 mpDragAndDropContext
->SetTargetSlideSorter();
1542 mpDragAndDropContext
.reset();
1544 mrSlideSorter
.GetController().GetInsertionIndicatorHandler()->End(Animator::AM_Animated
);
1547 SelectionFunction::Mode
DragAndDropModeHandler::GetMode() const
1549 return SelectionFunction::DragAndDropMode
;
1552 void DragAndDropModeHandler::Abort()
1554 mrSlideSorter
.GetController().GetClipboard().Abort();
1555 if (mpDragAndDropContext
)
1556 mpDragAndDropContext
->Dispose();
1557 // mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection());
1560 bool DragAndDropModeHandler::ProcessButtonUpEvent (
1561 SelectionFunction::EventDescriptor
& rDescriptor
)
1563 if (Match(rDescriptor
.mnEventCode
, BUTTON_UP
| LEFT_BUTTON
))
1565 // The following Process() call may lead to the destruction
1566 // of rDescriptor.mpHitDescriptor so release our reference to it.
1567 rDescriptor
.mpHitDescriptor
.reset();
1568 mrSelectionFunction
.SwitchToNormalMode();
1575 bool DragAndDropModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor
& rDescriptor
)
1577 OSL_ASSERT(mpDragAndDropContext
);
1579 if (rDescriptor
.mbIsLeaving
)
1581 mrSelectionFunction
.SwitchToNormalMode();
1583 else if (mpDragAndDropContext
)
1585 mpDragAndDropContext
->UpdatePosition(
1586 rDescriptor
.maMousePosition
,
1587 rDescriptor
.meDragMode
);
1593 } } } // end of namespace ::sd::slidesorter::controller
1595 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */