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 <unordered_map>
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();
95 :
96 : virtual void SAL_CALL disposing() 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();
130 :
131 : virtual void SAL_CALL disposing() 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();
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 22 : const OUString FrameworkHelper::msPaneURLPrefix("private:resource/pane/");
184 22 : const OUString FrameworkHelper::msCenterPaneURL( msPaneURLPrefix + "CenterPane");
185 22 : const OUString FrameworkHelper::msFullScreenPaneURL( msPaneURLPrefix + "FullScreenPane");
186 22 : const OUString FrameworkHelper::msLeftImpressPaneURL( msPaneURLPrefix + "LeftImpressPane");
187 22 : const OUString FrameworkHelper::msLeftDrawPaneURL( msPaneURLPrefix + "LeftDrawPane");
188 22 : const OUString FrameworkHelper::msSidebarPaneURL( msPaneURLPrefix + "SidebarPane");
189 :
190 : // View URLs.
191 :
192 22 : const OUString FrameworkHelper::msViewURLPrefix("private:resource/view/");
193 22 : const OUString FrameworkHelper::msImpressViewURL( msViewURLPrefix + "ImpressView");
194 22 : const OUString FrameworkHelper::msDrawViewURL( msViewURLPrefix + "GraphicView");
195 22 : const OUString FrameworkHelper::msOutlineViewURL( msViewURLPrefix + "OutlineView");
196 22 : const OUString FrameworkHelper::msNotesViewURL( msViewURLPrefix + "NotesView");
197 22 : const OUString FrameworkHelper::msHandoutViewURL( msViewURLPrefix + "HandoutView");
198 22 : const OUString FrameworkHelper::msSlideSorterURL( msViewURLPrefix + "SlideSorter");
199 22 : const OUString FrameworkHelper::msPresentationViewURL( msViewURLPrefix + "PresentationView");
200 22 : const OUString FrameworkHelper::msSidebarViewURL( msViewURLPrefix + "SidebarView");
201 :
202 : // Tool bar URLs.
203 :
204 22 : const OUString FrameworkHelper::msToolBarURLPrefix("private:resource/toolbar/");
205 22 : const OUString FrameworkHelper::msViewTabBarURL( msToolBarURLPrefix + "ViewTabBar");
206 :
207 : // Task panel URLs.
208 22 : const OUString FrameworkHelper::msTaskPanelURLPrefix( "private:resource/toolpanel/" );
209 22 : const OUString FrameworkHelper::msAllMasterPagesTaskPanelURL( msTaskPanelURLPrefix + "AllMasterPages" );
210 22 : const OUString FrameworkHelper::msRecentMasterPagesTaskPanelURL( msTaskPanelURLPrefix + "RecentMasterPages" );
211 22 : const OUString FrameworkHelper::msUsedMasterPagesTaskPanelURL( msTaskPanelURLPrefix + "UsedMasterPages" );
212 22 : const OUString FrameworkHelper::msLayoutTaskPanelURL( msTaskPanelURLPrefix + "Layouts" );
213 22 : const OUString FrameworkHelper::msTableDesignPanelURL( msTaskPanelURLPrefix + "TableDesign" );
214 22 : const OUString FrameworkHelper::msCustomAnimationTaskPanelURL( msTaskPanelURLPrefix + "CustomAnimations" );
215 22 : const OUString FrameworkHelper::msSlideTransitionTaskPanelURL( msTaskPanelURLPrefix + "SlideTransitions" );
216 :
217 : // Event URLs.
218 22 : const OUString FrameworkHelper::msResourceActivationRequestEvent( "ResourceActivationRequested" );
219 22 : const OUString FrameworkHelper::msResourceDeactivationRequestEvent( "ResourceDeactivationRequest" );
220 22 : const OUString FrameworkHelper::msResourceActivationEvent( "ResourceActivation" );
221 22 : const OUString FrameworkHelper::msResourceDeactivationEvent( "ResourceDeactivation" );
222 22 : const OUString FrameworkHelper::msResourceDeactivationEndEvent( "ResourceDeactivationEnd" );
223 22 : const OUString FrameworkHelper::msConfigurationUpdateStartEvent( "ConfigurationUpdateStart" );
224 22 : const OUString FrameworkHelper::msConfigurationUpdateEndEvent( "ConfigurationUpdateEnd" );
225 :
226 : // Service names of controllers.
227 22 : const OUString FrameworkHelper::msModuleControllerService("com.sun.star.drawing.framework.ModuleController");
228 22 : const OUString FrameworkHelper::msConfigurationControllerService("com.sun.star.drawing.framework.ConfigurationController");
229 :
230 : //----- helper ----------------------------------------------------------------
231 : namespace
232 : {
233 6587 : static ::boost::shared_ptr< ViewShell > lcl_getViewShell( const Reference< XResource >& i_rViewShellWrapper )
234 : {
235 6587 : ::boost::shared_ptr< ViewShell > pViewShell;
236 6587 : if ( !i_rViewShellWrapper.is() )
237 852 : return pViewShell;
238 :
239 : try
240 : {
241 5735 : Reference<lang::XUnoTunnel> xViewTunnel( i_rViewShellWrapper, UNO_QUERY_THROW );
242 11470 : pViewShell = reinterpret_cast< ViewShellWrapper* >(
243 17205 : xViewTunnel->getSomething( ViewShellWrapper::getUnoTunnelId() ) )->GetViewShell();
244 : }
245 0 : catch( const Exception& )
246 : {
247 : DBG_UNHANDLED_EXCEPTION();
248 : }
249 5735 : return pViewShell;
250 : }
251 6759 : Reference< XResource > lcl_getFirstViewInPane( const Reference< XConfigurationController >& i_rConfigController,
252 : const Reference< XResourceId >& i_rPaneId )
253 : {
254 : try
255 : {
256 6759 : Reference< XConfiguration > xConfiguration( i_rConfigController->getRequestedConfiguration(), UNO_SET_THROW );
257 6759 : Sequence< Reference< XResourceId > > aViewIds( xConfiguration->getResources(
258 7312 : i_rPaneId, FrameworkHelper::msViewURLPrefix, AnchorBindingMode_DIRECT ) );
259 6759 : if ( aViewIds.getLength() > 0 )
260 6759 : return i_rConfigController->getResource( aViewIds[0] );
261 : }
262 0 : catch( const Exception& )
263 : {
264 : DBG_UNHANDLED_EXCEPTION();
265 : }
266 553 : 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 22 : class FrameworkHelper::ViewURLMap
276 : : public std::unordered_map<
277 : OUString,
278 : ViewShell::ShellType,
279 : OUStringHash>
280 : {
281 : public:
282 22 : ViewURLMap() {}
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();
300 :
301 : virtual void SAL_CALL disposing() 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 127 : void operator()(FrameworkHelper* pObject)
316 : {
317 127 : delete pObject;
318 127 : }
319 : };
320 :
321 : //----- FrameworkHelper -------------------------------------------------------
322 :
323 22 : ::boost::scoped_ptr<FrameworkHelper::ViewURLMap> FrameworkHelper::mpViewURLMap(new ViewURLMap());
324 :
325 22 : FrameworkHelper::InstanceMap FrameworkHelper::maInstanceMap;
326 :
327 8744 : ::boost::shared_ptr<FrameworkHelper> FrameworkHelper::Instance (ViewShellBase& rBase)
328 : {
329 :
330 8744 : ::boost::shared_ptr<FrameworkHelper> pHelper;
331 :
332 8744 : InstanceMap::const_iterator iHelper (maInstanceMap.find(&rBase));
333 8744 : if (iHelper == maInstanceMap.end())
334 : {
335 : ::osl::GetGlobalMutex aMutexFunctor;
336 127 : ::osl::MutexGuard aGuard (aMutexFunctor());
337 127 : if (iHelper == maInstanceMap.end())
338 : {
339 381 : pHelper = ::boost::shared_ptr<FrameworkHelper>(
340 127 : new FrameworkHelper(rBase),
341 127 : FrameworkHelper::Deleter());
342 127 : pHelper->Initialize();
343 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
344 127 : maInstanceMap[&rBase] = pHelper;
345 127 : }
346 : }
347 : else
348 : {
349 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
350 8617 : pHelper = iHelper->second;
351 : }
352 :
353 8744 : return pHelper;
354 : }
355 :
356 127 : void FrameworkHelper::DisposeInstance (ViewShellBase& rBase)
357 : {
358 127 : InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
359 127 : if (iHelper != maInstanceMap.end())
360 : {
361 127 : iHelper->second->Dispose();
362 : }
363 127 : }
364 :
365 127 : void FrameworkHelper::ReleaseInstance (ViewShellBase& rBase)
366 : {
367 127 : InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
368 127 : if (iHelper != maInstanceMap.end())
369 127 : maInstanceMap.erase(iHelper);
370 127 : }
371 :
372 127 : FrameworkHelper::FrameworkHelper (ViewShellBase& rBase)
373 : : mrBase(rBase),
374 : mxConfigurationController(),
375 127 : mxDisposeListener()
376 :
377 : {
378 127 : Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY);
379 127 : if (xControllerManager.is())
380 : {
381 127 : mxConfigurationController = xControllerManager->getConfigurationController();
382 : }
383 :
384 127 : new LifetimeController(mrBase);
385 127 : }
386 :
387 127 : void FrameworkHelper::Initialize()
388 : {
389 127 : mxDisposeListener = new DisposeListener(shared_from_this());
390 127 : }
391 :
392 254 : FrameworkHelper::~FrameworkHelper()
393 : {
394 254 : }
395 :
396 127 : void FrameworkHelper::Dispose()
397 : {
398 127 : if (mxDisposeListener.is())
399 127 : mxDisposeListener->dispose();
400 127 : mxConfigurationController = NULL;
401 127 : }
402 :
403 0 : bool FrameworkHelper::IsValid()
404 : {
405 0 : return mxConfigurationController.is();
406 : }
407 :
408 7982 : ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const OUString& rsPaneURL)
409 : {
410 7982 : if ( !mxConfigurationController.is() )
411 1527 : return ::boost::shared_ptr<ViewShell>();
412 :
413 6455 : Reference<XResourceId> xPaneId( CreateResourceId( rsPaneURL ) );
414 6455 : return lcl_getViewShell( lcl_getFirstViewInPane( mxConfigurationController, xPaneId ) );
415 : }
416 :
417 132 : ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const Reference<XView>& rxView)
418 : {
419 132 : return lcl_getViewShell( rxView.get() );
420 : }
421 :
422 304 : Reference<XView> FrameworkHelper::GetView (const Reference<XResourceId>& rxPaneOrViewId)
423 : {
424 304 : Reference<XView> xView;
425 :
426 304 : if ( ! rxPaneOrViewId.is() || ! mxConfigurationController.is())
427 0 : return NULL;
428 :
429 : try
430 : {
431 304 : if (rxPaneOrViewId->getResourceURL().match(msViewURLPrefix))
432 : {
433 0 : xView.set( mxConfigurationController->getResource( rxPaneOrViewId ), UNO_QUERY );
434 : }
435 : else
436 : {
437 304 : xView.set( lcl_getFirstViewInPane( mxConfigurationController, rxPaneOrViewId ), UNO_QUERY );
438 : }
439 : }
440 0 : catch (lang::DisposedException&)
441 : {
442 0 : Dispose();
443 : }
444 0 : catch (RuntimeException&)
445 : {
446 : }
447 :
448 304 : return xView;
449 : }
450 :
451 47 : Reference<XResourceId> FrameworkHelper::RequestView (
452 : const OUString& rsResourceURL,
453 : const OUString& rsAnchorURL)
454 : {
455 47 : Reference<XResourceId> xViewId;
456 :
457 : try
458 : {
459 47 : if (mxConfigurationController.is())
460 : {
461 47 : mxConfigurationController->requestResourceActivation(
462 : CreateResourceId(rsAnchorURL),
463 47 : ResourceActivationMode_ADD);
464 47 : xViewId = CreateResourceId(rsResourceURL, rsAnchorURL);
465 47 : mxConfigurationController->requestResourceActivation(
466 : xViewId,
467 47 : ResourceActivationMode_REPLACE);
468 : }
469 : }
470 0 : catch (lang::DisposedException&)
471 : {
472 0 : Dispose();
473 0 : xViewId = NULL;
474 : }
475 0 : catch (RuntimeException&)
476 : {
477 0 : xViewId = NULL;
478 : }
479 :
480 47 : return xViewId;
481 : }
482 :
483 71 : ViewShell::ShellType FrameworkHelper::GetViewId (const OUString& rsViewURL)
484 : {
485 71 : if (mpViewURLMap->empty())
486 : {
487 9 : (*mpViewURLMap)[msImpressViewURL] = ViewShell::ST_IMPRESS;
488 9 : (*mpViewURLMap)[msDrawViewURL] = ViewShell::ST_DRAW;
489 9 : (*mpViewURLMap)[msOutlineViewURL] = ViewShell::ST_OUTLINE;
490 9 : (*mpViewURLMap)[msNotesViewURL] = ViewShell::ST_NOTES;
491 9 : (*mpViewURLMap)[msHandoutViewURL] = ViewShell::ST_HANDOUT;
492 9 : (*mpViewURLMap)[msSlideSorterURL] = ViewShell::ST_SLIDE_SORTER;
493 9 : (*mpViewURLMap)[msPresentationViewURL] = ViewShell::ST_PRESENTATION;
494 9 : (*mpViewURLMap)[msSidebarViewURL] = ViewShell::ST_SIDEBAR;
495 : }
496 71 : ViewURLMap::const_iterator iView (mpViewURLMap->find(rsViewURL));
497 71 : if (iView != mpViewURLMap->end())
498 70 : return iView->second;
499 : else
500 1 : return ViewShell::ST_NONE;
501 : }
502 :
503 0 : OUString FrameworkHelper::GetViewURL (ViewShell::ShellType eType)
504 : {
505 0 : switch (eType)
506 : {
507 0 : case ViewShell::ST_IMPRESS : return msImpressViewURL;
508 0 : case ViewShell::ST_DRAW : return msDrawViewURL;
509 0 : case ViewShell::ST_OUTLINE : return msOutlineViewURL;
510 0 : case ViewShell::ST_NOTES : return msNotesViewURL;
511 0 : case ViewShell::ST_HANDOUT : return msHandoutViewURL;
512 0 : case ViewShell::ST_SLIDE_SORTER : return msSlideSorterURL;
513 0 : case ViewShell::ST_PRESENTATION : return msPresentationViewURL;
514 0 : case ViewShell::ST_SIDEBAR : return msSidebarViewURL;
515 : default:
516 0 : return OUString();
517 : }
518 : }
519 :
520 0 : void FrameworkHelper::HandleModeChangeSlot (
521 : sal_uLong nSlotId,
522 : SfxRequest& rRequest)
523 : {
524 0 : bool bIsActive = true;
525 :
526 0 : if ( ! mxConfigurationController.is())
527 0 : return;
528 :
529 0 : switch (nSlotId)
530 : {
531 : case SID_DRAWINGMODE:
532 : case SID_NOTESMODE:
533 : case SID_HANDOUTMODE:
534 : case SID_DIAMODE:
535 : case SID_OUTLINEMODE:
536 : {
537 0 : const SfxItemSet* pRequestArguments = rRequest.GetArgs();
538 0 : if (pRequestArguments)
539 : {
540 0 : SFX_REQUEST_ARG (rRequest,
541 : pIsActive,
542 : SfxBoolItem,
543 : (sal_uInt16)nSlotId,
544 : false);
545 0 : bIsActive = pIsActive->GetValue ();
546 : }
547 : }
548 0 : break;
549 : }
550 :
551 : try
552 : {
553 0 : if ( ! mxConfigurationController.is())
554 0 : throw RuntimeException();
555 :
556 : Reference<XResourceId> xPaneId (
557 0 : CreateResourceId(framework::FrameworkHelper::msCenterPaneURL));
558 0 : Reference<XView> xView (GetView(xPaneId));
559 0 : ::boost::shared_ptr<ViewShell> pCenterViewShell (GetViewShell(xView));
560 :
561 0 : OUString sRequestedView;
562 0 : if (bIsActive)
563 : {
564 0 : switch (nSlotId)
565 : {
566 : case SID_NORMAL_MULTI_PANE_GUI:
567 : case SID_DRAWINGMODE:
568 0 : sRequestedView = FrameworkHelper::msImpressViewURL;
569 0 : break;
570 :
571 : case SID_NOTESMODE:
572 0 : sRequestedView = FrameworkHelper::msNotesViewURL;
573 0 : break;
574 :
575 : case SID_HANDOUTMODE:
576 0 : sRequestedView = FrameworkHelper::msHandoutViewURL;
577 0 : break;
578 :
579 : case SID_SLIDE_SORTER_MULTI_PANE_GUI:
580 : case SID_DIAMODE:
581 0 : sRequestedView = FrameworkHelper::msSlideSorterURL;
582 0 : break;
583 :
584 : case SID_OUTLINEMODE:
585 0 : sRequestedView = FrameworkHelper::msOutlineViewURL;
586 0 : break;
587 : }
588 : }
589 :
590 0 : if (xView.is()
591 0 : && xView->getResourceId()->getResourceURL().equals(sRequestedView))
592 : {
593 : // We do not have to switch the view shell but maybe the edit mode
594 : // has changed.
595 : DrawViewShell* pDrawViewShell
596 0 : = dynamic_cast<DrawViewShell*>(pCenterViewShell.get());
597 0 : if (pDrawViewShell != NULL)
598 : {
599 0 : pCenterViewShell->Broadcast (
600 0 : ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_START));
601 :
602 : pDrawViewShell->ChangeEditMode (
603 0 : EM_PAGE, pDrawViewShell->IsLayerModeActive());
604 :
605 0 : pCenterViewShell->Broadcast (
606 0 : ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_END));
607 : }
608 : }
609 : else
610 : {
611 0 : mxConfigurationController->requestResourceActivation(
612 : CreateResourceId(sRequestedView, msCenterPaneURL),
613 0 : ResourceActivationMode_REPLACE);
614 0 : }
615 : }
616 0 : catch (RuntimeException&)
617 : {
618 : DBG_UNHANDLED_EXCEPTION();
619 : }
620 : }
621 :
622 0 : void FrameworkHelper::RunOnConfigurationEvent(
623 : const OUString& rsEventType,
624 : const Callback& rCallback)
625 : {
626 : RunOnEvent(
627 : rsEventType,
628 : FrameworkHelperAllPassFilter(),
629 0 : rCallback);
630 0 : }
631 :
632 0 : void FrameworkHelper::RunOnResourceActivation(
633 : const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
634 : const Callback& rCallback)
635 : {
636 0 : if (mxConfigurationController.is()
637 0 : && mxConfigurationController->getResource(rxResourceId).is())
638 : {
639 0 : rCallback(false);
640 : }
641 : else
642 : {
643 : RunOnEvent(
644 : msResourceActivationEvent,
645 : FrameworkHelperResourceIdFilter(rxResourceId),
646 0 : rCallback);
647 : }
648 0 : }
649 :
650 : /** A callback that sets a flag to a specified value when the callback is
651 : called.
652 : */
653 : class FlagUpdater
654 : {
655 : public:
656 0 : FlagUpdater (bool& rFlag) : mrFlag(rFlag) {}
657 0 : void operator() (bool) const {mrFlag = true;}
658 : private:
659 : bool& mrFlag;
660 : };
661 :
662 6 : void FrameworkHelper::RequestSynchronousUpdate()
663 : {
664 : rtl::Reference<ConfigurationController> pCC (
665 6 : dynamic_cast<ConfigurationController*>(mxConfigurationController.get()));
666 6 : if (pCC.is())
667 6 : pCC->RequestSynchronousUpdate();
668 6 : }
669 :
670 0 : void FrameworkHelper::WaitForEvent (const OUString& rsEventType) const
671 : {
672 0 : bool bConfigurationUpdateSeen (false);
673 :
674 : RunOnEvent(
675 : rsEventType,
676 : FrameworkHelperAllPassFilter(),
677 0 : FlagUpdater(bConfigurationUpdateSeen));
678 :
679 0 : sal_uInt32 nStartTime = osl_getGlobalTimer();
680 0 : while ( ! bConfigurationUpdateSeen)
681 : {
682 0 : Application::Reschedule();
683 :
684 0 : if( (osl_getGlobalTimer() - nStartTime) > 60000 )
685 : {
686 : OSL_FAIL("FrameworkHelper::WaitForEvent(), no event for a minute? giving up!");
687 0 : break;
688 : }
689 : }
690 0 : }
691 :
692 0 : void FrameworkHelper::WaitForUpdate() const
693 : {
694 0 : WaitForEvent(msConfigurationUpdateEndEvent);
695 0 : }
696 :
697 0 : void FrameworkHelper::RunOnEvent(
698 : const OUString& rsEventType,
699 : const ConfigurationChangeEventFilter& rFilter,
700 : const Callback& rCallback) const
701 : {
702 0 : new CallbackCaller(mrBase,rsEventType,rFilter,rCallback);
703 0 : }
704 :
705 127 : void FrameworkHelper::disposing (const lang::EventObject& rEventObject)
706 : {
707 127 : if (rEventObject.Source == mxConfigurationController)
708 127 : mxConfigurationController = NULL;
709 127 : }
710 :
711 264 : void FrameworkHelper::UpdateConfiguration()
712 : {
713 264 : if (mxConfigurationController.is())
714 : {
715 : try
716 : {
717 136 : if (mxConfigurationController.is())
718 136 : mxConfigurationController->update();
719 : }
720 0 : catch (lang::DisposedException&)
721 : {
722 0 : Dispose();
723 : }
724 0 : catch (RuntimeException&)
725 : {
726 : DBG_UNHANDLED_EXCEPTION();
727 : }
728 : }
729 264 : }
730 :
731 0 : OUString FrameworkHelper::ResourceIdToString (const Reference<XResourceId>& rxResourceId)
732 : {
733 0 : OUString sString;
734 0 : if (rxResourceId.is())
735 : {
736 0 : sString += rxResourceId->getResourceURL();
737 0 : if (rxResourceId->hasAnchor())
738 : {
739 0 : Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
740 0 : for (sal_Int32 nIndex=0; nIndex < aAnchorURLs.getLength(); ++nIndex)
741 : {
742 0 : sString += " | ";
743 0 : sString += aAnchorURLs[nIndex];
744 0 : }
745 : }
746 : }
747 0 : return sString;
748 : }
749 :
750 7530 : Reference<XResourceId> FrameworkHelper::CreateResourceId (const OUString& rsResourceURL)
751 : {
752 7530 : return new ::sd::framework::ResourceId(rsResourceURL);
753 : }
754 :
755 505 : Reference<XResourceId> FrameworkHelper::CreateResourceId (
756 : const OUString& rsResourceURL,
757 : const OUString& rsAnchorURL)
758 : {
759 505 : return new ::sd::framework::ResourceId(rsResourceURL, rsAnchorURL);
760 : }
761 :
762 291 : Reference<XResourceId> FrameworkHelper::CreateResourceId (
763 : const OUString& rsResourceURL,
764 : const Reference<XResourceId>& rxAnchorId)
765 : {
766 291 : if (rxAnchorId.is())
767 : return new ::sd::framework::ResourceId(
768 : rsResourceURL,
769 291 : rxAnchorId->getResourceURL(),
770 291 : rxAnchorId->getAnchorURLs());
771 : else
772 0 : return new ::sd::framework::ResourceId(rsResourceURL);
773 : }
774 :
775 : //----- FrameworkHelper::DisposeListener --------------------------------------
776 :
777 127 : FrameworkHelper::DisposeListener::DisposeListener (
778 : const ::boost::shared_ptr<FrameworkHelper>& rpHelper)
779 : : FrameworkHelperDisposeListenerInterfaceBase(maMutex),
780 127 : mpHelper(rpHelper)
781 : {
782 127 : Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
783 127 : if (xComponent.is())
784 127 : xComponent->addEventListener(this);
785 127 : }
786 :
787 254 : FrameworkHelper::DisposeListener::~DisposeListener()
788 : {
789 254 : }
790 :
791 127 : void SAL_CALL FrameworkHelper::DisposeListener::disposing()
792 : {
793 127 : Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
794 127 : if (xComponent.is())
795 0 : xComponent->removeEventListener(this);
796 :
797 127 : mpHelper.reset();
798 127 : }
799 :
800 127 : void SAL_CALL FrameworkHelper::DisposeListener::disposing (const lang::EventObject& rEventObject)
801 : throw(RuntimeException, std::exception)
802 : {
803 127 : if (mpHelper.get() != NULL)
804 127 : mpHelper->disposing(rEventObject);
805 127 : }
806 :
807 : //===== FrameworkHelperResourceIdFilter =======================================
808 :
809 0 : FrameworkHelperResourceIdFilter::FrameworkHelperResourceIdFilter (
810 : const Reference<XResourceId>& rxResourceId)
811 0 : : mxResourceId(rxResourceId)
812 : {
813 0 : }
814 :
815 : } } // end of namespace sd::framework
816 :
817 : namespace {
818 :
819 : //===== CallbackCaller ========================================================
820 :
821 0 : CallbackCaller::CallbackCaller (
822 : ::sd::ViewShellBase& rBase,
823 : const OUString& rsEventType,
824 : const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter,
825 : const ::sd::framework::FrameworkHelper::Callback& rCallback)
826 : : CallbackCallerInterfaceBase(MutexOwner::maMutex),
827 : msEventType(rsEventType),
828 : mxConfigurationController(),
829 : maFilter(rFilter),
830 0 : maCallback(rCallback)
831 : {
832 : try
833 : {
834 0 : Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY_THROW);
835 0 : mxConfigurationController = xControllerManager->getConfigurationController();
836 0 : if (mxConfigurationController.is())
837 : {
838 0 : if (mxConfigurationController->hasPendingRequests())
839 0 : mxConfigurationController->addConfigurationChangeListener(this,msEventType,Any());
840 : else
841 : {
842 : // There are no requests waiting to be processed. Therefore
843 : // no event, especially not the one we are waiting for, will
844 : // be sent in the near future and the callback would never be
845 : // called.
846 : // Call the callback now and tell him that the event it is
847 : // waiting for was not sent.
848 0 : mxConfigurationController = NULL;
849 0 : maCallback(false);
850 : }
851 0 : }
852 : }
853 0 : catch (RuntimeException&)
854 : {
855 : DBG_UNHANDLED_EXCEPTION();
856 : }
857 0 : }
858 :
859 0 : CallbackCaller::~CallbackCaller()
860 : {
861 0 : }
862 :
863 0 : void CallbackCaller::disposing()
864 : {
865 : try
866 : {
867 0 : if (mxConfigurationController.is())
868 : {
869 0 : Reference<XConfigurationController> xCC (mxConfigurationController);
870 0 : mxConfigurationController = NULL;
871 0 : xCC->removeConfigurationChangeListener(this);
872 : }
873 : }
874 0 : catch (RuntimeException&)
875 : {
876 : DBG_UNHANDLED_EXCEPTION();
877 : }
878 0 : }
879 :
880 0 : void SAL_CALL CallbackCaller::disposing (const lang::EventObject& rEvent)
881 : throw (RuntimeException, std::exception)
882 : {
883 0 : if (rEvent.Source == mxConfigurationController)
884 : {
885 0 : mxConfigurationController = NULL;
886 0 : maCallback(false);
887 : }
888 0 : }
889 :
890 0 : void SAL_CALL CallbackCaller::notifyConfigurationChange (
891 : const ConfigurationChangeEvent& rEvent)
892 : throw (RuntimeException, std::exception)
893 : {
894 0 : if (rEvent.Type.equals(msEventType) && maFilter(rEvent))
895 : {
896 0 : maCallback(true);
897 0 : if (mxConfigurationController.is())
898 : {
899 : // Reset the reference to the configuration controller so that
900 : // dispose() will not try to remove the listener a second time.
901 0 : Reference<XConfigurationController> xCC (mxConfigurationController);
902 0 : mxConfigurationController = NULL;
903 :
904 : // Removing this object from the controller may very likely lead
905 : // to its destruction, so no calls after that.
906 0 : xCC->removeConfigurationChangeListener(this);
907 : }
908 : }
909 0 : }
910 :
911 : //----- LifetimeController -------------------------------------------------
912 :
913 127 : LifetimeController::LifetimeController (::sd::ViewShellBase& rBase)
914 : : LifetimeControllerInterfaceBase(maMutex),
915 : mrBase(rBase),
916 : mbListeningToViewShellBase(false),
917 127 : mbListeningToController(false)
918 : {
919 : // Register as listener at the ViewShellBase. Because that is not done
920 : // via a reference we have to increase the reference count manually.
921 : // This is necessary even though listening to the XController did
922 : // increase the reference count because the controller may release its
923 : // reference to us before the ViewShellBase is destroyed.
924 127 : StartListening(mrBase);
925 127 : acquire();
926 127 : mbListeningToViewShellBase = true;
927 :
928 127 : Reference<XComponent> xComponent (rBase.GetController(), UNO_QUERY);
929 127 : if (xComponent.is())
930 : {
931 127 : xComponent->addEventListener(this);
932 127 : mbListeningToController = true;
933 127 : }
934 127 : }
935 :
936 254 : LifetimeController::~LifetimeController()
937 : {
938 : OSL_ASSERT(!mbListeningToController && !mbListeningToViewShellBase);
939 254 : }
940 :
941 127 : void LifetimeController::disposing()
942 : {
943 127 : }
944 :
945 127 : void SAL_CALL LifetimeController::disposing (const lang::EventObject& rEvent)
946 : throw(RuntimeException, std::exception)
947 : {
948 : (void)rEvent;
949 127 : mbListeningToController = false;
950 127 : Update();
951 127 : }
952 :
953 127 : void LifetimeController::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
954 : {
955 : (void)rBroadcaster;
956 127 : const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
957 127 : if (pSimpleHint != NULL && pSimpleHint->GetId() == SFX_HINT_DYING)
958 : {
959 127 : mbListeningToViewShellBase = false;
960 127 : Update();
961 127 : release();
962 : }
963 127 : }
964 :
965 254 : void LifetimeController::Update()
966 : {
967 254 : if (mbListeningToViewShellBase && mbListeningToController)
968 : {
969 : // Both the controller and the ViewShellBase are alive. Keep
970 : // waiting for their destruction.
971 : }
972 254 : else if (mbListeningToViewShellBase)
973 : {
974 : // The controller has been destroyed but the ViewShellBase is still
975 : // alive. Dispose the associated FrameworkHelper but keep it around
976 : // so that no new instance is created for the dying framework.
977 127 : ::sd::framework::FrameworkHelper::DisposeInstance(mrBase);
978 : }
979 : else
980 : {
981 : // Both the controller and the ViewShellBase have been destroyed.
982 : // Remove the FrameworkHelper so that the next call its Instance()
983 : // method can create a new instance.
984 127 : ::sd::framework::FrameworkHelper::ReleaseInstance(mrBase);
985 : }
986 254 : }
987 :
988 66 : } // end of anonymous namespace.
989 :
990 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|