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