diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sd/source/ui/framework/factories | |
parent | Initial commit. (diff) | |
download | libreoffice-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.cxx | 407 | ||||
-rw-r--r-- | sd/source/ui/framework/factories/BasicToolBarFactory.cxx | 144 | ||||
-rw-r--r-- | sd/source/ui/framework/factories/BasicViewFactory.cxx | 495 | ||||
-rw-r--r-- | sd/source/ui/framework/factories/ChildWindowPane.cxx | 214 | ||||
-rw-r--r-- | sd/source/ui/framework/factories/ChildWindowPane.hxx | 101 | ||||
-rw-r--r-- | sd/source/ui/framework/factories/FrameWindowPane.cxx | 39 | ||||
-rw-r--r-- | sd/source/ui/framework/factories/FrameWindowPane.hxx | 50 | ||||
-rw-r--r-- | sd/source/ui/framework/factories/FullScreenPane.cxx | 235 | ||||
-rw-r--r-- | sd/source/ui/framework/factories/FullScreenPane.hxx | 86 | ||||
-rw-r--r-- | sd/source/ui/framework/factories/Pane.cxx | 165 | ||||
-rw-r--r-- | sd/source/ui/framework/factories/PresentationFactory.cxx | 150 | ||||
-rw-r--r-- | sd/source/ui/framework/factories/ViewShellWrapper.cxx | 239 |
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: */ |