bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / ui / slidesorter / controller / SlideSorterController.cxx
blobbb4f44ce0649619a6d1253ef3e6805de98fc916c
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 <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>
53 #include <Window.hxx>
54 #include <FrameView.hxx>
55 #include <DrawDocShell.hxx>
56 #include <sdpage.hxx>
58 #include <app.hrc>
59 #include <sdmod.hxx>
60 #include <sdxfer.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>
84 #include <memory>
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()),
99 mpPageSelector(),
100 mpFocusManager(),
101 mpSlotManager(),
102 mpScrollBarManager(),
103 mpCurrentSlideManager(),
104 mpSelectionManager(),
105 mpClipboard(),
106 mpInsertionIndicatorHandler(new InsertionIndicatorHandler(rSlideSorter)),
107 mpAnimator(new Animator(rSlideSorter)),
108 mpVisibleAreaManager(new VisibleAreaManager(rSlideSorter)),
109 mpListener(),
110 mnModelChangeLockCount(0),
111 mbIsForcedRearrangePending(false),
112 mbContextMenuOpen(false),
113 mbPostModelChangePending(false),
114 maSelectionBeforeSwitch(),
115 mnCurrentPageBeforeSwitch(0),
116 mpEditModeChangeMasterPage(nullptr),
117 maTotalWindowArea(),
118 mnPaintEntranceCount(0)
120 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
121 OSL_ASSERT(pWindow);
122 if (!pWindow)
123 return;
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
131 // class.
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 (
150 SID_OBJECT_SELECT,
151 SfxCallMode::SLOT,
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);
167 if (xComponent.is())
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);
182 mpClipboard.reset();
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(
203 pDescriptorAtPoint,
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);
230 return *mpClipboard;
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)
269 return;
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)
307 return false;
309 ViewShell* pViewShell = mrSlideSorter.GetViewShell();
310 if (pViewShell == nullptr)
311 return false;
313 switch (rEvent.GetCommand())
315 case CommandEventId::ContextMenu:
317 SdPage* pPage = nullptr;
318 OUString aPopupId;
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";
329 else
330 aPopupId = "pagepanenosel";
332 else if (pPage != nullptr)
333 aPopupId = "pagepanemaster";
334 else
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
342 // would take place.
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 (
365 pDescriptor,
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);
377 else
378 pDispatcher->ExecutePopup(aPopupId);
379 mbContextMenuOpen = false;
380 mrSlideSorter.GetView().UpdatePageUnderMouse();
381 ::rtl::Reference<SelectionFunction> pFunction(GetCurrentSelectionFunction());
382 if (pFunction.is())
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());
393 pContext.reset();
394 bEventHasBeenHandled = true;
396 break;
398 case CommandEventId::Wheel:
400 const CommandWheelData* pData = rEvent.GetWheelData();
401 if (pData == nullptr)
402 return false;
403 if (pData->IsMod1())
405 // We do not support zooming with control+mouse wheel.
406 return false;
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)
412 == pData->IsHorz())
414 GetScrollBarManager().Scroll(
415 ScrollBarManager::Orientation_Vertical,
416 -pData->GetNotchDelta());
418 else
420 GetScrollBarManager().Scroll(
421 ScrollBarManager::Orientation_Horizontal,
422 -pData->GetNotchDelta());
424 mrSlideSorter.GetView().UpdatePageUnderMouse(rEvent.GetMousePosPixel());
426 bEventHasBeenHandled = true;
428 break;
430 default: break;
433 return bEventHasBeenHandled;
436 void SlideSorterController::LockModelChange()
438 mnModelChangeLockCount += 1;
441 void SlideSorterController::UnlockModelChange()
443 mnModelChangeLockCount -= 1;
444 if (mnModelChangeLockCount==0 && mbPostModelChangePending)
446 PostModelChange();
450 void SlideSorterController::PreModelChange()
452 // Prevent PreModelChange to execute more than once per model lock.
453 if (mbPostModelChangePending)
454 return;
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;
471 mrModel.Resync();
473 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
474 if (pWindow)
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
485 // that.
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);
503 PreModelChange();
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();
524 break;
526 case VclEventId::WindowHide:
527 if (pActiveWindow && pWindow == pActiveWindow->GetParent())
528 mrView.SetPageUnderMouse(SharedPageDescriptor());
529 break;
531 case VclEventId::WindowGetFocus:
532 if (pActiveWindow)
533 if (pWindow == pActiveWindow)
534 GetFocusManager().ShowFocus(false);
535 break;
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());
552 break;
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.
570 mrView.Resize();
571 FontProvider::Instance().Invalidate();
573 // Update theme colors.
574 mrSlideSorter.GetProperties()->HandleDataChangeEvent();
575 mrSlideSorter.GetTheme()->Update(mrSlideSorter.GetProperties());
576 mrView.HandleDataChangeEvent();
578 break;
580 default:
581 break;
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");
593 if (pSlideViewFrame)
595 pSlideViewFrame->GetSlotState (SID_RELOAD, nullptr, &rSet);
597 else // MI says: no MDIFrame --> disable
599 rSet.DisableItem(SID_RELOAD);
603 // Output quality.
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) {
615 nQuality = 0;
616 } else if (nMode == sd::OUTPUT_DRAWMODE_GRAYSCALE) {
617 nQuality = 1;
618 } else if (nMode == sd::OUTPUT_DRAWMODE_BLACKWHITE) {
619 nQuality = 2;
620 } else if (nMode == sd::OUTPUT_DRAWMODE_CONTRAST) {
621 nQuality = 3;
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()
654 // Do a redraw.
655 mrSlideSorter.GetContentWindow()->Invalidate();
658 void SlideSorterController::Resize (const ::tools::Rectangle& rAvailableSpace)
660 if (maTotalWindowArea != rAvailableSpace)
662 maTotalWindowArea = rAvailableSpace;
663 Rearrange(true);
667 void SlideSorterController::Rearrange (bool bForce)
669 if (maTotalWindowArea.IsEmpty())
670 return;
672 if (mnModelChangeLockCount>0)
674 mbIsForcedRearrangePending |= bForce;
675 return;
677 else
678 mbIsForcedRearrangePending = false;
680 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
681 if (!pWindow)
682 return;
684 if (bForce)
685 mrView.UpdateOrientation();
687 // Place the scroll bars.
688 ::tools::Rectangle aNewContentArea = GetScrollBarManager().PlaceScrollBars(
689 maTotalWindowArea,
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.
696 if ( ! bForce)
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());
705 mrView.Resize();
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) );
721 return xFunc;
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)
736 return;
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);
769 PreModelChange();
770 // Do the actual edit mode switching.
771 bResult = mrModel.SetEditMode(eEditMode);
772 if (bResult)
773 HandleModelChange();
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);
793 break;
797 else
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());
825 if ( ! pWindow)
826 return;
828 css::uno::Reference< css::accessibility::XAccessible >
829 xAccessible (pWindow->GetAccessible(false));
830 if ( ! xAccessible.is())
831 return;
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)
846 return;
848 ::accessibility::AccessibleSlideSorterObject* pChild
849 = pAccessibleView->GetAccessibleChildImplementation(nPageIndex);
850 if (pChild == nullptr || pChild->GetPage() == nullptr)
851 return;
853 OUString sNewName (pChild->GetPage()->GetName());
854 pChild->FireAccessibleEvent(
855 css::accessibility::AccessibleEventId::NAME_CHANGED,
856 makeAny(rsOldName),
857 makeAny(sNewName));
860 void SlideSorterController::SetDocumentSlides (const Reference<container::XIndexAccess>& rxSlides)
862 if (mrModel.GetDocumentSlides() != rxSlides)
864 ModelChangeLock aLock (*this);
865 PreModelChange();
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)
880 return;
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)
896 return;
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
920 Release();
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: */