cid#1607171 Data race condition
[LibreOffice.git] / sd / source / ui / slidesorter / shell / SlideSorterViewShell.cxx
blob3eb048984b7003d6ad006ea257088a001de13040
1 #/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <SlideSorterViewShell.hxx>
21 #include <ViewShellImplementation.hxx>
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/dispatch.hxx>
54 #include <sfx2/sidebar/SidebarChildWindow.hxx>
55 #include <sfx2/devtools/DevelopmentToolChildWindow.hxx>
56 #include <svx/svxids.hrc>
57 #include <vcl/EnumContext.hxx>
58 #include <svx/sidebar/ContextChangeEventMultiplexer.hxx>
59 #include <comphelper/diagnose_ex.hxx>
60 #include <sfx2/sidebar/SidebarController.hxx>
62 using namespace ::sd::slidesorter;
63 #define ShellClass_SlideSorterViewShell
64 #include <sdslots.hxx>
66 using namespace ::com::sun::star;
67 using namespace ::com::sun::star::uno;
68 using namespace ::com::sun::star::drawing::framework;
70 using ::sd::framework::FrameworkHelper;
71 using ::vcl::EnumContext;
72 using namespace sfx2::sidebar;
74 namespace sd::slidesorter {
76 namespace {
78 bool inChartOrMathContext(const sd::View* pView)
80 if (!pView)
81 return false;
83 SfxViewShell* pViewShell = pView->GetSfxViewShell();
84 SidebarController* pSidebar = SidebarController::GetSidebarControllerForView(pViewShell);
85 if (pSidebar)
86 return pSidebar->hasChartOrMathContextCurrently();
88 return false;
91 } // anonymous namespace
94 SFX_IMPL_INTERFACE(SlideSorterViewShell, SfxShell)
96 void SlideSorterViewShell::InitInterface_Impl()
98 GetStaticInterface()->RegisterChildWindow(::sfx2::sidebar::SidebarChildWindow::GetChildWindowId());
99 GetStaticInterface()->RegisterChildWindow(DevelopmentToolChildWindow::GetChildWindowId());
103 std::shared_ptr<SlideSorterViewShell> SlideSorterViewShell::Create (
104 SfxViewFrame* pFrame,
105 ViewShellBase& rViewShellBase,
106 vcl::Window* pParentWindow,
107 FrameView* pFrameViewArgument)
109 std::shared_ptr<SlideSorterViewShell> pViewShell;
112 pViewShell.reset(
113 new SlideSorterViewShell(pFrame,rViewShellBase,pParentWindow,pFrameViewArgument));
114 pViewShell->Initialize();
115 if (pViewShell->mpSlideSorter == nullptr)
116 pViewShell.reset();
118 catch(Exception&)
120 pViewShell.reset();
122 return pViewShell;
125 SlideSorterViewShell::SlideSorterViewShell (
126 SfxViewFrame* /*pFrame*/,
127 ViewShellBase& rViewShellBase,
128 vcl::Window* pParentWindow,
129 FrameView* pFrameViewArgument)
130 : ViewShell (pParentWindow, rViewShellBase),
131 mbIsArrangeGUIElementsPending(true)
133 GetContentWindow()->set_id(u"slidesorter"_ustr);
134 meShellType = ST_SLIDE_SORTER;
136 if (pFrameViewArgument != nullptr)
137 mpFrameView = pFrameViewArgument;
138 else
139 mpFrameView = new FrameView(GetDoc());
140 GetFrameView()->Connect();
142 SetName (u"SlideSorterViewShell"_ustr);
144 pParentWindow->SetStyle(pParentWindow->GetStyle() | WB_DIALOGCONTROL);
147 SlideSorterViewShell::~SlideSorterViewShell()
149 DisposeFunctions();
153 ::sd::Window* pWindow = GetActiveWindow();
154 if (pWindow!=nullptr)
156 css::uno::Reference<css::lang::XComponent> xComponent (
157 pWindow->GetAccessible(false),
158 css::uno::UNO_QUERY);
159 if (xComponent.is())
160 xComponent->dispose();
163 catch( css::uno::Exception& )
165 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideSorterViewShell::~SlideSorterViewShell()" );
167 GetFrameView()->Disconnect();
170 void SlideSorterViewShell::Initialize()
172 mpSlideSorter = SlideSorter::CreateSlideSorter(
173 *this,
174 mpContentWindow,
175 mpHorizontalScrollBar,
176 mpVerticalScrollBar);
177 mpView = &mpSlideSorter->GetView();
179 doShow();
181 SetPool( &GetDoc()->GetPool() );
182 SetUndoManager( GetDoc()->GetDocSh()->GetUndoManager() );
184 // For accessibility we have to shortly hide the content window.
185 // This triggers the construction of a new accessibility object for
186 // the new view shell. (One is created earlier while the constructor
187 // of the base class is executed. At that time the correct
188 // accessibility object can not be constructed.)
189 sd::Window *pWindow (mpSlideSorter->GetContentWindow().get());
190 if (pWindow)
192 pWindow->Hide();
193 pWindow->Show();
197 void SlideSorterViewShell::Init (bool bIsMainViewShell)
199 ViewShell::Init(bIsMainViewShell);
201 // since the updatePageList will show focus, the window.show() must be called ahead. This show is deferred from Init()
202 ::sd::Window* pActiveWindow = GetActiveWindow();
203 if (pActiveWindow)
204 pActiveWindow->Show();
205 mpSlideSorter->GetModel().UpdatePageList();
207 if (mpContentWindow)
208 mpContentWindow->SetViewShell(this);
211 SlideSorterViewShell* SlideSorterViewShell::GetSlideSorter (ViewShellBase& rBase)
213 SlideSorterViewShell* pViewShell = nullptr;
215 // Test the center and left pane for showing a slide sorter.
216 OUString aPaneURLs[] = {
217 FrameworkHelper::msCenterPaneURL,
218 FrameworkHelper::msFullScreenPaneURL,
219 FrameworkHelper::msLeftImpressPaneURL,
220 FrameworkHelper::msLeftDrawPaneURL,
221 OUString()};
225 std::shared_ptr<FrameworkHelper> pFrameworkHelper (FrameworkHelper::Instance(rBase));
226 if (pFrameworkHelper->IsValid())
227 for (int i=0; pViewShell==nullptr && !aPaneURLs[i].isEmpty(); ++i)
229 pViewShell = dynamic_cast<SlideSorterViewShell*>(
230 pFrameworkHelper->GetViewShell(aPaneURLs[i]).get());
233 catch (RuntimeException&)
236 return pViewShell;
239 Reference<drawing::XDrawSubController> SlideSorterViewShell::CreateSubController()
241 Reference<drawing::XDrawSubController> xSubController;
243 if (IsMainViewShell())
245 // Create uno controller for the main view shell.
246 xSubController.set( new SdUnoSlideView( *mpSlideSorter));
249 return xSubController;
252 /** If there is a valid controller then create a new instance of
253 <type>AccessibleSlideSorterView</type>. Otherwise delegate this call
254 to the base class to return a default object (probably an empty
255 reference).
257 css::uno::Reference<css::accessibility::XAccessible>
258 SlideSorterViewShell::CreateAccessibleDocumentView (::sd::Window* pWindow)
260 // When the view is not set then the initialization is not yet complete
261 // and we can not yet provide an accessibility object.
262 if (mpView == nullptr || mpSlideSorter == nullptr)
263 return nullptr;
265 assert(mpSlideSorter);
267 rtl::Reference<::accessibility::AccessibleSlideSorterView> pAccessibleView =
268 new ::accessibility::AccessibleSlideSorterView(
269 *mpSlideSorter,
270 pWindow);
272 pAccessibleView->Init();
274 return pAccessibleView;
277 void SlideSorterViewShell::SwitchViewFireFocus(const css::uno::Reference< css::accessibility::XAccessible >& xAcc )
279 if (xAcc)
281 ::accessibility::AccessibleSlideSorterView* pBase = static_cast< ::accessibility::AccessibleSlideSorterView* >(xAcc.get());
282 if (pBase)
284 pBase->SwitchViewActivated();
289 SlideSorter& SlideSorterViewShell::GetSlideSorter() const
291 assert(mpSlideSorter);
292 return *mpSlideSorter;
295 bool SlideSorterViewShell::RelocateToParentWindow (vcl::Window* pParentWindow)
297 assert(mpSlideSorter);
298 if ( ! mpSlideSorter)
299 return false;
301 mpSlideSorter->RelocateToWindow(pParentWindow);
302 ReadFrameViewData(mpFrameView);
304 return true;
307 SfxUndoManager* SlideSorterViewShell::ImpGetUndoManager() const
309 SfxShell* pObjectBar = GetViewShellBase().GetViewShellManager()->GetTopShell();
310 if (pObjectBar != nullptr)
312 // When it exists then return the undo manager of the currently
313 // active object bar. The object bar is missing when the
314 // SlideSorterViewShell is not the main view shell.
315 return pObjectBar->GetUndoManager();
317 else
319 // Return the undo manager of this shell when there is no object or
320 // tool bar.
321 return const_cast<SlideSorterViewShell*>(this)->GetUndoManager();
325 SdPage* SlideSorterViewShell::getCurrentPage() const
327 // since SlideSorterViewShell::GetActualPage() currently also
328 // returns master pages, which is a wrong behaviour for GetActualPage(),
329 // we can just use that for now
330 return const_cast<SlideSorterViewShell*>(this)->GetActualPage();
333 SdPage* SlideSorterViewShell::GetActualPage()
335 SdPage* pCurrentPage = nullptr;
337 // 1. Try to get the current page from the view shell in the center pane
338 // (if we are that not ourself).
339 if ( ! IsMainViewShell())
341 std::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell();
342 if (pMainViewShell != nullptr)
343 pCurrentPage = pMainViewShell->GetActualPage();
346 if (pCurrentPage == nullptr)
348 model::SharedPageDescriptor pDescriptor (
349 mpSlideSorter->GetController().GetCurrentSlideManager()->GetCurrentSlide());
350 if (pDescriptor)
351 pCurrentPage = pDescriptor->GetPage();
354 return pCurrentPage;
357 void SlideSorterViewShell::GetMenuState ( SfxItemSet& rSet)
359 ViewShell::GetMenuState(rSet);
360 assert(mpSlideSorter);
361 mpSlideSorter->GetController().GetSlotManager()->GetMenuState(rSet);
364 void SlideSorterViewShell::GetClipboardState ( SfxItemSet& rSet)
366 ViewShell::GetMenuState(rSet);
367 assert(mpSlideSorter);
368 mpSlideSorter->GetController().GetSlotManager()->GetClipboardState(rSet);
371 void SlideSorterViewShell::ExecCtrl (SfxRequest& rRequest)
373 assert(mpSlideSorter);
374 mpSlideSorter->GetController().ExecCtrl(rRequest);
377 void SlideSorterViewShell::GetCtrlState (SfxItemSet& rSet)
379 assert(mpSlideSorter);
380 mpSlideSorter->GetController().GetCtrlState(rSet);
383 void SlideSorterViewShell::FuSupport (SfxRequest& rRequest)
385 assert(mpSlideSorter);
386 mpSlideSorter->GetController().FuSupport(rRequest);
389 /** We have to handle those slot calls here that need to have access to
390 private or protected members and methods of this class.
392 void SlideSorterViewShell::FuTemporary (SfxRequest& rRequest)
394 assert(mpSlideSorter);
395 switch (rRequest.GetSlot())
397 case SID_MODIFYPAGE:
399 SdPage* pCurrentPage = GetActualPage();
400 if (pCurrentPage != nullptr)
401 mpImpl->ProcessModifyPageSlot (
402 rRequest,
403 pCurrentPage,
404 PageKind::Standard);
405 Cancel();
406 rRequest.Done ();
408 break;
410 default:
411 mpSlideSorter->GetController().FuTemporary(rRequest);
412 break;
416 void SlideSorterViewShell::GetStatusBarState (SfxItemSet& rSet)
418 assert(mpSlideSorter);
419 mpSlideSorter->GetController().GetStatusBarState(rSet);
422 void SlideSorterViewShell::FuPermanent (SfxRequest& rRequest)
424 assert(mpSlideSorter);
425 mpSlideSorter->GetController().FuPermanent(rRequest);
428 void SlideSorterViewShell::GetAttrState (SfxItemSet& rSet)
430 assert(mpSlideSorter);
431 mpSlideSorter->GetController().GetAttrState(rSet);
434 void SlideSorterViewShell::ExecStatusBar (SfxRequest& rReq)
436 // nothing is executed during a slide show!
437 if(HasCurrentFunction(SID_PRESENTATION))
438 return;
440 switch (rReq.GetSlot())
442 case SID_STATUS_PAGE:
444 GetViewFrame()->GetDispatcher()->Execute(SID_GO_TO_PAGE,
445 SfxCallMode::SYNCHRON | SfxCallMode::RECORD);
447 break;
451 void SlideSorterViewShell::Paint (
452 const ::tools::Rectangle& rBBox,
453 ::sd::Window* pWindow)
455 SetActiveWindow (pWindow);
456 assert(mpSlideSorter);
457 if (mpSlideSorter)
458 mpSlideSorter->GetController().Paint(rBBox,pWindow);
461 void SlideSorterViewShell::ArrangeGUIElements()
463 if (IsActive())
465 assert(mpSlideSorter);
466 mpSlideSorter->ArrangeGUIElements(maViewPos, maViewSize);
467 mbIsArrangeGUIElementsPending = false;
469 else
470 mbIsArrangeGUIElementsPending = true;
473 void SlideSorterViewShell::Activate (bool bIsMDIActivate)
475 if(inChartOrMathContext(GetView()))
477 // Avoid context changes for chart/math during activation / deactivation.
478 const bool bIsContextBroadcasterEnabled (SfxShell::SetContextBroadcasterEnabled(false));
480 ViewShell::Activate(bIsMDIActivate);
482 SfxShell::SetContextBroadcasterEnabled(bIsContextBroadcasterEnabled);
483 return;
486 ViewShell::Activate(bIsMDIActivate);
487 if (mbIsArrangeGUIElementsPending)
488 ArrangeGUIElements();
490 // Determine and broadcast the context that belongs to the main view shell.
491 EnumContext::Context eContext = EnumContext::Context::Unknown;
492 std::shared_ptr<ViewShell> pMainViewShell (GetViewShellBase().GetMainViewShell());
493 ViewShell::ShellType eMainViewShellType (
494 pMainViewShell
495 ? pMainViewShell->GetShellType()
496 : ViewShell::ST_NONE);
497 switch (eMainViewShellType)
499 case ViewShell::ST_IMPRESS:
500 case ViewShell::ST_SLIDE_SORTER:
501 case ViewShell::ST_NOTES:
502 case ViewShell::ST_DRAW:
503 eContext = EnumContext::Context::DrawPage;
504 if( nullptr != dynamic_cast< const DrawViewShell *>( pMainViewShell.get() ))
506 DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(pMainViewShell.get());
507 if (pDrawViewShell != nullptr)
508 eContext = EnumContext::GetContextEnum(pDrawViewShell->GetSidebarContextName());
510 break;
512 default:
513 break;
515 ContextChangeEventMultiplexer::NotifyContextChange(
516 &GetViewShellBase(),
517 eContext);
520 void SlideSorterViewShell::Deactivate (bool /*bIsMDIActivate*/)
522 // Save Settings - Specifically SlidesPerRow to retrieve it later
523 WriteFrameViewData();
526 void SlideSorterViewShell::Command (
527 const CommandEvent& rEvent,
528 ::sd::Window* pWindow)
530 assert(mpSlideSorter);
531 if ( ! mpSlideSorter->GetController().Command (rEvent, pWindow))
532 ViewShell::Command (rEvent, pWindow);
535 void SlideSorterViewShell::ReadFrameViewData (FrameView* pFrameView)
537 assert(mpSlideSorter);
538 if (pFrameView != nullptr)
540 view::SlideSorterView& rView (mpSlideSorter->GetView());
542 sal_uInt16 nSlidesPerRow (pFrameView->GetSlidesPerRow());
543 if (nSlidesPerRow > 0
544 && rView.GetOrientation() == view::Layouter::GRID
545 && IsMainViewShell())
547 rView.GetLayouter().SetColumnCount(nSlidesPerRow,nSlidesPerRow);
549 if (IsMainViewShell())
550 mpSlideSorter->GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(
551 mpFrameView->GetSelectedPage());
552 mpSlideSorter->GetController().Rearrange(true);
554 // DrawMode for 'main' window
555 if (GetActiveWindow()->GetOutDev()->GetDrawMode() != pFrameView->GetDrawMode() )
556 GetActiveWindow()->GetOutDev()->SetDrawMode( pFrameView->GetDrawMode() );
559 // When this slide sorter is not displayed in the main window then we do
560 // not share the same frame view and have to find other ways to acquire
561 // certain values.
562 if ( ! IsMainViewShell())
564 std::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell();
565 if (pMainViewShell != nullptr)
566 mpSlideSorter->GetController().GetCurrentSlideManager()->NotifyCurrentSlideChange(
567 pMainViewShell->getCurrentPage());
571 void SlideSorterViewShell::WriteFrameViewData()
573 assert(mpSlideSorter);
574 if (mpFrameView == nullptr)
575 return;
577 view::SlideSorterView& rView (mpSlideSorter->GetView());
578 mpFrameView->SetSlidesPerRow(static_cast<sal_uInt16>(rView.GetLayouter().GetColumnCount()));
580 // DrawMode for 'main' window
581 if( mpFrameView->GetDrawMode() != GetActiveWindow()->GetOutDev()->GetDrawMode() )
582 mpFrameView->SetDrawMode( GetActiveWindow()->GetOutDev()->GetDrawMode() );
584 SdPage* pActualPage = GetActualPage();
585 if (pActualPage != nullptr)
587 if (IsMainViewShell())
588 mpFrameView->SetSelectedPage((pActualPage->GetPageNum()- 1) / 2);
589 // else
590 // The slide sorter is not expected to switch the current page
591 // other than by double clicks. That is handled separately.
593 else
595 // We have no current page to set but at least we can make sure
596 // that the index of the frame view has a legal value.
597 if (mpFrameView->GetSelectedPage() >= mpSlideSorter->GetModel().GetPageCount())
598 mpFrameView->SetSelectedPage(static_cast<sal_uInt16>(mpSlideSorter->GetModel().GetPageCount())-1);
602 void SlideSorterViewShell::SetZoom (::tools::Long )
604 // Ignored.
605 // The zoom scale is adapted internally to fit a number of columns in
606 // the window.
609 void SlideSorterViewShell::SetZoomRect (const ::tools::Rectangle& rZoomRect)
611 assert(mpSlideSorter);
612 Size aPageSize (mpSlideSorter->GetView().GetLayouter().GetPageObjectSize());
614 ::tools::Rectangle aRect(rZoomRect);
616 if (aRect.GetWidth() < aPageSize.Width())
618 ::tools::Long nWidthDiff = (aPageSize.Width() - aRect.GetWidth()) / 2;
620 aRect.AdjustLeft( -nWidthDiff );
621 aRect.AdjustRight(nWidthDiff );
623 if (aRect.Left() < 0)
625 aRect.SetPos(Point(0, aRect.Top()));
629 if (aRect.GetHeight() < aPageSize.Height())
631 ::tools::Long nHeightDiff = (aPageSize.Height() - aRect.GetHeight()) / 2;
633 aRect.AdjustTop( -nHeightDiff );
634 aRect.AdjustBottom(nHeightDiff );
636 if (aRect.Top() < 0)
638 aRect.SetPos(Point(aRect.Left(), 0));
642 ViewShell::SetZoomRect(aRect);
644 GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOM );
645 GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER );
648 void SlideSorterViewShell::UpdateScrollBars()
650 // Do not call the overwritten method of the base class: We do all the
651 // scroll bar setup by ourselves.
652 mpSlideSorter->GetController().GetScrollBarManager().UpdateScrollBars(true);
655 void SlideSorterViewShell::StartDrag (
656 const Point& rDragPt,
657 vcl::Window* pWindow )
659 assert(mpSlideSorter);
660 mpSlideSorter->GetController().GetClipboard().StartDrag (
661 rDragPt,
662 pWindow);
665 sal_Int8 SlideSorterViewShell::AcceptDrop (
666 const AcceptDropEvent& rEvt,
667 DropTargetHelper& rTargetHelper,
668 ::sd::Window* pTargetWindow,
669 sal_uInt16 nPage,
670 SdrLayerID nLayer)
672 assert(mpSlideSorter);
673 return mpSlideSorter->GetController().GetClipboard().AcceptDrop (
674 rEvt,
675 rTargetHelper,
676 pTargetWindow,
677 nPage,
678 nLayer);
681 sal_Int8 SlideSorterViewShell::ExecuteDrop (
682 const ExecuteDropEvent& rEvt,
683 DropTargetHelper& rTargetHelper,
684 ::sd::Window* pTargetWindow,
685 sal_uInt16 nPage,
686 SdrLayerID nLayer)
688 assert(mpSlideSorter);
689 return mpSlideSorter->GetController().GetClipboard().ExecuteDrop (
690 rEvt,
691 rTargetHelper,
692 pTargetWindow,
693 nPage,
694 nLayer);
697 std::shared_ptr<SlideSorterViewShell::PageSelection>
698 SlideSorterViewShell::GetPageSelection() const
700 assert(mpSlideSorter);
701 return mpSlideSorter->GetController().GetPageSelector().GetPageSelection();
704 void SlideSorterViewShell::SetPageSelection (
705 const std::shared_ptr<PageSelection>& rSelection)
707 assert(mpSlideSorter);
708 mpSlideSorter->GetController().GetPageSelector().SetPageSelection(rSelection, true);
711 void SlideSorterViewShell::AddSelectionChangeListener (
712 const Link<LinkParamNone*,void>& rCallback)
714 assert(mpSlideSorter);
715 mpSlideSorter->GetController().GetSelectionManager()->AddSelectionChangeListener(rCallback);
718 void SlideSorterViewShell::RemoveSelectionChangeListener (
719 const Link<LinkParamNone*,void>& rCallback)
721 assert(mpSlideSorter);
722 mpSlideSorter->GetController().GetSelectionManager()->RemoveSelectionChangeListener(rCallback);
725 void SlideSorterViewShell::MainViewEndEditAndUnmarkAll()
727 std::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell();
728 DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(pMainViewShell.get());
729 SdrView* pView = pDrawViewShell ? pDrawViewShell->GetDrawView() : nullptr;
730 if (pView)
732 pView->SdrEndTextEdit();
733 pView->UnmarkAll();
737 std::pair<sal_uInt16, sal_uInt16> SlideSorterViewShell::SyncPageSelectionToDocument(const std::shared_ptr<SlideSorterViewShell::PageSelection> &rpSelection)
739 sal_uInt16 firstSelectedPageNo = SAL_MAX_UINT16;
740 sal_uInt16 lastSelectedPageNo = 0;
742 GetDoc()->UnselectAllPages();
743 for (auto& rpPage : *rpSelection)
745 // Check page number
746 sal_uInt16 pageNo = rpPage->GetPageNum();
747 if (pageNo > lastSelectedPageNo)
748 lastSelectedPageNo = pageNo;
749 if (pageNo < firstSelectedPageNo)
750 firstSelectedPageNo = pageNo;
751 GetDoc()->SetSelected(rpPage, true);
754 return std::make_pair(firstSelectedPageNo, lastSelectedPageNo);
757 void SlideSorterViewShell::ExecMovePageFirst (SfxRequest& /*rReq*/)
759 MainViewEndEditAndUnmarkAll();
761 std::shared_ptr<SlideSorterViewShell::PageSelection> xSelection(GetPageSelection());
763 // SdDrawDocument MovePages is based on SdPage IsSelected, so
764 // transfer the SlideSorter selection to SdPages
765 SyncPageSelectionToDocument(xSelection);
767 // Moves selected pages after page -1
768 GetDoc()->MovePages( sal_uInt16(-1) );
770 PostMoveSlidesActions(xSelection);
773 void SlideSorterViewShell::GetStateMovePageFirst (SfxItemSet& rSet)
775 if ( ! IsMainViewShell())
777 std::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell();
778 DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(pMainViewShell.get());
779 if (pDrawViewShell != nullptr && pDrawViewShell->GetPageKind() == PageKind::Handout)
781 rSet.DisableItem( SID_MOVE_PAGE_FIRST );
782 rSet.DisableItem( SID_MOVE_PAGE_UP );
783 return;
787 std::shared_ptr<SlideSorterViewShell::PageSelection> xSelection(GetPageSelection());
789 // SdDrawDocument MovePages is based on SdPage IsSelected, so
790 // transfer the SlideSorter selection to SdPages
791 sal_uInt16 firstSelectedPageNo = SyncPageSelectionToDocument(xSelection).first;
792 // Now compute human page number from internal page number
793 firstSelectedPageNo = (firstSelectedPageNo - 1) / 2;
795 if (firstSelectedPageNo == 0)
797 rSet.DisableItem( SID_MOVE_PAGE_FIRST );
798 rSet.DisableItem( SID_MOVE_PAGE_UP );
802 void SlideSorterViewShell::ExecMovePageUp (SfxRequest& /*rReq*/)
804 MainViewEndEditAndUnmarkAll();
806 std::shared_ptr<SlideSorterViewShell::PageSelection> xSelection(GetPageSelection());
808 // SdDrawDocument MovePages is based on SdPage IsSelected, so
809 // transfer the SlideSorter selection to SdPages
810 sal_uInt16 firstSelectedPageNo = SyncPageSelectionToDocument(xSelection).first;
812 // In case no slide is selected
813 if (firstSelectedPageNo == SAL_MAX_UINT16)
814 return;
816 // Now compute human page number from internal page number
817 firstSelectedPageNo = (firstSelectedPageNo - 1) / 2;
819 if (firstSelectedPageNo == 0)
820 return;
822 // Move pages before firstSelectedPageNo - 1 (so after firstSelectedPageNo - 2),
823 // remembering that -1 means at first, which is good.
824 GetDoc()->MovePages( firstSelectedPageNo - 2 );
826 PostMoveSlidesActions(xSelection);
829 void SlideSorterViewShell::GetStateMovePageUp (SfxItemSet& rSet)
831 GetStateMovePageFirst(rSet);
834 void SlideSorterViewShell::ExecMovePageDown (SfxRequest& /*rReq*/)
836 MainViewEndEditAndUnmarkAll();
838 std::shared_ptr<SlideSorterViewShell::PageSelection> xSelection(GetPageSelection());
840 // SdDrawDocument MovePages is based on SdPage IsSelected, so
841 // transfer the SlideSorter selection to SdPages
842 sal_uInt16 lastSelectedPageNo = SyncPageSelectionToDocument(xSelection).second;
844 // Get page number of the last page
845 sal_uInt16 nNoOfPages = GetDoc()->GetSdPageCount(PageKind::Standard);
847 // Now compute human page number from internal page number
848 lastSelectedPageNo = (lastSelectedPageNo - 1) / 2;
849 if (lastSelectedPageNo == nNoOfPages - 1)
850 return;
852 // Move to position after lastSelectedPageNo
853 GetDoc()->MovePages( lastSelectedPageNo + 1 );
855 PostMoveSlidesActions(xSelection);
858 void SlideSorterViewShell::GetStateMovePageDown (SfxItemSet& rSet)
860 GetStateMovePageLast( rSet );
863 void SlideSorterViewShell::ExecMovePageLast (SfxRequest& /*rReq*/)
865 MainViewEndEditAndUnmarkAll();
867 std::shared_ptr<SlideSorterViewShell::PageSelection> xSelection(GetPageSelection());
869 // SdDrawDocument MovePages is based on SdPage IsSelected, so
870 // transfer the SlideSorter selection to SdPages
871 SyncPageSelectionToDocument(xSelection);
873 // Get page number of the last page
874 sal_uInt16 nNoOfPages = GetDoc()->GetSdPageCount(PageKind::Standard);
876 // Move to position after last page No (=Number of pages - 1)
877 GetDoc()->MovePages( nNoOfPages - 1 );
879 PostMoveSlidesActions(xSelection);
882 void SlideSorterViewShell::GetStateMovePageLast (SfxItemSet& rSet)
884 std::shared_ptr<ViewShell> pMainViewShell = GetViewShellBase().GetMainViewShell();
885 DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(pMainViewShell.get());
886 if (pDrawViewShell != nullptr && pDrawViewShell->GetPageKind() == PageKind::Handout)
888 rSet.DisableItem( SID_MOVE_PAGE_LAST );
889 rSet.DisableItem( SID_MOVE_PAGE_DOWN );
890 return;
893 std::shared_ptr<SlideSorterViewShell::PageSelection> xSelection(GetPageSelection());
895 // SdDrawDocument MovePages is based on SdPage IsSelected, so
896 // transfer the SlideSorter selection to SdPages
897 sal_uInt16 lastSelectedPageNo = SyncPageSelectionToDocument(xSelection).second;
899 // Get page number of the last page
900 sal_uInt16 nNoOfPages = GetDoc()->GetSdPageCount(PageKind::Standard);
902 // Now compute human page number from internal page number
903 lastSelectedPageNo = (lastSelectedPageNo - 1) / 2;
904 if (lastSelectedPageNo == nNoOfPages - 1)
906 rSet.DisableItem( SID_MOVE_PAGE_LAST );
907 rSet.DisableItem( SID_MOVE_PAGE_DOWN );
911 void SlideSorterViewShell::PostMoveSlidesActions(const std::shared_ptr<SlideSorterViewShell::PageSelection> &rpSelection)
913 sal_uInt16 nNoOfPages = GetDoc()->GetSdPageCount(PageKind::Standard);
914 for (sal_uInt16 nPage = 0; nPage < nNoOfPages; nPage++)
916 SdPage* pPage = GetDoc()->GetSdPage(nPage, PageKind::Standard);
917 GetDoc()->SetSelected(pPage, false);
920 mpSlideSorter->GetController().GetPageSelector().DeselectAllPages();
921 for (const auto& rpPage : *rpSelection)
923 mpSlideSorter->GetController().GetPageSelector().SelectPage(rpPage);
926 // Refresh toolbar icons
927 SfxBindings& rBindings = GetViewFrame()->GetBindings();
928 rBindings.Invalidate(SID_MOVE_PAGE_FIRST);
929 rBindings.Invalidate(SID_MOVE_PAGE_UP);
930 rBindings.Invalidate(SID_MOVE_PAGE_DOWN);
931 rBindings.Invalidate(SID_MOVE_PAGE_LAST);
935 } // end of namespace ::sd::slidesorter
937 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */