LibreOffice Module sd (master) 1
BasicPaneFactory.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <memory>
21#include <sal/config.h>
22
24
25#include "ChildWindowPane.hxx"
26#include "FrameWindowPane.hxx"
27#include "FullScreenPane.hxx"
28
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>
36
37using namespace ::com::sun::star;
38using namespace ::com::sun::star::uno;
39using namespace ::com::sun::star::lang;
41
42using ::sd::framework::FrameworkHelper;
43
44namespace {
45 enum PaneId {
46 CenterPaneId,
47 FullScreenPaneId,
48 LeftImpressPaneId,
49 LeftDrawPaneId
50 };
51
52 const sal_Int32 gnConfigurationUpdateStartEvent(0);
53 const sal_Int32 gnConfigurationUpdateEndEvent(1);
54}
55
56namespace sd::framework {
57
62{
63public:
64 OUString msPaneURL;
65 Reference<XResource> mxPane;
66 PaneId mePaneId;
72
73 bool CompareURL(std::u16string_view rsPaneURL) const { return msPaneURL == rsPaneURL; }
74 bool ComparePane(const Reference<XResource>& rxPane) const { return mxPane == rxPane; }
75};
76
78 : public ::std::vector<PaneDescriptor>
79{
80public:
82};
83
84//===== PaneFactory ===========================================================
85
87 const Reference<XComponentContext>& rxContext,
88 const rtl::Reference<::sd::DrawController>& rxController)
89 : mxComponentContext(rxContext),
90 mpViewShellBase(nullptr),
91 mpPaneContainer(new PaneContainer)
92{
93 try
94 {
95 // Tunnel through the controller to obtain access to the ViewShellBase.
96 mpViewShellBase = rxController->GetViewShellBase();
97
98 Reference<XConfigurationController> xCC (rxController->getConfigurationController());
100
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())
104 {
105 PaneDescriptor aDescriptor;
107 aDescriptor.mePaneId = CenterPaneId;
108 aDescriptor.mbIsReleased = false;
109 mpPaneContainer->push_back(aDescriptor);
110 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
111
113 aDescriptor.mePaneId = FullScreenPaneId;
114 mpPaneContainer->push_back(aDescriptor);
115 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
116
118 aDescriptor.mePaneId = LeftImpressPaneId;
119 mpPaneContainer->push_back(aDescriptor);
120 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
121
123 aDescriptor.mePaneId = LeftDrawPaneId;
124 mpPaneContainer->push_back(aDescriptor);
125 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
126 }
127
128 // Register as configuration change listener.
129 if (xCC.is())
130 {
131 xCC->addConfigurationChangeListener(
132 this,
134 Any(gnConfigurationUpdateStartEvent));
135 xCC->addConfigurationChangeListener(
136 this,
138 Any(gnConfigurationUpdateEndEvent));
139 }
140 }
141 catch (RuntimeException&)
142 {
143 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
144 if (xCC.is())
145 xCC->removeResourceFactoryForReference(this);
146 }
147}
148
150{
151}
152
153void BasicPaneFactory::disposing(std::unique_lock<std::mutex>&)
154{
155 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
156 if (xCC.is())
157 {
158 xCC->removeResourceFactoryForReference(this);
159 xCC->removeConfigurationChangeListener(this);
161 }
162
163 for (const auto& rDescriptor : *mpPaneContainer)
164 {
165 if (rDescriptor.mbIsReleased)
166 {
167 Reference<XComponent> xComponent (rDescriptor.mxPane, UNO_QUERY);
168 if (xComponent.is())
169 {
170 xComponent->removeEventListener(this);
171 xComponent->dispose();
172 }
173 }
174 }
175}
176
177//===== XPaneFactory ==========================================================
178
179Reference<XResource> SAL_CALL BasicPaneFactory::createResource (
180 const Reference<XResourceId>& rxPaneId)
181{
183
184 Reference<XResource> xPane;
185
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 } ));
195
196 if (iDescriptor == mpPaneContainer->end())
197 {
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,
202 0);
203 }
204
205 if (iDescriptor->mxPane.is())
206 {
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;
210 }
211 else
212 {
213 // Create a new pane.
214 switch (iDescriptor->mePaneId)
215 {
216 case CenterPaneId:
217 xPane = CreateFrameWindowPane(rxPaneId);
218 break;
219
220 case FullScreenPaneId:
221 xPane = CreateFullScreenPane(mxComponentContext, rxPaneId);
222 break;
223
224 case LeftImpressPaneId:
225 case LeftDrawPaneId:
226 xPane = CreateChildWindowPane(
227 rxPaneId,
228 *iDescriptor);
229 break;
230 }
231 iDescriptor->mxPane = xPane;
232
233 // Listen for the pane being disposed.
234 Reference<lang::XComponent> xComponent (xPane, UNO_QUERY);
235 if (xComponent.is())
236 xComponent->addEventListener(this);
237 }
238 iDescriptor->mbIsReleased = false;
239
240
241 return xPane;
242}
243
245 const Reference<XResource>& rxPane)
246{
248
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); } ));
256
257 if (iDescriptor == mpPaneContainer->end())
258 {
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,
264 0);
265 }
266
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)
274 {
275 iDescriptor->mbIsReleased = true;
276 pChildWindowPane->Hide();
277 }
278 else
279 {
280 iDescriptor->mxPane = nullptr;
281 Reference<XComponent> xComponent (rxPane, UNO_QUERY);
282 if (xComponent.is())
283 {
284 // We are disposing the pane and do not have to be informed of
285 // that.
286 xComponent->removeEventListener(this);
287 xComponent->dispose();
288 }
289 }
290
291}
292
293//===== XConfigurationChangeListener ==========================================
294
296 const ConfigurationChangeEvent& /* rEvent */ )
297{
298 // FIXME: nothing to do
299}
300
301//===== lang::XEventListener ==================================================
302
303void SAL_CALL BasicPaneFactory::disposing (
304 const lang::EventObject& rEventObject)
305{
306 if (mxConfigurationControllerWeak.get() == rEventObject.Source)
307 {
309 }
310 else
311 {
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())
321 {
322 iDescriptor->mxPane = nullptr;
323 }
324 }
325}
326
328 const Reference<XResourceId>& rxPaneId)
329{
330 Reference<XResource> xPane;
331
332 if (mpViewShellBase != nullptr)
333 {
334 xPane = new FrameWindowPane(rxPaneId, mpViewShellBase->GetViewWindow());
335 }
336
337 return xPane;
338}
339
341 const Reference<XComponentContext>& rxComponentContext,
342 const Reference<XResourceId>& rxPaneId)
343{
344 Reference<XResource> xPane (
345 new FullScreenPane(
346 rxComponentContext,
347 rxPaneId,
349
350 return xPane;
351}
352
354 const Reference<XResourceId>& rxPaneId,
355 const PaneDescriptor& rDescriptor)
356{
357 Reference<XResource> xPane;
358
359 if (mpViewShellBase != nullptr)
360 {
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)
365 {
366 case LeftImpressPaneId:
367 pShell.reset(new LeftImpressPaneShell());
368 nChildWindowId = ::sd::LeftPaneImpressChildWindow::GetChildWindowId();
369 break;
370
371 case LeftDrawPaneId:
372 pShell.reset(new LeftDrawPaneShell());
373 nChildWindowId = ::sd::LeftPaneDrawChildWindow::GetChildWindowId();
374 break;
375
376 default:
377 break;
378 }
379
380 // With shell and child window id create the ChildWindowPane
381 // wrapper.
382 if (pShell != nullptr)
383 {
384 xPane = new ChildWindowPane(
385 rxPaneId,
386 nChildWindowId,
388 std::move(pShell));
389 }
390 }
391
392 return xPane;
393}
394
396{
397 if (m_bDisposed)
398 {
399 throw lang::DisposedException ("BasicPaneFactory object has already been disposed",
400 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
401 }
402}
403
404} // end of namespace sd::framework
405
406
407/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
Shell that displays the left pane for Draw.
Definition: PaneShells.hxx:48
Shell that displays the left pane for Impress.
Definition: PaneShells.hxx:31
vcl::Window * GetViewWindow()
Return the window that is used by the main view shell to display its view and other UI elements,...
Store URL, XPane reference and (local) PaneId for every pane factory that is registered at the PaneCo...
bool CompareURL(std::u16string_view rsPaneURL) const
bool ComparePane(const Reference< XResource > &rxPane) const
bool mbIsReleased
The mbReleased flag is set when the pane has been released.
css::uno::Reference< css::drawing::framework::XResource > CreateFrameWindowPane(const css::uno::Reference< css::drawing::framework::XResourceId > &rxPaneId)
Create a new instance of FrameWindowPane.
css::uno::WeakReference< css::drawing::framework::XConfigurationController > mxConfigurationControllerWeak
std::unique_ptr< PaneContainer > mpPaneContainer
virtual css::uno::Reference< css::drawing::framework::XResource > SAL_CALL createResource(const css::uno::Reference< css::drawing::framework::XResourceId > &rxPaneId) override
css::uno::Reference< css::drawing::framework::XResource > CreateFullScreenPane(const css::uno::Reference< css::uno::XComponentContext > &rxComponentContext, const css::uno::Reference< css::drawing::framework::XResourceId > &rxPaneId)
Create a new pane that represents the center pane in full screen mode.
virtual void SAL_CALL releaseResource(const css::uno::Reference< css::drawing::framework::XResource > &rxPane) override
virtual void SAL_CALL notifyConfigurationChange(const css::drawing::framework::ConfigurationChangeEvent &rEvent) override
BasicPaneFactory(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const rtl::Reference<::sd::DrawController > &rxController)
css::uno::Reference< css::drawing::framework::XResource > CreateChildWindowPane(const css::uno::Reference< css::drawing::framework::XResourceId > &rxPaneId, const PaneDescriptor &rDescriptor)
Create a new instance of ChildWindowPane.
virtual void disposing(std::unique_lock< std::mutex > &) override
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
The ChildWindowPane listens to the child window and disposes itself when the child window becomes ina...
This subclass is not necessary anymore.
static const OUString msCenterPaneURL
static const OUString msLeftDrawPaneURL
static constexpr OUStringLiteral msConfigurationUpdateStartEvent
static constexpr OUStringLiteral msConfigurationUpdateEndEvent
static const OUString msLeftImpressPaneURL
static const OUString msFullScreenPaneURL
The full screen pane creates a pane that covers the complete application window, i....