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