bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / framework / tools / FrameworkHelper.cxx
blobc666e7017b19b883acc2b256ba2e30e74e14e490
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <osl/time.h>
22 #include "framework/FrameworkHelper.hxx"
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>
38 #include <sfx2/request.hxx>
39 #include <sfx2/dispatch.hxx>
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>
48 using namespace ::com::sun::star;
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::drawing::framework;
52 namespace {
54 //----- CallbackCaller --------------------------------------------------------
56 typedef ::cppu::WeakComponentImplHelper1 <
57 ::com::sun::star::drawing::framework::XConfigurationChangeListener
58 > CallbackCallerInterfaceBase;
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.
66 class CallbackCaller
67 : public ::sd::MutexOwner,
68 public CallbackCallerInterfaceBase
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.
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();
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;
104 private:
105 OUString msEventType;
106 Reference<XConfigurationController> mxConfigurationController;
107 ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter maFilter;
108 ::sd::framework::FrameworkHelper::Callback maCallback;
111 //----- LifetimeController ----------------------------------------------------
113 typedef ::cppu::WeakComponentImplHelper1 <
114 ::com::sun::star::lang::XEventListener
115 > LifetimeControllerInterfaceBase;
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.
122 class LifetimeController
123 : public ::sd::MutexOwner,
124 public LifetimeControllerInterfaceBase,
125 public SfxListener
127 public:
128 explicit LifetimeController (::sd::ViewShellBase& rBase);
129 virtual ~LifetimeController();
131 virtual void SAL_CALL disposing() SAL_OVERRIDE;
133 /** XEventListener. This method is called when the frame::XController
134 is being destroyed.
136 virtual void SAL_CALL disposing (const lang::EventObject& rEvent)
137 throw (RuntimeException, std::exception) SAL_OVERRIDE;
139 /** This method is called when the ViewShellBase is being destroyed.
141 virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) SAL_OVERRIDE;
143 private:
144 ::sd::ViewShellBase& mrBase;
145 bool mbListeningToViewShellBase;
146 bool mbListeningToController;
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.
152 void Update();
155 } // end of anonymous namespace
157 namespace sd { namespace framework {
159 namespace {
161 class FrameworkHelperAllPassFilter
163 public:
164 bool operator() (const css::drawing::framework::ConfigurationChangeEvent&) { return true; }
167 class FrameworkHelperResourceIdFilter
169 public:
170 FrameworkHelperResourceIdFilter (
171 const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId);
172 bool operator() (const css::drawing::framework::ConfigurationChangeEvent& rEvent)
173 { return mxResourceId.is() && rEvent.ResourceId.is()
174 && mxResourceId->compareTo(rEvent.ResourceId) == 0; }
175 private:
176 css::uno::Reference<css::drawing::framework::XResourceId> mxResourceId;
179 } // end of anonymous namespace
181 // Pane URLS.
183 const OUString FrameworkHelper::msPaneURLPrefix("private:resource/pane/");
184 const OUString FrameworkHelper::msCenterPaneURL( msPaneURLPrefix + "CenterPane");
185 const OUString FrameworkHelper::msFullScreenPaneURL( msPaneURLPrefix + "FullScreenPane");
186 const OUString FrameworkHelper::msLeftImpressPaneURL( msPaneURLPrefix + "LeftImpressPane");
187 const OUString FrameworkHelper::msLeftDrawPaneURL( msPaneURLPrefix + "LeftDrawPane");
188 const OUString FrameworkHelper::msSidebarPaneURL( msPaneURLPrefix + "SidebarPane");
190 // View URLs.
192 const OUString FrameworkHelper::msViewURLPrefix("private:resource/view/");
193 const OUString FrameworkHelper::msImpressViewURL( msViewURLPrefix + "ImpressView");
194 const OUString FrameworkHelper::msDrawViewURL( msViewURLPrefix + "GraphicView");
195 const OUString FrameworkHelper::msOutlineViewURL( msViewURLPrefix + "OutlineView");
196 const OUString FrameworkHelper::msNotesViewURL( msViewURLPrefix + "NotesView");
197 const OUString FrameworkHelper::msHandoutViewURL( msViewURLPrefix + "HandoutView");
198 const OUString FrameworkHelper::msSlideSorterURL( msViewURLPrefix + "SlideSorter");
199 const OUString FrameworkHelper::msPresentationViewURL( msViewURLPrefix + "PresentationView");
200 const OUString FrameworkHelper::msSidebarViewURL( msViewURLPrefix + "SidebarView");
202 // Tool bar URLs.
204 const OUString FrameworkHelper::msToolBarURLPrefix("private:resource/toolbar/");
205 const OUString FrameworkHelper::msViewTabBarURL( msToolBarURLPrefix + "ViewTabBar");
207 // Task panel URLs.
208 const OUString FrameworkHelper::msTaskPanelURLPrefix( "private:resource/toolpanel/" );
209 const OUString FrameworkHelper::msAllMasterPagesTaskPanelURL( msTaskPanelURLPrefix + "AllMasterPages" );
210 const OUString FrameworkHelper::msRecentMasterPagesTaskPanelURL( msTaskPanelURLPrefix + "RecentMasterPages" );
211 const OUString FrameworkHelper::msUsedMasterPagesTaskPanelURL( msTaskPanelURLPrefix + "UsedMasterPages" );
212 const OUString FrameworkHelper::msLayoutTaskPanelURL( msTaskPanelURLPrefix + "Layouts" );
213 const OUString FrameworkHelper::msTableDesignPanelURL( msTaskPanelURLPrefix + "TableDesign" );
214 const OUString FrameworkHelper::msCustomAnimationTaskPanelURL( msTaskPanelURLPrefix + "CustomAnimations" );
215 const OUString FrameworkHelper::msSlideTransitionTaskPanelURL( msTaskPanelURLPrefix + "SlideTransitions" );
217 // Event URLs.
218 const OUString FrameworkHelper::msResourceActivationRequestEvent( "ResourceActivationRequested" );
219 const OUString FrameworkHelper::msResourceDeactivationRequestEvent( "ResourceDeactivationRequest" );
220 const OUString FrameworkHelper::msResourceActivationEvent( "ResourceActivation" );
221 const OUString FrameworkHelper::msResourceDeactivationEvent( "ResourceDeactivation" );
222 const OUString FrameworkHelper::msResourceDeactivationEndEvent( "ResourceDeactivationEnd" );
223 const OUString FrameworkHelper::msConfigurationUpdateStartEvent( "ConfigurationUpdateStart" );
224 const OUString FrameworkHelper::msConfigurationUpdateEndEvent( "ConfigurationUpdateEnd" );
226 // Service names of controllers.
227 const OUString FrameworkHelper::msModuleControllerService("com.sun.star.drawing.framework.ModuleController");
228 const OUString FrameworkHelper::msConfigurationControllerService("com.sun.star.drawing.framework.ConfigurationController");
230 //----- helper ----------------------------------------------------------------
231 namespace
233 static ::boost::shared_ptr< ViewShell > lcl_getViewShell( const Reference< XResource >& i_rViewShellWrapper )
235 ::boost::shared_ptr< ViewShell > pViewShell;
236 if ( !i_rViewShellWrapper.is() )
237 return pViewShell;
241 Reference<lang::XUnoTunnel> xViewTunnel( i_rViewShellWrapper, UNO_QUERY_THROW );
242 pViewShell = reinterpret_cast< ViewShellWrapper* >(
243 xViewTunnel->getSomething( ViewShellWrapper::getUnoTunnelId() ) )->GetViewShell();
245 catch( const Exception& )
247 DBG_UNHANDLED_EXCEPTION();
249 return pViewShell;
251 Reference< XResource > lcl_getFirstViewInPane( const Reference< XConfigurationController >& i_rConfigController,
252 const Reference< XResourceId >& i_rPaneId )
256 Reference< XConfiguration > xConfiguration( i_rConfigController->getRequestedConfiguration(), UNO_SET_THROW );
257 Sequence< Reference< XResourceId > > aViewIds( xConfiguration->getResources(
258 i_rPaneId, FrameworkHelper::msViewURLPrefix, AnchorBindingMode_DIRECT ) );
259 if ( aViewIds.getLength() > 0 )
260 return i_rConfigController->getResource( aViewIds[0] );
262 catch( const Exception& )
264 DBG_UNHANDLED_EXCEPTION();
266 return NULL;
270 //----- FrameworkHelper::ViewURLMap -------------------------------------------
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.
275 class FrameworkHelper::ViewURLMap
276 : public std::unordered_map<
277 OUString,
278 ViewShell::ShellType,
279 OUStringHash>
281 public:
282 ViewURLMap() {}
285 //----- Framework::DiposeListener ---------------------------------------------
287 namespace {
288 typedef ::cppu::WeakComponentImplHelper1 <
289 ::com::sun::star::lang::XEventListener
290 > FrameworkHelperDisposeListenerInterfaceBase;
293 class FrameworkHelper::DisposeListener
294 : public ::sd::MutexOwner,
295 public FrameworkHelperDisposeListenerInterfaceBase
297 public:
298 DisposeListener (const ::boost::shared_ptr<FrameworkHelper>& rpHelper);
299 virtual ~DisposeListener();
301 virtual void SAL_CALL disposing() SAL_OVERRIDE;
303 virtual void SAL_CALL disposing (const lang::EventObject& rEventObject)
304 throw(RuntimeException, std::exception) SAL_OVERRIDE;
306 private:
307 ::boost::shared_ptr<FrameworkHelper> mpHelper;
310 //----- FrameworkHelper::Deleter ----------------------------------------------
312 class FrameworkHelper::Deleter
314 public:
315 void operator()(FrameworkHelper* pObject)
317 delete pObject;
321 //----- FrameworkHelper -------------------------------------------------------
323 ::boost::scoped_ptr<FrameworkHelper::ViewURLMap> FrameworkHelper::mpViewURLMap(new ViewURLMap());
325 FrameworkHelper::InstanceMap FrameworkHelper::maInstanceMap;
327 ::boost::shared_ptr<FrameworkHelper> FrameworkHelper::Instance (ViewShellBase& rBase)
330 ::boost::shared_ptr<FrameworkHelper> pHelper;
332 InstanceMap::const_iterator iHelper (maInstanceMap.find(&rBase));
333 if (iHelper == maInstanceMap.end())
335 ::osl::GetGlobalMutex aMutexFunctor;
336 ::osl::MutexGuard aGuard (aMutexFunctor());
337 if (iHelper == maInstanceMap.end())
339 pHelper = ::boost::shared_ptr<FrameworkHelper>(
340 new FrameworkHelper(rBase),
341 FrameworkHelper::Deleter());
342 pHelper->Initialize();
343 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
344 maInstanceMap[&rBase] = pHelper;
347 else
349 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
350 pHelper = iHelper->second;
353 return pHelper;
356 void FrameworkHelper::DisposeInstance (ViewShellBase& rBase)
358 InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
359 if (iHelper != maInstanceMap.end())
361 iHelper->second->Dispose();
365 void FrameworkHelper::ReleaseInstance (ViewShellBase& rBase)
367 InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
368 if (iHelper != maInstanceMap.end())
369 maInstanceMap.erase(iHelper);
372 FrameworkHelper::FrameworkHelper (ViewShellBase& rBase)
373 : mrBase(rBase),
374 mxConfigurationController(),
375 mxDisposeListener()
378 Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY);
379 if (xControllerManager.is())
381 mxConfigurationController = xControllerManager->getConfigurationController();
384 new LifetimeController(mrBase);
387 void FrameworkHelper::Initialize()
389 mxDisposeListener = new DisposeListener(shared_from_this());
392 FrameworkHelper::~FrameworkHelper()
396 void FrameworkHelper::Dispose()
398 if (mxDisposeListener.is())
399 mxDisposeListener->dispose();
400 mxConfigurationController = NULL;
403 bool FrameworkHelper::IsValid()
405 return mxConfigurationController.is();
408 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const OUString& rsPaneURL)
410 if ( !mxConfigurationController.is() )
411 return ::boost::shared_ptr<ViewShell>();
413 Reference<XResourceId> xPaneId( CreateResourceId( rsPaneURL ) );
414 return lcl_getViewShell( lcl_getFirstViewInPane( mxConfigurationController, xPaneId ) );
417 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const Reference<XView>& rxView)
419 return lcl_getViewShell( rxView.get() );
422 Reference<XView> FrameworkHelper::GetView (const Reference<XResourceId>& rxPaneOrViewId)
424 Reference<XView> xView;
426 if ( ! rxPaneOrViewId.is() || ! mxConfigurationController.is())
427 return NULL;
431 if (rxPaneOrViewId->getResourceURL().match(msViewURLPrefix))
433 xView.set( mxConfigurationController->getResource( rxPaneOrViewId ), UNO_QUERY );
435 else
437 xView.set( lcl_getFirstViewInPane( mxConfigurationController, rxPaneOrViewId ), UNO_QUERY );
440 catch (lang::DisposedException&)
442 Dispose();
444 catch (RuntimeException&)
448 return xView;
451 Reference<XResourceId> FrameworkHelper::RequestView (
452 const OUString& rsResourceURL,
453 const OUString& rsAnchorURL)
455 Reference<XResourceId> xViewId;
459 if (mxConfigurationController.is())
461 mxConfigurationController->requestResourceActivation(
462 CreateResourceId(rsAnchorURL),
463 ResourceActivationMode_ADD);
464 xViewId = CreateResourceId(rsResourceURL, rsAnchorURL);
465 mxConfigurationController->requestResourceActivation(
466 xViewId,
467 ResourceActivationMode_REPLACE);
470 catch (lang::DisposedException&)
472 Dispose();
473 xViewId = NULL;
475 catch (RuntimeException&)
477 xViewId = NULL;
480 return xViewId;
483 ViewShell::ShellType FrameworkHelper::GetViewId (const OUString& rsViewURL)
485 if (mpViewURLMap->empty())
487 (*mpViewURLMap)[msImpressViewURL] = ViewShell::ST_IMPRESS;
488 (*mpViewURLMap)[msDrawViewURL] = ViewShell::ST_DRAW;
489 (*mpViewURLMap)[msOutlineViewURL] = ViewShell::ST_OUTLINE;
490 (*mpViewURLMap)[msNotesViewURL] = ViewShell::ST_NOTES;
491 (*mpViewURLMap)[msHandoutViewURL] = ViewShell::ST_HANDOUT;
492 (*mpViewURLMap)[msSlideSorterURL] = ViewShell::ST_SLIDE_SORTER;
493 (*mpViewURLMap)[msPresentationViewURL] = ViewShell::ST_PRESENTATION;
494 (*mpViewURLMap)[msSidebarViewURL] = ViewShell::ST_SIDEBAR;
496 ViewURLMap::const_iterator iView (mpViewURLMap->find(rsViewURL));
497 if (iView != mpViewURLMap->end())
498 return iView->second;
499 else
500 return ViewShell::ST_NONE;
503 OUString FrameworkHelper::GetViewURL (ViewShell::ShellType eType)
505 switch (eType)
507 case ViewShell::ST_IMPRESS : return msImpressViewURL;
508 case ViewShell::ST_DRAW : return msDrawViewURL;
509 case ViewShell::ST_OUTLINE : return msOutlineViewURL;
510 case ViewShell::ST_NOTES : return msNotesViewURL;
511 case ViewShell::ST_HANDOUT : return msHandoutViewURL;
512 case ViewShell::ST_SLIDE_SORTER : return msSlideSorterURL;
513 case ViewShell::ST_PRESENTATION : return msPresentationViewURL;
514 case ViewShell::ST_SIDEBAR : return msSidebarViewURL;
515 default:
516 return OUString();
520 void FrameworkHelper::HandleModeChangeSlot (
521 sal_uLong nSlotId,
522 SfxRequest& rRequest)
524 bool bIsActive = true;
526 if ( ! mxConfigurationController.is())
527 return;
529 switch (nSlotId)
531 case SID_DRAWINGMODE:
532 case SID_NOTESMODE:
533 case SID_HANDOUTMODE:
534 case SID_DIAMODE:
535 case SID_OUTLINEMODE:
537 const SfxItemSet* pRequestArguments = rRequest.GetArgs();
538 if (pRequestArguments)
540 SFX_REQUEST_ARG (rRequest,
541 pIsActive,
542 SfxBoolItem,
543 (sal_uInt16)nSlotId,
544 false);
545 bIsActive = pIsActive->GetValue ();
548 break;
553 if ( ! mxConfigurationController.is())
554 throw RuntimeException();
556 Reference<XResourceId> xPaneId (
557 CreateResourceId(framework::FrameworkHelper::msCenterPaneURL));
558 Reference<XView> xView (GetView(xPaneId));
559 ::boost::shared_ptr<ViewShell> pCenterViewShell (GetViewShell(xView));
561 OUString sRequestedView;
562 if (bIsActive)
564 switch (nSlotId)
566 case SID_NORMAL_MULTI_PANE_GUI:
567 case SID_DRAWINGMODE:
568 sRequestedView = FrameworkHelper::msImpressViewURL;
569 break;
571 case SID_NOTESMODE:
572 sRequestedView = FrameworkHelper::msNotesViewURL;
573 break;
575 case SID_HANDOUTMODE:
576 sRequestedView = FrameworkHelper::msHandoutViewURL;
577 break;
579 case SID_SLIDE_SORTER_MULTI_PANE_GUI:
580 case SID_DIAMODE:
581 sRequestedView = FrameworkHelper::msSlideSorterURL;
582 break;
584 case SID_OUTLINEMODE:
585 sRequestedView = FrameworkHelper::msOutlineViewURL;
586 break;
590 if (xView.is()
591 && xView->getResourceId()->getResourceURL().equals(sRequestedView))
593 // We do not have to switch the view shell but maybe the edit mode
594 // has changed.
595 DrawViewShell* pDrawViewShell
596 = dynamic_cast<DrawViewShell*>(pCenterViewShell.get());
597 if (pDrawViewShell != NULL)
599 pCenterViewShell->Broadcast (
600 ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_START));
602 pDrawViewShell->ChangeEditMode (
603 EM_PAGE, pDrawViewShell->IsLayerModeActive());
605 pCenterViewShell->Broadcast (
606 ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_END));
609 else
611 mxConfigurationController->requestResourceActivation(
612 CreateResourceId(sRequestedView, msCenterPaneURL),
613 ResourceActivationMode_REPLACE);
616 catch (RuntimeException&)
618 DBG_UNHANDLED_EXCEPTION();
622 void FrameworkHelper::RunOnConfigurationEvent(
623 const OUString& rsEventType,
624 const Callback& rCallback)
626 RunOnEvent(
627 rsEventType,
628 FrameworkHelperAllPassFilter(),
629 rCallback);
632 void FrameworkHelper::RunOnResourceActivation(
633 const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
634 const Callback& rCallback)
636 if (mxConfigurationController.is()
637 && mxConfigurationController->getResource(rxResourceId).is())
639 rCallback(false);
641 else
643 RunOnEvent(
644 msResourceActivationEvent,
645 FrameworkHelperResourceIdFilter(rxResourceId),
646 rCallback);
650 /** A callback that sets a flag to a specified value when the callback is
651 called.
653 class FlagUpdater
655 public:
656 FlagUpdater (bool& rFlag) : mrFlag(rFlag) {}
657 void operator() (bool) const {mrFlag = true;}
658 private:
659 bool& mrFlag;
662 void FrameworkHelper::RequestSynchronousUpdate()
664 rtl::Reference<ConfigurationController> pCC (
665 dynamic_cast<ConfigurationController*>(mxConfigurationController.get()));
666 if (pCC.is())
667 pCC->RequestSynchronousUpdate();
670 void FrameworkHelper::WaitForEvent (const OUString& rsEventType) const
672 bool bConfigurationUpdateSeen (false);
674 RunOnEvent(
675 rsEventType,
676 FrameworkHelperAllPassFilter(),
677 FlagUpdater(bConfigurationUpdateSeen));
679 sal_uInt32 nStartTime = osl_getGlobalTimer();
680 while ( ! bConfigurationUpdateSeen)
682 Application::Reschedule();
684 if( (osl_getGlobalTimer() - nStartTime) > 60000 )
686 OSL_FAIL("FrameworkHelper::WaitForEvent(), no event for a minute? giving up!");
687 break;
692 void FrameworkHelper::WaitForUpdate() const
694 WaitForEvent(msConfigurationUpdateEndEvent);
697 void FrameworkHelper::RunOnEvent(
698 const OUString& rsEventType,
699 const ConfigurationChangeEventFilter& rFilter,
700 const Callback& rCallback) const
702 new CallbackCaller(mrBase,rsEventType,rFilter,rCallback);
705 void FrameworkHelper::disposing (const lang::EventObject& rEventObject)
707 if (rEventObject.Source == mxConfigurationController)
708 mxConfigurationController = NULL;
711 void FrameworkHelper::UpdateConfiguration()
713 if (mxConfigurationController.is())
717 if (mxConfigurationController.is())
718 mxConfigurationController->update();
720 catch (lang::DisposedException&)
722 Dispose();
724 catch (RuntimeException&)
726 DBG_UNHANDLED_EXCEPTION();
731 OUString FrameworkHelper::ResourceIdToString (const Reference<XResourceId>& rxResourceId)
733 OUString sString;
734 if (rxResourceId.is())
736 sString += rxResourceId->getResourceURL();
737 if (rxResourceId->hasAnchor())
739 Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
740 for (sal_Int32 nIndex=0; nIndex < aAnchorURLs.getLength(); ++nIndex)
742 sString += " | ";
743 sString += aAnchorURLs[nIndex];
747 return sString;
750 Reference<XResourceId> FrameworkHelper::CreateResourceId (const OUString& rsResourceURL)
752 return new ::sd::framework::ResourceId(rsResourceURL);
755 Reference<XResourceId> FrameworkHelper::CreateResourceId (
756 const OUString& rsResourceURL,
757 const OUString& rsAnchorURL)
759 return new ::sd::framework::ResourceId(rsResourceURL, rsAnchorURL);
762 Reference<XResourceId> FrameworkHelper::CreateResourceId (
763 const OUString& rsResourceURL,
764 const Reference<XResourceId>& rxAnchorId)
766 if (rxAnchorId.is())
767 return new ::sd::framework::ResourceId(
768 rsResourceURL,
769 rxAnchorId->getResourceURL(),
770 rxAnchorId->getAnchorURLs());
771 else
772 return new ::sd::framework::ResourceId(rsResourceURL);
775 //----- FrameworkHelper::DisposeListener --------------------------------------
777 FrameworkHelper::DisposeListener::DisposeListener (
778 const ::boost::shared_ptr<FrameworkHelper>& rpHelper)
779 : FrameworkHelperDisposeListenerInterfaceBase(maMutex),
780 mpHelper(rpHelper)
782 Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
783 if (xComponent.is())
784 xComponent->addEventListener(this);
787 FrameworkHelper::DisposeListener::~DisposeListener()
791 void SAL_CALL FrameworkHelper::DisposeListener::disposing()
793 Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
794 if (xComponent.is())
795 xComponent->removeEventListener(this);
797 mpHelper.reset();
800 void SAL_CALL FrameworkHelper::DisposeListener::disposing (const lang::EventObject& rEventObject)
801 throw(RuntimeException, std::exception)
803 if (mpHelper.get() != NULL)
804 mpHelper->disposing(rEventObject);
807 //===== FrameworkHelperResourceIdFilter =======================================
809 FrameworkHelperResourceIdFilter::FrameworkHelperResourceIdFilter (
810 const Reference<XResourceId>& rxResourceId)
811 : mxResourceId(rxResourceId)
815 } } // end of namespace sd::framework
817 namespace {
819 //===== CallbackCaller ========================================================
821 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 maCallback(rCallback)
834 Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY_THROW);
835 mxConfigurationController = xControllerManager->getConfigurationController();
836 if (mxConfigurationController.is())
838 if (mxConfigurationController->hasPendingRequests())
839 mxConfigurationController->addConfigurationChangeListener(this,msEventType,Any());
840 else
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 mxConfigurationController = NULL;
849 maCallback(false);
853 catch (RuntimeException&)
855 DBG_UNHANDLED_EXCEPTION();
859 CallbackCaller::~CallbackCaller()
863 void CallbackCaller::disposing()
867 if (mxConfigurationController.is())
869 Reference<XConfigurationController> xCC (mxConfigurationController);
870 mxConfigurationController = NULL;
871 xCC->removeConfigurationChangeListener(this);
874 catch (RuntimeException&)
876 DBG_UNHANDLED_EXCEPTION();
880 void SAL_CALL CallbackCaller::disposing (const lang::EventObject& rEvent)
881 throw (RuntimeException, std::exception)
883 if (rEvent.Source == mxConfigurationController)
885 mxConfigurationController = NULL;
886 maCallback(false);
890 void SAL_CALL CallbackCaller::notifyConfigurationChange (
891 const ConfigurationChangeEvent& rEvent)
892 throw (RuntimeException, std::exception)
894 if (rEvent.Type.equals(msEventType) && maFilter(rEvent))
896 maCallback(true);
897 if (mxConfigurationController.is())
899 // Reset the reference to the configuration controller so that
900 // dispose() will not try to remove the listener a second time.
901 Reference<XConfigurationController> xCC (mxConfigurationController);
902 mxConfigurationController = NULL;
904 // Removing this object from the controller may very likely lead
905 // to its destruction, so no calls after that.
906 xCC->removeConfigurationChangeListener(this);
911 //----- LifetimeController -------------------------------------------------
913 LifetimeController::LifetimeController (::sd::ViewShellBase& rBase)
914 : LifetimeControllerInterfaceBase(maMutex),
915 mrBase(rBase),
916 mbListeningToViewShellBase(false),
917 mbListeningToController(false)
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 StartListening(mrBase);
925 acquire();
926 mbListeningToViewShellBase = true;
928 Reference<XComponent> xComponent (rBase.GetController(), UNO_QUERY);
929 if (xComponent.is())
931 xComponent->addEventListener(this);
932 mbListeningToController = true;
936 LifetimeController::~LifetimeController()
938 OSL_ASSERT(!mbListeningToController && !mbListeningToViewShellBase);
941 void LifetimeController::disposing()
945 void SAL_CALL LifetimeController::disposing (const lang::EventObject& rEvent)
946 throw(RuntimeException, std::exception)
948 (void)rEvent;
949 mbListeningToController = false;
950 Update();
953 void LifetimeController::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
955 (void)rBroadcaster;
956 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
957 if (pSimpleHint != NULL && pSimpleHint->GetId() == SFX_HINT_DYING)
959 mbListeningToViewShellBase = false;
960 Update();
961 release();
965 void LifetimeController::Update()
967 if (mbListeningToViewShellBase && mbListeningToController)
969 // Both the controller and the ViewShellBase are alive. Keep
970 // waiting for their destruction.
972 else if (mbListeningToViewShellBase)
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 ::sd::framework::FrameworkHelper::DisposeInstance(mrBase);
979 else
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 ::sd::framework::FrameworkHelper::ReleaseInstance(mrBase);
988 } // end of anonymous namespace.
990 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */