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