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