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