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