summaryrefslogtreecommitdiffstats
path: root/sd/source/ui/slidesorter/controller/SlideSorterController.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/slidesorter/controller/SlideSorterController.cxx')
-rw-r--r--sd/source/ui/slidesorter/controller/SlideSorterController.cxx910
1 files changed, 910 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/controller/SlideSorterController.cxx b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx
new file mode 100644
index 000000000..5c851f183
--- /dev/null
+++ b/sd/source/ui/slidesorter/controller/SlideSorterController.cxx
@@ -0,0 +1,910 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <controller/SlideSorterController.hxx>
+
+#include <SlideSorter.hxx>
+#include <controller/SlsPageSelector.hxx>
+#include <controller/SlsSelectionFunction.hxx>
+#include <controller/SlsProperties.hxx>
+#include <controller/SlsCurrentSlideManager.hxx>
+#include "SlsListener.hxx"
+#include <controller/SlsFocusManager.hxx>
+#include <controller/SlsAnimator.hxx>
+#include <controller/SlsClipboard.hxx>
+#include <controller/SlsInsertionIndicatorHandler.hxx>
+#include <controller/SlsScrollBarManager.hxx>
+#include <controller/SlsSelectionManager.hxx>
+#include <controller/SlsSlotManager.hxx>
+#include <controller/SlsVisibleAreaManager.hxx>
+#include <model/SlideSorterModel.hxx>
+#include <model/SlsPageEnumerationProvider.hxx>
+#include <model/SlsPageDescriptor.hxx>
+#include <view/SlideSorterView.hxx>
+#include <view/SlsLayouter.hxx>
+#include <view/SlsPageObjectLayouter.hxx>
+#include <view/SlsTheme.hxx>
+#include <view/SlsToolTip.hxx>
+#include <cache/SlsPageCache.hxx>
+#include <cache/SlsPageCacheManager.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <drawdoc.hxx>
+#include <ViewShellBase.hxx>
+#include <Window.hxx>
+#include <FrameView.hxx>
+#include <sdpage.hxx>
+
+#include <app.hrc>
+#include <sdmod.hxx>
+#include <ViewShellHint.hxx>
+#include <AccessibleSlideSorterView.hxx>
+#include <AccessibleSlideSorterObject.hxx>
+
+#include <vcl/window.hxx>
+#include <svx/svxids.hrc>
+#include <sfx2/request.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <sfx2/dispatch.hxx>
+#include <tools/debug.hxx>
+#include <vcl/commandevent.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::sd::slidesorter::model;
+using namespace ::sd::slidesorter::view;
+using namespace ::sd::slidesorter::controller;
+using namespace ::basegfx;
+
+namespace sd::slidesorter::controller {
+
+SlideSorterController::SlideSorterController (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mrModel(mrSlideSorter.GetModel()),
+ mrView(mrSlideSorter.GetView()),
+ mpInsertionIndicatorHandler(std::make_shared<InsertionIndicatorHandler>(rSlideSorter)),
+ mpAnimator(std::make_shared<Animator>(rSlideSorter)),
+ mpVisibleAreaManager(new VisibleAreaManager(rSlideSorter)),
+ mnModelChangeLockCount(0),
+ mbIsForcedRearrangePending(false),
+ mbContextMenuOpen(false),
+ mbPostModelChangePending(false),
+ mnCurrentPageBeforeSwitch(0),
+ mpEditModeChangeMasterPage(nullptr),
+ mnPaintEntranceCount(0)
+{
+ sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
+ OSL_ASSERT(pWindow);
+ if (!pWindow)
+ return;
+
+ // The whole background is painted by the view and controls.
+ vcl::Window* pParentWindow = pWindow->GetParent();
+ OSL_ASSERT(pParentWindow!=nullptr);
+ pParentWindow->SetBackground (Wallpaper());
+
+ // Connect the view with the window that has been created by our base
+ // class.
+ pWindow->SetBackground(Wallpaper());
+ pWindow->SetCenterAllowed(false);
+ pWindow->SetMapMode(MapMode(MapUnit::MapPixel));
+ pWindow->SetViewSize(mrView.GetModelArea().GetSize());
+}
+
+void SlideSorterController::Init()
+{
+ mpCurrentSlideManager = std::make_shared<CurrentSlideManager>(mrSlideSorter);
+ mpPageSelector.reset(new PageSelector(mrSlideSorter));
+ mpFocusManager.reset(new FocusManager(mrSlideSorter));
+ mpSlotManager = std::make_shared<SlotManager>(mrSlideSorter);
+ mpScrollBarManager.reset(new ScrollBarManager(mrSlideSorter));
+ mpSelectionManager = std::make_shared<SelectionManager>(mrSlideSorter);
+ mpClipboard.reset(new Clipboard(mrSlideSorter));
+
+ // Create the selection function.
+ SfxRequest aRequest (
+ SID_OBJECT_SELECT,
+ SfxCallMode::SLOT,
+ mrModel.GetDocument()->GetItemPool());
+ mrSlideSorter.SetCurrentFunction(CreateSelectionFunction(aRequest));
+
+ mpListener = new Listener(mrSlideSorter);
+
+ mpPageSelector->GetCoreSelection();
+ GetSelectionManager()->SelectionHasChanged();
+}
+
+SlideSorterController::~SlideSorterController()
+{
+ try
+ {
+ uno::Reference<lang::XComponent> xComponent = mpListener;
+ if (xComponent.is())
+ xComponent->dispose();
+ }
+ catch( uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "sd", "sd::SlideSorterController::~SlideSorterController()" );
+ }
+
+ // dispose should have been called by now so that nothing is to be done
+ // to shut down cleanly.
+}
+
+void SlideSorterController::Dispose()
+{
+ mpInsertionIndicatorHandler->End(Animator::AM_Immediate);
+ mpClipboard.reset();
+ mpSelectionManager.reset();
+ mpAnimator->Dispose();
+}
+
+model::SharedPageDescriptor SlideSorterController::GetPageAt (
+ const Point& aWindowPosition)
+{
+ sal_Int32 nHitPageIndex (mrView.GetPageIndexAtPoint(aWindowPosition));
+ model::SharedPageDescriptor pDescriptorAtPoint;
+ if (nHitPageIndex >= 0)
+ {
+ pDescriptorAtPoint = mrModel.GetPageDescriptor(nHitPageIndex);
+
+ // Depending on a property we may have to check that the mouse is no
+ // just over the page object but over the preview area.
+ if (pDescriptorAtPoint
+ && ! pDescriptorAtPoint->HasState(PageDescriptor::ST_Selected))
+ {
+ // Make sure that the mouse is over the preview area.
+ if ( ! mrView.GetLayouter().GetPageObjectLayouter()->GetBoundingBox(
+ pDescriptorAtPoint,
+ view::PageObjectLayouter::Part::Preview,
+ view::PageObjectLayouter::WindowCoordinateSystem).Contains(aWindowPosition))
+ {
+ pDescriptorAtPoint.reset();
+ }
+ }
+ }
+
+ return pDescriptorAtPoint;
+}
+
+PageSelector& SlideSorterController::GetPageSelector()
+{
+ OSL_ASSERT(mpPageSelector != nullptr);
+ return *mpPageSelector;
+}
+
+FocusManager& SlideSorterController::GetFocusManager()
+{
+ OSL_ASSERT(mpFocusManager != nullptr);
+ return *mpFocusManager;
+}
+
+Clipboard& SlideSorterController::GetClipboard()
+{
+ OSL_ASSERT(mpClipboard != nullptr);
+ return *mpClipboard;
+}
+
+ScrollBarManager& SlideSorterController::GetScrollBarManager()
+{
+ OSL_ASSERT(mpScrollBarManager != nullptr);
+ return *mpScrollBarManager;
+}
+
+std::shared_ptr<CurrentSlideManager> const & SlideSorterController::GetCurrentSlideManager() const
+{
+ OSL_ASSERT(mpCurrentSlideManager != nullptr);
+ return mpCurrentSlideManager;
+}
+
+std::shared_ptr<SlotManager> const & SlideSorterController::GetSlotManager() const
+{
+ OSL_ASSERT(mpSlotManager != nullptr);
+ return mpSlotManager;
+}
+
+std::shared_ptr<SelectionManager> const & SlideSorterController::GetSelectionManager() const
+{
+ OSL_ASSERT(mpSelectionManager != nullptr);
+ return mpSelectionManager;
+}
+
+std::shared_ptr<InsertionIndicatorHandler> const &
+ SlideSorterController::GetInsertionIndicatorHandler() const
+{
+ OSL_ASSERT(mpInsertionIndicatorHandler != nullptr);
+ return mpInsertionIndicatorHandler;
+}
+
+void SlideSorterController::Paint (
+ const ::tools::Rectangle& rBBox,
+ vcl::Window* pWindow)
+{
+ if (mnPaintEntranceCount != 0)
+ return;
+
+ ++mnPaintEntranceCount;
+
+ try
+ {
+ mrView.CompleteRedraw(pWindow->GetOutDev(), vcl::Region(rBBox));
+ }
+ catch (const Exception&)
+ {
+ // Ignore all exceptions.
+ }
+
+ --mnPaintEntranceCount;
+}
+
+void SlideSorterController::FuTemporary (SfxRequest& rRequest)
+{
+ mpSlotManager->FuTemporary (rRequest);
+}
+
+void SlideSorterController::FuPermanent (SfxRequest &rRequest)
+{
+ mpSlotManager->FuPermanent (rRequest);
+}
+
+void SlideSorterController::FuSupport (SfxRequest &rRequest)
+{
+ mpSlotManager->FuSupport (rRequest);
+}
+
+bool SlideSorterController::Command (
+ const CommandEvent& rEvent,
+ ::sd::Window* pWindow)
+{
+ bool bEventHasBeenHandled = false;
+
+ if (pWindow == nullptr)
+ return false;
+
+ ViewShell* pViewShell = mrSlideSorter.GetViewShell();
+ if (pViewShell == nullptr)
+ return false;
+
+ switch (rEvent.GetCommand())
+ {
+ case CommandEventId::ContextMenu:
+ {
+ SdPage* pPage = nullptr;
+ OUString aPopupId;
+
+ model::PageEnumeration aSelectedPages (
+ PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
+ if (aSelectedPages.HasMoreElements())
+ pPage = aSelectedPages.GetNextElement()->GetPage();
+
+ if (mrModel.GetEditMode() == EditMode::Page)
+ {
+ if (pPage != nullptr)
+ aPopupId = "pagepane";
+ else
+ aPopupId = "pagepanenosel";
+ }
+ else if (pPage != nullptr)
+ aPopupId = "pagepanemaster";
+ else
+ aPopupId = "pagepanenoselmaster";
+
+ std::unique_ptr<InsertionIndicatorHandler::ForceShowContext, o3tl::default_delete<InsertionIndicatorHandler::ForceShowContext>> xContext;
+ if (pPage == nullptr)
+ {
+ // When there is no selection, then we show the insertion
+ // indicator so that the user knows where a page insertion
+ // would take place.
+ mpInsertionIndicatorHandler->Start(false);
+ mpInsertionIndicatorHandler->UpdateIndicatorIcon(SD_MOD()->pTransferClip);
+ mpInsertionIndicatorHandler->UpdatePosition(
+ pWindow->PixelToLogic(rEvent.GetMousePosPixel()),
+ InsertionIndicatorHandler::MoveMode);
+ xContext.reset(new InsertionIndicatorHandler::ForceShowContext(
+ mpInsertionIndicatorHandler));
+ }
+
+ pWindow->ReleaseMouse();
+
+ Point aMenuLocation (0,0);
+ if (!rEvent.IsMouseEvent())
+ {
+ // The event is not a mouse event. Use the center of the
+ // focused page as top left position of the context menu.
+ model::SharedPageDescriptor pDescriptor (
+ GetFocusManager().GetFocusedPageDescriptor());
+ if (pDescriptor)
+ {
+ ::tools::Rectangle aBBox (
+ mrView.GetLayouter().GetPageObjectLayouter()->GetBoundingBox (
+ pDescriptor,
+ PageObjectLayouter::Part::PageObject,
+ PageObjectLayouter::ModelCoordinateSystem));
+ aMenuLocation = aBBox.Center();
+ }
+ }
+
+ if (SfxDispatcher* pDispatcher = pViewShell->GetDispatcher())
+ {
+ mbContextMenuOpen = true;
+ if (!rEvent.IsMouseEvent())
+ pDispatcher->ExecutePopup(aPopupId, pWindow, &aMenuLocation);
+ else
+ pDispatcher->ExecutePopup(aPopupId, pWindow);
+ mbContextMenuOpen = false;
+ mrSlideSorter.GetView().UpdatePageUnderMouse();
+ ::rtl::Reference<SelectionFunction> pFunction(GetCurrentSelectionFunction());
+ if (pFunction.is())
+ pFunction->ResetMouseAnchor();
+ }
+ if (pPage == nullptr)
+ {
+ // Remember the position of the insertion indicator before
+ // it is hidden, so that a pending slide insertion slot call
+ // finds the right place to insert a new slide.
+ GetSelectionManager()->SetInsertionPosition(
+ GetInsertionIndicatorHandler()->GetInsertionPageIndex());
+ }
+ xContext.reset();
+ bEventHasBeenHandled = true;
+ }
+ break;
+
+ case CommandEventId::Wheel:
+ {
+ const CommandWheelData* pData = rEvent.GetWheelData();
+ if (pData == nullptr)
+ return false;
+ if (pData->IsMod1())
+ {
+ // We do not support zooming with control+mouse wheel.
+ return false;
+ }
+ // Determine whether to scroll horizontally or vertically. This
+ // depends on the orientation of the scroll bar and the
+ // IsHoriz() flag of the event.
+ if ((mrSlideSorter.GetView().GetOrientation()==view::Layouter::HORIZONTAL)
+ == pData->IsHorz())
+ {
+ GetScrollBarManager().Scroll(
+ ScrollBarManager::Orientation_Vertical,
+ -pData->GetNotchDelta());
+ }
+ else
+ {
+ GetScrollBarManager().Scroll(
+ ScrollBarManager::Orientation_Horizontal,
+ -pData->GetNotchDelta());
+ }
+ mrSlideSorter.GetView().UpdatePageUnderMouse(rEvent.GetMousePosPixel());
+
+ bEventHasBeenHandled = true;
+ }
+ break;
+
+ default: break;
+ }
+
+ return bEventHasBeenHandled;
+}
+
+void SlideSorterController::LockModelChange()
+{
+ mnModelChangeLockCount += 1;
+}
+
+void SlideSorterController::UnlockModelChange()
+{
+ mnModelChangeLockCount -= 1;
+ if (mnModelChangeLockCount==0 && mbPostModelChangePending)
+ {
+ PostModelChange();
+ }
+}
+
+void SlideSorterController::PreModelChange()
+{
+ // Prevent PreModelChange to execute more than once per model lock.
+ if (mbPostModelChangePending)
+ return;
+
+ if (mrSlideSorter.GetViewShell() != nullptr)
+ mrSlideSorter.GetViewShell()->Broadcast(
+ ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START));
+
+ GetCurrentSlideManager()->PrepareModelChange();
+
+ if (mrSlideSorter.GetContentWindow())
+ mrView.PreModelChange();
+
+ mbPostModelChangePending = true;
+}
+
+void SlideSorterController::PostModelChange()
+{
+ mbPostModelChangePending = false;
+ mrModel.Resync();
+
+ sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
+ if (pWindow)
+ {
+ GetCurrentSlideManager()->HandleModelChange();
+
+ mrView.PostModelChange ();
+
+ pWindow->SetViewOrigin (Point (0,0));
+ pWindow->SetViewSize (mrView.GetModelArea().GetSize());
+
+ // The visibility of the scroll bars may have to be changed. Then
+ // the size of the view has to change, too. Let Rearrange() handle
+ // that.
+ Rearrange(mbIsForcedRearrangePending);
+ }
+
+ if (mrSlideSorter.GetViewShell() != nullptr)
+ mrSlideSorter.GetViewShell()->Broadcast(
+ ViewShellHint(ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END));
+}
+
+void SlideSorterController::HandleModelChange()
+{
+ // Ignore this call when the document is not in a valid state, i.e. has
+ // not the same number of regular and notes pages.
+ bool bIsDocumentValid = (mrModel.GetDocument()->GetPageCount() % 2 == 1);
+
+ if (bIsDocumentValid)
+ {
+ ModelChangeLock aLock (*this);
+ PreModelChange();
+ }
+}
+
+IMPL_LINK(SlideSorterController, ApplicationEventHandler, VclSimpleEvent&, rEvent, void)
+{
+ auto windowEvent = dynamic_cast<VclWindowEvent *>(&rEvent);
+ if (windowEvent != nullptr) {
+ WindowEventHandler(*windowEvent);
+ }
+}
+IMPL_LINK(SlideSorterController, WindowEventHandler, VclWindowEvent&, rEvent, void)
+{
+ vcl::Window* pWindow = rEvent.GetWindow();
+ sd::Window *pActiveWindow (mrSlideSorter.GetContentWindow().get());
+ switch (rEvent.GetId())
+ {
+ case VclEventId::WindowActivate:
+ case VclEventId::WindowShow:
+ if (pActiveWindow && pWindow == pActiveWindow->GetParent())
+ mrView.RequestRepaint();
+ break;
+
+ case VclEventId::WindowHide:
+ if (pActiveWindow && pWindow == pActiveWindow->GetParent())
+ mrView.SetPageUnderMouse(SharedPageDescriptor());
+ break;
+
+ case VclEventId::WindowGetFocus:
+ if (pActiveWindow)
+ if (pWindow == pActiveWindow)
+ GetFocusManager().ShowFocus(false);
+ break;
+
+ case VclEventId::WindowLoseFocus:
+ if (pActiveWindow && pWindow == pActiveWindow)
+ {
+ GetFocusManager().HideFocus();
+ mrView.GetToolTip().Hide();
+
+ //don't scroll back to the selected slide when we lose
+ //focus due to a temporary active context menu
+ if (!mbContextMenuOpen)
+ {
+ // Select the current slide so that it is properly
+ // visualized when the focus is moved to the edit view.
+ GetPageSelector().SelectPage(GetCurrentSlideManager()->GetCurrentSlide());
+ }
+ }
+ break;
+
+ case VclEventId::ApplicationDataChanged:
+ {
+ // Invalidate the preview cache.
+ cache::PageCacheManager::Instance()->InvalidateAllCaches();
+
+ // Update the draw mode.
+ DrawModeFlags nDrawMode (Application::GetSettings().GetStyleSettings().GetHighContrastMode()
+ ? sd::OUTPUT_DRAWMODE_CONTRAST
+ : sd::OUTPUT_DRAWMODE_COLOR);
+ if (mrSlideSorter.GetViewShell() != nullptr)
+ mrSlideSorter.GetViewShell()->GetFrameView()->SetDrawMode(nDrawMode);
+ if (pActiveWindow != nullptr)
+ pActiveWindow->GetOutDev()->SetDrawMode(nDrawMode);
+ mrView.HandleDrawModeChange();
+
+ // When the system font has changed a layout has to be done.
+ mrView.Resize();
+
+ // Update theme colors.
+ mrSlideSorter.GetProperties()->HandleDataChangeEvent();
+ mrSlideSorter.GetTheme()->Update(mrSlideSorter.GetProperties());
+ mrView.HandleDataChangeEvent();
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void SlideSorterController::GetCtrlState (SfxItemSet& rSet)
+{
+ if (rSet.GetItemState(SID_RELOAD) != SfxItemState::UNKNOWN)
+ {
+ // let SFx en-/disable "last version"
+ SfxViewFrame* pSlideViewFrame = SfxViewFrame::Current();
+ DBG_ASSERT(pSlideViewFrame!=nullptr,
+ "SlideSorterController::GetCtrlState: ViewFrame not found");
+ if (pSlideViewFrame)
+ {
+ pSlideViewFrame->GetSlotState (SID_RELOAD, nullptr, &rSet);
+ }
+ else // MI says: no MDIFrame --> disable
+ {
+ rSet.DisableItem(SID_RELOAD);
+ }
+ }
+
+ // Output quality.
+ if (rSet.GetItemState(SID_OUTPUT_QUALITY_COLOR)==SfxItemState::DEFAULT
+ ||rSet.GetItemState(SID_OUTPUT_QUALITY_GRAYSCALE)==SfxItemState::DEFAULT
+ ||rSet.GetItemState(SID_OUTPUT_QUALITY_BLACKWHITE)==SfxItemState::DEFAULT
+ ||rSet.GetItemState(SID_OUTPUT_QUALITY_CONTRAST)==SfxItemState::DEFAULT)
+ {
+ if (mrSlideSorter.GetContentWindow())
+ {
+ DrawModeFlags nMode = mrSlideSorter.GetContentWindow()->GetOutDev()->GetDrawMode();
+ sal_uInt16 nQuality = 0;
+
+ if (nMode == sd::OUTPUT_DRAWMODE_COLOR) {
+ nQuality = 0;
+ } else if (nMode == sd::OUTPUT_DRAWMODE_GRAYSCALE) {
+ nQuality = 1;
+ } else if (nMode == sd::OUTPUT_DRAWMODE_BLACKWHITE) {
+ nQuality = 2;
+ } else if (nMode == sd::OUTPUT_DRAWMODE_CONTRAST) {
+ nQuality = 3;
+ }
+
+ rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_COLOR, nQuality==0));
+ rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_GRAYSCALE, nQuality==1));
+ rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_BLACKWHITE, nQuality==2));
+ rSet.Put (SfxBoolItem (SID_OUTPUT_QUALITY_CONTRAST, nQuality==3));
+ }
+ }
+
+ if (rSet.GetItemState(SID_MAIL_SCROLLBODY_PAGEDOWN) == SfxItemState::DEFAULT)
+ {
+ rSet.Put (SfxBoolItem( SID_MAIL_SCROLLBODY_PAGEDOWN, true));
+ }
+}
+
+void SlideSorterController::GetStatusBarState (SfxItemSet& rSet)
+{
+ mpSlotManager->GetStatusBarState (rSet);
+}
+
+void SlideSorterController::ExecCtrl (SfxRequest& rRequest)
+{
+ mpSlotManager->ExecCtrl (rRequest);
+}
+
+void SlideSorterController::GetAttrState (SfxItemSet& rSet)
+{
+ mpSlotManager->GetAttrState (rSet);
+}
+
+void SlideSorterController::UpdateAllPages()
+{
+ // Do a redraw.
+ mrSlideSorter.GetContentWindow()->Invalidate();
+}
+
+void SlideSorterController::Resize (const ::tools::Rectangle& rAvailableSpace)
+{
+ if (maTotalWindowArea != rAvailableSpace)
+ {
+ maTotalWindowArea = rAvailableSpace;
+ Rearrange(true);
+ }
+}
+
+void SlideSorterController::Rearrange (bool bForce)
+{
+ if (maTotalWindowArea.IsEmpty())
+ return;
+
+ if (mnModelChangeLockCount>0)
+ {
+ mbIsForcedRearrangePending |= bForce;
+ return;
+ }
+ else
+ mbIsForcedRearrangePending = false;
+
+ sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
+ if (!pWindow)
+ return;
+
+ if (bForce)
+ mrView.UpdateOrientation();
+
+ // Place the scroll bars.
+ ::tools::Rectangle aNewContentArea = GetScrollBarManager().PlaceScrollBars(
+ maTotalWindowArea,
+ mrView.GetOrientation() != view::Layouter::VERTICAL,
+ mrView.GetOrientation() != view::Layouter::HORIZONTAL);
+
+ bool bSizeHasChanged (false);
+ // Only when bForce is not true we have to test for a size change in
+ // order to determine whether the window and the view have to be resized.
+ if ( ! bForce)
+ {
+ ::tools::Rectangle aCurrentContentArea (pWindow->GetPosPixel(), pWindow->GetOutputSizePixel());
+ bSizeHasChanged = (aNewContentArea != aCurrentContentArea);
+ }
+ if (bForce || bSizeHasChanged)
+ {
+ // The browser window gets the remaining space.
+ pWindow->SetPosSizePixel (aNewContentArea.TopLeft(), aNewContentArea.GetSize());
+ mrView.Resize();
+ }
+
+ // Adapt the scroll bars to the new zoom factor of the browser
+ // window and the arrangement of the page objects.
+ GetScrollBarManager().UpdateScrollBars(!bForce);
+
+ // Keep the current slide in the visible area.
+ GetVisibleAreaManager().RequestCurrentSlideVisible();
+
+ mrView.RequestRepaint();
+}
+
+rtl::Reference<FuPoor> SlideSorterController::CreateSelectionFunction (SfxRequest& rRequest)
+{
+ rtl::Reference<FuPoor> xFunc( SelectionFunction::Create(mrSlideSorter, rRequest) );
+ return xFunc;
+}
+
+::rtl::Reference<SelectionFunction> SlideSorterController::GetCurrentSelectionFunction() const
+{
+ rtl::Reference<FuPoor> pFunction (mrSlideSorter.GetViewShell()->GetCurrentFunction());
+ return ::rtl::Reference<SelectionFunction>(dynamic_cast<SelectionFunction*>(pFunction.get()));
+}
+
+void SlideSorterController::PrepareEditModeChange()
+{
+ // Before we throw away the page descriptors we prepare for selecting
+ // descriptors in the other mode and for restoring the current
+ // selection when switching back to the current mode.
+ if (mrModel.GetEditMode() != EditMode::Page)
+ return;
+
+ maSelectionBeforeSwitch.clear();
+
+ // Search for the first selected page and determine the master page
+ // used by its page object. It will be selected after the switch.
+ // In the same loop the current selection is stored.
+ PageEnumeration aSelectedPages (
+ PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
+ while (aSelectedPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
+ SdPage* pPage = pDescriptor->GetPage();
+ // Remember the master page of the first selected descriptor.
+ if (pPage!=nullptr && mpEditModeChangeMasterPage==nullptr)
+ mpEditModeChangeMasterPage = &static_cast<SdPage&>(
+ pPage->TRG_GetMasterPage());
+
+ maSelectionBeforeSwitch.push_back(pPage);
+ }
+
+ // Remember the current page.
+ if (mrSlideSorter.GetViewShell() != nullptr)
+ mnCurrentPageBeforeSwitch = (mrSlideSorter.GetViewShell()->GetViewShellBase()
+ .GetMainViewShell()->GetActualPage()->GetPageNum()-1)/2;
+}
+
+void SlideSorterController::ChangeEditMode (EditMode eEditMode)
+{
+ if (mrModel.GetEditMode() != eEditMode)
+ {
+ ModelChangeLock aLock (*this);
+ PreModelChange();
+ // Do the actual edit mode switching.
+ bool bResult = mrModel.SetEditMode(eEditMode);
+ if (bResult)
+ HandleModelChange();
+ }
+}
+
+void SlideSorterController::FinishEditModeChange()
+{
+ if (mrModel.GetEditMode() == EditMode::MasterPage)
+ {
+ mpPageSelector->DeselectAllPages();
+
+ // Search for the master page that was determined in
+ // PrepareEditModeChange() and make it the current page.
+ PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aAllPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ if (pDescriptor->GetPage() == mpEditModeChangeMasterPage)
+ {
+ GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
+ mpPageSelector->SelectPage(pDescriptor);
+ break;
+ }
+ }
+ }
+ else
+ {
+ PageSelector::BroadcastLock aBroadcastLock (*mpPageSelector);
+
+ SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(mnCurrentPageBeforeSwitch));
+ GetCurrentSlideManager()->SwitchCurrentSlide(pDescriptor);
+
+ // Restore the selection.
+ mpPageSelector->DeselectAllPages();
+ for (const auto& rpPage : maSelectionBeforeSwitch)
+ {
+ mpPageSelector->SelectPage(rpPage);
+ }
+ maSelectionBeforeSwitch.clear( );
+ }
+ mpEditModeChangeMasterPage = nullptr;
+}
+
+void SlideSorterController::PageNameHasChanged (int nPageIndex, const OUString& rsOldName)
+{
+ // Request a repaint for the page object whose name has changed.
+ model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
+ if (pDescriptor)
+ mrView.RequestRepaint(pDescriptor);
+
+ // Get a pointer to the corresponding accessible object and notify
+ // that of the name change.
+ sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
+ if ( ! pWindow)
+ return;
+
+ css::uno::Reference< css::accessibility::XAccessible >
+ xAccessible (pWindow->GetAccessible(false));
+ if ( ! xAccessible.is())
+ return;
+
+ // Now comes a small hack. We assume that the accessible object is
+ // an instantiation of AccessibleSlideSorterView and cast it to that
+ // class. The cleaner alternative to this cast would be a new member
+ // in which we would store the last AccessibleSlideSorterView object
+ // created by SlideSorterViewShell::CreateAccessibleDocumentView().
+ // But then there is no guaranty that the accessible object obtained
+ // from the window really is that instance last created by
+ // CreateAccessibleDocumentView().
+ // However, the dynamic cast together with the check of the result
+ // being NULL should be safe enough.
+ ::accessibility::AccessibleSlideSorterView* pAccessibleView
+ = dynamic_cast< ::accessibility::AccessibleSlideSorterView*>(xAccessible.get());
+ if (pAccessibleView == nullptr)
+ return;
+
+ ::accessibility::AccessibleSlideSorterObject* pChild
+ = pAccessibleView->GetAccessibleChildImplementation(nPageIndex);
+ if (pChild == nullptr || pChild->GetPage() == nullptr)
+ return;
+
+ OUString sNewName (pChild->GetPage()->GetName());
+ pChild->FireAccessibleEvent(
+ css::accessibility::AccessibleEventId::NAME_CHANGED,
+ Any(rsOldName),
+ Any(sNewName));
+}
+
+void SlideSorterController::SetDocumentSlides (const Reference<container::XIndexAccess>& rxSlides)
+{
+ if (mrModel.GetDocumentSlides() != rxSlides)
+ {
+ ModelChangeLock aLock (*this);
+ PreModelChange();
+
+ mrModel.SetDocumentSlides(rxSlides);
+ }
+}
+
+VisibleAreaManager& SlideSorterController::GetVisibleAreaManager() const
+{
+ OSL_ASSERT(mpVisibleAreaManager);
+ return *mpVisibleAreaManager;
+}
+
+void SlideSorterController::CheckForMasterPageAssignment()
+{
+ if (mrModel.GetPageCount()%2==0)
+ return;
+ PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aAllPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ if (pDescriptor->UpdateMasterPage())
+ {
+ mrView.GetPreviewCache()->InvalidatePreviewBitmap (
+ pDescriptor->GetPage());
+ }
+ }
+}
+
+void SlideSorterController::CheckForSlideTransitionAssignment()
+{
+ if (mrModel.GetPageCount()%2==0)
+ return;
+ PageEnumeration aAllPages (PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aAllPages.HasMoreElements())
+ {
+ SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
+ if (pDescriptor->UpdateTransitionFlag())
+ {
+ mrView.GetPreviewCache()->InvalidatePreviewBitmap (
+ pDescriptor->GetPage());
+ }
+ }
+}
+
+//===== SlideSorterController::ModelChangeLock ================================
+
+SlideSorterController::ModelChangeLock::ModelChangeLock (
+ SlideSorterController& rController)
+ : mpController(&rController)
+{
+ mpController->LockModelChange();
+}
+
+SlideSorterController::ModelChangeLock::~ModelChangeLock() COVERITY_NOEXCEPT_FALSE
+{
+ Release();
+}
+
+void SlideSorterController::ModelChangeLock::Release()
+{
+ if (mpController != nullptr)
+ {
+ mpController->UnlockModelChange();
+ mpController = nullptr;
+ }
+}
+
+} // end of namespace ::sd::slidesorter
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */