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