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