officecfg/registry/schema/org/openoffice/Office/Impress.xcs |   40 +
 sd/Library_sd.mk                                            |    1 
 sd/sdi/NotesPanelView.sdi                                   |   11 
 sd/source/ui/framework/module/ImpressModule.cxx             |    2 
 sd/source/ui/framework/module/ModuleController.cxx          |    2 
 sd/source/ui/framework/module/NotesPaneModule.cxx           |  268 ++++++++++++
 sd/source/ui/framework/module/NotesPaneModule.hxx           |   91 ++++
 sd/source/ui/inc/framework/factories/BasicPaneFactory.hxx   |    1 
 sd/source/ui/view/NotesPanelViewShell.cxx                   |    5 
 9 files changed, 405 insertions(+), 16 deletions(-)

New commits:
commit 8af78dc0de96daab6a23a21e152d5c91b93ee74c
Author:     Sarper Akdemir <sarper.akde...@allotropia.de>
AuthorDate: Wed May 8 17:36:01 2024 +0200
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Wed May 8 20:55:44 2024 +0200

    tdf#33603: do not block SID_SAVEDOC slots on NotesPanelViewShell
    
    Change-Id: Icc7320b0960f0d73027359b7525a37b44bdd7ee7

diff --git a/sd/sdi/NotesPanelView.sdi b/sd/sdi/NotesPanelView.sdi
index 90217efaa4e8..b54addb52b8c 100644
--- a/sd/sdi/NotesPanelView.sdi
+++ b/sd/sdi/NotesPanelView.sdi
@@ -195,17 +195,6 @@ interface NotesPanelView
         ExecMethod = FuPermanent ;
         StateMethod = GetMenuState ;
     ]
-    SID_SAVEDOC // ole : no, status : ?
-    [
-        ExecMethod = Execute ;
-        StateMethod = GetMenuState ;
-        GroupId = SfxGroupId::Document ;
-    ]
-    SID_SAVEASDOC // ole : no, status : ?
-    [
-        ExecMethod = Execute ;
-        GroupId = SfxGroupId::Document ;
-    ]
     SID_RULER // ole : no, status : ?
     [
         ExecMethod = FuSupport ;
diff --git a/sd/source/ui/view/NotesPanelViewShell.cxx 
b/sd/source/ui/view/NotesPanelViewShell.cxx
index 5b7bdcf6329f..7bc46a5464b6 100644
--- a/sd/source/ui/view/NotesPanelViewShell.cxx
+++ b/sd/source/ui/view/NotesPanelViewShell.cxx
@@ -1338,11 +1338,6 @@ void NotesPanelViewShell::Execute(SfxRequest& rReq)
 
     switch (rReq.GetSlot())
     {
-        case SID_SAVEDOC:
-        case SID_SAVEASDOC:
-            PrepareClose();
-            break;
-
         case SID_SEARCH_ITEM:
             // Forward this request to the common (old) code of the
             // document shell.
commit 537be0af79d95852eb66d7683908b683ce2b7f2f
Author:     Sarper Akdemir <sarper.akde...@allotropia.de>
AuthorDate: Wed May 8 14:14:58 2024 +0200
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Wed May 8 20:54:36 2024 +0200

    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

diff --git a/officecfg/registry/schema/org/openoffice/Office/Impress.xcs 
b/officecfg/registry/schema/org/openoffice/Office/Impress.xcs
index 876780d1bd09..54fec3bd1989 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Impress.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Impress.xcs
@@ -1308,6 +1308,46 @@
           </info>
         </set>
       </group>
+      <group oor:name="NotesPane">
+        <info>
+          <desc>Values related to the slide sorter.</desc>
+          <label>Notes Pane Options</label>
+        </info>
+        <group oor:name="Visible">
+          <info>
+            <desc>Options that control the visibility of the slide 
sorter.</desc>
+            <label>Notes Pane Visibility</label>
+          </info>
+          <prop oor:name="ImpressView" oor:type="xs:boolean">
+            <info>
+              <desc>Visibility of the Notes Pane in the Impress view.</desc>
+              <label>Notes Pane Visibility ImpressView</label>
+            </info>
+            <value>false</value>
+          </prop>
+               <prop oor:name="OutlineView" oor:type="xs:boolean">
+            <info>
+              <desc>Visibility of the Notes Pane in the Outline view.</desc>
+              <label>Notes Pane Visibility OutlineView</label>
+            </info>
+            <value>false</value>
+          </prop>
+          <prop oor:name="NotesView" oor:type="xs:boolean">
+            <info>
+              <desc>Visibility of the Notes Pane in the Notes view.</desc>
+              <label>Notes Pane Visibility NotesView</label>
+            </info>
+            <value>false</value>
+          </prop>
+          <prop oor:name="HandoutView" oor:type="xs:boolean">
+            <info>
+              <desc>Visibility of the Notes Pane in the Handout view.</desc>
+              <label>Notes Pane Visibility HandoutView</label>
+            </info>
+            <value>false</value>
+          </prop>
+        </group>
+      </group>
       <group oor:name="SlideSorterBar">
         <info>
           <desc>Values related to the slide sorter.</desc>
diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk
index b633ee26f7d6..0cb001c98e31 100644
--- a/sd/Library_sd.mk
+++ b/sd/Library_sd.mk
@@ -279,6 +279,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 f89212e4a0a8..39f718ac4b32 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"
@@ -43,6 +44,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.

Reply via email to