summaryrefslogtreecommitdiffstats
path: root/sd/source/ui/framework/factories
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sd/source/ui/framework/factories
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sd/source/ui/framework/factories')
-rw-r--r--sd/source/ui/framework/factories/BasicPaneFactory.cxx407
-rw-r--r--sd/source/ui/framework/factories/BasicToolBarFactory.cxx144
-rw-r--r--sd/source/ui/framework/factories/BasicViewFactory.cxx495
-rw-r--r--sd/source/ui/framework/factories/ChildWindowPane.cxx214
-rw-r--r--sd/source/ui/framework/factories/ChildWindowPane.hxx101
-rw-r--r--sd/source/ui/framework/factories/FrameWindowPane.cxx39
-rw-r--r--sd/source/ui/framework/factories/FrameWindowPane.hxx50
-rw-r--r--sd/source/ui/framework/factories/FullScreenPane.cxx235
-rw-r--r--sd/source/ui/framework/factories/FullScreenPane.hxx86
-rw-r--r--sd/source/ui/framework/factories/Pane.cxx165
-rw-r--r--sd/source/ui/framework/factories/PresentationFactory.cxx150
-rw-r--r--sd/source/ui/framework/factories/ViewShellWrapper.cxx239
12 files changed, 2325 insertions, 0 deletions
diff --git a/sd/source/ui/framework/factories/BasicPaneFactory.cxx b/sd/source/ui/framework/factories/BasicPaneFactory.cxx
new file mode 100644
index 0000000000..e112ac4c31
--- /dev/null
+++ b/sd/source/ui/framework/factories/BasicPaneFactory.cxx
@@ -0,0 +1,407 @@
+/* -*- 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 <memory>
+#include <sal/config.h>
+
+#include <framework/factories/BasicPaneFactory.hxx>
+
+#include "ChildWindowPane.hxx"
+#include "FrameWindowPane.hxx"
+#include "FullScreenPane.hxx"
+
+#include <comphelper/servicehelper.hxx>
+#include <framework/FrameworkHelper.hxx>
+#include <PaneShells.hxx>
+#include <ViewShellBase.hxx>
+#include <PaneChildWindows.hxx>
+#include <DrawController.hxx>
+#include <com/sun/star/drawing/framework/XControllerManager.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::drawing::framework;
+
+using ::sd::framework::FrameworkHelper;
+
+namespace {
+ enum PaneId {
+ CenterPaneId,
+ FullScreenPaneId,
+ LeftImpressPaneId,
+ LeftDrawPaneId
+ };
+
+ const sal_Int32 gnConfigurationUpdateStartEvent(0);
+ const sal_Int32 gnConfigurationUpdateEndEvent(1);
+}
+
+namespace sd::framework {
+
+/** Store URL, XPane reference and (local) PaneId for every pane factory
+ that is registered at the PaneController.
+*/
+class BasicPaneFactory::PaneDescriptor
+{
+public:
+ OUString msPaneURL;
+ Reference<XResource> mxPane;
+ PaneId mePaneId;
+ /** The mbReleased flag is set when the pane has been released. Some
+ panes are just hidden and destroyed. When the pane is reused this
+ flag is reset.
+ */
+ bool mbIsReleased;
+
+ bool CompareURL(std::u16string_view rsPaneURL) const { return msPaneURL == rsPaneURL; }
+ bool ComparePane(const Reference<XResource>& rxPane) const { return mxPane == rxPane; }
+};
+
+class BasicPaneFactory::PaneContainer
+ : public ::std::vector<PaneDescriptor>
+{
+public:
+ PaneContainer() {}
+};
+
+//===== PaneFactory ===========================================================
+
+BasicPaneFactory::BasicPaneFactory (
+ const Reference<XComponentContext>& rxContext,
+ const rtl::Reference<::sd::DrawController>& rxController)
+ : mxComponentContext(rxContext),
+ mpViewShellBase(nullptr),
+ mpPaneContainer(new PaneContainer)
+{
+ try
+ {
+ // Tunnel through the controller to obtain access to the ViewShellBase.
+ mpViewShellBase = rxController->GetViewShellBase();
+
+ Reference<XConfigurationController> xCC (rxController->getConfigurationController());
+ mxConfigurationControllerWeak = xCC;
+
+ // Add pane factories for the two left panes (one for Impress and one for
+ // Draw) and the center pane.
+ if (rxController.is() && xCC.is())
+ {
+ PaneDescriptor aDescriptor;
+ aDescriptor.msPaneURL = FrameworkHelper::msCenterPaneURL;
+ aDescriptor.mePaneId = CenterPaneId;
+ aDescriptor.mbIsReleased = false;
+ mpPaneContainer->push_back(aDescriptor);
+ xCC->addResourceFactory(aDescriptor.msPaneURL, this);
+
+ aDescriptor.msPaneURL = FrameworkHelper::msFullScreenPaneURL;
+ aDescriptor.mePaneId = FullScreenPaneId;
+ mpPaneContainer->push_back(aDescriptor);
+ xCC->addResourceFactory(aDescriptor.msPaneURL, this);
+
+ aDescriptor.msPaneURL = FrameworkHelper::msLeftImpressPaneURL;
+ aDescriptor.mePaneId = LeftImpressPaneId;
+ mpPaneContainer->push_back(aDescriptor);
+ xCC->addResourceFactory(aDescriptor.msPaneURL, this);
+
+ aDescriptor.msPaneURL = FrameworkHelper::msLeftDrawPaneURL;
+ aDescriptor.mePaneId = LeftDrawPaneId;
+ mpPaneContainer->push_back(aDescriptor);
+ xCC->addResourceFactory(aDescriptor.msPaneURL, this);
+ }
+
+ // Register as configuration change listener.
+ if (xCC.is())
+ {
+ xCC->addConfigurationChangeListener(
+ this,
+ FrameworkHelper::msConfigurationUpdateStartEvent,
+ Any(gnConfigurationUpdateStartEvent));
+ xCC->addConfigurationChangeListener(
+ this,
+ FrameworkHelper::msConfigurationUpdateEndEvent,
+ Any(gnConfigurationUpdateEndEvent));
+ }
+ }
+ catch (RuntimeException&)
+ {
+ Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
+ if (xCC.is())
+ xCC->removeResourceFactoryForReference(this);
+ }
+}
+
+BasicPaneFactory::~BasicPaneFactory()
+{
+}
+
+void BasicPaneFactory::disposing(std::unique_lock<std::mutex>&)
+{
+ Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
+ if (xCC.is())
+ {
+ xCC->removeResourceFactoryForReference(this);
+ xCC->removeConfigurationChangeListener(this);
+ mxConfigurationControllerWeak.clear();
+ }
+
+ for (const auto& rDescriptor : *mpPaneContainer)
+ {
+ if (rDescriptor.mbIsReleased)
+ {
+ Reference<XComponent> xComponent (rDescriptor.mxPane, UNO_QUERY);
+ if (xComponent.is())
+ {
+ xComponent->removeEventListener(this);
+ xComponent->dispose();
+ }
+ }
+ }
+}
+
+//===== XPaneFactory ==========================================================
+
+Reference<XResource> SAL_CALL BasicPaneFactory::createResource (
+ const Reference<XResourceId>& rxPaneId)
+{
+ ThrowIfDisposed();
+
+ Reference<XResource> xPane;
+
+ // Based on the ResourceURL of the given ResourceId look up the
+ // corresponding factory descriptor.
+ PaneContainer::iterator iDescriptor (
+ ::std::find_if (
+ mpPaneContainer->begin(),
+ mpPaneContainer->end(),
+ [&] (PaneDescriptor const& rPane) {
+ return rPane.CompareURL(rxPaneId->getResourceURL());
+ } ));
+
+ if (iDescriptor == mpPaneContainer->end())
+ {
+ // The requested pane can not be created by any of the factories
+ // managed by the called BasicPaneFactory object.
+ throw lang::IllegalArgumentException("BasicPaneFactory::createPane() called for unknown resource id",
+ nullptr,
+ 0);
+ }
+
+ if (iDescriptor->mxPane.is())
+ {
+ // The pane has already been created and is still active (has
+ // not yet been released). This should not happen.
+ xPane = iDescriptor->mxPane;
+ }
+ else
+ {
+ // Create a new pane.
+ switch (iDescriptor->mePaneId)
+ {
+ case CenterPaneId:
+ xPane = CreateFrameWindowPane(rxPaneId);
+ break;
+
+ case FullScreenPaneId:
+ xPane = CreateFullScreenPane(mxComponentContext, rxPaneId);
+ break;
+
+ case LeftImpressPaneId:
+ case LeftDrawPaneId:
+ xPane = CreateChildWindowPane(
+ rxPaneId,
+ *iDescriptor);
+ break;
+ }
+ iDescriptor->mxPane = xPane;
+
+ // Listen for the pane being disposed.
+ Reference<lang::XComponent> xComponent (xPane, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->addEventListener(this);
+ }
+ iDescriptor->mbIsReleased = false;
+
+
+ return xPane;
+}
+
+void SAL_CALL BasicPaneFactory::releaseResource (
+ const Reference<XResource>& rxPane)
+{
+ ThrowIfDisposed();
+
+ // Based on the given XPane reference look up the corresponding factory
+ // descriptor.
+ PaneContainer::iterator iDescriptor (
+ ::std::find_if(
+ mpPaneContainer->begin(),
+ mpPaneContainer->end(),
+ [&] (PaneDescriptor const& rPane) { return rPane.ComparePane(rxPane); } ));
+
+ if (iDescriptor == mpPaneContainer->end())
+ {
+ // The given XPane reference is either empty or the pane was not
+ // created by any of the factories managed by the called
+ // BasicPaneFactory object.
+ throw lang::IllegalArgumentException("BasicPaneFactory::releasePane() called for pane that was not created by same factory.",
+ nullptr,
+ 0);
+ }
+
+ // The given pane was created by one of the factories. Child
+ // windows are just hidden and will be reused when requested later.
+ // Other windows are disposed and their reference is reset so that
+ // on the next createPane() call for the same pane type the pane is
+ // created anew.
+ ChildWindowPane* pChildWindowPane = dynamic_cast<ChildWindowPane*>(rxPane.get());
+ if (pChildWindowPane != nullptr)
+ {
+ iDescriptor->mbIsReleased = true;
+ pChildWindowPane->Hide();
+ }
+ else
+ {
+ iDescriptor->mxPane = nullptr;
+ Reference<XComponent> xComponent (rxPane, UNO_QUERY);
+ if (xComponent.is())
+ {
+ // We are disposing the pane and do not have to be informed of
+ // that.
+ xComponent->removeEventListener(this);
+ xComponent->dispose();
+ }
+ }
+
+}
+
+//===== XConfigurationChangeListener ==========================================
+
+void SAL_CALL BasicPaneFactory::notifyConfigurationChange (
+ const ConfigurationChangeEvent& /* rEvent */ )
+{
+ // FIXME: nothing to do
+}
+
+//===== lang::XEventListener ==================================================
+
+void SAL_CALL BasicPaneFactory::disposing (
+ const lang::EventObject& rEventObject)
+{
+ if (mxConfigurationControllerWeak.get() == rEventObject.Source)
+ {
+ mxConfigurationControllerWeak.clear();
+ }
+ else
+ {
+ // Has one of the panes been disposed? If so, then release the
+ // reference to that pane, but not the pane descriptor.
+ Reference<XResource> xPane (rEventObject.Source, UNO_QUERY);
+ PaneContainer::iterator iDescriptor (
+ ::std::find_if (
+ mpPaneContainer->begin(),
+ mpPaneContainer->end(),
+ [&] (PaneDescriptor const& rPane) { return rPane.ComparePane(xPane); } ));
+ if (iDescriptor != mpPaneContainer->end())
+ {
+ iDescriptor->mxPane = nullptr;
+ }
+ }
+}
+
+Reference<XResource> BasicPaneFactory::CreateFrameWindowPane (
+ const Reference<XResourceId>& rxPaneId)
+{
+ Reference<XResource> xPane;
+
+ if (mpViewShellBase != nullptr)
+ {
+ xPane = new FrameWindowPane(rxPaneId, mpViewShellBase->GetViewWindow());
+ }
+
+ return xPane;
+}
+
+Reference<XResource> BasicPaneFactory::CreateFullScreenPane (
+ const Reference<XComponentContext>& rxComponentContext,
+ const Reference<XResourceId>& rxPaneId)
+{
+ Reference<XResource> xPane (
+ new FullScreenPane(
+ rxComponentContext,
+ rxPaneId,
+ mpViewShellBase->GetViewWindow()));
+
+ return xPane;
+}
+
+Reference<XResource> BasicPaneFactory::CreateChildWindowPane (
+ const Reference<XResourceId>& rxPaneId,
+ const PaneDescriptor& rDescriptor)
+{
+ Reference<XResource> xPane;
+
+ if (mpViewShellBase != nullptr)
+ {
+ // Create the corresponding shell and determine the id of the child window.
+ sal_uInt16 nChildWindowId = 0;
+ ::std::unique_ptr<SfxShell> pShell;
+ switch (rDescriptor.mePaneId)
+ {
+ case LeftImpressPaneId:
+ pShell.reset(new LeftImpressPaneShell());
+ nChildWindowId = ::sd::LeftPaneImpressChildWindow::GetChildWindowId();
+ break;
+
+ case LeftDrawPaneId:
+ pShell.reset(new LeftDrawPaneShell());
+ nChildWindowId = ::sd::LeftPaneDrawChildWindow::GetChildWindowId();
+ break;
+
+ default:
+ break;
+ }
+
+ // With shell and child window id create the ChildWindowPane
+ // wrapper.
+ if (pShell != nullptr)
+ {
+ xPane = new ChildWindowPane(
+ rxPaneId,
+ nChildWindowId,
+ *mpViewShellBase,
+ std::move(pShell));
+ }
+ }
+
+ return xPane;
+}
+
+void BasicPaneFactory::ThrowIfDisposed() const
+{
+ if (m_bDisposed)
+ {
+ throw lang::DisposedException ("BasicPaneFactory object has already been disposed",
+ const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
+ }
+}
+
+} // end of namespace sd::framework
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/framework/factories/BasicToolBarFactory.cxx b/sd/source/ui/framework/factories/BasicToolBarFactory.cxx
new file mode 100644
index 0000000000..0c6ac16d4a
--- /dev/null
+++ b/sd/source/ui/framework/factories/BasicToolBarFactory.cxx
@@ -0,0 +1,144 @@
+/* -*- 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 <framework/factories/BasicToolBarFactory.hxx>
+
+#include <ViewTabBar.hxx>
+#include <framework/FrameworkHelper.hxx>
+#include <DrawController.hxx>
+#include <unotools/mediadescriptor.hxx>
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/drawing/framework/XControllerManager.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::drawing::framework;
+
+namespace sd::framework {
+
+//===== BasicToolBarFactory ===================================================
+
+BasicToolBarFactory::BasicToolBarFactory(const rtl::Reference<::sd::DrawController>& rxController)
+{
+ try
+ {
+ mxController = rxController;
+
+ utl::MediaDescriptor aDescriptor (mxController->getModel()->getArgs());
+ if ( ! aDescriptor.getUnpackedValueOrDefault(
+ utl::MediaDescriptor::PROP_PREVIEW,
+ false))
+ {
+ // Register the factory for its supported tool bars.
+ mxConfigurationController = mxController->getConfigurationController();
+ if (mxConfigurationController.is())
+ {
+ mxConfigurationController->addResourceFactory(
+ FrameworkHelper::msViewTabBarURL, this);
+ }
+
+ Reference<lang::XComponent> xComponent (mxConfigurationController, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->addEventListener(static_cast<lang::XEventListener*>(this));
+ }
+ else
+ {
+ // The view shell is in preview mode and thus does not need
+ // the view tab bar.
+ mxConfigurationController = nullptr;
+ }
+ }
+ catch (RuntimeException&)
+ {
+ Shutdown();
+ throw;
+ }
+}
+
+
+BasicToolBarFactory::~BasicToolBarFactory()
+{
+}
+
+void BasicToolBarFactory::disposing(std::unique_lock<std::mutex>&)
+{
+ Shutdown();
+}
+
+void BasicToolBarFactory::Shutdown()
+{
+ Reference<lang::XComponent> xComponent (mxConfigurationController, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->removeEventListener(static_cast<lang::XEventListener*>(this));
+ if (mxConfigurationController.is())
+ {
+ mxConfigurationController->removeResourceFactoryForReference(this);
+ mxConfigurationController = nullptr;
+ }
+}
+
+//----- lang::XEventListener --------------------------------------------------
+
+void SAL_CALL BasicToolBarFactory::disposing (
+ const lang::EventObject& rEventObject)
+{
+ if (rEventObject.Source == mxConfigurationController)
+ mxConfigurationController = nullptr;
+}
+
+//===== XPaneFactory ==========================================================
+
+Reference<XResource> SAL_CALL BasicToolBarFactory::createResource (
+ const Reference<XResourceId>& rxToolBarId)
+{
+ ThrowIfDisposed();
+
+ if (rxToolBarId->getResourceURL() != FrameworkHelper::msViewTabBarURL)
+ throw lang::IllegalArgumentException();
+
+ Reference<XResource> xToolBar = new ViewTabBar(rxToolBarId, mxController);
+ return xToolBar;
+}
+
+void SAL_CALL BasicToolBarFactory::releaseResource (
+ const Reference<XResource>& rxToolBar)
+{
+ ThrowIfDisposed();
+
+ Reference<XComponent> xComponent (rxToolBar, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+}
+
+void BasicToolBarFactory::ThrowIfDisposed() const
+{
+ if (m_bDisposed)
+ {
+ throw lang::DisposedException ("BasicToolBarFactory object has already been disposed",
+ const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
+ }
+}
+
+} // end of namespace sd::framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/framework/factories/BasicViewFactory.cxx b/sd/source/ui/framework/factories/BasicViewFactory.cxx
new file mode 100644
index 0000000000..3ea7e37f1f
--- /dev/null
+++ b/sd/source/ui/framework/factories/BasicViewFactory.cxx
@@ -0,0 +1,495 @@
+/* -*- 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 <framework/factories/BasicViewFactory.hxx>
+
+#include <framework/ViewShellWrapper.hxx>
+#include <framework/FrameworkHelper.hxx>
+#include <com/sun/star/drawing/framework/XControllerManager.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <framework/Pane.hxx>
+#include <DrawController.hxx>
+#include <ViewShellBase.hxx>
+#include <ViewShellManager.hxx>
+#include <DrawDocShell.hxx>
+#include <DrawViewShell.hxx>
+#include <GraphicViewShell.hxx>
+#include <OutlineViewShell.hxx>
+#include <PresentationViewShell.hxx>
+#include <SlideSorterViewShell.hxx>
+#include <FrameView.hxx>
+#include <Window.hxx>
+
+#include <comphelper/servicehelper.hxx>
+#include <sfx2/viewfrm.hxx>
+#include <vcl/wrkwin.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::drawing::framework;
+
+using ::sd::framework::FrameworkHelper;
+
+namespace sd::framework {
+
+//===== ViewDescriptor ========================================================
+
+class BasicViewFactory::ViewDescriptor
+{
+public:
+ Reference<XResource> mxView;
+ std::shared_ptr<sd::ViewShell> mpViewShell;
+ Reference<XResourceId> mxViewId;
+ static bool CompareView (const std::shared_ptr<ViewDescriptor>& rpDescriptor,
+ const Reference<XResource>& rxView)
+ { return rpDescriptor->mxView.get() == rxView.get(); }
+};
+
+//===== BasicViewFactory::ViewShellContainer ==================================
+
+class BasicViewFactory::ViewShellContainer
+ : public ::std::vector<std::shared_ptr<ViewDescriptor> >
+{
+public:
+ ViewShellContainer() {};
+};
+
+class BasicViewFactory::ViewCache
+ : public ::std::vector<std::shared_ptr<ViewDescriptor> >
+{
+public:
+ ViewCache() {};
+};
+
+//===== ViewFactory ===========================================================
+
+BasicViewFactory::BasicViewFactory (const rtl::Reference<::sd::DrawController>& rxController)
+ : mpViewShellContainer(new ViewShellContainer()),
+ mpBase(nullptr),
+ mpFrameView(nullptr),
+ mpWindow(VclPtr<WorkWindow>::Create(nullptr,WB_STDWORK)),
+ mpViewCache(std::make_shared<ViewCache>()),
+ mxLocalPane(new Pane(Reference<XResourceId>(), mpWindow.get()))
+{
+ try
+ {
+ // Tunnel through the controller to obtain a ViewShellBase.
+ mpBase = rxController->GetViewShellBase();
+
+ // Register the factory for its supported views.
+ mxConfigurationController = rxController->getConfigurationController();
+ if ( ! mxConfigurationController.is())
+ throw RuntimeException();
+ mxConfigurationController->addResourceFactory(FrameworkHelper::msImpressViewURL, this);
+ mxConfigurationController->addResourceFactory(FrameworkHelper::msDrawViewURL, this);
+ mxConfigurationController->addResourceFactory(FrameworkHelper::msOutlineViewURL, this);
+ mxConfigurationController->addResourceFactory(FrameworkHelper::msNotesViewURL, this);
+ mxConfigurationController->addResourceFactory(FrameworkHelper::msHandoutViewURL, this);
+ mxConfigurationController->addResourceFactory(FrameworkHelper::msPresentationViewURL, this);
+ mxConfigurationController->addResourceFactory(FrameworkHelper::msSlideSorterURL, this);
+ }
+ catch (RuntimeException&)
+ {
+ mpBase = nullptr;
+ if (mxConfigurationController.is())
+ mxConfigurationController->removeResourceFactoryForReference(this);
+ throw;
+ }
+}
+
+BasicViewFactory::~BasicViewFactory()
+{
+}
+
+void BasicViewFactory::disposing(std::unique_lock<std::mutex>&)
+{
+ // Disconnect from the frame view.
+ if (mpFrameView != nullptr)
+ {
+ mpFrameView->Disconnect();
+ mpFrameView = nullptr;
+ }
+
+ // Release the view cache.
+ for (const auto& rxView : *mpViewCache)
+ {
+ ReleaseView(rxView, true);
+ }
+
+ // Release the view shell container. At this point no one other than us
+ // should hold references to the view shells (at the moment this is a
+ // trivial requirement, because no one other than us holds a shared
+ // pointer).
+ // ViewShellContainer::const_iterator iView;
+ for (const auto& rxView : *mpViewShellContainer)
+ {
+ OSL_ASSERT(rxView->mpViewShell.use_count() == 1);
+ }
+ mpViewShellContainer.reset();
+}
+
+Reference<XResource> SAL_CALL BasicViewFactory::createResource (
+ const Reference<XResourceId>& rxViewId)
+{
+ Reference<XResource> xView;
+ const bool bIsCenterPane (
+ rxViewId->isBoundToURL(FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT));
+
+ // Get the pane for the anchor URL.
+ Reference<XPane> xPane;
+ if (mxConfigurationController.is())
+ xPane.set(mxConfigurationController->getResource(rxViewId->getAnchor()), UNO_QUERY);
+
+ // For main views use the frame view of the last main view.
+ ::sd::FrameView* pFrameView = nullptr;
+ if (xPane.is() && bIsCenterPane)
+ {
+ pFrameView = mpFrameView;
+ }
+
+ // Get Window pointer for XWindow of the pane.
+ vcl::Window* pWindow = nullptr;
+ if (xPane.is())
+ pWindow = VCLUnoHelper::GetWindow(xPane->getWindow());
+
+ // Get the view frame.
+ SfxViewFrame* pFrame = nullptr;
+ if (mpBase != nullptr)
+ pFrame = &mpBase->GetViewFrame();
+
+ if (pFrame != nullptr && mpBase!=nullptr && pWindow!=nullptr)
+ {
+ // Try to get the view from the cache.
+ std::shared_ptr<ViewDescriptor> pDescriptor (GetViewFromCache(rxViewId, xPane));
+
+ // When the requested view is not in the cache then create a new view.
+ if (pDescriptor == nullptr)
+ {
+ pDescriptor = CreateView(rxViewId, *pFrame, *pWindow, xPane, pFrameView, bIsCenterPane);
+ }
+
+ xView = pDescriptor->mxView;
+
+ mpViewShellContainer->push_back(pDescriptor);
+
+ if (bIsCenterPane)
+ ActivateCenterView(pDescriptor);
+ else
+ pWindow->Resize();
+ }
+
+ return xView;
+}
+
+void SAL_CALL BasicViewFactory::releaseResource (const Reference<XResource>& rxView)
+{
+ if ( ! rxView.is())
+ throw lang::IllegalArgumentException();
+
+ if (!rxView.is() || !mpBase)
+ return;
+
+ ViewShellContainer::iterator iViewShell (
+ ::std::find_if(
+ mpViewShellContainer->begin(),
+ mpViewShellContainer->end(),
+ [&] (std::shared_ptr<ViewDescriptor> const& pVD) {
+ return ViewDescriptor::CompareView(pVD, rxView);
+ } ));
+ if (iViewShell == mpViewShellContainer->end())
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ std::shared_ptr<ViewShell> pViewShell ((*iViewShell)->mpViewShell);
+
+ if ((*iViewShell)->mxViewId->isBoundToURL(
+ FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
+ {
+ // Obtain a pointer to and connect to the frame view of the
+ // view. The next view, that is created, will be
+ // initialized with this frame view.
+ if (mpFrameView == nullptr)
+ {
+ mpFrameView = pViewShell->GetFrameView();
+ if (mpFrameView)
+ mpFrameView->Connect();
+ }
+
+ // With the view in the center pane the sub controller is
+ // released, too.
+ mpBase->GetDrawController()->SetSubController(
+ Reference<drawing::XDrawSubController>());
+
+ SfxViewShell* pSfxViewShell = pViewShell->GetViewShell();
+ if (pSfxViewShell != nullptr)
+ pSfxViewShell->DisconnectAllClients();
+ }
+
+ ReleaseView(*iViewShell, false);
+
+ mpViewShellContainer->erase(iViewShell);
+}
+
+std::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::CreateView (
+ const Reference<XResourceId>& rxViewId,
+ SfxViewFrame& rFrame,
+ vcl::Window& rWindow,
+ const Reference<XPane>& rxPane,
+ FrameView* pFrameView,
+ const bool bIsCenterPane)
+{
+ auto pDescriptor = std::make_shared<ViewDescriptor>();
+
+ pDescriptor->mpViewShell = CreateViewShell(
+ rxViewId,
+ rFrame,
+ rWindow,
+ pFrameView);
+ pDescriptor->mxViewId = rxViewId;
+
+ if (pDescriptor->mpViewShell != nullptr)
+ {
+ pDescriptor->mpViewShell->Init(bIsCenterPane);
+ mpBase->GetViewShellManager()->ActivateViewShell(pDescriptor->mpViewShell.get());
+
+ Reference<awt::XWindow> xWindow(rxPane->getWindow());
+ rtl::Reference<ViewShellWrapper> wrapper(new ViewShellWrapper(
+ pDescriptor->mpViewShell,
+ rxViewId,
+ xWindow));
+
+ // register ViewShellWrapper on pane window
+ if (xWindow.is())
+ {
+ xWindow->addWindowListener(wrapper);
+ if (pDescriptor->mpViewShell != nullptr)
+ {
+ pDescriptor->mpViewShell->Resize();
+ }
+ }
+
+ pDescriptor->mxView = wrapper.get();
+ }
+
+ return pDescriptor;
+}
+
+std::shared_ptr<ViewShell> BasicViewFactory::CreateViewShell (
+ const Reference<XResourceId>& rxViewId,
+ SfxViewFrame& rFrame,
+ vcl::Window& rWindow,
+ FrameView* pFrameView)
+{
+ std::shared_ptr<ViewShell> pViewShell;
+ const OUString& rsViewURL (rxViewId->getResourceURL());
+ if (rsViewURL == FrameworkHelper::msImpressViewURL)
+ {
+ pViewShell =
+ std::make_shared<DrawViewShell>(
+ *mpBase,
+ &rWindow,
+ PageKind::Standard,
+ pFrameView);
+ pViewShell->GetContentWindow()->set_id("impress_win");
+ }
+ else if (rsViewURL == FrameworkHelper::msDrawViewURL)
+ {
+ pViewShell = std::shared_ptr<GraphicViewShell>(
+ new GraphicViewShell(*mpBase, &rWindow, pFrameView),
+ o3tl::default_delete<GraphicViewShell>());
+ pViewShell->GetContentWindow()->set_id("draw_win");
+ }
+ else if (rsViewURL == FrameworkHelper::msOutlineViewURL)
+ {
+ pViewShell =
+ std::make_shared<OutlineViewShell>(
+ &rFrame,
+ *mpBase,
+ &rWindow,
+ pFrameView);
+ pViewShell->GetContentWindow()->set_id("outline_win");
+ }
+ else if (rsViewURL == FrameworkHelper::msNotesViewURL)
+ {
+ pViewShell =
+ std::make_shared<DrawViewShell>(
+ *mpBase,
+ &rWindow,
+ PageKind::Notes,
+ pFrameView);
+ pViewShell->GetContentWindow()->set_id("notes_win");
+ }
+ else if (rsViewURL == FrameworkHelper::msHandoutViewURL)
+ {
+ pViewShell =
+ std::make_shared<DrawViewShell>(
+ *mpBase,
+ &rWindow,
+ PageKind::Handout,
+ pFrameView);
+ pViewShell->GetContentWindow()->set_id("handout_win");
+ }
+ else if (rsViewURL == FrameworkHelper::msPresentationViewURL)
+ {
+ pViewShell =
+ std::make_shared<PresentationViewShell>(
+ *mpBase,
+ &rWindow,
+ pFrameView);
+ pViewShell->GetContentWindow()->set_id("presentation_win");
+ }
+ else if (rsViewURL == FrameworkHelper::msSlideSorterURL)
+ {
+ pViewShell = ::sd::slidesorter::SlideSorterViewShell::Create (
+ &rFrame,
+ *mpBase,
+ &rWindow,
+ pFrameView);
+ pViewShell->GetContentWindow()->set_id("slidesorter");
+ }
+
+ return pViewShell;
+}
+
+void BasicViewFactory::ReleaseView (
+ const std::shared_ptr<ViewDescriptor>& rpDescriptor,
+ bool bDoNotCache)
+{
+ bool bIsCacheable (!bDoNotCache && IsCacheable(rpDescriptor));
+
+ if (bIsCacheable)
+ {
+ Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY);
+ if (xResource.is())
+ {
+ if (mxLocalPane.is())
+ if (xResource->relocateToAnchor(mxLocalPane))
+ mpViewCache->push_back(rpDescriptor);
+ else
+ bIsCacheable = false;
+ else
+ bIsCacheable = false;
+ }
+ else
+ {
+ bIsCacheable = false;
+ }
+ }
+
+ if ( ! bIsCacheable)
+ {
+ // Shut down the current view shell.
+ rpDescriptor->mpViewShell->Shutdown ();
+ mpBase->GetDocShell()->Disconnect(rpDescriptor->mpViewShell.get());
+ mpBase->GetViewShellManager()->DeactivateViewShell(rpDescriptor->mpViewShell.get());
+
+ Reference<XComponent> xComponent (rpDescriptor->mxView, UNO_QUERY);
+ if (xComponent.is())
+ xComponent->dispose();
+ }
+}
+
+bool BasicViewFactory::IsCacheable (const std::shared_ptr<ViewDescriptor>& rpDescriptor)
+{
+ bool bIsCacheable (false);
+
+ Reference<XRelocatableResource> xResource (rpDescriptor->mxView, UNO_QUERY);
+ if (xResource.is())
+ {
+ static ::std::vector<Reference<XResourceId> > s_aCacheableResources = [&]()
+ {
+ ::std::vector<Reference<XResourceId> > tmp;
+ FrameworkHelper::Instance(*mpBase);
+
+ // The slide sorter and the task panel are cacheable and relocatable.
+ tmp.push_back(FrameworkHelper::CreateResourceId(
+ FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftDrawPaneURL));
+ tmp.push_back(FrameworkHelper::CreateResourceId(
+ FrameworkHelper::msSlideSorterURL, FrameworkHelper::msLeftImpressPaneURL));
+ return tmp;
+ }();
+
+ bIsCacheable = std::any_of(s_aCacheableResources.begin(), s_aCacheableResources.end(),
+ [&rpDescriptor](const Reference<XResourceId>& rxId) { return rxId->compareTo(rpDescriptor->mxViewId) == 0; });
+ }
+
+ return bIsCacheable;
+}
+
+std::shared_ptr<BasicViewFactory::ViewDescriptor> BasicViewFactory::GetViewFromCache (
+ const Reference<XResourceId>& rxViewId,
+ const Reference<XPane>& rxPane)
+{
+ std::shared_ptr<ViewDescriptor> pDescriptor;
+
+ // Search for the requested view in the cache.
+ ViewCache::iterator iEntry = std::find_if(mpViewCache->begin(), mpViewCache->end(),
+ [&rxViewId](const ViewCache::value_type& rxEntry) { return rxEntry->mxViewId->compareTo(rxViewId) == 0; });
+ if (iEntry != mpViewCache->end())
+ {
+ pDescriptor = *iEntry;
+ mpViewCache->erase(iEntry);
+ }
+
+ // When the view has been found then relocate it to the given pane and
+ // remove it from the cache.
+ if (pDescriptor != nullptr)
+ {
+ bool bRelocationSuccessful (false);
+ Reference<XRelocatableResource> xResource (pDescriptor->mxView, UNO_QUERY);
+ if (xResource.is() && rxPane.is())
+ {
+ if (xResource->relocateToAnchor(rxPane))
+ bRelocationSuccessful = true;
+ }
+
+ if ( ! bRelocationSuccessful)
+ {
+ ReleaseView(pDescriptor, true);
+ pDescriptor.reset();
+ }
+ }
+
+ return pDescriptor;
+}
+
+void BasicViewFactory::ActivateCenterView (
+ const std::shared_ptr<ViewDescriptor>& rpDescriptor)
+{
+ mpBase->GetDocShell()->Connect(rpDescriptor->mpViewShell.get());
+
+ // During the creation of the new sub-shell, resize requests were not
+ // forwarded to it because it was not yet registered. Therefore, we
+ // have to request a resize now.
+ rpDescriptor->mpViewShell->UIFeatureChanged();
+ if (mpBase->GetDocShell()->IsInPlaceActive())
+ mpBase->GetViewFrame().Resize(true);
+
+ mpBase->GetDrawController()->SetSubController(
+ rpDescriptor->mpViewShell->CreateSubController());
+}
+
+} // end of namespace sd::framework
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/framework/factories/ChildWindowPane.cxx b/sd/source/ui/framework/factories/ChildWindowPane.cxx
new file mode 100644
index 0000000000..1eaf0f0aee
--- /dev/null
+++ b/sd/source/ui/framework/factories/ChildWindowPane.cxx
@@ -0,0 +1,214 @@
+/* -*- 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 <memory>
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <utility>
+
+#include "ChildWindowPane.hxx"
+
+#include <titledockwin.hxx>
+#include <ViewShellBase.hxx>
+#include <ViewShellManager.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <sfx2/viewfrm.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+
+namespace sd::framework {
+
+ChildWindowPane::ChildWindowPane (
+ const Reference<XResourceId>& rxPaneId,
+ sal_uInt16 nChildWindowId,
+ ViewShellBase& rViewShellBase,
+ ::std::unique_ptr<SfxShell> && pShell)
+ : ChildWindowPaneInterfaceBase(rxPaneId,nullptr),
+ mnChildWindowId(nChildWindowId),
+ mrViewShellBase(rViewShellBase),
+ mpShell(std::move(pShell)),
+ mbHasBeenActivated(false)
+{
+ mrViewShellBase.GetViewShellManager()->ActivateShell(mpShell.get());
+
+ SfxViewFrame& rViewFrame = mrViewShellBase.GetViewFrame();
+
+ if (mrViewShellBase.IsActive())
+ {
+ if (rViewFrame.KnowsChildWindow(mnChildWindowId))
+ {
+ if (rViewFrame.HasChildWindow(mnChildWindowId))
+ {
+ // The ViewShellBase has already been activated. Make
+ // the child window visible as soon as possible.
+ rViewFrame.SetChildWindow(mnChildWindowId, true);
+ }
+ else
+ {
+ // The window is created asynchronously. Rely on the
+ // ConfigurationUpdater to try another update, and with
+ // that another request for this window, in a short
+ // time.
+ }
+ }
+ else
+ {
+ SAL_WARN("sd", "ChildWindowPane:not known");
+ }
+ }
+ else
+ {
+ // The ViewShellBase has not yet been activated. Hide the
+ // window and wait a little before it is made visible. See
+ // comments in the GetWindow() method for an explanation.
+ rViewFrame.SetChildWindow(mnChildWindowId, false);
+ }
+}
+
+ChildWindowPane::~ChildWindowPane()
+{
+}
+
+void ChildWindowPane::Hide()
+{
+ SfxViewFrame& rViewFrame = mrViewShellBase.GetViewFrame();
+ if (rViewFrame.KnowsChildWindow(mnChildWindowId))
+ if (rViewFrame.HasChildWindow(mnChildWindowId))
+ rViewFrame.SetChildWindow(mnChildWindowId, false);
+
+ // Release the window because when the child window is shown again it
+ // may use a different window.
+ mxWindow = nullptr;
+}
+
+void SAL_CALL ChildWindowPane::disposing()
+{
+ ::osl::MutexGuard aGuard (m_aMutex);
+
+ mrViewShellBase.GetViewShellManager()->DeactivateShell(mpShell.get());
+ mpShell.reset();
+
+ if (mxWindow.is())
+ {
+ mxWindow->removeEventListener(this);
+ }
+
+ Pane::disposing();
+}
+
+vcl::Window* ChildWindowPane::GetWindow()
+{
+ do
+ {
+ if (mxWindow.is())
+ // Window already exists => nothing to do.
+ break;
+
+ // When the window is not yet present then obtain it only when the
+ // shell has already been activated. The activation is not
+ // necessary for the code to work properly but is used to optimize
+ // the layouting and displaying of the window. When it is made
+ // visible too early then some layouting seems to be made twice or at
+ // an inconvenient time and the overall process of initializing the
+ // Impress takes longer.
+ if (!mbHasBeenActivated && mpShell != nullptr && !mpShell->IsActive())
+ break;
+
+ mbHasBeenActivated = true;
+ SfxViewFrame& rViewFrame = mrViewShellBase.GetViewFrame();
+ // The view frame has to know the child window. This can be the
+ // case, when for example the document is in read-only mode: the
+ // task pane is then not available.
+ if ( ! rViewFrame.KnowsChildWindow(mnChildWindowId))
+ break;
+
+ rViewFrame.SetChildWindow(mnChildWindowId, true);
+ SfxChildWindow* pChildWindow = rViewFrame.GetChildWindow(mnChildWindowId);
+ if (pChildWindow == nullptr)
+ if (rViewFrame.HasChildWindow(mnChildWindowId))
+ {
+ // The child window is not yet visible. Ask the view frame
+ // to show it and try again to get access to the child
+ // window.
+ rViewFrame.ShowChildWindow(mnChildWindowId);
+ pChildWindow = rViewFrame.GetChildWindow(mnChildWindowId);
+ }
+
+ // When the child window is still not visible then we have to try later.
+ if (pChildWindow == nullptr)
+ break;
+
+ // From the child window get the docking window and from that the
+ // content window that is the container for the actual content.
+ TitledDockingWindow* pDockingWindow = dynamic_cast<TitledDockingWindow*>(
+ pChildWindow->GetWindow());
+ if (pDockingWindow == nullptr)
+ break;
+
+ // At last, we have access to the window and its UNO wrapper.
+ mpWindow = &pDockingWindow->GetContentWindow();
+ mxWindow = VCLUnoHelper::GetInterface(mpWindow);
+
+ // Register as window listener to be informed when the child window
+ // is hidden.
+ if (mxWindow.is())
+ mxWindow->addEventListener(this);
+ }
+ while (false);
+
+ return mpWindow;
+}
+
+Reference<awt::XWindow> SAL_CALL ChildWindowPane::getWindow()
+{
+ if (mpWindow == nullptr || ! mxWindow.is())
+ GetWindow();
+ return Pane::getWindow();
+}
+
+IMPLEMENT_FORWARD_XINTERFACE2(
+ ChildWindowPane,
+ ChildWindowPaneInterfaceBase,
+ Pane);
+IMPLEMENT_FORWARD_XTYPEPROVIDER2(
+ ChildWindowPane,
+ ChildWindowPaneInterfaceBase,
+ Pane);
+
+//----- XEventListener --------------------------------------------------------
+
+void SAL_CALL ChildWindowPane::disposing (const lang::EventObject& rEvent)
+{
+ ThrowIfDisposed();
+
+ if (rEvent.Source == mxWindow)
+ {
+ // The window is gone but the pane remains alive. The next call to
+ // GetWindow() may create the window anew.
+ mxWindow = nullptr;
+ mpWindow = nullptr;
+ }
+}
+
+} // end of namespace sd::framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/framework/factories/ChildWindowPane.hxx b/sd/source/ui/framework/factories/ChildWindowPane.hxx
new file mode 100644
index 0000000000..0821777578
--- /dev/null
+++ b/sd/source/ui/framework/factories/ChildWindowPane.hxx
@@ -0,0 +1,101 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <framework/Pane.hxx>
+
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <memory>
+
+class SfxShell;
+
+namespace sd { class ViewShellBase; }
+namespace com::sun::star::awt { class XWindow; }
+namespace com::sun::star::drawing::framework { class XResourceId; }
+
+namespace sd::framework {
+
+typedef ::cppu::ImplInheritanceHelper <
+ ::sd::framework::Pane,
+ css::lang::XEventListener
+ > ChildWindowPaneInterfaceBase;
+
+/** The ChildWindowPane listens to the child window and disposes itself when
+ the child window becomes inaccessible. This happens for instance when a
+ document is made read-only and the task pane is turned off.
+*/
+class ChildWindowPane
+ : public ChildWindowPaneInterfaceBase
+{
+public:
+ ChildWindowPane (
+ const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
+ sal_uInt16 nChildWindowId,
+ ViewShellBase& rViewShellBase,
+ ::std::unique_ptr<SfxShell> && pShell);
+ virtual ~ChildWindowPane() override;
+
+ /** Hide the pane. To make the pane visible again, call GetWindow().
+ */
+ void Hide();
+
+ virtual void SAL_CALL disposing() override;
+
+ /** This returns the content window when the child window is already
+ visible. Otherwise <NULL/> is returned. In that case a later call
+ may return the requested window (making a child window visible is an
+ asynchronous process.)
+ Note that GetWindow() may return different Window pointers when
+ Hide() is called in between.
+ */
+ virtual vcl::Window* GetWindow() override;
+
+ /** The local getWindow() first calls GetWindow() to provide a valid
+ window pointer before forwarding the call to the base class.
+ */
+ virtual css::uno::Reference<css::awt::XWindow>
+ SAL_CALL getWindow() override;
+
+ DECLARE_XINTERFACE()
+ DECLARE_XTYPEPROVIDER()
+
+ // XEventListener
+
+ virtual void SAL_CALL disposing(
+ const css::lang::EventObject& rEvent) override;
+
+private:
+ sal_uInt16 mnChildWindowId;
+ ViewShellBase& mrViewShellBase;
+ ::std::unique_ptr<SfxShell> mpShell;
+
+ /** This flag is set when the pane shell has been activated at least
+ once. It is used to optimize the start-up performance (by not
+ showing the window too early) and by not delaying its creation at
+ later times.
+ */
+ bool mbHasBeenActivated;
+};
+
+} // end of namespace sd::framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/framework/factories/FrameWindowPane.cxx b/sd/source/ui/framework/factories/FrameWindowPane.cxx
new file mode 100644
index 0000000000..1f4b387d88
--- /dev/null
+++ b/sd/source/ui/framework/factories/FrameWindowPane.cxx
@@ -0,0 +1,39 @@
+/* -*- 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 "FrameWindowPane.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+
+namespace sd::framework
+{
+FrameWindowPane::FrameWindowPane(const Reference<XResourceId>& rxPaneId, vcl::Window* pWindow)
+ : Pane(rxPaneId, pWindow)
+{
+}
+
+FrameWindowPane::~FrameWindowPane() noexcept {}
+
+sal_Bool SAL_CALL FrameWindowPane::isAnchorOnly() { return false; }
+
+} // end of namespace sd::framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/framework/factories/FrameWindowPane.hxx b/sd/source/ui/framework/factories/FrameWindowPane.hxx
new file mode 100644
index 0000000000..67da37fdff
--- /dev/null
+++ b/sd/source/ui/framework/factories/FrameWindowPane.hxx
@@ -0,0 +1,50 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <framework/Pane.hxx>
+
+namespace com::sun::star::drawing::framework
+{
+class XResourceId;
+}
+
+namespace sd::framework
+{
+/** This subclass is not necessary anymore. We can remove it if that
+ remains so.
+*/
+class FrameWindowPane : public Pane
+{
+public:
+ FrameWindowPane(const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
+ vcl::Window* pWindow);
+ virtual ~FrameWindowPane() noexcept override;
+
+ /** A frame window typically can (and should) exists on its own without
+ children, if only to visualize that something (a view) is missing.
+ Therefore this method always returns <FALSE/>.
+ */
+ virtual sal_Bool SAL_CALL isAnchorOnly() override;
+};
+
+} // end of namespace sd::framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/framework/factories/FullScreenPane.cxx b/sd/source/ui/framework/factories/FullScreenPane.cxx
new file mode 100644
index 0000000000..39da06144c
--- /dev/null
+++ b/sd/source/ui/framework/factories/FullScreenPane.cxx
@@ -0,0 +1,235 @@
+/* -*- 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 "FullScreenPane.hxx"
+#include <vcl/vclevent.hxx>
+#include <vcl/wrkwin.hxx>
+#include <o3tl/string_view.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/util/URL.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+
+namespace sd::framework {
+
+FullScreenPane::FullScreenPane (
+ const Reference<XComponentContext>& rxComponentContext,
+ const Reference<XResourceId>& rxPaneId,
+ const vcl::Window* pViewShellWindow)
+ : FrameWindowPane(rxPaneId,nullptr),
+ mxComponentContext(rxComponentContext)
+{
+ sal_Int32 nScreenNumber = 1;
+ bool bFullScreen = true;
+ ExtractArguments(rxPaneId, nScreenNumber, bFullScreen);
+
+ vcl::Window* pParent = nullptr;
+ WinBits nStyle = bFullScreen ? 0 : (WB_BORDER | WB_MOVEABLE | WB_SIZEABLE);
+
+ mpWorkWindow.reset(VclPtr<WorkWindow>::Create(
+ pParent,
+ nStyle)); // For debugging (non-fullscreen) use WB_BORDER | WB_MOVEABLE | WB_SIZEABLE));
+
+ if ( ! rxPaneId.is())
+ throw lang::IllegalArgumentException();
+
+ if (!mpWorkWindow)
+ return;
+
+ // Create a new top-level window that is displayed full screen.
+ if (bFullScreen)
+ mpWorkWindow->ShowFullScreenMode(bFullScreen, nScreenNumber);
+
+ // For debugging (non-fullscreen) use mpWorkWindow->SetScreenNumber(nScreenNumber);
+ mpWorkWindow->SetMenuBarMode(MenuBarMode::Hide);
+ mpWorkWindow->SetBorderStyle(WindowBorderStyle::REMOVEBORDER);
+ mpWorkWindow->SetBackground(Wallpaper());
+ // Don't show the window right now in order to allow the setting of an
+ // accessibility object: accessibility objects are typically
+ // requested by AT-tools when the window is shown. Chaining it
+ // afterwards may or may not work.
+
+ // Add resize listener at the work window.
+ Link<VclWindowEvent&,void> aWindowEventHandler (LINK(this, FullScreenPane, WindowEventHandler));
+ mpWorkWindow->AddEventListener(aWindowEventHandler);
+
+ // Set title and icon of the new window to those of the current window
+ // of the view shell.
+ if (pViewShellWindow != nullptr)
+ {
+ const SystemWindow* pSystemWindow = pViewShellWindow->GetSystemWindow();
+ mpWorkWindow->SetText(pSystemWindow->GetText());
+ mpWorkWindow->SetIcon(pSystemWindow->GetIcon());
+ }
+
+ // For some reason the VCL canvas can not paint into a WorkWindow.
+ // Therefore a child window is created that covers the WorkWindow
+ // completely.
+ mpWindow = VclPtr<vcl::Window>::Create(mpWorkWindow.get());
+ mpWindow->SetPosSizePixel(Point(0,0), mpWorkWindow->GetSizePixel());
+ mpWindow->SetBackground(Wallpaper());
+ mxWindow = VCLUnoHelper::GetInterface(mpWindow);
+
+ // Create the canvas.
+ mxCanvas = CreateCanvas();
+
+ mpWindow->GrabFocus();
+}
+
+FullScreenPane::~FullScreenPane() noexcept
+{
+}
+
+void SAL_CALL FullScreenPane::disposing()
+{
+ mpWindow.disposeAndClear();
+
+ if (mpWorkWindow)
+ {
+ Link<VclWindowEvent&,void> aWindowEventHandler (LINK(this, FullScreenPane, WindowEventHandler));
+ mpWorkWindow->RemoveEventListener(aWindowEventHandler);
+ mpWorkWindow.disposeAndClear();
+ }
+
+ FrameWindowPane::disposing();
+}
+
+//----- XPane -----------------------------------------------------------------
+
+sal_Bool SAL_CALL FullScreenPane::isVisible()
+{
+ ThrowIfDisposed();
+
+ if (mpWindow != nullptr)
+ return mpWindow->IsReallyVisible();
+ else
+ return false;
+}
+
+void SAL_CALL FullScreenPane::setVisible (const sal_Bool bIsVisible)
+{
+ ThrowIfDisposed();
+
+ if (mpWindow != nullptr)
+ mpWindow->Show(bIsVisible);
+ if (mpWorkWindow != nullptr)
+ mpWorkWindow->Show(bIsVisible);
+}
+
+Reference<css::accessibility::XAccessible> SAL_CALL FullScreenPane::getAccessible()
+{
+ ThrowIfDisposed();
+
+ if (mpWorkWindow != nullptr)
+ return mpWorkWindow->GetAccessible(false);
+ else
+ return nullptr;
+}
+
+void SAL_CALL FullScreenPane::setAccessible (
+ const Reference<css::accessibility::XAccessible>& rxAccessible)
+{
+ ThrowIfDisposed();
+
+ if (mpWindow == nullptr)
+ return;
+
+ Reference<lang::XInitialization> xInitializable (rxAccessible, UNO_QUERY);
+ if (xInitializable.is())
+ {
+ vcl::Window* pParentWindow = mpWindow->GetParent();
+ Reference<css::accessibility::XAccessible> xAccessibleParent;
+ if (pParentWindow != nullptr)
+ xAccessibleParent = pParentWindow->GetAccessible();
+ Sequence<Any> aArguments{ Any(xAccessibleParent) };
+ xInitializable->initialize(aArguments);
+ }
+ GetWindow()->SetAccessible(rxAccessible);
+}
+
+IMPL_LINK(FullScreenPane, WindowEventHandler, VclWindowEvent&, rEvent, void)
+{
+ switch (rEvent.GetId())
+ {
+ case VclEventId::WindowResize:
+ GetWindow()->SetPosPixel(Point(0,0));
+ GetWindow()->SetSizePixel(Size(
+ mpWorkWindow->GetSizePixel().Width(),
+ mpWorkWindow->GetSizePixel().Height()));
+ break;
+
+ case VclEventId::ObjectDying:
+ mpWorkWindow.disposeAndClear();
+ break;
+
+ default: break;
+ }
+}
+
+Reference<rendering::XCanvas> FullScreenPane::CreateCanvas()
+{
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(mxWindow);
+ if (!pWindow)
+ throw RuntimeException();
+
+ Sequence<Any> aArg{ // common: first any is VCL pointer to window (for VCL canvas)
+ Any(reinterpret_cast<sal_Int64>(pWindow.get())),
+ Any(css::awt::Rectangle()),
+ Any(false),
+ Any(mxWindow)
+ };
+
+ Reference<lang::XMultiServiceFactory> xFactory (
+ mxComponentContext->getServiceManager(), UNO_QUERY_THROW);
+ return Reference<rendering::XCanvas>(
+ xFactory->createInstanceWithArguments("com.sun.star.rendering.SpriteCanvas.VCL",
+ aArg),
+ UNO_QUERY);
+}
+
+void FullScreenPane::ExtractArguments (
+ const Reference<XResourceId>& rxPaneId,
+ sal_Int32& rnScreenNumberReturnValue,
+ bool& rbFullScreen)
+{
+ // Extract arguments from the resource URL.
+ const util::URL aURL = rxPaneId->getFullResourceURL();
+ for (sal_Int32 nIndex{ 0 }; nIndex >= 0; )
+ {
+ const std::u16string_view aToken = o3tl::getToken(aURL.Arguments, 0, '&', nIndex);
+ std::u16string_view sValue;
+ if (o3tl::starts_with(aToken, u"ScreenNumber=", &sValue))
+ {
+ rnScreenNumberReturnValue = o3tl::toInt32(sValue);
+ }
+ if (o3tl::starts_with(aToken, u"FullScreen=", &sValue))
+ {
+ rbFullScreen = o3tl::equalsAscii(sValue, "true");
+ }
+ }
+}
+
+} // end of namespace sd::framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/framework/factories/FullScreenPane.hxx b/sd/source/ui/framework/factories/FullScreenPane.hxx
new file mode 100644
index 0000000000..138503d02f
--- /dev/null
+++ b/sd/source/ui/framework/factories/FullScreenPane.hxx
@@ -0,0 +1,86 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include "FrameWindowPane.hxx"
+#include <tools/link.hxx>
+#include <vcl/wrkwin.hxx>
+
+class VclWindowEvent;
+
+namespace vcl { class Window; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace sd::framework {
+
+/** The full screen pane creates a pane that covers the complete application
+ window, i.e. that hides menu bar, tool bars, status bars.
+*/
+class FullScreenPane
+ : public FrameWindowPane
+{
+public:
+ /** Create a new full screen pane.
+ @param rxComponentContext
+ Used for creating a new canvas.
+ @param rxPaneId
+ The resource id of the new pane.
+ @param pViewShellWindow
+ The top-level parent of this window is used to obtain title and
+ icon for the new top-level window.
+ */
+ FullScreenPane (
+ const css::uno::Reference<css::uno::XComponentContext>& rxComponentContext,
+ const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
+ const vcl::Window* pViewShellWindow);
+ virtual ~FullScreenPane() noexcept override;
+
+ virtual void SAL_CALL disposing() override;
+
+ //----- XPane -------------------------------------------------------------
+
+ virtual sal_Bool SAL_CALL isVisible() override;
+
+ virtual void SAL_CALL setVisible (sal_Bool bIsVisible) override;
+
+ virtual css::uno::Reference<css::accessibility::XAccessible> SAL_CALL getAccessible() override;
+
+ virtual void SAL_CALL setAccessible (
+ const css::uno::Reference<css::accessibility::XAccessible>& rxAccessible) override;
+
+ DECL_LINK(WindowEventHandler, VclWindowEvent&, void);
+
+protected:
+ virtual css::uno::Reference<css::rendering::XCanvas>
+ CreateCanvas() override;
+
+private:
+ css::uno::Reference<css::uno::XComponentContext> mxComponentContext;
+ VclPtr<WorkWindow> mpWorkWindow;
+
+ static void ExtractArguments (
+ const css::uno::Reference<css::drawing::framework::XResourceId>& rxPaneId,
+ sal_Int32& rnScreenNumberReturnValue,
+ bool& rbFullScreen);
+};
+
+} // end of namespace sd::framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/framework/factories/Pane.cxx b/sd/source/ui/framework/factories/Pane.cxx
new file mode 100644
index 0000000000..c128a5351f
--- /dev/null
+++ b/sd/source/ui/framework/factories/Pane.cxx
@@ -0,0 +1,165 @@
+/* -*- 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 <framework/Pane.hxx>
+
+#include <osl/mutex.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/window.hxx>
+#include <cppcanvas/vclfactory.hxx>
+#include <com/sun/star/rendering/XSpriteCanvas.hpp>
+#include <comphelper/servicehelper.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+
+namespace sd::framework {
+
+Pane::Pane (
+ const Reference<XResourceId>& rxPaneId,
+ vcl::Window* pWindow)
+ noexcept
+ : PaneInterfaceBase(m_aMutex),
+ mxPaneId(rxPaneId),
+ mpWindow(pWindow),
+ mxWindow(VCLUnoHelper::GetInterface(pWindow))
+{
+}
+
+Pane::~Pane()
+{
+}
+
+void Pane::disposing()
+{
+ mxWindow = nullptr;
+ mpWindow = nullptr;
+}
+
+vcl::Window* Pane::GetWindow()
+{
+ if (mxWindow.is())
+ return mpWindow;
+ else
+ return nullptr;
+}
+
+//----- XPane -----------------------------------------------------------------
+
+Reference<awt::XWindow> SAL_CALL Pane::getWindow()
+{
+ ThrowIfDisposed();
+
+ return mxWindow;
+}
+
+Reference<rendering::XCanvas> SAL_CALL Pane::getCanvas()
+{
+ ::osl::MutexGuard aGuard (m_aMutex);
+ ThrowIfDisposed();
+
+ if ( ! mxCanvas.is())
+ mxCanvas = CreateCanvas();
+
+ return mxCanvas;
+}
+
+//----- XPane2 ----------------------------------------------------------------
+
+sal_Bool SAL_CALL Pane::isVisible()
+{
+ ThrowIfDisposed();
+
+ const vcl::Window* pWindow = GetWindow();
+ if (pWindow != nullptr)
+ return pWindow->IsVisible();
+ else
+ return false;
+}
+
+void SAL_CALL Pane::setVisible (sal_Bool bIsVisible)
+{
+ ThrowIfDisposed();
+
+ vcl::Window* pWindow = GetWindow();
+ if (pWindow != nullptr)
+ pWindow->Show(bIsVisible);
+}
+
+Reference<css::accessibility::XAccessible> SAL_CALL Pane::getAccessible()
+{
+ ThrowIfDisposed();
+ vcl::Window* pWindow = GetWindow();
+ if (pWindow != nullptr)
+ return pWindow->GetAccessible(false);
+ else
+ return nullptr;
+}
+
+void SAL_CALL Pane::setAccessible (
+ const Reference<css::accessibility::XAccessible>& rxAccessible)
+{
+ ThrowIfDisposed();
+ vcl::Window* pWindow = GetWindow();
+ if (pWindow != nullptr)
+ pWindow->SetAccessible(rxAccessible);
+}
+
+//----- XResource -------------------------------------------------------------
+
+Reference<XResourceId> SAL_CALL Pane::getResourceId()
+{
+ ThrowIfDisposed();
+
+ return mxPaneId;
+}
+
+sal_Bool SAL_CALL Pane::isAnchorOnly()
+{
+ return true;
+}
+
+Reference<rendering::XCanvas> Pane::CreateCanvas()
+{
+ Reference<rendering::XCanvas> xCanvas;
+
+ if (mpWindow != nullptr)
+ {
+ ::cppcanvas::SpriteCanvasSharedPtr pCanvas (
+ cppcanvas::VCLFactory::createSpriteCanvas(*mpWindow));
+ if (pCanvas)
+ xCanvas.set(pCanvas->getUNOSpriteCanvas());
+ }
+
+ return xCanvas;
+}
+
+void Pane::ThrowIfDisposed() const
+{
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ throw lang::DisposedException ("Pane object has already been disposed",
+ const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
+ }
+}
+
+} // end of namespace sd::framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/framework/factories/PresentationFactory.cxx b/sd/source/ui/framework/factories/PresentationFactory.cxx
new file mode 100644
index 0000000000..d859ac3fbe
--- /dev/null
+++ b/sd/source/ui/framework/factories/PresentationFactory.cxx
@@ -0,0 +1,150 @@
+/* -*- 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 <framework/PresentationFactory.hxx>
+
+#include <DrawController.hxx>
+#include <com/sun/star/drawing/framework/XControllerManager.hpp>
+#include <com/sun/star/drawing/framework/XView.hpp>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/compbase.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <slideshow.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::drawing::framework;
+
+
+namespace sd::framework {
+
+namespace {
+
+typedef comphelper::WeakComponentImplHelper<XView> PresentationViewInterfaceBase;
+
+/** The PresentationView is not an actual view, it is a marker whose
+ existence in a configuration indicates that a slideshow is running
+ (in another application window).
+*/
+class PresentationView
+ : public PresentationViewInterfaceBase
+{
+public:
+ explicit PresentationView (const Reference<XResourceId>& rxViewId)
+ : mxResourceId(rxViewId) {};
+
+ // XView
+
+ virtual Reference<XResourceId> SAL_CALL getResourceId() override
+ { return mxResourceId; };
+
+ virtual sal_Bool SAL_CALL isAnchorOnly() override
+ { return false; }
+
+private:
+ Reference<XResourceId> mxResourceId;
+};
+
+} // end of anonymous namespace.
+
+//===== PresentationFactory ===================================================
+
+constexpr OUString gsPresentationViewURL = u"private:resource/view/Presentation"_ustr;
+
+PresentationFactory::PresentationFactory (
+ const rtl::Reference<::sd::DrawController>& rxController)
+ : mxController(rxController)
+{
+}
+
+PresentationFactory::~PresentationFactory()
+{
+}
+
+//----- XViewFactory ----------------------------------------------------------
+
+Reference<XResource> SAL_CALL PresentationFactory::createResource (
+ const Reference<XResourceId>& rxViewId)
+{
+ ThrowIfDisposed();
+
+ if (rxViewId.is())
+ if ( ! rxViewId->hasAnchor() && rxViewId->getResourceURL() == gsPresentationViewURL)
+ return new PresentationView(rxViewId);
+
+ return Reference<XResource>();
+}
+
+void SAL_CALL PresentationFactory::releaseResource (
+ const Reference<XResource>&)
+{
+ ThrowIfDisposed();
+
+ if (mxController)
+ {
+ ViewShellBase* pBase = mxController->GetViewShellBase();
+ if (pBase != nullptr)
+ SlideShow::Stop( *pBase );
+ }
+}
+
+//===== XConfigurationChangeListener ==========================================
+
+void SAL_CALL PresentationFactory::notifyConfigurationChange (
+ const ConfigurationChangeEvent&)
+{}
+
+//===== lang::XEventListener ==================================================
+
+void SAL_CALL PresentationFactory::disposing (
+ const lang::EventObject&)
+{}
+
+void PresentationFactory::ThrowIfDisposed() const
+{
+ if (m_bDisposed)
+ {
+ throw lang::DisposedException ("PresentationFactory object has already been disposed",
+ const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
+ }
+}
+
+void PresentationFactory::install(const rtl::Reference<::sd::DrawController>& rxController)
+{
+ try
+ {
+ Reference<XConfigurationController> xCC (rxController->getConfigurationController());
+ if (xCC.is())
+ xCC->addResourceFactory(
+ gsPresentationViewURL,
+ new PresentationFactory(rxController));
+ }
+ catch (RuntimeException&)
+ {
+ DBG_UNHANDLED_EXCEPTION("sd");
+ }
+}
+
+} // end of namespace sd::framework
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/framework/factories/ViewShellWrapper.cxx b/sd/source/ui/framework/factories/ViewShellWrapper.cxx
new file mode 100644
index 0000000000..294b7a550f
--- /dev/null
+++ b/sd/source/ui/framework/factories/ViewShellWrapper.cxx
@@ -0,0 +1,239 @@
+/* -*- 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 <framework/ViewShellWrapper.hxx>
+#include <sdpage.hxx>
+#include <ViewShell.hxx>
+
+#include <SlideSorter.hxx>
+#include <SlideSorterViewShell.hxx>
+#include <controller/SlsPageSelector.hxx>
+#include <controller/SlideSorterController.hxx>
+#include <model/SlsPageEnumerationProvider.hxx>
+#include <model/SlsPageDescriptor.hxx>
+
+#include <com/sun/star/drawing/framework/XPane.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <sal/log.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing::framework;
+
+using ::com::sun::star::awt::XWindow;
+
+namespace sd::framework {
+
+ViewShellWrapper::ViewShellWrapper (
+ const std::shared_ptr<ViewShell>& pViewShell,
+ const Reference<XResourceId>& rxViewId,
+ const Reference<awt::XWindow>& rxWindow)
+ : mpViewShell(pViewShell),
+ mpSlideSorterViewShell(
+ std::dynamic_pointer_cast< ::sd::slidesorter::SlideSorterViewShell >( pViewShell )),
+ mxViewId(rxViewId),
+ mxWindow(rxWindow)
+{
+}
+
+ViewShellWrapper::~ViewShellWrapper()
+{
+}
+
+void ViewShellWrapper::disposing(std::unique_lock<std::mutex>&)
+{
+ SAL_INFO("sd.ui", "disposing ViewShellWrapper " << this);
+ Reference<awt::XWindow> xWindow (mxWindow);
+ if (xWindow.is())
+ {
+ SAL_INFO(
+ "sd.ui",
+ "removing ViewShellWrapper " << this << " from window listener at "
+ << mxWindow.get());
+ xWindow->removeWindowListener(this);
+ }
+
+ mpSlideSorterViewShell.reset();
+ mpViewShell.reset();
+}
+
+uno::Any SAL_CALL ViewShellWrapper::queryInterface( const uno::Type & rType )
+{
+ if( mpSlideSorterViewShell &&
+ rType == cppu::UnoType<view::XSelectionSupplier>::get() )
+ {
+ uno::Reference<view::XSelectionSupplier> xSupplier( this );
+ return Any(xSupplier);
+ }
+ else
+ return ViewShellWrapperInterfaceBase::queryInterface( rType );
+}
+
+//----- XResource -------------------------------------------------------------
+
+Reference<XResourceId> SAL_CALL ViewShellWrapper::getResourceId()
+{
+ return mxViewId;
+}
+
+sal_Bool SAL_CALL ViewShellWrapper::isAnchorOnly()
+{
+ return false;
+}
+
+//----- XSelectionSupplier --------------------------------------------------
+
+sal_Bool SAL_CALL ViewShellWrapper::select( const css::uno::Any& aSelection )
+{
+ if (!mpSlideSorterViewShell)
+ return false;
+
+ ::sd::slidesorter::controller::SlideSorterController& rSlideSorterController
+ = mpSlideSorterViewShell->GetSlideSorter().GetController();
+ ::sd::slidesorter::controller::PageSelector& rSelector (rSlideSorterController.GetPageSelector());
+ rSelector.DeselectAllPages();
+ Sequence<Reference<drawing::XDrawPage> > xPages;
+ aSelection >>= xPages;
+ for (const auto& rPage : std::as_const(xPages))
+ {
+ Reference<beans::XPropertySet> xSet (rPage, UNO_QUERY);
+ if (xSet.is())
+ {
+ try
+ {
+ Any aNumber = xSet->getPropertyValue("Number");
+ sal_Int32 nPageNumber = 0;
+ aNumber >>= nPageNumber;
+ nPageNumber -=1; // Transform 1-based page numbers to 0-based ones.
+ rSelector.SelectPage(nPageNumber);
+ }
+ catch (const RuntimeException&)
+ {
+ }
+ }
+ }
+
+ return true;
+}
+
+uno::Any SAL_CALL ViewShellWrapper::getSelection()
+{
+ Any aResult;
+
+ if (!mpSlideSorterViewShell)
+ return aResult;
+
+ slidesorter::model::PageEnumeration aSelectedPages (
+ slidesorter::model::PageEnumerationProvider::CreateSelectedPagesEnumeration(
+ mpSlideSorterViewShell->GetSlideSorter().GetModel()));
+ int nSelectedPageCount (
+ mpSlideSorterViewShell->GetSlideSorter().GetController().GetPageSelector().GetSelectedPageCount());
+
+ Sequence<Reference<XInterface> > aPages(nSelectedPageCount);
+ auto aPagesRange = asNonConstRange(aPages);
+ int nIndex = 0;
+ while (aSelectedPages.HasMoreElements() && nIndex<nSelectedPageCount)
+ {
+ slidesorter::model::SharedPageDescriptor pDescriptor (aSelectedPages.GetNextElement());
+ aPagesRange[nIndex++] = pDescriptor->GetPage()->getUnoPage();
+ }
+ aResult <<= aPages;
+
+ return aResult;
+}
+
+void SAL_CALL ViewShellWrapper::addSelectionChangeListener( const uno::Reference< view::XSelectionChangeListener >& )
+{
+}
+
+void SAL_CALL ViewShellWrapper::removeSelectionChangeListener( const uno::Reference< view::XSelectionChangeListener >& )
+{
+}
+
+//----- XRelocatableResource --------------------------------------------------
+
+sal_Bool SAL_CALL ViewShellWrapper::relocateToAnchor (
+ const Reference<XResource>& xResource)
+{
+ bool bResult (false);
+
+ Reference<XPane> xPane (xResource, UNO_QUERY);
+ if (xPane.is())
+ {
+ // Detach from the window of the old pane.
+ Reference<awt::XWindow> xWindow (mxWindow);
+ if (xWindow.is())
+ xWindow->removeWindowListener(this);
+ mxWindow = nullptr;
+
+ if (mpViewShell != nullptr)
+ {
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xPane->getWindow());
+ if (pWindow && mpViewShell->RelocateToParentWindow(pWindow))
+ {
+ bResult = true;
+
+ // Attach to the window of the new pane.
+ xWindow = xPane->getWindow();
+ if (xWindow.is())
+ {
+ xWindow->addWindowListener(this);
+ mpViewShell->Resize();
+ }
+ }
+ }
+ }
+
+ return bResult;
+}
+
+//===== awt::XWindowListener ==================================================
+
+void SAL_CALL ViewShellWrapper::windowResized (const awt::WindowEvent&)
+{
+ ViewShell* pViewShell (mpViewShell.get());
+ if (pViewShell != nullptr)
+ pViewShell->Resize();
+}
+
+void SAL_CALL ViewShellWrapper::windowMoved (const awt::WindowEvent&) {}
+
+void SAL_CALL ViewShellWrapper::windowShown (const lang::EventObject&)
+{
+ ViewShell* pViewShell (mpViewShell.get());
+ if (pViewShell != nullptr)
+ pViewShell->Resize();
+}
+
+void SAL_CALL ViewShellWrapper::windowHidden (const lang::EventObject&) {}
+
+//===== XEventListener ========================================================
+
+void SAL_CALL ViewShellWrapper::disposing (const lang::EventObject& rEvent)
+{
+ if (rEvent.Source == mxWindow)
+ mxWindow = nullptr;
+}
+
+} // end of namespace sd::framework
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */