xref: /trunk/main/sd/source/ui/framework/tools/FrameworkHelper.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 #include "precompiled_sd.hxx"
23 
24 #include <osl/time.h>
25 
26 #include "framework/FrameworkHelper.hxx"
27 
28 #include "framework/ConfigurationController.hxx"
29 #include "framework/ResourceId.hxx"
30 #include "framework/ViewShellWrapper.hxx"
31 #include "ViewShellBase.hxx"
32 #include "FrameView.hxx"
33 #include "DrawViewShell.hxx"
34 #include "ViewShellHint.hxx"
35 #include "DrawController.hxx"
36 #include "app.hrc"
37 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
38 #include <com/sun/star/drawing/framework/XPane.hpp>
39 #include <cppuhelper/compbase1.hxx>
40 #include <svl/lstner.hxx>
41 
42 #include <comphelper/stl_types.hxx>
43 #include <sfx2/request.hxx>
44 #include <sfx2/dispatch.hxx>
45 
46 #include "MutexOwner.hxx"
47 #include "vcl/svapp.hxx"
48 #include <osl/doublecheckedlocking.h>
49 #include <osl/getglobalmutex.hxx>
50 #include <tools/diagnose_ex.h>
51 
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::drawing::framework;
55 
56 using ::rtl::OUString;
57 
58 namespace {
59 
60 
61 //----- CallbackCaller --------------------------------------------------------
62 
63 typedef ::cppu::WeakComponentImplHelper1 <
64     ::com::sun::star::drawing::framework::XConfigurationChangeListener
65     > CallbackCallerInterfaceBase;
66 
67 /** A CallbackCaller registers as listener at an XConfigurationController
68     object and waits for the notification of one type of event.  When that
69     event is received, or when the CallbackCaller detects at its
70     construction that the event will not be sent in the near future, the
71     actual callback object is called and the CallbackCaller destroys itself.
72 */
73 class CallbackCaller
74     : public ::sd::MutexOwner,
75       public CallbackCallerInterfaceBase
76 {
77 public:
78     /** Create a new CallbackCaller object.  This object controls its own
79         lifetime by acquiring a reference to itself in the constructor.
80         When it detects that the event will not be notified in the near
81         future (because the queue of pending configuration change operations
82         is empty and therefore no event will be sent int the near future, it
83         does not acquires a reference and thus initiates its destruction in
84         the constructor.)
85         @param rBase
86             This ViewShellBase object is used to determine the
87             XConfigurationController at which to register.
88         @param rsEventType
89             The event type which the callback is waiting for.
90         @param pCallback
91             The callback object which is to be notified.  The caller will
92             typically release his reference to the caller so that when the
93             CallbackCaller dies (after having called the callback) the
94             callback is destroyed.
95     */
96     CallbackCaller (
97         ::sd::ViewShellBase& rBase,
98         const OUString& rsEventType,
99         const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter,
100         const ::sd::framework::FrameworkHelper::Callback& rCallback);
101     virtual ~CallbackCaller (void);
102 
103     virtual void SAL_CALL disposing (void);
104     // XEventListener
105     virtual void SAL_CALL disposing (const lang::EventObject& rEvent);
106     // XConfigurationChangeListener
107     virtual void SAL_CALL notifyConfigurationChange (const ConfigurationChangeEvent& rEvent);
108 
109 private:
110     OUString msEventType;
111     Reference<XConfigurationController> mxConfigurationController;
112     ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter maFilter;
113     ::sd::framework::FrameworkHelper::Callback maCallback;
114 };
115 
116 
117 
118 
119 //----- LifetimeController ----------------------------------------------------
120 
121 typedef ::cppu::WeakComponentImplHelper1 <
122     ::com::sun::star::lang::XEventListener
123     > LifetimeControllerInterfaceBase;
124 
125 /** This class helps controlling the lifetime of the
126     FrameworkHelper. Register at a ViewShellBase object and an XController
127     object and call Dispose() at the associated FrameworkHelper object when
128     one of them and Release() when both of them are destroyed.
129 */
130 class LifetimeController
131     : public ::sd::MutexOwner,
132       public LifetimeControllerInterfaceBase,
133       public SfxListener
134 {
135 public:
136     explicit LifetimeController (::sd::ViewShellBase& rBase);
137     virtual ~LifetimeController (void);
138 
139     virtual void SAL_CALL disposing (void);
140 
141     /** XEventListener.  This method is called when the frame::XController
142         is being destroyed.
143     */
144     virtual void SAL_CALL disposing (const lang::EventObject& rEvent);
145 
146     /** This method is called when the ViewShellBase is being destroyed.
147     */
148     virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint);
149 
150 private:
151     ::sd::ViewShellBase& mrBase;
152     bool mbListeningToViewShellBase;
153     bool mbListeningToController;
154 
155     /** When one or both of the mbListeningToViewShellBase and
156         mbListeningToController members were modified then call this method
157         to either dispose or release the associated FrameworkHelper.
158     */
159     void Update (void);
160 };
161 
162 
163 
164 } // end of anonymous namespace
165 
166 namespace sd { namespace framework {
167 
168 // Pane URLS.
169 
170 const OUString FrameworkHelper::msPaneURLPrefix(
171     OUString::createFromAscii("private:resource/pane/"));
172 const OUString FrameworkHelper::msCenterPaneURL(
173     msPaneURLPrefix + OUString::createFromAscii("CenterPane"));
174 const OUString FrameworkHelper::msFullScreenPaneURL(
175     msPaneURLPrefix + OUString::createFromAscii("FullScreenPane"));
176 const OUString FrameworkHelper::msLeftImpressPaneURL(
177     msPaneURLPrefix + OUString::createFromAscii("LeftImpressPane"));
178 const OUString FrameworkHelper::msLeftDrawPaneURL(
179     msPaneURLPrefix + OUString::createFromAscii("LeftDrawPane"));
180 const OUString FrameworkHelper::msSidebarPaneURL(
181     msPaneURLPrefix + OUString::createFromAscii("SidebarPane"));
182 
183 
184 // View URLs.
185 
186 const OUString FrameworkHelper::msViewURLPrefix(
187     OUString::createFromAscii("private:resource/view/"));
188 const OUString FrameworkHelper::msImpressViewURL(
189     msViewURLPrefix + OUString::createFromAscii("ImpressView"));
190 const OUString FrameworkHelper::msDrawViewURL(
191     msViewURLPrefix + OUString::createFromAscii("GraphicView"));
192 const OUString FrameworkHelper::msOutlineViewURL(
193     msViewURLPrefix + OUString::createFromAscii("OutlineView"));
194 const OUString FrameworkHelper::msNotesViewURL(
195     msViewURLPrefix + OUString::createFromAscii("NotesView"));
196 const OUString FrameworkHelper::msHandoutViewURL(
197     msViewURLPrefix + OUString::createFromAscii("HandoutView"));
198 const OUString FrameworkHelper::msSlideSorterURL(
199     msViewURLPrefix + OUString::createFromAscii("SlideSorter"));
200 const OUString FrameworkHelper::msPresentationViewURL(
201     msViewURLPrefix + OUString::createFromAscii("PresentationView"));
202 const OUString FrameworkHelper::msSidebarViewURL(
203     msViewURLPrefix + OUString::createFromAscii("SidebarView"));
204 
205 
206 // Tool bar URLs.
207 
208 const OUString FrameworkHelper::msToolBarURLPrefix(
209     OUString::createFromAscii("private:resource/toolbar/"));
210 const OUString FrameworkHelper::msViewTabBarURL(
211     msToolBarURLPrefix + OUString::createFromAscii("ViewTabBar"));
212 
213 
214 // Task panel URLs.
215 const ::rtl::OUString FrameworkHelper::msTaskPanelURLPrefix(
216     OUString::createFromAscii("private:resource/toolpanel/"));
217 const ::rtl::OUString FrameworkHelper::msAllMasterPagesTaskPanelURL(
218     msTaskPanelURLPrefix + OUString::createFromAscii("AllMasterPages"));
219 const ::rtl::OUString FrameworkHelper::msRecentMasterPagesTaskPanelURL(
220     msTaskPanelURLPrefix + OUString::createFromAscii("RecentMasterPages"));
221 const ::rtl::OUString FrameworkHelper::msUsedMasterPagesTaskPanelURL(
222     msTaskPanelURLPrefix + OUString::createFromAscii("UsedMasterPages"));
223 const ::rtl::OUString FrameworkHelper::msLayoutTaskPanelURL(
224     msTaskPanelURLPrefix + OUString::createFromAscii("Layouts"));
225 const ::rtl::OUString FrameworkHelper::msTableDesignPanelURL(
226     msTaskPanelURLPrefix + OUString::createFromAscii("TableDesign"));
227 const ::rtl::OUString FrameworkHelper::msCustomAnimationTaskPanelURL(
228     msTaskPanelURLPrefix + OUString::createFromAscii("CustomAnimations"));
229 const ::rtl::OUString FrameworkHelper::msSlideTransitionTaskPanelURL(
230     msTaskPanelURLPrefix + OUString::createFromAscii("SlideTransitions"));
231 
232 
233 // Event URLs.
234 const OUString FrameworkHelper::msResourceActivationRequestEvent(
235     OUString::createFromAscii("ResourceActivationRequested"));
236 const OUString FrameworkHelper::msResourceDeactivationRequestEvent(
237     OUString::createFromAscii("ResourceDeactivationRequest"));
238 const OUString FrameworkHelper::msResourceActivationEvent(
239     OUString::createFromAscii("ResourceActivation"));
240 const OUString FrameworkHelper::msResourceDeactivationEvent(
241     OUString::createFromAscii("ResourceDeactivation"));
242 const OUString FrameworkHelper::msResourceDeactivationEndEvent(
243     OUString::createFromAscii("ResourceDeactivationEnd"));
244 const OUString FrameworkHelper::msConfigurationUpdateStartEvent(
245     OUString::createFromAscii("ConfigurationUpdateStart"));
246 const OUString FrameworkHelper::msConfigurationUpdateEndEvent(
247     OUString::createFromAscii("ConfigurationUpdateEnd"));
248 
249 
250 // Service names of controllers.
251 const OUString FrameworkHelper::msModuleControllerService(
252     OUString::createFromAscii("com.sun.star.drawing.framework.ModuleController"));
253 const OUString FrameworkHelper::msConfigurationControllerService(
254     OUString::createFromAscii("com.sun.star.drawing.framework.ConfigurationController"));
255 
256 //----- helper ----------------------------------------------------------------
257 namespace
258 {
lcl_getViewShell(const Reference<XResource> & i_rViewShellWrapper)259     static ::boost::shared_ptr< ViewShell > lcl_getViewShell( const Reference< XResource >& i_rViewShellWrapper )
260     {
261         ::boost::shared_ptr< ViewShell > pViewShell;
262         if ( !i_rViewShellWrapper.is() )
263             return pViewShell;
264 
265         try
266         {
267             Reference<lang::XUnoTunnel> xViewTunnel( i_rViewShellWrapper, UNO_QUERY_THROW );
268             pViewShell = reinterpret_cast< ViewShellWrapper* >(
269                 xViewTunnel->getSomething( ViewShellWrapper::getUnoTunnelId() ) )->GetViewShell();
270         }
271         catch( const Exception& )
272         {
273             DBG_UNHANDLED_EXCEPTION();
274         }
275         return pViewShell;
276     }
lcl_getFirstViewInPane(const Reference<XConfigurationController> & i_rConfigController,const Reference<XResourceId> & i_rPaneId)277     Reference< XResource > lcl_getFirstViewInPane( const Reference< XConfigurationController >& i_rConfigController,
278         const Reference< XResourceId >& i_rPaneId )
279     {
280         try
281         {
282             Reference< XConfiguration > xConfiguration( i_rConfigController->getRequestedConfiguration(), UNO_SET_THROW );
283             Sequence< Reference< XResourceId > > aViewIds( xConfiguration->getResources(
284                 i_rPaneId, FrameworkHelper::msViewURLPrefix, AnchorBindingMode_DIRECT ) );
285             if ( aViewIds.getLength() > 0 )
286                 return i_rConfigController->getResource( aViewIds[0] );
287         }
288         catch( const Exception& )
289         {
290             DBG_UNHANDLED_EXCEPTION();
291         }
292         return NULL;
293     }
294 }
295 
296 
297 //----- FrameworkHelper::ViewURLMap -------------------------------------------
298 
299 /** The ViewURLMap is used to translate between the view URLs used by the
300     drawing framework and the enums defined in the ViewShell class.
301 */
302 class FrameworkHelper::ViewURLMap
303     : public ::std::hash_map<
304           rtl::OUString,
305           ViewShell::ShellType,
306           ::comphelper::UStringHash,
307           ::comphelper::UStringEqual>
308 {
309 public:
ViewURLMap(void)310     ViewURLMap (void) {}
311 };
312 
313 
314 
315 
316 //----- Framework::DiposeListener ---------------------------------------------
317 
318 namespace {
319     typedef ::cppu::WeakComponentImplHelper1 <
320         ::com::sun::star::lang::XEventListener
321         > FrameworkHelperDisposeListenerInterfaceBase;
322 }
323 
324 class FrameworkHelper::DisposeListener
325     : public ::sd::MutexOwner,
326       public FrameworkHelperDisposeListenerInterfaceBase
327 {
328 public:
329     DisposeListener (const ::boost::shared_ptr<FrameworkHelper>& rpHelper);
330     ~DisposeListener (void);
331 
332     virtual void SAL_CALL disposing (void);
333 
334     virtual void SAL_CALL disposing (const lang::EventObject& rEventObject);
335 
336 private:
337     ::boost::shared_ptr<FrameworkHelper> mpHelper;
338 };
339 
340 
341 
342 
343 //----- FrameworkHelper::Deleter ----------------------------------------------
344 
345 class FrameworkHelper::Deleter
346 {
347 public:
operator ()(FrameworkHelper * pObject)348     void operator()(FrameworkHelper* pObject)
349     {
350         delete pObject;
351     }
352 };
353 
354 
355 
356 
357 //----- FrameworkHelper -------------------------------------------------------
358 
359 ::boost::scoped_ptr<FrameworkHelper::ViewURLMap> FrameworkHelper::mpViewURLMap(new ViewURLMap());
360 
361 
362 FrameworkHelper::InstanceMap FrameworkHelper::maInstanceMap;
363 
364 
365 
Instance(const Reference<frame::XController> & rxController)366 ::boost::shared_ptr<FrameworkHelper> FrameworkHelper::Instance (
367     const Reference<frame::XController>& rxController)
368 {
369     // Tunnel through the controller to obtain a ViewShellBase.
370     Reference<lang::XUnoTunnel> xTunnel (rxController, UNO_QUERY);
371     if (xTunnel.is())
372     {
373         ::sd::DrawController* pController = reinterpret_cast<sd::DrawController*>(
374             xTunnel->getSomething(sd::DrawController::getUnoTunnelId()));
375         if (pController != NULL)
376         {
377             ViewShellBase* pBase = pController->GetViewShellBase();
378             if (pBase != NULL)
379                 return Instance(*pBase);
380         }
381     }
382 
383     return ::boost::shared_ptr<FrameworkHelper>();
384 }
385 
386 
387 
388 
Instance(ViewShellBase & rBase)389 ::boost::shared_ptr<FrameworkHelper> FrameworkHelper::Instance (ViewShellBase& rBase)
390 {
391 
392     ::boost::shared_ptr<FrameworkHelper> pHelper;
393 
394     InstanceMap::const_iterator iHelper (maInstanceMap.find(&rBase));
395     if (iHelper == maInstanceMap.end())
396     {
397         ::osl::GetGlobalMutex aMutexFunctor;
398         ::osl::MutexGuard aGuard (aMutexFunctor());
399         if (iHelper == maInstanceMap.end())
400         {
401             pHelper = ::boost::shared_ptr<FrameworkHelper>(
402                 new FrameworkHelper(rBase),
403                 FrameworkHelper::Deleter());
404             pHelper->Initialize();
405             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
406             maInstanceMap[&rBase] = pHelper;
407         }
408     }
409     else
410     {
411         OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
412         pHelper = iHelper->second;
413     }
414 
415     return pHelper;
416 }
417 
418 
419 
420 
DisposeInstance(ViewShellBase & rBase)421 void FrameworkHelper::DisposeInstance (ViewShellBase& rBase)
422 {
423     InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
424     if (iHelper != maInstanceMap.end())
425     {
426         iHelper->second->Dispose();
427     }
428 }
429 
430 
431 
432 
ReleaseInstance(ViewShellBase & rBase)433 void FrameworkHelper::ReleaseInstance (ViewShellBase& rBase)
434 {
435     InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
436     if (iHelper != maInstanceMap.end())
437         maInstanceMap.erase(iHelper);
438 }
439 
440 
441 
442 
FrameworkHelper(ViewShellBase & rBase)443 FrameworkHelper::FrameworkHelper (ViewShellBase& rBase)
444     : mrBase(rBase),
445       mxConfigurationController(),
446       mxDisposeListener()
447 
448 {
449     Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY);
450     if (xControllerManager.is())
451     {
452         mxConfigurationController = xControllerManager->getConfigurationController();
453     }
454 
455     new LifetimeController(mrBase);
456 }
457 
458 
459 
460 
Initialize(void)461 void FrameworkHelper::Initialize (void)
462 {
463     mxDisposeListener = new DisposeListener(shared_from_this());
464 }
465 
466 
467 
468 
~FrameworkHelper(void)469 FrameworkHelper::~FrameworkHelper (void)
470 {
471 }
472 
473 
474 
475 
Dispose(void)476 void FrameworkHelper::Dispose (void)
477 {
478     if (mxDisposeListener.is())
479         mxDisposeListener->dispose();
480     mxConfigurationController = NULL;
481 }
482 
483 
484 
485 
IsValid(void)486 bool FrameworkHelper::IsValid (void)
487 {
488     return mxConfigurationController.is();
489 }
490 
491 
492 
493 
GetViewShell(const OUString & rsPaneURL)494 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const OUString& rsPaneURL)
495 {
496     if ( !mxConfigurationController.is() )
497         return ::boost::shared_ptr<ViewShell>();
498 
499     Reference<XResourceId> xPaneId( CreateResourceId( rsPaneURL ) );
500     return lcl_getViewShell( lcl_getFirstViewInPane( mxConfigurationController, xPaneId ) );
501 }
502 
503 
504 
505 
GetViewShell(const Reference<XView> & rxView)506 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const Reference<XView>& rxView)
507 {
508     return lcl_getViewShell( rxView.get() );
509 }
510 
511 
512 
513 
GetView(const Reference<XResourceId> & rxPaneOrViewId)514 Reference<XView> FrameworkHelper::GetView (const Reference<XResourceId>& rxPaneOrViewId)
515 {
516     Reference<XView> xView;
517 
518     if ( ! rxPaneOrViewId.is() || ! mxConfigurationController.is())
519         return NULL;
520 
521     try
522     {
523         if (rxPaneOrViewId->getResourceURL().match(msViewURLPrefix))
524         {
525             xView.set( mxConfigurationController->getResource( rxPaneOrViewId ), UNO_QUERY );
526         }
527         else
528         {
529             xView.set( lcl_getFirstViewInPane( mxConfigurationController, rxPaneOrViewId ), UNO_QUERY );
530         }
531     }
532     catch (lang::DisposedException&)
533     {
534         Dispose();
535     }
536     catch (RuntimeException&)
537     {
538     }
539 
540     return xView;
541 }
542 
543 
544 
545 
GetPaneWindow(const Reference<XResourceId> & rxPaneId)546 Reference<awt::XWindow> FrameworkHelper::GetPaneWindow (const Reference<XResourceId>& rxPaneId)
547 {
548     Reference<awt::XWindow> xWindow;
549 
550     if (rxPaneId.is() && mxConfigurationController.is())
551     {
552         try
553         {
554             if (rxPaneId->getResourceURL().match(msPaneURLPrefix))
555             {
556                 Reference<XPane> xPane (mxConfigurationController->getResource(rxPaneId), UNO_QUERY);
557                 if (xPane.is())
558                     xWindow = xPane->getWindow();
559             }
560         }
561         catch (lang::DisposedException&)
562         {
563             Dispose();
564         }
565         catch (RuntimeException&)
566         {
567         }
568     }
569 
570     return xWindow;
571 }
572 
573 
574 
575 
GetResource(const Reference<XResourceId> & rxResourceId)576 Reference<XResource> FrameworkHelper::GetResource (const Reference<XResourceId>& rxResourceId)
577 {
578     Reference<XResource> xResource;
579 
580     if (rxResourceId.is() && mxConfigurationController.is())
581     {
582         try
583         {
584             return mxConfigurationController->getResource(rxResourceId);
585         }
586         catch (lang::DisposedException&)
587         {
588             Dispose();
589         }
590         catch (RuntimeException&)
591         {
592         }
593     }
594 
595     return NULL;
596 }
597 
598 
599 
600 
RequestView(const OUString & rsResourceURL,const OUString & rsAnchorURL)601 Reference<XResourceId> FrameworkHelper::RequestView (
602     const OUString& rsResourceURL,
603     const OUString& rsAnchorURL)
604 {
605     Reference<XResourceId> xViewId;
606 
607     try
608     {
609         if (mxConfigurationController.is())
610         {
611             mxConfigurationController->requestResourceActivation(
612                 CreateResourceId(rsAnchorURL),
613                 ResourceActivationMode_ADD);
614             xViewId = CreateResourceId(rsResourceURL, rsAnchorURL);
615             mxConfigurationController->requestResourceActivation(
616                 xViewId,
617                 ResourceActivationMode_REPLACE);
618         }
619     }
620     catch (lang::DisposedException&)
621     {
622         Dispose();
623         xViewId = NULL;
624     }
625     catch (RuntimeException&)
626     {
627         xViewId = NULL;
628     }
629 
630     return xViewId;
631 }
632 
633 
634 
635 
RequestResourceDeactivation(const cssu::Reference<cssdf::XResourceId> & rxResourceId)636 void FrameworkHelper::RequestResourceDeactivation (const cssu::Reference<cssdf::XResourceId>& rxResourceId)
637 {
638     try
639     {
640         if (mxConfigurationController.is() && rxResourceId.is())
641             mxConfigurationController->requestResourceDeactivation(rxResourceId);
642     }
643     catch (lang::DisposedException&)
644     {
645         Dispose();
646     }
647     catch (RuntimeException&)
648     {}
649 }
650 
651 
652 
653 
GetViewId(const rtl::OUString & rsViewURL)654 ViewShell::ShellType FrameworkHelper::GetViewId (const rtl::OUString& rsViewURL)
655 {
656     if (mpViewURLMap->empty())
657     {
658         (*mpViewURLMap)[msImpressViewURL] = ViewShell::ST_IMPRESS;
659         (*mpViewURLMap)[msDrawViewURL] = ViewShell::ST_DRAW;
660         (*mpViewURLMap)[msOutlineViewURL] = ViewShell::ST_OUTLINE;
661         (*mpViewURLMap)[msNotesViewURL] = ViewShell::ST_NOTES;
662         (*mpViewURLMap)[msHandoutViewURL] = ViewShell::ST_HANDOUT;
663         (*mpViewURLMap)[msSlideSorterURL] = ViewShell::ST_SLIDE_SORTER;
664         (*mpViewURLMap)[msPresentationViewURL] = ViewShell::ST_PRESENTATION;
665         (*mpViewURLMap)[msSidebarViewURL] = ViewShell::ST_SIDEBAR;
666     }
667     ViewURLMap::const_iterator iView (mpViewURLMap->find(rsViewURL));
668     if (iView != mpViewURLMap->end())
669         return iView->second;
670     else
671         return ViewShell::ST_NONE;
672 }
673 
674 
675 
676 
GetViewURL(ViewShell::ShellType eType)677 ::rtl::OUString FrameworkHelper::GetViewURL (ViewShell::ShellType eType)
678 {
679     switch (eType)
680     {
681         case ViewShell::ST_IMPRESS : return msImpressViewURL;
682         case ViewShell::ST_DRAW : return msDrawViewURL;
683         case ViewShell::ST_OUTLINE : return msOutlineViewURL;
684         case ViewShell::ST_NOTES : return msNotesViewURL;
685         case ViewShell::ST_HANDOUT : return msHandoutViewURL;
686         case ViewShell::ST_SLIDE_SORTER : return msSlideSorterURL;
687         case ViewShell::ST_PRESENTATION : return msPresentationViewURL;
688         case ViewShell::ST_SIDEBAR : return msSidebarViewURL;
689         default:
690             return OUString();
691     }
692 }
693 
694 
695 
696 
HandleModeChangeSlot(sal_uLong nSlotId,SfxRequest & rRequest)697 void FrameworkHelper::HandleModeChangeSlot (
698     sal_uLong nSlotId,
699     SfxRequest& rRequest)
700 {
701     sal_Bool bIsActive = sal_True;
702 
703     if ( ! mxConfigurationController.is())
704         return;
705 
706     switch (nSlotId)
707     {
708         case SID_DRAWINGMODE:
709         case SID_NOTESMODE:
710         case SID_HANDOUTMODE:
711         case SID_DIAMODE:
712         case SID_OUTLINEMODE:
713         {
714             const SfxItemSet* pRequestArguments = rRequest.GetArgs();
715             if (pRequestArguments)
716             {
717                 SFX_REQUEST_ARG (rRequest,
718                     pIsActive,
719                     SfxBoolItem,
720                     (sal_uInt16)nSlotId,
721                     sal_False);
722                 bIsActive = pIsActive->GetValue ();
723             }
724         }
725         break;
726     }
727 
728     try
729     {
730         if ( ! mxConfigurationController.is())
731             throw RuntimeException();
732 
733 
734         Reference<XResourceId> xPaneId (
735             CreateResourceId(framework::FrameworkHelper::msCenterPaneURL));
736         Reference<XView> xView (GetView(xPaneId));
737         ::boost::shared_ptr<ViewShell> pCenterViewShell (GetViewShell(xView));
738 
739         ::rtl::OUString sRequestedView;
740         if (bIsActive)
741         {
742             switch (nSlotId)
743             {
744                 case SID_NORMAL_MULTI_PANE_GUI:
745                 case SID_DRAWINGMODE:
746                     sRequestedView = FrameworkHelper::msImpressViewURL;
747                     break;
748 
749                 case SID_NOTESMODE:
750                     sRequestedView = FrameworkHelper::msNotesViewURL;
751                 break;
752 
753                 case SID_HANDOUTMODE:
754                     sRequestedView = FrameworkHelper::msHandoutViewURL;
755                     break;
756 
757                 case SID_SLIDE_SORTER_MULTI_PANE_GUI:
758                 case SID_DIAMODE:
759                     sRequestedView = FrameworkHelper::msSlideSorterURL;
760                     break;
761 
762                 case SID_OUTLINEMODE:
763                     sRequestedView = FrameworkHelper::msOutlineViewURL;
764                     break;
765             }
766         }
767 
768         if (xView.is()
769             && xView->getResourceId()->getResourceURL().equals(sRequestedView))
770         {
771             // We do not have to switch the view shell but maybe the edit mode
772             // has changed.
773             DrawViewShell* pDrawViewShell
774                 = dynamic_cast<DrawViewShell*>(pCenterViewShell.get());
775             if (pDrawViewShell != NULL)
776             {
777                 pCenterViewShell->Broadcast (
778                     ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_START));
779 
780                 pDrawViewShell->ChangeEditMode (
781                     EM_PAGE, pDrawViewShell->IsLayerModeActive());
782 
783                 pCenterViewShell->Broadcast (
784                     ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_END));
785             }
786         }
787         else
788         {
789             mxConfigurationController->requestResourceActivation(
790                 CreateResourceId(sRequestedView, msCenterPaneURL),
791                 ResourceActivationMode_REPLACE);
792         }
793     }
794     catch (RuntimeException&)
795     {
796         DBG_UNHANDLED_EXCEPTION();
797     }
798 }
799 
800 
801 
802 
RunOnConfigurationEvent(const::rtl::OUString & rsEventType,const Callback & rCallback)803 void FrameworkHelper::RunOnConfigurationEvent(
804     const ::rtl::OUString& rsEventType,
805     const Callback& rCallback)
806 {
807     RunOnEvent(
808         rsEventType,
809         FrameworkHelperAllPassFilter(),
810         rCallback);
811 }
812 
813 
814 
815 
RunOnResourceActivation(const css::uno::Reference<css::drawing::framework::XResourceId> & rxResourceId,const Callback & rCallback)816 void FrameworkHelper::RunOnResourceActivation(
817     const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
818     const Callback& rCallback)
819 {
820     if (mxConfigurationController.is()
821         && mxConfigurationController->getResource(rxResourceId).is())
822     {
823         rCallback(false);
824     }
825     else
826     {
827         RunOnEvent(
828             msResourceActivationEvent,
829             FrameworkHelperResourceIdFilter(rxResourceId),
830             rCallback);
831     }
832 }
833 
834 
835 
836 
RunOnResourceDeactivation(const css::uno::Reference<css::drawing::framework::XResourceId> & rxResourceId,const Callback & rCallback,const bool bRunOnDeactivationEnd)837 void FrameworkHelper::RunOnResourceDeactivation(
838     const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
839     const Callback& rCallback,
840     const bool bRunOnDeactivationEnd)
841 {
842     if (mxConfigurationController.is()
843         && ! mxConfigurationController->getResource(rxResourceId).is())
844     {
845         rCallback(false);
846     }
847     else
848     {
849         RunOnEvent(
850             bRunOnDeactivationEnd
851                 ? msResourceDeactivationEndEvent
852                 : msResourceDeactivationEvent,
853             FrameworkHelperResourceIdFilter(rxResourceId),
854             rCallback);
855     }
856 }
857 
858 
859 
860 
861 /** A callback that sets a flag to a specified value when the callback is
862     called.
863 */
864 class FlagUpdater
865 {
866 public:
FlagUpdater(bool & rFlag)867     FlagUpdater (bool& rFlag) : mrFlag(rFlag) {}
operator ()(bool)868     void operator() (bool) {mrFlag = true;}
869 private:
870     bool& mrFlag;
871 };
872 
873 
874 
875 
RequestSynchronousUpdate(void)876 void FrameworkHelper::RequestSynchronousUpdate (void)
877 {
878     rtl::Reference<ConfigurationController> pCC (
879         dynamic_cast<ConfigurationController*>(mxConfigurationController.get()));
880     if (pCC.is())
881         pCC->RequestSynchronousUpdate();
882 }
883 
884 
885 
886 
WaitForEvent(const OUString & rsEventType) const887 void FrameworkHelper::WaitForEvent (const OUString& rsEventType) const
888 {
889     bool bConfigurationUpdateSeen (false);
890 
891     RunOnEvent(
892         rsEventType,
893         FrameworkHelperAllPassFilter(),
894         FlagUpdater(bConfigurationUpdateSeen));
895 
896     sal_uInt32 nStartTime = osl_getGlobalTimer();
897     while ( ! bConfigurationUpdateSeen)
898     {
899         Application::Reschedule();
900 
901         if( (osl_getGlobalTimer() - nStartTime) > 60000  )
902         {
903             DBG_ERROR("FrameworkHelper::WaitForEvent(), no event for a minute? giving up!");
904             break;
905         }
906     }
907 }
908 
909 
910 
911 
WaitForUpdate(void) const912 void FrameworkHelper::WaitForUpdate (void) const
913 {
914     WaitForEvent(msConfigurationUpdateEndEvent);
915 }
916 
917 
918 
919 
RunOnEvent(const::rtl::OUString & rsEventType,const ConfigurationChangeEventFilter & rFilter,const Callback & rCallback) const920 void FrameworkHelper::RunOnEvent(
921     const ::rtl::OUString& rsEventType,
922     const ConfigurationChangeEventFilter& rFilter,
923     const Callback& rCallback) const
924 {
925     new CallbackCaller(mrBase,rsEventType,rFilter,rCallback);
926 }
927 
928 
929 
930 
disposing(const lang::EventObject & rEventObject)931 void FrameworkHelper::disposing (const lang::EventObject& rEventObject)
932 {
933     if (rEventObject.Source == mxConfigurationController)
934         mxConfigurationController = NULL;
935 }
936 
937 
938 
939 
UpdateConfiguration(void)940 void FrameworkHelper::UpdateConfiguration (void)
941 {
942     if (mxConfigurationController.is())
943     {
944         try
945         {
946             if (mxConfigurationController.is())
947                 mxConfigurationController->update();
948         }
949         catch (lang::DisposedException&)
950         {
951             Dispose();
952         }
953         catch (RuntimeException&)
954         {
955             DBG_UNHANDLED_EXCEPTION();
956         }
957     }
958 }
959 
960 
961 
962 
ResourceIdToString(const Reference<XResourceId> & rxResourceId)963 OUString FrameworkHelper::ResourceIdToString (const Reference<XResourceId>& rxResourceId)
964 {
965     OUString sString;
966     if (rxResourceId.is())
967     {
968         sString += rxResourceId->getResourceURL();
969         if (rxResourceId->hasAnchor())
970         {
971             Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
972             for (sal_Int32 nIndex=0; nIndex<aAnchorURLs.getLength(); ++nIndex)
973             {
974                 sString += OUString::createFromAscii(" | ");
975                 sString += aAnchorURLs[nIndex];
976             }
977         }
978     }
979     return sString;
980 }
981 
982 
983 
984 
CreateResourceId(const::rtl::OUString & rsResourceURL)985 Reference<XResourceId> FrameworkHelper::CreateResourceId (const ::rtl::OUString& rsResourceURL)
986 {
987     return new ::sd::framework::ResourceId(rsResourceURL);
988 }
989 
990 
991 
992 
CreateResourceId(const OUString & rsResourceURL,const OUString & rsAnchorURL)993 Reference<XResourceId> FrameworkHelper::CreateResourceId (
994     const OUString& rsResourceURL,
995     const OUString& rsAnchorURL)
996 {
997     return new ::sd::framework::ResourceId(rsResourceURL, rsAnchorURL);
998 }
999 
1000 
1001 
1002 
CreateResourceId(const OUString & rsResourceURL,const OUString & rsFirstAnchorURL,const OUString & rsSecondAnchorURL)1003 Reference<XResourceId> FrameworkHelper::CreateResourceId (
1004     const OUString& rsResourceURL,
1005     const OUString& rsFirstAnchorURL,
1006     const OUString& rsSecondAnchorURL)
1007 {
1008     ::std::vector<OUString> aAnchorURLs (2);
1009     aAnchorURLs[0] = rsFirstAnchorURL;
1010     aAnchorURLs[1] = rsSecondAnchorURL;
1011     return new ::sd::framework::ResourceId(rsResourceURL, aAnchorURLs);
1012 }
1013 
1014 
1015 
1016 
CreateResourceId(const::rtl::OUString & rsResourceURL,const Reference<XResourceId> & rxAnchorId)1017 Reference<XResourceId> FrameworkHelper::CreateResourceId (
1018     const ::rtl::OUString& rsResourceURL,
1019     const Reference<XResourceId>& rxAnchorId)
1020 {
1021     if (rxAnchorId.is())
1022         return new ::sd::framework::ResourceId(
1023             rsResourceURL,
1024             rxAnchorId->getResourceURL(),
1025             rxAnchorId->getAnchorURLs());
1026     else
1027         return new ::sd::framework::ResourceId(rsResourceURL);
1028 }
1029 
1030 
1031 
1032 
GetConfigurationController(void) const1033 Reference<XConfigurationController> FrameworkHelper::GetConfigurationController (void) const
1034 {
1035     return mxConfigurationController;
1036 }
1037 
1038 
1039 
1040 
1041 //----- FrameworkHelper::DisposeListener --------------------------------------
1042 
DisposeListener(const::boost::shared_ptr<FrameworkHelper> & rpHelper)1043 FrameworkHelper::DisposeListener::DisposeListener (
1044     const ::boost::shared_ptr<FrameworkHelper>& rpHelper)
1045     : FrameworkHelperDisposeListenerInterfaceBase(maMutex),
1046       mpHelper(rpHelper)
1047 {
1048     Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
1049     if (xComponent.is())
1050         xComponent->addEventListener(this);
1051 }
1052 
1053 
1054 
1055 
~DisposeListener(void)1056 FrameworkHelper::DisposeListener::~DisposeListener (void)
1057 {
1058 }
1059 
1060 
1061 
1062 
disposing(void)1063 void SAL_CALL FrameworkHelper::DisposeListener::disposing (void)
1064 {
1065     Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
1066     if (xComponent.is())
1067         xComponent->removeEventListener(this);
1068 
1069     mpHelper.reset();
1070 }
1071 
1072 
1073 
1074 
disposing(const lang::EventObject & rEventObject)1075 void SAL_CALL FrameworkHelper::DisposeListener::disposing (const lang::EventObject& rEventObject)
1076 {
1077     if (mpHelper.get() != NULL)
1078         mpHelper->disposing(rEventObject);
1079 }
1080 
1081 
1082 
1083 
1084 //===== FrameworkHelperResourceIdFilter =======================================
1085 
FrameworkHelperResourceIdFilter(const Reference<XResourceId> & rxResourceId)1086 FrameworkHelperResourceIdFilter::FrameworkHelperResourceIdFilter (
1087     const Reference<XResourceId>& rxResourceId)
1088     : mxResourceId(rxResourceId)
1089 {
1090 }
1091 
1092 
1093 } } // end of namespace sd::framework
1094 
1095 namespace {
1096 
1097 //===== CallbackCaller ========================================================
1098 
CallbackCaller(::sd::ViewShellBase & rBase,const OUString & rsEventType,const::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter & rFilter,const::sd::framework::FrameworkHelper::Callback & rCallback)1099 CallbackCaller::CallbackCaller (
1100     ::sd::ViewShellBase& rBase,
1101     const OUString& rsEventType,
1102     const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter,
1103     const ::sd::framework::FrameworkHelper::Callback& rCallback)
1104     : CallbackCallerInterfaceBase(MutexOwner::maMutex),
1105       msEventType(rsEventType),
1106       mxConfigurationController(),
1107       maFilter(rFilter),
1108       maCallback(rCallback)
1109 {
1110     try
1111     {
1112         Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY_THROW);
1113         mxConfigurationController = xControllerManager->getConfigurationController();
1114         if (mxConfigurationController.is())
1115         {
1116             if (mxConfigurationController->hasPendingRequests())
1117                 mxConfigurationController->addConfigurationChangeListener(this,msEventType,Any());
1118             else
1119             {
1120                 // There are no requests waiting to be processed.  Therefore
1121                 // no event, especially not the one we are waiting for, will
1122                 // be sent in the near future and the callback would never be
1123                 // called.
1124                 // Call the callback now and tell him that the event it is
1125                 // waiting for was not sent.
1126                 mxConfigurationController = NULL;
1127                 maCallback(false);
1128             }
1129         }
1130     }
1131     catch (RuntimeException&)
1132     {
1133         DBG_UNHANDLED_EXCEPTION();
1134     }
1135 }
1136 
1137 
1138 
1139 
~CallbackCaller(void)1140 CallbackCaller::~CallbackCaller (void)
1141 {
1142 }
1143 
1144 
1145 
1146 
disposing(void)1147 void CallbackCaller::disposing (void)
1148 {
1149     try
1150     {
1151         if (mxConfigurationController.is())
1152         {
1153             Reference<XConfigurationController> xCC (mxConfigurationController);
1154             mxConfigurationController = NULL;
1155             xCC->removeConfigurationChangeListener(this);
1156         }
1157     }
1158     catch (RuntimeException&)
1159     {
1160         DBG_UNHANDLED_EXCEPTION();
1161     }
1162 }
1163 
1164 
1165 
1166 
disposing(const lang::EventObject & rEvent)1167 void SAL_CALL CallbackCaller::disposing (const lang::EventObject& rEvent)
1168 {
1169     if (rEvent.Source == mxConfigurationController)
1170     {
1171         mxConfigurationController = NULL;
1172         maCallback(false);
1173     }
1174 }
1175 
1176 
1177 
1178 
notifyConfigurationChange(const ConfigurationChangeEvent & rEvent)1179 void SAL_CALL CallbackCaller::notifyConfigurationChange (
1180     const ConfigurationChangeEvent& rEvent)
1181 {
1182     if (rEvent.Type.equals(msEventType) && maFilter(rEvent))
1183     {
1184         maCallback(true);
1185         if (mxConfigurationController.is())
1186         {
1187             // Reset the reference to the configuration controller so that
1188             // dispose() will not try to remove the listener a second time.
1189             Reference<XConfigurationController> xCC (mxConfigurationController);
1190             mxConfigurationController = NULL;
1191 
1192             // Removing this object from the controller may very likely lead
1193             // to its destruction, so no calls after that.
1194             xCC->removeConfigurationChangeListener(this);
1195         }
1196     }
1197 }
1198 
1199 
1200 
1201 
1202 //----- LifetimeController -------------------------------------------------
1203 
LifetimeController(::sd::ViewShellBase & rBase)1204 LifetimeController::LifetimeController (::sd::ViewShellBase& rBase)
1205     : LifetimeControllerInterfaceBase(maMutex),
1206       mrBase(rBase),
1207       mbListeningToViewShellBase(false),
1208       mbListeningToController(false)
1209 {
1210     // Register as listener at the ViewShellBase.  Because that is not done
1211     // via a reference we have to increase the reference count manually.
1212     // This is necessary even though listening to the XController did
1213     // increase the reference count because the controller may release its
1214     // reference to us before the ViewShellBase is destroyed.
1215     StartListening(mrBase);
1216     acquire();
1217     mbListeningToViewShellBase = true;
1218 
1219     Reference<XComponent> xComponent (rBase.GetController(), UNO_QUERY);
1220     if (xComponent.is())
1221     {
1222         xComponent->addEventListener(this);
1223         mbListeningToController = true;
1224     }
1225 }
1226 
1227 
1228 
1229 
~LifetimeController(void)1230 LifetimeController::~LifetimeController (void)
1231 {
1232     OSL_ASSERT(!mbListeningToController && !mbListeningToViewShellBase);
1233 }
1234 
1235 
1236 
1237 
disposing(void)1238 void LifetimeController::disposing (void)
1239 {
1240 }
1241 
1242 
1243 
1244 
disposing(const lang::EventObject & rEvent)1245 void SAL_CALL LifetimeController::disposing (const lang::EventObject& rEvent)
1246 {
1247     (void)rEvent;
1248     mbListeningToController = false;
1249     Update();
1250 }
1251 
1252 
1253 
1254 
Notify(SfxBroadcaster & rBroadcaster,const SfxHint & rHint)1255 void LifetimeController::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
1256 {
1257     (void)rBroadcaster;
1258     const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
1259     if (pSimpleHint != NULL && pSimpleHint->GetId() == SFX_HINT_DYING)
1260     {
1261         mbListeningToViewShellBase = false;
1262         Update();
1263         release();
1264     }
1265 }
1266 
1267 
1268 
1269 
Update(void)1270 void LifetimeController::Update (void)
1271 {
1272     if (mbListeningToViewShellBase && mbListeningToController)
1273     {
1274         // Both the controller and the ViewShellBase are alive.  Keep
1275         // waiting for their destruction.
1276     }
1277     else if (mbListeningToViewShellBase)
1278     {
1279         // The controller has been destroyed but the ViewShellBase is still
1280         // alive.  Dispose the associated FrameworkHelper but keep it around
1281         // so that no new instance is created for the dying framework.
1282         ::sd::framework::FrameworkHelper::DisposeInstance(mrBase);
1283     }
1284     else
1285     {
1286         // Both the controller and the ViewShellBase have been destroyed.
1287         // Remove the FrameworkHelper so that the next call its Instance()
1288         // method can create a new instance.
1289         ::sd::framework::FrameworkHelper::ReleaseInstance(mrBase);
1290     }
1291 }
1292 
1293 
1294 
1295 } // end of anonymous namespace.
1296