1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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
;
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
65 Reference
<XResource
> mxPane
;
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
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
>
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
)
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.
131 xCC
->addConfigurationChangeListener(
133 FrameworkHelper::msConfigurationUpdateStartEvent
,
134 Any(gnConfigurationUpdateStartEvent
));
135 xCC
->addConfigurationChangeListener(
137 FrameworkHelper::msConfigurationUpdateEndEvent
,
138 Any(gnConfigurationUpdateEndEvent
));
141 catch (RuntimeException
&)
143 Reference
<XConfigurationController
> xCC (mxConfigurationControllerWeak
);
145 xCC
->removeResourceFactoryForReference(this);
149 BasicPaneFactory::~BasicPaneFactory()
153 void BasicPaneFactory::disposing(std::unique_lock
<std::mutex
>&)
155 Reference
<XConfigurationController
> xCC (mxConfigurationControllerWeak
);
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
);
170 xComponent
->removeEventListener(this);
171 xComponent
->dispose();
177 //===== XPaneFactory ==========================================================
179 Reference
<XResource
> SAL_CALL
BasicPaneFactory::createResource (
180 const Reference
<XResourceId
>& rxPaneId
)
184 Reference
<XResource
> xPane
;
186 // Based on the ResourceURL of the given ResourceId look up the
187 // corresponding factory descriptor.
188 PaneContainer::iterator
iDescriptor (
190 mpPaneContainer
->begin(),
191 mpPaneContainer
->end(),
192 [&] (PaneDescriptor
const& rPane
) {
193 return rPane
.CompareURL(rxPaneId
->getResourceURL());
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",
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
;
213 // Create a new pane.
214 switch (iDescriptor
->mePaneId
)
217 xPane
= CreateFrameWindowPane(rxPaneId
);
220 case FullScreenPaneId
:
221 xPane
= CreateFullScreenPane(mxComponentContext
, rxPaneId
);
224 case LeftImpressPaneId
:
226 xPane
= CreateChildWindowPane(
231 iDescriptor
->mxPane
= xPane
;
233 // Listen for the pane being disposed.
234 Reference
<lang::XComponent
> xComponent (xPane
, UNO_QUERY
);
236 xComponent
->addEventListener(this);
238 iDescriptor
->mbIsReleased
= false;
244 void SAL_CALL
BasicPaneFactory::releaseResource (
245 const Reference
<XResource
>& rxPane
)
249 // Based on the given XPane reference look up the corresponding factory
251 PaneContainer::iterator
iDescriptor (
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.",
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
272 ChildWindowPane
* pChildWindowPane
= dynamic_cast<ChildWindowPane
*>(rxPane
.get());
273 if (pChildWindowPane
!= nullptr)
275 iDescriptor
->mbIsReleased
= true;
276 pChildWindowPane
->Hide();
280 iDescriptor
->mxPane
= nullptr;
281 Reference
<XComponent
> xComponent (rxPane
, UNO_QUERY
);
284 // We are disposing the pane and do not have to be informed of
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();
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 (
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());
340 Reference
<XResource
> BasicPaneFactory::CreateFullScreenPane (
341 const Reference
<XComponentContext
>& rxComponentContext
,
342 const Reference
<XResourceId
>& rxPaneId
)
344 Reference
<XResource
> xPane (
348 mpViewShellBase
->GetViewWindow()));
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();
372 pShell
.reset(new LeftDrawPaneShell());
373 nChildWindowId
= ::sd::LeftPaneDrawChildWindow::GetChildWindowId();
380 // With shell and child window id create the ChildWindowPane
382 if (pShell
!= nullptr)
384 xPane
= new ChildWindowPane(
395 void BasicPaneFactory::ThrowIfDisposed() const
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: */