1 #/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <SlideSorterViewShell.hxx> 21 #include <ViewShellImplementation.hxx> 22 23 #include <SlideSorter.hxx> 24 #include <controller/SlideSorterController.hxx> 25 #include <controller/SlsClipboard.hxx> 26 #include <controller/SlsScrollBarManager.hxx> 27 #include <controller/SlsPageSelector.hxx> 28 #include <controller/SlsSlotManager.hxx> 29 #include <controller/SlsCurrentSlideManager.hxx> 30 #include <controller/SlsSelectionManager.hxx> 31 #include <view/SlideSorterView.hxx> 32 #include <view/SlsLayouter.hxx> 33 #include <model/SlideSorterModel.hxx> 34 #include <model/SlsPageDescriptor.hxx> 35 #include <framework/FrameworkHelper.hxx> 36 #include <ViewShellBase.hxx> 37 #include <drawdoc.hxx> 38 #include <sdpage.hxx> 39 #include <app.hrc> 40 #include <AccessibleSlideSorterView.hxx> 41 #include <DrawDocShell.hxx> 42 #include <DrawViewShell.hxx> 43 #include <FrameView.hxx> 44 #include <SdUnoSlideView.hxx> 45 #include <ViewShellManager.hxx> 46 #include <Window.hxx> 47 #include <drawview.hxx> 48 #include <sfx2/msg.hxx> 49 #include <sfx2/objface.hxx> 50 #include <sfx2/viewfrm.hxx> 51 #include <sfx2/bindings.hxx> 52 #include <sfx2/request.hxx> 53 #include <sfx2/sidebar/SidebarChildWindow.hxx> 54 #include <sfx2/devtools/DevelopmentToolChildWindow.hxx> 55 #include <svx/svxids.hrc> 56 #include <vcl/EnumContext.hxx> 57 #include <svx/sidebar/ContextChangeEventMultiplexer.hxx> 58 #include <tools/diagnose_ex.h> 59 #include <sfx2/sidebar/SidebarController.hxx> 60 61 using namespace ::sd::slidesorter; 62 #define ShellClass_SlideSorterViewShell 63 #include <sdslots.hxx> 64 65 using namespace ::com::sun::star; 66 using namespace ::com::sun::star::uno; 67 using namespace ::com::sun::star::drawing::framework; 68 69 using ::sd::framework::FrameworkHelper; 70 using ::vcl::EnumContext; 71 using namespace sfx2::sidebar; 72 73 namespace sd::slidesorter { 74 75 namespace { 76 77 bool inChartContext(sd::View* pView) 78 { 79 if (!pView) 80 return false; 81 82 SfxViewShell* pViewShell = pView->GetSfxViewShell(); 83 SidebarController* pSidebar = SidebarController::GetSidebarControllerForView(pViewShell); 84 if (pSidebar) 85 return pSidebar->hasChartContextCurrently(); 86 87 return false; 88 } 89 90 } // anonymous namespace 91 92 93 SFX_IMPL_INTERFACE(SlideSorterViewShell, SfxShell) 94 95 void SlideSorterViewShell::InitInterface_Impl() 96 { 97 GetStaticInterface()->RegisterChildWindow(::sfx2::sidebar::SidebarChildWindow::GetChildWindowId()); 98 GetStaticInterface()->RegisterChildWindow(DevelopmentToolChildWindow::GetChildWindowId()); 99 } 100 101 102 std::shared_ptr<SlideSorterViewShell> SlideSorterViewShell::Create ( 103 SfxViewFrame* pFrame, 104 ViewShellBase& rViewShellBase, 105 vcl::Window* pParentWindow, 106 FrameView* pFrameViewArgument) 107 { 108 std::shared_ptr<SlideSorterViewShell> pViewShell; 109 try 110 { 111 pViewShell.reset( 112 new SlideSorterViewShell(pFrame,rViewShellBase,pParentWindow,pFrameViewArgument)); 113 pViewShell->Initialize(); 114 if (pViewShell->mpSlideSorter == nullptr) 115 pViewShell.reset(); 116 } 117 catch(Exception&) 118 { 119 pViewShell.reset(); 120 } 121 return pViewShell; 122 } 123 124 SlideSorterViewShell::SlideSorterViewShell ( 125 SfxViewFrame* /*pFrame*/, 126 ViewShellBase& rViewShellBase, 127 vcl::Window* pParentWindow, 128 FrameView* pFrameViewArgument) 129 : ViewShell (pParentWindow, rViewShellBase), 130 mpSlideSorter(), 131 mbIsArrangeGUIElementsPending(true) 132 { 133 GetContentWindow()->set_id("slidesorter"); 134 meShellType = ST_SLIDE_SORTER; 135 136 if (pFrameViewArgument != nullptr) 137 mpFrameView = pFrameViewArgument; 138 else 139 mpFrameView = new FrameView(GetDoc()); 140 GetFrameView()->Connect(); 141 142 SetName ("SlideSorterViewShell"); 143 144 pParentWindow->SetStyle(pParentWindow->GetStyle() | WB_DIALOGCONTROL); 145 } 146 147 SlideSorterViewShell::~SlideSorterViewShell() 148 { 149 DisposeFunctions(); 150 151 try 152 { 153 ::sd::Window* pWindow = GetActiveWindow(); 154 if (pWindow!=nullptr) 155 { 156 css::uno::Reference<css::lang::XComponent> xComponent ( 157 pWindow->GetAccessible(false), 158 css::uno::UNO_QUERY); 159 if (xComponent.is()) 160 xComponent->dispose(); 161 } 162 } 163 catch( css::uno::Exception& ) 164 { 165 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideSorterViewShell::~SlideSorterViewShell()" ); 166 } 167 GetFrameView()->Disconnect(); 168 } 169 170 void SlideSorterViewShell::Initialize() 171 { 172 mpSlideSorter = SlideSorter::CreateSlideSorter( 173 *this, 174 mpContentWindow, 175 mpHorizontalScrollBar, 176 mpVerticalScrollBar, 177 mpScrollBarBox); 178 mpView = &mpSlideSorter->GetView(); 179 180 doShow(); 181 182 SetPool( &GetDoc()->GetPool() ); 183 SetUndoManager( GetDoc()->GetDocSh()->GetUndoManager() ); 184 185 // For accessibility we have to shortly hide the content window. 186 // This triggers the construction of a new accessibility object for 187 // the new view shell. (One is created earlier while the constructor 188 // of the base class is executed. At that time the correct 189 // accessibility object can not be constructed.) 190 sd::Window *pWindow (mpSlideSorter->GetContentWindow().get()); 191 if (pWindow) 192 { 193 pWindow->Hide(); 194 pWindow->Show(); 195 } 196 } 197 198 void SlideSorterViewShell::Init (bool bIsMainViewShell) 199 { 200 ViewShell::Init(bIsMainViewShell); 201 202 // since the updatePageList will show focus, the window.show() must be called ahead. This show is deferred from Init() 203 ::sd::Window* pActiveWindow = GetActiveWindow(); 204 if (pActiveWindow) 205 pActiveWindow->Show(); 206 mpSlideSorter->GetModel().UpdatePageList(); 207 208 if (mpContentWindow) 209 mpContentWindow->SetViewShell(this); 210 } 211 212 SlideSorterViewShell* SlideSorterViewShell::GetSlideSorter (ViewShellBase& rBase) 213 { 214 SlideSorterViewShell* pViewShell = nullptr; 215 216 // Test the center and left pane for showing a slide sorter. 217 OUString aPaneURLs[] = { 218 FrameworkHelper::msCenterPaneURL, 219 FrameworkHelper::msFullScreenPaneURL, 220 FrameworkHelper::msLeftImpressPaneURL, 221 FrameworkHelper::msLeftDrawPaneURL, 222 OUString()}; 223 224 try 225 { 226 std::shared_ptr<FrameworkHelper> pFrameworkHelper (FrameworkHelper::Instance(rBase)); 227 if (pFrameworkHelper->IsValid()) 228 for (int i=0; pViewShell==nullptr && !aPaneURLs[i].isEmpty(); ++i) 229 { 230 pViewShell = dynamic_cast<SlideSorterViewShell*>( 231 pFrameworkHelper->GetViewShell(aPaneURLs[i]).get()); 232 } 233 } 234 catch (RuntimeException&) 235 {} 236 237 return pViewShell; 238 } 239 240 Reference<drawing::XDrawSubController> SlideSorterViewShell::CreateSubController() 241 { 242 Reference<drawing::XDrawSubController> xSubController; 243 244 if (IsMainViewShell()) 245 { 246 // Create uno controller for the main view shell. 247 xSubController.set( new SdUnoSlideView( *mpSlideSorter)); 248 } 249 250 return xSubController; 251 } 252 253 /** If there is a valid controller then create a new instance of 254 <type>AccessibleSlideSorterView</type>. Otherwise delegate this call 255 to the base class to return a default object (probably an empty 256 reference). 257 */ 258 css::uno::Reference<css::accessibility::XAccessible> 259 SlideSorterViewShell::CreateAccessibleDocumentView (::sd::Window* pWindow) 260 { 261 // When the view is not set then the initialization is not yet complete 262 // and we can not yet provide an accessibility object. 263 if (mpView == nullptr || mpSlideSorter == nullptr) 264 return nullptr; 265 266 assert(mpSlideSorter); 267 268 rtl::Reference<::accessibility::AccessibleSlideSorterView> pAccessibleView = 269 new ::accessibility::AccessibleSlideSorterView( 270 *mpSlideSorter, 271 pWindow); 272 273 pAccessibleView->Init(); 274 275 return pAccessibleView; 276 } 277 278 void SlideSorterViewShell::SwitchViewFireFocus(const css::uno::Reference< css::accessibility::XAccessible >& xAcc ) 279 { 280 if (xAcc) 281 { 282 ::accessibility::AccessibleSlideSorterView* pBase = static_cast< ::accessibility::AccessibleSlideSorterView* >(xAcc.get()); 283 if (pBase) 284 { 285 pBase->SwitchViewActivated(); 286 } 287 } 288 } 289 290 SlideSorter& SlideSorterViewShell::GetSlideSorter() const 291 { 292 assert(mpSlideSorter); 293 return *mpSlideSorter; 294 } 295 296 bool SlideSorterViewShell::RelocateToParentWindow (vcl::Window* pParentWindow) 297 { 298 assert(mpSlideSorter); 299 if ( ! mpSlideSorter) 300 return false; 301 302 mpSlideSorter->RelocateToWindow(pParentWindow); 303 ReadFrameViewData(mpFrameView); 304 305 return true; 306 } 307 308 SfxUndoManager* SlideSorterViewShell::ImpGetUndoManager() const 309 { 310 SfxShell* pObjectBar = GetViewShellBase().GetViewShellManager()->GetTopShell(); 311 if (pObjectBar != nullptr) 312 { 313 // When it exists then return the undo manager of the currently 314 // active object bar. The object bar is missing when the 315 // SlideSorterViewShell is not the main view shell. 316 return pObjectBar->GetUndoManager(); 317 } 318 else 319 { 320 // Return the undo manager of this shell when there is no object or 321 // tool bar. 322 return const_cast<SlideSorterViewShell*>(this)->GetUndoManager(); 323 } 324 } 325 326 SdPage* SlideSorterViewShell::getCurrentPage() const 327 { 328 // since SlideSorterViewShell::GetActualPage() currently also 329 // returns master pages, which is a wrong behaviour for GetActualPage(), 330 // we can just use that for now 331 return const_cast<SlideSorterViewShell*>(this)->GetActualPage(); 332 } 333 334 SdPage* SlideSorterViewShell::GetActualPage() 335 { 336 SdPage* pCurrentPage = nullptr; 337 338 // 1. Try to get the current page from the view shell in the center pane 339 // (if we are that not ourself). 340 if ( ! IsMainViewShell()) 341 { 342 std::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell(); 343 if (pMainViewShell != nullptr) 344 pCurrentPage = pMainViewShell->GetActualPage(); 345 } 346 347 if (pCurrentPage == nullptr) 348 { 349 model::SharedPageDescriptor pDescriptor ( 350 mpSlideSorter->GetController().GetCurrentSlideManager()->GetCurrentSlide()); 351 if (pDescriptor) 352 pCurrentPage = pDescriptor->GetPage(); 353 } 354 355 return pCurrentPage; 356 } 357 358 void SlideSorterViewShell::GetMenuState ( SfxItemSet& rSet) 359 { 360 ViewShell::GetMenuState(rSet); 361 assert(mpSlideSorter); 362 mpSlideSorter->GetController().GetSlotManager()->GetMenuState(rSet); 363 } 364 365 void SlideSorterViewShell::GetClipboardState ( SfxItemSet& rSet) 366 { 367 ViewShell::GetMenuState(rSet); 368 assert(mpSlideSorter); 369 mpSlideSorter->GetController().GetSlotManager()->GetClipboardState(rSet); 370 } 371 372 void SlideSorterViewShell::ExecCtrl (SfxRequest& rRequest) 373 { 374 assert(mpSlideSorter); 375 mpSlideSorter->GetController().ExecCtrl(rRequest); 376 } 377 378 void SlideSorterViewShell::GetCtrlState (SfxItemSet& rSet) 379 { 380 assert(mpSlideSorter); 381 mpSlideSorter->GetController().GetCtrlState(rSet); 382 } 383 384 void SlideSorterViewShell::FuSupport (SfxRequest& rRequest) 385 { 386 assert(mpSlideSorter); 387 mpSlideSorter->GetController().FuSupport(rRequest); 388 } 389 390 /** We have to handle those slot calls here that need to have access to 391 private or protected members and methods of this class. 392 */ 393 void SlideSorterViewShell::FuTemporary (SfxRequest& rRequest) 394 { 395 assert(mpSlideSorter); 396 switch (rRequest.GetSlot()) 397 { 398 case SID_MODIFYPAGE: 399 { 400 SdPage* pCurrentPage = GetActualPage(); 401 if (pCurrentPage != nullptr) 402 mpImpl->ProcessModifyPageSlot ( 403 rRequest, 404 pCurrentPage, 405 PageKind::Standard); 406 Cancel(); 407 rRequest.Done (); 408 } 409 break; 410 411 default: 412 mpSlideSorter->GetController().FuTemporary(rRequest); 413 break; 414 } 415 } 416 417 void SlideSorterViewShell::GetStatusBarState (SfxItemSet& rSet) 418 { 419 assert(mpSlideSorter); 420 mpSlideSorter->GetController().GetStatusBarState(rSet); 421 } 422 423 void SlideSorterViewShell::FuPermanent (SfxRequest& rRequest) 424 { 425 assert(mpSlideSorter); 426 mpSlideSorter->GetController().FuPermanent(rRequest); 427 } 428 429 void SlideSorterViewShell::GetAttrState (SfxItemSet& rSet) 430 { 431 assert(mpSlideSorter); 432 mpSlideSorter->GetController().GetAttrState(rSet); 433 } 434 435 void SlideSorterViewShell::ExecStatusBar (SfxRequest& ) 436 { 437 } 438 439 void SlideSorterViewShell::Paint ( 440 const ::tools::Rectangle& rBBox, 441 ::sd::Window* pWindow) 442 { 443 SetActiveWindow (pWindow); 444 assert(mpSlideSorter); 445 if (mpSlideSorter) 446 mpSlideSorter->GetController().Paint(rBBox,pWindow); 447 } 448 449 void SlideSorterViewShell::ArrangeGUIElements() 450 { 451 if (IsActive()) 452 { 453 assert(mpSlideSorter); 454 mpSlideSorter->ArrangeGUIElements(maViewPos, maViewSize); 455 mbIsArrangeGUIElementsPending = false; 456 } 457 else 458 mbIsArrangeGUIElementsPending = true; 459 } 460 461 void SlideSorterViewShell::Activate (bool bIsMDIActivate) 462 { 463 if(inChartContext(GetView())) 464 { 465 // Avoid context changes for chart during activation / deactivation. 466 const bool bIsContextBroadcasterEnabled (SfxShell::SetContextBroadcasterEnabled(false)); 467 468 ViewShell::Activate(bIsMDIActivate); 469 470 SfxShell::SetContextBroadcasterEnabled(bIsContextBroadcasterEnabled); 471 return; 472 } 473 474 ViewShell::Activate(bIsMDIActivate); 475 if (mbIsArrangeGUIElementsPending) 476 ArrangeGUIElements(); 477 478 // Determine and broadcast the context that belongs to the main view shell. 479 EnumContext::Context eContext = EnumContext::Context::Unknown; 480 std::shared_ptr<ViewShell> pMainViewShell (GetViewShellBase().GetMainViewShell()); 481 ViewShell::ShellType eMainViewShellType ( 482 pMainViewShell 483 ? pMainViewShell->GetShellType() 484 : ViewShell::ST_NONE); 485 switch (eMainViewShellType) 486 { 487 case ViewShell::ST_IMPRESS: 488 case ViewShell::ST_SLIDE_SORTER: 489 case ViewShell::ST_NOTES: 490 case ViewShell::ST_DRAW: 491 eContext = EnumContext::Context::DrawPage; 492 if( nullptr != dynamic_cast< const DrawViewShell *>( pMainViewShell.get() )) 493 { 494 DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(pMainViewShell.get()); 495 if (pDrawViewShell != nullptr) 496 eContext = EnumContext::GetContextEnum(pDrawViewShell->GetSidebarContextName()); 497 } 498 break; 499 500 default: 501 break; 502 } 503 ContextChangeEventMultiplexer::NotifyContextChange( 504 &GetViewShellBase(), 505 eContext); 506 } 507 508 void SlideSorterViewShell::Deactivate (bool /*bIsMDIActivate*/) 509 { 510 // Save Settings - Specifically SlidesPerRow to retrieve it later 511 WriteFrameViewData(); 512 } 513 514 void SlideSorterViewShell::Command ( 515 const CommandEvent& rEvent, 516 ::sd::Window* pWindow) 517 { 518 assert(mpSlideSorter); 519 if ( ! mpSlideSorter->GetController().Command (rEvent, pWindow)) 520 ViewShell::Command (rEvent, pWindow); 521 } 522 523 void SlideSorterViewShell::ReadFrameViewData (FrameView* pFrameView) 524 { 525 assert(mpSlideSorter); 526 if (pFrameView != nullptr) 527 { 528 view::SlideSorterView& rView (mpSlideSorter->GetView()); 529 530 sal_uInt16 nSlidesPerRow (pFrameView->GetSlidesPerRow()); 531 if (nSlidesPerRow > 0 532 && rView.GetOrientation() == view::Layouter::GRID 533 && IsMainViewShell()) 534 { 535 rView.GetLayouter().SetColumnCount(nSlidesPerRow,nSlidesPerRow); 536 } 537 if (IsMainViewShell()) 538 mpSlideSorter->GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange( 539 mpFrameView->GetSelectedPage()); 540 mpSlideSorter->GetController().Rearrange(true); 541 542 // DrawMode for 'main' window 543 if (GetActiveWindow()->GetOutDev()->GetDrawMode() != pFrameView->GetDrawMode() ) 544 GetActiveWindow()->GetOutDev()->SetDrawMode( pFrameView->GetDrawMode() ); 545 } 546 547 // When this slide sorter is not displayed in the main window then we do 548 // not share the same frame view and have to find other ways to acquire 549 // certain values. 550 if ( ! IsMainViewShell()) 551 { 552 std::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell(); 553 if (pMainViewShell != nullptr) 554 mpSlideSorter->GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange( 555 pMainViewShell->getCurrentPage()); 556 } 557 } 558 559 void SlideSorterViewShell::WriteFrameViewData() 560 { 561 assert(mpSlideSorter); 562 if (mpFrameView == nullptr) 563 return; 564 565 view::SlideSorterView& rView (mpSlideSorter->GetView()); 566 mpFrameView->SetSlidesPerRow(static_cast<sal_uInt16>(rView.GetLayouter().GetColumnCount())); 567 568 // DrawMode for 'main' window 569 if( mpFrameView->GetDrawMode() != GetActiveWindow()->GetOutDev()->GetDrawMode() ) 570 mpFrameView->SetDrawMode( GetActiveWindow()->GetOutDev()->GetDrawMode() ); 571 572 SdPage* pActualPage = GetActualPage(); 573 if (pActualPage != nullptr) 574 { 575 if (IsMainViewShell()) 576 mpFrameView->SetSelectedPage((pActualPage->GetPageNum()- 1) / 2); 577 // else 578 // The slide sorter is not expected to switch the current page 579 // other than by double clicks. That is handled separately. 580 } 581 else 582 { 583 // We have no current page to set but at least we can make sure 584 // that the index of the frame view has a legal value. 585 if (mpFrameView->GetSelectedPage() >= mpSlideSorter->GetModel().GetPageCount()) 586 mpFrameView->SetSelectedPage(static_cast<sal_uInt16>(mpSlideSorter->GetModel().GetPageCount())-1); 587 } 588 } 589 590 void SlideSorterViewShell::SetZoom (::tools::Long ) 591 { 592 // Ignored. 593 // The zoom scale is adapted internally to fit a number of columns in 594 // the window. 595 } 596 597 void SlideSorterViewShell::SetZoomRect (const ::tools::Rectangle& rZoomRect) 598 { 599 assert(mpSlideSorter); 600 Size aPageSize (mpSlideSorter->GetView().GetLayouter().GetPageObjectSize()); 601 602 ::tools::Rectangle aRect(rZoomRect); 603 604 if (aRect.GetWidth() < aPageSize.Width()) 605 { 606 ::tools::Long nWidthDiff = (aPageSize.Width() - aRect.GetWidth()) / 2; 607 608 aRect.AdjustLeft( -nWidthDiff ); 609 aRect.AdjustRight(nWidthDiff ); 610 611 if (aRect.Left() < 0) 612 { 613 aRect.SetPos(Point(0, aRect.Top())); 614 } 615 } 616 617 if (aRect.GetHeight() < aPageSize.Height()) 618 { 619 ::tools::Long nHeightDiff = (aPageSize.Height() - aRect.GetHeight()) / 2; 620 621 aRect.AdjustTop( -nHeightDiff ); 622 aRect.AdjustBottom(nHeightDiff ); 623 624 if (aRect.Top() < 0) 625 { 626 aRect.SetPos(Point(aRect.Left(), 0)); 627 } 628 } 629 630 ViewShell::SetZoomRect(aRect); 631 632 GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOM ); 633 GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER ); 634 } 635 636 void SlideSorterViewShell::UpdateScrollBars() 637 { 638 // Do not call the overwritten method of the base class: We do all the 639 // scroll bar setup by ourselves. 640 mpSlideSorter->GetController().GetScrollBarManager().UpdateScrollBars(true); 641 } 642 643 void SlideSorterViewShell::StartDrag ( 644 const Point& rDragPt, 645 vcl::Window* pWindow ) 646 { 647 assert(mpSlideSorter); 648 mpSlideSorter->GetController().GetClipboard().StartDrag ( 649 rDragPt, 650 pWindow); 651 } 652 653 sal_Int8 SlideSorterViewShell::AcceptDrop ( 654 const AcceptDropEvent& rEvt, 655 DropTargetHelper& rTargetHelper, 656 ::sd::Window* pTargetWindow, 657 sal_uInt16 nPage, 658 SdrLayerID nLayer) 659 { 660 assert(mpSlideSorter); 661 return mpSlideSorter->GetController().GetClipboard().AcceptDrop ( 662 rEvt, 663 rTargetHelper, 664 pTargetWindow, 665 nPage, 666 nLayer); 667 } 668 669 sal_Int8 SlideSorterViewShell::ExecuteDrop ( 670 const ExecuteDropEvent& rEvt, 671 DropTargetHelper& rTargetHelper, 672 ::sd::Window* pTargetWindow, 673 sal_uInt16 nPage, 674 SdrLayerID nLayer) 675 { 676 assert(mpSlideSorter); 677 return mpSlideSorter->GetController().GetClipboard().ExecuteDrop ( 678 rEvt, 679 rTargetHelper, 680 pTargetWindow, 681 nPage, 682 nLayer); 683 } 684 685 std::shared_ptr<SlideSorterViewShell::PageSelection> 686 SlideSorterViewShell::GetPageSelection() const 687 { 688 assert(mpSlideSorter); 689 return mpSlideSorter->GetController().GetPageSelector().GetPageSelection(); 690 } 691 692 void SlideSorterViewShell::SetPageSelection ( 693 const std::shared_ptr<PageSelection>& rSelection) 694 { 695 assert(mpSlideSorter); 696 mpSlideSorter->GetController().GetPageSelector().SetPageSelection(rSelection, true); 697 } 698 699 void SlideSorterViewShell::AddSelectionChangeListener ( 700 const Link<LinkParamNone*,void>& rCallback) 701 { 702 assert(mpSlideSorter); 703 mpSlideSorter->GetController().GetSelectionManager()->AddSelectionChangeListener(rCallback); 704 } 705 706 void SlideSorterViewShell::RemoveSelectionChangeListener ( 707 const Link<LinkParamNone*,void>& rCallback) 708 { 709 assert(mpSlideSorter); 710 mpSlideSorter->GetController().GetSelectionManager()->RemoveSelectionChangeListener(rCallback); 711 } 712 713 void SlideSorterViewShell::MainViewEndEditAndUnmarkAll() 714 { 715 std::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell(); 716 DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(pMainViewShell.get()); 717 SdrView* pView = pDrawViewShell ? pDrawViewShell->GetDrawView() : nullptr; 718 if (pView) 719 { 720 pView->SdrEndTextEdit(); 721 pView->UnmarkAll(); 722 } 723 } 724 725 std::pair<sal_uInt16, sal_uInt16> SlideSorterViewShell::SyncPageSelectionToDocument(const std::shared_ptr<SlideSorterViewShell::PageSelection> &rpSelection) 726 { 727 sal_uInt16 firstSelectedPageNo = SAL_MAX_UINT16; 728 sal_uInt16 lastSelectedPageNo = 0; 729 730 GetDoc()->UnselectAllPages(); 731 for (auto& rpPage : *rpSelection) 732 { 733 // Check page number 734 sal_uInt16 pageNo = rpPage->GetPageNum(); 735 if (pageNo > lastSelectedPageNo) 736 lastSelectedPageNo = pageNo; 737 if (pageNo < firstSelectedPageNo) 738 firstSelectedPageNo = pageNo; 739 GetDoc()->SetSelected(rpPage, true); 740 } 741 742 return std::make_pair(firstSelectedPageNo, lastSelectedPageNo); 743 } 744 745 void SlideSorterViewShell::ExecMovePageFirst (SfxRequest& /*rReq*/) 746 { 747 MainViewEndEditAndUnmarkAll(); 748 749 std::shared_ptr<SlideSorterViewShell::PageSelection> xSelection(GetPageSelection()); 750 751 // SdDrawDocument MovePages is based on SdPage IsSelected, so 752 // transfer the SlideSorter selection to SdPages 753 SyncPageSelectionToDocument(xSelection); 754 755 // Moves selected pages after page -1 756 GetDoc()->MovePages( sal_uInt16(-1) ); 757 758 PostMoveSlidesActions(xSelection); 759 } 760 761 void SlideSorterViewShell::GetStateMovePageFirst (SfxItemSet& rSet) 762 { 763 if ( ! IsMainViewShell()) 764 { 765 std::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell(); 766 DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(pMainViewShell.get()); 767 if (pDrawViewShell != nullptr && pDrawViewShell->GetPageKind() == PageKind::Handout) 768 { 769 rSet.DisableItem( SID_MOVE_PAGE_FIRST ); 770 rSet.DisableItem( SID_MOVE_PAGE_UP ); 771 return; 772 } 773 } 774 775 std::shared_ptr<SlideSorterViewShell::PageSelection> xSelection(GetPageSelection()); 776 777 // SdDrawDocument MovePages is based on SdPage IsSelected, so 778 // transfer the SlideSorter selection to SdPages 779 sal_uInt16 firstSelectedPageNo = SyncPageSelectionToDocument(xSelection).first; 780 // Now compute human page number from internal page number 781 firstSelectedPageNo = (firstSelectedPageNo - 1) / 2; 782 783 if (firstSelectedPageNo == 0) 784 { 785 rSet.DisableItem( SID_MOVE_PAGE_FIRST ); 786 rSet.DisableItem( SID_MOVE_PAGE_UP ); 787 } 788 } 789 790 void SlideSorterViewShell::ExecMovePageUp (SfxRequest& /*rReq*/) 791 { 792 MainViewEndEditAndUnmarkAll(); 793 794 std::shared_ptr<SlideSorterViewShell::PageSelection> xSelection(GetPageSelection()); 795 796 // SdDrawDocument MovePages is based on SdPage IsSelected, so 797 // transfer the SlideSorter selection to SdPages 798 sal_uInt16 firstSelectedPageNo = SyncPageSelectionToDocument(xSelection).first; 799 800 // In case no slide is selected 801 if (firstSelectedPageNo == SAL_MAX_UINT16) 802 return; 803 804 // Now compute human page number from internal page number 805 firstSelectedPageNo = (firstSelectedPageNo - 1) / 2; 806 807 if (firstSelectedPageNo == 0) 808 return; 809 810 // Move pages before firstSelectedPageNo - 1 (so after firstSelectedPageNo - 2), 811 // remembering that -1 means at first, which is good. 812 GetDoc()->MovePages( firstSelectedPageNo - 2 ); 813 814 PostMoveSlidesActions(xSelection); 815 } 816 817 void SlideSorterViewShell::GetStateMovePageUp (SfxItemSet& rSet) 818 { 819 GetStateMovePageFirst(rSet); 820 } 821 822 void SlideSorterViewShell::ExecMovePageDown (SfxRequest& /*rReq*/) 823 { 824 MainViewEndEditAndUnmarkAll(); 825 826 std::shared_ptr<SlideSorterViewShell::PageSelection> xSelection(GetPageSelection()); 827 828 // SdDrawDocument MovePages is based on SdPage IsSelected, so 829 // transfer the SlideSorter selection to SdPages 830 sal_uInt16 lastSelectedPageNo = SyncPageSelectionToDocument(xSelection).second; 831 832 // Get page number of the last page 833 sal_uInt16 nNoOfPages = GetDoc()->GetSdPageCount(PageKind::Standard); 834 835 // Now compute human page number from internal page number 836 lastSelectedPageNo = (lastSelectedPageNo - 1) / 2; 837 if (lastSelectedPageNo == nNoOfPages - 1) 838 return; 839 840 // Move to position after lastSelectedPageNo 841 GetDoc()->MovePages( lastSelectedPageNo + 1 ); 842 843 PostMoveSlidesActions(xSelection); 844 } 845 846 void SlideSorterViewShell::GetStateMovePageDown (SfxItemSet& rSet) 847 { 848 GetStateMovePageLast( rSet ); 849 } 850 851 void SlideSorterViewShell::ExecMovePageLast (SfxRequest& /*rReq*/) 852 { 853 MainViewEndEditAndUnmarkAll(); 854 855 std::shared_ptr<SlideSorterViewShell::PageSelection> xSelection(GetPageSelection()); 856 857 // SdDrawDocument MovePages is based on SdPage IsSelected, so 858 // transfer the SlideSorter selection to SdPages 859 SyncPageSelectionToDocument(xSelection); 860 861 // Get page number of the last page 862 sal_uInt16 nNoOfPages = GetDoc()->GetSdPageCount(PageKind::Standard); 863 864 // Move to position after last page No (=Number of pages - 1) 865 GetDoc()->MovePages( nNoOfPages - 1 ); 866 867 PostMoveSlidesActions(xSelection); 868 } 869 870 void SlideSorterViewShell::GetStateMovePageLast (SfxItemSet& rSet) 871 { 872 std::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell(); 873 DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(pMainViewShell.get()); 874 if (pDrawViewShell != nullptr && pDrawViewShell->GetPageKind() == PageKind::Handout) 875 { 876 rSet.DisableItem( SID_MOVE_PAGE_LAST ); 877 rSet.DisableItem( SID_MOVE_PAGE_DOWN ); 878 return; 879 } 880 881 std::shared_ptr<SlideSorterViewShell::PageSelection> xSelection(GetPageSelection()); 882 883 // SdDrawDocument MovePages is based on SdPage IsSelected, so 884 // transfer the SlideSorter selection to SdPages 885 sal_uInt16 lastSelectedPageNo = SyncPageSelectionToDocument(xSelection).second; 886 887 // Get page number of the last page 888 sal_uInt16 nNoOfPages = GetDoc()->GetSdPageCount(PageKind::Standard); 889 890 // Now compute human page number from internal page number 891 lastSelectedPageNo = (lastSelectedPageNo - 1) / 2; 892 if (lastSelectedPageNo == nNoOfPages - 1) 893 { 894 rSet.DisableItem( SID_MOVE_PAGE_LAST ); 895 rSet.DisableItem( SID_MOVE_PAGE_DOWN ); 896 } 897 } 898 899 void SlideSorterViewShell::PostMoveSlidesActions(const std::shared_ptr<SlideSorterViewShell::PageSelection> &rpSelection) 900 { 901 sal_uInt16 nNoOfPages = GetDoc()->GetSdPageCount(PageKind::Standard); 902 for (sal_uInt16 nPage = 0; nPage < nNoOfPages; nPage++) 903 { 904 SdPage* pPage = GetDoc()->GetSdPage(nPage, PageKind::Standard); 905 GetDoc()->SetSelected(pPage, false); 906 } 907 908 mpSlideSorter->GetController().GetPageSelector().DeselectAllPages(); 909 for (const auto& rpPage : *rpSelection) 910 { 911 mpSlideSorter->GetController().GetPageSelector().SelectPage(rpPage); 912 } 913 914 // Refresh toolbar icons 915 SfxBindings& rBindings = GetViewFrame()->GetBindings(); 916 rBindings.Invalidate(SID_MOVE_PAGE_FIRST); 917 rBindings.Invalidate(SID_MOVE_PAGE_UP); 918 rBindings.Invalidate(SID_MOVE_PAGE_DOWN); 919 rBindings.Invalidate(SID_MOVE_PAGE_LAST); 920 921 } 922 923 } // end of namespace ::sd::slidesorter 924 925 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 926
