Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sd / source / ui / framework / factories / BasicPaneFactory.cxx
blobe112ac4c315aebbee00d95a3e464c2f044e65315
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <sal/config.h>
23 #include <framework/factories/BasicPaneFactory.hxx>
25 #include "ChildWindowPane.hxx"
26 #include "FrameWindowPane.hxx"
27 #include "FullScreenPane.hxx"
29 #include <comphelper/servicehelper.hxx>
30 #include <framework/FrameworkHelper.hxx>
31 #include <PaneShells.hxx>
32 #include <ViewShellBase.hxx>
33 #include <PaneChildWindows.hxx>
34 #include <DrawController.hxx>
35 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
37 using namespace ::com::sun::star;
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::lang;
40 using namespace ::com::sun::star::drawing::framework;
42 using ::sd::framework::FrameworkHelper;
44 namespace {
45 enum PaneId {
46 CenterPaneId,
47 FullScreenPaneId,
48 LeftImpressPaneId,
49 LeftDrawPaneId
52 const sal_Int32 gnConfigurationUpdateStartEvent(0);
53 const sal_Int32 gnConfigurationUpdateEndEvent(1);
56 namespace sd::framework {
58 /** Store URL, XPane reference and (local) PaneId for every pane factory
59 that is registered at the PaneController.
61 class BasicPaneFactory::PaneDescriptor
63 public:
64 OUString msPaneURL;
65 Reference<XResource> mxPane;
66 PaneId mePaneId;
67 /** The mbReleased flag is set when the pane has been released. Some
68 panes are just hidden and destroyed. When the pane is reused this
69 flag is reset.
71 bool mbIsReleased;
73 bool CompareURL(std::u16string_view rsPaneURL) const { return msPaneURL == rsPaneURL; }
74 bool ComparePane(const Reference<XResource>& rxPane) const { return mxPane == rxPane; }
77 class BasicPaneFactory::PaneContainer
78 : public ::std::vector<PaneDescriptor>
80 public:
81 PaneContainer() {}
84 //===== PaneFactory ===========================================================
86 BasicPaneFactory::BasicPaneFactory (
87 const Reference<XComponentContext>& rxContext,
88 const rtl::Reference<::sd::DrawController>& rxController)
89 : mxComponentContext(rxContext),
90 mpViewShellBase(nullptr),
91 mpPaneContainer(new PaneContainer)
93 try
95 // Tunnel through the controller to obtain access to the ViewShellBase.
96 mpViewShellBase = rxController->GetViewShellBase();
98 Reference<XConfigurationController> xCC (rxController->getConfigurationController());
99 mxConfigurationControllerWeak = xCC;
101 // Add pane factories for the two left panes (one for Impress and one for
102 // Draw) and the center pane.
103 if (rxController.is() && xCC.is())
105 PaneDescriptor aDescriptor;
106 aDescriptor.msPaneURL = FrameworkHelper::msCenterPaneURL;
107 aDescriptor.mePaneId = CenterPaneId;
108 aDescriptor.mbIsReleased = false;
109 mpPaneContainer->push_back(aDescriptor);
110 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
112 aDescriptor.msPaneURL = FrameworkHelper::msFullScreenPaneURL;
113 aDescriptor.mePaneId = FullScreenPaneId;
114 mpPaneContainer->push_back(aDescriptor);
115 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
117 aDescriptor.msPaneURL = FrameworkHelper::msLeftImpressPaneURL;
118 aDescriptor.mePaneId = LeftImpressPaneId;
119 mpPaneContainer->push_back(aDescriptor);
120 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
122 aDescriptor.msPaneURL = FrameworkHelper::msLeftDrawPaneURL;
123 aDescriptor.mePaneId = LeftDrawPaneId;
124 mpPaneContainer->push_back(aDescriptor);
125 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
128 // Register as configuration change listener.
129 if (xCC.is())
131 xCC->addConfigurationChangeListener(
132 this,
133 FrameworkHelper::msConfigurationUpdateStartEvent,
134 Any(gnConfigurationUpdateStartEvent));
135 xCC->addConfigurationChangeListener(
136 this,
137 FrameworkHelper::msConfigurationUpdateEndEvent,
138 Any(gnConfigurationUpdateEndEvent));
141 catch (RuntimeException&)
143 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
144 if (xCC.is())
145 xCC->removeResourceFactoryForReference(this);
149 BasicPaneFactory::~BasicPaneFactory()
153 void BasicPaneFactory::disposing(std::unique_lock<std::mutex>&)
155 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
156 if (xCC.is())
158 xCC->removeResourceFactoryForReference(this);
159 xCC->removeConfigurationChangeListener(this);
160 mxConfigurationControllerWeak.clear();
163 for (const auto& rDescriptor : *mpPaneContainer)
165 if (rDescriptor.mbIsReleased)
167 Reference<XComponent> xComponent (rDescriptor.mxPane, UNO_QUERY);
168 if (xComponent.is())
170 xComponent->removeEventListener(this);
171 xComponent->dispose();
177 //===== XPaneFactory ==========================================================
179 Reference<XResource> SAL_CALL BasicPaneFactory::createResource (
180 const Reference<XResourceId>& rxPaneId)
182 ThrowIfDisposed();
184 Reference<XResource> xPane;
186 // Based on the ResourceURL of the given ResourceId look up the
187 // corresponding factory descriptor.
188 PaneContainer::iterator iDescriptor (
189 ::std::find_if (
190 mpPaneContainer->begin(),
191 mpPaneContainer->end(),
192 [&] (PaneDescriptor const& rPane) {
193 return rPane.CompareURL(rxPaneId->getResourceURL());
194 } ));
196 if (iDescriptor == mpPaneContainer->end())
198 // The requested pane can not be created by any of the factories
199 // managed by the called BasicPaneFactory object.
200 throw lang::IllegalArgumentException("BasicPaneFactory::createPane() called for unknown resource id",
201 nullptr,
205 if (iDescriptor->mxPane.is())
207 // The pane has already been created and is still active (has
208 // not yet been released). This should not happen.
209 xPane = iDescriptor->mxPane;
211 else
213 // Create a new pane.
214 switch (iDescriptor->mePaneId)
216 case CenterPaneId:
217 xPane = CreateFrameWindowPane(rxPaneId);
218 break;
220 case FullScreenPaneId:
221 xPane = CreateFullScreenPane(mxComponentContext, rxPaneId);
222 break;
224 case LeftImpressPaneId:
225 case LeftDrawPaneId:
226 xPane = CreateChildWindowPane(
227 rxPaneId,
228 *iDescriptor);
229 break;
231 iDescriptor->mxPane = xPane;
233 // Listen for the pane being disposed.
234 Reference<lang::XComponent> xComponent (xPane, UNO_QUERY);
235 if (xComponent.is())
236 xComponent->addEventListener(this);
238 iDescriptor->mbIsReleased = false;
241 return xPane;
244 void SAL_CALL BasicPaneFactory::releaseResource (
245 const Reference<XResource>& rxPane)
247 ThrowIfDisposed();
249 // Based on the given XPane reference look up the corresponding factory
250 // descriptor.
251 PaneContainer::iterator iDescriptor (
252 ::std::find_if(
253 mpPaneContainer->begin(),
254 mpPaneContainer->end(),
255 [&] (PaneDescriptor const& rPane) { return rPane.ComparePane(rxPane); } ));
257 if (iDescriptor == mpPaneContainer->end())
259 // The given XPane reference is either empty or the pane was not
260 // created by any of the factories managed by the called
261 // BasicPaneFactory object.
262 throw lang::IllegalArgumentException("BasicPaneFactory::releasePane() called for pane that was not created by same factory.",
263 nullptr,
267 // The given pane was created by one of the factories. Child
268 // windows are just hidden and will be reused when requested later.
269 // Other windows are disposed and their reference is reset so that
270 // on the next createPane() call for the same pane type the pane is
271 // created anew.
272 ChildWindowPane* pChildWindowPane = dynamic_cast<ChildWindowPane*>(rxPane.get());
273 if (pChildWindowPane != nullptr)
275 iDescriptor->mbIsReleased = true;
276 pChildWindowPane->Hide();
278 else
280 iDescriptor->mxPane = nullptr;
281 Reference<XComponent> xComponent (rxPane, UNO_QUERY);
282 if (xComponent.is())
284 // We are disposing the pane and do not have to be informed of
285 // that.
286 xComponent->removeEventListener(this);
287 xComponent->dispose();
293 //===== XConfigurationChangeListener ==========================================
295 void SAL_CALL BasicPaneFactory::notifyConfigurationChange (
296 const ConfigurationChangeEvent& /* rEvent */ )
298 // FIXME: nothing to do
301 //===== lang::XEventListener ==================================================
303 void SAL_CALL BasicPaneFactory::disposing (
304 const lang::EventObject& rEventObject)
306 if (mxConfigurationControllerWeak.get() == rEventObject.Source)
308 mxConfigurationControllerWeak.clear();
310 else
312 // Has one of the panes been disposed? If so, then release the
313 // reference to that pane, but not the pane descriptor.
314 Reference<XResource> xPane (rEventObject.Source, UNO_QUERY);
315 PaneContainer::iterator iDescriptor (
316 ::std::find_if (
317 mpPaneContainer->begin(),
318 mpPaneContainer->end(),
319 [&] (PaneDescriptor const& rPane) { return rPane.ComparePane(xPane); } ));
320 if (iDescriptor != mpPaneContainer->end())
322 iDescriptor->mxPane = nullptr;
327 Reference<XResource> BasicPaneFactory::CreateFrameWindowPane (
328 const Reference<XResourceId>& rxPaneId)
330 Reference<XResource> xPane;
332 if (mpViewShellBase != nullptr)
334 xPane = new FrameWindowPane(rxPaneId, mpViewShellBase->GetViewWindow());
337 return xPane;
340 Reference<XResource> BasicPaneFactory::CreateFullScreenPane (
341 const Reference<XComponentContext>& rxComponentContext,
342 const Reference<XResourceId>& rxPaneId)
344 Reference<XResource> xPane (
345 new FullScreenPane(
346 rxComponentContext,
347 rxPaneId,
348 mpViewShellBase->GetViewWindow()));
350 return xPane;
353 Reference<XResource> BasicPaneFactory::CreateChildWindowPane (
354 const Reference<XResourceId>& rxPaneId,
355 const PaneDescriptor& rDescriptor)
357 Reference<XResource> xPane;
359 if (mpViewShellBase != nullptr)
361 // Create the corresponding shell and determine the id of the child window.
362 sal_uInt16 nChildWindowId = 0;
363 ::std::unique_ptr<SfxShell> pShell;
364 switch (rDescriptor.mePaneId)
366 case LeftImpressPaneId:
367 pShell.reset(new LeftImpressPaneShell());
368 nChildWindowId = ::sd::LeftPaneImpressChildWindow::GetChildWindowId();
369 break;
371 case LeftDrawPaneId:
372 pShell.reset(new LeftDrawPaneShell());
373 nChildWindowId = ::sd::LeftPaneDrawChildWindow::GetChildWindowId();
374 break;
376 default:
377 break;
380 // With shell and child window id create the ChildWindowPane
381 // wrapper.
382 if (pShell != nullptr)
384 xPane = new ChildWindowPane(
385 rxPaneId,
386 nChildWindowId,
387 *mpViewShellBase,
388 std::move(pShell));
392 return xPane;
395 void BasicPaneFactory::ThrowIfDisposed() const
397 if (m_bDisposed)
399 throw lang::DisposedException ("BasicPaneFactory object has already been disposed",
400 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
404 } // end of namespace sd::framework
407 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */