tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sd / source / ui / slidesorter / controller / SlsSelectionFunction.cxx
blob902f02cd303f28863adf78df49da09d427cf11e6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <memory>
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>
45 #include <Window.hxx>
46 #include <sdpage.hxx>
47 #include <drawdoc.hxx>
48 #include <sdxfer.hxx>
49 #include <ViewShell.hxx>
50 #include <FrameView.hxx>
51 #include <app.hrc>
52 #include <o3tl/deleter.hxx>
53 #include <sfx2/dispatch.hxx>
54 #include <vcl/ptrstyle.hxx>
55 #include <optional>
56 #include <sdmod.hxx>
58 namespace {
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
69 // key codes.
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);
79 // Masks
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) \
86 code|NO_MODIFIER: \
87 case code|SHIFT_MODIFIER: \
88 case code|CONTROL_MODIFIER
90 namespace sd::slidesorter::controller {
92 //===== SelectionFunction::EventDescriptor ====================================
94 class SelectionFunction::EventDescriptor
96 public:
97 Point maMousePosition;
98 Point maMouseModelPosition;
99 model::SharedPageDescriptor mpHitDescriptor;
100 SdrPage* mpHitPage;
101 sal_uInt32 mnEventCode;
102 InsertionIndicatorHandler::Mode meDragMode;
103 bool mbIsLeaving;
105 EventDescriptor (
106 sal_uInt32 nEventType,
107 const MouseEvent& rEvent,
108 SlideSorter const & rSlideSorter);
109 EventDescriptor (
110 sal_uInt32 nEventType,
111 const AcceptDropEvent& rEvent,
112 const sal_Int8 nDragAction,
113 SlideSorter const & rSlideSorter);
115 private:
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
132 public:
133 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
144 the current page.
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);
157 void StartDrag (
158 const Point& rMousePosition);
160 bool IsMouseOverIndicatorAllowed() const { return mbIsMouseOverIndicatorAllowed;}
162 protected:
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);
174 private:
175 const bool mbIsMouseOverIndicatorAllowed;
178 namespace {
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
185 public:
186 NormalModeHandler (
187 SlideSorter& rSlideSorter,
188 SelectionFunction& rSelectionFunction);
190 virtual SelectionFunction::Mode GetMode() const override;
191 virtual void Abort() override;
193 void ResetButtonDownLocation();
195 protected:
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;
201 private:
202 ::std::optional<Point> maButtonDownLocation;
204 /** Select all pages between and including the selection anchor and the
205 specified page.
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
215 public:
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);
235 protected:
236 virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor) override;
237 virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor) override;
238 virtual bool HandleUnprocessedEvent (SelectionFunction::EventDescriptor& rDescriptor) override;
240 private:
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
267 public:
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;
278 protected:
279 virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor) override;
280 virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor) override;
282 private:
283 std::unique_ptr<DragAndDropContext, o3tl::default_delete<DragAndDropContext>> mpDragAndDropContext;
288 //===== SelectionFunction =====================================================
291 SelectionFunction::SelectionFunction (
292 SlideSorter& rSlideSorter,
293 SfxRequest& rRequest)
294 : FuPoor (
295 rSlideSorter.GetViewShell(),
296 rSlideSorter.GetContentWindow(),
297 &rSlideSorter.GetView(),
298 rSlideSorter.GetModel().GetDocument(),
299 rRequest),
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 ) );
317 return xFunc;
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);
330 return true;
333 bool SelectionFunction::MouseMove (const MouseEvent& rEvent)
335 ProcessMouseEvent(MOUSE_MOTION, rEvent);
336 return true;
339 bool SelectionFunction::MouseButtonUp (const MouseEvent& rEvent)
341 mrController.GetScrollBarManager().StopAutoScroll ();
343 ProcessMouseEvent(BUTTON_UP, rEvent);
345 return true;
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())
364 case KEY_RETURN:
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
372 // the right pane.
373 if (pViewShell->IsMainViewShell())
375 mpModeHandler->SetCurrentPage(pDescriptor);
376 mpModeHandler->SwitchView(pDescriptor);
378 else if (pViewShell->GetDispatcher() != nullptr)
380 // tdf#111737 - add new (master) page depending on the edit mode
381 pViewShell->GetDispatcher()->Execute(
382 mrSlideSorter.GetModel().GetEditMode() == EditMode::Page
383 ? SID_INSERTPAGE
384 : SID_INSERT_MASTER_PAGE,
385 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
387 bResult = true;
389 break;
392 case KEY_TAB:
393 if ( ! rFocusManager.IsFocusShowing())
395 rFocusManager.ShowFocus();
396 bResult = true;
398 break;
400 case KEY_ESCAPE:
401 // When there is an active multiselection or drag-and-drop
402 // operation then stop that.
403 mpModeHandler->Abort();
404 SwitchToNormalMode();
405 bResult = true;
406 break;
408 case KEY_SPACE:
410 // Toggle the selection state.
411 model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor());
412 if (pDescriptor && rCode.IsMod1())
414 if (pDescriptor->HasState(model::PageDescriptor::ST_Selected))
415 mrController.GetPageSelector().DeselectPage(pDescriptor, false);
416 else
417 mrController.GetPageSelector().SelectPage(pDescriptor);
419 bResult = true;
421 break;
423 // Move the focus indicator left.
424 case KEY_LEFT:
425 MoveFocus(FocusManager::FocusMoveDirection::Left, rCode.IsShift(), rCode.IsMod1());
426 bResult = true;
427 break;
429 // Move the focus indicator right.
430 case KEY_RIGHT:
431 MoveFocus(FocusManager::FocusMoveDirection::Right, rCode.IsShift(), rCode.IsMod1());
432 bResult = true;
433 break;
435 // Move the focus indicator up.
436 case KEY_UP:
437 MoveFocus(FocusManager::FocusMoveDirection::Up, rCode.IsShift(), rCode.IsMod1());
438 bResult = true;
439 break;
441 // Move the focus indicator down.
442 case KEY_DOWN:
443 MoveFocus(FocusManager::FocusMoveDirection::Down, rCode.IsShift(), rCode.IsMod1());
444 bResult = true;
445 break;
447 // Go to previous page. No wrap around.
448 case KEY_PAGEUP:
449 GotoNextPage(-1);
450 bResult = true;
451 break;
453 // Go to next page. No wrap around...
454 case KEY_PAGEDOWN:
455 GotoNextPage(+1);
456 bResult = true;
457 break;
459 case KEY_HOME:
460 GotoPage(0);
461 bResult = true;
462 break;
464 case KEY_END:
465 GotoPage(mrSlideSorter.GetModel().GetPageCount()-1);
466 bResult = true;
467 break;
469 case KEY_DELETE:
470 case KEY_BACKSPACE:
472 mrController.GetSelectionManager()->DeleteSelectedPages(rCode.GetCode()==KEY_DELETE);
474 mnShiftKeySelectionAnchor = -1;
475 bResult = true;
477 break;
479 case KEY_F10:
480 if (rCode.IsShift())
482 mpModeHandler->SelectOnePage(
483 mrSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor());
485 break;
487 default:
488 break;
491 if ( ! bResult)
492 bResult = FuPoor::KeyInput(rEvent);
494 return bResult;
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.
503 if (bIsShiftDown)
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());
520 if (bIsShiftDown)
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());
533 if (pDescriptor)
535 const sal_Int32 nPageIndex(pDescriptor->GetPageIndex());
536 if ((nPageIndex>=mnShiftKeySelectionAnchor && nPageIndex<=nPageRangeEnd)
537 || (nPageIndex<=mnShiftKeySelectionAnchor && nPageIndex>=nPageRangeEnd))
539 rSelector.SelectPage(pDescriptor);
541 else
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.
554 else
556 // Without shift just select the focused page.
557 mpModeHandler->SelectOnePage(pFocusedDescriptor);
561 void SelectionFunction::DoCut()
563 mrController.GetClipboard().DoCut();
566 void SelectionFunction::DoCopy()
568 mrController.GetClipboard().DoCopy();
571 void SelectionFunction::DoPaste()
573 mrController.GetClipboard().DoPaste();
576 bool SelectionFunction::cancel()
578 mrController.GetFocusManager().ToggleFocus();
579 return true;
582 void SelectionFunction::GotoNextPage (int nOffset)
584 model::SharedPageDescriptor pDescriptor
585 = mrController.GetCurrentSlideManager()->GetCurrentSlide();
586 if (pDescriptor)
588 SdPage* pPage = pDescriptor->GetPage();
589 assert(pPage!=nullptr);
590 sal_Int32 nIndex = (pPage->GetPageNum()-1) / 2;
591 GotoPage(nIndex + nOffset);
593 ResetShiftKeySelectionAnchor();
596 void SelectionFunction::GotoPage (int nIndex)
598 sal_uInt16 nPageCount = static_cast<sal_uInt16>(mrSlideSorter.GetModel().GetPageCount());
600 if (nIndex >= nPageCount)
601 nIndex = nPageCount - 1;
602 if (nIndex < 0)
603 nIndex = 0;
605 mrController.GetFocusManager().SetFocusedPage(nIndex);
606 model::SharedPageDescriptor pNextPageDescriptor (
607 mrSlideSorter.GetModel().GetPageDescriptor (nIndex));
608 if (pNextPageDescriptor)
609 mpModeHandler->SetCurrentPage(pNextPageDescriptor);
610 else
612 OSL_ASSERT(pNextPageDescriptor);
614 ResetShiftKeySelectionAnchor();
617 void SelectionFunction::ProcessMouseEvent (sal_uInt32 nEventType, const MouseEvent& rEvent)
619 // #95491# remember button state for creation of own MouseEvents
620 SetMouseButtonCode (rEvent.GetButtons());
622 EventDescriptor aEventDescriptor (nEventType, rEvent, mrSlideSorter);
623 ProcessEvent(aEventDescriptor);
626 void SelectionFunction::MouseDragged (
627 const AcceptDropEvent& rEvent,
628 const sal_Int8 nDragAction)
630 EventDescriptor aEventDescriptor (MOUSE_DRAG, rEvent, nDragAction, mrSlideSorter);
631 ProcessEvent(aEventDescriptor);
634 void SelectionFunction::ProcessEvent (EventDescriptor& rDescriptor)
636 // The call to ProcessEvent may switch to another mode handler.
637 // Prevent the untimely destruction of the called handler by acquiring a
638 // temporary reference here.
639 std::shared_ptr<ModeHandler> pModeHandler (mpModeHandler);
640 pModeHandler->ProcessEvent(rDescriptor);
643 static bool Match (
644 const sal_uInt32 nEventCode,
645 const sal_uInt32 nPositivePattern)
647 return (nEventCode & nPositivePattern)==nPositivePattern;
650 void SelectionFunction::SwitchToNormalMode()
652 if (mpModeHandler->GetMode() != NormalMode)
653 SwitchMode(std::make_shared<NormalModeHandler>(mrSlideSorter, *this));
656 void SelectionFunction::SwitchToDragAndDropMode (const Point& rMousePosition)
658 if (mpModeHandler->GetMode() == DragAndDropMode)
659 return;
661 SwitchMode(std::make_shared<DragAndDropModeHandler>(mrSlideSorter, *this, rMousePosition, mpWindow));
664 void SelectionFunction::SwitchToMultiSelectionMode (
665 const Point& rMousePosition,
666 const sal_uInt32 nEventCode)
668 if (mpModeHandler->GetMode() != MultiSelectionMode)
669 SwitchMode(std::make_shared<MultiSelectionModeHandler>(mrSlideSorter, *this, rMousePosition, nEventCode));
672 void SelectionFunction::SwitchMode (const std::shared_ptr<ModeHandler>& rpHandler)
674 // Not all modes allow mouse over indicator.
675 if (mpModeHandler->IsMouseOverIndicatorAllowed() != rpHandler->IsMouseOverIndicatorAllowed())
677 if ( ! rpHandler->IsMouseOverIndicatorAllowed())
679 mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
681 else
682 mrSlideSorter.GetView().UpdatePageUnderMouse();
685 mpModeHandler = rpHandler;
688 void SelectionFunction::ResetShiftKeySelectionAnchor()
690 mnShiftKeySelectionAnchor = -1;
693 void SelectionFunction::ResetMouseAnchor()
695 if (mpModeHandler && mpModeHandler->GetMode() == NormalMode)
697 std::shared_ptr<NormalModeHandler> pHandler (
698 std::dynamic_pointer_cast<NormalModeHandler>(mpModeHandler));
699 if (pHandler)
700 pHandler->ResetButtonDownLocation();
704 //===== EventDescriptor =======================================================
706 SelectionFunction::EventDescriptor::EventDescriptor (
707 const sal_uInt32 nEventType,
708 const MouseEvent& rEvent,
709 SlideSorter const & rSlideSorter)
710 : maMousePosition(rEvent.GetPosPixel()),
711 mpHitPage(),
712 mnEventCode(nEventType),
713 meDragMode(InsertionIndicatorHandler::MoveMode),
714 mbIsLeaving(false)
716 maMouseModelPosition = rSlideSorter.GetContentWindow()->PixelToLogic(maMousePosition);
717 mpHitDescriptor = rSlideSorter.GetController().GetPageAt(maMousePosition);
718 if (mpHitDescriptor)
720 mpHitPage = mpHitDescriptor->GetPage();
723 mnEventCode |= EncodeMouseEvent(rEvent);
724 mnEventCode |= EncodeState();
726 // Detect the mouse leaving the window. When not button is pressed then
727 // we can call IsLeaveWindow at the event. Otherwise we have to make an
728 // explicit test.
729 mbIsLeaving = rEvent.IsLeaveWindow()
730 || ! ::tools::Rectangle(Point(0,0),
731 rSlideSorter.GetContentWindow()->GetOutputSizePixel()).Contains(maMousePosition);
734 SelectionFunction::EventDescriptor::EventDescriptor (
735 const sal_uInt32 nEventType,
736 const AcceptDropEvent& rEvent,
737 const sal_Int8 nDragAction,
738 SlideSorter const & rSlideSorter)
739 : maMousePosition(rEvent.maPosPixel),
740 mpHitPage(),
741 mnEventCode(nEventType),
742 meDragMode(InsertionIndicatorHandler::GetModeFromDndAction(nDragAction)),
743 mbIsLeaving(false)
745 maMouseModelPosition = rSlideSorter.GetContentWindow()->PixelToLogic(maMousePosition);
746 mpHitDescriptor = rSlideSorter.GetController().GetPageAt(maMousePosition);
747 if (mpHitDescriptor)
749 mpHitPage = mpHitDescriptor->GetPage();
752 mnEventCode |= EncodeState();
754 // Detect the mouse leaving the window. When not button is pressed then
755 // we can call IsLeaveWindow at the event. Otherwise we have to make an
756 // explicit test.
757 mbIsLeaving = rEvent.mbLeaving
758 || ! ::tools::Rectangle(Point(0,0),
759 rSlideSorter.GetContentWindow()->GetOutputSizePixel()).Contains(maMousePosition);
762 sal_uInt32 SelectionFunction::EventDescriptor::EncodeMouseEvent (
763 const MouseEvent& rEvent) const
765 // Initialize with the type of mouse event.
766 sal_uInt32 nEventCode (mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION));
768 // Detect the affected button.
769 switch (rEvent.GetButtons())
771 case MOUSE_LEFT: nEventCode |= LEFT_BUTTON; break;
772 case MOUSE_RIGHT: nEventCode |= RIGHT_BUTTON; break;
773 case MOUSE_MIDDLE: nEventCode |= MIDDLE_BUTTON; break;
776 // Detect the number of clicks.
777 switch (rEvent.GetClicks())
779 case 1: nEventCode |= SINGLE_CLICK; break;
780 case 2: nEventCode |= DOUBLE_CLICK; break;
783 // Detect pressed modifier keys.
784 if (rEvent.IsShift())
785 nEventCode |= SHIFT_MODIFIER;
786 if (rEvent.IsMod1())
787 nEventCode |= CONTROL_MODIFIER;
789 return nEventCode;
792 sal_uInt32 SelectionFunction::EventDescriptor::EncodeState() const
794 sal_uInt32 nEventCode (0);
796 // Detect whether the event has happened over a page object.
797 if (mpHitPage!=nullptr && mpHitDescriptor)
799 if (mpHitDescriptor->HasState(model::PageDescriptor::ST_Selected))
800 nEventCode |= OVER_SELECTED_PAGE;
801 else
802 nEventCode |= OVER_UNSELECTED_PAGE;
805 return nEventCode;
808 //===== SelectionFunction::ModeHandler ========================================
810 SelectionFunction::ModeHandler::ModeHandler (
811 SlideSorter& rSlideSorter,
812 SelectionFunction& rSelectionFunction,
813 const bool bIsMouseOverIndicatorAllowed)
814 : mrSlideSorter(rSlideSorter),
815 mrSelectionFunction(rSelectionFunction),
816 mbIsMouseOverIndicatorAllowed(bIsMouseOverIndicatorAllowed)
820 SelectionFunction::ModeHandler::~ModeHandler() COVERITY_NOEXCEPT_FALSE
824 void SelectionFunction::ModeHandler::ReprocessEvent (EventDescriptor& rDescriptor)
826 mrSelectionFunction.ProcessEvent(rDescriptor);
829 void SelectionFunction::ModeHandler::ProcessEvent (
830 SelectionFunction::EventDescriptor& rDescriptor)
832 PageSelector::BroadcastLock aBroadcastLock (mrSlideSorter);
833 PageSelector::UpdateLock aUpdateLock (mrSlideSorter);
835 bool bIsProcessed (false);
836 switch (rDescriptor.mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION | MOUSE_DRAG))
838 case BUTTON_DOWN:
839 bIsProcessed = ProcessButtonDownEvent(rDescriptor);
840 break;
842 case BUTTON_UP:
843 bIsProcessed = ProcessButtonUpEvent(rDescriptor);
844 break;
846 case MOUSE_MOTION:
847 bIsProcessed = ProcessMotionEvent(rDescriptor);
848 break;
850 case MOUSE_DRAG:
851 bIsProcessed = ProcessDragEvent(rDescriptor);
852 break;
855 if ( ! bIsProcessed)
856 HandleUnprocessedEvent(rDescriptor);
859 bool SelectionFunction::ModeHandler::ProcessButtonDownEvent (EventDescriptor&)
861 return false;
864 bool SelectionFunction::ModeHandler::ProcessButtonUpEvent (EventDescriptor&)
866 mrSelectionFunction.SwitchToNormalMode();
867 return false;
870 bool SelectionFunction::ModeHandler::ProcessMotionEvent (EventDescriptor& rDescriptor)
872 if (mbIsMouseOverIndicatorAllowed)
873 mrSlideSorter.GetView().UpdatePageUnderMouse(rDescriptor.maMousePosition);
875 if (rDescriptor.mbIsLeaving)
877 mrSelectionFunction.SwitchToNormalMode();
878 mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
880 return true;
882 else
883 return false;
886 bool SelectionFunction::ModeHandler::ProcessDragEvent (EventDescriptor&)
888 return false;
891 bool SelectionFunction::ModeHandler::HandleUnprocessedEvent (EventDescriptor&)
893 return false;
896 void SelectionFunction::ModeHandler::SetCurrentPage (
897 const model::SharedPageDescriptor& rpDescriptor)
899 SelectOnePage(rpDescriptor);
900 mrSlideSorter.GetController().GetCurrentSlideManager()->SwitchCurrentSlide(rpDescriptor);
903 void SelectionFunction::ModeHandler::DeselectAllPages()
905 mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
906 mrSelectionFunction.ResetShiftKeySelectionAnchor();
909 void SelectionFunction::ModeHandler::SelectOnePage (
910 const model::SharedPageDescriptor& rpDescriptor)
912 DeselectAllPages();
913 mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
916 void SelectionFunction::ModeHandler::SwitchView (const model::SharedPageDescriptor& rpDescriptor)
918 // Switch to the draw view. This is done only when the current
919 // view is the main view.
920 ViewShell* pViewShell = mrSlideSorter.GetViewShell();
921 if (pViewShell==nullptr || !pViewShell->IsMainViewShell())
922 return;
924 if (rpDescriptor && rpDescriptor->GetPage()!=nullptr)
926 mrSlideSorter.GetModel().GetDocument()->SetSelected(rpDescriptor->GetPage(), true);
927 pViewShell->GetFrameView()->SetSelectedPage(
928 (rpDescriptor->GetPage()->GetPageNum()-1)/2);
930 if (mrSlideSorter.GetViewShellBase() != nullptr)
931 framework::FrameworkHelper::Instance(*mrSlideSorter.GetViewShellBase())->RequestView(
932 framework::FrameworkHelper::msImpressViewURL,
933 framework::FrameworkHelper::msCenterPaneURL);
936 void SelectionFunction::ModeHandler::StartDrag (
937 const Point& rMousePosition)
939 // Do not start a drag-and-drop operation when one is already active.
940 // (when dragging pages from one document into another, pressing a
941 // modifier key can trigger a MouseMotion event in the originating
942 // window (focus still in there). Together with the mouse button pressed
943 // (drag-and-drop is active) this triggers the start of drag-and-drop.)
944 if (SdModule::get()->pTransferDrag != nullptr)
945 return;
947 mrSelectionFunction.SwitchToDragAndDropMode(rMousePosition);
950 //===== NormalModeHandler =====================================================
952 NormalModeHandler::NormalModeHandler (
953 SlideSorter& rSlideSorter,
954 SelectionFunction& rSelectionFunction)
955 : ModeHandler(rSlideSorter, rSelectionFunction, true)
959 SelectionFunction::Mode NormalModeHandler::GetMode() const
961 return SelectionFunction::NormalMode;
964 void NormalModeHandler::Abort()
968 bool NormalModeHandler::ProcessButtonDownEvent (
969 SelectionFunction::EventDescriptor& rDescriptor)
971 // Remember the location where the left button is pressed. With
972 // that we can filter away motion events that are caused by key
973 // presses. We also can tune the minimal motion distance that
974 // triggers a drag-and-drop operation.
975 if ((rDescriptor.mnEventCode & BUTTON_DOWN) != 0)
976 maButtonDownLocation = rDescriptor.maMousePosition;
978 switch (rDescriptor.mnEventCode)
980 case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
981 break;
983 case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | OVER_SELECTED_PAGE:
984 case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | OVER_UNSELECTED_PAGE:
985 // A double click always shows the selected slide in the center
986 // pane in an edit view.
987 SetCurrentPage(rDescriptor.mpHitDescriptor);
988 SwitchView(rDescriptor.mpHitDescriptor);
989 break;
991 case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | SHIFT_MODIFIER:
992 case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | SHIFT_MODIFIER:
993 // Range selection with the shift modifier.
994 RangeSelect(rDescriptor.mpHitDescriptor);
995 break;
997 // Right button for context menu.
998 case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE:
999 case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE:
1000 // Single right click and shift+F10 select as preparation to
1001 // show the context menu. Change the selection only when the
1002 // page under the mouse is not selected. In this case the
1003 // selection is set to this single page. Otherwise the
1004 // selection is not modified.
1005 SetCurrentPage(rDescriptor.mpHitDescriptor);
1006 break;
1008 case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
1009 // Do not change the selection. Just adjust the insertion indicator.
1010 break;
1012 case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE:
1013 case ANY_MODIFIER(BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE):
1014 // Remember the current selection so that when a multi selection
1015 // is started, we can restore the previous selection.
1016 mrSlideSorter.GetModel().SaveCurrentSelection();
1017 DeselectAllPages();
1018 break;
1020 case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | NOT_OVER_PAGE:
1022 // Insert a new slide:
1023 // First of all we need to set the insertion indicator which sets the
1024 // position where the new slide will be inserted.
1025 std::shared_ptr<InsertionIndicatorHandler> pInsertionIndicatorHandler
1026 = mrSlideSorter.GetController().GetInsertionIndicatorHandler();
1028 pInsertionIndicatorHandler->Start(false);
1029 pInsertionIndicatorHandler->UpdatePosition(
1030 rDescriptor.maMousePosition,
1031 InsertionIndicatorHandler::MoveMode);
1033 mrSlideSorter.GetController().GetSelectionManager()->SetInsertionPosition(
1034 pInsertionIndicatorHandler->GetInsertionPageIndex());
1036 mrSlideSorter.GetViewShell()->GetDispatcher()->Execute(
1037 SID_INSERTPAGE,
1038 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD);
1040 pInsertionIndicatorHandler->End(Animator::AM_Immediate);
1042 break;
1045 default:
1046 return false;
1048 return true;
1051 bool NormalModeHandler::ProcessButtonUpEvent (
1052 SelectionFunction::EventDescriptor& rDescriptor)
1054 bool bIsProcessed (true);
1055 switch (rDescriptor.mnEventCode)
1057 case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
1058 SetCurrentPage(rDescriptor.mpHitDescriptor);
1059 break;
1061 // Multi selection with the control modifier.
1062 case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | CONTROL_MODIFIER:
1063 mrSlideSorter.GetController().GetPageSelector().DeselectPage(
1064 rDescriptor.mpHitDescriptor);
1065 break;
1067 case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | CONTROL_MODIFIER:
1068 mrSlideSorter.GetController().GetPageSelector().SelectPage(
1069 rDescriptor.mpHitDescriptor);
1070 mrSlideSorter.GetView().SetPageUnderMouse(rDescriptor.mpHitDescriptor);
1071 break;
1072 case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE:
1073 break;
1075 default:
1076 bIsProcessed = false;
1077 break;
1079 mrSelectionFunction.SwitchToNormalMode();
1080 return bIsProcessed;
1083 bool NormalModeHandler::ProcessMotionEvent (
1084 SelectionFunction::EventDescriptor& rDescriptor)
1086 if (ModeHandler::ProcessMotionEvent(rDescriptor))
1087 return true;
1089 bool bIsProcessed (true);
1090 switch (rDescriptor.mnEventCode)
1092 // A mouse motion without visible substitution starts that.
1093 case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE):
1094 case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE):
1096 if (maButtonDownLocation)
1098 const sal_Int32 nDistance(std::max(
1099 std::abs(maButtonDownLocation->X() - rDescriptor.maMousePosition.X()),
1100 std::abs(maButtonDownLocation->Y() - rDescriptor.maMousePosition.Y())));
1101 if (nDistance > 3)
1102 StartDrag(rDescriptor.maMousePosition);
1104 break;
1107 // A mouse motion not over a page starts a rectangle selection.
1108 case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE):
1109 mrSelectionFunction.SwitchToMultiSelectionMode(
1110 rDescriptor.maMouseModelPosition,
1111 rDescriptor.mnEventCode);
1112 break;
1114 default:
1115 bIsProcessed = false;
1116 break;
1118 return bIsProcessed;
1121 bool NormalModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor)
1123 mrSelectionFunction.SwitchToDragAndDropMode(rDescriptor.maMousePosition);
1124 ReprocessEvent(rDescriptor);
1125 return true;
1128 void NormalModeHandler::RangeSelect (const model::SharedPageDescriptor& rpDescriptor)
1130 PageSelector::UpdateLock aLock (mrSlideSorter);
1131 PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector());
1133 model::SharedPageDescriptor pAnchor (rSelector.GetSelectionAnchor());
1134 DeselectAllPages();
1136 if (!pAnchor)
1137 return;
1139 // Select all pages between the anchor and the given one, including
1140 // the two.
1141 const sal_uInt16 nAnchorIndex ((pAnchor->GetPage()->GetPageNum()-1) / 2);
1142 const sal_uInt16 nOtherIndex ((rpDescriptor->GetPage()->GetPageNum()-1) / 2);
1144 // Iterate over all pages in the range. Start with the anchor
1145 // page. This way the PageSelector will recognize it again as
1146 // anchor (the first selected page after a DeselectAllPages()
1147 // becomes the anchor.)
1148 const sal_Int16 nStep ((nAnchorIndex < nOtherIndex) ? +1 : -1);
1149 sal_uInt16 nIndex (nAnchorIndex);
1150 while (true)
1152 rSelector.SelectPage(nIndex);
1153 if (nIndex == nOtherIndex)
1154 break;
1155 nIndex = nIndex + nStep;
1159 void NormalModeHandler::ResetButtonDownLocation()
1161 maButtonDownLocation = ::std::optional<Point>();
1164 //===== MultiSelectionModeHandler =============================================
1166 MultiSelectionModeHandler::MultiSelectionModeHandler (
1167 SlideSorter& rSlideSorter,
1168 SelectionFunction& rSelectionFunction,
1169 const Point& rMouseModelPosition,
1170 const sal_uInt32 nEventCode)
1171 : ModeHandler(rSlideSorter, rSelectionFunction, false),
1172 meSelectionMode(SM_Normal),
1173 maSecondCorner(rMouseModelPosition),
1174 maSavedPointer(mrSlideSorter.GetContentWindow()->GetPointer()),
1175 mbAutoScrollInstalled(false),
1176 mnAnchorIndex(-1),
1177 mnSecondIndex(-1)
1180 mrSlideSorter.GetContentWindow()->SetPointer(PointerStyle::Text);
1181 SetSelectionModeFromModifier(nEventCode);
1184 MultiSelectionModeHandler::~MultiSelectionModeHandler()
1186 if (mbAutoScrollInstalled)
1188 //a call to this handler's MultiSelectionModeHandler::UpdatePosition
1189 //may be still waiting to be called back
1190 mrSlideSorter.GetController().GetScrollBarManager().clearAutoScrollFunctor();
1192 mrSlideSorter.GetContentWindow()->SetPointer(maSavedPointer);
1195 SelectionFunction::Mode MultiSelectionModeHandler::GetMode() const
1197 return SelectionFunction::MultiSelectionMode;
1200 void MultiSelectionModeHandler::Abort()
1202 mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection());
1205 void MultiSelectionModeHandler::ProcessEvent (
1206 SelectionFunction::EventDescriptor& rDescriptor)
1208 // During a multi selection we do not want sudden jumps of the
1209 // visible area caused by moving newly selected pages into view.
1210 // Therefore disable that temporarily. The disabled object is
1211 // released at the end of the event processing, after the focus and
1212 // current slide have been updated.
1213 VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
1215 ModeHandler::ProcessEvent(rDescriptor);
1218 bool MultiSelectionModeHandler::ProcessButtonUpEvent (
1219 SelectionFunction::EventDescriptor& rDescriptor)
1221 if (mbAutoScrollInstalled)
1223 //a call to this handler's MultiSelectionModeHandler::UpdatePosition
1224 //may be still waiting to be called back
1225 mrSlideSorter.GetController().GetScrollBarManager().clearAutoScrollFunctor();
1226 mbAutoScrollInstalled = false;
1229 if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK))
1231 mrSelectionFunction.SwitchToNormalMode();
1232 return true;
1234 else
1235 return false;
1238 bool MultiSelectionModeHandler::ProcessMotionEvent (
1239 SelectionFunction::EventDescriptor& rDescriptor)
1241 // The selection rectangle is visible. Handle events accordingly.
1242 if (Match(rDescriptor.mnEventCode, MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK))
1244 SetSelectionModeFromModifier(rDescriptor.mnEventCode);
1245 UpdatePosition(rDescriptor.maMousePosition, true);
1246 return true;
1248 else
1249 return false;
1252 bool MultiSelectionModeHandler::HandleUnprocessedEvent (
1253 SelectionFunction::EventDescriptor& rDescriptor)
1255 if ( ! ModeHandler::HandleUnprocessedEvent(rDescriptor))
1257 // If the event has not been processed then stop multi selection.
1258 mrSelectionFunction.SwitchToNormalMode();
1259 ReprocessEvent(rDescriptor);
1261 return true;
1264 void MultiSelectionModeHandler::UpdatePosition (
1265 const Point& rMousePosition,
1266 const bool bAllowAutoScroll)
1268 VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
1270 // Convert window coordinates into model coordinates (we need the
1271 // window coordinates for auto-scrolling because that remains
1272 // constant while scrolling.)
1273 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
1274 const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition));
1276 bool bDoAutoScroll = bAllowAutoScroll && mrSlideSorter.GetController().GetScrollBarManager().AutoScroll(
1277 rMousePosition,
1278 [this, &rMousePosition] () { return this->UpdatePosition(rMousePosition, false); });
1280 if (!bDoAutoScroll)
1281 UpdateModelPosition(aMouseModelPosition);
1283 mbAutoScrollInstalled |= bDoAutoScroll;
1286 void MultiSelectionModeHandler::SetSelectionModeFromModifier (
1287 const sal_uInt32 nEventCode)
1289 switch (nEventCode & MODIFIER_MASK)
1291 case NO_MODIFIER:
1292 SetSelectionMode(SM_Normal);
1293 break;
1295 case SHIFT_MODIFIER:
1296 SetSelectionMode(SM_Add);
1297 break;
1299 case CONTROL_MODIFIER:
1300 SetSelectionMode(SM_Toggle);
1301 break;
1305 void MultiSelectionModeHandler::SetSelectionMode (const SelectionMode eSelectionMode)
1307 if (meSelectionMode != eSelectionMode)
1309 meSelectionMode = eSelectionMode;
1310 UpdateSelection();
1314 void MultiSelectionModeHandler::UpdateSelectionState (
1315 const model::SharedPageDescriptor& rpDescriptor,
1316 const bool bIsInSelection) const
1318 // Determine whether the page was selected before the rectangle
1319 // selection was started.
1320 const bool bWasSelected (rpDescriptor->HasState(model::PageDescriptor::ST_WasSelected));
1322 // Combine the two selection states depending on the selection mode.
1323 bool bSelect (false);
1324 switch(meSelectionMode)
1326 case SM_Normal:
1327 bSelect = bIsInSelection;
1328 break;
1330 case SM_Add:
1331 bSelect = bIsInSelection || bWasSelected;
1332 break;
1334 case SM_Toggle:
1335 if (bIsInSelection)
1336 bSelect = !bWasSelected;
1337 else
1338 bSelect = bWasSelected;
1339 break;
1342 // Set the new selection state.
1343 if (bSelect)
1344 mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
1345 else
1346 mrSlideSorter.GetController().GetPageSelector().DeselectPage(rpDescriptor);
1349 void MultiSelectionModeHandler::UpdateModelPosition (const Point& rMouseModelPosition)
1351 maSecondCorner = rMouseModelPosition;
1352 UpdateSelection();
1355 void MultiSelectionModeHandler::UpdateSelection()
1357 view::SlideSorterView::DrawLock aLock (mrSlideSorter);
1359 model::SlideSorterModel& rModel (mrSlideSorter.GetModel());
1360 const sal_Int32 nPageCount (rModel.GetPageCount());
1362 const sal_Int32 nIndexUnderMouse (
1363 mrSlideSorter.GetView().GetLayouter().GetIndexAtPoint (
1364 maSecondCorner,
1365 false,
1366 false));
1367 if (nIndexUnderMouse < 0 || nIndexUnderMouse >= nPageCount)
1368 return;
1370 if (mnAnchorIndex < 0)
1371 mnAnchorIndex = nIndexUnderMouse;
1372 mnSecondIndex = nIndexUnderMouse;
1374 Range aRange (mnAnchorIndex, mnSecondIndex);
1375 aRange.Normalize();
1377 for (sal_Int32 nIndex=0; nIndex<nPageCount; ++nIndex)
1379 UpdateSelectionState(rModel.GetPageDescriptor(nIndex), aRange.Contains(nIndex));
1383 //===== DragAndDropModeHandler ================================================
1385 DragAndDropModeHandler::DragAndDropModeHandler (
1386 SlideSorter& rSlideSorter,
1387 SelectionFunction& rSelectionFunction,
1388 const Point& rMousePosition,
1389 vcl::Window* pWindow)
1390 : ModeHandler(rSlideSorter, rSelectionFunction, false)
1392 SdModule* mod = SdModule::get();
1393 SdTransferable* pDragTransferable = mod->pTransferDrag;
1394 if (pDragTransferable==nullptr && mrSlideSorter.GetViewShell() != nullptr)
1396 SlideSorterViewShell* pSlideSorterViewShell
1397 = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell());
1398 if (pSlideSorterViewShell != nullptr)
1399 pSlideSorterViewShell->StartDrag(rMousePosition, pWindow);
1400 pDragTransferable = mod->pTransferDrag;
1403 mpDragAndDropContext.reset(new DragAndDropContext(mrSlideSorter));
1404 mrSlideSorter.GetController().GetInsertionIndicatorHandler()->Start(
1405 pDragTransferable != nullptr
1406 && pDragTransferable->GetView()==&mrSlideSorter.GetView());
1409 DragAndDropModeHandler::~DragAndDropModeHandler()
1411 if (mpDragAndDropContext)
1413 // Disconnect the substitution handler from this selection function.
1414 mpDragAndDropContext->SetTargetSlideSorter();
1415 mpDragAndDropContext.reset();
1417 mrSlideSorter.GetController().GetInsertionIndicatorHandler()->End(Animator::AM_Animated);
1420 SelectionFunction::Mode DragAndDropModeHandler::GetMode() const
1422 return SelectionFunction::DragAndDropMode;
1425 void DragAndDropModeHandler::Abort()
1427 mrSlideSorter.GetController().GetClipboard().Abort();
1428 if (mpDragAndDropContext)
1429 mpDragAndDropContext->Dispose();
1430 // mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection());
1433 bool DragAndDropModeHandler::ProcessButtonUpEvent (
1434 SelectionFunction::EventDescriptor& rDescriptor)
1436 if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON))
1438 // The following Process() call may lead to the destruction
1439 // of rDescriptor.mpHitDescriptor so release our reference to it.
1440 rDescriptor.mpHitDescriptor.reset();
1441 mrSelectionFunction.SwitchToNormalMode();
1442 return true;
1444 else
1445 return false;
1448 bool DragAndDropModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor)
1450 OSL_ASSERT(mpDragAndDropContext);
1452 if (rDescriptor.mbIsLeaving)
1454 mrSelectionFunction.SwitchToNormalMode();
1456 else if (mpDragAndDropContext)
1458 mpDragAndDropContext->UpdatePosition(
1459 rDescriptor.maMousePosition,
1460 rDescriptor.meDragMode, true);
1463 return true;
1466 } // end of namespace ::sd::slidesorter::controller
1468 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */