diff options
author | Sarper Akdemir <sarper.akdemir@allotropia.de> | 2024-05-08 14:14:58 +0200 |
---|---|---|
committer | Sarper Akdemir <sarper.akdemir@allotropia.de> | 2024-05-16 15:01:55 +0200 |
commit | 9d075157ccf3e9468b5208291e398a9d7e4728b8 (patch) | |
tree | 92ade858a5884c015519948f2e0e09f6beb47e5f /sd | |
parent | 45f9627659e882b9157782dfc5981e31567a306e (diff) |
tdf#33603: sd: make state of notes pane persist across runs
Introduces new NotesPaneModule which manages the visibility
of NotesPane across modes and different runs.
Also introduces new three config values under
Office/Impress/MuliPaneGUI/NotesPane/Visible ImpressView,
OutlineView and NotesView.
Similar to what was there for SlideSorterBar.
Change-Id: Id540c508e81878e5a8e1aebd6544839e70b813c8
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167348
Tested-by: Jenkins
Reviewed-by: Sarper Akdemir <sarper.akdemir@allotropia.de>
Diffstat (limited to 'sd')
-rw-r--r-- | sd/Library_sd.mk | 1 | ||||
-rw-r--r-- | sd/source/ui/framework/module/ImpressModule.cxx | 2 | ||||
-rw-r--r-- | sd/source/ui/framework/module/ModuleController.cxx | 2 | ||||
-rw-r--r-- | sd/source/ui/framework/module/NotesPaneModule.cxx | 268 | ||||
-rw-r--r-- | sd/source/ui/framework/module/NotesPaneModule.hxx | 91 | ||||
-rw-r--r-- | sd/source/ui/inc/framework/factories/BasicPaneFactory.hxx | 1 |
6 files changed, 365 insertions, 0 deletions
diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk index de39df79b25b..01f3a1d59610 100644 --- a/sd/Library_sd.mk +++ b/sd/Library_sd.mk @@ -277,6 +277,7 @@ $(eval $(call gb_Library_add_exception_objects,sd,\ sd/source/ui/framework/module/DrawModule \ sd/source/ui/framework/module/ImpressModule \ sd/source/ui/framework/module/ModuleController \ + sd/source/ui/framework/module/NotesPaneModule \ sd/source/ui/framework/module/PresentationModule \ sd/source/ui/framework/module/ShellStackGuard \ sd/source/ui/framework/module/SlideSorterModule \ diff --git a/sd/source/ui/framework/module/ImpressModule.cxx b/sd/source/ui/framework/module/ImpressModule.cxx index 03c393e29ec4..6879513950a9 100644 --- a/sd/source/ui/framework/module/ImpressModule.cxx +++ b/sd/source/ui/framework/module/ImpressModule.cxx @@ -22,6 +22,7 @@ #include <framework/FrameworkHelper.hxx> #include "ViewTabBarModule.hxx" #include "CenterViewFocusModule.hxx" +#include "NotesPaneModule.hxx" #include "SlideSorterModule.hxx" #include "ToolBarModule.hxx" #include "ShellStackGuard.hxx" @@ -42,6 +43,7 @@ void ImpressModule::Initialize (rtl::Reference<sd::DrawController> const & rxCon new SlideSorterModule( rxController, FrameworkHelper::msLeftImpressPaneURL); + new NotesPaneModule(rxController); new ToolBarModule(rxController); new ShellStackGuard(rxController); } diff --git a/sd/source/ui/framework/module/ModuleController.cxx b/sd/source/ui/framework/module/ModuleController.cxx index b064eefcdad7..501eb0d81af9 100644 --- a/sd/source/ui/framework/module/ModuleController.cxx +++ b/sd/source/ui/framework/module/ModuleController.cxx @@ -52,6 +52,7 @@ ModuleController::ModuleController(const rtl::Reference<::sd::DrawController>& r "com.sun.star.drawing.framework.BasicPaneFactory", { "private:resource/pane/CenterPane", "private:resource/pane/LeftImpressPane", + "private:resource/pane/BottomImpressPane", "private:resource/pane/LeftDrawPane" }); ProcessFactory( "com.sun.star.drawing.framework.BasicViewFactory", @@ -59,6 +60,7 @@ ModuleController::ModuleController(const rtl::Reference<::sd::DrawController>& r "private:resource/view/GraphicView", "private:resource/view/OutlineView", "private:resource/view/NotesView", + "private:resource/view/NotesPanelView", "private:resource/view/HandoutView", "private:resource/view/SlideSorter", "private:resource/view/PresentationView" }); diff --git a/sd/source/ui/framework/module/NotesPaneModule.cxx b/sd/source/ui/framework/module/NotesPaneModule.cxx new file mode 100644 index 000000000000..e489d8a8ff7c --- /dev/null +++ b/sd/source/ui/framework/module/NotesPaneModule.cxx @@ -0,0 +1,268 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ + +#include "NotesPaneModule.hxx" + +#include <DrawController.hxx> +#include <DrawViewShell.hxx> +#include <EventMultiplexer.hxx> +#include <ViewShellBase.hxx> +#include <ViewShellManager.hxx> + +#include <framework/ConfigurationController.hxx> +#include <framework/FrameworkHelper.hxx> +#include <framework/ViewShellWrapper.hxx> + +#include <officecfg/Office/Impress.hxx> + +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/frame/XController.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; + +namespace +{ +const sal_Int32 ResourceActivationRequestEvent = 0; +const sal_Int32 ResourceDeactivationRequestEvent = 1; +} + +namespace sd::framework +{ +NotesPaneModule::NotesPaneModule(const rtl::Reference<::sd::DrawController>& rxController) + : mxBottomImpressPaneId(FrameworkHelper::CreateResourceId( + FrameworkHelper::msNotesPanelViewURL, FrameworkHelper::msBottomImpressPaneURL)) + , mxMainViewAnchorId(FrameworkHelper::CreateResourceId(FrameworkHelper::msCenterPaneURL)) +{ + if (!rxController.is()) + return; + + mpViewShellBase = rxController->GetViewShellBase(); + + mxConfigurationController = rxController->getConfigurationController(); + if (!mxConfigurationController.is()) + return; + + mxConfigurationController->addConfigurationChangeListener( + this, FrameworkHelper::msResourceActivationRequestEvent, + Any(ResourceActivationRequestEvent)); + mxConfigurationController->addConfigurationChangeListener( + this, FrameworkHelper::msResourceDeactivationRequestEvent, + Any(ResourceDeactivationRequestEvent)); + + if (officecfg::Office::Impress::MultiPaneGUI::NotesPane::Visible::ImpressView::get().value_or( + false)) + AddActiveMainView(FrameworkHelper::msImpressViewURL); + if (officecfg::Office::Impress::MultiPaneGUI::NotesPane::Visible::OutlineView::get().value_or( + false)) + AddActiveMainView(FrameworkHelper::msOutlineViewURL); + if (officecfg::Office::Impress::MultiPaneGUI::NotesPane::Visible::NotesView::get().value_or( + false)) + AddActiveMainView(FrameworkHelper::msNotesViewURL); +} + +NotesPaneModule::~NotesPaneModule() +{ + if (mpViewShellBase && mbListeningEventMultiplexer) + mpViewShellBase->GetEventMultiplexer()->RemoveEventListener( + LINK(this, NotesPaneModule, EventMultiplexerListener)); +} + +void NotesPaneModule::AddActiveMainView(const OUString& rsMainViewURL) +{ + maActiveMainViewContainer.insert(rsMainViewURL); +} + +bool NotesPaneModule::IsResourceActive(const OUString& rsMainViewURL) +{ + return maActiveMainViewContainer.contains(rsMainViewURL); +} + +void NotesPaneModule::SaveResourceState() +{ + auto xChanges = comphelper::ConfigurationChanges::create(); + officecfg::Office::Impress::MultiPaneGUI::NotesPane::Visible::ImpressView::set( + IsResourceActive(FrameworkHelper::msImpressViewURL), xChanges); + officecfg::Office::Impress::MultiPaneGUI::NotesPane::Visible::OutlineView::set( + IsResourceActive(FrameworkHelper::msOutlineViewURL), xChanges); + officecfg::Office::Impress::MultiPaneGUI::NotesPane::Visible::NotesView::set( + IsResourceActive(FrameworkHelper::msNotesViewURL), xChanges); + xChanges->commit(); +} + +void NotesPaneModule::disposing(std::unique_lock<std::mutex>&) +{ + if (mxConfigurationController.is()) + { + mxConfigurationController->removeConfigurationChangeListener(this); + mxConfigurationController = nullptr; + } +} + +IMPL_LINK(NotesPaneModule, EventMultiplexerListener, sd::tools::EventMultiplexerEvent&, rEvent, + void) +{ + if (!mxConfigurationController.is()) + return; + + switch (rEvent.meEventId) + { + case EventMultiplexerEventId::EditModeNormal: + mbInMasterEditMode = false; + if (IsResourceActive(msCurrentMainViewURL)) + { + mxConfigurationController->requestResourceActivation( + mxBottomImpressPaneId->getAnchor(), ResourceActivationMode_ADD); + mxConfigurationController->requestResourceActivation( + mxBottomImpressPaneId, ResourceActivationMode_REPLACE); + } + else + { + mxConfigurationController->requestResourceDeactivation(mxBottomImpressPaneId); + } + break; + case EventMultiplexerEventId::EditModeMaster: + mbInMasterEditMode = true; + mxConfigurationController->requestResourceDeactivation(mxBottomImpressPaneId); + break; + default: + break; + } +} + +void SAL_CALL NotesPaneModule::notifyConfigurationChange(const ConfigurationChangeEvent& rEvent) +{ + if (!mxConfigurationController.is()) + return; + + // the late init is hacked here since there's EventMultiplexer isn't available when the + // NotesPaneModule is constructed + if (!mbListeningEventMultiplexer) + { + mpViewShellBase->GetEventMultiplexer()->AddEventListener( + LINK(this, NotesPaneModule, EventMultiplexerListener)); + mbListeningEventMultiplexer = true; + } + + sal_Int32 nEventType = 0; + rEvent.UserData >>= nEventType; + switch (nEventType) + { + case ResourceActivationRequestEvent: + if (rEvent.ResourceId->isBoundToURL(FrameworkHelper::msCenterPaneURL, + AnchorBindingMode_DIRECT)) + { + if (rEvent.ResourceId->getResourceTypePrefix() == FrameworkHelper::msViewURLPrefix) + { + onMainViewSwitch(rEvent.ResourceId->getResourceURL(), true); + } + } + else if (rEvent.ResourceId->compareTo(mxBottomImpressPaneId) == 0) + { + onResourceRequest(true, rEvent.Configuration); + } + break; + + case ResourceDeactivationRequestEvent: + if (rEvent.ResourceId->compareTo(mxMainViewAnchorId) == 0) + { + onMainViewSwitch(OUString(), false); + } + else if (rEvent.ResourceId->compareTo(mxBottomImpressPaneId) == 0) + { + onResourceRequest(false, rEvent.Configuration); + } + break; + default: + break; + } +} + +void SAL_CALL NotesPaneModule::disposing(const lang::EventObject& rEvent) +{ + if (mxConfigurationController.is() && rEvent.Source == mxConfigurationController) + { + SaveResourceState(); + // Without the configuration controller this class can do nothing. + mxConfigurationController = nullptr; + dispose(); + } +} + +void NotesPaneModule::onMainViewSwitch(const OUString& rsViewURL, const bool bIsActivated) +{ + if (bIsActivated) + msCurrentMainViewURL = rsViewURL; + else + msCurrentMainViewURL.clear(); + + if (!mxConfigurationController.is()) + return; + + sd::framework::ConfigurationController::Lock aLock(mxConfigurationController); + + if (IsResourceActive(msCurrentMainViewURL) && !mbInMasterEditMode) + { + mxConfigurationController->requestResourceActivation(mxBottomImpressPaneId->getAnchor(), + ResourceActivationMode_ADD); + mxConfigurationController->requestResourceActivation(mxBottomImpressPaneId, + ResourceActivationMode_REPLACE); + } + else + { + mxConfigurationController->requestResourceDeactivation(mxBottomImpressPaneId); + } +} + +bool NotesPaneModule::IsMasterView(const Reference<XView>& xView) +{ + if (mpViewShellBase != nullptr) + { + auto pViewShellWrapper = dynamic_cast<ViewShellWrapper*>(xView.get()); + if (pViewShellWrapper) + { + std::shared_ptr<ViewShell> pViewShell = pViewShellWrapper->GetViewShell(); + auto pDrawViewShell = std::dynamic_pointer_cast<DrawViewShell>(pViewShell); + + if (pDrawViewShell && pDrawViewShell->GetEditMode() == EditMode::MasterPage) + return true; + } + } + return false; +} + +void NotesPaneModule::onResourceRequest( + bool bActivation, + const css::uno::Reference<css::drawing::framework::XConfiguration>& rxConfiguration) +{ + Sequence<Reference<XResourceId>> aCenterViews = rxConfiguration->getResources( + FrameworkHelper::CreateResourceId(FrameworkHelper::msCenterPaneURL), + FrameworkHelper::msViewURLPrefix, AnchorBindingMode_DIRECT); + + if (aCenterViews.getLength() != 1) + return; + + // do not record the state of bottom pane when in master edit modes + if (!IsMasterView({ mxConfigurationController->getResource(aCenterViews[0]), UNO_QUERY })) + { + if (bActivation) + { + maActiveMainViewContainer.insert(aCenterViews[0]->getResourceURL()); + } + else + { + maActiveMainViewContainer.erase(aCenterViews[0]->getResourceURL()); + } + } +} + +} // end of namespace sd::framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sd/source/ui/framework/module/NotesPaneModule.hxx b/sd/source/ui/framework/module/NotesPaneModule.hxx new file mode 100644 index 000000000000..69a74acbdf0c --- /dev/null +++ b/sd/source/ui/framework/module/NotesPaneModule.hxx @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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/. + */ +#pragma once + +#include <com/sun/star/drawing/framework/XConfigurationChangeListener.hpp> +#include <comphelper/compbase.hxx> +#include <rtl/ref.hxx> +#include <tools/link.hxx> +#include <set> + +namespace com::sun::star::drawing::framework +{ +class XConfigurationController; +class XView; +} +namespace com::sun::star::frame +{ +class XController; +} +namespace sd +{ +class DrawController; +class ViewShellBase; +} +namespace sd::tools +{ +class EventMultiplexerEvent; +} + +namespace sd::framework +{ +/** This module is responsible for handling visibility of NotesPane across modes +*/ +class NotesPaneModule : public comphelper::WeakComponentImplHelper< + css::drawing::framework::XConfigurationChangeListener> +{ +public: + /** Create a new module that controls the view tab bar above the view + in the specified pane. + @param rxController + This is the access point to the drawing framework. + */ + NotesPaneModule(const rtl::Reference<::sd::DrawController>& rxController); + virtual ~NotesPaneModule() override; + + void AddActiveMainView(const OUString& rsMainViewURL); + bool IsResourceActive(const OUString& rsMainViewURL); + void SaveResourceState(); + + virtual void disposing(std::unique_lock<std::mutex>&) override; + + // XConfigurationChangeListener + + virtual void SAL_CALL notifyConfigurationChange( + const css::drawing::framework::ConfigurationChangeEvent& rEvent) override; + + // XEventListener + + virtual void SAL_CALL disposing(const css::lang::EventObject& rEvent) override; + +private: + css::uno::Reference<css::drawing::framework::XConfigurationController> + mxConfigurationController; + + css::uno::Reference<css::drawing::framework::XResourceId> mxBottomImpressPaneId; + css::uno::Reference<css::drawing::framework::XResourceId> mxMainViewAnchorId; + + std::set<OUString> maActiveMainViewContainer; + OUString msCurrentMainViewURL; + ViewShellBase* mpViewShellBase; + bool mbListeningEventMultiplexer = false; + bool mbInMasterEditMode = false; + + void onMainViewSwitch(const OUString& rsViewURL, const bool bIsActivated); + void onResourceRequest( + bool bActivation, + const css::uno::Reference<css::drawing::framework::XConfiguration>& rxConfiguration); + bool IsMasterView(const css::uno::Reference<css::drawing::framework::XView>& xView); + + DECL_LINK(EventMultiplexerListener, ::sd::tools::EventMultiplexerEvent&, void); +}; + +} // end of namespace sd::framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/sd/source/ui/inc/framework/factories/BasicPaneFactory.hxx b/sd/source/ui/inc/framework/factories/BasicPaneFactory.hxx index fb1ac2cf8236..57395f196bf4 100644 --- a/sd/source/ui/inc/framework/factories/BasicPaneFactory.hxx +++ b/sd/source/ui/inc/framework/factories/BasicPaneFactory.hxx @@ -47,6 +47,7 @@ typedef comphelper::WeakComponentImplHelper < private:resource/pane/CenterPane private:resource/pane/FullScreenPane private:resource/pane/LeftImpressPane + private:resource/pane/BottomImpressPane private:resource/pane/LeftDrawPane There are two left panes because this is (seems to be) the only way to show different titles for the left pane in Draw and Impress. |