xref: /AOO41X/main/sd/source/ui/slidesorter/controller/SlsSelectionFunction.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "precompiled_sd.hxx"
29 
30 #include "controller/SlsSelectionFunction.hxx"
31 
32 #include "SlideSorter.hxx"
33 #include "SlideSorterViewShell.hxx"
34 #include "SlsDragAndDropContext.hxx"
35 #include "controller/SlsTransferableData.hxx"
36 #include "controller/SlideSorterController.hxx"
37 #include "controller/SlsPageSelector.hxx"
38 #include "controller/SlsFocusManager.hxx"
39 #include "controller/SlsScrollBarManager.hxx"
40 #include "controller/SlsClipboard.hxx"
41 #include "controller/SlsCurrentSlideManager.hxx"
42 #include "controller/SlsInsertionIndicatorHandler.hxx"
43 #include "controller/SlsSelectionManager.hxx"
44 #include "controller/SlsProperties.hxx"
45 #include "controller/SlsProperties.hxx"
46 #include "controller/SlsSlotManager.hxx"
47 #include "controller/SlsVisibleAreaManager.hxx"
48 #include "model/SlideSorterModel.hxx"
49 #include "model/SlsPageDescriptor.hxx"
50 #include "model/SlsPageEnumerationProvider.hxx"
51 #include "view/SlideSorterView.hxx"
52 #include "view/SlsLayouter.hxx"
53 #include "view/SlsPageObjectLayouter.hxx"
54 #include "view/SlsButtonBar.hxx"
55 #include "framework/FrameworkHelper.hxx"
56 #include "ViewShellBase.hxx"
57 #include "DrawController.hxx"
58 #include "Window.hxx"
59 #include "sdpage.hxx"
60 #include "drawdoc.hxx"
61 #include "DrawDocShell.hxx"
62 #include "sdxfer.hxx"
63 #include "ViewShell.hxx"
64 #include "ViewShellBase.hxx"
65 #include "FrameView.hxx"
66 #include "app.hrc"
67 #include "sdresid.hxx"
68 #include "strings.hrc"
69 #include <vcl/sound.hxx>
70 #include <sfx2/viewfrm.hxx>
71 #include <sfx2/dispatch.hxx>
72 #include <svx/svdpagv.hxx>
73 #include <vcl/msgbox.hxx>
74 #include <svx/svxids.hrc>
75 #include <boost/bind.hpp>
76 #include <boost/optional.hpp>
77 
78 namespace {
79 static const sal_uInt32 SINGLE_CLICK             (0x00000001);
80 static const sal_uInt32 DOUBLE_CLICK             (0x00000002);
81 static const sal_uInt32 LEFT_BUTTON              (0x00000010);
82 static const sal_uInt32 RIGHT_BUTTON             (0x00000020);
83 static const sal_uInt32 MIDDLE_BUTTON            (0x00000040);
84 static const sal_uInt32 BUTTON_DOWN              (0x00000100);
85 static const sal_uInt32 BUTTON_UP                (0x00000200);
86 static const sal_uInt32 MOUSE_MOTION             (0x00000400);
87 static const sal_uInt32 MOUSE_DRAG               (0x00000800);
88 // The rest leaves the lower 16 bit untouched so that it can be used with
89 // key codes.
90 static const sal_uInt32 OVER_SELECTED_PAGE       (0x00010000);
91 static const sal_uInt32 OVER_UNSELECTED_PAGE     (0x00020000);
92 static const sal_uInt32 OVER_FADE_INDICATOR      (0x00040000);
93 static const sal_uInt32 OVER_BUTTON_AREA         (0x00080000);
94 static const sal_uInt32 OVER_BUTTON              (0x00100000);
95 static const sal_uInt32 SHIFT_MODIFIER           (0x00200000);
96 static const sal_uInt32 CONTROL_MODIFIER         (0x00400000);
97 
98 static const sal_uInt32 KEY_EVENT                (0x10000000);
99 
100 // Some absent events are defined so they can be expressed explicitly.
101 static const sal_uInt32 NO_MODIFIER              (0x00000000);
102 static const sal_uInt32 NOT_OVER_PAGE            (0x00000000);
103 
104 // Masks
105 static const sal_uInt32 MODIFIER_MASK            (SHIFT_MODIFIER | CONTROL_MODIFIER);
106 static const sal_uInt32 BUTTON_MASK              (LEFT_BUTTON | RIGHT_BUTTON | MIDDLE_BUTTON);
107 
108 } // end of anonymous namespace
109 
110 
111 
112 // Define some macros to make the following switch statement more readable.
113 #define ANY_MODIFIER(code)                  \
114          code|NO_MODIFIER:                  \
115     case code|SHIFT_MODIFIER:               \
116     case code|CONTROL_MODIFIER
117 
118 namespace sd { namespace slidesorter { namespace controller {
119 
120 //===== SelectionFunction::EventDescriptor ====================================
121 
122 class SelectionFunction::EventDescriptor
123 {
124 public:
125     Point maMousePosition;
126     Point maMouseModelPosition;
127     model::SharedPageDescriptor mpHitDescriptor;
128     SdrPage* mpHitPage;
129     sal_uInt32 mnEventCode;
130     bool mbIsOverButton;
131     InsertionIndicatorHandler::Mode meDragMode;
132     bool mbMakeSelectionVisible;
133     bool mbIsLeaving;
134 
135     EventDescriptor (
136         sal_uInt32 nEventType,
137         const MouseEvent& rEvent,
138         SlideSorter& rSlideSorter);
139     EventDescriptor (
140         sal_uInt32 nEventType,
141         const AcceptDropEvent& rEvent,
142         const sal_Int8 nDragAction,
143         SlideSorter& rSlideSorter);
144     EventDescriptor (
145         const KeyEvent& rEvent,
146         SlideSorter& rSlideSorter);
147 
148     void SetDragMode (const InsertionIndicatorHandler::Mode eMode);
149 
150 private:
151     /** Compute a numerical code that describes a mouse event and that can
152         be used for fast look up of the appropriate reaction.
153     */
154     sal_uInt32 EncodeMouseEvent (const MouseEvent& rEvent) const;
155 
156     /** Compute a numerical code that describes a key event and that can
157         be used for fast look up of the appropriate reaction.
158     */
159     sal_uInt32 EncodeKeyEvent (const KeyEvent& rEvent) const;
160 
161     /** Compute a numerical code that describes the current state like
162         whether the selection rectangle is visible or whether the page under
163         the mouse or the one that has the focus is selected.
164     */
165     sal_uInt32 EncodeState (void) const;
166 };
167 
168 
169 
170 
171 //===== SelectionFunction::ModeHandler ========================================
172 
173 class SelectionFunction::ModeHandler
174 {
175 public:
176     ModeHandler (
177         SlideSorter& rSlideSorter,
178         SelectionFunction& rSelectionFunction,
179         const bool bIsMouseOverIndicatorAllowed);
180     virtual ~ModeHandler (void);
181 
182     virtual Mode GetMode (void) const = 0;
183     virtual void Abort (void) = 0;
184     virtual void ProcessEvent (EventDescriptor& rDescriptor);
185 
186     /** Set the selection to exactly the specified page and also set it as
187         the current page.
188     */
189     void SetCurrentPage (const model::SharedPageDescriptor& rpDescriptor);
190 
191     /// Deselect all pages.
192     void DeselectAllPages (void);
193     void SelectOnePage (const model::SharedPageDescriptor& rpDescriptor);
194 
195         /** When the view on which this selection function is working is the
196         main view then the view is switched to the regular editing view.
197     */
198     void SwitchView (const model::SharedPageDescriptor& rpDescriptor);
199 
200     void StartDrag (
201         const Point& rMousePosition,
202         const InsertionIndicatorHandler::Mode eMode);
203 
204     bool IsMouseOverIndicatorAllowed (void) const;
205 
206 protected:
207     SlideSorter& mrSlideSorter;
208     SelectionFunction& mrSelectionFunction;
209 
210     virtual bool ProcessButtonDownEvent (EventDescriptor& rDescriptor);
211     virtual bool ProcessButtonUpEvent (EventDescriptor& rDescriptor);
212     virtual bool ProcessMotionEvent (EventDescriptor& rDescriptor);
213     virtual bool ProcessDragEvent (EventDescriptor& rDescriptor);
214     virtual bool HandleUnprocessedEvent (EventDescriptor& rDescriptor);
215 
216     void ReprocessEvent (EventDescriptor& rDescriptor);
217 
218 private:
219     const bool mbIsMouseOverIndicatorAllowed;
220 };
221 
222 
223 /** This is the default handler for processing events.  It activates the
224     multi selection or drag-and-drop when the right conditions are met.
225 */
226 class NormalModeHandler : public SelectionFunction::ModeHandler
227 {
228 public:
229     NormalModeHandler (
230         SlideSorter& rSlideSorter,
231         SelectionFunction& rSelectionFunction);
232     virtual ~NormalModeHandler (void);
233 
234     virtual SelectionFunction::Mode GetMode (void) const;
235     virtual void Abort (void);
236 
237     void ResetButtonDownLocation (void);
238 
239 protected:
240     virtual bool ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor);
241     virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor);
242     virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor);
243     virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor);
244 
245 private:
246     ::boost::optional<Point> maButtonDownLocation;
247 
248     /** Select all pages between and including the selection anchor and the
249         specified page.
250     */
251     void RangeSelect (const model::SharedPageDescriptor& rpDescriptor);
252 };
253 
254 
255 /** Handle events during a multi selection, which typically is started by
256     pressing the left mouse button when not over a page.
257 */
258 class MultiSelectionModeHandler : public SelectionFunction::ModeHandler
259 {
260 public:
261     /** Start a rectangle selection at the given position.
262     */
263     MultiSelectionModeHandler (
264         SlideSorter& rSlideSorter,
265         SelectionFunction& rSelectionFunction,
266         const Point& rMouseModelPosition,
267         const sal_uInt32 nEventCode);
268     virtual ~MultiSelectionModeHandler (void);
269 
270     virtual SelectionFunction::Mode GetMode (void) const;
271     virtual void Abort (void);
272     virtual void ProcessEvent (SelectionFunction::EventDescriptor& rDescriptor);
273 
274     enum SelectionMode { SM_Normal, SM_Add, SM_Toggle };
275 
276     void SetSelectionMode (const SelectionMode eSelectionMode);
277     void SetSelectionModeFromModifier (const sal_uInt32 nEventCode);
278 
279 protected:
280     virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor);
281     virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor);
282     virtual bool HandleUnprocessedEvent (SelectionFunction::EventDescriptor& rDescriptor);
283 
284 private:
285     SelectionMode meSelectionMode;
286     Point maSecondCorner;
287     Pointer maSavedPointer;
288     sal_Int32 mnAnchorIndex;
289     sal_Int32 mnSecondIndex;
290     view::ButtonBar::Lock maButtonBarLock;
291 
292     virtual void UpdateModelPosition (const Point& rMouseModelPosition);
293     virtual void UpdateSelection (void);
294 
295     /** Update the rectangle selection so that the given position becomes
296         the new second point of the selection rectangle.
297     */
298     void UpdatePosition (
299         const Point& rMousePosition,
300         const bool bAllowAutoScroll);
301 
302     void UpdateSelectionState (
303         const model::SharedPageDescriptor& rpDescriptor,
304         const bool bIsInSelection) const;
305 };
306 
307 
308 /** Handle events during drag-and-drop.
309 */
310 class DragAndDropModeHandler : public SelectionFunction::ModeHandler
311 {
312 public:
313     DragAndDropModeHandler (
314         SlideSorter& rSlideSorter,
315         SelectionFunction& rSelectionFunction,
316         const Point& rMousePosition,
317         ::Window* pWindow);
318     virtual ~DragAndDropModeHandler (void);
319 
320     virtual SelectionFunction::Mode GetMode (void) const;
321     virtual void Abort (void);
322 
323 protected:
324     virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor);
325     virtual bool ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor);
326 
327 private:
328     ::boost::scoped_ptr<DragAndDropContext> mpDragAndDropContext;
329 };
330 
331 
332 /** Handle events while the left mouse button is pressed over the button
333     bar.
334 */
335 class ButtonModeHandler : public SelectionFunction::ModeHandler
336 {
337 public:
338     ButtonModeHandler (
339         SlideSorter& rSlideSorter,
340         SelectionFunction& rSelectionFunction);
341     virtual ~ButtonModeHandler (void);
342     virtual void Abort (void);
343 
344     virtual SelectionFunction::Mode GetMode (void) const;
345 
346 protected:
347     virtual bool ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor);
348     virtual bool ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor);
349     virtual bool ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor);
350 };
351 
352 
353 
354 
355 //===== SelectionFunction =====================================================
356 
357 TYPEINIT1(SelectionFunction, FuPoor);
358 
359 
360 SelectionFunction::SelectionFunction (
361     SlideSorter& rSlideSorter,
362     SfxRequest& rRequest)
363     : FuPoor (
364         rSlideSorter.GetViewShell(),
365         rSlideSorter.GetContentWindow().get(),
366         &rSlideSorter.GetView(),
367         rSlideSorter.GetModel().GetDocument(),
368         rRequest),
369       mrSlideSorter(rSlideSorter),
370       mrController(mrSlideSorter.GetController()),
371       mbDragSelection(false),
372       maInsertionMarkerBox(),
373       mbProcessingMouseButtonDown(false),
374       mnShiftKeySelectionAnchor(-1),
375       mpModeHandler(new NormalModeHandler(rSlideSorter, *this))
376 {
377 }
378 
379 
380 
381 
382 SelectionFunction::~SelectionFunction (void)
383 {
384     mpModeHandler.reset();
385 }
386 
387 
388 
389 
390 FunctionReference SelectionFunction::Create(
391     SlideSorter& rSlideSorter,
392     SfxRequest& rRequest)
393 {
394 	FunctionReference xFunc( new SelectionFunction( rSlideSorter, rRequest ) );
395 	return xFunc;
396 }
397 
398 
399 
400 
401 sal_Bool SelectionFunction::MouseButtonDown (const MouseEvent& rEvent)
402 {
403 	// #95491# remember button state for creation of own MouseEvents
404 	SetMouseButtonCode (rEvent.GetButtons());
405     aMDPos = rEvent.GetPosPixel();
406     mbProcessingMouseButtonDown = true;
407 
408     //	mpWindow->CaptureMouse();
409 
410     ProcessMouseEvent(BUTTON_DOWN, rEvent);
411 
412 	return sal_True;
413 }
414 
415 
416 
417 
418 sal_Bool SelectionFunction::MouseMove (const MouseEvent& rEvent)
419 {
420     ProcessMouseEvent(MOUSE_MOTION, rEvent);
421 	return sal_True;
422 }
423 
424 
425 
426 
427 sal_Bool SelectionFunction::MouseButtonUp (const MouseEvent& rEvent)
428 {
429     mrController.GetScrollBarManager().StopAutoScroll ();
430 
431     ProcessMouseEvent(BUTTON_UP, rEvent);
432 
433     mbProcessingMouseButtonDown = false;
434 //    mpWindow->ReleaseMouse();
435 
436 	return sal_True;
437 }
438 
439 
440 
441 
442 void SelectionFunction::NotifyDragFinished (void)
443 {
444     SwitchToNormalMode();
445 }
446 
447 
448 
449 
450 sal_Bool SelectionFunction::KeyInput (const KeyEvent& rEvent)
451 {
452     view::SlideSorterView::DrawLock aDrawLock (mrSlideSorter);
453     PageSelector::UpdateLock aLock (mrSlideSorter);
454     FocusManager& rFocusManager (mrController.GetFocusManager());
455 	sal_Bool bResult = sal_False;
456 
457     const KeyCode& rCode (rEvent.GetKeyCode());
458 	switch (rCode.GetCode())
459 	{
460         case KEY_RETURN:
461         {
462             model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor());
463             ViewShell* pViewShell = mrSlideSorter.GetViewShell();
464             if (rFocusManager.HasFocus() && pDescriptor && pViewShell!=NULL)
465             {
466                 // The Return key triggers different functions depending on
467                 // whether the slide sorter is the main view or displayed in
468                 // the right pane.
469                 if (pViewShell->IsMainViewShell())
470                 {
471                     mpModeHandler->SetCurrentPage(pDescriptor);
472                     mpModeHandler->SwitchView(pDescriptor);
473                 }
474                 else
475                 {
476                     pViewShell->GetDispatcher()->Execute(
477                         SID_INSERTPAGE,
478                         SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD);
479                 }
480 		        bResult = sal_True;
481             }
482             break;
483         }
484 
485         case KEY_TAB:
486             if ( ! rFocusManager.IsFocusShowing())
487             {
488                 rFocusManager.ShowFocus();
489                 bResult = sal_True;
490             }
491             break;
492 
493 		case KEY_ESCAPE:
494             // When there is an active multiselection or drag-and-drop
495             // operation then stop that.
496             mpModeHandler->Abort();
497             SwitchToNormalMode();
498             bResult = sal_True;
499             break;
500 
501         case KEY_SPACE:
502         {
503             // Toggle the selection state.
504             model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor());
505             if (pDescriptor && rCode.IsMod1())
506             {
507                 if (pDescriptor->HasState(model::PageDescriptor::ST_Selected))
508                     mrController.GetPageSelector().DeselectPage(pDescriptor, false);
509                 else
510                     mrController.GetPageSelector().SelectPage(pDescriptor);
511             }
512             bResult = sal_True;
513         }
514         break;
515 
516 
517         // Move the focus indicator left.
518 		case KEY_LEFT:
519             MoveFocus(FocusManager::FMD_LEFT, rCode.IsShift(), rCode.IsMod1());
520             bResult = sal_True;
521             break;
522 
523         // Move the focus indicator right.
524 		case KEY_RIGHT:
525             MoveFocus(FocusManager::FMD_RIGHT, rCode.IsShift(), rCode.IsMod1());
526             bResult = sal_True;
527             break;
528 
529         // Move the focus indicator up.
530 		case KEY_UP:
531             MoveFocus(FocusManager::FMD_UP, rCode.IsShift(), rCode.IsMod1());
532             bResult = sal_True;
533             break;
534 
535         // Move the focus indicator down.
536 		case KEY_DOWN:
537             MoveFocus(FocusManager::FMD_DOWN, rCode.IsShift(), rCode.IsMod1());
538             bResult = sal_True;
539             break;
540 
541         // Go to previous page.  No wrap around.
542 		case KEY_PAGEUP:
543             GotoNextPage(-1);
544             bResult = sal_True;
545             break;
546 
547         // Go to next page.  No wrap around..
548 		case KEY_PAGEDOWN:
549             GotoNextPage(+1);
550             bResult = sal_True;
551             break;
552 
553         case KEY_HOME:
554             GotoPage(0);
555             bResult = sal_True;
556             break;
557 
558         case KEY_END:
559             GotoPage(mrSlideSorter.GetModel().GetPageCount()-1);
560             bResult = sal_True;
561             break;
562 
563         case KEY_DELETE:
564         case KEY_BACKSPACE:
565         {
566             if (mrSlideSorter.GetProperties()->IsUIReadOnly())
567                 break;
568 
569             mrController.GetSelectionManager()->DeleteSelectedPages(rCode.GetCode()==KEY_DELETE);
570 
571             mnShiftKeySelectionAnchor = -1;
572             bResult = sal_True;
573         }
574         break;
575 
576         case KEY_F10:
577             if (rCode.IsShift())
578             {
579                 mpModeHandler->SelectOnePage(
580                     mrSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor());
581             }
582             break;
583 
584         default:
585             break;
586 	}
587 
588     if ( ! bResult)
589         bResult = FuPoor::KeyInput(rEvent);
590 
591 	return bResult;
592 }
593 
594 
595 
596 
597 void SelectionFunction::MoveFocus (
598     const FocusManager::FocusMoveDirection eDirection,
599     const bool bIsShiftDown,
600     const bool bIsControlDown)
601 {
602     // Remember the anchor of shift key multi selection.
603     if (bIsShiftDown)
604     {
605         if (mnShiftKeySelectionAnchor<0)
606         {
607             model::SharedPageDescriptor pFocusedDescriptor (
608                 mrController.GetFocusManager().GetFocusedPageDescriptor());
609             mnShiftKeySelectionAnchor = pFocusedDescriptor->GetPageIndex();
610         }
611     }
612     else if ( ! bIsControlDown)
613         ResetShiftKeySelectionAnchor();
614 
615     mrController.GetFocusManager().MoveFocus(eDirection);
616 
617     PageSelector& rSelector (mrController.GetPageSelector());
618     model::SharedPageDescriptor pFocusedDescriptor (
619         mrController.GetFocusManager().GetFocusedPageDescriptor());
620     if (bIsShiftDown)
621     {
622         // When shift is pressed then select all pages in the range between
623         // the currently and the previously focused pages, including them.
624         if (pFocusedDescriptor)
625         {
626             sal_Int32 nPageRangeEnd (pFocusedDescriptor->GetPageIndex());
627             model::PageEnumeration aPages (
628                 model::PageEnumerationProvider::CreateAllPagesEnumeration(
629                     mrSlideSorter.GetModel()));
630             while (aPages.HasMoreElements())
631             {
632                 model::SharedPageDescriptor pDescriptor (aPages.GetNextElement());
633                 if (pDescriptor)
634                 {
635                     const sal_Int32 nPageIndex(pDescriptor->GetPageIndex());
636                     if ((nPageIndex>=mnShiftKeySelectionAnchor && nPageIndex<=nPageRangeEnd)
637                         || (nPageIndex<=mnShiftKeySelectionAnchor && nPageIndex>=nPageRangeEnd))
638                     {
639                         rSelector.SelectPage(pDescriptor);
640                     }
641                     else
642                     {
643                         rSelector.DeselectPage(pDescriptor);
644                     }
645                 }
646             }
647         }
648     }
649     else if (bIsControlDown)
650     {
651         // When control is pressed then do not alter the selection or the
652         // current page, just move the focus.
653     }
654     else
655     {
656         // Without shift just select the focused page.
657         mpModeHandler->SelectOnePage(pFocusedDescriptor);
658     }
659 }
660 
661 
662 
663 
664 void SelectionFunction::Activate()
665 {
666 	FuPoor::Activate();
667 }
668 
669 
670 
671 
672 void SelectionFunction::Deactivate()
673 {
674 	FuPoor::Deactivate();
675 }
676 
677 
678 
679 void SelectionFunction::ScrollStart (void)
680 {
681 }
682 
683 
684 
685 
686 void SelectionFunction::ScrollEnd (void)
687 {
688 }
689 
690 
691 
692 
693 void SelectionFunction::DoCut (void)
694 {
695     if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly())
696     {
697         mrController.GetClipboard().DoCut();
698     }
699 }
700 
701 
702 
703 
704 void SelectionFunction::DoCopy (void)
705 {
706     mrController.GetClipboard().DoCopy();
707 }
708 
709 
710 
711 
712 void SelectionFunction::DoPaste (void)
713 {
714     if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly())
715     {
716         mrController.GetClipboard().DoPaste();
717     }
718 }
719 
720 
721 
722 
723 bool SelectionFunction::cancel (void)
724 {
725     mrController.GetFocusManager().ToggleFocus();
726     return true;
727 }
728 
729 
730 
731 
732 void SelectionFunction::GotoNextPage (int nOffset)
733 {
734     model::SharedPageDescriptor pDescriptor
735         = mrController.GetCurrentSlideManager()->GetCurrentSlide();
736     if (pDescriptor.get() != NULL)
737     {
738         SdPage* pPage = pDescriptor->GetPage();
739         OSL_ASSERT(pPage!=NULL);
740         sal_Int32 nIndex = (pPage->GetPageNum()-1) / 2;
741         GotoPage(nIndex + nOffset);
742     }
743     ResetShiftKeySelectionAnchor();
744 }
745 
746 
747 
748 
749 void SelectionFunction::GotoPage (int nIndex)
750 {
751     sal_uInt16 nPageCount = (sal_uInt16)mrSlideSorter.GetModel().GetPageCount();
752 
753     if (nIndex >= nPageCount)
754         nIndex = nPageCount - 1;
755     if (nIndex < 0)
756         nIndex = 0;
757 
758     mrController.GetFocusManager().SetFocusedPage(nIndex);
759     model::SharedPageDescriptor pNextPageDescriptor (
760         mrSlideSorter.GetModel().GetPageDescriptor (nIndex));
761     if (pNextPageDescriptor.get() != NULL)
762         mpModeHandler->SetCurrentPage(pNextPageDescriptor);
763     else
764     {
765         OSL_ASSERT(pNextPageDescriptor.get() != NULL);
766     }
767     ResetShiftKeySelectionAnchor();
768 }
769 
770 
771 
772 
773 void SelectionFunction::ProcessMouseEvent (sal_uInt32 nEventType, const MouseEvent& rEvent)
774 {
775 	// #95491# remember button state for creation of own MouseEvents
776 	SetMouseButtonCode (rEvent.GetButtons());
777 
778     EventDescriptor aEventDescriptor (nEventType, rEvent, mrSlideSorter);
779     ProcessEvent(aEventDescriptor);
780 }
781 
782 
783 
784 
785 void SelectionFunction::MouseDragged (
786     const AcceptDropEvent& rEvent,
787     const sal_Int8 nDragAction)
788 {
789     EventDescriptor aEventDescriptor (MOUSE_DRAG, rEvent, nDragAction, mrSlideSorter);
790     ProcessEvent(aEventDescriptor);
791 }
792 
793 
794 
795 
796 void SelectionFunction::ProcessKeyEvent (const KeyEvent& rEvent)
797 {
798     EventDescriptor aEventDescriptor (rEvent, mrSlideSorter);
799     ProcessEvent(aEventDescriptor);
800 }
801 
802 
803 
804 
805 void SelectionFunction::ProcessEvent (EventDescriptor& rDescriptor)
806 {
807     // The call to ProcessEvent may switch to another mode handler.
808     // Prevent the untimely destruction of the called handler  by aquiring a
809     // temporary reference here.
810     ::boost::shared_ptr<ModeHandler> pModeHandler (mpModeHandler);
811     pModeHandler->ProcessEvent(rDescriptor);
812 }
813 
814 
815 
816 
817 bool Match (
818     const sal_uInt32 nEventCode,
819     const sal_uInt32 nPositivePattern)
820 {
821     return (nEventCode & nPositivePattern)==nPositivePattern;
822 }
823 
824 
825 
826 
827 void SelectionFunction::SwitchToNormalMode (void)
828 {
829     if (mpModeHandler->GetMode() != NormalMode)
830         SwitchMode(::boost::shared_ptr<ModeHandler>(
831             new NormalModeHandler(mrSlideSorter, *this)));
832 }
833 
834 
835 
836 
837 void SelectionFunction::SwitchToDragAndDropMode (const Point aMousePosition)
838 {
839     if (mpModeHandler->GetMode() != DragAndDropMode)
840     {
841         SwitchMode(::boost::shared_ptr<ModeHandler>(
842             new DragAndDropModeHandler(mrSlideSorter, *this, aMousePosition, mpWindow)));
843     }
844 }
845 
846 
847 
848 
849 void SelectionFunction::SwitchToMultiSelectionMode (
850     const Point aMousePosition,
851     const sal_uInt32 nEventCode)
852 {
853     if (mpModeHandler->GetMode() != MultiSelectionMode)
854         SwitchMode(::boost::shared_ptr<ModeHandler>(
855             new MultiSelectionModeHandler(mrSlideSorter, *this, aMousePosition, nEventCode)));
856 }
857 
858 
859 
860 
861 bool SelectionFunction::SwitchToButtonMode (void)
862 {
863     // Do not show the buttons for draw pages.
864     ::boost::shared_ptr<ViewShell> pMainViewShell (mrSlideSorter.GetViewShellBase()->GetMainViewShell());
865     if (pMainViewShell
866         && pMainViewShell->GetShellType()!=ViewShell::ST_DRAW
867         && mpModeHandler->GetMode() != ButtonMode)
868     {
869         SwitchMode(::boost::shared_ptr<ModeHandler>(new ButtonModeHandler(mrSlideSorter, *this)));
870         return true;
871     }
872     else
873         return false;
874 }
875 
876 
877 
878 
879 void SelectionFunction::SwitchMode (const ::boost::shared_ptr<ModeHandler>& rpHandler)
880 {
881     // Not all modes allow mouse over indicator.
882     if (mpModeHandler->IsMouseOverIndicatorAllowed() != rpHandler->IsMouseOverIndicatorAllowed())
883     {
884         if ( ! rpHandler->IsMouseOverIndicatorAllowed())
885         {
886             mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
887             mrSlideSorter.GetView().GetButtonBar().ResetPage();
888         }
889         else
890             mrSlideSorter.GetView().UpdatePageUnderMouse(false);
891     }
892 
893     mpModeHandler = rpHandler;
894 }
895 
896 
897 
898 
899 void SelectionFunction::ResetShiftKeySelectionAnchor (void)
900 {
901     mnShiftKeySelectionAnchor = -1;
902 }
903 
904 
905 
906 
907 void SelectionFunction::ResetMouseAnchor (void)
908 {
909     if (mpModeHandler && mpModeHandler->GetMode() == NormalMode)
910     {
911         ::boost::shared_ptr<NormalModeHandler> pHandler (
912             ::boost::dynamic_pointer_cast<NormalModeHandler>(mpModeHandler));
913         if (pHandler)
914             pHandler->ResetButtonDownLocation();
915     }
916 }
917 
918 
919 
920 
921 //===== EventDescriptor =======================================================
922 
923 SelectionFunction::EventDescriptor::EventDescriptor (
924     const sal_uInt32 nEventType,
925     const MouseEvent& rEvent,
926     SlideSorter& rSlideSorter)
927     : maMousePosition(rEvent.GetPosPixel()),
928       maMouseModelPosition(),
929       mpHitDescriptor(),
930       mpHitPage(),
931       mnEventCode(nEventType),
932       mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()),
933       meDragMode(InsertionIndicatorHandler::MoveMode),
934       mbMakeSelectionVisible(true),
935       mbIsLeaving(false)
936 {
937     maMouseModelPosition = rSlideSorter.GetContentWindow()->PixelToLogic(maMousePosition);
938     mpHitDescriptor = rSlideSorter.GetController().GetPageAt(maMousePosition);
939     if (mpHitDescriptor)
940     {
941         mpHitPage = mpHitDescriptor->GetPage();
942     }
943 
944     mnEventCode |= EncodeMouseEvent(rEvent);
945     mnEventCode |= EncodeState();
946 
947     // Detect the mouse leaving the window.  When not button is pressed then
948     // we can call IsLeaveWindow at the event.  Otherwise we have to make an
949     // explicit test.
950     mbIsLeaving = rEvent.IsLeaveWindow()
951         || ! Rectangle(Point(0,0),
952              rSlideSorter.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition);
953 }
954 
955 
956 
957 
958 SelectionFunction::EventDescriptor::EventDescriptor (
959     const sal_uInt32 nEventType,
960     const AcceptDropEvent& rEvent,
961     const sal_Int8 nDragAction,
962     SlideSorter& rSlideSorter)
963     : maMousePosition(rEvent.maPosPixel),
964       maMouseModelPosition(),
965       mpHitDescriptor(),
966       mpHitPage(),
967       mnEventCode(nEventType),
968       mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()),
969       meDragMode(InsertionIndicatorHandler::GetModeFromDndAction(nDragAction)),
970       mbMakeSelectionVisible(true),
971       mbIsLeaving(false)
972 {
973     maMouseModelPosition = rSlideSorter.GetContentWindow()->PixelToLogic(maMousePosition);
974     mpHitDescriptor = rSlideSorter.GetController().GetPageAt(maMousePosition);
975     if (mpHitDescriptor)
976     {
977         mpHitPage = mpHitDescriptor->GetPage();
978     }
979 
980     mnEventCode |= EncodeState();
981 
982     // Detect the mouse leaving the window.  When not button is pressed then
983     // we can call IsLeaveWindow at the event.  Otherwise we have to make an
984     // explicit test.
985     mbIsLeaving = rEvent.mbLeaving
986         || ! Rectangle(Point(0,0),
987              rSlideSorter.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition);
988 }
989 
990 
991 
992 
993 SelectionFunction::EventDescriptor::EventDescriptor (
994     const KeyEvent& rEvent,
995     SlideSorter& rSlideSorter)
996     : maMousePosition(),
997       maMouseModelPosition(),
998       mpHitDescriptor(),
999       mpHitPage(),
1000       mnEventCode(KEY_EVENT),
1001       mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()),
1002       meDragMode(InsertionIndicatorHandler::MoveMode),
1003       mbMakeSelectionVisible(true),
1004       mbIsLeaving(false)
1005 {
1006     model::SharedPageDescriptor pHitDescriptor (
1007         rSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor());
1008     if (pHitDescriptor.get() != NULL)
1009     {
1010         mpHitPage = pHitDescriptor->GetPage();
1011         mpHitDescriptor = pHitDescriptor;
1012     }
1013 
1014     mnEventCode |= EncodeKeyEvent(rEvent) | EncodeState();
1015 }
1016 
1017 
1018 
1019 
1020 void SelectionFunction::EventDescriptor::SetDragMode (const InsertionIndicatorHandler::Mode eMode)
1021 {
1022     meDragMode = eMode;
1023 }
1024 
1025 
1026 
1027 
1028 sal_uInt32 SelectionFunction::EventDescriptor::EncodeMouseEvent (
1029     const MouseEvent& rEvent) const
1030 {
1031     // Initialize with the type of mouse event.
1032     sal_uInt32 nEventCode (mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION));
1033 
1034     // Detect the affected button.
1035 	switch (rEvent.GetButtons())
1036     {
1037         case MOUSE_LEFT:   nEventCode |= LEFT_BUTTON; break;
1038         case MOUSE_RIGHT:  nEventCode |= RIGHT_BUTTON; break;
1039         case MOUSE_MIDDLE: nEventCode |= MIDDLE_BUTTON; break;
1040     }
1041 
1042     // Detect the number of clicks.
1043     switch (rEvent.GetClicks())
1044     {
1045         case 1: nEventCode |= SINGLE_CLICK; break;
1046         case 2: nEventCode |= DOUBLE_CLICK; break;
1047     }
1048 
1049     // Detect pressed modifier keys.
1050     if (rEvent.IsShift())
1051         nEventCode |= SHIFT_MODIFIER;
1052     if (rEvent.IsMod1())
1053         nEventCode |= CONTROL_MODIFIER;
1054 
1055     // Detect whether the mouse is over one of the active elements inside a
1056     // page object.
1057     if (mbIsOverButton)
1058         nEventCode |= OVER_BUTTON;
1059 
1060     return nEventCode;
1061 }
1062 
1063 
1064 
1065 
1066 sal_uInt32 SelectionFunction::EventDescriptor::EncodeKeyEvent (const KeyEvent& rEvent) const
1067 {
1068     // The key code in the lower 16 bit.
1069     sal_uInt32 nEventCode (rEvent.GetKeyCode().GetCode());
1070 
1071     // Detect pressed modifier keys.
1072     if (rEvent.GetKeyCode().IsShift())
1073         nEventCode |= SHIFT_MODIFIER;
1074     if (rEvent.GetKeyCode().IsMod1())
1075         nEventCode |= CONTROL_MODIFIER;
1076 
1077     return nEventCode;
1078 }
1079 
1080 
1081 
1082 
1083 sal_uInt32 SelectionFunction::EventDescriptor::EncodeState (void) const
1084 {
1085     sal_uInt32 nEventCode (0);
1086 
1087     // Detect whether the event has happened over a page object.
1088     if (mpHitPage!=NULL && mpHitDescriptor)
1089     {
1090         if (mpHitDescriptor->HasState(model::PageDescriptor::ST_Selected))
1091             nEventCode |= OVER_SELECTED_PAGE;
1092         else
1093             nEventCode |= OVER_UNSELECTED_PAGE;
1094 
1095         // Detect whether the mouse is over one of the active elements
1096         // inside a page object.
1097         if (mbIsOverButton)
1098             nEventCode |= OVER_BUTTON;
1099     }
1100 
1101     return nEventCode;
1102 }
1103 
1104 
1105 
1106 
1107 //===== SelectionFunction::ModeHandler ========================================
1108 
1109 SelectionFunction::ModeHandler::ModeHandler (
1110     SlideSorter& rSlideSorter,
1111     SelectionFunction& rSelectionFunction,
1112     const bool bIsMouseOverIndicatorAllowed)
1113     : mrSlideSorter(rSlideSorter),
1114       mrSelectionFunction(rSelectionFunction),
1115       mbIsMouseOverIndicatorAllowed(bIsMouseOverIndicatorAllowed)
1116 {
1117 }
1118 
1119 
1120 
1121 
1122 SelectionFunction::ModeHandler::~ModeHandler (void)
1123 {
1124 }
1125 
1126 
1127 
1128 
1129 void SelectionFunction::ModeHandler::ReprocessEvent (EventDescriptor& rDescriptor)
1130 {
1131     mrSelectionFunction.ProcessEvent(rDescriptor);
1132 }
1133 
1134 
1135 
1136 
1137 void SelectionFunction::ModeHandler::ProcessEvent (
1138     SelectionFunction::EventDescriptor& rDescriptor)
1139 {
1140     PageSelector::BroadcastLock aBroadcastLock (mrSlideSorter);
1141     PageSelector::UpdateLock aUpdateLock (mrSlideSorter);
1142 
1143     bool bIsProcessed (false);
1144     switch (rDescriptor.mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION | MOUSE_DRAG))
1145     {
1146         case BUTTON_DOWN:
1147             bIsProcessed = ProcessButtonDownEvent(rDescriptor);
1148             break;
1149 
1150         case BUTTON_UP:
1151             bIsProcessed = ProcessButtonUpEvent(rDescriptor);
1152             break;
1153 
1154         case MOUSE_MOTION:
1155             bIsProcessed = ProcessMotionEvent(rDescriptor);
1156             break;
1157 
1158         case MOUSE_DRAG:
1159             bIsProcessed = ProcessDragEvent(rDescriptor);
1160             break;
1161     }
1162 
1163     if ( ! bIsProcessed)
1164         HandleUnprocessedEvent(rDescriptor);
1165 }
1166 
1167 
1168 
1169 
1170 bool SelectionFunction::ModeHandler::ProcessButtonDownEvent (EventDescriptor&)
1171 {
1172     return false;
1173 }
1174 
1175 
1176 
1177 
1178 bool SelectionFunction::ModeHandler::ProcessButtonUpEvent (EventDescriptor&)
1179 {
1180     mrSelectionFunction.SwitchToNormalMode();
1181     return false;
1182 }
1183 
1184 
1185 
1186 
1187 bool SelectionFunction::ModeHandler::ProcessMotionEvent (EventDescriptor& rDescriptor)
1188 {
1189     if (mbIsMouseOverIndicatorAllowed)
1190         mrSlideSorter.GetView().UpdatePageUnderMouse(
1191             rDescriptor.maMousePosition,
1192             (rDescriptor.mnEventCode & LEFT_BUTTON) != 0,
1193             true);
1194 
1195     if (rDescriptor.mbIsLeaving)
1196     {
1197         mrSelectionFunction.SwitchToNormalMode();
1198         mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor());
1199 
1200         return true;
1201     }
1202     else
1203         return false;
1204 }
1205 
1206 
1207 
1208 
1209 bool SelectionFunction::ModeHandler::ProcessDragEvent (EventDescriptor&)
1210 {
1211     return false;
1212 }
1213 
1214 
1215 
1216 
1217 bool SelectionFunction::ModeHandler::HandleUnprocessedEvent (EventDescriptor&)
1218 {
1219     return false;
1220 }
1221 
1222 
1223 
1224 
1225 void SelectionFunction::ModeHandler::SetCurrentPage (
1226     const model::SharedPageDescriptor& rpDescriptor)
1227 {
1228     SelectOnePage(rpDescriptor);
1229     mrSlideSorter.GetController().GetCurrentSlideManager()->SwitchCurrentSlide(rpDescriptor);
1230 }
1231 
1232 
1233 
1234 
1235 void SelectionFunction::ModeHandler::DeselectAllPages (void)
1236 {
1237     mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
1238     mrSelectionFunction.ResetShiftKeySelectionAnchor();
1239 }
1240 
1241 
1242 
1243 
1244 void SelectionFunction::ModeHandler::SelectOnePage (
1245     const model::SharedPageDescriptor& rpDescriptor)
1246 {
1247     DeselectAllPages();
1248     mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
1249 }
1250 
1251 
1252 
1253 
1254 void SelectionFunction::ModeHandler::SwitchView (const model::SharedPageDescriptor& rpDescriptor)
1255 {
1256     // Switch to the draw view.  This is done only when the current
1257     // view is the main view.
1258     ViewShell* pViewShell = mrSlideSorter.GetViewShell();
1259     if (pViewShell!=NULL && pViewShell->IsMainViewShell())
1260     {
1261         if (rpDescriptor.get()!=NULL && rpDescriptor->GetPage()!=NULL)
1262         {
1263             mrSlideSorter.GetModel().GetDocument()->SetSelected(rpDescriptor->GetPage(), sal_True);
1264             pViewShell->GetFrameView()->SetSelectedPage(
1265                 (rpDescriptor->GetPage()->GetPageNum()-1)/2);
1266         }
1267         if (mrSlideSorter.GetViewShellBase() != NULL)
1268         framework::FrameworkHelper::Instance(*mrSlideSorter.GetViewShellBase())->RequestView(
1269             framework::FrameworkHelper::msImpressViewURL,
1270             framework::FrameworkHelper::msCenterPaneURL);
1271     }
1272 }
1273 
1274 
1275 
1276 
1277 void SelectionFunction::ModeHandler::StartDrag (
1278     const Point& rMousePosition,
1279     const InsertionIndicatorHandler::Mode eMode)
1280 {
1281     (void)eMode;
1282     // Do not start a drag-and-drop operation when one is already active.
1283     // (when dragging pages from one document into another, pressing a
1284     // modifier key can trigger a MouseMotion event in the originating
1285     // window (focus still in there).  Together with the mouse button pressed
1286     // (drag-and-drop is active) this triggers the start of drag-and-drop.)
1287     if (SD_MOD()->pTransferDrag != NULL)
1288         return;
1289 
1290 	if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly())
1291 	{
1292         mrSelectionFunction.SwitchToDragAndDropMode(rMousePosition);
1293 	}
1294 }
1295 
1296 
1297 
1298 
1299 bool SelectionFunction::ModeHandler::IsMouseOverIndicatorAllowed (void) const
1300 {
1301     return mbIsMouseOverIndicatorAllowed;
1302 }
1303 
1304 
1305 
1306 
1307 //===== NormalModeHandler =====================================================
1308 
1309 NormalModeHandler::NormalModeHandler (
1310     SlideSorter& rSlideSorter,
1311     SelectionFunction& rSelectionFunction)
1312     : ModeHandler(rSlideSorter, rSelectionFunction, true),
1313       maButtonDownLocation()
1314 {
1315 }
1316 
1317 
1318 
1319 
1320 NormalModeHandler::~NormalModeHandler (void)
1321 {
1322 }
1323 
1324 
1325 
1326 
1327 SelectionFunction::Mode NormalModeHandler::GetMode (void) const
1328 {
1329     return SelectionFunction::NormalMode;
1330 }
1331 
1332 
1333 
1334 
1335 void NormalModeHandler::Abort (void)
1336 {
1337 }
1338 
1339 
1340 
1341 
1342 bool NormalModeHandler::ProcessButtonDownEvent (
1343     SelectionFunction::EventDescriptor& rDescriptor)
1344 {
1345     // Remember the location where the left button is pressed.  With
1346     // that we can filter away motion events that are caused by key
1347     // presses.  We also can tune the minimal motion distance that
1348     // triggers a drag-and-drop operation.
1349     if ((rDescriptor.mnEventCode & BUTTON_DOWN) != 0)
1350         maButtonDownLocation = rDescriptor.maMousePosition;
1351 
1352     switch (rDescriptor.mnEventCode)
1353     {
1354         case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE:
1355             SetCurrentPage(rDescriptor.mpHitDescriptor);
1356             break;
1357 
1358         case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
1359             break;
1360 
1361         case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | OVER_SELECTED_PAGE:
1362         case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | OVER_UNSELECTED_PAGE:
1363             // A double click allways shows the selected slide in the center
1364             // pane in an edit view.
1365             SetCurrentPage(rDescriptor.mpHitDescriptor);
1366             SwitchView(rDescriptor.mpHitDescriptor);
1367             break;
1368 
1369         case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | SHIFT_MODIFIER:
1370         case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | SHIFT_MODIFIER:
1371             // Range selection with the shift modifier.
1372             RangeSelect(rDescriptor.mpHitDescriptor);
1373             break;
1374 
1375         case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | OVER_BUTTON:
1376         case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | OVER_BUTTON:
1377             OSL_ASSERT(mrSlideSorter.GetView().GetButtonBar().IsMouseOverButton());
1378 
1379             // Switch to button mode only when the buttons are visible
1380             // (or being faded in.)
1381             if (mrSlideSorter.GetView().GetButtonBar().IsVisible(rDescriptor.mpHitDescriptor))
1382             {
1383                 if (mrSelectionFunction.SwitchToButtonMode())
1384                     ReprocessEvent(rDescriptor);
1385             }
1386             else
1387             {
1388                 // When the buttons are not (yet) visible then behave like
1389                 // the left button had been clicked over any other part of
1390                 // the slide.
1391                 SetCurrentPage(rDescriptor.mpHitDescriptor);
1392             }
1393             break;
1394 
1395             // Right button for context menu.
1396         case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE:
1397             // Single right click and shift+F10 select as preparation to
1398             // show the context menu.  Change the selection only when the
1399             // page under the mouse is not selected.  In this case the
1400             // selection is set to this single page.  Otherwise the
1401             // selection is not modified.
1402             SetCurrentPage(rDescriptor.mpHitDescriptor);
1403             rDescriptor.mbMakeSelectionVisible = false;
1404             break;
1405 
1406         case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
1407             // Do not change the selection.  Just adjust the insertion indicator.
1408             rDescriptor.mbMakeSelectionVisible = false;
1409             break;
1410 
1411         case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE:
1412             // Remember the current selection so that when a multi selection
1413             // is started, we can restore the previous selection.
1414             mrSlideSorter.GetModel().SaveCurrentSelection();
1415             DeselectAllPages();
1416             break;
1417 
1418         case ANY_MODIFIER(BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE):
1419             // Remember the current selection so that when a multi selection
1420             // is started, we can restore the previous selection.
1421             mrSlideSorter.GetModel().SaveCurrentSelection();
1422             DeselectAllPages();
1423             break;
1424 
1425         default:
1426             return false;
1427     }
1428     return true;
1429 }
1430 
1431 
1432 
1433 
1434 bool NormalModeHandler::ProcessButtonUpEvent (
1435     SelectionFunction::EventDescriptor& rDescriptor)
1436 {
1437     bool bIsProcessed (true);
1438     switch (rDescriptor.mnEventCode)
1439     {
1440         case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE:
1441             SetCurrentPage(rDescriptor.mpHitDescriptor);
1442             break;
1443 
1444             // Multi selection with the control modifier.
1445         case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | CONTROL_MODIFIER:
1446             mrSlideSorter.GetController().GetPageSelector().DeselectPage(
1447                 rDescriptor.mpHitDescriptor);
1448             break;
1449 
1450         case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | CONTROL_MODIFIER:
1451             mrSlideSorter.GetController().GetPageSelector().SelectPage(
1452                 rDescriptor.mpHitDescriptor);
1453             mrSlideSorter.GetView().UpdatePageUnderMouse(
1454                 rDescriptor.mpHitDescriptor,
1455                 rDescriptor.maMousePosition,
1456                 false);
1457             break;
1458         case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE:
1459             break;
1460 
1461         default:
1462             bIsProcessed = false;
1463             break;
1464     }
1465     mrSelectionFunction.SwitchToNormalMode();
1466     return bIsProcessed;
1467 }
1468 
1469 
1470 
1471 
1472 
1473 bool NormalModeHandler::ProcessMotionEvent (
1474     SelectionFunction::EventDescriptor& rDescriptor)
1475 {
1476     if (ModeHandler::ProcessMotionEvent(rDescriptor))
1477         return true;
1478 
1479     bool bIsProcessed (true);
1480     switch (rDescriptor.mnEventCode)
1481     {
1482         case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE):
1483             //            SetCurrentPage(rDescriptor.mpHitDescriptor);
1484             // Fallthrough
1485 
1486         // A mouse motion without visible substitution starts that.
1487         case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE):
1488         {
1489             if (maButtonDownLocation)
1490             {
1491                 const sal_Int32 nDistance (maButtonDownLocation
1492                     ? ::std::max (
1493                         abs(maButtonDownLocation->X() - rDescriptor.maMousePosition.X()),
1494                         abs(maButtonDownLocation->Y() - rDescriptor.maMousePosition.Y()))
1495                     : 0);
1496                 if (nDistance > 3)
1497                     StartDrag(
1498                         rDescriptor.maMousePosition,
1499                         (rDescriptor.mnEventCode & CONTROL_MODIFIER) != 0
1500                             ? InsertionIndicatorHandler::CopyMode
1501                             : InsertionIndicatorHandler::MoveMode);
1502             }
1503         }
1504         break;
1505 
1506             // A mouse motion not over a page starts a rectangle selection.
1507         case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE):
1508             mrSelectionFunction.SwitchToMultiSelectionMode(
1509                 rDescriptor.maMouseModelPosition,
1510                 rDescriptor.mnEventCode);
1511             break;
1512 
1513         default:
1514             bIsProcessed = false;
1515             break;
1516     }
1517     return bIsProcessed;
1518 }
1519 
1520 
1521 
1522 
1523 bool NormalModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor)
1524 {
1525     mrSelectionFunction.SwitchToDragAndDropMode(rDescriptor.maMousePosition);
1526     ReprocessEvent(rDescriptor);
1527     return true;
1528 }
1529 
1530 
1531 
1532 
1533 void NormalModeHandler::RangeSelect (const model::SharedPageDescriptor& rpDescriptor)
1534 {
1535     PageSelector::UpdateLock aLock (mrSlideSorter);
1536     PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector());
1537 
1538     model::SharedPageDescriptor pAnchor (rSelector.GetSelectionAnchor());
1539     DeselectAllPages();
1540 
1541     if (pAnchor.get() != NULL)
1542     {
1543         // Select all pages between the anchor and the given one, including
1544         // the two.
1545         const sal_uInt16 nAnchorIndex ((pAnchor->GetPage()->GetPageNum()-1) / 2);
1546         const sal_uInt16 nOtherIndex ((rpDescriptor->GetPage()->GetPageNum()-1) / 2);
1547 
1548         // Iterate over all pages in the range.  Start with the anchor
1549         // page.  This way the PageSelector will recognize it again as
1550         // anchor (the first selected page after a DeselectAllPages()
1551         // becomes the anchor.)
1552         const sal_uInt16 nStep ((nAnchorIndex < nOtherIndex) ? +1 : -1);
1553         sal_uInt16 nIndex (nAnchorIndex);
1554         while (true)
1555         {
1556             rSelector.SelectPage(nIndex);
1557             if (nIndex == nOtherIndex)
1558                 break;
1559             nIndex = nIndex + nStep;
1560         }
1561     }
1562 }
1563 
1564 
1565 
1566 
1567 void NormalModeHandler::ResetButtonDownLocation (void)
1568 {
1569     maButtonDownLocation = ::boost::optional<Point>();
1570 }
1571 
1572 
1573 
1574 
1575 //===== MultiSelectionModeHandler =============================================
1576 
1577 MultiSelectionModeHandler::MultiSelectionModeHandler (
1578     SlideSorter& rSlideSorter,
1579     SelectionFunction& rSelectionFunction,
1580     const Point& rMouseModelPosition,
1581     const sal_uInt32 nEventCode)
1582     : ModeHandler(rSlideSorter, rSelectionFunction, false),
1583       meSelectionMode(SM_Normal),
1584       maSecondCorner(rMouseModelPosition),
1585       maSavedPointer(mrSlideSorter.GetContentWindow()->GetPointer()),
1586       mnAnchorIndex(-1),
1587       mnSecondIndex(-1),
1588       maButtonBarLock(rSlideSorter)
1589 {
1590     const Pointer aSelectionPointer (POINTER_TEXT);
1591     mrSlideSorter.GetContentWindow()->SetPointer(aSelectionPointer);
1592     SetSelectionModeFromModifier(nEventCode);
1593 }
1594 
1595 
1596 
1597 
1598 
1599 MultiSelectionModeHandler::~MultiSelectionModeHandler (void)
1600 {
1601     mrSlideSorter.GetContentWindow()->SetPointer(maSavedPointer);
1602 }
1603 
1604 
1605 
1606 
1607 SelectionFunction::Mode MultiSelectionModeHandler::GetMode (void) const
1608 {
1609     return SelectionFunction::MultiSelectionMode;
1610 }
1611 
1612 
1613 
1614 
1615 void MultiSelectionModeHandler::Abort (void)
1616 {
1617     mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection());
1618 }
1619 
1620 
1621 
1622 
1623 void MultiSelectionModeHandler::ProcessEvent (
1624     SelectionFunction::EventDescriptor& rDescriptor)
1625 {
1626     // During a multi selection we do not want sudden jumps of the
1627     // visible area caused by moving newly selected pages into view.
1628     // Therefore disable that temporarily.  The disabler object is
1629     // released at the end of the event processing, after the focus and
1630     // current slide have been updated.
1631     VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
1632 
1633     ModeHandler::ProcessEvent(rDescriptor);
1634 }
1635 
1636 
1637 
1638 
1639 bool MultiSelectionModeHandler::ProcessButtonUpEvent (
1640     SelectionFunction::EventDescriptor& rDescriptor)
1641 {
1642     if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK))
1643     {
1644         mrSelectionFunction.SwitchToNormalMode();
1645         return true;
1646     }
1647     else
1648         return false;
1649 }
1650 
1651 
1652 
1653 
1654 bool MultiSelectionModeHandler::ProcessMotionEvent (
1655     SelectionFunction::EventDescriptor& rDescriptor)
1656 {
1657     // The selection rectangle is visible.  Handle events accordingly.
1658     if (Match(rDescriptor.mnEventCode, MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK))
1659     {
1660         SetSelectionModeFromModifier(rDescriptor.mnEventCode);
1661         UpdatePosition(rDescriptor.maMousePosition, true);
1662         rDescriptor.mbMakeSelectionVisible = false;
1663         return true;
1664     }
1665     else
1666         return false;
1667 }
1668 
1669 
1670 
1671 bool MultiSelectionModeHandler::HandleUnprocessedEvent (
1672     SelectionFunction::EventDescriptor& rDescriptor)
1673 {
1674     if ( ! ModeHandler::HandleUnprocessedEvent(rDescriptor))
1675     {
1676         // If the event has not been processed then stop multi selection.
1677         mrSelectionFunction.SwitchToNormalMode();
1678         ReprocessEvent(rDescriptor);
1679     }
1680     return true;
1681 }
1682 
1683 
1684 
1685 
1686 void MultiSelectionModeHandler::UpdatePosition (
1687     const Point& rMousePosition,
1688     const bool bAllowAutoScroll)
1689 {
1690     VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
1691 
1692     // Convert window coordinates into model coordinates (we need the
1693     // window coordinates for auto-scrolling because that remains
1694     // constant while scrolling.)
1695     SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
1696     const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition));
1697 
1698     if ( ! (bAllowAutoScroll && mrSlideSorter.GetController().GetScrollBarManager().AutoScroll(
1699         rMousePosition,
1700         ::boost::bind(
1701             &MultiSelectionModeHandler::UpdatePosition,
1702             this,
1703             rMousePosition,
1704             false))))
1705     {
1706         UpdateModelPosition(aMouseModelPosition);
1707     }
1708 }
1709 
1710 
1711 
1712 
1713 void MultiSelectionModeHandler::SetSelectionModeFromModifier (
1714     const sal_uInt32 nEventCode)
1715 {
1716     switch (nEventCode & MODIFIER_MASK)
1717     {
1718         case NO_MODIFIER:
1719             SetSelectionMode(SM_Normal);
1720             break;
1721 
1722         case SHIFT_MODIFIER:
1723             SetSelectionMode(SM_Add);
1724             break;
1725 
1726         case CONTROL_MODIFIER:
1727             SetSelectionMode(SM_Toggle);
1728             break;
1729     }
1730 }
1731 
1732 
1733 
1734 
1735 void MultiSelectionModeHandler::SetSelectionMode (const SelectionMode eSelectionMode)
1736 {
1737     if (meSelectionMode != eSelectionMode)
1738     {
1739         meSelectionMode = eSelectionMode;
1740         UpdateSelection();
1741     }
1742 }
1743 
1744 
1745 
1746 
1747 void MultiSelectionModeHandler::UpdateSelectionState (
1748     const model::SharedPageDescriptor& rpDescriptor,
1749     const bool bIsInSelection) const
1750 {
1751     // Determine whether the page was selected before the rectangle
1752     // selection was started.
1753     const bool bWasSelected (rpDescriptor->HasState(model::PageDescriptor::ST_WasSelected));
1754 
1755     // Combine the two selection states depending on the selection mode.
1756     bool bSelect (false);
1757     switch(meSelectionMode)
1758     {
1759         case SM_Normal:
1760             bSelect = bIsInSelection;
1761             break;
1762 
1763         case SM_Add:
1764             bSelect = bIsInSelection || bWasSelected;
1765             break;
1766 
1767         case SM_Toggle:
1768             if (bIsInSelection)
1769                 bSelect = !bWasSelected;
1770             else
1771                 bSelect = bWasSelected;
1772             break;
1773     }
1774 
1775     // Set the new selection state.
1776     if (bSelect)
1777         mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor);
1778     else
1779         mrSlideSorter.GetController().GetPageSelector().DeselectPage(rpDescriptor);
1780 }
1781 
1782 
1783 
1784 
1785 void MultiSelectionModeHandler::UpdateModelPosition (const Point& rMouseModelPosition)
1786 {
1787     maSecondCorner = rMouseModelPosition;
1788     UpdateSelection();
1789 }
1790 
1791 
1792 
1793 
1794 void MultiSelectionModeHandler::UpdateSelection (void)
1795 {
1796     view::SlideSorterView::DrawLock aLock (mrSlideSorter);
1797 
1798     model::SlideSorterModel& rModel (mrSlideSorter.GetModel());
1799     const sal_Int32 nPageCount (rModel.GetPageCount());
1800 
1801     const sal_Int32 nIndexUnderMouse (
1802         mrSlideSorter.GetView().GetLayouter().GetIndexAtPoint (
1803             maSecondCorner,
1804             false,
1805             false));
1806     if (nIndexUnderMouse>=0 && nIndexUnderMouse<nPageCount)
1807     {
1808         if (mnAnchorIndex < 0)
1809             mnAnchorIndex = nIndexUnderMouse;
1810         mnSecondIndex = nIndexUnderMouse;
1811 
1812         Range aRange (mnAnchorIndex, mnSecondIndex);
1813         aRange.Justify();
1814 
1815         for (sal_Int32 nIndex=0; nIndex<nPageCount; ++nIndex)
1816         {
1817             UpdateSelectionState(rModel.GetPageDescriptor(nIndex), aRange.IsInside(nIndex));
1818         }
1819     }
1820 }
1821 
1822 
1823 
1824 
1825 //===== DragAndDropModeHandler ================================================
1826 
1827 DragAndDropModeHandler::DragAndDropModeHandler (
1828     SlideSorter& rSlideSorter,
1829     SelectionFunction& rSelectionFunction,
1830     const Point& rMousePosition,
1831     ::Window* pWindow)
1832     : ModeHandler(rSlideSorter, rSelectionFunction, false)
1833 {
1834     SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag;
1835     if (pDragTransferable==NULL && mrSlideSorter.GetViewShell() != NULL)
1836     {
1837         SlideSorterViewShell* pSlideSorterViewShell
1838             = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell());
1839         if (pSlideSorterViewShell != NULL)
1840             pSlideSorterViewShell->StartDrag(rMousePosition, pWindow);
1841         pDragTransferable = SD_MOD()->pTransferDrag;
1842     }
1843 
1844     mpDragAndDropContext.reset(new DragAndDropContext(mrSlideSorter));
1845     mrSlideSorter.GetController().GetInsertionIndicatorHandler()->Start(
1846         pDragTransferable != NULL
1847             && pDragTransferable->GetView()==&mrSlideSorter.GetView());
1848 }
1849 
1850 
1851 
1852 
1853 DragAndDropModeHandler::~DragAndDropModeHandler (void)
1854 {
1855     if (mpDragAndDropContext)
1856     {
1857         // Disconnect the substitution handler from this selection function.
1858         mpDragAndDropContext->SetTargetSlideSorter();
1859         mpDragAndDropContext.reset();
1860     }
1861     mrSlideSorter.GetController().GetInsertionIndicatorHandler()->End(Animator::AM_Animated);
1862 }
1863 
1864 
1865 
1866 
1867 SelectionFunction::Mode DragAndDropModeHandler::GetMode (void) const
1868 {
1869     return SelectionFunction::DragAndDropMode;
1870 }
1871 
1872 
1873 
1874 
1875 void DragAndDropModeHandler::Abort (void)
1876 {
1877     mrSlideSorter.GetController().GetClipboard().Abort();
1878     if (mpDragAndDropContext)
1879         mpDragAndDropContext->Dispose();
1880     //    mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection());
1881 }
1882 
1883 
1884 
1885 
1886 bool DragAndDropModeHandler::ProcessButtonUpEvent (
1887     SelectionFunction::EventDescriptor& rDescriptor)
1888 {
1889     if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON))
1890     {
1891         // The following Process() call may lead to the desctruction
1892         // of rDescriptor.mpHitDescriptor so release our reference to it.
1893         rDescriptor.mpHitDescriptor.reset();
1894         mrSelectionFunction.SwitchToNormalMode();
1895         return true;
1896     }
1897     else
1898         return false;
1899 }
1900 
1901 
1902 
1903 
1904 bool DragAndDropModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor)
1905 {
1906     OSL_ASSERT(mpDragAndDropContext);
1907 
1908     if (rDescriptor.mbIsLeaving)
1909     {
1910         mrSelectionFunction.SwitchToNormalMode();
1911     }
1912     else if (mpDragAndDropContext)
1913     {
1914         mpDragAndDropContext->UpdatePosition(
1915             rDescriptor.maMousePosition,
1916             rDescriptor.meDragMode);
1917     }
1918 
1919     return true;
1920 }
1921 
1922 
1923 
1924 
1925 //===== ButtonModeHandler =====================================================
1926 
1927 ButtonModeHandler::ButtonModeHandler (
1928     SlideSorter& rSlideSorter,
1929     SelectionFunction& rSelectionFunction)
1930     : ModeHandler(rSlideSorter, rSelectionFunction, true)
1931 {
1932 }
1933 
1934 
1935 
1936 
1937 ButtonModeHandler::~ButtonModeHandler (void)
1938 {
1939 }
1940 
1941 
1942 
1943 
1944 SelectionFunction::Mode ButtonModeHandler::GetMode (void) const
1945 {
1946     return SelectionFunction::ButtonMode;
1947 }
1948 
1949 
1950 
1951 
1952 void ButtonModeHandler::Abort (void)
1953 {
1954 }
1955 
1956 
1957 
1958 
1959 bool ButtonModeHandler::ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor)
1960 {
1961     switch (rDescriptor.mnEventCode)
1962     {
1963         case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | OVER_BUTTON:
1964         case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | OVER_BUTTON:
1965             // Remember page and button index.  When mouse button is
1966             // released over same page and button then invoke action of that
1967             // button.
1968             mrSlideSorter.GetView().GetButtonBar().ProcessButtonDownEvent(
1969                 rDescriptor.mpHitDescriptor,
1970                 rDescriptor.maMouseModelPosition);
1971             return true;
1972 
1973         default:
1974             return false;
1975     }
1976 }
1977 
1978 
1979 
1980 
1981 bool ButtonModeHandler::ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor)
1982 {
1983     switch (rDescriptor.mnEventCode & BUTTON_MASK)
1984     {
1985         case LEFT_BUTTON:
1986             mrSlideSorter.GetView().GetButtonBar().ProcessButtonUpEvent(
1987                 rDescriptor.mpHitDescriptor,
1988                 rDescriptor.maMouseModelPosition);
1989             mrSelectionFunction.SwitchToNormalMode();
1990             return true;
1991     }
1992 
1993     return false;
1994 }
1995 
1996 
1997 
1998 
1999 bool ButtonModeHandler::ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor)
2000 {
2001     switch (rDescriptor.mnEventCode & (MOUSE_MOTION | BUTTON_MASK))
2002     {
2003         case MOUSE_MOTION | LEFT_BUTTON:
2004             mrSlideSorter.GetView().GetButtonBar().ProcessMouseMotionEvent(
2005                 rDescriptor.mpHitDescriptor,
2006                 rDescriptor.maMouseModelPosition,
2007                 true);
2008             return true;
2009 
2010         case MOUSE_MOTION:
2011             mrSlideSorter.GetView().GetButtonBar().ProcessMouseMotionEvent(
2012                 rDescriptor.mpHitDescriptor,
2013                 rDescriptor.maMouseModelPosition,
2014                 false);
2015             return true;
2016     }
2017 
2018     return false;
2019 }
2020 
2021 
2022 
2023 
2024 } } } // end of namespace ::sd::slidesorter::controller
2025