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