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