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