bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / framework / factories / BasicPaneFactory.cxx
blob9d9c7959e0b261f101a3e10f234becfacba4283d
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 <sal/config.h>
22 #include <utility>
24 #include "BasicPaneFactory.hxx"
25 #include "facreg.hxx"
27 #include "ChildWindowPane.hxx"
28 #include "FrameWindowPane.hxx"
29 #include "FullScreenPane.hxx"
31 #include "framework/FrameworkHelper.hxx"
32 #include "ViewShellBase.hxx"
33 #include "PaneChildWindows.hxx"
34 #include "DrawController.hxx"
35 #include "DrawDocShell.hxx"
36 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
37 #include <boost/bind.hpp>
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
41 using namespace ::com::sun::star::lang;
42 using namespace ::com::sun::star::drawing::framework;
44 using ::sd::framework::FrameworkHelper;
46 namespace {
47 enum PaneId {
48 CenterPaneId,
49 FullScreenPaneId,
50 LeftImpressPaneId,
51 LeftDrawPaneId
54 static const sal_Int32 gnConfigurationUpdateStartEvent(0);
55 static const sal_Int32 gnConfigurationUpdateEndEvent(1);
58 namespace sd { namespace framework {
60 /** Store URL, XPane reference and (local) PaneId for every pane factory
61 that is registered at the PaneController.
63 class BasicPaneFactory::PaneDescriptor
65 public:
66 OUString msPaneURL;
67 Reference<XResource> mxPane;
68 PaneId mePaneId;
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
71 flag is reset.
73 bool mbIsReleased;
74 bool mbIsChildWindow;
76 bool CompareURL (const OUString& rsPaneURL) { return msPaneURL.equals(rsPaneURL); }
77 bool ComparePane (const Reference<XResource>& rxPane) { return mxPane==rxPane; }
80 class BasicPaneFactory::PaneContainer
81 : public ::std::vector<PaneDescriptor>
83 public:
84 PaneContainer() {}
87 //===== PaneFactory ===========================================================
89 BasicPaneFactory::BasicPaneFactory (
90 const Reference<XComponentContext>& rxContext)
91 : BasicPaneFactoryInterfaceBase(m_aMutex),
92 mxComponentContext(rxContext),
93 mxConfigurationControllerWeak(),
94 mpViewShellBase(NULL),
95 mpPaneContainer(new PaneContainer)
99 BasicPaneFactory::~BasicPaneFactory()
103 void SAL_CALL BasicPaneFactory::disposing()
105 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
106 if (xCC.is())
108 xCC->removeResourceFactoryForReference(this);
109 xCC->removeConfigurationChangeListener(this);
110 mxConfigurationControllerWeak.clear();
113 for (PaneContainer::const_iterator iDescriptor = mpPaneContainer->begin();
114 iDescriptor != mpPaneContainer->end();
115 ++iDescriptor)
117 if (iDescriptor->mbIsReleased)
119 Reference<XComponent> xComponent (iDescriptor->mxPane, UNO_QUERY);
120 if (xComponent.is())
122 xComponent->removeEventListener(this);
123 xComponent->dispose();
129 void SAL_CALL BasicPaneFactory::initialize (const Sequence<Any>& aArguments)
130 throw (Exception, RuntimeException, std::exception)
132 if (aArguments.getLength() > 0)
136 // Get the XController from the first argument.
137 Reference<frame::XController> xController (aArguments[0], UNO_QUERY_THROW);
138 mxControllerWeak = xController;
140 // Tunnel through the controller to obtain access to the ViewShellBase.
143 Reference<lang::XUnoTunnel> xTunnel (xController, UNO_QUERY_THROW);
144 DrawController* pController
145 = reinterpret_cast<DrawController*>(
146 (sal::static_int_cast<sal_uIntPtr>(
147 xTunnel->getSomething(DrawController::getUnoTunnelId()))));
148 mpViewShellBase = pController->GetViewShellBase();
150 catch(RuntimeException&)
153 Reference<XControllerManager> xCM (xController, UNO_QUERY_THROW);
154 Reference<XConfigurationController> xCC (xCM->getConfigurationController());
155 mxConfigurationControllerWeak = xCC;
157 // Add pane factories for the two left panes (one for Impress and one for
158 // Draw) and the center pane.
159 if (xController.is() && xCC.is())
161 PaneDescriptor aDescriptor;
162 aDescriptor.msPaneURL = FrameworkHelper::msCenterPaneURL;
163 aDescriptor.mePaneId = CenterPaneId;
164 aDescriptor.mbIsReleased = false;
165 aDescriptor.mbIsChildWindow = false;
166 mpPaneContainer->push_back(aDescriptor);
167 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
169 aDescriptor.msPaneURL = FrameworkHelper::msFullScreenPaneURL;
170 aDescriptor.mePaneId = FullScreenPaneId;
171 mpPaneContainer->push_back(aDescriptor);
172 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
174 aDescriptor.msPaneURL = FrameworkHelper::msLeftImpressPaneURL;
175 aDescriptor.mePaneId = LeftImpressPaneId;
176 aDescriptor.mbIsChildWindow = true;
177 mpPaneContainer->push_back(aDescriptor);
178 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
180 aDescriptor.msPaneURL = FrameworkHelper::msLeftDrawPaneURL;
181 aDescriptor.mePaneId = LeftDrawPaneId;
182 mpPaneContainer->push_back(aDescriptor);
183 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
186 // Register as configuration change listener.
187 if (xCC.is())
189 xCC->addConfigurationChangeListener(
190 this,
191 FrameworkHelper::msConfigurationUpdateStartEvent,
192 makeAny(gnConfigurationUpdateStartEvent));
193 xCC->addConfigurationChangeListener(
194 this,
195 FrameworkHelper::msConfigurationUpdateEndEvent,
196 makeAny(gnConfigurationUpdateEndEvent));
199 catch (RuntimeException&)
201 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
202 if (xCC.is())
203 xCC->removeResourceFactoryForReference(this);
208 //===== XPaneFactory ==========================================================
210 Reference<XResource> SAL_CALL BasicPaneFactory::createResource (
211 const Reference<XResourceId>& rxPaneId)
212 throw (RuntimeException, IllegalArgumentException, WrappedTargetException, std::exception)
214 ThrowIfDisposed();
216 Reference<XResource> xPane;
218 // Based on the ResourceURL of the given ResourceId look up the
219 // corresponding factory descriptor.
220 PaneContainer::iterator iDescriptor (
221 ::std::find_if (
222 mpPaneContainer->begin(),
223 mpPaneContainer->end(),
224 ::boost::bind(&PaneDescriptor::CompareURL, _1, rxPaneId->getResourceURL())));
226 if (iDescriptor != mpPaneContainer->end())
228 if (iDescriptor->mxPane.is())
230 // The pane has already been created and is still active (has
231 // not yet been released). This should not happen.
232 xPane = iDescriptor->mxPane;
234 else
236 // Create a new pane.
237 switch (iDescriptor->mePaneId)
239 case CenterPaneId:
240 xPane = CreateFrameWindowPane(rxPaneId);
241 break;
243 case FullScreenPaneId:
244 xPane = CreateFullScreenPane(mxComponentContext, rxPaneId);
245 break;
247 case LeftImpressPaneId:
248 case LeftDrawPaneId:
249 xPane = CreateChildWindowPane(
250 rxPaneId,
251 *iDescriptor);
252 break;
254 iDescriptor->mxPane = xPane;
256 // Listen for the pane being disposed.
257 Reference<lang::XComponent> xComponent (xPane, UNO_QUERY);
258 if (xComponent.is())
259 xComponent->addEventListener(this);
261 iDescriptor->mbIsReleased = false;
263 else
265 // The requested pane can not be created by any of the factories
266 // managed by the called BasicPaneFactory object.
267 throw lang::IllegalArgumentException("BasicPaneFactory::createPane() called for unknown resource id",
268 NULL,
272 return xPane;
275 void SAL_CALL BasicPaneFactory::releaseResource (
276 const Reference<XResource>& rxPane)
277 throw (RuntimeException, std::exception)
279 ThrowIfDisposed();
281 // Based on the given XPane reference look up the corresponding factory
282 // descriptor.
283 PaneContainer::iterator iDescriptor (
284 ::std::find_if(
285 mpPaneContainer->begin(),
286 mpPaneContainer->end(),
287 ::boost::bind(&PaneDescriptor::ComparePane, _1, rxPane)));
289 if (iDescriptor != mpPaneContainer->end())
291 // The given pane was created by one of the factories. Child
292 // windows are just hidden and will be reused when requested later.
293 // Other windows are disposed and their reference is reset so that
294 // on the next createPane() call for the same pane type the pane is
295 // created anew.
296 ChildWindowPane* pChildWindowPane = dynamic_cast<ChildWindowPane*>(rxPane.get());
297 if (pChildWindowPane != NULL)
299 iDescriptor->mbIsReleased = true;
300 pChildWindowPane->Hide();
302 else
304 iDescriptor->mxPane = NULL;
305 Reference<XComponent> xComponent (rxPane, UNO_QUERY);
306 if (xComponent.is())
308 // We are disposing the pane and do not have to be informed of
309 // that.
310 xComponent->removeEventListener(this);
311 xComponent->dispose();
315 else
317 // The given XPane reference is either empty or the pane was not
318 // created by any of the factories managed by the called
319 // BasicPaneFactory object.
320 throw lang::IllegalArgumentException("BasicPaneFactory::releasePane() called for pane that was not created by same factory.",
321 NULL,
326 //===== XConfigurationChangeListener ==========================================
328 void SAL_CALL BasicPaneFactory::notifyConfigurationChange (
329 const ConfigurationChangeEvent& /* rEvent */ )
330 throw (RuntimeException, std::exception)
332 // FIXME: nothing to do
335 //===== lang::XEventListener ==================================================
337 void SAL_CALL BasicPaneFactory::disposing (
338 const lang::EventObject& rEventObject)
339 throw (RuntimeException, std::exception)
341 if (mxConfigurationControllerWeak == rEventObject.Source)
343 mxConfigurationControllerWeak.clear();
345 else
347 // Has one of the panes been disposed? If so, then release the
348 // reference to that pane, but not the pane descriptor.
349 Reference<XResource> xPane (rEventObject.Source, UNO_QUERY);
350 PaneContainer::iterator iDescriptor (
351 ::std::find_if (
352 mpPaneContainer->begin(),
353 mpPaneContainer->end(),
354 ::boost::bind(&PaneDescriptor::ComparePane, _1, xPane)));
355 if (iDescriptor != mpPaneContainer->end())
357 iDescriptor->mxPane = NULL;
362 Reference<XResource> BasicPaneFactory::CreateFrameWindowPane (
363 const Reference<XResourceId>& rxPaneId)
365 Reference<XResource> xPane;
367 if (mpViewShellBase != NULL)
369 xPane = new FrameWindowPane(rxPaneId, mpViewShellBase->GetViewWindow());
372 return xPane;
375 Reference<XResource> BasicPaneFactory::CreateFullScreenPane (
376 const Reference<XComponentContext>& rxComponentContext,
377 const Reference<XResourceId>& rxPaneId)
379 Reference<XResource> xPane (
380 new FullScreenPane(
381 rxComponentContext,
382 rxPaneId,
383 mpViewShellBase->GetViewWindow()));
385 return xPane;
388 Reference<XResource> BasicPaneFactory::CreateChildWindowPane (
389 const Reference<XResourceId>& rxPaneId,
390 const PaneDescriptor& rDescriptor)
392 Reference<XResource> xPane;
394 if (mpViewShellBase != NULL)
396 // Create the corresponding shell and determine the id of the child window.
397 sal_uInt16 nChildWindowId = 0;
398 ::std::unique_ptr<SfxShell> pShell;
399 switch (rDescriptor.mePaneId)
401 case LeftImpressPaneId:
402 pShell.reset(new LeftImpressPaneShell());
403 nChildWindowId = ::sd::LeftPaneImpressChildWindow::GetChildWindowId();
404 break;
406 case LeftDrawPaneId:
407 pShell.reset(new LeftDrawPaneShell());
408 nChildWindowId = ::sd::LeftPaneDrawChildWindow::GetChildWindowId();
409 break;
411 default:
412 break;
415 // With shell and child window id create the ChildWindowPane
416 // wrapper.
417 if (pShell.get() != NULL)
419 xPane = new ChildWindowPane(
420 rxPaneId,
421 nChildWindowId,
422 *mpViewShellBase,
423 std::move(pShell));
427 return xPane;
430 void BasicPaneFactory::ThrowIfDisposed() const
431 throw (lang::DisposedException)
433 if (rBHelper.bDisposed || rBHelper.bInDispose)
435 throw lang::DisposedException ("BasicPaneFactory object has already been disposed",
436 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
440 } } // end of namespace sd::framework
443 extern "C" SAL_DLLPUBLIC_EXPORT ::com::sun::star::uno::XInterface* SAL_CALL
444 com_sun_star_comp_Draw_framework_BasicPaneFactory_get_implementation(::com::sun::star::uno::XComponentContext* context,
445 ::com::sun::star::uno::Sequence<css::uno::Any> const &)
447 return cppu::acquire(new sd::framework::BasicPaneFactory(context));
451 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */