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 <osl/time.h>
21 :
22 : #include "framework/FrameworkHelper.hxx"
23 :
24 : #include "framework/ConfigurationController.hxx"
25 : #include "framework/ResourceId.hxx"
26 : #include "framework/ViewShellWrapper.hxx"
27 : #include "ViewShellBase.hxx"
28 : #include "FrameView.hxx"
29 : #include "DrawViewShell.hxx"
30 : #include "ViewShellHint.hxx"
31 : #include "DrawController.hxx"
32 : #include "app.hrc"
33 : #include <com/sun/star/drawing/framework/XControllerManager.hpp>
34 : #include <com/sun/star/drawing/framework/XPane.hpp>
35 : #include <cppuhelper/compbase1.hxx>
36 : #include <svl/lstner.hxx>
37 :
38 : #include <sfx2/request.hxx>
39 : #include <sfx2/dispatch.hxx>
40 :
41 : #include "MutexOwner.hxx"
42 : #include "vcl/svapp.hxx"
43 : #include <osl/doublecheckedlocking.h>
44 : #include <osl/getglobalmutex.hxx>
45 : #include <tools/diagnose_ex.h>
46 : #include <boost/unordered_map.hpp>
47 :
48 : using namespace ::com::sun::star;
49 : using namespace ::com::sun::star::uno;
50 : using namespace ::com::sun::star::drawing::framework;
51 :
52 : namespace {
53 :
54 : //----- CallbackCaller --------------------------------------------------------
55 :
56 : typedef ::cppu::WeakComponentImplHelper1 <
57 : ::com::sun::star::drawing::framework::XConfigurationChangeListener
58 : > CallbackCallerInterfaceBase;
59 :
60 : /** A CallbackCaller registers as listener at an XConfigurationController
61 : object and waits for the notification of one type of event. When that
62 : event is received, or when the CallbackCaller detects at its
63 : construction that the event will not be sent in the near future, the
64 : actual callback object is called and the CallbackCaller destroys itself.
65 : */
66 : class CallbackCaller
67 : : public ::sd::MutexOwner,
68 : public CallbackCallerInterfaceBase
69 : {
70 : public:
71 : /** Create a new CallbackCaller object. This object controls its own
72 : lifetime by acquiring a reference to itself in the constructor.
73 : When it detects that the event will not be notified in the near
74 : future (because the queue of pending configuration change operations
75 : is empty and therefore no event will be sent int the near future, it
76 : does not acquires a reference and thus initiates its destruction in
77 : the constructor.)
78 : @param rBase
79 : This ViewShellBase object is used to determine the
80 : XConfigurationController at which to register.
81 : @param rsEventType
82 : The event type which the callback is waiting for.
83 : @param pCallback
84 : The callback object which is to be notified. The caller will
85 : typically release his reference to the caller so that when the
86 : CallbackCaller dies (after having called the callback) the
87 : callback is destroyed.
88 : */
89 : CallbackCaller (
90 : ::sd::ViewShellBase& rBase,
91 : const OUString& rsEventType,
92 : const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter,
93 : const ::sd::framework::FrameworkHelper::Callback& rCallback);
94 : virtual ~CallbackCaller (void);
95 :
96 : virtual void SAL_CALL disposing (void) SAL_OVERRIDE;
97 : // XEventListener
98 : virtual void SAL_CALL disposing (const lang::EventObject& rEvent)
99 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
100 : // XConfigurationChangeListener
101 : virtual void SAL_CALL notifyConfigurationChange (const ConfigurationChangeEvent& rEvent)
102 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
103 :
104 : private:
105 : OUString msEventType;
106 : Reference<XConfigurationController> mxConfigurationController;
107 : ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter maFilter;
108 : ::sd::framework::FrameworkHelper::Callback maCallback;
109 : };
110 :
111 : //----- LifetimeController ----------------------------------------------------
112 :
113 : typedef ::cppu::WeakComponentImplHelper1 <
114 : ::com::sun::star::lang::XEventListener
115 : > LifetimeControllerInterfaceBase;
116 :
117 : /** This class helps controlling the lifetime of the
118 : FrameworkHelper. Register at a ViewShellBase object and an XController
119 : object and call Dispose() at the associated FrameworkHelper object when
120 : one of them and Release() when both of them are destroyed.
121 : */
122 : class LifetimeController
123 : : public ::sd::MutexOwner,
124 : public LifetimeControllerInterfaceBase,
125 : public SfxListener
126 : {
127 : public:
128 : explicit LifetimeController (::sd::ViewShellBase& rBase);
129 : virtual ~LifetimeController (void);
130 :
131 : virtual void SAL_CALL disposing (void) SAL_OVERRIDE;
132 :
133 : /** XEventListener. This method is called when the frame::XController
134 : is being destroyed.
135 : */
136 : virtual void SAL_CALL disposing (const lang::EventObject& rEvent)
137 : throw (RuntimeException, std::exception) SAL_OVERRIDE;
138 :
139 : /** This method is called when the ViewShellBase is being destroyed.
140 : */
141 : virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) SAL_OVERRIDE;
142 :
143 : private:
144 : ::sd::ViewShellBase& mrBase;
145 : bool mbListeningToViewShellBase;
146 : bool mbListeningToController;
147 :
148 : /** When one or both of the mbListeningToViewShellBase and
149 : mbListeningToController members were modified then call this method
150 : to either dispose or release the associated FrameworkHelper.
151 : */
152 : void Update (void);
153 : };
154 :
155 : } // end of anonymous namespace
156 :
157 : namespace sd { namespace framework {
158 :
159 : namespace {
160 :
161 : class FrameworkHelperAllPassFilter
162 : {
163 : public:
164 0 : bool operator() (const css::drawing::framework::ConfigurationChangeEvent&) { return true; }
165 : };
166 :
167 0 : class FrameworkHelperResourceIdFilter
168 : {
169 : public:
170 : FrameworkHelperResourceIdFilter (
171 : const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId);
172 0 : bool operator() (const css::drawing::framework::ConfigurationChangeEvent& rEvent)
173 0 : { return mxResourceId.is() && rEvent.ResourceId.is()
174 0 : && mxResourceId->compareTo(rEvent.ResourceId) == 0; }
175 : private:
176 : css::uno::Reference<css::drawing::framework::XResourceId> mxResourceId;
177 : };
178 :
179 : } // end of anonymous namespace
180 :
181 : // Pane URLS.
182 :
183 38 : const OUString FrameworkHelper::msPaneURLPrefix("private:resource/pane/");
184 38 : const OUString FrameworkHelper::msCenterPaneURL( msPaneURLPrefix + "CenterPane");
185 38 : const OUString FrameworkHelper::msFullScreenPaneURL( msPaneURLPrefix + "FullScreenPane");
186 38 : const OUString FrameworkHelper::msLeftImpressPaneURL( msPaneURLPrefix + "LeftImpressPane");
187 38 : const OUString FrameworkHelper::msLeftDrawPaneURL( msPaneURLPrefix + "LeftDrawPane");
188 38 : const OUString FrameworkHelper::msSidebarPaneURL( msPaneURLPrefix + "SidebarPane");
189 :
190 : // View URLs.
191 :
192 38 : const OUString FrameworkHelper::msViewURLPrefix("private:resource/view/");
193 38 : const OUString FrameworkHelper::msImpressViewURL( msViewURLPrefix + "ImpressView");
194 38 : const OUString FrameworkHelper::msDrawViewURL( msViewURLPrefix + "GraphicView");
195 38 : const OUString FrameworkHelper::msOutlineViewURL( msViewURLPrefix + "OutlineView");
196 38 : const OUString FrameworkHelper::msNotesViewURL( msViewURLPrefix + "NotesView");
197 38 : const OUString FrameworkHelper::msHandoutViewURL( msViewURLPrefix + "HandoutView");
198 38 : const OUString FrameworkHelper::msSlideSorterURL( msViewURLPrefix + "SlideSorter");
199 38 : const OUString FrameworkHelper::msPresentationViewURL( msViewURLPrefix + "PresentationView");
200 38 : const OUString FrameworkHelper::msSidebarViewURL( msViewURLPrefix + "SidebarView");
201 :
202 : // Tool bar URLs.
203 :
204 38 : const OUString FrameworkHelper::msToolBarURLPrefix("private:resource/toolbar/");
205 38 : const OUString FrameworkHelper::msViewTabBarURL( msToolBarURLPrefix + "ViewTabBar");
206 :
207 : // Task panel URLs.
208 38 : const OUString FrameworkHelper::msTaskPanelURLPrefix( "private:resource/toolpanel/" );
209 38 : const OUString FrameworkHelper::msAllMasterPagesTaskPanelURL( msTaskPanelURLPrefix + "AllMasterPages" );
210 38 : const OUString FrameworkHelper::msRecentMasterPagesTaskPanelURL( msTaskPanelURLPrefix + "RecentMasterPages" );
211 38 : const OUString FrameworkHelper::msUsedMasterPagesTaskPanelURL( msTaskPanelURLPrefix + "UsedMasterPages" );
212 38 : const OUString FrameworkHelper::msLayoutTaskPanelURL( msTaskPanelURLPrefix + "Layouts" );
213 38 : const OUString FrameworkHelper::msTableDesignPanelURL( msTaskPanelURLPrefix + "TableDesign" );
214 38 : const OUString FrameworkHelper::msCustomAnimationTaskPanelURL( msTaskPanelURLPrefix + "CustomAnimations" );
215 38 : const OUString FrameworkHelper::msSlideTransitionTaskPanelURL( msTaskPanelURLPrefix + "SlideTransitions" );
216 :
217 : // Event URLs.
218 38 : const OUString FrameworkHelper::msResourceActivationRequestEvent( "ResourceActivationRequested" );
219 38 : const OUString FrameworkHelper::msResourceDeactivationRequestEvent( "ResourceDeactivationRequest" );
220 38 : const OUString FrameworkHelper::msResourceActivationEvent( "ResourceActivation" );
221 38 : const OUString FrameworkHelper::msResourceDeactivationEvent( "ResourceDeactivation" );
222 38 : const OUString FrameworkHelper::msResourceDeactivationEndEvent( "ResourceDeactivationEnd" );
223 38 : const OUString FrameworkHelper::msConfigurationUpdateStartEvent( "ConfigurationUpdateStart" );
224 38 : const OUString FrameworkHelper::msConfigurationUpdateEndEvent( "ConfigurationUpdateEnd" );
225 :
226 : // Service names of controllers.
227 38 : const OUString FrameworkHelper::msModuleControllerService("com.sun.star.drawing.framework.ModuleController");
228 38 : const OUString FrameworkHelper::msConfigurationControllerService("com.sun.star.drawing.framework.ConfigurationController");
229 :
230 : //----- helper ----------------------------------------------------------------
231 : namespace
232 : {
233 10052 : static ::boost::shared_ptr< ViewShell > lcl_getViewShell( const Reference< XResource >& i_rViewShellWrapper )
234 : {
235 10052 : ::boost::shared_ptr< ViewShell > pViewShell;
236 10052 : if ( !i_rViewShellWrapper.is() )
237 1272 : return pViewShell;
238 :
239 : try
240 : {
241 8780 : Reference<lang::XUnoTunnel> xViewTunnel( i_rViewShellWrapper, UNO_QUERY_THROW );
242 17560 : pViewShell = reinterpret_cast< ViewShellWrapper* >(
243 26340 : xViewTunnel->getSomething( ViewShellWrapper::getUnoTunnelId() ) )->GetViewShell();
244 : }
245 0 : catch( const Exception& )
246 : {
247 : DBG_UNHANDLED_EXCEPTION();
248 : }
249 8780 : return pViewShell;
250 : }
251 10234 : Reference< XResource > lcl_getFirstViewInPane( const Reference< XConfigurationController >& i_rConfigController,
252 : const Reference< XResourceId >& i_rPaneId )
253 : {
254 : try
255 : {
256 10234 : Reference< XConfiguration > xConfiguration( i_rConfigController->getRequestedConfiguration(), UNO_SET_THROW );
257 10234 : Sequence< Reference< XResourceId > > aViewIds( xConfiguration->getResources(
258 11082 : i_rPaneId, FrameworkHelper::msViewURLPrefix, AnchorBindingMode_DIRECT ) );
259 10234 : if ( aViewIds.getLength() > 0 )
260 10234 : return i_rConfigController->getResource( aViewIds[0] );
261 : }
262 0 : catch( const Exception& )
263 : {
264 : DBG_UNHANDLED_EXCEPTION();
265 : }
266 848 : return NULL;
267 : }
268 : }
269 :
270 : //----- FrameworkHelper::ViewURLMap -------------------------------------------
271 :
272 : /** The ViewURLMap is used to translate between the view URLs used by the
273 : drawing framework and the enums defined in the ViewShell class.
274 : */
275 38 : class FrameworkHelper::ViewURLMap
276 : : public ::boost::unordered_map<
277 : OUString,
278 : ViewShell::ShellType,
279 : OUStringHash>
280 : {
281 : public:
282 38 : ViewURLMap (void) {}
283 : };
284 :
285 : //----- Framework::DiposeListener ---------------------------------------------
286 :
287 : namespace {
288 : typedef ::cppu::WeakComponentImplHelper1 <
289 : ::com::sun::star::lang::XEventListener
290 : > FrameworkHelperDisposeListenerInterfaceBase;
291 : }
292 :
293 : class FrameworkHelper::DisposeListener
294 : : public ::sd::MutexOwner,
295 : public FrameworkHelperDisposeListenerInterfaceBase
296 : {
297 : public:
298 : DisposeListener (const ::boost::shared_ptr<FrameworkHelper>& rpHelper);
299 : virtual ~DisposeListener (void);
300 :
301 : virtual void SAL_CALL disposing (void) SAL_OVERRIDE;
302 :
303 : virtual void SAL_CALL disposing (const lang::EventObject& rEventObject)
304 : throw(RuntimeException, std::exception) SAL_OVERRIDE;
305 :
306 : private:
307 : ::boost::shared_ptr<FrameworkHelper> mpHelper;
308 : };
309 :
310 : //----- FrameworkHelper::Deleter ----------------------------------------------
311 :
312 : class FrameworkHelper::Deleter
313 : {
314 : public:
315 212 : void operator()(FrameworkHelper* pObject)
316 : {
317 212 : delete pObject;
318 212 : }
319 : };
320 :
321 : //----- FrameworkHelper -------------------------------------------------------
322 :
323 38 : ::boost::scoped_ptr<FrameworkHelper::ViewURLMap> FrameworkHelper::mpViewURLMap(new ViewURLMap());
324 :
325 38 : FrameworkHelper::InstanceMap FrameworkHelper::maInstanceMap;
326 :
327 0 : ::boost::shared_ptr<FrameworkHelper> FrameworkHelper::Instance (
328 : const Reference<frame::XController>& rxController)
329 : {
330 : // Tunnel through the controller to obtain a ViewShellBase.
331 0 : Reference<lang::XUnoTunnel> xTunnel (rxController, UNO_QUERY);
332 0 : if (xTunnel.is())
333 : {
334 : ::sd::DrawController* pController = reinterpret_cast<sd::DrawController*>(
335 0 : xTunnel->getSomething(sd::DrawController::getUnoTunnelId()));
336 0 : if (pController != NULL)
337 : {
338 0 : ViewShellBase* pBase = pController->GetViewShellBase();
339 0 : if (pBase != NULL)
340 0 : return Instance(*pBase);
341 : }
342 : }
343 :
344 0 : return ::boost::shared_ptr<FrameworkHelper>();
345 : }
346 :
347 13688 : ::boost::shared_ptr<FrameworkHelper> FrameworkHelper::Instance (ViewShellBase& rBase)
348 : {
349 :
350 13688 : ::boost::shared_ptr<FrameworkHelper> pHelper;
351 :
352 13688 : InstanceMap::const_iterator iHelper (maInstanceMap.find(&rBase));
353 13688 : if (iHelper == maInstanceMap.end())
354 : {
355 : ::osl::GetGlobalMutex aMutexFunctor;
356 212 : ::osl::MutexGuard aGuard (aMutexFunctor());
357 212 : if (iHelper == maInstanceMap.end())
358 : {
359 636 : pHelper = ::boost::shared_ptr<FrameworkHelper>(
360 212 : new FrameworkHelper(rBase),
361 212 : FrameworkHelper::Deleter());
362 212 : pHelper->Initialize();
363 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
364 212 : maInstanceMap[&rBase] = pHelper;
365 212 : }
366 : }
367 : else
368 : {
369 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
370 13476 : pHelper = iHelper->second;
371 : }
372 :
373 13688 : return pHelper;
374 : }
375 :
376 212 : void FrameworkHelper::DisposeInstance (ViewShellBase& rBase)
377 : {
378 212 : InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
379 212 : if (iHelper != maInstanceMap.end())
380 : {
381 212 : iHelper->second->Dispose();
382 : }
383 212 : }
384 :
385 212 : void FrameworkHelper::ReleaseInstance (ViewShellBase& rBase)
386 : {
387 212 : InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
388 212 : if (iHelper != maInstanceMap.end())
389 212 : maInstanceMap.erase(iHelper);
390 212 : }
391 :
392 212 : FrameworkHelper::FrameworkHelper (ViewShellBase& rBase)
393 : : mrBase(rBase),
394 : mxConfigurationController(),
395 212 : mxDisposeListener()
396 :
397 : {
398 212 : Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY);
399 212 : if (xControllerManager.is())
400 : {
401 212 : mxConfigurationController = xControllerManager->getConfigurationController();
402 : }
403 :
404 212 : new LifetimeController(mrBase);
405 212 : }
406 :
407 212 : void FrameworkHelper::Initialize (void)
408 : {
409 212 : mxDisposeListener = new DisposeListener(shared_from_this());
410 212 : }
411 :
412 424 : FrameworkHelper::~FrameworkHelper (void)
413 : {
414 424 : }
415 :
416 212 : void FrameworkHelper::Dispose (void)
417 : {
418 212 : if (mxDisposeListener.is())
419 212 : mxDisposeListener->dispose();
420 212 : mxConfigurationController = NULL;
421 212 : }
422 :
423 0 : bool FrameworkHelper::IsValid (void)
424 : {
425 0 : return mxConfigurationController.is();
426 : }
427 :
428 12464 : ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const OUString& rsPaneURL)
429 : {
430 12464 : if ( !mxConfigurationController.is() )
431 2664 : return ::boost::shared_ptr<ViewShell>();
432 :
433 9800 : Reference<XResourceId> xPaneId( CreateResourceId( rsPaneURL ) );
434 9800 : return lcl_getViewShell( lcl_getFirstViewInPane( mxConfigurationController, xPaneId ) );
435 : }
436 :
437 252 : ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const Reference<XView>& rxView)
438 : {
439 252 : return lcl_getViewShell( rxView.get() );
440 : }
441 :
442 434 : Reference<XView> FrameworkHelper::GetView (const Reference<XResourceId>& rxPaneOrViewId)
443 : {
444 434 : Reference<XView> xView;
445 :
446 434 : if ( ! rxPaneOrViewId.is() || ! mxConfigurationController.is())
447 0 : return NULL;
448 :
449 : try
450 : {
451 434 : if (rxPaneOrViewId->getResourceURL().match(msViewURLPrefix))
452 : {
453 0 : xView.set( mxConfigurationController->getResource( rxPaneOrViewId ), UNO_QUERY );
454 : }
455 : else
456 : {
457 434 : xView.set( lcl_getFirstViewInPane( mxConfigurationController, rxPaneOrViewId ), UNO_QUERY );
458 : }
459 : }
460 0 : catch (lang::DisposedException&)
461 : {
462 0 : Dispose();
463 : }
464 0 : catch (RuntimeException&)
465 : {
466 : }
467 :
468 434 : return xView;
469 : }
470 :
471 52 : Reference<XResourceId> FrameworkHelper::RequestView (
472 : const OUString& rsResourceURL,
473 : const OUString& rsAnchorURL)
474 : {
475 52 : Reference<XResourceId> xViewId;
476 :
477 : try
478 : {
479 52 : if (mxConfigurationController.is())
480 : {
481 52 : mxConfigurationController->requestResourceActivation(
482 : CreateResourceId(rsAnchorURL),
483 52 : ResourceActivationMode_ADD);
484 52 : xViewId = CreateResourceId(rsResourceURL, rsAnchorURL);
485 52 : mxConfigurationController->requestResourceActivation(
486 : xViewId,
487 52 : ResourceActivationMode_REPLACE);
488 : }
489 : }
490 0 : catch (lang::DisposedException&)
491 : {
492 0 : Dispose();
493 0 : xViewId = NULL;
494 : }
495 0 : catch (RuntimeException&)
496 : {
497 0 : xViewId = NULL;
498 : }
499 :
500 52 : return xViewId;
501 : }
502 :
503 126 : ViewShell::ShellType FrameworkHelper::GetViewId (const OUString& rsViewURL)
504 : {
505 126 : if (mpViewURLMap->empty())
506 : {
507 16 : (*mpViewURLMap)[msImpressViewURL] = ViewShell::ST_IMPRESS;
508 16 : (*mpViewURLMap)[msDrawViewURL] = ViewShell::ST_DRAW;
509 16 : (*mpViewURLMap)[msOutlineViewURL] = ViewShell::ST_OUTLINE;
510 16 : (*mpViewURLMap)[msNotesViewURL] = ViewShell::ST_NOTES;
511 16 : (*mpViewURLMap)[msHandoutViewURL] = ViewShell::ST_HANDOUT;
512 16 : (*mpViewURLMap)[msSlideSorterURL] = ViewShell::ST_SLIDE_SORTER;
513 16 : (*mpViewURLMap)[msPresentationViewURL] = ViewShell::ST_PRESENTATION;
514 16 : (*mpViewURLMap)[msSidebarViewURL] = ViewShell::ST_SIDEBAR;
515 : }
516 126 : ViewURLMap::const_iterator iView (mpViewURLMap->find(rsViewURL));
517 126 : if (iView != mpViewURLMap->end())
518 126 : return iView->second;
519 : else
520 0 : return ViewShell::ST_NONE;
521 : }
522 :
523 0 : OUString FrameworkHelper::GetViewURL (ViewShell::ShellType eType)
524 : {
525 0 : switch (eType)
526 : {
527 0 : case ViewShell::ST_IMPRESS : return msImpressViewURL;
528 0 : case ViewShell::ST_DRAW : return msDrawViewURL;
529 0 : case ViewShell::ST_OUTLINE : return msOutlineViewURL;
530 0 : case ViewShell::ST_NOTES : return msNotesViewURL;
531 0 : case ViewShell::ST_HANDOUT : return msHandoutViewURL;
532 0 : case ViewShell::ST_SLIDE_SORTER : return msSlideSorterURL;
533 0 : case ViewShell::ST_PRESENTATION : return msPresentationViewURL;
534 0 : case ViewShell::ST_SIDEBAR : return msSidebarViewURL;
535 : default:
536 0 : return OUString();
537 : }
538 : }
539 :
540 0 : void FrameworkHelper::HandleModeChangeSlot (
541 : sal_uLong nSlotId,
542 : SfxRequest& rRequest)
543 : {
544 0 : bool bIsActive = true;
545 :
546 0 : if ( ! mxConfigurationController.is())
547 0 : return;
548 :
549 0 : switch (nSlotId)
550 : {
551 : case SID_DRAWINGMODE:
552 : case SID_NOTESMODE:
553 : case SID_HANDOUTMODE:
554 : case SID_DIAMODE:
555 : case SID_OUTLINEMODE:
556 : {
557 0 : const SfxItemSet* pRequestArguments = rRequest.GetArgs();
558 0 : if (pRequestArguments)
559 : {
560 0 : SFX_REQUEST_ARG (rRequest,
561 : pIsActive,
562 : SfxBoolItem,
563 : (sal_uInt16)nSlotId,
564 : false);
565 0 : bIsActive = pIsActive->GetValue ();
566 : }
567 : }
568 0 : break;
569 : }
570 :
571 : try
572 : {
573 0 : if ( ! mxConfigurationController.is())
574 0 : throw RuntimeException();
575 :
576 : Reference<XResourceId> xPaneId (
577 0 : CreateResourceId(framework::FrameworkHelper::msCenterPaneURL));
578 0 : Reference<XView> xView (GetView(xPaneId));
579 0 : ::boost::shared_ptr<ViewShell> pCenterViewShell (GetViewShell(xView));
580 :
581 0 : OUString sRequestedView;
582 0 : if (bIsActive)
583 : {
584 0 : switch (nSlotId)
585 : {
586 : case SID_NORMAL_MULTI_PANE_GUI:
587 : case SID_DRAWINGMODE:
588 0 : sRequestedView = FrameworkHelper::msImpressViewURL;
589 0 : break;
590 :
591 : case SID_NOTESMODE:
592 0 : sRequestedView = FrameworkHelper::msNotesViewURL;
593 0 : break;
594 :
595 : case SID_HANDOUTMODE:
596 0 : sRequestedView = FrameworkHelper::msHandoutViewURL;
597 0 : break;
598 :
599 : case SID_SLIDE_SORTER_MULTI_PANE_GUI:
600 : case SID_DIAMODE:
601 0 : sRequestedView = FrameworkHelper::msSlideSorterURL;
602 0 : break;
603 :
604 : case SID_OUTLINEMODE:
605 0 : sRequestedView = FrameworkHelper::msOutlineViewURL;
606 0 : break;
607 : }
608 : }
609 :
610 0 : if (xView.is()
611 0 : && xView->getResourceId()->getResourceURL().equals(sRequestedView))
612 : {
613 : // We do not have to switch the view shell but maybe the edit mode
614 : // has changed.
615 : DrawViewShell* pDrawViewShell
616 0 : = dynamic_cast<DrawViewShell*>(pCenterViewShell.get());
617 0 : if (pDrawViewShell != NULL)
618 : {
619 0 : pCenterViewShell->Broadcast (
620 0 : ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_START));
621 :
622 : pDrawViewShell->ChangeEditMode (
623 0 : EM_PAGE, pDrawViewShell->IsLayerModeActive());
624 :
625 0 : pCenterViewShell->Broadcast (
626 0 : ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_END));
627 : }
628 : }
629 : else
630 : {
631 0 : mxConfigurationController->requestResourceActivation(
632 : CreateResourceId(sRequestedView, msCenterPaneURL),
633 0 : ResourceActivationMode_REPLACE);
634 0 : }
635 : }
636 0 : catch (RuntimeException&)
637 : {
638 : DBG_UNHANDLED_EXCEPTION();
639 : }
640 : }
641 :
642 0 : void FrameworkHelper::RunOnConfigurationEvent(
643 : const OUString& rsEventType,
644 : const Callback& rCallback)
645 : {
646 : RunOnEvent(
647 : rsEventType,
648 : FrameworkHelperAllPassFilter(),
649 0 : rCallback);
650 0 : }
651 :
652 0 : void FrameworkHelper::RunOnResourceActivation(
653 : const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
654 : const Callback& rCallback)
655 : {
656 0 : if (mxConfigurationController.is()
657 0 : && mxConfigurationController->getResource(rxResourceId).is())
658 : {
659 0 : rCallback(false);
660 : }
661 : else
662 : {
663 : RunOnEvent(
664 : msResourceActivationEvent,
665 : FrameworkHelperResourceIdFilter(rxResourceId),
666 0 : rCallback);
667 : }
668 0 : }
669 :
670 : /** A callback that sets a flag to a specified value when the callback is
671 : called.
672 : */
673 : class FlagUpdater
674 : {
675 : public:
676 0 : FlagUpdater (bool& rFlag) : mrFlag(rFlag) {}
677 0 : void operator() (bool) const {mrFlag = true;}
678 : private:
679 : bool& mrFlag;
680 : };
681 :
682 0 : void FrameworkHelper::RequestSynchronousUpdate (void)
683 : {
684 : rtl::Reference<ConfigurationController> pCC (
685 0 : dynamic_cast<ConfigurationController*>(mxConfigurationController.get()));
686 0 : if (pCC.is())
687 0 : pCC->RequestSynchronousUpdate();
688 0 : }
689 :
690 0 : void FrameworkHelper::WaitForEvent (const OUString& rsEventType) const
691 : {
692 0 : bool bConfigurationUpdateSeen (false);
693 :
694 : RunOnEvent(
695 : rsEventType,
696 : FrameworkHelperAllPassFilter(),
697 0 : FlagUpdater(bConfigurationUpdateSeen));
698 :
699 0 : sal_uInt32 nStartTime = osl_getGlobalTimer();
700 0 : while ( ! bConfigurationUpdateSeen)
701 : {
702 0 : Application::Reschedule();
703 :
704 0 : if( (osl_getGlobalTimer() - nStartTime) > 60000 )
705 : {
706 : OSL_FAIL("FrameworkHelper::WaitForEvent(), no event for a minute? giving up!");
707 0 : break;
708 : }
709 : }
710 0 : }
711 :
712 0 : void FrameworkHelper::WaitForUpdate (void) const
713 : {
714 0 : WaitForEvent(msConfigurationUpdateEndEvent);
715 0 : }
716 :
717 0 : void FrameworkHelper::RunOnEvent(
718 : const OUString& rsEventType,
719 : const ConfigurationChangeEventFilter& rFilter,
720 : const Callback& rCallback) const
721 : {
722 0 : new CallbackCaller(mrBase,rsEventType,rFilter,rCallback);
723 0 : }
724 :
725 212 : void FrameworkHelper::disposing (const lang::EventObject& rEventObject)
726 : {
727 212 : if (rEventObject.Source == mxConfigurationController)
728 212 : mxConfigurationController = NULL;
729 212 : }
730 :
731 504 : void FrameworkHelper::UpdateConfiguration (void)
732 : {
733 504 : if (mxConfigurationController.is())
734 : {
735 : try
736 : {
737 252 : if (mxConfigurationController.is())
738 252 : mxConfigurationController->update();
739 : }
740 0 : catch (lang::DisposedException&)
741 : {
742 0 : Dispose();
743 : }
744 0 : catch (RuntimeException&)
745 : {
746 : DBG_UNHANDLED_EXCEPTION();
747 : }
748 : }
749 504 : }
750 :
751 0 : OUString FrameworkHelper::ResourceIdToString (const Reference<XResourceId>& rxResourceId)
752 : {
753 0 : OUString sString;
754 0 : if (rxResourceId.is())
755 : {
756 0 : sString += rxResourceId->getResourceURL();
757 0 : if (rxResourceId->hasAnchor())
758 : {
759 0 : Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
760 0 : for (sal_Int32 nIndex=0; nIndex < aAnchorURLs.getLength(); ++nIndex)
761 : {
762 0 : sString += " | ";
763 0 : sString += aAnchorURLs[nIndex];
764 0 : }
765 : }
766 : }
767 0 : return sString;
768 : }
769 :
770 11532 : Reference<XResourceId> FrameworkHelper::CreateResourceId (const OUString& rsResourceURL)
771 : {
772 11532 : return new ::sd::framework::ResourceId(rsResourceURL);
773 : }
774 :
775 728 : Reference<XResourceId> FrameworkHelper::CreateResourceId (
776 : const OUString& rsResourceURL,
777 : const OUString& rsAnchorURL)
778 : {
779 728 : return new ::sd::framework::ResourceId(rsResourceURL, rsAnchorURL);
780 : }
781 :
782 420 : Reference<XResourceId> FrameworkHelper::CreateResourceId (
783 : const OUString& rsResourceURL,
784 : const Reference<XResourceId>& rxAnchorId)
785 : {
786 420 : if (rxAnchorId.is())
787 : return new ::sd::framework::ResourceId(
788 : rsResourceURL,
789 420 : rxAnchorId->getResourceURL(),
790 420 : rxAnchorId->getAnchorURLs());
791 : else
792 0 : return new ::sd::framework::ResourceId(rsResourceURL);
793 : }
794 :
795 : //----- FrameworkHelper::DisposeListener --------------------------------------
796 :
797 212 : FrameworkHelper::DisposeListener::DisposeListener (
798 : const ::boost::shared_ptr<FrameworkHelper>& rpHelper)
799 : : FrameworkHelperDisposeListenerInterfaceBase(maMutex),
800 212 : mpHelper(rpHelper)
801 : {
802 212 : Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
803 212 : if (xComponent.is())
804 212 : xComponent->addEventListener(this);
805 212 : }
806 :
807 424 : FrameworkHelper::DisposeListener::~DisposeListener (void)
808 : {
809 424 : }
810 :
811 212 : void SAL_CALL FrameworkHelper::DisposeListener::disposing (void)
812 : {
813 212 : Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
814 212 : if (xComponent.is())
815 0 : xComponent->removeEventListener(this);
816 :
817 212 : mpHelper.reset();
818 212 : }
819 :
820 212 : void SAL_CALL FrameworkHelper::DisposeListener::disposing (const lang::EventObject& rEventObject)
821 : throw(RuntimeException, std::exception)
822 : {
823 212 : if (mpHelper.get() != NULL)
824 212 : mpHelper->disposing(rEventObject);
825 212 : }
826 :
827 : //===== FrameworkHelperResourceIdFilter =======================================
828 :
829 0 : FrameworkHelperResourceIdFilter::FrameworkHelperResourceIdFilter (
830 : const Reference<XResourceId>& rxResourceId)
831 0 : : mxResourceId(rxResourceId)
832 : {
833 0 : }
834 :
835 : } } // end of namespace sd::framework
836 :
837 : namespace {
838 :
839 : //===== CallbackCaller ========================================================
840 :
841 0 : CallbackCaller::CallbackCaller (
842 : ::sd::ViewShellBase& rBase,
843 : const OUString& rsEventType,
844 : const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter,
845 : const ::sd::framework::FrameworkHelper::Callback& rCallback)
846 : : CallbackCallerInterfaceBase(MutexOwner::maMutex),
847 : msEventType(rsEventType),
848 : mxConfigurationController(),
849 : maFilter(rFilter),
850 0 : maCallback(rCallback)
851 : {
852 : try
853 : {
854 0 : Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY_THROW);
855 0 : mxConfigurationController = xControllerManager->getConfigurationController();
856 0 : if (mxConfigurationController.is())
857 : {
858 0 : if (mxConfigurationController->hasPendingRequests())
859 0 : mxConfigurationController->addConfigurationChangeListener(this,msEventType,Any());
860 : else
861 : {
862 : // There are no requests waiting to be processed. Therefore
863 : // no event, especially not the one we are waiting for, will
864 : // be sent in the near future and the callback would never be
865 : // called.
866 : // Call the callback now and tell him that the event it is
867 : // waiting for was not sent.
868 0 : mxConfigurationController = NULL;
869 0 : maCallback(false);
870 : }
871 0 : }
872 : }
873 0 : catch (RuntimeException&)
874 : {
875 : DBG_UNHANDLED_EXCEPTION();
876 : }
877 0 : }
878 :
879 0 : CallbackCaller::~CallbackCaller (void)
880 : {
881 0 : }
882 :
883 0 : void CallbackCaller::disposing (void)
884 : {
885 : try
886 : {
887 0 : if (mxConfigurationController.is())
888 : {
889 0 : Reference<XConfigurationController> xCC (mxConfigurationController);
890 0 : mxConfigurationController = NULL;
891 0 : xCC->removeConfigurationChangeListener(this);
892 : }
893 : }
894 0 : catch (RuntimeException&)
895 : {
896 : DBG_UNHANDLED_EXCEPTION();
897 : }
898 0 : }
899 :
900 0 : void SAL_CALL CallbackCaller::disposing (const lang::EventObject& rEvent)
901 : throw (RuntimeException, std::exception)
902 : {
903 0 : if (rEvent.Source == mxConfigurationController)
904 : {
905 0 : mxConfigurationController = NULL;
906 0 : maCallback(false);
907 : }
908 0 : }
909 :
910 0 : void SAL_CALL CallbackCaller::notifyConfigurationChange (
911 : const ConfigurationChangeEvent& rEvent)
912 : throw (RuntimeException, std::exception)
913 : {
914 0 : if (rEvent.Type.equals(msEventType) && maFilter(rEvent))
915 : {
916 0 : maCallback(true);
917 0 : if (mxConfigurationController.is())
918 : {
919 : // Reset the reference to the configuration controller so that
920 : // dispose() will not try to remove the listener a second time.
921 0 : Reference<XConfigurationController> xCC (mxConfigurationController);
922 0 : mxConfigurationController = NULL;
923 :
924 : // Removing this object from the controller may very likely lead
925 : // to its destruction, so no calls after that.
926 0 : xCC->removeConfigurationChangeListener(this);
927 : }
928 : }
929 0 : }
930 :
931 : //----- LifetimeController -------------------------------------------------
932 :
933 212 : LifetimeController::LifetimeController (::sd::ViewShellBase& rBase)
934 : : LifetimeControllerInterfaceBase(maMutex),
935 : mrBase(rBase),
936 : mbListeningToViewShellBase(false),
937 212 : mbListeningToController(false)
938 : {
939 : // Register as listener at the ViewShellBase. Because that is not done
940 : // via a reference we have to increase the reference count manually.
941 : // This is necessary even though listening to the XController did
942 : // increase the reference count because the controller may release its
943 : // reference to us before the ViewShellBase is destroyed.
944 212 : StartListening(mrBase);
945 212 : acquire();
946 212 : mbListeningToViewShellBase = true;
947 :
948 212 : Reference<XComponent> xComponent (rBase.GetController(), UNO_QUERY);
949 212 : if (xComponent.is())
950 : {
951 212 : xComponent->addEventListener(this);
952 212 : mbListeningToController = true;
953 212 : }
954 212 : }
955 :
956 424 : LifetimeController::~LifetimeController (void)
957 : {
958 : OSL_ASSERT(!mbListeningToController && !mbListeningToViewShellBase);
959 424 : }
960 :
961 212 : void LifetimeController::disposing (void)
962 : {
963 212 : }
964 :
965 212 : void SAL_CALL LifetimeController::disposing (const lang::EventObject& rEvent)
966 : throw(RuntimeException, std::exception)
967 : {
968 : (void)rEvent;
969 212 : mbListeningToController = false;
970 212 : Update();
971 212 : }
972 :
973 212 : void LifetimeController::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
974 : {
975 : (void)rBroadcaster;
976 212 : const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
977 212 : if (pSimpleHint != NULL && pSimpleHint->GetId() == SFX_HINT_DYING)
978 : {
979 212 : mbListeningToViewShellBase = false;
980 212 : Update();
981 212 : release();
982 : }
983 212 : }
984 :
985 424 : void LifetimeController::Update (void)
986 : {
987 424 : if (mbListeningToViewShellBase && mbListeningToController)
988 : {
989 : // Both the controller and the ViewShellBase are alive. Keep
990 : // waiting for their destruction.
991 : }
992 424 : else if (mbListeningToViewShellBase)
993 : {
994 : // The controller has been destroyed but the ViewShellBase is still
995 : // alive. Dispose the associated FrameworkHelper but keep it around
996 : // so that no new instance is created for the dying framework.
997 212 : ::sd::framework::FrameworkHelper::DisposeInstance(mrBase);
998 : }
999 : else
1000 : {
1001 : // Both the controller and the ViewShellBase have been destroyed.
1002 : // Remove the FrameworkHelper so that the next call its Instance()
1003 : // method can create a new instance.
1004 212 : ::sd::framework::FrameworkHelper::ReleaseInstance(mrBase);
1005 : }
1006 424 : }
1007 :
1008 114 : } // end of anonymous namespace.
1009 :
1010 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|