loplugin:sequenceloop in sd
[LibreOffice.git] / sd / source / ui / framework / tools / FrameworkHelper.cxx
blob1f51a6bba052ffbbaf85753fde9c3a3cfa4b9cfb
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 <DrawViewShell.hxx>
29 #include <ViewShellHint.hxx>
30 #include <app.hrc>
31 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
32 #include <cppuhelper/compbase.hxx>
33 #include <svl/lstner.hxx>
35 #include <sfx2/request.hxx>
37 #include <MutexOwner.hxx>
38 #include <vcl/svapp.hxx>
39 #include <osl/doublecheckedlocking.h>
40 #include <osl/getglobalmutex.hxx>
41 #include <tools/diagnose_ex.h>
42 #include <memory>
43 #include <unordered_map>
45 using namespace ::com::sun::star;
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::drawing::framework;
49 namespace {
51 //----- CallbackCaller --------------------------------------------------------
53 typedef ::cppu::WeakComponentImplHelper <
54 css::drawing::framework::XConfigurationChangeListener
55 > CallbackCallerInterfaceBase;
57 /** A CallbackCaller registers as listener at an XConfigurationController
58 object and waits for the notification of one type of event. When that
59 event is received, or when the CallbackCaller detects at its
60 construction that the event will not be sent in the near future, the
61 actual callback object is called and the CallbackCaller destroys itself.
63 class CallbackCaller
64 : public ::sd::MutexOwner,
65 public CallbackCallerInterfaceBase
67 public:
68 /** Create a new CallbackCaller object. This object controls its own
69 lifetime by acquiring a reference to itself in the constructor.
70 When it detects that the event will not be notified in the near
71 future (because the queue of pending configuration change operations
72 is empty and therefore no event will be sent int the near future, it
73 does not acquires a reference and thus initiates its destruction in
74 the constructor.)
75 @param rBase
76 This ViewShellBase object is used to determine the
77 XConfigurationController at which to register.
78 @param rsEventType
79 The event type which the callback is waiting for.
80 @param pCallback
81 The callback object which is to be notified. The caller will
82 typically release his reference to the caller so that when the
83 CallbackCaller dies (after having called the callback) the
84 callback is destroyed.
86 CallbackCaller (
87 const ::sd::ViewShellBase& rBase,
88 const OUString& rsEventType,
89 const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter,
90 const ::sd::framework::FrameworkHelper::Callback& rCallback);
92 virtual void SAL_CALL disposing() override;
93 // XEventListener
94 virtual void SAL_CALL disposing (const lang::EventObject& rEvent) override;
95 // XConfigurationChangeListener
96 virtual void SAL_CALL notifyConfigurationChange (const ConfigurationChangeEvent& rEvent) override;
98 private:
99 OUString const msEventType;
100 Reference<XConfigurationController> mxConfigurationController;
101 ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter const maFilter;
102 ::sd::framework::FrameworkHelper::Callback const maCallback;
105 //----- LifetimeController ----------------------------------------------------
107 typedef ::cppu::WeakComponentImplHelper <
108 css::lang::XEventListener
109 > LifetimeControllerInterfaceBase;
111 /** This class helps controlling the lifetime of the
112 FrameworkHelper. Register at a ViewShellBase object and an XController
113 object and call Dispose() at the associated FrameworkHelper object when
114 one of them and Release() when both of them are destroyed.
116 class LifetimeController
117 : public ::sd::MutexOwner,
118 public LifetimeControllerInterfaceBase,
119 public SfxListener
121 public:
122 explicit LifetimeController (::sd::ViewShellBase& rBase);
123 virtual ~LifetimeController() override;
125 virtual void SAL_CALL disposing() override;
127 /** XEventListener. This method is called when the frame::XController
128 is being destroyed.
130 virtual void SAL_CALL disposing (const lang::EventObject& rEvent) override;
132 /** This method is called when the ViewShellBase is being destroyed.
134 virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint) override;
136 private:
137 ::sd::ViewShellBase& mrBase;
138 bool mbListeningToViewShellBase;
139 bool mbListeningToController;
141 /** When one or both of the mbListeningToViewShellBase and
142 mbListeningToController members were modified then call this method
143 to either dispose or release the associated FrameworkHelper.
145 void Update();
148 } // end of anonymous namespace
150 namespace sd { namespace framework {
152 namespace {
154 class FrameworkHelperAllPassFilter
156 public:
157 bool operator() (const css::drawing::framework::ConfigurationChangeEvent&) { return true; }
160 class FrameworkHelperResourceIdFilter
162 public:
163 explicit FrameworkHelperResourceIdFilter (
164 const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId);
165 bool operator() (const css::drawing::framework::ConfigurationChangeEvent& rEvent)
166 { return mxResourceId.is() && rEvent.ResourceId.is()
167 && mxResourceId->compareTo(rEvent.ResourceId) == 0; }
168 private:
169 css::uno::Reference<css::drawing::framework::XResourceId> mxResourceId;
172 } // end of anonymous namespace
174 // Pane URLS.
176 const OUString FrameworkHelper::msPaneURLPrefix("private:resource/pane/");
177 const OUString FrameworkHelper::msCenterPaneURL( msPaneURLPrefix + "CenterPane");
178 const OUString FrameworkHelper::msFullScreenPaneURL( msPaneURLPrefix + "FullScreenPane");
179 const OUString FrameworkHelper::msLeftImpressPaneURL( msPaneURLPrefix + "LeftImpressPane");
180 const OUString FrameworkHelper::msLeftDrawPaneURL( msPaneURLPrefix + "LeftDrawPane");
181 const OUString FrameworkHelper::msSidebarPaneURL( msPaneURLPrefix + "SidebarPane");
183 // View URLs.
185 const OUString FrameworkHelper::msViewURLPrefix("private:resource/view/");
186 const OUString FrameworkHelper::msImpressViewURL( msViewURLPrefix + "ImpressView");
187 const OUString FrameworkHelper::msDrawViewURL( msViewURLPrefix + "GraphicView");
188 const OUString FrameworkHelper::msOutlineViewURL( msViewURLPrefix + "OutlineView");
189 const OUString FrameworkHelper::msNotesViewURL( msViewURLPrefix + "NotesView");
190 const OUString FrameworkHelper::msHandoutViewURL( msViewURLPrefix + "HandoutView");
191 const OUString FrameworkHelper::msSlideSorterURL( msViewURLPrefix + "SlideSorter");
192 const OUString FrameworkHelper::msPresentationViewURL( msViewURLPrefix + "PresentationView");
193 const OUString FrameworkHelper::msSidebarViewURL( msViewURLPrefix + "SidebarView");
195 // Tool bar URLs.
197 const OUString FrameworkHelper::msToolBarURLPrefix("private:resource/toolbar/");
198 const OUString FrameworkHelper::msViewTabBarURL( msToolBarURLPrefix + "ViewTabBar");
200 // Task panel URLs.
201 const OUString FrameworkHelper::msTaskPanelURLPrefix( "private:resource/toolpanel/" );
202 const OUString FrameworkHelper::msAllMasterPagesTaskPanelURL( msTaskPanelURLPrefix + "AllMasterPages" );
203 const OUString FrameworkHelper::msRecentMasterPagesTaskPanelURL( msTaskPanelURLPrefix + "RecentMasterPages" );
204 const OUString FrameworkHelper::msUsedMasterPagesTaskPanelURL( msTaskPanelURLPrefix + "UsedMasterPages" );
205 const OUString FrameworkHelper::msLayoutTaskPanelURL( msTaskPanelURLPrefix + "Layouts" );
206 const OUString FrameworkHelper::msTableDesignPanelURL( msTaskPanelURLPrefix + "TableDesign" );
207 const OUString FrameworkHelper::msCustomAnimationTaskPanelURL( msTaskPanelURLPrefix + "CustomAnimations" );
208 const OUString FrameworkHelper::msSlideTransitionTaskPanelURL( msTaskPanelURLPrefix + "SlideTransitions" );
210 // Event URLs.
211 const OUString FrameworkHelper::msResourceActivationRequestEvent( "ResourceActivationRequested" );
212 const OUString FrameworkHelper::msResourceDeactivationRequestEvent( "ResourceDeactivationRequest" );
213 const OUString FrameworkHelper::msResourceActivationEvent( "ResourceActivation" );
214 const OUString FrameworkHelper::msResourceDeactivationEvent( "ResourceDeactivation" );
215 const OUString FrameworkHelper::msResourceDeactivationEndEvent( "ResourceDeactivationEnd" );
216 const OUString FrameworkHelper::msConfigurationUpdateStartEvent( "ConfigurationUpdateStart" );
217 const OUString FrameworkHelper::msConfigurationUpdateEndEvent( "ConfigurationUpdateEnd" );
219 // Service names of controllers.
220 const OUString FrameworkHelper::msModuleControllerService("com.sun.star.drawing.framework.ModuleController");
221 const OUString FrameworkHelper::msConfigurationControllerService("com.sun.star.drawing.framework.ConfigurationController");
223 //----- helper ----------------------------------------------------------------
224 namespace
226 ::std::shared_ptr< ViewShell > lcl_getViewShell( const Reference< XResource >& i_rViewShellWrapper )
228 ::std::shared_ptr< ViewShell > pViewShell;
229 if ( !i_rViewShellWrapper.is() )
230 return pViewShell;
234 Reference<lang::XUnoTunnel> xViewTunnel( i_rViewShellWrapper, UNO_QUERY_THROW );
235 pViewShell = reinterpret_cast< ViewShellWrapper* >(
236 xViewTunnel->getSomething( ViewShellWrapper::getUnoTunnelId() ) )->GetViewShell();
238 catch( const Exception& )
240 DBG_UNHANDLED_EXCEPTION("sd");
242 return pViewShell;
244 Reference< XResource > lcl_getFirstViewInPane( const Reference< XConfigurationController >& i_rConfigController,
245 const Reference< XResourceId >& i_rPaneId )
249 Reference< XConfiguration > xConfiguration( i_rConfigController->getRequestedConfiguration(), UNO_SET_THROW );
250 Sequence< Reference< XResourceId > > aViewIds( xConfiguration->getResources(
251 i_rPaneId, FrameworkHelper::msViewURLPrefix, AnchorBindingMode_DIRECT ) );
252 if ( aViewIds.hasElements() )
253 return i_rConfigController->getResource( aViewIds[0] );
255 catch( const Exception& )
257 DBG_UNHANDLED_EXCEPTION("sd");
259 return nullptr;
263 //----- FrameworkHelper::ViewURLMap -------------------------------------------
265 /** The ViewURLMap is used to translate between the view URLs used by the
266 drawing framework and the enums defined in the ViewShell class.
268 class FrameworkHelper::ViewURLMap
269 : public std::unordered_map<
270 OUString,
271 ViewShell::ShellType>
273 public:
274 ViewURLMap() {}
277 //----- Framework::DiposeListener ---------------------------------------------
279 namespace {
280 typedef ::cppu::WeakComponentImplHelper <
281 css::lang::XEventListener
282 > FrameworkHelperDisposeListenerInterfaceBase;
285 class FrameworkHelper::DisposeListener
286 : public ::sd::MutexOwner,
287 public FrameworkHelperDisposeListenerInterfaceBase
289 public:
290 explicit DisposeListener (const ::std::shared_ptr<FrameworkHelper>& rpHelper);
292 virtual void SAL_CALL disposing() override;
294 virtual void SAL_CALL disposing (const lang::EventObject& rEventObject) override;
296 private:
297 ::std::shared_ptr<FrameworkHelper> mpHelper;
300 //----- FrameworkHelper::Deleter ----------------------------------------------
302 class FrameworkHelper::Deleter
304 public:
305 void operator()(FrameworkHelper* pObject)
307 delete pObject;
311 //----- FrameworkHelper -------------------------------------------------------
313 std::unique_ptr<FrameworkHelper::ViewURLMap> FrameworkHelper::mpViewURLMap(new ViewURLMap());
315 FrameworkHelper::InstanceMap FrameworkHelper::maInstanceMap;
317 ::std::shared_ptr<FrameworkHelper> FrameworkHelper::Instance (ViewShellBase& rBase)
320 ::std::shared_ptr<FrameworkHelper> pHelper;
322 InstanceMap::const_iterator iHelper (maInstanceMap.find(&rBase));
323 if (iHelper == maInstanceMap.end())
325 ::osl::GetGlobalMutex aMutexFunctor;
326 ::osl::MutexGuard aGuard (aMutexFunctor());
327 if (iHelper == maInstanceMap.end())
329 pHelper = ::std::shared_ptr<FrameworkHelper>(
330 new FrameworkHelper(rBase),
331 FrameworkHelper::Deleter());
332 pHelper->Initialize();
333 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
334 maInstanceMap[&rBase] = pHelper;
337 else
339 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
340 pHelper = iHelper->second;
343 return pHelper;
346 void FrameworkHelper::DisposeInstance (const ViewShellBase& rBase)
348 InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
349 if (iHelper != maInstanceMap.end())
351 iHelper->second->Dispose();
355 void FrameworkHelper::ReleaseInstance (const ViewShellBase& rBase)
357 InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
358 if (iHelper != maInstanceMap.end())
359 maInstanceMap.erase(iHelper);
362 FrameworkHelper::FrameworkHelper (ViewShellBase& rBase)
363 : mrBase(rBase),
364 mxConfigurationController(),
365 mxDisposeListener()
368 Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY);
369 if (xControllerManager.is())
371 mxConfigurationController = xControllerManager->getConfigurationController();
374 new LifetimeController(mrBase);
377 void FrameworkHelper::Initialize()
379 mxDisposeListener = new DisposeListener(shared_from_this());
382 FrameworkHelper::~FrameworkHelper()
386 void FrameworkHelper::Dispose()
388 if (mxDisposeListener.is())
389 mxDisposeListener->dispose();
390 mxConfigurationController = nullptr;
393 bool FrameworkHelper::IsValid()
395 return mxConfigurationController.is();
398 ::std::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const OUString& rsPaneURL)
400 if ( !mxConfigurationController.is() )
401 return ::std::shared_ptr<ViewShell>();
403 Reference<XResourceId> xPaneId( CreateResourceId( rsPaneURL ) );
404 return lcl_getViewShell( lcl_getFirstViewInPane( mxConfigurationController, xPaneId ) );
407 ::std::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const Reference<XView>& rxView)
409 return lcl_getViewShell( rxView.get() );
412 Reference<XView> FrameworkHelper::GetView (const Reference<XResourceId>& rxPaneOrViewId)
414 Reference<XView> xView;
416 if ( ! rxPaneOrViewId.is() || ! mxConfigurationController.is())
417 return nullptr;
421 if (rxPaneOrViewId->getResourceURL().match(msViewURLPrefix))
423 xView.set( mxConfigurationController->getResource( rxPaneOrViewId ), UNO_QUERY );
425 else
427 xView.set( lcl_getFirstViewInPane( mxConfigurationController, rxPaneOrViewId ), UNO_QUERY );
430 catch (lang::DisposedException&)
432 Dispose();
434 catch (RuntimeException&)
438 return xView;
441 Reference<XResourceId> FrameworkHelper::RequestView (
442 const OUString& rsResourceURL,
443 const OUString& rsAnchorURL)
445 Reference<XResourceId> xViewId;
449 if (mxConfigurationController.is())
451 mxConfigurationController->requestResourceActivation(
452 CreateResourceId(rsAnchorURL),
453 ResourceActivationMode_ADD);
454 xViewId = CreateResourceId(rsResourceURL, rsAnchorURL);
455 mxConfigurationController->requestResourceActivation(
456 xViewId,
457 ResourceActivationMode_REPLACE);
460 catch (lang::DisposedException&)
462 Dispose();
463 xViewId = nullptr;
465 catch (RuntimeException&)
467 xViewId = nullptr;
470 return xViewId;
473 ViewShell::ShellType FrameworkHelper::GetViewId (const OUString& rsViewURL)
475 if (mpViewURLMap->empty())
477 (*mpViewURLMap)[msImpressViewURL] = ViewShell::ST_IMPRESS;
478 (*mpViewURLMap)[msDrawViewURL] = ViewShell::ST_DRAW;
479 (*mpViewURLMap)[msOutlineViewURL] = ViewShell::ST_OUTLINE;
480 (*mpViewURLMap)[msNotesViewURL] = ViewShell::ST_NOTES;
481 (*mpViewURLMap)[msHandoutViewURL] = ViewShell::ST_HANDOUT;
482 (*mpViewURLMap)[msSlideSorterURL] = ViewShell::ST_SLIDE_SORTER;
483 (*mpViewURLMap)[msPresentationViewURL] = ViewShell::ST_PRESENTATION;
484 (*mpViewURLMap)[msSidebarViewURL] = ViewShell::ST_SIDEBAR;
486 ViewURLMap::const_iterator iView (mpViewURLMap->find(rsViewURL));
487 if (iView != mpViewURLMap->end())
488 return iView->second;
489 else
490 return ViewShell::ST_NONE;
493 OUString FrameworkHelper::GetViewURL (ViewShell::ShellType eType)
495 switch (eType)
497 case ViewShell::ST_IMPRESS : return msImpressViewURL;
498 case ViewShell::ST_DRAW : return msDrawViewURL;
499 case ViewShell::ST_OUTLINE : return msOutlineViewURL;
500 case ViewShell::ST_NOTES : return msNotesViewURL;
501 case ViewShell::ST_HANDOUT : return msHandoutViewURL;
502 case ViewShell::ST_SLIDE_SORTER : return msSlideSorterURL;
503 case ViewShell::ST_PRESENTATION : return msPresentationViewURL;
504 case ViewShell::ST_SIDEBAR : return msSidebarViewURL;
505 default:
506 return OUString();
510 namespace
513 void updateEditMode(const Reference<XView> &xView, const EditMode eEMode, bool updateFrameView)
515 // Ensure we have the expected edit mode
516 // The check is only for DrawViewShell as OutlineViewShell
517 // and SlideSorterViewShell have no master mode
518 const ::std::shared_ptr<ViewShell> pCenterViewShell (FrameworkHelper::GetViewShell(xView));
519 DrawViewShell* pDrawViewShell
520 = dynamic_cast<DrawViewShell*>(pCenterViewShell.get());
521 if (pDrawViewShell != nullptr)
523 pCenterViewShell->Broadcast (
524 ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_START));
526 pDrawViewShell->ChangeEditMode(eEMode, pDrawViewShell->IsLayerModeActive());
527 if (updateFrameView)
528 pDrawViewShell->WriteFrameViewData();
530 pCenterViewShell->Broadcast (
531 ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_END));
535 void asyncUpdateEditMode(FrameworkHelper* const pHelper, const EditMode eEMode)
537 Reference<XResourceId> xPaneId (
538 FrameworkHelper::CreateResourceId(framework::FrameworkHelper::msCenterPaneURL));
539 Reference<XView> xView (pHelper->GetView(xPaneId));
540 updateEditMode(xView, eEMode, true);
545 void FrameworkHelper::HandleModeChangeSlot (
546 sal_uLong nSlotId,
547 SfxRequest const & rRequest)
549 if ( ! mxConfigurationController.is())
550 return;
552 // Parameters are allowed for NotesMasterPage and SlideMasterPage
553 // for these command, transfor xxxxMasterPage with param = false
554 // to ActivatexxxxxMode
555 if (nSlotId == SID_NOTES_MASTER_MODE || nSlotId == SID_SLIDE_MASTER_MODE)
557 const SfxItemSet* pRequestArguments = rRequest.GetArgs();
558 if (pRequestArguments)
560 const SfxBoolItem* pIsActive = rRequest.GetArg<SfxBoolItem>(static_cast<sal_uInt16>(nSlotId));
561 if (!pIsActive->GetValue ())
563 if (nSlotId == SID_NOTES_MASTER_MODE)
564 nSlotId = SID_NOTES_MODE;
565 else
566 nSlotId = SID_NORMAL_MULTI_PANE_GUI;
573 if ( ! mxConfigurationController.is())
574 throw RuntimeException();
576 Reference<XResourceId> xPaneId (
577 CreateResourceId(framework::FrameworkHelper::msCenterPaneURL));
578 Reference<XView> xView (GetView(xPaneId));
580 // Compute requested view
581 OUString sRequestedView;
582 switch (nSlotId)
584 // draw
585 case SID_DRAWINGMODE:
586 // impress
587 case SID_NORMAL_MULTI_PANE_GUI:
588 case SID_SLIDE_MASTER_MODE:
589 sRequestedView = FrameworkHelper::msImpressViewURL;
590 break;
592 case SID_NOTES_MODE:
593 case SID_NOTES_MASTER_MODE:
594 sRequestedView = FrameworkHelper::msNotesViewURL;
595 break;
597 case SID_HANDOUT_MASTER_MODE:
598 sRequestedView = FrameworkHelper::msHandoutViewURL;
599 break;
601 case SID_SLIDE_SORTER_MULTI_PANE_GUI:
602 case SID_SLIDE_SORTER_MODE:
603 sRequestedView = FrameworkHelper::msSlideSorterURL;
604 break;
606 case SID_OUTLINE_MODE:
607 sRequestedView = FrameworkHelper::msOutlineViewURL;
608 break;
611 // Compute requested mode
612 EditMode eEMode = EditMode::Page;
613 if (nSlotId == SID_SLIDE_MASTER_MODE
614 || nSlotId == SID_NOTES_MASTER_MODE
615 || nSlotId == SID_HANDOUT_MASTER_MODE)
616 eEMode = EditMode::MasterPage;
617 // Ensure we have the expected view shell
618 if (!(xView.is() && xView->getResourceId()->getResourceURL() == sRequestedView))
621 const auto xId = CreateResourceId(sRequestedView, msCenterPaneURL);
622 mxConfigurationController->requestResourceActivation(
623 xId,
624 ResourceActivationMode_REPLACE);
625 RunOnResourceActivation(xId, std::bind(&asyncUpdateEditMode, this, eEMode));
627 else
629 updateEditMode(xView, eEMode, false);
632 catch (RuntimeException&)
634 DBG_UNHANDLED_EXCEPTION("sd");
638 void FrameworkHelper::RunOnConfigurationEvent(
639 const OUString& rsEventType,
640 const Callback& rCallback)
642 RunOnEvent(
643 rsEventType,
644 FrameworkHelperAllPassFilter(),
645 rCallback);
648 void FrameworkHelper::RunOnResourceActivation(
649 const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
650 const Callback& rCallback)
652 if (mxConfigurationController.is()
653 && mxConfigurationController->getResource(rxResourceId).is())
655 rCallback(false);
657 else
659 RunOnEvent(
660 msResourceActivationEvent,
661 FrameworkHelperResourceIdFilter(rxResourceId),
662 rCallback);
666 /** A callback that sets a flag to a specified value when the callback is
667 called.
669 class FlagUpdater
671 public:
672 explicit FlagUpdater (bool& rFlag) : mrFlag(rFlag) {}
673 void operator() (bool) const {mrFlag = true;}
674 private:
675 bool& mrFlag;
678 void FrameworkHelper::RequestSynchronousUpdate()
680 rtl::Reference<ConfigurationController> pCC (
681 dynamic_cast<ConfigurationController*>(mxConfigurationController.get()));
682 if (pCC.is())
683 pCC->RequestSynchronousUpdate();
686 void FrameworkHelper::WaitForEvent (const OUString& rsEventType) const
688 bool bConfigurationUpdateSeen (false);
690 RunOnEvent(
691 rsEventType,
692 FrameworkHelperAllPassFilter(),
693 FlagUpdater(bConfigurationUpdateSeen));
695 sal_uInt32 nStartTime = osl_getGlobalTimer();
696 while ( ! bConfigurationUpdateSeen)
698 Application::Reschedule();
700 if( (osl_getGlobalTimer() - nStartTime) > 60000 )
702 OSL_FAIL("FrameworkHelper::WaitForEvent(), no event for a minute? giving up!");
703 break;
708 void FrameworkHelper::WaitForUpdate() const
710 WaitForEvent(msConfigurationUpdateEndEvent);
713 void FrameworkHelper::RunOnEvent(
714 const OUString& rsEventType,
715 const ConfigurationChangeEventFilter& rFilter,
716 const Callback& rCallback) const
718 new CallbackCaller(mrBase,rsEventType,rFilter,rCallback);
721 void FrameworkHelper::disposing (const lang::EventObject& rEventObject)
723 if (rEventObject.Source == mxConfigurationController)
724 mxConfigurationController = nullptr;
727 void FrameworkHelper::UpdateConfiguration()
729 if (!mxConfigurationController.is())
730 return;
734 if (mxConfigurationController.is())
735 mxConfigurationController->update();
737 catch (lang::DisposedException&)
739 Dispose();
741 catch (RuntimeException&)
743 DBG_UNHANDLED_EXCEPTION("sd");
747 OUString FrameworkHelper::ResourceIdToString (const Reference<XResourceId>& rxResourceId)
749 OUStringBuffer sString;
750 if (rxResourceId.is())
752 sString.append(rxResourceId->getResourceURL());
753 if (rxResourceId->hasAnchor())
755 const Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
756 for (const auto& rAnchorURL : aAnchorURLs)
758 sString.append(" | ");
759 sString.append(rAnchorURL);
763 return sString.makeStringAndClear();
766 Reference<XResourceId> FrameworkHelper::CreateResourceId (const OUString& rsResourceURL)
768 return new ::sd::framework::ResourceId(rsResourceURL);
771 Reference<XResourceId> FrameworkHelper::CreateResourceId (
772 const OUString& rsResourceURL,
773 const OUString& rsAnchorURL)
775 return new ::sd::framework::ResourceId(rsResourceURL, rsAnchorURL);
778 Reference<XResourceId> FrameworkHelper::CreateResourceId (
779 const OUString& rsResourceURL,
780 const Reference<XResourceId>& rxAnchorId)
782 if (rxAnchorId.is())
783 return new ::sd::framework::ResourceId(
784 rsResourceURL,
785 rxAnchorId->getResourceURL(),
786 rxAnchorId->getAnchorURLs());
787 else
788 return new ::sd::framework::ResourceId(rsResourceURL);
791 //----- FrameworkHelper::DisposeListener --------------------------------------
793 FrameworkHelper::DisposeListener::DisposeListener (
794 const ::std::shared_ptr<FrameworkHelper>& rpHelper)
795 : FrameworkHelperDisposeListenerInterfaceBase(maMutex),
796 mpHelper(rpHelper)
798 Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
799 if (xComponent.is())
800 xComponent->addEventListener(this);
803 void SAL_CALL FrameworkHelper::DisposeListener::disposing()
805 Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
806 if (xComponent.is())
807 xComponent->removeEventListener(this);
809 mpHelper.reset();
812 void SAL_CALL FrameworkHelper::DisposeListener::disposing (const lang::EventObject& rEventObject)
814 if (mpHelper != nullptr)
815 mpHelper->disposing(rEventObject);
818 //===== FrameworkHelperResourceIdFilter =======================================
820 FrameworkHelperResourceIdFilter::FrameworkHelperResourceIdFilter (
821 const Reference<XResourceId>& rxResourceId)
822 : mxResourceId(rxResourceId)
826 } } // end of namespace sd::framework
828 namespace {
830 //===== CallbackCaller ========================================================
832 CallbackCaller::CallbackCaller (
833 const ::sd::ViewShellBase& rBase,
834 const OUString& rsEventType,
835 const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter,
836 const ::sd::framework::FrameworkHelper::Callback& rCallback)
837 : CallbackCallerInterfaceBase(MutexOwner::maMutex),
838 msEventType(rsEventType),
839 mxConfigurationController(),
840 maFilter(rFilter),
841 maCallback(rCallback)
845 Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY_THROW);
846 mxConfigurationController = xControllerManager->getConfigurationController();
847 if (mxConfigurationController.is())
849 if (mxConfigurationController->hasPendingRequests())
850 mxConfigurationController->addConfigurationChangeListener(this,msEventType,Any());
851 else
853 // There are no requests waiting to be processed. Therefore
854 // no event, especially not the one we are waiting for, will
855 // be sent in the near future and the callback would never be
856 // called.
857 // Call the callback now and tell him that the event it is
858 // waiting for was not sent.
859 mxConfigurationController = nullptr;
860 maCallback(false);
864 catch (RuntimeException&)
866 DBG_UNHANDLED_EXCEPTION("sd");
870 void CallbackCaller::disposing()
874 if (mxConfigurationController.is())
876 Reference<XConfigurationController> xCC (mxConfigurationController);
877 mxConfigurationController = nullptr;
878 xCC->removeConfigurationChangeListener(this);
881 catch (RuntimeException&)
883 DBG_UNHANDLED_EXCEPTION("sd");
887 void SAL_CALL CallbackCaller::disposing (const lang::EventObject& rEvent)
889 if (rEvent.Source == mxConfigurationController)
891 mxConfigurationController = nullptr;
892 maCallback(false);
896 void SAL_CALL CallbackCaller::notifyConfigurationChange (
897 const ConfigurationChangeEvent& rEvent)
899 if (!(rEvent.Type == msEventType && maFilter(rEvent)))
900 return;
902 maCallback(true);
903 if (mxConfigurationController.is())
905 // Reset the reference to the configuration controller so that
906 // dispose() will not try to remove the listener a second time.
907 Reference<XConfigurationController> xCC (mxConfigurationController);
908 mxConfigurationController = nullptr;
910 // Removing this object from the controller may very likely lead
911 // to its destruction, so no calls after that.
912 xCC->removeConfigurationChangeListener(this);
916 //----- LifetimeController -------------------------------------------------
918 LifetimeController::LifetimeController (::sd::ViewShellBase& rBase)
919 : LifetimeControllerInterfaceBase(maMutex),
920 mrBase(rBase),
921 mbListeningToViewShellBase(false),
922 mbListeningToController(false)
924 // Register as listener at the ViewShellBase. Because that is not done
925 // via a reference we have to increase the reference count manually.
926 // This is necessary even though listening to the XController did
927 // increase the reference count because the controller may release its
928 // reference to us before the ViewShellBase is destroyed.
929 StartListening(mrBase);
930 acquire();
931 mbListeningToViewShellBase = true;
933 Reference<XComponent> xComponent = rBase.GetController();
934 if (xComponent.is())
936 xComponent->addEventListener(this);
937 mbListeningToController = true;
941 LifetimeController::~LifetimeController()
943 OSL_ASSERT(!mbListeningToController && !mbListeningToViewShellBase);
946 void LifetimeController::disposing()
950 void SAL_CALL LifetimeController::disposing (const lang::EventObject&)
952 mbListeningToController = false;
953 Update();
956 void LifetimeController::Notify (SfxBroadcaster&, const SfxHint& rHint)
958 if (rHint.GetId() == SfxHintId::Dying)
960 mbListeningToViewShellBase = false;
961 Update();
962 release();
966 void LifetimeController::Update()
968 if (mbListeningToViewShellBase && mbListeningToController)
970 // Both the controller and the ViewShellBase are alive. Keep
971 // waiting for their destruction.
973 else if (mbListeningToViewShellBase)
975 // The controller has been destroyed but the ViewShellBase is still
976 // alive. Dispose the associated FrameworkHelper but keep it around
977 // so that no new instance is created for the dying framework.
978 ::sd::framework::FrameworkHelper::DisposeInstance(mrBase);
980 else
982 // Both the controller and the ViewShellBase have been destroyed.
983 // Remove the FrameworkHelper so that the next call its Instance()
984 // method can create a new instance.
985 ::sd::framework::FrameworkHelper::ReleaseInstance(mrBase);
989 } // end of anonymous namespace.
991 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */