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/SlsTransferableData.hxx>
36 #include <controller/SlsVisibleAreaManager.hxx>
37 #include <model/SlideSorterModel.hxx>
38 #include <model/SlsPageEnumerationProvider.hxx>
39 #include <model/SlsPageDescriptor.hxx>
40 #include <view/SlideSorterView.hxx>
41 #include <view/SlsLayouter.hxx>
42 #include <view/SlsFontProvider.hxx>
43 #include <view/SlsPageObjectLayouter.hxx>
44 #include <view/SlsPageObjectPainter.hxx>
45 #include <view/SlsTheme.hxx>
46 #include <view/SlsToolTip.hxx>
47 #include <cache/SlsPageCache.hxx>
48 #include <cache/SlsPageCacheManager.hxx>
50 #include <drawdoc.hxx>
51 #include <DrawViewShell.hxx>
52 #include <ViewShellBase.hxx>
54 #include <FrameView.hxx>
55 #include <DrawDocShell.hxx>
61 #include <ViewShellHint.hxx>
62 #include <AccessibleSlideSorterView.hxx>
63 #include <AccessibleSlideSorterObject.hxx>
65 #include <vcl/window.hxx>
66 #include <svx/svdopage.hxx>
67 #include <svx/svxids.hrc>
68 #include <svx/ruler.hxx>
69 #include <sfx2/zoomitem.hxx>
70 #include <svtools/tabbar.hxx>
71 #include <sfx2/request.hxx>
72 #include <sfx2/viewfrm.hxx>
73 #include <sfx2/dispatch.hxx>
74 #include <vcl/commandevent.hxx>
75 #include <vcl/svapp.hxx>
76 #include <vcl/settings.hxx>
78 #include <com/sun/star/lang/XComponent.hpp>
79 #include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
80 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
81 #include <com/sun/star/drawing/XDrawPages.hpp>
82 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
86 using namespace ::com::sun::star
;
87 using namespace ::com::sun::star::uno
;
88 using namespace ::sd::slidesorter::model
;
89 using namespace ::sd::slidesorter::view
;
90 using namespace ::sd::slidesorter::controller
;
91 using namespace ::basegfx
;
93 namespace sd
{ namespace slidesorter
{ namespace controller
{
95 SlideSorterController::SlideSorterController (SlideSorter
& rSlideSorter
)
96 : mrSlideSorter(rSlideSorter
),
97 mrModel(mrSlideSorter
.GetModel()),
98 mrView(mrSlideSorter
.GetView()),
102 mpScrollBarManager(),
103 mpCurrentSlideManager(),
104 mpSelectionManager(),
106 mpInsertionIndicatorHandler(new InsertionIndicatorHandler(rSlideSorter
)),
107 mpAnimator(new Animator(rSlideSorter
)),
108 mpVisibleAreaManager(new VisibleAreaManager(rSlideSorter
)),
110 mnModelChangeLockCount(0),
111 mbIsForcedRearrangePending(false),
112 mbContextMenuOpen(false),
113 mbPostModelChangePending(false),
114 maSelectionBeforeSwitch(),
115 mnCurrentPageBeforeSwitch(0),
116 mpEditModeChangeMasterPage(nullptr),
118 mnPaintEntranceCount(0)
120 sd::Window
*pWindow (mrSlideSorter
.GetContentWindow().get());
125 // The whole background is painted by the view and controls.
126 vcl::Window
* pParentWindow
= pWindow
->GetParent();
127 OSL_ASSERT(pParentWindow
!=nullptr);
128 pParentWindow
->SetBackground (Wallpaper());
130 // Connect the view with the window that has been created by our base
132 pWindow
->SetBackground(Wallpaper());
133 pWindow
->SetCenterAllowed(false);
134 pWindow
->SetMapMode(MapMode(MapUnit::MapPixel
));
135 pWindow
->SetViewSize(mrView
.GetModelArea().GetSize());
138 void SlideSorterController::Init()
140 mpCurrentSlideManager
.reset(new CurrentSlideManager(mrSlideSorter
));
141 mpPageSelector
.reset(new PageSelector(mrSlideSorter
));
142 mpFocusManager
.reset(new FocusManager(mrSlideSorter
));
143 mpSlotManager
.reset(new SlotManager(mrSlideSorter
));
144 mpScrollBarManager
.reset(new ScrollBarManager(mrSlideSorter
));
145 mpSelectionManager
.reset(new SelectionManager(mrSlideSorter
));
146 mpClipboard
.reset(new Clipboard(mrSlideSorter
));
148 // Create the selection function.
149 SfxRequest
aRequest (
152 mrModel
.GetDocument()->GetItemPool());
153 mrSlideSorter
.SetCurrentFunction(CreateSelectionFunction(aRequest
));
155 mpListener
= new Listener(mrSlideSorter
);
157 mpPageSelector
->GetCoreSelection();
158 GetSelectionManager()->SelectionHasChanged();
161 SlideSorterController::~SlideSorterController()
165 uno::Reference
<lang::XComponent
> xComponent (
166 static_cast<XWeak
*>(mpListener
.get()), uno::UNO_QUERY
);
168 xComponent
->dispose();
170 catch( uno::Exception
& )
172 OSL_FAIL( "sd::SlideSorterController::~SlideSorterController(), exception caught!" );
175 // dispose should have been called by now so that nothing is to be done
176 // to shut down cleanly.
179 void SlideSorterController::Dispose()
181 mpInsertionIndicatorHandler
->End(Animator::AM_Immediate
);
183 mpSelectionManager
.reset();
184 mpAnimator
->Dispose();
187 model::SharedPageDescriptor
SlideSorterController::GetPageAt (
188 const Point
& aWindowPosition
)
190 sal_Int32
nHitPageIndex (mrView
.GetPageIndexAtPoint(aWindowPosition
));
191 model::SharedPageDescriptor pDescriptorAtPoint
;
192 if (nHitPageIndex
>= 0)
194 pDescriptorAtPoint
= mrModel
.GetPageDescriptor(nHitPageIndex
);
196 // Depending on a property we may have to check that the mouse is no
197 // just over the page object but over the preview area.
198 if (pDescriptorAtPoint
199 && ! pDescriptorAtPoint
->HasState(PageDescriptor::ST_Selected
))
201 // Make sure that the mouse is over the preview area.
202 if ( ! mrView
.GetLayouter().GetPageObjectLayouter()->GetBoundingBox(
204 view::PageObjectLayouter::Part::Preview
,
205 view::PageObjectLayouter::WindowCoordinateSystem
).IsInside(aWindowPosition
))
207 pDescriptorAtPoint
.reset();
212 return pDescriptorAtPoint
;
215 PageSelector
& SlideSorterController::GetPageSelector()
217 OSL_ASSERT(mpPageSelector
!= nullptr);
218 return *mpPageSelector
;
221 FocusManager
& SlideSorterController::GetFocusManager()
223 OSL_ASSERT(mpFocusManager
!= nullptr);
224 return *mpFocusManager
;
227 Clipboard
& SlideSorterController::GetClipboard()
229 OSL_ASSERT(mpClipboard
!= nullptr);
233 ScrollBarManager
& SlideSorterController::GetScrollBarManager()
235 OSL_ASSERT(mpScrollBarManager
!= nullptr);
236 return *mpScrollBarManager
;
239 std::shared_ptr
<CurrentSlideManager
> const & SlideSorterController::GetCurrentSlideManager() const
241 OSL_ASSERT(mpCurrentSlideManager
!= nullptr);
242 return mpCurrentSlideManager
;
245 std::shared_ptr
<SlotManager
> const & SlideSorterController::GetSlotManager() const
247 OSL_ASSERT(mpSlotManager
!= nullptr);
248 return mpSlotManager
;
251 std::shared_ptr
<SelectionManager
> const & SlideSorterController::GetSelectionManager() const
253 OSL_ASSERT(mpSelectionManager
!= nullptr);
254 return mpSelectionManager
;
257 std::shared_ptr
<InsertionIndicatorHandler
> const &
258 SlideSorterController::GetInsertionIndicatorHandler() const
260 OSL_ASSERT(mpInsertionIndicatorHandler
!= nullptr);
261 return mpInsertionIndicatorHandler
;
264 void SlideSorterController::Paint (
265 const ::tools::Rectangle
& rBBox
,
266 vcl::Window
* pWindow
)
268 if (mnPaintEntranceCount
!= 0)
271 ++mnPaintEntranceCount
;
275 mrView
.CompleteRedraw(pWindow
, vcl::Region(rBBox
));
277 catch (const Exception
&)
279 // Ignore all exceptions.
282 --mnPaintEntranceCount
;
285 void SlideSorterController::FuTemporary (SfxRequest
& rRequest
)
287 mpSlotManager
->FuTemporary (rRequest
);
290 void SlideSorterController::FuPermanent (SfxRequest
&rRequest
)
292 mpSlotManager
->FuPermanent (rRequest
);
295 void SlideSorterController::FuSupport (SfxRequest
&rRequest
)
297 mpSlotManager
->FuSupport (rRequest
);
300 bool SlideSorterController::Command (
301 const CommandEvent
& rEvent
,
302 ::sd::Window
* pWindow
)
304 bool bEventHasBeenHandled
= false;
306 if (pWindow
== nullptr)
309 ViewShell
* pViewShell
= mrSlideSorter
.GetViewShell();
310 if (pViewShell
== nullptr)
313 switch (rEvent
.GetCommand())
315 case CommandEventId::ContextMenu
:
317 SdPage
* pPage
= nullptr;
320 model::PageEnumeration
aSelectedPages (
321 PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel
));
322 if (aSelectedPages
.HasMoreElements())
323 pPage
= aSelectedPages
.GetNextElement()->GetPage();
325 if (mrModel
.GetEditMode() == EditMode::Page
)
327 if (pPage
!= nullptr)
328 aPopupId
= "pagepane";
330 aPopupId
= "pagepanenosel";
332 else if (pPage
!= nullptr)
333 aPopupId
= "pagepanemaster";
335 aPopupId
= "pagepanenoselmaster";
337 std::unique_ptr
<InsertionIndicatorHandler::ForceShowContext
> pContext
;
338 if (pPage
== nullptr)
340 // When there is no selection, then we show the insertion
341 // indicator so that the user knows where a page insertion
343 mpInsertionIndicatorHandler
->Start(false);
344 mpInsertionIndicatorHandler
->UpdateIndicatorIcon(SD_MOD()->pTransferClip
);
345 mpInsertionIndicatorHandler
->UpdatePosition(
346 pWindow
->PixelToLogic(rEvent
.GetMousePosPixel()),
347 InsertionIndicatorHandler::MoveMode
);
348 pContext
.reset(new InsertionIndicatorHandler::ForceShowContext(
349 mpInsertionIndicatorHandler
));
352 pWindow
->ReleaseMouse();
354 Point
aMenuLocation (0,0);
355 if (!rEvent
.IsMouseEvent())
357 // The event is not a mouse event. Use the center of the
358 // focused page as top left position of the context menu.
359 model::SharedPageDescriptor
pDescriptor (
360 GetFocusManager().GetFocusedPageDescriptor());
361 if (pDescriptor
.get() != nullptr)
363 ::tools::Rectangle
aBBox (
364 mrView
.GetLayouter().GetPageObjectLayouter()->GetBoundingBox (
366 PageObjectLayouter::Part::PageObject
,
367 PageObjectLayouter::ModelCoordinateSystem
));
368 aMenuLocation
= aBBox
.Center();
372 if (SfxDispatcher
* pDispatcher
= pViewShell
->GetDispatcher())
374 mbContextMenuOpen
= true;
375 if (!rEvent
.IsMouseEvent())
376 pDispatcher
->ExecutePopup(aPopupId
, pWindow
, &aMenuLocation
);
378 pDispatcher
->ExecutePopup(aPopupId
);
379 mbContextMenuOpen
= false;
380 mrSlideSorter
.GetView().UpdatePageUnderMouse();
381 ::rtl::Reference
<SelectionFunction
> pFunction(GetCurrentSelectionFunction());
383 pFunction
->ResetMouseAnchor();
385 if (pPage
== nullptr)
387 // Remember the position of the insertion indicator before
388 // it is hidden, so that a pending slide insertion slot call
389 // finds the right place to insert a new slide.
390 GetSelectionManager()->SetInsertionPosition(
391 GetInsertionIndicatorHandler()->GetInsertionPageIndex());
394 bEventHasBeenHandled
= true;
398 case CommandEventId::Wheel
:
400 const CommandWheelData
* pData
= rEvent
.GetWheelData();
401 if (pData
== nullptr)
405 // We do not support zooming with control+mouse wheel.
408 // Determine whether to scroll horizontally or vertically. This
409 // depends on the orientation of the scroll bar and the
410 // IsHoriz() flag of the event.
411 if ((mrSlideSorter
.GetView().GetOrientation()==view::Layouter::HORIZONTAL
)
414 GetScrollBarManager().Scroll(
415 ScrollBarManager::Orientation_Vertical
,
416 -pData
->GetNotchDelta());
420 GetScrollBarManager().Scroll(
421 ScrollBarManager::Orientation_Horizontal
,
422 -pData
->GetNotchDelta());
424 mrSlideSorter
.GetView().UpdatePageUnderMouse(rEvent
.GetMousePosPixel());
426 bEventHasBeenHandled
= true;
433 return bEventHasBeenHandled
;
436 void SlideSorterController::LockModelChange()
438 mnModelChangeLockCount
+= 1;
441 void SlideSorterController::UnlockModelChange()
443 mnModelChangeLockCount
-= 1;
444 if (mnModelChangeLockCount
==0 && mbPostModelChangePending
)
450 void SlideSorterController::PreModelChange()
452 // Prevent PreModelChange to execute more than once per model lock.
453 if (mbPostModelChangePending
)
456 if (mrSlideSorter
.GetViewShell() != nullptr)
457 mrSlideSorter
.GetViewShell()->Broadcast(
458 ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START
));
460 GetCurrentSlideManager()->PrepareModelChange();
462 if (mrSlideSorter
.GetContentWindow())
463 mrView
.PreModelChange();
465 mbPostModelChangePending
= true;
468 void SlideSorterController::PostModelChange()
470 mbPostModelChangePending
= false;
473 sd::Window
*pWindow (mrSlideSorter
.GetContentWindow().get());
476 GetCurrentSlideManager()->HandleModelChange();
478 mrView
.PostModelChange ();
480 pWindow
->SetViewOrigin (Point (0,0));
481 pWindow
->SetViewSize (mrView
.GetModelArea().GetSize());
483 // The visibility of the scroll bars may have to be changed. Then
484 // the size of the view has to change, too. Let Rearrange() handle
486 Rearrange(mbIsForcedRearrangePending
);
489 if (mrSlideSorter
.GetViewShell() != nullptr)
490 mrSlideSorter
.GetViewShell()->Broadcast(
491 ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END
));
494 void SlideSorterController::HandleModelChange()
496 // Ignore this call when the document is not in a valid state, i.e. has
497 // not the same number of regular and notes pages.
498 bool bIsDocumentValid
= (mrModel
.GetDocument()->GetPageCount() % 2 == 1);
500 if (bIsDocumentValid
)
502 ModelChangeLock
aLock (*this);
507 IMPL_LINK(SlideSorterController
, ApplicationEventHandler
, VclSimpleEvent
&, rEvent
, void)
509 auto windowEvent
= dynamic_cast<VclWindowEvent
*>(&rEvent
);
510 if (windowEvent
!= nullptr) {
511 WindowEventHandler(*windowEvent
);
514 IMPL_LINK(SlideSorterController
, WindowEventHandler
, VclWindowEvent
&, rEvent
, void)
516 vcl::Window
* pWindow
= rEvent
.GetWindow();
517 sd::Window
*pActiveWindow (mrSlideSorter
.GetContentWindow().get());
518 switch (rEvent
.GetId())
520 case VclEventId::WindowActivate
:
521 case VclEventId::WindowShow
:
522 if (pActiveWindow
&& pWindow
== pActiveWindow
->GetParent())
523 mrView
.RequestRepaint();
526 case VclEventId::WindowHide
:
527 if (pActiveWindow
&& pWindow
== pActiveWindow
->GetParent())
528 mrView
.SetPageUnderMouse(SharedPageDescriptor());
531 case VclEventId::WindowGetFocus
:
533 if (pWindow
== pActiveWindow
)
534 GetFocusManager().ShowFocus(false);
537 case VclEventId::WindowLoseFocus
:
538 if (pActiveWindow
&& pWindow
== pActiveWindow
)
540 GetFocusManager().HideFocus();
541 mrView
.GetToolTip().Hide();
543 //don't scroll back to the selected slide when we lose
544 //focus due to a temporary active context menu
545 if (!mbContextMenuOpen
)
547 // Select the current slide so that it is properly
548 // visualized when the focus is moved to the edit view.
549 GetPageSelector().SelectPage(GetCurrentSlideManager()->GetCurrentSlide());
554 case VclEventId::ApplicationDataChanged
:
556 // Invalidate the preview cache.
557 cache::PageCacheManager::Instance()->InvalidateAllCaches();
559 // Update the draw mode.
560 DrawModeFlags
nDrawMode (Application::GetSettings().GetStyleSettings().GetHighContrastMode()
561 ? sd::OUTPUT_DRAWMODE_CONTRAST
562 : sd::OUTPUT_DRAWMODE_COLOR
);
563 if (mrSlideSorter
.GetViewShell() != nullptr)
564 mrSlideSorter
.GetViewShell()->GetFrameView()->SetDrawMode(nDrawMode
);
565 if (pActiveWindow
!= nullptr)
566 pActiveWindow
->SetDrawMode(nDrawMode
);
567 mrView
.HandleDrawModeChange();
569 // When the system font has changed a layout has to be done.
571 FontProvider::Instance().Invalidate();
573 // Update theme colors.
574 mrSlideSorter
.GetProperties()->HandleDataChangeEvent();
575 mrSlideSorter
.GetTheme()->Update(mrSlideSorter
.GetProperties());
576 mrView
.HandleDataChangeEvent();
585 void SlideSorterController::GetCtrlState (SfxItemSet
& rSet
)
587 if (rSet
.GetItemState(SID_RELOAD
) != SfxItemState::UNKNOWN
)
589 // let SFx en-/disable "last version"
590 SfxViewFrame
* pSlideViewFrame
= SfxViewFrame::Current();
591 DBG_ASSERT(pSlideViewFrame
!=nullptr,
592 "SlideSorterController::GetCtrlState: ViewFrame not found");
595 pSlideViewFrame
->GetSlotState (SID_RELOAD
, nullptr, &rSet
);
597 else // MI says: no MDIFrame --> disable
599 rSet
.DisableItem(SID_RELOAD
);
604 if (rSet
.GetItemState(SID_OUTPUT_QUALITY_COLOR
)==SfxItemState::DEFAULT
605 ||rSet
.GetItemState(SID_OUTPUT_QUALITY_GRAYSCALE
)==SfxItemState::DEFAULT
606 ||rSet
.GetItemState(SID_OUTPUT_QUALITY_BLACKWHITE
)==SfxItemState::DEFAULT
607 ||rSet
.GetItemState(SID_OUTPUT_QUALITY_CONTRAST
)==SfxItemState::DEFAULT
)
609 if (mrSlideSorter
.GetContentWindow())
611 DrawModeFlags nMode
= mrSlideSorter
.GetContentWindow()->GetDrawMode();
612 sal_uInt16 nQuality
= 0;
614 if (nMode
== sd::OUTPUT_DRAWMODE_COLOR
) {
616 } else if (nMode
== sd::OUTPUT_DRAWMODE_GRAYSCALE
) {
618 } else if (nMode
== sd::OUTPUT_DRAWMODE_BLACKWHITE
) {
620 } else if (nMode
== sd::OUTPUT_DRAWMODE_CONTRAST
) {
624 rSet
.Put (SfxBoolItem (SID_OUTPUT_QUALITY_COLOR
, nQuality
==0));
625 rSet
.Put (SfxBoolItem (SID_OUTPUT_QUALITY_GRAYSCALE
, nQuality
==1));
626 rSet
.Put (SfxBoolItem (SID_OUTPUT_QUALITY_BLACKWHITE
, nQuality
==2));
627 rSet
.Put (SfxBoolItem (SID_OUTPUT_QUALITY_CONTRAST
, nQuality
==3));
631 if (rSet
.GetItemState(SID_MAIL_SCROLLBODY_PAGEDOWN
) == SfxItemState::DEFAULT
)
633 rSet
.Put (SfxBoolItem( SID_MAIL_SCROLLBODY_PAGEDOWN
, true));
637 void SlideSorterController::GetStatusBarState (SfxItemSet
& rSet
)
639 mpSlotManager
->GetStatusBarState (rSet
);
642 void SlideSorterController::ExecCtrl (SfxRequest
& rRequest
)
644 mpSlotManager
->ExecCtrl (rRequest
);
647 void SlideSorterController::GetAttrState (SfxItemSet
& rSet
)
649 mpSlotManager
->GetAttrState (rSet
);
652 void SlideSorterController::UpdateAllPages()
655 mrSlideSorter
.GetContentWindow()->Invalidate();
658 void SlideSorterController::Resize (const ::tools::Rectangle
& rAvailableSpace
)
660 if (maTotalWindowArea
!= rAvailableSpace
)
662 maTotalWindowArea
= rAvailableSpace
;
667 void SlideSorterController::Rearrange (bool bForce
)
669 if (maTotalWindowArea
.IsEmpty())
672 if (mnModelChangeLockCount
>0)
674 mbIsForcedRearrangePending
|= bForce
;
678 mbIsForcedRearrangePending
= false;
680 sd::Window
*pWindow (mrSlideSorter
.GetContentWindow().get());
685 mrView
.UpdateOrientation();
687 // Place the scroll bars.
688 ::tools::Rectangle aNewContentArea
= GetScrollBarManager().PlaceScrollBars(
690 mrView
.GetOrientation() != view::Layouter::VERTICAL
,
691 mrView
.GetOrientation() != view::Layouter::HORIZONTAL
);
693 bool bSizeHasChanged (false);
694 // Only when bForce is not true we have to test for a size change in
695 // order to determine whether the window and the view have to be resized.
698 ::tools::Rectangle
aCurrentContentArea (pWindow
->GetPosPixel(), pWindow
->GetOutputSizePixel());
699 bSizeHasChanged
= (aNewContentArea
!= aCurrentContentArea
);
701 if (bForce
|| bSizeHasChanged
)
703 // The browser window gets the remaining space.
704 pWindow
->SetPosSizePixel (aNewContentArea
.TopLeft(), aNewContentArea
.GetSize());
708 // Adapt the scroll bars to the new zoom factor of the browser
709 // window and the arrangement of the page objects.
710 GetScrollBarManager().UpdateScrollBars(!bForce
);
712 // Keep the current slide in the visible area.
713 GetVisibleAreaManager().RequestCurrentSlideVisible();
715 mrView
.RequestRepaint();
718 rtl::Reference
<FuPoor
> SlideSorterController::CreateSelectionFunction (SfxRequest
& rRequest
)
720 rtl::Reference
<FuPoor
> xFunc( SelectionFunction::Create(mrSlideSorter
, rRequest
) );
724 ::rtl::Reference
<SelectionFunction
> SlideSorterController::GetCurrentSelectionFunction()
726 rtl::Reference
<FuPoor
> pFunction (mrSlideSorter
.GetViewShell()->GetCurrentFunction());
727 return ::rtl::Reference
<SelectionFunction
>(dynamic_cast<SelectionFunction
*>(pFunction
.get()));
730 void SlideSorterController::PrepareEditModeChange()
732 // Before we throw away the page descriptors we prepare for selecting
733 // descriptors in the other mode and for restoring the current
734 // selection when switching back to the current mode.
735 if (mrModel
.GetEditMode() != EditMode::Page
)
738 maSelectionBeforeSwitch
.clear();
740 // Search for the first selected page and determine the master page
741 // used by its page object. It will be selected after the switch.
742 // In the same loop the current selection is stored.
743 PageEnumeration
aSelectedPages (
744 PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel
));
745 while (aSelectedPages
.HasMoreElements())
747 SharedPageDescriptor
pDescriptor (aSelectedPages
.GetNextElement());
748 SdPage
* pPage
= pDescriptor
->GetPage();
749 // Remember the master page of the first selected descriptor.
750 if (pPage
!=nullptr && mpEditModeChangeMasterPage
==nullptr)
751 mpEditModeChangeMasterPage
= &static_cast<SdPage
&>(
752 pPage
->TRG_GetMasterPage());
754 maSelectionBeforeSwitch
.push_back(pPage
);
757 // Remember the current page.
758 if (mrSlideSorter
.GetViewShell() != nullptr)
759 mnCurrentPageBeforeSwitch
= (mrSlideSorter
.GetViewShell()->GetViewShellBase()
760 .GetMainViewShell()->GetActualPage()->GetPageNum()-1)/2;
763 void SlideSorterController::ChangeEditMode (EditMode eEditMode
)
765 bool bResult (false);
766 if (mrModel
.GetEditMode() != eEditMode
)
768 ModelChangeLock
aLock (*this);
770 // Do the actual edit mode switching.
771 bResult
= mrModel
.SetEditMode(eEditMode
);
777 void SlideSorterController::FinishEditModeChange()
779 if (mrModel
.GetEditMode() == EditMode::MasterPage
)
781 mpPageSelector
->DeselectAllPages();
783 // Search for the master page that was determined in
784 // PrepareEditModeChange() and make it the current page.
785 PageEnumeration
aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel
));
786 while (aAllPages
.HasMoreElements())
788 SharedPageDescriptor
pDescriptor (aAllPages
.GetNextElement());
789 if (pDescriptor
->GetPage() == mpEditModeChangeMasterPage
)
791 GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor
);
792 mpPageSelector
->SelectPage(pDescriptor
);
799 PageSelector::BroadcastLock
aBroadcastLock (*mpPageSelector
);
801 SharedPageDescriptor
pDescriptor (mrModel
.GetPageDescriptor(mnCurrentPageBeforeSwitch
));
802 GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor
);
804 // Restore the selection.
805 mpPageSelector
->DeselectAllPages();
806 for (const auto& rpPage
: maSelectionBeforeSwitch
)
808 mpPageSelector
->SelectPage(rpPage
);
810 maSelectionBeforeSwitch
.clear( );
812 mpEditModeChangeMasterPage
= nullptr;
815 void SlideSorterController::PageNameHasChanged (int nPageIndex
, const OUString
& rsOldName
)
817 // Request a repaint for the page object whose name has changed.
818 model::SharedPageDescriptor
pDescriptor (mrModel
.GetPageDescriptor(nPageIndex
));
819 if (pDescriptor
.get() != nullptr)
820 mrView
.RequestRepaint(pDescriptor
);
822 // Get a pointer to the corresponding accessible object and notify
823 // that of the name change.
824 sd::Window
*pWindow (mrSlideSorter
.GetContentWindow().get());
828 css::uno::Reference
< css::accessibility::XAccessible
>
829 xAccessible (pWindow
->GetAccessible(false));
830 if ( ! xAccessible
.is())
833 // Now comes a small hack. We assume that the accessible object is
834 // an instantiation of AccessibleSlideSorterView and cast it to that
835 // class. The cleaner alternative to this cast would be a new member
836 // in which we would store the last AccessibleSlideSorterView object
837 // created by SlideSorterViewShell::CreateAccessibleDocumentView().
838 // But then there is no guaranty that the accessible object obtained
839 // from the window really is that instance last created by
840 // CreateAccessibleDocumentView().
841 // However, the dynamic cast together with the check of the result
842 // being NULL should be safe enough.
843 ::accessibility::AccessibleSlideSorterView
* pAccessibleView
844 = dynamic_cast< ::accessibility::AccessibleSlideSorterView
*>(xAccessible
.get());
845 if (pAccessibleView
== nullptr)
848 ::accessibility::AccessibleSlideSorterObject
* pChild
849 = pAccessibleView
->GetAccessibleChildImplementation(nPageIndex
);
850 if (pChild
== nullptr || pChild
->GetPage() == nullptr)
853 OUString
sNewName (pChild
->GetPage()->GetName());
854 pChild
->FireAccessibleEvent(
855 css::accessibility::AccessibleEventId::NAME_CHANGED
,
860 void SlideSorterController::SetDocumentSlides (const Reference
<container::XIndexAccess
>& rxSlides
)
862 if (mrModel
.GetDocumentSlides() != rxSlides
)
864 ModelChangeLock
aLock (*this);
867 mrModel
.SetDocumentSlides(rxSlides
);
871 VisibleAreaManager
& SlideSorterController::GetVisibleAreaManager() const
873 OSL_ASSERT(mpVisibleAreaManager
);
874 return *mpVisibleAreaManager
;
877 void SlideSorterController::CheckForMasterPageAssignment()
879 if (mrModel
.GetPageCount()%2==0)
881 PageEnumeration
aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel
));
882 while (aAllPages
.HasMoreElements())
884 SharedPageDescriptor
pDescriptor (aAllPages
.GetNextElement());
885 if (pDescriptor
->UpdateMasterPage())
887 mrView
.GetPreviewCache()->InvalidatePreviewBitmap (
888 pDescriptor
->GetPage());
893 void SlideSorterController::CheckForSlideTransitionAssignment()
895 if (mrModel
.GetPageCount()%2==0)
897 PageEnumeration
aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel
));
898 while (aAllPages
.HasMoreElements())
900 SharedPageDescriptor
pDescriptor (aAllPages
.GetNextElement());
901 if (pDescriptor
->UpdateTransitionFlag())
903 mrView
.GetPreviewCache()->InvalidatePreviewBitmap (
904 pDescriptor
->GetPage());
909 //===== SlideSorterController::ModelChangeLock ================================
911 SlideSorterController::ModelChangeLock::ModelChangeLock (
912 SlideSorterController
& rController
)
913 : mpController(&rController
)
915 mpController
->LockModelChange();
918 SlideSorterController::ModelChangeLock::~ModelChangeLock() COVERITY_NOEXCEPT_FALSE
923 void SlideSorterController::ModelChangeLock::Release()
925 if (mpController
!= nullptr)
927 mpController
->UnlockModelChange();
928 mpController
= nullptr;
932 } } } // end of namespace ::sd::slidesorter
934 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */