1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <controller/SlideSorterController.hxx>
22 #include <SlideSorter.hxx>
23 #include <controller/SlsPageSelector.hxx>
24 #include <controller/SlsSelectionFunction.hxx>
25 #include <controller/SlsProperties.hxx>
26 #include <controller/SlsCurrentSlideManager.hxx>
27 #include "SlsListener.hxx"
28 #include <controller/SlsFocusManager.hxx>
29 #include <controller/SlsAnimator.hxx>
30 #include <controller/SlsClipboard.hxx>
31 #include <controller/SlsInsertionIndicatorHandler.hxx>
32 #include <controller/SlsScrollBarManager.hxx>
33 #include <controller/SlsSelectionManager.hxx>
34 #include <controller/SlsSlotManager.hxx>
35 #include <controller/SlsVisibleAreaManager.hxx>
36 #include <model/SlideSorterModel.hxx>
37 #include <model/SlsPageEnumerationProvider.hxx>
38 #include <model/SlsPageDescriptor.hxx>
39 #include <view/SlideSorterView.hxx>
40 #include <view/SlsLayouter.hxx>
41 #include <view/SlsPageObjectLayouter.hxx>
42 #include <view/SlsTheme.hxx>
43 #include <view/SlsToolTip.hxx>
44 #include <cache/SlsPageCache.hxx>
45 #include <cache/SlsPageCacheManager.hxx>
46 #include <comphelper/diagnose_ex.hxx>
48 #include <drawdoc.hxx>
49 #include <ViewShellBase.hxx>
51 #include <FrameView.hxx>
56 #include <ViewShellHint.hxx>
57 #include <AccessibleSlideSorterView.hxx>
58 #include <AccessibleSlideSorterObject.hxx>
60 #include <vcl/window.hxx>
61 #include <svx/svxids.hrc>
62 #include <sfx2/request.hxx>
63 #include <sfx2/viewfrm.hxx>
64 #include <sfx2/dispatch.hxx>
65 #include <tools/debug.hxx>
66 #include <vcl/commandevent.hxx>
67 #include <vcl/svapp.hxx>
68 #include <vcl/settings.hxx>
70 #include <com/sun/star/lang/XComponent.hpp>
71 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
75 using namespace ::com::sun::star
;
76 using namespace ::com::sun::star::uno
;
77 using namespace ::sd::slidesorter::model
;
78 using namespace ::sd::slidesorter::view
;
79 using namespace ::sd::slidesorter::controller
;
80 using namespace ::basegfx
;
82 namespace sd::slidesorter::controller
{
84 SlideSorterController::SlideSorterController (SlideSorter
& rSlideSorter
)
85 : mrSlideSorter(rSlideSorter
),
86 mrModel(mrSlideSorter
.GetModel()),
87 mrView(mrSlideSorter
.GetView()),
88 mpInsertionIndicatorHandler(std::make_shared
<InsertionIndicatorHandler
>(rSlideSorter
)),
89 mpAnimator(std::make_shared
<Animator
>(rSlideSorter
)),
90 mpVisibleAreaManager(new VisibleAreaManager(rSlideSorter
)),
91 mnModelChangeLockCount(0),
92 mbIsForcedRearrangePending(false),
93 mbContextMenuOpen(false),
94 mbPostModelChangePending(false),
95 mnCurrentPageBeforeSwitch(0),
96 mpEditModeChangeMasterPage(nullptr),
97 mnPaintEntranceCount(0)
99 sd::Window
*pWindow (mrSlideSorter
.GetContentWindow().get());
104 // The whole background is painted by the view and controls.
105 vcl::Window
* pParentWindow
= pWindow
->GetParent();
106 OSL_ASSERT(pParentWindow
!=nullptr);
107 pParentWindow
->SetBackground (Wallpaper());
109 // Connect the view with the window that has been created by our base
111 pWindow
->SetBackground(Wallpaper());
112 pWindow
->SetCenterAllowed(false);
113 pWindow
->SetMapMode(MapMode(MapUnit::MapPixel
));
114 pWindow
->SetViewSize(mrView
.GetModelArea().GetSize());
117 void SlideSorterController::Init()
119 mpCurrentSlideManager
= std::make_shared
<CurrentSlideManager
>(mrSlideSorter
);
120 mpPageSelector
.reset(new PageSelector(mrSlideSorter
));
121 mpFocusManager
.reset(new FocusManager(mrSlideSorter
));
122 mpSlotManager
= std::make_shared
<SlotManager
>(mrSlideSorter
);
123 mpScrollBarManager
.reset(new ScrollBarManager(mrSlideSorter
));
124 mpSelectionManager
= std::make_shared
<SelectionManager
>(mrSlideSorter
);
125 mpClipboard
.reset(new Clipboard(mrSlideSorter
));
127 // Create the selection function.
128 SfxRequest
aRequest (
131 mrModel
.GetDocument()->GetItemPool());
132 mrSlideSorter
.SetCurrentFunction(CreateSelectionFunction(aRequest
));
134 mpListener
= new Listener(mrSlideSorter
);
136 mpPageSelector
->GetCoreSelection();
137 GetSelectionManager()->SelectionHasChanged();
140 SlideSorterController::~SlideSorterController()
144 uno::Reference
<lang::XComponent
> xComponent
= mpListener
;
146 xComponent
->dispose();
148 catch( uno::Exception
& )
150 TOOLS_WARN_EXCEPTION( "sd", "sd::SlideSorterController::~SlideSorterController()" );
153 // dispose should have been called by now so that nothing is to be done
154 // to shut down cleanly.
157 void SlideSorterController::Dispose()
159 mpInsertionIndicatorHandler
->End(Animator::AM_Immediate
);
161 mpSelectionManager
.reset();
162 mpAnimator
->Dispose();
165 model::SharedPageDescriptor
SlideSorterController::GetPageAt (
166 const Point
& aWindowPosition
)
168 sal_Int32
nHitPageIndex (mrView
.GetPageIndexAtPoint(aWindowPosition
));
169 model::SharedPageDescriptor pDescriptorAtPoint
;
170 if (nHitPageIndex
>= 0)
172 pDescriptorAtPoint
= mrModel
.GetPageDescriptor(nHitPageIndex
);
174 // Depending on a property we may have to check that the mouse is no
175 // just over the page object but over the preview area.
176 if (pDescriptorAtPoint
177 && ! pDescriptorAtPoint
->HasState(PageDescriptor::ST_Selected
))
179 // Make sure that the mouse is over the preview area.
180 if ( ! mrView
.GetLayouter().GetPageObjectLayouter()->GetBoundingBox(
182 view::PageObjectLayouter::Part::Preview
,
183 view::PageObjectLayouter::WindowCoordinateSystem
).Contains(aWindowPosition
))
185 pDescriptorAtPoint
.reset();
190 return pDescriptorAtPoint
;
193 PageSelector
& SlideSorterController::GetPageSelector()
195 OSL_ASSERT(mpPageSelector
!= nullptr);
196 return *mpPageSelector
;
199 FocusManager
& SlideSorterController::GetFocusManager()
201 OSL_ASSERT(mpFocusManager
!= nullptr);
202 return *mpFocusManager
;
205 Clipboard
& SlideSorterController::GetClipboard()
207 OSL_ASSERT(mpClipboard
!= nullptr);
211 ScrollBarManager
& SlideSorterController::GetScrollBarManager()
213 OSL_ASSERT(mpScrollBarManager
!= nullptr);
214 return *mpScrollBarManager
;
217 std::shared_ptr
<CurrentSlideManager
> const & SlideSorterController::GetCurrentSlideManager() const
219 OSL_ASSERT(mpCurrentSlideManager
!= nullptr);
220 return mpCurrentSlideManager
;
223 std::shared_ptr
<SlotManager
> const & SlideSorterController::GetSlotManager() const
225 OSL_ASSERT(mpSlotManager
!= nullptr);
226 return mpSlotManager
;
229 std::shared_ptr
<SelectionManager
> const & SlideSorterController::GetSelectionManager() const
231 OSL_ASSERT(mpSelectionManager
!= nullptr);
232 return mpSelectionManager
;
235 std::shared_ptr
<InsertionIndicatorHandler
> const &
236 SlideSorterController::GetInsertionIndicatorHandler() const
238 OSL_ASSERT(mpInsertionIndicatorHandler
!= nullptr);
239 return mpInsertionIndicatorHandler
;
242 void SlideSorterController::Paint (
243 const ::tools::Rectangle
& rBBox
,
244 vcl::Window
* pWindow
)
246 if (mnPaintEntranceCount
!= 0)
249 ++mnPaintEntranceCount
;
253 mrView
.CompleteRedraw(pWindow
->GetOutDev(), vcl::Region(rBBox
));
255 catch (const Exception
&)
257 // Ignore all exceptions.
260 --mnPaintEntranceCount
;
263 void SlideSorterController::FuTemporary (SfxRequest
& rRequest
)
265 mpSlotManager
->FuTemporary (rRequest
);
268 void SlideSorterController::FuPermanent (SfxRequest
&rRequest
)
270 mpSlotManager
->FuPermanent (rRequest
);
273 void SlideSorterController::FuSupport (SfxRequest
&rRequest
)
275 mpSlotManager
->FuSupport (rRequest
);
278 bool SlideSorterController::Command (
279 const CommandEvent
& rEvent
,
280 ::sd::Window
* pWindow
)
282 bool bEventHasBeenHandled
= false;
284 if (pWindow
== nullptr)
287 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
288 if (pViewShell
== nullptr)
291 switch (rEvent
.GetCommand())
293 case CommandEventId::ContextMenu
:
295 SdPage
* pPage
= nullptr;
298 model::PageEnumeration
aSelectedPages (
299 PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel
));
300 if (aSelectedPages
.HasMoreElements())
301 pPage
= aSelectedPages
.GetNextElement()->GetPage();
303 if (mrModel
.GetEditMode() == EditMode::Page
)
305 if (pPage
!= nullptr)
306 aPopupId
= "pagepane";
308 aPopupId
= "pagepanenosel";
310 else if (pPage
!= nullptr)
311 aPopupId
= "pagepanemaster";
313 aPopupId
= "pagepanenoselmaster";
315 std::unique_ptr
<InsertionIndicatorHandler::ForceShowContext
, o3tl::default_delete
<InsertionIndicatorHandler::ForceShowContext
>> xContext
;
316 if (pPage
== nullptr)
318 // When there is no selection, then we show the insertion
319 // indicator so that the user knows where a page insertion
321 mpInsertionIndicatorHandler
->Start(false);
322 mpInsertionIndicatorHandler
->UpdateIndicatorIcon(SD_MOD()->pTransferClip
);
323 mpInsertionIndicatorHandler
->UpdatePosition(
324 pWindow
->PixelToLogic(rEvent
.GetMousePosPixel()),
325 InsertionIndicatorHandler::MoveMode
);
326 xContext
.reset(new InsertionIndicatorHandler::ForceShowContext(
327 mpInsertionIndicatorHandler
));
330 pWindow
->ReleaseMouse();
332 Point
aMenuLocation (0,0);
333 if (!rEvent
.IsMouseEvent())
335 // The event is not a mouse event. Use the center of the
336 // focused page as top left position of the context menu.
337 model::SharedPageDescriptor
pDescriptor (
338 GetFocusManager().GetFocusedPageDescriptor());
341 ::tools::Rectangle
aBBox (
342 mrView
.GetLayouter().GetPageObjectLayouter()->GetBoundingBox (
344 PageObjectLayouter::Part::PageObject
,
345 PageObjectLayouter::ModelCoordinateSystem
));
346 aMenuLocation
= aBBox
.Center();
350 if (SfxDispatcher
* pDispatcher
= pViewShell
->GetDispatcher())
352 mbContextMenuOpen
= true;
353 if (!rEvent
.IsMouseEvent())
354 pDispatcher
->ExecutePopup(aPopupId
, pWindow
, &aMenuLocation
);
356 pDispatcher
->ExecutePopup(aPopupId
, pWindow
);
357 mbContextMenuOpen
= false;
358 mrSlideSorter
.GetView().UpdatePageUnderMouse();
359 ::rtl::Reference
<SelectionFunction
> pFunction(GetCurrentSelectionFunction());
361 pFunction
->ResetMouseAnchor();
363 if (pPage
== nullptr)
365 // Remember the position of the insertion indicator before
366 // it is hidden, so that a pending slide insertion slot call
367 // finds the right place to insert a new slide.
368 GetSelectionManager()->SetInsertionPosition(
369 GetInsertionIndicatorHandler()->GetInsertionPageIndex());
372 bEventHasBeenHandled
= true;
376 case CommandEventId::Wheel
:
378 const CommandWheelData
* pData
= rEvent
.GetWheelData();
379 if (pData
== nullptr)
383 // We do not support zooming with control+mouse wheel.
386 // Determine whether to scroll horizontally or vertically. This
387 // depends on the orientation of the scroll bar and the
388 // IsHoriz() flag of the event.
389 if ((mrSlideSorter
.GetView().GetOrientation()==view::Layouter::HORIZONTAL
)
392 GetScrollBarManager().Scroll(
393 ScrollBarManager::Orientation_Vertical
,
394 -pData
->GetNotchDelta());
398 GetScrollBarManager().Scroll(
399 ScrollBarManager::Orientation_Horizontal
,
400 -pData
->GetNotchDelta());
402 mrSlideSorter
.GetView().UpdatePageUnderMouse(rEvent
.GetMousePosPixel());
404 bEventHasBeenHandled
= true;
411 return bEventHasBeenHandled
;
414 void SlideSorterController::LockModelChange()
416 mnModelChangeLockCount
+= 1;
419 void SlideSorterController::UnlockModelChange()
421 mnModelChangeLockCount
-= 1;
422 if (mnModelChangeLockCount
==0 && mbPostModelChangePending
)
428 void SlideSorterController::PreModelChange()
430 // Prevent PreModelChange to execute more than once per model lock.
431 if (mbPostModelChangePending
)
434 if (mrSlideSorter
.GetViewShell() != nullptr)
435 mrSlideSorter
.GetViewShell()->Broadcast(
436 ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START
));
438 GetCurrentSlideManager()->PrepareModelChange();
440 if (mrSlideSorter
.GetContentWindow())
441 mrView
.PreModelChange();
443 mbPostModelChangePending
= true;
446 void SlideSorterController::PostModelChange()
448 mbPostModelChangePending
= false;
451 sd::Window
*pWindow (mrSlideSorter
.GetContentWindow().get());
454 GetCurrentSlideManager()->HandleModelChange();
456 mrView
.PostModelChange ();
458 pWindow
->SetViewOrigin (Point (0,0));
459 pWindow
->SetViewSize (mrView
.GetModelArea().GetSize());
461 // The visibility of the scroll bars may have to be changed. Then
462 // the size of the view has to change, too. Let Rearrange() handle
464 Rearrange(mbIsForcedRearrangePending
);
467 if (mrSlideSorter
.GetViewShell() != nullptr)
468 mrSlideSorter
.GetViewShell()->Broadcast(
469 ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END
));
472 void SlideSorterController::HandleModelChange()
474 // Ignore this call when the document is not in a valid state, i.e. has
475 // not the same number of regular and notes pages.
476 bool bIsDocumentValid
= (mrModel
.GetDocument()->GetPageCount() % 2 == 1);
478 if (bIsDocumentValid
)
480 ModelChangeLock
aLock (*this);
485 IMPL_LINK(SlideSorterController
, ApplicationEventHandler
, VclSimpleEvent
&, rEvent
, void)
487 auto windowEvent
= dynamic_cast<VclWindowEvent
*>(&rEvent
);
488 if (windowEvent
!= nullptr) {
489 WindowEventHandler(*windowEvent
);
492 IMPL_LINK(SlideSorterController
, WindowEventHandler
, VclWindowEvent
&, rEvent
, void)
494 vcl::Window
* pWindow
= rEvent
.GetWindow();
495 sd::Window
*pActiveWindow (mrSlideSorter
.GetContentWindow().get());
496 switch (rEvent
.GetId())
498 case VclEventId::WindowActivate
:
499 case VclEventId::WindowShow
:
500 if (pActiveWindow
&& pWindow
== pActiveWindow
->GetParent())
501 mrView
.RequestRepaint();
504 case VclEventId::WindowHide
:
505 if (pActiveWindow
&& pWindow
== pActiveWindow
->GetParent())
506 mrView
.SetPageUnderMouse(SharedPageDescriptor());
509 case VclEventId::WindowGetFocus
:
511 if (pWindow
== pActiveWindow
)
512 GetFocusManager().ShowFocus(false);
515 case VclEventId::WindowLoseFocus
:
516 if (pActiveWindow
&& pWindow
== pActiveWindow
)
518 GetFocusManager().HideFocus();
519 mrView
.GetToolTip().Hide();
521 //don't scroll back to the selected slide when we lose
522 //focus due to a temporary active context menu
523 if (!mbContextMenuOpen
)
525 // Select the current slide so that it is properly
526 // visualized when the focus is moved to the edit view.
527 GetPageSelector().SelectPage(GetCurrentSlideManager()->GetCurrentSlide());
532 case VclEventId::ApplicationDataChanged
:
534 // Invalidate the preview cache.
535 cache::PageCacheManager::Instance()->InvalidateAllCaches();
537 // Update the draw mode.
538 DrawModeFlags
nDrawMode (Application::GetSettings().GetStyleSettings().GetHighContrastMode()
539 ? sd::OUTPUT_DRAWMODE_CONTRAST
540 : sd::OUTPUT_DRAWMODE_COLOR
);
541 if (mrSlideSorter
.GetViewShell() != nullptr)
542 mrSlideSorter
.GetViewShell()->GetFrameView()->SetDrawMode(nDrawMode
);
543 if (pActiveWindow
!= nullptr)
544 pActiveWindow
->GetOutDev()->SetDrawMode(nDrawMode
);
545 mrView
.HandleDrawModeChange();
547 // When the system font has changed a layout has to be done.
550 // Update theme colors.
551 mrSlideSorter
.GetProperties()->HandleDataChangeEvent();
552 mrSlideSorter
.GetTheme()->Update(mrSlideSorter
.GetProperties());
553 mrView
.HandleDataChangeEvent();
562 void SlideSorterController::GetCtrlState (SfxItemSet
& rSet
)
564 if (rSet
.GetItemState(SID_RELOAD
) != SfxItemState::UNKNOWN
)
566 // let SFx en-/disable "last version"
567 SfxViewFrame
* pSlideViewFrame
= SfxViewFrame::Current();
568 DBG_ASSERT(pSlideViewFrame
!=nullptr,
569 "SlideSorterController::GetCtrlState: ViewFrame not found");
572 pSlideViewFrame
->GetSlotState (SID_RELOAD
, nullptr, &rSet
);
574 else // MI says: no MDIFrame --> disable
576 rSet
.DisableItem(SID_RELOAD
);
581 if (rSet
.GetItemState(SID_OUTPUT_QUALITY_COLOR
)==SfxItemState::DEFAULT
582 ||rSet
.GetItemState(SID_OUTPUT_QUALITY_GRAYSCALE
)==SfxItemState::DEFAULT
583 ||rSet
.GetItemState(SID_OUTPUT_QUALITY_BLACKWHITE
)==SfxItemState::DEFAULT
584 ||rSet
.GetItemState(SID_OUTPUT_QUALITY_CONTRAST
)==SfxItemState::DEFAULT
)
586 if (mrSlideSorter
.GetContentWindow())
588 DrawModeFlags nMode
= mrSlideSorter
.GetContentWindow()->GetOutDev()->GetDrawMode();
589 sal_uInt16 nQuality
= 0;
591 if (nMode
== sd::OUTPUT_DRAWMODE_COLOR
) {
593 } else if (nMode
== sd::OUTPUT_DRAWMODE_GRAYSCALE
) {
595 } else if (nMode
== sd::OUTPUT_DRAWMODE_BLACKWHITE
) {
597 } else if (nMode
== sd::OUTPUT_DRAWMODE_CONTRAST
) {
601 rSet
.Put (SfxBoolItem (SID_OUTPUT_QUALITY_COLOR
, nQuality
==0));
602 rSet
.Put (SfxBoolItem (SID_OUTPUT_QUALITY_GRAYSCALE
, nQuality
==1));
603 rSet
.Put (SfxBoolItem (SID_OUTPUT_QUALITY_BLACKWHITE
, nQuality
==2));
604 rSet
.Put (SfxBoolItem (SID_OUTPUT_QUALITY_CONTRAST
, nQuality
==3));
608 if (rSet
.GetItemState(SID_MAIL_SCROLLBODY_PAGEDOWN
) == SfxItemState::DEFAULT
)
610 rSet
.Put (SfxBoolItem( SID_MAIL_SCROLLBODY_PAGEDOWN
, true));
614 void SlideSorterController::GetStatusBarState (SfxItemSet
& rSet
)
616 mpSlotManager
->GetStatusBarState (rSet
);
619 void SlideSorterController::ExecCtrl (SfxRequest
& rRequest
)
621 mpSlotManager
->ExecCtrl (rRequest
);
624 void SlideSorterController::GetAttrState (SfxItemSet
& rSet
)
626 mpSlotManager
->GetAttrState (rSet
);
629 void SlideSorterController::UpdateAllPages()
632 mrSlideSorter
.GetContentWindow()->Invalidate();
635 void SlideSorterController::Resize (const ::tools::Rectangle
& rAvailableSpace
)
637 if (maTotalWindowArea
!= rAvailableSpace
)
639 maTotalWindowArea
= rAvailableSpace
;
644 void SlideSorterController::Rearrange (bool bForce
)
646 if (maTotalWindowArea
.IsEmpty())
649 if (mnModelChangeLockCount
>0)
651 mbIsForcedRearrangePending
|= bForce
;
655 mbIsForcedRearrangePending
= false;
657 sd::Window
*pWindow (mrSlideSorter
.GetContentWindow().get());
662 mrView
.UpdateOrientation();
664 // Place the scroll bars.
665 ::tools::Rectangle aNewContentArea
= GetScrollBarManager().PlaceScrollBars(
667 mrView
.GetOrientation() != view::Layouter::VERTICAL
,
668 mrView
.GetOrientation() != view::Layouter::HORIZONTAL
);
670 bool bSizeHasChanged (false);
671 // Only when bForce is not true we have to test for a size change in
672 // order to determine whether the window and the view have to be resized.
675 ::tools::Rectangle
aCurrentContentArea (pWindow
->GetPosPixel(), pWindow
->GetOutputSizePixel());
676 bSizeHasChanged
= (aNewContentArea
!= aCurrentContentArea
);
678 if (bForce
|| bSizeHasChanged
)
680 // The browser window gets the remaining space.
681 pWindow
->SetPosSizePixel (aNewContentArea
.TopLeft(), aNewContentArea
.GetSize());
685 // Adapt the scroll bars to the new zoom factor of the browser
686 // window and the arrangement of the page objects.
687 GetScrollBarManager().UpdateScrollBars(!bForce
);
689 // Keep the current slide in the visible area.
690 GetVisibleAreaManager().RequestCurrentSlideVisible();
692 mrView
.RequestRepaint();
695 rtl::Reference
<FuPoor
> SlideSorterController::CreateSelectionFunction (SfxRequest
& rRequest
)
697 rtl::Reference
<FuPoor
> xFunc( SelectionFunction::Create(mrSlideSorter
, rRequest
) );
701 ::rtl::Reference
<SelectionFunction
> SlideSorterController::GetCurrentSelectionFunction() const
703 rtl::Reference
<FuPoor
> pFunction (mrSlideSorter
.GetViewShell()->GetCurrentFunction());
704 return ::rtl::Reference
<SelectionFunction
>(dynamic_cast<SelectionFunction
*>(pFunction
.get()));
707 void SlideSorterController::PrepareEditModeChange()
709 // Before we throw away the page descriptors we prepare for selecting
710 // descriptors in the other mode and for restoring the current
711 // selection when switching back to the current mode.
712 if (mrModel
.GetEditMode() != EditMode::Page
)
715 maSelectionBeforeSwitch
.clear();
717 // Search for the first selected page and determine the master page
718 // used by its page object. It will be selected after the switch.
719 // In the same loop the current selection is stored.
720 PageEnumeration
aSelectedPages (
721 PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel
));
722 while (aSelectedPages
.HasMoreElements())
724 SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
725 SdPage
* pPage
= pDescriptor
->GetPage();
726 // Remember the master page of the first selected descriptor.
727 if (pPage
!=nullptr && mpEditModeChangeMasterPage
==nullptr)
728 mpEditModeChangeMasterPage
= &static_cast<SdPage
&>(
729 pPage
->TRG_GetMasterPage());
731 maSelectionBeforeSwitch
.push_back(pPage
);
734 // Remember the current page.
735 if (mrSlideSorter
.GetViewShell() != nullptr)
736 mnCurrentPageBeforeSwitch
= (mrSlideSorter
.GetViewShell()->GetViewShellBase()
737 .GetMainViewShell()->GetActualPage()->GetPageNum()-1)/2;
740 void SlideSorterController::ChangeEditMode (EditMode eEditMode
)
742 if (mrModel
.GetEditMode() != eEditMode
)
744 ModelChangeLock
aLock (*this);
746 // Do the actual edit mode switching.
747 bool bResult
= mrModel
.SetEditMode(eEditMode
);
753 void SlideSorterController::FinishEditModeChange()
755 if (mrModel
.GetEditMode() == EditMode::MasterPage
)
757 mpPageSelector
->DeselectAllPages();
759 // Search for the master page that was determined in
760 // PrepareEditModeChange() and make it the current page.
761 PageEnumeration
aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel
));
762 while (aAllPages
.HasMoreElements())
764 SharedPageDescriptor
pDescriptor (aAllPages
.GetNextElement());
765 if (pDescriptor
->GetPage() == mpEditModeChangeMasterPage
)
767 GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor
);
768 mpPageSelector
->SelectPage(pDescriptor
);
775 PageSelector::BroadcastLock
aBroadcastLock (*mpPageSelector
);
777 SharedPageDescriptor
pDescriptor (mrModel
.GetPageDescriptor(mnCurrentPageBeforeSwitch
));
778 GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor
);
780 // Restore the selection.
781 mpPageSelector
->DeselectAllPages();
782 for (const auto& rpPage
: maSelectionBeforeSwitch
)
784 mpPageSelector
->SelectPage(rpPage
);
786 maSelectionBeforeSwitch
.clear( );
788 mpEditModeChangeMasterPage
= nullptr;
791 void SlideSorterController::PageNameHasChanged (int nPageIndex
, const OUString
& rsOldName
)
793 // Request a repaint for the page object whose name has changed.
794 model::SharedPageDescriptor
pDescriptor (mrModel
.GetPageDescriptor(nPageIndex
));
796 mrView
.RequestRepaint(pDescriptor
);
798 // Get a pointer to the corresponding accessible object and notify
799 // that of the name change.
800 sd::Window
*pWindow (mrSlideSorter
.GetContentWindow().get());
804 css::uno::Reference
< css::accessibility::XAccessible
>
805 xAccessible (pWindow
->GetAccessible(false));
806 if ( ! xAccessible
.is())
809 // Now comes a small hack. We assume that the accessible object is
810 // an instantiation of AccessibleSlideSorterView and cast it to that
811 // class. The cleaner alternative to this cast would be a new member
812 // in which we would store the last AccessibleSlideSorterView object
813 // created by SlideSorterViewShell::CreateAccessibleDocumentView().
814 // But then there is no guaranty that the accessible object obtained
815 // from the window really is that instance last created by
816 // CreateAccessibleDocumentView().
817 // However, the dynamic cast together with the check of the result
818 // being NULL should be safe enough.
819 ::accessibility::AccessibleSlideSorterView
* pAccessibleView
820 = dynamic_cast< ::accessibility::AccessibleSlideSorterView
*>(xAccessible
.get());
821 if (pAccessibleView
== nullptr)
824 ::accessibility::AccessibleSlideSorterObject
* pChild
825 = pAccessibleView
->GetAccessibleChildImplementation(nPageIndex
);
826 if (pChild
== nullptr || pChild
->GetPage() == nullptr)
829 OUString
sNewName (pChild
->GetPage()->GetName());
830 pChild
->FireAccessibleEvent(
831 css::accessibility::AccessibleEventId::NAME_CHANGED
,
836 void SlideSorterController::SetDocumentSlides (const Reference
<container::XIndexAccess
>& rxSlides
)
838 if (mrModel
.GetDocumentSlides() != rxSlides
)
840 ModelChangeLock
aLock (*this);
843 mrModel
.SetDocumentSlides(rxSlides
);
847 VisibleAreaManager
& SlideSorterController::GetVisibleAreaManager() const
849 OSL_ASSERT(mpVisibleAreaManager
);
850 return *mpVisibleAreaManager
;
853 void SlideSorterController::CheckForMasterPageAssignment()
855 if (mrModel
.GetPageCount()%2==0)
857 PageEnumeration
aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel
));
858 while (aAllPages
.HasMoreElements())
860 SharedPageDescriptor
pDescriptor (aAllPages
.GetNextElement());
861 if (pDescriptor
->UpdateMasterPage())
863 mrView
.GetPreviewCache()->InvalidatePreviewBitmap (
864 pDescriptor
->GetPage());
869 void SlideSorterController::CheckForSlideTransitionAssignment()
871 if (mrModel
.GetPageCount()%2==0)
873 PageEnumeration
aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel
));
874 while (aAllPages
.HasMoreElements())
876 SharedPageDescriptor
pDescriptor (aAllPages
.GetNextElement());
877 if (pDescriptor
->UpdateTransitionFlag())
879 mrView
.GetPreviewCache()->InvalidatePreviewBitmap (
880 pDescriptor
->GetPage());
885 //===== SlideSorterController::ModelChangeLock ================================
887 SlideSorterController::ModelChangeLock::ModelChangeLock (
888 SlideSorterController
& rController
)
889 : mpController(&rController
)
891 mpController
->LockModelChange();
894 SlideSorterController::ModelChangeLock::~ModelChangeLock() COVERITY_NOEXCEPT_FALSE
899 void SlideSorterController::ModelChangeLock::Release()
901 if (mpController
!= nullptr)
903 mpController
->UnlockModelChange();
904 mpController
= nullptr;
908 } // end of namespace ::sd::slidesorter
910 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */