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