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::UpdateLock aLock (mrSlideSorter); 450 FocusManager& rFocusManager (mrController.GetFocusManager()); 451 sal_Bool bResult = sal_False; 452 453 const KeyCode& rCode (rEvent.GetKeyCode()); 454 switch (rCode.GetCode()) 455 { 456 case KEY_RETURN: 457 { 458 model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor()); 459 ViewShell* pViewShell = mrSlideSorter.GetViewShell(); 460 if (rFocusManager.HasFocus() && pDescriptor && pViewShell!=NULL) 461 { 462 // The Return key triggers different functions depending on 463 // whether the slide sorter is the main view or displayed in 464 // the right pane. 465 if (pViewShell->IsMainViewShell()) 466 { 467 mpModeHandler->SetCurrentPage(pDescriptor); 468 mpModeHandler->SwitchView(pDescriptor); 469 } 470 else 471 { 472 pViewShell->GetDispatcher()->Execute( 473 SID_INSERTPAGE, 474 SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD); 475 } 476 bResult = sal_True; 477 } 478 break; 479 } 480 481 case KEY_TAB: 482 if ( ! rFocusManager.IsFocusShowing()) 483 { 484 rFocusManager.ShowFocus(); 485 bResult = sal_True; 486 } 487 break; 488 489 case KEY_ESCAPE: 490 // When there is an active multiselection or drag-and-drop 491 // operation then stop that. 492 mpModeHandler->Abort(); 493 SwitchToNormalMode(); 494 bResult = sal_True; 495 break; 496 497 case KEY_SPACE: 498 { 499 // Toggle the selection state. 500 model::SharedPageDescriptor pDescriptor (rFocusManager.GetFocusedPageDescriptor()); 501 if (pDescriptor && rCode.IsMod1()) 502 { 503 if (pDescriptor->HasState(model::PageDescriptor::ST_Selected)) 504 mrController.GetPageSelector().DeselectPage(pDescriptor, false); 505 else 506 mrController.GetPageSelector().SelectPage(pDescriptor); 507 } 508 bResult = sal_True; 509 } 510 break; 511 512 513 // Move the focus indicator left. 514 case KEY_LEFT: 515 MoveFocus(FocusManager::FMD_LEFT, rCode.IsShift(), rCode.IsMod1()); 516 bResult = sal_True; 517 break; 518 519 // Move the focus indicator right. 520 case KEY_RIGHT: 521 MoveFocus(FocusManager::FMD_RIGHT, rCode.IsShift(), rCode.IsMod1()); 522 bResult = sal_True; 523 break; 524 525 // Move the focus indicator up. 526 case KEY_UP: 527 MoveFocus(FocusManager::FMD_UP, rCode.IsShift(), rCode.IsMod1()); 528 bResult = sal_True; 529 break; 530 531 // Move the focus indicator down. 532 case KEY_DOWN: 533 MoveFocus(FocusManager::FMD_DOWN, rCode.IsShift(), rCode.IsMod1()); 534 bResult = sal_True; 535 break; 536 537 // Go to previous page. No wrap around. 538 case KEY_PAGEUP: 539 GotoNextPage(-1); 540 bResult = sal_True; 541 break; 542 543 // Go to next page. No wrap around.. 544 case KEY_PAGEDOWN: 545 GotoNextPage(+1); 546 bResult = sal_True; 547 break; 548 549 case KEY_HOME: 550 GotoPage(0); 551 bResult = sal_True; 552 break; 553 554 case KEY_END: 555 GotoPage(mrSlideSorter.GetModel().GetPageCount()-1); 556 bResult = sal_True; 557 break; 558 559 case KEY_DELETE: 560 case KEY_BACKSPACE: 561 { 562 if (mrSlideSorter.GetProperties()->IsUIReadOnly()) 563 break; 564 565 mrController.GetSelectionManager()->DeleteSelectedPages(rCode.GetCode()==KEY_DELETE); 566 567 mnShiftKeySelectionAnchor = -1; 568 bResult = sal_True; 569 } 570 break; 571 572 case KEY_F10: 573 if (rCode.IsShift()) 574 { 575 mpModeHandler->SelectOnePage( 576 mrSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor()); 577 } 578 break; 579 580 default: 581 break; 582 } 583 584 if ( ! bResult) 585 bResult = FuPoor::KeyInput(rEvent); 586 587 return bResult; 588 } 589 590 591 592 593 void SelectionFunction::MoveFocus ( 594 const FocusManager::FocusMoveDirection eDirection, 595 const bool bIsShiftDown, 596 const bool bIsControlDown) 597 { 598 // Remember the anchor of shift key multi selection. 599 if (bIsShiftDown) 600 { 601 if (mnShiftKeySelectionAnchor<0) 602 { 603 model::SharedPageDescriptor pFocusedDescriptor ( 604 mrController.GetFocusManager().GetFocusedPageDescriptor()); 605 mnShiftKeySelectionAnchor = pFocusedDescriptor->GetPageIndex(); 606 } 607 } 608 else if ( ! bIsControlDown) 609 ResetShiftKeySelectionAnchor(); 610 611 mrController.GetFocusManager().MoveFocus(eDirection); 612 613 PageSelector& rSelector (mrController.GetPageSelector()); 614 model::SharedPageDescriptor pFocusedDescriptor ( 615 mrController.GetFocusManager().GetFocusedPageDescriptor()); 616 if (bIsShiftDown) 617 { 618 // When shift is pressed then select all pages in the range between 619 // the currently and the previously focused pages, including them. 620 if (pFocusedDescriptor) 621 { 622 sal_Int32 nPageRangeEnd (pFocusedDescriptor->GetPageIndex()); 623 model::PageEnumeration aPages ( 624 model::PageEnumerationProvider::CreateAllPagesEnumeration( 625 mrSlideSorter.GetModel())); 626 while (aPages.HasMoreElements()) 627 { 628 model::SharedPageDescriptor pDescriptor (aPages.GetNextElement()); 629 if (pDescriptor) 630 { 631 const sal_Int32 nPageIndex(pDescriptor->GetPageIndex()); 632 if ((nPageIndex>=mnShiftKeySelectionAnchor && nPageIndex<=nPageRangeEnd) 633 || (nPageIndex<=mnShiftKeySelectionAnchor && nPageIndex>=nPageRangeEnd)) 634 { 635 rSelector.SelectPage(pDescriptor); 636 } 637 else 638 { 639 rSelector.DeselectPage(pDescriptor); 640 } 641 } 642 } 643 } 644 } 645 else if (bIsControlDown) 646 { 647 // When control is pressed then do not alter the selection or the 648 // current page, just move the focus. 649 } 650 else 651 { 652 // Without shift just select the focused page. 653 mpModeHandler->SelectOnePage(pFocusedDescriptor); 654 } 655 } 656 657 658 659 660 void SelectionFunction::Activate() 661 { 662 FuPoor::Activate(); 663 } 664 665 666 667 668 void SelectionFunction::Deactivate() 669 { 670 FuPoor::Deactivate(); 671 } 672 673 674 675 void SelectionFunction::ScrollStart (void) 676 { 677 } 678 679 680 681 682 void SelectionFunction::ScrollEnd (void) 683 { 684 } 685 686 687 688 689 void SelectionFunction::DoCut (void) 690 { 691 if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly()) 692 { 693 mrController.GetClipboard().DoCut(); 694 } 695 } 696 697 698 699 700 void SelectionFunction::DoCopy (void) 701 { 702 mrController.GetClipboard().DoCopy(); 703 } 704 705 706 707 708 void SelectionFunction::DoPaste (void) 709 { 710 if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly()) 711 { 712 mrController.GetClipboard().DoPaste(); 713 } 714 } 715 716 717 718 719 bool SelectionFunction::cancel (void) 720 { 721 mrController.GetFocusManager().ToggleFocus(); 722 return true; 723 } 724 725 726 727 728 void SelectionFunction::GotoNextPage (int nOffset) 729 { 730 model::SharedPageDescriptor pDescriptor 731 = mrController.GetCurrentSlideManager()->GetCurrentSlide(); 732 if (pDescriptor.get() != NULL) 733 { 734 SdPage* pPage = pDescriptor->GetPage(); 735 OSL_ASSERT(pPage!=NULL); 736 sal_Int32 nIndex = (pPage->GetPageNum()-1) / 2; 737 GotoPage(nIndex + nOffset); 738 } 739 ResetShiftKeySelectionAnchor(); 740 } 741 742 743 744 745 void SelectionFunction::GotoPage (int nIndex) 746 { 747 sal_uInt16 nPageCount = (sal_uInt16)mrSlideSorter.GetModel().GetPageCount(); 748 749 if (nIndex >= nPageCount) 750 nIndex = nPageCount - 1; 751 if (nIndex < 0) 752 nIndex = 0; 753 754 mrController.GetFocusManager().SetFocusedPage(nIndex); 755 model::SharedPageDescriptor pNextPageDescriptor ( 756 mrSlideSorter.GetModel().GetPageDescriptor (nIndex)); 757 if (pNextPageDescriptor.get() != NULL) 758 mpModeHandler->SetCurrentPage(pNextPageDescriptor); 759 else 760 { 761 OSL_ASSERT(pNextPageDescriptor.get() != NULL); 762 } 763 ResetShiftKeySelectionAnchor(); 764 } 765 766 767 768 769 void SelectionFunction::ProcessMouseEvent (sal_uInt32 nEventType, const MouseEvent& rEvent) 770 { 771 // #95491# remember button state for creation of own MouseEvents 772 SetMouseButtonCode (rEvent.GetButtons()); 773 774 EventDescriptor aEventDescriptor (nEventType, rEvent, mrSlideSorter); 775 ProcessEvent(aEventDescriptor); 776 } 777 778 779 780 781 void SelectionFunction::MouseDragged ( 782 const AcceptDropEvent& rEvent, 783 const sal_Int8 nDragAction) 784 { 785 EventDescriptor aEventDescriptor (MOUSE_DRAG, rEvent, nDragAction, mrSlideSorter); 786 ProcessEvent(aEventDescriptor); 787 } 788 789 790 791 792 void SelectionFunction::ProcessKeyEvent (const KeyEvent& rEvent) 793 { 794 EventDescriptor aEventDescriptor (rEvent, mrSlideSorter); 795 ProcessEvent(aEventDescriptor); 796 } 797 798 799 800 801 void SelectionFunction::ProcessEvent (EventDescriptor& rDescriptor) 802 { 803 // The call to ProcessEvent may switch to another mode handler. 804 // Prevent the untimely destruction of the called handler by aquiring a 805 // temporary reference here. 806 ::boost::shared_ptr<ModeHandler> pModeHandler (mpModeHandler); 807 pModeHandler->ProcessEvent(rDescriptor); 808 } 809 810 811 812 813 bool Match ( 814 const sal_uInt32 nEventCode, 815 const sal_uInt32 nPositivePattern) 816 { 817 return (nEventCode & nPositivePattern)==nPositivePattern; 818 } 819 820 821 822 823 void SelectionFunction::SwitchToNormalMode (void) 824 { 825 if (mpModeHandler->GetMode() != NormalMode) 826 SwitchMode(::boost::shared_ptr<ModeHandler>( 827 new NormalModeHandler(mrSlideSorter, *this))); 828 } 829 830 831 832 833 void SelectionFunction::SwitchToDragAndDropMode (const Point aMousePosition) 834 { 835 if (mpModeHandler->GetMode() != DragAndDropMode) 836 { 837 SwitchMode(::boost::shared_ptr<ModeHandler>( 838 new DragAndDropModeHandler(mrSlideSorter, *this, aMousePosition, mpWindow))); 839 } 840 } 841 842 843 844 845 void SelectionFunction::SwitchToMultiSelectionMode ( 846 const Point aMousePosition, 847 const sal_uInt32 nEventCode) 848 { 849 if (mpModeHandler->GetMode() != MultiSelectionMode) 850 SwitchMode(::boost::shared_ptr<ModeHandler>( 851 new MultiSelectionModeHandler(mrSlideSorter, *this, aMousePosition, nEventCode))); 852 } 853 854 855 856 857 bool SelectionFunction::SwitchToButtonMode (void) 858 { 859 // Do not show the buttons for draw pages. 860 ::boost::shared_ptr<ViewShell> pMainViewShell (mrSlideSorter.GetViewShellBase()->GetMainViewShell()); 861 if (pMainViewShell 862 && pMainViewShell->GetShellType()!=ViewShell::ST_DRAW 863 && mpModeHandler->GetMode() != ButtonMode) 864 { 865 SwitchMode(::boost::shared_ptr<ModeHandler>(new ButtonModeHandler(mrSlideSorter, *this))); 866 return true; 867 } 868 else 869 return false; 870 } 871 872 873 874 875 void SelectionFunction::SwitchMode (const ::boost::shared_ptr<ModeHandler>& rpHandler) 876 { 877 // Not all modes allow mouse over indicator. 878 if (mpModeHandler->IsMouseOverIndicatorAllowed() != rpHandler->IsMouseOverIndicatorAllowed()) 879 { 880 if ( ! rpHandler->IsMouseOverIndicatorAllowed()) 881 { 882 mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor()); 883 mrSlideSorter.GetView().GetButtonBar().ResetPage(); 884 } 885 else 886 mrSlideSorter.GetView().UpdatePageUnderMouse(false); 887 } 888 889 mpModeHandler = rpHandler; 890 } 891 892 893 894 895 void SelectionFunction::ResetShiftKeySelectionAnchor (void) 896 { 897 mnShiftKeySelectionAnchor = -1; 898 } 899 900 901 902 903 void SelectionFunction::ResetMouseAnchor (void) 904 { 905 if (mpModeHandler && mpModeHandler->GetMode() == NormalMode) 906 { 907 ::boost::shared_ptr<NormalModeHandler> pHandler ( 908 ::boost::dynamic_pointer_cast<NormalModeHandler>(mpModeHandler)); 909 if (pHandler) 910 pHandler->ResetButtonDownLocation(); 911 } 912 } 913 914 915 916 917 //===== EventDescriptor ======================================================= 918 919 SelectionFunction::EventDescriptor::EventDescriptor ( 920 const sal_uInt32 nEventType, 921 const MouseEvent& rEvent, 922 SlideSorter& rSlideSorter) 923 : maMousePosition(rEvent.GetPosPixel()), 924 maMouseModelPosition(), 925 mpHitDescriptor(), 926 mpHitPage(), 927 mnEventCode(nEventType), 928 mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()), 929 meDragMode(InsertionIndicatorHandler::MoveMode), 930 mbMakeSelectionVisible(true), 931 mbIsLeaving(false) 932 { 933 maMouseModelPosition = rSlideSorter.GetContentWindow()->PixelToLogic(maMousePosition); 934 mpHitDescriptor = rSlideSorter.GetController().GetPageAt(maMousePosition); 935 if (mpHitDescriptor) 936 { 937 mpHitPage = mpHitDescriptor->GetPage(); 938 } 939 940 mnEventCode |= EncodeMouseEvent(rEvent); 941 mnEventCode |= EncodeState(); 942 943 // Detect the mouse leaving the window. When not button is pressed then 944 // we can call IsLeaveWindow at the event. Otherwise we have to make an 945 // explicit test. 946 mbIsLeaving = rEvent.IsLeaveWindow() 947 || ! Rectangle(Point(0,0), 948 rSlideSorter.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition); 949 } 950 951 952 953 954 SelectionFunction::EventDescriptor::EventDescriptor ( 955 const sal_uInt32 nEventType, 956 const AcceptDropEvent& rEvent, 957 const sal_Int8 nDragAction, 958 SlideSorter& rSlideSorter) 959 : maMousePosition(rEvent.maPosPixel), 960 maMouseModelPosition(), 961 mpHitDescriptor(), 962 mpHitPage(), 963 mnEventCode(nEventType), 964 mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()), 965 meDragMode(InsertionIndicatorHandler::GetModeFromDndAction(nDragAction)), 966 mbMakeSelectionVisible(true), 967 mbIsLeaving(false) 968 { 969 maMouseModelPosition = rSlideSorter.GetContentWindow()->PixelToLogic(maMousePosition); 970 mpHitDescriptor = rSlideSorter.GetController().GetPageAt(maMousePosition); 971 if (mpHitDescriptor) 972 { 973 mpHitPage = mpHitDescriptor->GetPage(); 974 } 975 976 mnEventCode |= EncodeState(); 977 978 // Detect the mouse leaving the window. When not button is pressed then 979 // we can call IsLeaveWindow at the event. Otherwise we have to make an 980 // explicit test. 981 mbIsLeaving = rEvent.mbLeaving 982 || ! Rectangle(Point(0,0), 983 rSlideSorter.GetContentWindow()->GetOutputSizePixel()).IsInside(maMousePosition); 984 } 985 986 987 988 989 SelectionFunction::EventDescriptor::EventDescriptor ( 990 const KeyEvent& rEvent, 991 SlideSorter& rSlideSorter) 992 : maMousePosition(), 993 maMouseModelPosition(), 994 mpHitDescriptor(), 995 mpHitPage(), 996 mnEventCode(KEY_EVENT), 997 mbIsOverButton(rSlideSorter.GetView().GetButtonBar().IsMouseOverButton()), 998 meDragMode(InsertionIndicatorHandler::MoveMode), 999 mbMakeSelectionVisible(true), 1000 mbIsLeaving(false) 1001 { 1002 model::SharedPageDescriptor pHitDescriptor ( 1003 rSlideSorter.GetController().GetFocusManager().GetFocusedPageDescriptor()); 1004 if (pHitDescriptor.get() != NULL) 1005 { 1006 mpHitPage = pHitDescriptor->GetPage(); 1007 mpHitDescriptor = pHitDescriptor; 1008 } 1009 1010 mnEventCode |= EncodeKeyEvent(rEvent) | EncodeState(); 1011 } 1012 1013 1014 1015 1016 void SelectionFunction::EventDescriptor::SetDragMode (const InsertionIndicatorHandler::Mode eMode) 1017 { 1018 meDragMode = eMode; 1019 } 1020 1021 1022 1023 1024 sal_uInt32 SelectionFunction::EventDescriptor::EncodeMouseEvent ( 1025 const MouseEvent& rEvent) const 1026 { 1027 // Initialize with the type of mouse event. 1028 sal_uInt32 nEventCode (mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION)); 1029 1030 // Detect the affected button. 1031 switch (rEvent.GetButtons()) 1032 { 1033 case MOUSE_LEFT: nEventCode |= LEFT_BUTTON; break; 1034 case MOUSE_RIGHT: nEventCode |= RIGHT_BUTTON; break; 1035 case MOUSE_MIDDLE: nEventCode |= MIDDLE_BUTTON; break; 1036 } 1037 1038 // Detect the number of clicks. 1039 switch (rEvent.GetClicks()) 1040 { 1041 case 1: nEventCode |= SINGLE_CLICK; break; 1042 case 2: nEventCode |= DOUBLE_CLICK; break; 1043 } 1044 1045 // Detect pressed modifier keys. 1046 if (rEvent.IsShift()) 1047 nEventCode |= SHIFT_MODIFIER; 1048 if (rEvent.IsMod1()) 1049 nEventCode |= CONTROL_MODIFIER; 1050 1051 // Detect whether the mouse is over one of the active elements inside a 1052 // page object. 1053 if (mbIsOverButton) 1054 nEventCode |= OVER_BUTTON; 1055 1056 return nEventCode; 1057 } 1058 1059 1060 1061 1062 sal_uInt32 SelectionFunction::EventDescriptor::EncodeKeyEvent (const KeyEvent& rEvent) const 1063 { 1064 // The key code in the lower 16 bit. 1065 sal_uInt32 nEventCode (rEvent.GetKeyCode().GetCode()); 1066 1067 // Detect pressed modifier keys. 1068 if (rEvent.GetKeyCode().IsShift()) 1069 nEventCode |= SHIFT_MODIFIER; 1070 if (rEvent.GetKeyCode().IsMod1()) 1071 nEventCode |= CONTROL_MODIFIER; 1072 1073 return nEventCode; 1074 } 1075 1076 1077 1078 1079 sal_uInt32 SelectionFunction::EventDescriptor::EncodeState (void) const 1080 { 1081 sal_uInt32 nEventCode (0); 1082 1083 // Detect whether the event has happened over a page object. 1084 if (mpHitPage!=NULL && mpHitDescriptor) 1085 { 1086 if (mpHitDescriptor->HasState(model::PageDescriptor::ST_Selected)) 1087 nEventCode |= OVER_SELECTED_PAGE; 1088 else 1089 nEventCode |= OVER_UNSELECTED_PAGE; 1090 1091 // Detect whether the mouse is over one of the active elements 1092 // inside a page object. 1093 if (mbIsOverButton) 1094 nEventCode |= OVER_BUTTON; 1095 } 1096 1097 return nEventCode; 1098 } 1099 1100 1101 1102 1103 //===== SelectionFunction::ModeHandler ======================================== 1104 1105 SelectionFunction::ModeHandler::ModeHandler ( 1106 SlideSorter& rSlideSorter, 1107 SelectionFunction& rSelectionFunction, 1108 const bool bIsMouseOverIndicatorAllowed) 1109 : mrSlideSorter(rSlideSorter), 1110 mrSelectionFunction(rSelectionFunction), 1111 mbIsMouseOverIndicatorAllowed(bIsMouseOverIndicatorAllowed) 1112 { 1113 } 1114 1115 1116 1117 1118 SelectionFunction::ModeHandler::~ModeHandler (void) 1119 { 1120 } 1121 1122 1123 1124 1125 void SelectionFunction::ModeHandler::ReprocessEvent (EventDescriptor& rDescriptor) 1126 { 1127 mrSelectionFunction.ProcessEvent(rDescriptor); 1128 } 1129 1130 1131 1132 1133 void SelectionFunction::ModeHandler::ProcessEvent ( 1134 SelectionFunction::EventDescriptor& rDescriptor) 1135 { 1136 PageSelector::BroadcastLock aBroadcastLock (mrSlideSorter); 1137 PageSelector::UpdateLock aUpdateLock (mrSlideSorter); 1138 1139 bool bIsProcessed (false); 1140 switch (rDescriptor.mnEventCode & (BUTTON_DOWN | BUTTON_UP | MOUSE_MOTION | MOUSE_DRAG)) 1141 { 1142 case BUTTON_DOWN: 1143 bIsProcessed = ProcessButtonDownEvent(rDescriptor); 1144 break; 1145 1146 case BUTTON_UP: 1147 bIsProcessed = ProcessButtonUpEvent(rDescriptor); 1148 break; 1149 1150 case MOUSE_MOTION: 1151 bIsProcessed = ProcessMotionEvent(rDescriptor); 1152 break; 1153 1154 case MOUSE_DRAG: 1155 bIsProcessed = ProcessDragEvent(rDescriptor); 1156 break; 1157 } 1158 1159 if ( ! bIsProcessed) 1160 HandleUnprocessedEvent(rDescriptor); 1161 } 1162 1163 1164 1165 1166 bool SelectionFunction::ModeHandler::ProcessButtonDownEvent (EventDescriptor&) 1167 { 1168 return false; 1169 } 1170 1171 1172 1173 1174 bool SelectionFunction::ModeHandler::ProcessButtonUpEvent (EventDescriptor&) 1175 { 1176 mrSelectionFunction.SwitchToNormalMode(); 1177 return false; 1178 } 1179 1180 1181 1182 1183 bool SelectionFunction::ModeHandler::ProcessMotionEvent (EventDescriptor& rDescriptor) 1184 { 1185 if (mbIsMouseOverIndicatorAllowed) 1186 mrSlideSorter.GetView().UpdatePageUnderMouse( 1187 rDescriptor.maMousePosition, 1188 (rDescriptor.mnEventCode & LEFT_BUTTON) != 0, 1189 true); 1190 1191 if (rDescriptor.mbIsLeaving) 1192 { 1193 mrSelectionFunction.SwitchToNormalMode(); 1194 mrSlideSorter.GetView().SetPageUnderMouse(model::SharedPageDescriptor()); 1195 1196 return true; 1197 } 1198 else 1199 return false; 1200 } 1201 1202 1203 1204 1205 bool SelectionFunction::ModeHandler::ProcessDragEvent (EventDescriptor&) 1206 { 1207 return false; 1208 } 1209 1210 1211 1212 1213 bool SelectionFunction::ModeHandler::HandleUnprocessedEvent (EventDescriptor&) 1214 { 1215 return false; 1216 } 1217 1218 1219 1220 1221 void SelectionFunction::ModeHandler::SetCurrentPage ( 1222 const model::SharedPageDescriptor& rpDescriptor) 1223 { 1224 SelectOnePage(rpDescriptor); 1225 mrSlideSorter.GetController().GetCurrentSlideManager()->SwitchCurrentSlide(rpDescriptor); 1226 } 1227 1228 1229 1230 1231 void SelectionFunction::ModeHandler::DeselectAllPages (void) 1232 { 1233 mrSlideSorter.GetController().GetPageSelector().DeselectAllPages(); 1234 mrSelectionFunction.ResetShiftKeySelectionAnchor(); 1235 } 1236 1237 1238 1239 1240 void SelectionFunction::ModeHandler::SelectOnePage ( 1241 const model::SharedPageDescriptor& rpDescriptor) 1242 { 1243 DeselectAllPages(); 1244 mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor); 1245 } 1246 1247 1248 1249 1250 void SelectionFunction::ModeHandler::SwitchView (const model::SharedPageDescriptor& rpDescriptor) 1251 { 1252 // Switch to the draw view. This is done only when the current 1253 // view is the main view. 1254 ViewShell* pViewShell = mrSlideSorter.GetViewShell(); 1255 if (pViewShell!=NULL && pViewShell->IsMainViewShell()) 1256 { 1257 if (rpDescriptor.get()!=NULL && rpDescriptor->GetPage()!=NULL) 1258 { 1259 mrSlideSorter.GetModel().GetDocument()->SetSelected(rpDescriptor->GetPage(), sal_True); 1260 pViewShell->GetFrameView()->SetSelectedPage( 1261 (rpDescriptor->GetPage()->GetPageNum()-1)/2); 1262 } 1263 if (mrSlideSorter.GetViewShellBase() != NULL) 1264 framework::FrameworkHelper::Instance(*mrSlideSorter.GetViewShellBase())->RequestView( 1265 framework::FrameworkHelper::msImpressViewURL, 1266 framework::FrameworkHelper::msCenterPaneURL); 1267 } 1268 } 1269 1270 1271 1272 1273 void SelectionFunction::ModeHandler::StartDrag ( 1274 const Point& rMousePosition, 1275 const InsertionIndicatorHandler::Mode eMode) 1276 { 1277 (void)eMode; 1278 // Do not start a drag-and-drop operation when one is already active. 1279 // (when dragging pages from one document into another, pressing a 1280 // modifier key can trigger a MouseMotion event in the originating 1281 // window (focus still in there). Together with the mouse button pressed 1282 // (drag-and-drop is active) this triggers the start of drag-and-drop.) 1283 if (SD_MOD()->pTransferDrag != NULL) 1284 return; 1285 1286 if ( ! mrSlideSorter.GetProperties()->IsUIReadOnly()) 1287 { 1288 mrSelectionFunction.SwitchToDragAndDropMode(rMousePosition); 1289 } 1290 } 1291 1292 1293 1294 1295 bool SelectionFunction::ModeHandler::IsMouseOverIndicatorAllowed (void) const 1296 { 1297 return mbIsMouseOverIndicatorAllowed; 1298 } 1299 1300 1301 1302 1303 //===== NormalModeHandler ===================================================== 1304 1305 NormalModeHandler::NormalModeHandler ( 1306 SlideSorter& rSlideSorter, 1307 SelectionFunction& rSelectionFunction) 1308 : ModeHandler(rSlideSorter, rSelectionFunction, true), 1309 maButtonDownLocation() 1310 { 1311 } 1312 1313 1314 1315 1316 NormalModeHandler::~NormalModeHandler (void) 1317 { 1318 } 1319 1320 1321 1322 1323 SelectionFunction::Mode NormalModeHandler::GetMode (void) const 1324 { 1325 return SelectionFunction::NormalMode; 1326 } 1327 1328 1329 1330 1331 void NormalModeHandler::Abort (void) 1332 { 1333 } 1334 1335 1336 1337 1338 bool NormalModeHandler::ProcessButtonDownEvent ( 1339 SelectionFunction::EventDescriptor& rDescriptor) 1340 { 1341 // Remember the location where the left button is pressed. With 1342 // that we can filter away motion events that are caused by key 1343 // presses. We also can tune the minimal motion distance that 1344 // triggers a drag-and-drop operation. 1345 if ((rDescriptor.mnEventCode & BUTTON_DOWN) != 0) 1346 maButtonDownLocation = rDescriptor.maMousePosition; 1347 1348 switch (rDescriptor.mnEventCode) 1349 { 1350 case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE: 1351 SetCurrentPage(rDescriptor.mpHitDescriptor); 1352 break; 1353 1354 case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE: 1355 break; 1356 1357 case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | OVER_SELECTED_PAGE: 1358 case BUTTON_DOWN | LEFT_BUTTON | DOUBLE_CLICK | OVER_UNSELECTED_PAGE: 1359 // A double click allways shows the selected slide in the center 1360 // pane in an edit view. 1361 SetCurrentPage(rDescriptor.mpHitDescriptor); 1362 SwitchView(rDescriptor.mpHitDescriptor); 1363 break; 1364 1365 case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | SHIFT_MODIFIER: 1366 case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | SHIFT_MODIFIER: 1367 // Range selection with the shift modifier. 1368 RangeSelect(rDescriptor.mpHitDescriptor); 1369 break; 1370 1371 case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | OVER_BUTTON: 1372 case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | OVER_BUTTON: 1373 OSL_ASSERT(mrSlideSorter.GetView().GetButtonBar().IsMouseOverButton()); 1374 1375 // Switch to button mode only when the buttons are visible 1376 // (or being faded in.) 1377 if (mrSlideSorter.GetView().GetButtonBar().IsVisible(rDescriptor.mpHitDescriptor)) 1378 { 1379 if (mrSelectionFunction.SwitchToButtonMode()) 1380 ReprocessEvent(rDescriptor); 1381 } 1382 else 1383 { 1384 // When the buttons are not (yet) visible then behave like 1385 // the left button had been clicked over any other part of 1386 // the slide. 1387 SetCurrentPage(rDescriptor.mpHitDescriptor); 1388 } 1389 break; 1390 1391 // Right button for context menu. 1392 case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE: 1393 // Single right click and shift+F10 select as preparation to 1394 // show the context menu. Change the selection only when the 1395 // page under the mouse is not selected. In this case the 1396 // selection is set to this single page. Otherwise the 1397 // selection is not modified. 1398 SetCurrentPage(rDescriptor.mpHitDescriptor); 1399 rDescriptor.mbMakeSelectionVisible = false; 1400 break; 1401 1402 case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE: 1403 // Do not change the selection. Just adjust the insertion indicator. 1404 rDescriptor.mbMakeSelectionVisible = false; 1405 break; 1406 1407 case BUTTON_DOWN | RIGHT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE: 1408 // Remember the current selection so that when a multi selection 1409 // is started, we can restore the previous selection. 1410 mrSlideSorter.GetModel().SaveCurrentSelection(); 1411 DeselectAllPages(); 1412 break; 1413 1414 case ANY_MODIFIER(BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE): 1415 // Remember the current selection so that when a multi selection 1416 // is started, we can restore the previous selection. 1417 mrSlideSorter.GetModel().SaveCurrentSelection(); 1418 DeselectAllPages(); 1419 break; 1420 1421 default: 1422 return false; 1423 } 1424 return true; 1425 } 1426 1427 1428 1429 1430 bool NormalModeHandler::ProcessButtonUpEvent ( 1431 SelectionFunction::EventDescriptor& rDescriptor) 1432 { 1433 bool bIsProcessed (true); 1434 switch (rDescriptor.mnEventCode) 1435 { 1436 case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE: 1437 SetCurrentPage(rDescriptor.mpHitDescriptor); 1438 break; 1439 1440 // Multi selection with the control modifier. 1441 case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | CONTROL_MODIFIER: 1442 mrSlideSorter.GetController().GetPageSelector().DeselectPage( 1443 rDescriptor.mpHitDescriptor); 1444 break; 1445 1446 case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | CONTROL_MODIFIER: 1447 mrSlideSorter.GetController().GetPageSelector().SelectPage( 1448 rDescriptor.mpHitDescriptor); 1449 mrSlideSorter.GetView().UpdatePageUnderMouse( 1450 rDescriptor.mpHitDescriptor, 1451 rDescriptor.maMousePosition, 1452 false); 1453 break; 1454 case BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE: 1455 break; 1456 1457 default: 1458 bIsProcessed = false; 1459 break; 1460 } 1461 mrSelectionFunction.SwitchToNormalMode(); 1462 return bIsProcessed; 1463 } 1464 1465 1466 1467 1468 1469 bool NormalModeHandler::ProcessMotionEvent ( 1470 SelectionFunction::EventDescriptor& rDescriptor) 1471 { 1472 if (ModeHandler::ProcessMotionEvent(rDescriptor)) 1473 return true; 1474 1475 bool bIsProcessed (true); 1476 switch (rDescriptor.mnEventCode) 1477 { 1478 case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE): 1479 // SetCurrentPage(rDescriptor.mpHitDescriptor); 1480 // Fallthrough 1481 1482 // A mouse motion without visible substitution starts that. 1483 case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE): 1484 { 1485 if (maButtonDownLocation) 1486 { 1487 const sal_Int32 nDistance (maButtonDownLocation 1488 ? ::std::max ( 1489 abs(maButtonDownLocation->X() - rDescriptor.maMousePosition.X()), 1490 abs(maButtonDownLocation->Y() - rDescriptor.maMousePosition.Y())) 1491 : 0); 1492 if (nDistance > 3) 1493 StartDrag( 1494 rDescriptor.maMousePosition, 1495 (rDescriptor.mnEventCode & CONTROL_MODIFIER) != 0 1496 ? InsertionIndicatorHandler::CopyMode 1497 : InsertionIndicatorHandler::MoveMode); 1498 } 1499 } 1500 break; 1501 1502 // A mouse motion not over a page starts a rectangle selection. 1503 case ANY_MODIFIER(MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK | NOT_OVER_PAGE): 1504 mrSelectionFunction.SwitchToMultiSelectionMode( 1505 rDescriptor.maMouseModelPosition, 1506 rDescriptor.mnEventCode); 1507 break; 1508 1509 default: 1510 bIsProcessed = false; 1511 break; 1512 } 1513 return bIsProcessed; 1514 } 1515 1516 1517 1518 1519 bool NormalModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor) 1520 { 1521 mrSelectionFunction.SwitchToDragAndDropMode(rDescriptor.maMousePosition); 1522 ReprocessEvent(rDescriptor); 1523 return true; 1524 } 1525 1526 1527 1528 1529 void NormalModeHandler::RangeSelect (const model::SharedPageDescriptor& rpDescriptor) 1530 { 1531 PageSelector::UpdateLock aLock (mrSlideSorter); 1532 PageSelector& rSelector (mrSlideSorter.GetController().GetPageSelector()); 1533 1534 model::SharedPageDescriptor pAnchor (rSelector.GetSelectionAnchor()); 1535 DeselectAllPages(); 1536 1537 if (pAnchor.get() != NULL) 1538 { 1539 // Select all pages between the anchor and the given one, including 1540 // the two. 1541 const sal_uInt16 nAnchorIndex ((pAnchor->GetPage()->GetPageNum()-1) / 2); 1542 const sal_uInt16 nOtherIndex ((rpDescriptor->GetPage()->GetPageNum()-1) / 2); 1543 1544 // Iterate over all pages in the range. Start with the anchor 1545 // page. This way the PageSelector will recognize it again as 1546 // anchor (the first selected page after a DeselectAllPages() 1547 // becomes the anchor.) 1548 const sal_uInt16 nStep ((nAnchorIndex < nOtherIndex) ? +1 : -1); 1549 sal_uInt16 nIndex (nAnchorIndex); 1550 while (true) 1551 { 1552 rSelector.SelectPage(nIndex); 1553 if (nIndex == nOtherIndex) 1554 break; 1555 nIndex = nIndex + nStep; 1556 } 1557 } 1558 } 1559 1560 1561 1562 1563 void NormalModeHandler::ResetButtonDownLocation (void) 1564 { 1565 maButtonDownLocation = ::boost::optional<Point>(); 1566 } 1567 1568 1569 1570 1571 //===== MultiSelectionModeHandler ============================================= 1572 1573 MultiSelectionModeHandler::MultiSelectionModeHandler ( 1574 SlideSorter& rSlideSorter, 1575 SelectionFunction& rSelectionFunction, 1576 const Point& rMouseModelPosition, 1577 const sal_uInt32 nEventCode) 1578 : ModeHandler(rSlideSorter, rSelectionFunction, false), 1579 meSelectionMode(SM_Normal), 1580 maSecondCorner(rMouseModelPosition), 1581 maSavedPointer(mrSlideSorter.GetContentWindow()->GetPointer()), 1582 mnAnchorIndex(-1), 1583 mnSecondIndex(-1), 1584 maButtonBarLock(rSlideSorter) 1585 { 1586 const Pointer aSelectionPointer (POINTER_TEXT); 1587 mrSlideSorter.GetContentWindow()->SetPointer(aSelectionPointer); 1588 SetSelectionModeFromModifier(nEventCode); 1589 } 1590 1591 1592 1593 1594 1595 MultiSelectionModeHandler::~MultiSelectionModeHandler (void) 1596 { 1597 mrSlideSorter.GetContentWindow()->SetPointer(maSavedPointer); 1598 } 1599 1600 1601 1602 1603 SelectionFunction::Mode MultiSelectionModeHandler::GetMode (void) const 1604 { 1605 return SelectionFunction::MultiSelectionMode; 1606 } 1607 1608 1609 1610 1611 void MultiSelectionModeHandler::Abort (void) 1612 { 1613 mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection()); 1614 } 1615 1616 1617 1618 1619 void MultiSelectionModeHandler::ProcessEvent ( 1620 SelectionFunction::EventDescriptor& rDescriptor) 1621 { 1622 // During a multi selection we do not want sudden jumps of the 1623 // visible area caused by moving newly selected pages into view. 1624 // Therefore disable that temporarily. The disabler object is 1625 // released at the end of the event processing, after the focus and 1626 // current slide have been updated. 1627 VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter); 1628 1629 ModeHandler::ProcessEvent(rDescriptor); 1630 } 1631 1632 1633 1634 1635 bool MultiSelectionModeHandler::ProcessButtonUpEvent ( 1636 SelectionFunction::EventDescriptor& rDescriptor) 1637 { 1638 if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON | SINGLE_CLICK)) 1639 { 1640 mrSelectionFunction.SwitchToNormalMode(); 1641 return true; 1642 } 1643 else 1644 return false; 1645 } 1646 1647 1648 1649 1650 bool MultiSelectionModeHandler::ProcessMotionEvent ( 1651 SelectionFunction::EventDescriptor& rDescriptor) 1652 { 1653 // The selection rectangle is visible. Handle events accordingly. 1654 if (Match(rDescriptor.mnEventCode, MOUSE_MOTION | LEFT_BUTTON | SINGLE_CLICK)) 1655 { 1656 SetSelectionModeFromModifier(rDescriptor.mnEventCode); 1657 UpdatePosition(rDescriptor.maMousePosition, true); 1658 rDescriptor.mbMakeSelectionVisible = false; 1659 return true; 1660 } 1661 else 1662 return false; 1663 } 1664 1665 1666 1667 bool MultiSelectionModeHandler::HandleUnprocessedEvent ( 1668 SelectionFunction::EventDescriptor& rDescriptor) 1669 { 1670 if ( ! ModeHandler::HandleUnprocessedEvent(rDescriptor)) 1671 { 1672 // If the event has not been processed then stop multi selection. 1673 mrSelectionFunction.SwitchToNormalMode(); 1674 ReprocessEvent(rDescriptor); 1675 } 1676 return true; 1677 } 1678 1679 1680 1681 1682 void MultiSelectionModeHandler::UpdatePosition ( 1683 const Point& rMousePosition, 1684 const bool bAllowAutoScroll) 1685 { 1686 VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter); 1687 1688 // Convert window coordinates into model coordinates (we need the 1689 // window coordinates for auto-scrolling because that remains 1690 // constant while scrolling.) 1691 SharedSdWindow pWindow (mrSlideSorter.GetContentWindow()); 1692 const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition)); 1693 1694 if ( ! (bAllowAutoScroll && mrSlideSorter.GetController().GetScrollBarManager().AutoScroll( 1695 rMousePosition, 1696 ::boost::bind( 1697 &MultiSelectionModeHandler::UpdatePosition, 1698 this, 1699 rMousePosition, 1700 false)))) 1701 { 1702 UpdateModelPosition(aMouseModelPosition); 1703 } 1704 } 1705 1706 1707 1708 1709 void MultiSelectionModeHandler::SetSelectionModeFromModifier ( 1710 const sal_uInt32 nEventCode) 1711 { 1712 switch (nEventCode & MODIFIER_MASK) 1713 { 1714 case NO_MODIFIER: 1715 SetSelectionMode(SM_Normal); 1716 break; 1717 1718 case SHIFT_MODIFIER: 1719 SetSelectionMode(SM_Add); 1720 break; 1721 1722 case CONTROL_MODIFIER: 1723 SetSelectionMode(SM_Toggle); 1724 break; 1725 } 1726 } 1727 1728 1729 1730 1731 void MultiSelectionModeHandler::SetSelectionMode (const SelectionMode eSelectionMode) 1732 { 1733 if (meSelectionMode != eSelectionMode) 1734 { 1735 meSelectionMode = eSelectionMode; 1736 UpdateSelection(); 1737 } 1738 } 1739 1740 1741 1742 1743 void MultiSelectionModeHandler::UpdateSelectionState ( 1744 const model::SharedPageDescriptor& rpDescriptor, 1745 const bool bIsInSelection) const 1746 { 1747 // Determine whether the page was selected before the rectangle 1748 // selection was started. 1749 const bool bWasSelected (rpDescriptor->HasState(model::PageDescriptor::ST_WasSelected)); 1750 1751 // Combine the two selection states depending on the selection mode. 1752 bool bSelect (false); 1753 switch(meSelectionMode) 1754 { 1755 case SM_Normal: 1756 bSelect = bIsInSelection; 1757 break; 1758 1759 case SM_Add: 1760 bSelect = bIsInSelection || bWasSelected; 1761 break; 1762 1763 case SM_Toggle: 1764 if (bIsInSelection) 1765 bSelect = !bWasSelected; 1766 else 1767 bSelect = bWasSelected; 1768 break; 1769 } 1770 1771 // Set the new selection state. 1772 if (bSelect) 1773 mrSlideSorter.GetController().GetPageSelector().SelectPage(rpDescriptor); 1774 else 1775 mrSlideSorter.GetController().GetPageSelector().DeselectPage(rpDescriptor); 1776 } 1777 1778 1779 1780 1781 void MultiSelectionModeHandler::UpdateModelPosition (const Point& rMouseModelPosition) 1782 { 1783 maSecondCorner = rMouseModelPosition; 1784 UpdateSelection(); 1785 } 1786 1787 1788 1789 1790 void MultiSelectionModeHandler::UpdateSelection (void) 1791 { 1792 view::SlideSorterView::DrawLock aLock (mrSlideSorter); 1793 1794 model::SlideSorterModel& rModel (mrSlideSorter.GetModel()); 1795 const sal_Int32 nPageCount (rModel.GetPageCount()); 1796 1797 const sal_Int32 nIndexUnderMouse ( 1798 mrSlideSorter.GetView().GetLayouter().GetIndexAtPoint ( 1799 maSecondCorner, 1800 false, 1801 false)); 1802 if (nIndexUnderMouse>=0 && nIndexUnderMouse<nPageCount) 1803 { 1804 if (mnAnchorIndex < 0) 1805 mnAnchorIndex = nIndexUnderMouse; 1806 mnSecondIndex = nIndexUnderMouse; 1807 1808 Range aRange (mnAnchorIndex, mnSecondIndex); 1809 aRange.Justify(); 1810 1811 for (sal_Int32 nIndex=0; nIndex<nPageCount; ++nIndex) 1812 { 1813 UpdateSelectionState(rModel.GetPageDescriptor(nIndex), aRange.IsInside(nIndex)); 1814 } 1815 } 1816 } 1817 1818 1819 1820 1821 //===== DragAndDropModeHandler ================================================ 1822 1823 DragAndDropModeHandler::DragAndDropModeHandler ( 1824 SlideSorter& rSlideSorter, 1825 SelectionFunction& rSelectionFunction, 1826 const Point& rMousePosition, 1827 ::Window* pWindow) 1828 : ModeHandler(rSlideSorter, rSelectionFunction, false) 1829 { 1830 SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; 1831 if (pDragTransferable==NULL && mrSlideSorter.GetViewShell() != NULL) 1832 { 1833 SlideSorterViewShell* pSlideSorterViewShell 1834 = dynamic_cast<SlideSorterViewShell*>(mrSlideSorter.GetViewShell()); 1835 if (pSlideSorterViewShell != NULL) 1836 pSlideSorterViewShell->StartDrag(rMousePosition, pWindow); 1837 pDragTransferable = SD_MOD()->pTransferDrag; 1838 } 1839 1840 mpDragAndDropContext.reset(new DragAndDropContext(mrSlideSorter)); 1841 mrSlideSorter.GetController().GetInsertionIndicatorHandler()->Start( 1842 pDragTransferable != NULL 1843 && pDragTransferable->GetView()==&mrSlideSorter.GetView()); 1844 } 1845 1846 1847 1848 1849 DragAndDropModeHandler::~DragAndDropModeHandler (void) 1850 { 1851 if (mpDragAndDropContext) 1852 { 1853 // Disconnect the substitution handler from this selection function. 1854 mpDragAndDropContext->SetTargetSlideSorter(); 1855 mpDragAndDropContext.reset(); 1856 } 1857 mrSlideSorter.GetController().GetInsertionIndicatorHandler()->End(Animator::AM_Animated); 1858 } 1859 1860 1861 1862 1863 SelectionFunction::Mode DragAndDropModeHandler::GetMode (void) const 1864 { 1865 return SelectionFunction::DragAndDropMode; 1866 } 1867 1868 1869 1870 1871 void DragAndDropModeHandler::Abort (void) 1872 { 1873 mrSlideSorter.GetController().GetClipboard().Abort(); 1874 if (mpDragAndDropContext) 1875 mpDragAndDropContext->Dispose(); 1876 // mrSlideSorter.GetView().RequestRepaint(mrSlideSorter.GetModel().RestoreSelection()); 1877 } 1878 1879 1880 1881 1882 bool DragAndDropModeHandler::ProcessButtonUpEvent ( 1883 SelectionFunction::EventDescriptor& rDescriptor) 1884 { 1885 if (Match(rDescriptor.mnEventCode, BUTTON_UP | LEFT_BUTTON)) 1886 { 1887 // The following Process() call may lead to the desctruction 1888 // of rDescriptor.mpHitDescriptor so release our reference to it. 1889 rDescriptor.mpHitDescriptor.reset(); 1890 mrSelectionFunction.SwitchToNormalMode(); 1891 return true; 1892 } 1893 else 1894 return false; 1895 } 1896 1897 1898 1899 1900 bool DragAndDropModeHandler::ProcessDragEvent (SelectionFunction::EventDescriptor& rDescriptor) 1901 { 1902 OSL_ASSERT(mpDragAndDropContext); 1903 1904 if (rDescriptor.mbIsLeaving) 1905 { 1906 mrSelectionFunction.SwitchToNormalMode(); 1907 } 1908 else if (mpDragAndDropContext) 1909 { 1910 mpDragAndDropContext->UpdatePosition( 1911 rDescriptor.maMousePosition, 1912 rDescriptor.meDragMode); 1913 } 1914 1915 return true; 1916 } 1917 1918 1919 1920 1921 //===== ButtonModeHandler ===================================================== 1922 1923 ButtonModeHandler::ButtonModeHandler ( 1924 SlideSorter& rSlideSorter, 1925 SelectionFunction& rSelectionFunction) 1926 : ModeHandler(rSlideSorter, rSelectionFunction, true) 1927 { 1928 } 1929 1930 1931 1932 1933 ButtonModeHandler::~ButtonModeHandler (void) 1934 { 1935 } 1936 1937 1938 1939 1940 SelectionFunction::Mode ButtonModeHandler::GetMode (void) const 1941 { 1942 return SelectionFunction::ButtonMode; 1943 } 1944 1945 1946 1947 1948 void ButtonModeHandler::Abort (void) 1949 { 1950 } 1951 1952 1953 1954 1955 bool ButtonModeHandler::ProcessButtonDownEvent (SelectionFunction::EventDescriptor& rDescriptor) 1956 { 1957 switch (rDescriptor.mnEventCode) 1958 { 1959 case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_UNSELECTED_PAGE | OVER_BUTTON: 1960 case BUTTON_DOWN | LEFT_BUTTON | SINGLE_CLICK | OVER_SELECTED_PAGE | OVER_BUTTON: 1961 // Remember page and button index. When mouse button is 1962 // released over same page and button then invoke action of that 1963 // button. 1964 mrSlideSorter.GetView().GetButtonBar().ProcessButtonDownEvent( 1965 rDescriptor.mpHitDescriptor, 1966 rDescriptor.maMouseModelPosition); 1967 return true; 1968 1969 default: 1970 return false; 1971 } 1972 } 1973 1974 1975 1976 1977 bool ButtonModeHandler::ProcessButtonUpEvent (SelectionFunction::EventDescriptor& rDescriptor) 1978 { 1979 switch (rDescriptor.mnEventCode & BUTTON_MASK) 1980 { 1981 case LEFT_BUTTON: 1982 mrSlideSorter.GetView().GetButtonBar().ProcessButtonUpEvent( 1983 rDescriptor.mpHitDescriptor, 1984 rDescriptor.maMouseModelPosition); 1985 mrSelectionFunction.SwitchToNormalMode(); 1986 return true; 1987 } 1988 1989 return false; 1990 } 1991 1992 1993 1994 1995 bool ButtonModeHandler::ProcessMotionEvent (SelectionFunction::EventDescriptor& rDescriptor) 1996 { 1997 switch (rDescriptor.mnEventCode & (MOUSE_MOTION | BUTTON_MASK)) 1998 { 1999 case MOUSE_MOTION | LEFT_BUTTON: 2000 mrSlideSorter.GetView().GetButtonBar().ProcessMouseMotionEvent( 2001 rDescriptor.mpHitDescriptor, 2002 rDescriptor.maMouseModelPosition, 2003 true); 2004 return true; 2005 2006 case MOUSE_MOTION: 2007 mrSlideSorter.GetView().GetButtonBar().ProcessMouseMotionEvent( 2008 rDescriptor.mpHitDescriptor, 2009 rDescriptor.maMouseModelPosition, 2010 false); 2011 return true; 2012 } 2013 2014 return false; 2015 } 2016 2017 2018 2019 2020 } } } // end of namespace ::sd::slidesorter::controller 2021