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 <framework/ConfigurationController.hxx>
32 #include <PaneShells.hxx>
33 #include <ViewShellBase.hxx>
34 #include <PaneChildWindows.hxx>
35 #include <DrawController.hxx>
36 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
38 using namespace ::com::sun::star
;
39 using namespace ::com::sun::star::uno
;
40 using namespace ::com::sun::star::lang
;
41 using namespace ::com::sun::star::drawing::framework
;
43 using ::sd::framework::FrameworkHelper
;
54 const sal_Int32
gnConfigurationUpdateStartEvent(0);
55 const sal_Int32
gnConfigurationUpdateEndEvent(1);
58 namespace sd::framework
{
60 /** Store URL, XPane reference and (local) PaneId for every pane factory
61 that is registered at the PaneController.
63 class BasicPaneFactory::PaneDescriptor
67 Reference
<XResource
> mxPane
;
69 /** The mbReleased flag is set when the pane has been released. Some
70 panes are just hidden and destroyed. When the pane is reused this
75 bool CompareURL(std::u16string_view rsPaneURL
) const { return msPaneURL
== rsPaneURL
; }
76 bool ComparePane(const Reference
<XResource
>& rxPane
) const { return mxPane
== rxPane
; }
79 class BasicPaneFactory::PaneContainer
80 : public ::std::vector
<PaneDescriptor
>
86 //===== PaneFactory ===========================================================
88 BasicPaneFactory::BasicPaneFactory (
89 const Reference
<XComponentContext
>& rxContext
,
90 const rtl::Reference
<::sd::DrawController
>& rxController
)
91 : mxComponentContext(rxContext
),
92 mpViewShellBase(nullptr),
93 mpPaneContainer(new PaneContainer
)
97 // Tunnel through the controller to obtain access to the ViewShellBase.
98 mpViewShellBase
= rxController
->GetViewShellBase();
100 rtl::Reference
<sd::framework::ConfigurationController
> xCC (rxController
->getConfigurationControllerImpl());
101 mxConfigurationControllerWeak
= xCC
.get();
103 // Add pane factories for the two left panes (one for Impress and one for
104 // Draw) and the center pane.
105 if (rxController
.is() && xCC
.is())
107 PaneDescriptor aDescriptor
;
108 aDescriptor
.msPaneURL
= FrameworkHelper::msCenterPaneURL
;
109 aDescriptor
.mePaneId
= CenterPaneId
;
110 aDescriptor
.mbIsReleased
= false;
111 mpPaneContainer
->push_back(aDescriptor
);
112 xCC
->addResourceFactory(aDescriptor
.msPaneURL
, this);
114 aDescriptor
.msPaneURL
= FrameworkHelper::msFullScreenPaneURL
;
115 aDescriptor
.mePaneId
= FullScreenPaneId
;
116 mpPaneContainer
->push_back(aDescriptor
);
117 xCC
->addResourceFactory(aDescriptor
.msPaneURL
, this);
119 aDescriptor
.msPaneURL
= FrameworkHelper::msLeftImpressPaneURL
;
120 aDescriptor
.mePaneId
= LeftImpressPaneId
;
121 mpPaneContainer
->push_back(aDescriptor
);
122 xCC
->addResourceFactory(aDescriptor
.msPaneURL
, this);
124 aDescriptor
.msPaneURL
= FrameworkHelper::msBottomImpressPaneURL
;
125 aDescriptor
.mePaneId
= BottomImpressPaneId
;
126 mpPaneContainer
->push_back(aDescriptor
);
127 xCC
->addResourceFactory(aDescriptor
.msPaneURL
, this);
129 aDescriptor
.msPaneURL
= FrameworkHelper::msLeftDrawPaneURL
;
130 aDescriptor
.mePaneId
= LeftDrawPaneId
;
131 mpPaneContainer
->push_back(aDescriptor
);
132 xCC
->addResourceFactory(aDescriptor
.msPaneURL
, this);
135 // Register as configuration change listener.
138 xCC
->addConfigurationChangeListener(
140 FrameworkHelper::msConfigurationUpdateStartEvent
,
141 Any(gnConfigurationUpdateStartEvent
));
142 xCC
->addConfigurationChangeListener(
144 FrameworkHelper::msConfigurationUpdateEndEvent
,
145 Any(gnConfigurationUpdateEndEvent
));
148 catch (RuntimeException
&)
150 rtl::Reference
<ConfigurationController
> xCC (mxConfigurationControllerWeak
);
152 xCC
->removeResourceFactoryForReference(this);
156 BasicPaneFactory::~BasicPaneFactory()
160 void BasicPaneFactory::disposing(std::unique_lock
<std::mutex
>&)
162 rtl::Reference
<ConfigurationController
> xCC (mxConfigurationControllerWeak
);
165 xCC
->removeResourceFactoryForReference(this);
166 xCC
->removeConfigurationChangeListener(this);
167 mxConfigurationControllerWeak
.clear();
170 for (const auto& rDescriptor
: *mpPaneContainer
)
172 if (rDescriptor
.mbIsReleased
)
174 Reference
<XComponent
> xComponent (rDescriptor
.mxPane
, UNO_QUERY
);
177 xComponent
->removeEventListener(this);
178 xComponent
->dispose();
184 //===== XPaneFactory ==========================================================
186 Reference
<XResource
> SAL_CALL
BasicPaneFactory::createResource (
187 const Reference
<XResourceId
>& rxPaneId
)
191 Reference
<XResource
> xPane
;
193 // Based on the ResourceURL of the given ResourceId look up the
194 // corresponding factory descriptor.
195 PaneContainer::iterator
iDescriptor (
197 mpPaneContainer
->begin(),
198 mpPaneContainer
->end(),
199 [&] (PaneDescriptor
const& rPane
) {
200 return rPane
.CompareURL(rxPaneId
->getResourceURL());
203 if (iDescriptor
== mpPaneContainer
->end())
205 // The requested pane can not be created by any of the factories
206 // managed by the called BasicPaneFactory object.
207 throw lang::IllegalArgumentException(u
"BasicPaneFactory::createPane() called for unknown resource id"_ustr
,
212 if (iDescriptor
->mxPane
.is())
214 // The pane has already been created and is still active (has
215 // not yet been released). This should not happen.
216 xPane
= iDescriptor
->mxPane
;
220 // Create a new pane.
221 switch (iDescriptor
->mePaneId
)
224 xPane
= CreateFrameWindowPane(rxPaneId
);
227 case FullScreenPaneId
:
228 xPane
= CreateFullScreenPane(mxComponentContext
, rxPaneId
);
231 case LeftImpressPaneId
:
232 case BottomImpressPaneId
:
234 xPane
= CreateChildWindowPane(
239 iDescriptor
->mxPane
= xPane
;
241 // Listen for the pane being disposed.
242 Reference
<lang::XComponent
> xComponent (xPane
, UNO_QUERY
);
244 xComponent
->addEventListener(this);
246 iDescriptor
->mbIsReleased
= false;
252 void SAL_CALL
BasicPaneFactory::releaseResource (
253 const Reference
<XResource
>& rxPane
)
257 // Based on the given XPane reference look up the corresponding factory
259 PaneContainer::iterator
iDescriptor (
261 mpPaneContainer
->begin(),
262 mpPaneContainer
->end(),
263 [&] (PaneDescriptor
const& rPane
) { return rPane
.ComparePane(rxPane
); } ));
265 if (iDescriptor
== mpPaneContainer
->end())
267 // The given XPane reference is either empty or the pane was not
268 // created by any of the factories managed by the called
269 // BasicPaneFactory object.
270 throw lang::IllegalArgumentException(u
"BasicPaneFactory::releasePane() called for pane that was not created by same factory."_ustr
,
275 // The given pane was created by one of the factories. Child
276 // windows are just hidden and will be reused when requested later.
277 // Other windows are disposed and their reference is reset so that
278 // on the next createPane() call for the same pane type the pane is
280 ChildWindowPane
* pChildWindowPane
= dynamic_cast<ChildWindowPane
*>(rxPane
.get());
281 if (pChildWindowPane
!= nullptr)
283 iDescriptor
->mbIsReleased
= true;
284 pChildWindowPane
->Hide();
288 iDescriptor
->mxPane
= nullptr;
289 Reference
<XComponent
> xComponent (rxPane
, UNO_QUERY
);
292 // We are disposing the pane and do not have to be informed of
294 xComponent
->removeEventListener(this);
295 xComponent
->dispose();
301 //===== XConfigurationChangeListener ==========================================
303 void SAL_CALL
BasicPaneFactory::notifyConfigurationChange (
304 const ConfigurationChangeEvent
& /* rEvent */ )
306 // FIXME: nothing to do
309 //===== lang::XEventListener ==================================================
311 void SAL_CALL
BasicPaneFactory::disposing (
312 const lang::EventObject
& rEventObject
)
314 if (uno::Reference
<XInterface
>(cppu::getXWeak(mxConfigurationControllerWeak
.get().get())) == rEventObject
.Source
)
316 mxConfigurationControllerWeak
.clear();
320 // Has one of the panes been disposed? If so, then release the
321 // reference to that pane, but not the pane descriptor.
322 Reference
<XResource
> xPane (rEventObject
.Source
, UNO_QUERY
);
323 PaneContainer::iterator
iDescriptor (
325 mpPaneContainer
->begin(),
326 mpPaneContainer
->end(),
327 [&] (PaneDescriptor
const& rPane
) { return rPane
.ComparePane(xPane
); } ));
328 if (iDescriptor
!= mpPaneContainer
->end())
330 iDescriptor
->mxPane
= nullptr;
335 Reference
<XResource
> BasicPaneFactory::CreateFrameWindowPane (
336 const Reference
<XResourceId
>& rxPaneId
)
338 Reference
<XResource
> xPane
;
340 if (mpViewShellBase
!= nullptr)
342 xPane
= new FrameWindowPane(rxPaneId
, mpViewShellBase
->GetViewWindow());
348 Reference
<XResource
> BasicPaneFactory::CreateFullScreenPane (
349 const Reference
<XComponentContext
>& rxComponentContext
,
350 const Reference
<XResourceId
>& rxPaneId
)
352 Reference
<XResource
> xPane (
356 mpViewShellBase
->GetViewWindow(),
357 mpViewShellBase
->GetDocShell()));
362 Reference
<XResource
> BasicPaneFactory::CreateChildWindowPane (
363 const Reference
<XResourceId
>& rxPaneId
,
364 const PaneDescriptor
& rDescriptor
)
366 Reference
<XResource
> xPane
;
368 if (mpViewShellBase
!= nullptr)
370 // Create the corresponding shell and determine the id of the child window.
371 sal_uInt16 nChildWindowId
= 0;
372 ::std::unique_ptr
<SfxShell
> pShell
;
373 switch (rDescriptor
.mePaneId
)
375 case LeftImpressPaneId
:
376 pShell
.reset(new LeftImpressPaneShell());
377 nChildWindowId
= ::sd::LeftPaneImpressChildWindow::GetChildWindowId();
380 case BottomImpressPaneId
:
381 pShell
.reset(new BottomImpressPaneShell());
382 nChildWindowId
= ::sd::BottomPaneImpressChildWindow::GetChildWindowId();
386 pShell
.reset(new LeftDrawPaneShell());
387 nChildWindowId
= ::sd::LeftPaneDrawChildWindow::GetChildWindowId();
394 // With shell and child window id create the ChildWindowPane
396 if (pShell
!= nullptr)
398 xPane
= new ChildWindowPane(
409 void BasicPaneFactory::ThrowIfDisposed() const
413 throw lang::DisposedException (u
"BasicPaneFactory object has already been disposed"_ustr
,
414 const_cast<uno::XWeak
*>(static_cast<const uno::XWeak
*>(this)));
418 } // end of namespace sd::framework
421 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */