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