1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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>
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>
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
;
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.
64 : public ::sd::MutexOwner
,
65 public CallbackCallerInterfaceBase
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
76 This ViewShellBase object is used to determine the
77 XConfigurationController at which to register.
79 The event type which the callback is waiting for.
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.
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
;
94 virtual void SAL_CALL
disposing (const lang::EventObject
& rEvent
) override
;
95 // XConfigurationChangeListener
96 virtual void SAL_CALL
notifyConfigurationChange (const ConfigurationChangeEvent
& rEvent
) override
;
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
,
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
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
;
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.
148 } // end of anonymous namespace
150 namespace sd
{ namespace framework
{
154 class FrameworkHelperAllPassFilter
157 bool operator() (const css::drawing::framework::ConfigurationChangeEvent
&) { return true; }
160 class FrameworkHelperResourceIdFilter
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; }
169 css::uno::Reference
<css::drawing::framework::XResourceId
> mxResourceId
;
172 } // end of anonymous namespace
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");
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");
197 const OUString
FrameworkHelper::msToolBarURLPrefix("private:resource/toolbar/");
198 const OUString
FrameworkHelper::msViewTabBarURL( msToolBarURLPrefix
+ "ViewTabBar");
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" );
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 ----------------------------------------------------------------
226 ::std::shared_ptr
< ViewShell
> lcl_getViewShell( const Reference
< XResource
>& i_rViewShellWrapper
)
228 ::std::shared_ptr
< ViewShell
> pViewShell
;
229 if ( !i_rViewShellWrapper
.is() )
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");
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");
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
<
271 ViewShell::ShellType
>
277 //----- Framework::DiposeListener ---------------------------------------------
280 typedef ::cppu::WeakComponentImplHelper
<
281 css::lang::XEventListener
282 > FrameworkHelperDisposeListenerInterfaceBase
;
285 class FrameworkHelper::DisposeListener
286 : public ::sd::MutexOwner
,
287 public FrameworkHelperDisposeListenerInterfaceBase
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
;
297 ::std::shared_ptr
<FrameworkHelper
> mpHelper
;
300 //----- FrameworkHelper::Deleter ----------------------------------------------
302 class FrameworkHelper::Deleter
305 void operator()(FrameworkHelper
* 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
;
339 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
340 pHelper
= iHelper
->second
;
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
)
364 mxConfigurationController(),
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())
421 if (rxPaneOrViewId
->getResourceURL().match(msViewURLPrefix
))
423 xView
.set( mxConfigurationController
->getResource( rxPaneOrViewId
), UNO_QUERY
);
427 xView
.set( lcl_getFirstViewInPane( mxConfigurationController
, rxPaneOrViewId
), UNO_QUERY
);
430 catch (lang::DisposedException
&)
434 catch (RuntimeException
&)
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(
457 ResourceActivationMode_REPLACE
);
460 catch (lang::DisposedException
&)
465 catch (RuntimeException
&)
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
;
490 return ViewShell::ST_NONE
;
493 OUString
FrameworkHelper::GetViewURL (ViewShell::ShellType 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
;
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());
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 (
547 SfxRequest
const & rRequest
)
549 if ( ! mxConfigurationController
.is())
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
;
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
;
585 case SID_DRAWINGMODE
:
587 case SID_NORMAL_MULTI_PANE_GUI
:
588 case SID_SLIDE_MASTER_MODE
:
589 sRequestedView
= FrameworkHelper::msImpressViewURL
;
593 case SID_NOTES_MASTER_MODE
:
594 sRequestedView
= FrameworkHelper::msNotesViewURL
;
597 case SID_HANDOUT_MASTER_MODE
:
598 sRequestedView
= FrameworkHelper::msHandoutViewURL
;
601 case SID_SLIDE_SORTER_MULTI_PANE_GUI
:
602 case SID_SLIDE_SORTER_MODE
:
603 sRequestedView
= FrameworkHelper::msSlideSorterURL
;
606 case SID_OUTLINE_MODE
:
607 sRequestedView
= FrameworkHelper::msOutlineViewURL
;
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(
624 ResourceActivationMode_REPLACE
);
625 RunOnResourceActivation(xId
, std::bind(&asyncUpdateEditMode
, this, eEMode
));
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
)
644 FrameworkHelperAllPassFilter(),
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())
660 msResourceActivationEvent
,
661 FrameworkHelperResourceIdFilter(rxResourceId
),
666 /** A callback that sets a flag to a specified value when the callback is
672 explicit FlagUpdater (bool& rFlag
) : mrFlag(rFlag
) {}
673 void operator() (bool) const {mrFlag
= true;}
678 void FrameworkHelper::RequestSynchronousUpdate()
680 rtl::Reference
<ConfigurationController
> pCC (
681 dynamic_cast<ConfigurationController
*>(mxConfigurationController
.get()));
683 pCC
->RequestSynchronousUpdate();
686 void FrameworkHelper::WaitForEvent (const OUString
& rsEventType
) const
688 bool bConfigurationUpdateSeen (false);
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!");
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())
734 if (mxConfigurationController
.is())
735 mxConfigurationController
->update();
737 catch (lang::DisposedException
&)
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
)
783 return new ::sd::framework::ResourceId(
785 rxAnchorId
->getResourceURL(),
786 rxAnchorId
->getAnchorURLs());
788 return new ::sd::framework::ResourceId(rsResourceURL
);
791 //----- FrameworkHelper::DisposeListener --------------------------------------
793 FrameworkHelper::DisposeListener::DisposeListener (
794 const ::std::shared_ptr
<FrameworkHelper
>& rpHelper
)
795 : FrameworkHelperDisposeListenerInterfaceBase(maMutex
),
798 Reference
<XComponent
> xComponent (mpHelper
->mxConfigurationController
, UNO_QUERY
);
800 xComponent
->addEventListener(this);
803 void SAL_CALL
FrameworkHelper::DisposeListener::disposing()
805 Reference
<XComponent
> xComponent (mpHelper
->mxConfigurationController
, UNO_QUERY
);
807 xComponent
->removeEventListener(this);
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
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(),
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());
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
857 // Call the callback now and tell him that the event it is
858 // waiting for was not sent.
859 mxConfigurationController
= nullptr;
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;
896 void SAL_CALL
CallbackCaller::notifyConfigurationChange (
897 const ConfigurationChangeEvent
& rEvent
)
899 if (!(rEvent
.Type
== msEventType
&& maFilter(rEvent
)))
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
),
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
);
931 mbListeningToViewShellBase
= true;
933 Reference
<XComponent
> xComponent
= rBase
.GetController();
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;
956 void LifetimeController::Notify (SfxBroadcaster
&, const SfxHint
& rHint
)
958 if (rHint
.GetId() == SfxHintId::Dying
)
960 mbListeningToViewShellBase
= false;
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
);
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: */