Line data Source code
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 <sal/config.h>
21 :
22 : #include <utility>
23 :
24 : #include "BasicPaneFactory.hxx"
25 : #include "facreg.hxx"
26 :
27 : #include "ChildWindowPane.hxx"
28 : #include "FrameWindowPane.hxx"
29 : #include "FullScreenPane.hxx"
30 :
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>
38 :
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;
43 :
44 : using ::sd::framework::FrameworkHelper;
45 :
46 : namespace {
47 : enum PaneId {
48 : CenterPaneId,
49 : FullScreenPaneId,
50 : LeftImpressPaneId,
51 : LeftDrawPaneId
52 : };
53 :
54 : static const sal_Int32 gnConfigurationUpdateStartEvent(0);
55 : static const sal_Int32 gnConfigurationUpdateEndEvent(1);
56 : }
57 :
58 : namespace sd { namespace framework {
59 :
60 : /** Store URL, XPane reference and (local) PaneId for every pane factory
61 : that is registered at the PaneController.
62 : */
63 1528 : class BasicPaneFactory::PaneDescriptor
64 : {
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.
72 : */
73 : bool mbIsReleased;
74 : bool mbIsChildWindow;
75 :
76 840 : bool CompareURL (const OUString& rsPaneURL) { return msPaneURL.equals(rsPaneURL); }
77 840 : bool ComparePane (const Reference<XResource>& rxPane) { return mxPane==rxPane; }
78 : };
79 :
80 1 : class BasicPaneFactory::PaneContainer
81 : : public ::std::vector<PaneDescriptor>
82 : {
83 : public:
84 127 : PaneContainer() {}
85 : };
86 :
87 : //===== PaneFactory ===========================================================
88 :
89 127 : BasicPaneFactory::BasicPaneFactory (
90 : const Reference<XComponentContext>& rxContext)
91 : : BasicPaneFactoryInterfaceBase(m_aMutex),
92 : mxComponentContext(rxContext),
93 : mxConfigurationControllerWeak(),
94 : mpViewShellBase(NULL),
95 127 : mpPaneContainer(new PaneContainer)
96 : {
97 127 : }
98 :
99 2 : BasicPaneFactory::~BasicPaneFactory()
100 : {
101 2 : }
102 :
103 1 : void SAL_CALL BasicPaneFactory::disposing()
104 : {
105 1 : Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
106 1 : if (xCC.is())
107 : {
108 0 : xCC->removeResourceFactoryForReference(this);
109 0 : xCC->removeConfigurationChangeListener(this);
110 0 : mxConfigurationControllerWeak.clear();
111 : }
112 :
113 15 : for (PaneContainer::const_iterator iDescriptor = mpPaneContainer->begin();
114 10 : iDescriptor != mpPaneContainer->end();
115 : ++iDescriptor)
116 : {
117 4 : if (iDescriptor->mbIsReleased)
118 : {
119 0 : Reference<XComponent> xComponent (iDescriptor->mxPane, UNO_QUERY);
120 0 : if (xComponent.is())
121 : {
122 0 : xComponent->removeEventListener(this);
123 0 : xComponent->dispose();
124 0 : }
125 : }
126 1 : }
127 1 : }
128 :
129 127 : void SAL_CALL BasicPaneFactory::initialize (const Sequence<Any>& aArguments)
130 : throw (Exception, RuntimeException, std::exception)
131 : {
132 127 : if (aArguments.getLength() > 0)
133 : {
134 : try
135 : {
136 : // Get the XController from the first argument.
137 127 : Reference<frame::XController> xController (aArguments[0], UNO_QUERY_THROW);
138 127 : mxControllerWeak = xController;
139 :
140 : // Tunnel through the controller to obtain access to the ViewShellBase.
141 : try
142 : {
143 127 : Reference<lang::XUnoTunnel> xTunnel (xController, UNO_QUERY_THROW);
144 : DrawController* pController
145 : = reinterpret_cast<DrawController*>(
146 : (sal::static_int_cast<sal_uIntPtr>(
147 127 : xTunnel->getSomething(DrawController::getUnoTunnelId()))));
148 127 : mpViewShellBase = pController->GetViewShellBase();
149 : }
150 0 : catch(RuntimeException&)
151 : {}
152 :
153 254 : Reference<XControllerManager> xCM (xController, UNO_QUERY_THROW);
154 254 : Reference<XConfigurationController> xCC (xCM->getConfigurationController());
155 127 : mxConfigurationControllerWeak = xCC;
156 :
157 : // Add pane factories for the two left panes (one for Impress and one for
158 : // Draw) and the center pane.
159 127 : if (xController.is() && xCC.is())
160 : {
161 127 : PaneDescriptor aDescriptor;
162 127 : aDescriptor.msPaneURL = FrameworkHelper::msCenterPaneURL;
163 127 : aDescriptor.mePaneId = CenterPaneId;
164 127 : aDescriptor.mbIsReleased = false;
165 127 : aDescriptor.mbIsChildWindow = false;
166 127 : mpPaneContainer->push_back(aDescriptor);
167 127 : xCC->addResourceFactory(aDescriptor.msPaneURL, this);
168 :
169 127 : aDescriptor.msPaneURL = FrameworkHelper::msFullScreenPaneURL;
170 127 : aDescriptor.mePaneId = FullScreenPaneId;
171 127 : mpPaneContainer->push_back(aDescriptor);
172 127 : xCC->addResourceFactory(aDescriptor.msPaneURL, this);
173 :
174 127 : aDescriptor.msPaneURL = FrameworkHelper::msLeftImpressPaneURL;
175 127 : aDescriptor.mePaneId = LeftImpressPaneId;
176 127 : aDescriptor.mbIsChildWindow = true;
177 127 : mpPaneContainer->push_back(aDescriptor);
178 127 : xCC->addResourceFactory(aDescriptor.msPaneURL, this);
179 :
180 127 : aDescriptor.msPaneURL = FrameworkHelper::msLeftDrawPaneURL;
181 127 : aDescriptor.mePaneId = LeftDrawPaneId;
182 127 : mpPaneContainer->push_back(aDescriptor);
183 127 : xCC->addResourceFactory(aDescriptor.msPaneURL, this);
184 : }
185 :
186 : // Register as configuration change listener.
187 127 : if (xCC.is())
188 : {
189 127 : xCC->addConfigurationChangeListener(
190 : this,
191 : FrameworkHelper::msConfigurationUpdateStartEvent,
192 127 : makeAny(gnConfigurationUpdateStartEvent));
193 127 : xCC->addConfigurationChangeListener(
194 : this,
195 : FrameworkHelper::msConfigurationUpdateEndEvent,
196 127 : makeAny(gnConfigurationUpdateEndEvent));
197 127 : }
198 : }
199 0 : catch (RuntimeException&)
200 : {
201 0 : Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
202 0 : if (xCC.is())
203 0 : xCC->removeResourceFactoryForReference(this);
204 : }
205 : }
206 127 : }
207 :
208 : //===== XPaneFactory ==========================================================
209 :
210 319 : Reference<XResource> SAL_CALL BasicPaneFactory::createResource (
211 : const Reference<XResourceId>& rxPaneId)
212 : throw (RuntimeException, IllegalArgumentException, WrappedTargetException, std::exception)
213 : {
214 319 : ThrowIfDisposed();
215 :
216 319 : Reference<XResource> xPane;
217 :
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 319 : mpPaneContainer->begin(),
223 319 : mpPaneContainer->end(),
224 957 : ::boost::bind(&PaneDescriptor::CompareURL, _1, rxPaneId->getResourceURL())));
225 :
226 319 : if (iDescriptor != mpPaneContainer->end())
227 : {
228 319 : if (iDescriptor->mxPane.is())
229 : {
230 : // The pane has already been created and is still active (has
231 : // not yet been released). This should not happen.
232 66 : xPane = iDescriptor->mxPane;
233 : }
234 : else
235 : {
236 : // Create a new pane.
237 253 : switch (iDescriptor->mePaneId)
238 : {
239 : case CenterPaneId:
240 127 : xPane = CreateFrameWindowPane(rxPaneId);
241 127 : break;
242 :
243 : case FullScreenPaneId:
244 0 : xPane = CreateFullScreenPane(mxComponentContext, rxPaneId);
245 0 : break;
246 :
247 : case LeftImpressPaneId:
248 : case LeftDrawPaneId:
249 252 : xPane = CreateChildWindowPane(
250 : rxPaneId,
251 252 : *iDescriptor);
252 126 : break;
253 : }
254 253 : iDescriptor->mxPane = xPane;
255 :
256 : // Listen for the pane being disposed.
257 253 : Reference<lang::XComponent> xComponent (xPane, UNO_QUERY);
258 253 : if (xComponent.is())
259 253 : xComponent->addEventListener(this);
260 : }
261 319 : iDescriptor->mbIsReleased = false;
262 : }
263 : else
264 : {
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,
269 0 : 0);
270 : }
271 :
272 319 : return xPane;
273 : }
274 :
275 319 : void SAL_CALL BasicPaneFactory::releaseResource (
276 : const Reference<XResource>& rxPane)
277 : throw (RuntimeException, std::exception)
278 : {
279 319 : ThrowIfDisposed();
280 :
281 : // Based on the given XPane reference look up the corresponding factory
282 : // descriptor.
283 : PaneContainer::iterator iDescriptor (
284 : ::std::find_if(
285 319 : mpPaneContainer->begin(),
286 319 : mpPaneContainer->end(),
287 957 : ::boost::bind(&PaneDescriptor::ComparePane, _1, rxPane)));
288 :
289 319 : if (iDescriptor != mpPaneContainer->end())
290 : {
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 319 : ChildWindowPane* pChildWindowPane = dynamic_cast<ChildWindowPane*>(rxPane.get());
297 319 : if (pChildWindowPane != NULL)
298 : {
299 192 : iDescriptor->mbIsReleased = true;
300 192 : pChildWindowPane->Hide();
301 : }
302 : else
303 : {
304 127 : iDescriptor->mxPane = NULL;
305 127 : Reference<XComponent> xComponent (rxPane, UNO_QUERY);
306 127 : if (xComponent.is())
307 : {
308 : // We are disposing the pane and do not have to be informed of
309 : // that.
310 127 : xComponent->removeEventListener(this);
311 127 : xComponent->dispose();
312 127 : }
313 : }
314 : }
315 : else
316 : {
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,
322 0 : 0);
323 : }
324 319 : }
325 :
326 : //===== XConfigurationChangeListener ==========================================
327 :
328 583 : void SAL_CALL BasicPaneFactory::notifyConfigurationChange (
329 : const ConfigurationChangeEvent& /* rEvent */ )
330 : throw (RuntimeException, std::exception)
331 : {
332 : // FIXME: nothing to do
333 583 : }
334 :
335 : //===== lang::XEventListener ==================================================
336 :
337 127 : void SAL_CALL BasicPaneFactory::disposing (
338 : const lang::EventObject& rEventObject)
339 : throw (RuntimeException, std::exception)
340 : {
341 127 : if (mxConfigurationControllerWeak == rEventObject.Source)
342 : {
343 127 : mxConfigurationControllerWeak.clear();
344 : }
345 : else
346 : {
347 : // Has one of the panes been disposed? If so, then release the
348 : // reference to that pane, but not the pane descriptor.
349 0 : Reference<XResource> xPane (rEventObject.Source, UNO_QUERY);
350 : PaneContainer::iterator iDescriptor (
351 : ::std::find_if (
352 0 : mpPaneContainer->begin(),
353 0 : mpPaneContainer->end(),
354 0 : ::boost::bind(&PaneDescriptor::ComparePane, _1, xPane)));
355 0 : if (iDescriptor != mpPaneContainer->end())
356 : {
357 0 : iDescriptor->mxPane = NULL;
358 0 : }
359 : }
360 127 : }
361 :
362 127 : Reference<XResource> BasicPaneFactory::CreateFrameWindowPane (
363 : const Reference<XResourceId>& rxPaneId)
364 : {
365 127 : Reference<XResource> xPane;
366 :
367 127 : if (mpViewShellBase != NULL)
368 : {
369 127 : xPane = new FrameWindowPane(rxPaneId, mpViewShellBase->GetViewWindow());
370 : }
371 :
372 127 : return xPane;
373 : }
374 :
375 0 : Reference<XResource> BasicPaneFactory::CreateFullScreenPane (
376 : const Reference<XComponentContext>& rxComponentContext,
377 : const Reference<XResourceId>& rxPaneId)
378 : {
379 : Reference<XResource> xPane (
380 : new FullScreenPane(
381 : rxComponentContext,
382 : rxPaneId,
383 0 : mpViewShellBase->GetViewWindow()));
384 :
385 0 : return xPane;
386 : }
387 :
388 126 : Reference<XResource> BasicPaneFactory::CreateChildWindowPane (
389 : const Reference<XResourceId>& rxPaneId,
390 : const PaneDescriptor& rDescriptor)
391 : {
392 126 : Reference<XResource> xPane;
393 :
394 126 : if (mpViewShellBase != NULL)
395 : {
396 : // Create the corresponding shell and determine the id of the child window.
397 126 : sal_uInt16 nChildWindowId = 0;
398 126 : ::std::unique_ptr<SfxShell> pShell;
399 126 : switch (rDescriptor.mePaneId)
400 : {
401 : case LeftImpressPaneId:
402 40 : pShell.reset(new LeftImpressPaneShell());
403 40 : nChildWindowId = ::sd::LeftPaneImpressChildWindow::GetChildWindowId();
404 40 : break;
405 :
406 : case LeftDrawPaneId:
407 86 : pShell.reset(new LeftDrawPaneShell());
408 86 : nChildWindowId = ::sd::LeftPaneDrawChildWindow::GetChildWindowId();
409 86 : break;
410 :
411 : default:
412 0 : break;
413 : }
414 :
415 : // With shell and child window id create the ChildWindowPane
416 : // wrapper.
417 126 : if (pShell.get() != NULL)
418 : {
419 252 : xPane = new ChildWindowPane(
420 : rxPaneId,
421 : nChildWindowId,
422 : *mpViewShellBase,
423 252 : std::move(pShell));
424 126 : }
425 : }
426 :
427 126 : return xPane;
428 : }
429 :
430 638 : void BasicPaneFactory::ThrowIfDisposed() const
431 : throw (lang::DisposedException)
432 : {
433 638 : if (rBHelper.bDisposed || rBHelper.bInDispose)
434 : {
435 : throw lang::DisposedException ("BasicPaneFactory object has already been disposed",
436 0 : const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
437 : }
438 638 : }
439 :
440 : } } // end of namespace sd::framework
441 :
442 :
443 : extern "C" SAL_DLLPUBLIC_EXPORT ::com::sun::star::uno::XInterface* SAL_CALL
444 127 : 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 &)
446 : {
447 127 : return cppu::acquire(new sd::framework::BasicPaneFactory(context));
448 66 : }
449 :
450 :
451 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|