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             SdGlobalResourceContainer::Instance().AddResource(pHelper);
388             maInstanceMap[&rBase] = pHelper;
389         }
390     }
391     else
392     {
393         OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
394         pHelper = iHelper->second;
395     }
396 
397     return pHelper;
398 }
399 
400 
401 
402 
403 void FrameworkHelper::DisposeInstance (ViewShellBase& rBase)
404 {
405     InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
406     if (iHelper != maInstanceMap.end())
407     {
408         iHelper->second->Dispose();
409     }
410 }
411 
412 
413 
414 
415 void FrameworkHelper::ReleaseInstance (ViewShellBase& rBase)
416 {
417     InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
418     if (iHelper != maInstanceMap.end())
419         maInstanceMap.erase(iHelper);
420 }
421 
422 
423 
424 
425 FrameworkHelper::FrameworkHelper (ViewShellBase& rBase)
426     : mrBase(rBase),
427       mxConfigurationController(),
428       mxDisposeListener()
429 
430 {
431     Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY);
432     if (xControllerManager.is())
433     {
434         mxConfigurationController = xControllerManager->getConfigurationController();
435     }
436 
437     new LifetimeController(mrBase);
438 }
439 
440 
441 
442 
443 void FrameworkHelper::Initialize (void)
444 {
445     mxDisposeListener = new DisposeListener(shared_from_this());
446 }
447 
448 
449 
450 
451 FrameworkHelper::~FrameworkHelper (void)
452 {
453 }
454 
455 
456 
457 
458 void FrameworkHelper::Dispose (void)
459 {
460     if (mxDisposeListener.is())
461         mxDisposeListener->dispose();
462     mxConfigurationController = NULL;
463 }
464 
465 
466 
467 
468 bool FrameworkHelper::IsValid (void)
469 {
470     return mxConfigurationController.is();
471 }
472 
473 
474 
475 
476 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const OUString& rsPaneURL)
477 {
478     if ( !mxConfigurationController.is() )
479         return ::boost::shared_ptr<ViewShell>();
480 
481     Reference<XResourceId> xPaneId( CreateResourceId( rsPaneURL ) );
482     return lcl_getViewShell( lcl_getFirstViewInPane( mxConfigurationController, xPaneId ) );
483 }
484 
485 
486 
487 
488 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const Reference<XView>& rxView)
489 {
490     return lcl_getViewShell( rxView.get() );
491 }
492 
493 
494 
495 
496 Reference<XView> FrameworkHelper::GetView (const Reference<XResourceId>& rxPaneOrViewId)
497 {
498     Reference<XView> xView;
499 
500     if ( ! rxPaneOrViewId.is() || ! mxConfigurationController.is())
501         return NULL;
502 
503     try
504     {
505         if (rxPaneOrViewId->getResourceURL().match(msViewURLPrefix))
506         {
507             xView.set( mxConfigurationController->getResource( rxPaneOrViewId ), UNO_QUERY );
508         }
509         else
510         {
511             xView.set( lcl_getFirstViewInPane( mxConfigurationController, rxPaneOrViewId ), UNO_QUERY );
512         }
513     }
514     catch (lang::DisposedException&)
515     {
516         Dispose();
517     }
518     catch (RuntimeException&)
519     {
520     }
521 
522     return xView;
523 }
524 
525 
526 
527 
528 Reference<XResourceId> FrameworkHelper::RequestView (
529     const OUString& rsResourceURL,
530     const OUString& rsAnchorURL)
531 {
532     Reference<XResourceId> xViewId;
533 
534     try
535     {
536         if (mxConfigurationController.is())
537         {
538             mxConfigurationController->requestResourceActivation(
539                 CreateResourceId(rsAnchorURL),
540                 ResourceActivationMode_ADD);
541             xViewId = CreateResourceId(rsResourceURL, rsAnchorURL);
542             mxConfigurationController->requestResourceActivation(
543                 xViewId,
544                 ResourceActivationMode_REPLACE);
545         }
546     }
547     catch (lang::DisposedException&)
548     {
549         Dispose();
550         xViewId = NULL;
551     }
552     catch (RuntimeException&)
553     {
554         xViewId = NULL;
555     }
556 
557     return xViewId;
558 }
559 
560 
561 
562 
563 void FrameworkHelper::RequestTaskPanel (
564     const OUString& rsTaskPanelURL,
565     const bool bEnsureTaskPaneIsVisible)
566 {
567     try
568     {
569         if (mxConfigurationController.is())
570         {
571             // Check the existence of the task pane.
572             if ( ! bEnsureTaskPaneIsVisible)
573             {
574                 Reference<XConfiguration> xConfiguration (
575                     mxConfigurationController->getCurrentConfiguration());
576             if (xConfiguration.is())
577                 if ( ! xConfiguration->hasResource(
578                     CreateResourceId(msTaskPaneURL, msRightPaneURL)))
579                 {
580                     // Task pane does is not active.  Do not force it.
581                     return;
582                 }
583             }
584 
585             // Create the resource id from URLs for the pane, the task pane
586             // view, and the task panel.
587             mxConfigurationController->requestResourceActivation(
588                 CreateResourceId(msRightPaneURL),
589                 ResourceActivationMode_ADD);
590             mxConfigurationController->requestResourceActivation(
591                 CreateResourceId(msTaskPaneURL, msRightPaneURL),
592                 ResourceActivationMode_REPLACE);
593             mxConfigurationController->requestResourceActivation(
594                 CreateResourceId(rsTaskPanelURL, msTaskPaneURL, msRightPaneURL),
595                 ResourceActivationMode_REPLACE);
596         }
597     }
598     catch (lang::DisposedException&)
599     {
600         Dispose();
601     }
602     catch (RuntimeException&)
603     {}
604 }
605 
606 
607 
608 
609 ViewShell::ShellType FrameworkHelper::GetViewId (const rtl::OUString& rsViewURL)
610 {
611     if (mpViewURLMap->empty())
612     {
613         (*mpViewURLMap)[msImpressViewURL] = ViewShell::ST_IMPRESS;
614         (*mpViewURLMap)[msDrawViewURL] = ViewShell::ST_DRAW;
615         (*mpViewURLMap)[msOutlineViewURL] = ViewShell::ST_OUTLINE;
616         (*mpViewURLMap)[msNotesViewURL] = ViewShell::ST_NOTES;
617         (*mpViewURLMap)[msHandoutViewURL] = ViewShell::ST_HANDOUT;
618         (*mpViewURLMap)[msSlideSorterURL] = ViewShell::ST_SLIDE_SORTER;
619         (*mpViewURLMap)[msPresentationViewURL] = ViewShell::ST_PRESENTATION;
620         (*mpViewURLMap)[msTaskPaneURL] = ViewShell::ST_TASK_PANE;
621     }
622     ViewURLMap::const_iterator iView (mpViewURLMap->find(rsViewURL));
623     if (iView != mpViewURLMap->end())
624         return iView->second;
625     else
626         return ViewShell::ST_NONE;
627 }
628 
629 
630 
631 
632 ::rtl::OUString FrameworkHelper::GetViewURL (ViewShell::ShellType eType)
633 {
634     switch (eType)
635     {
636         case ViewShell::ST_IMPRESS : return msImpressViewURL;
637         case ViewShell::ST_DRAW : return msDrawViewURL;
638         case ViewShell::ST_OUTLINE : return msOutlineViewURL;
639         case ViewShell::ST_NOTES : return msNotesViewURL;
640         case ViewShell::ST_HANDOUT : return msHandoutViewURL;
641         case ViewShell::ST_SLIDE_SORTER : return msSlideSorterURL;
642         case ViewShell::ST_PRESENTATION : return msPresentationViewURL;
643         case ViewShell::ST_TASK_PANE : return msTaskPaneURL;
644         default:
645             return OUString();
646     }
647 }
648 
649 
650 
651 
652 void FrameworkHelper::HandleModeChangeSlot (
653     sal_uLong nSlotId,
654     SfxRequest& rRequest)
655 {
656     sal_Bool bIsActive = sal_True;
657 
658     if ( ! mxConfigurationController.is())
659         return;
660 
661     switch (nSlotId)
662     {
663         case SID_DRAWINGMODE:
664         case SID_NOTESMODE:
665 		case SID_HANDOUTMODE:
666 		case SID_DIAMODE:
667 		case SID_OUTLINEMODE:
668         {
669 			const SfxItemSet* pRequestArguments = rRequest.GetArgs();
670 			if (pRequestArguments)
671             {
672                 SFX_REQUEST_ARG (rRequest,
673                     pIsActive,
674                     SfxBoolItem,
675                     (sal_uInt16)nSlotId,
676                     sal_False);
677 				bIsActive = pIsActive->GetValue ();
678 			}
679         }
680         break;
681     }
682 
683     try
684     {
685         if ( ! mxConfigurationController.is())
686             throw RuntimeException();
687 
688 
689         Reference<XResourceId> xPaneId (
690             CreateResourceId(framework::FrameworkHelper::msCenterPaneURL));
691         Reference<XView> xView (GetView(xPaneId));
692         ::boost::shared_ptr<ViewShell> pCenterViewShell (GetViewShell(xView));
693 
694         ::rtl::OUString sRequestedView;
695         if (bIsActive)
696         {
697             switch (nSlotId)
698             {
699                 case SID_NORMAL_MULTI_PANE_GUI:
700                 case SID_DRAWINGMODE:
701                     sRequestedView = FrameworkHelper::msImpressViewURL;
702                     break;
703 
704                 case SID_NOTESMODE:
705                     sRequestedView = FrameworkHelper::msNotesViewURL;
706                 break;
707 
708                 case SID_HANDOUTMODE:
709                     sRequestedView = FrameworkHelper::msHandoutViewURL;
710                     break;
711 
712                 case SID_SLIDE_SORTER_MULTI_PANE_GUI:
713                 case SID_DIAMODE:
714                     sRequestedView = FrameworkHelper::msSlideSorterURL;
715                     break;
716 
717                 case SID_OUTLINEMODE:
718                     sRequestedView = FrameworkHelper::msOutlineViewURL;
719                     break;
720             }
721         }
722 
723         if (xView.is()
724             && xView->getResourceId()->getResourceURL().equals(sRequestedView))
725         {
726             // We do not have to switch the view shell but maybe the edit mode
727             // has changed.
728             DrawViewShell* pDrawViewShell
729                 = dynamic_cast<DrawViewShell*>(pCenterViewShell.get());
730             if (pDrawViewShell != NULL)
731             {
732                 pCenterViewShell->Broadcast (
733                     ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_START));
734 
735                 pDrawViewShell->ChangeEditMode (
736                     EM_PAGE, pDrawViewShell->IsLayerModeActive());
737 
738                 pCenterViewShell->Broadcast (
739                     ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_END));
740             }
741         }
742         else
743         {
744             mxConfigurationController->requestResourceActivation(
745                 CreateResourceId(sRequestedView, msCenterPaneURL),
746                 ResourceActivationMode_REPLACE);
747         }
748     }
749     catch (RuntimeException&)
750     {
751         DBG_UNHANDLED_EXCEPTION();
752     }
753 }
754 
755 
756 
757 
758 void FrameworkHelper::RunOnConfigurationEvent(
759     const ::rtl::OUString& rsEventType,
760     const Callback& rCallback)
761 {
762     RunOnEvent(
763         rsEventType,
764         FrameworkHelperAllPassFilter(),
765         rCallback);
766 }
767 
768 
769 
770 
771 void FrameworkHelper::RunOnResourceActivation(
772     const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
773     const Callback& rCallback)
774 {
775     if (mxConfigurationController.is()
776         && mxConfigurationController->getResource(rxResourceId).is())
777     {
778         rCallback(false);
779     }
780     else
781     {
782         RunOnEvent(
783             msResourceActivationEvent,
784             FrameworkHelperResourceIdFilter(rxResourceId),
785             rCallback);
786     }
787 }
788 
789 
790 
791 
792 /** A callback that sets a flag to a specified value when the callback is
793     called.
794 */
795 class FlagUpdater
796 {
797 public:
798     FlagUpdater (bool& rFlag) : mrFlag(rFlag) {}
799     void operator() (bool) {mrFlag = true;}
800 private:
801     bool& mrFlag;
802 };
803 
804 
805 
806 
807 void FrameworkHelper::RequestSynchronousUpdate (void)
808 {
809     rtl::Reference<ConfigurationController> pCC (
810         dynamic_cast<ConfigurationController*>(mxConfigurationController.get()));
811     if (pCC.is())
812         pCC->RequestSynchronousUpdate();
813 }
814 
815 
816 
817 
818 void FrameworkHelper::WaitForEvent (const OUString& rsEventType) const
819 {
820     bool bConfigurationUpdateSeen (false);
821 
822     RunOnEvent(
823         rsEventType,
824         FrameworkHelperAllPassFilter(),
825         FlagUpdater(bConfigurationUpdateSeen));
826 
827 	sal_uInt32 nStartTime = osl_getGlobalTimer();
828     while ( ! bConfigurationUpdateSeen)
829     {
830         Application::Reschedule();
831 
832 		if( (osl_getGlobalTimer() - nStartTime) > 60000  )
833 		{
834 			DBG_ERROR("FrameworkHelper::WaitForEvent(), no event for a minute? giving up!");
835 			break;
836 		}
837     }
838 }
839 
840 
841 
842 
843 void FrameworkHelper::WaitForUpdate (void) const
844 {
845     WaitForEvent(msConfigurationUpdateEndEvent);
846 }
847 
848 
849 
850 
851 void FrameworkHelper::RunOnEvent(
852     const ::rtl::OUString& rsEventType,
853     const ConfigurationChangeEventFilter& rFilter,
854     const Callback& rCallback) const
855 {
856     new CallbackCaller(mrBase,rsEventType,rFilter,rCallback);
857 }
858 
859 
860 
861 
862 void FrameworkHelper::disposing (const lang::EventObject& rEventObject)
863 {
864     if (rEventObject.Source == mxConfigurationController)
865         mxConfigurationController = NULL;
866 }
867 
868 
869 
870 
871 void FrameworkHelper::UpdateConfiguration (void)
872 {
873     if (mxConfigurationController.is())
874     {
875         try
876         {
877             if (mxConfigurationController.is())
878                 mxConfigurationController->update();
879         }
880         catch (lang::DisposedException&)
881         {
882             Dispose();
883         }
884         catch (RuntimeException&)
885         {
886             DBG_UNHANDLED_EXCEPTION();
887         }
888     }
889 }
890 
891 
892 
893 
894 OUString FrameworkHelper::ResourceIdToString (const Reference<XResourceId>& rxResourceId)
895 {
896     OUString sString;
897     if (rxResourceId.is())
898     {
899         sString += rxResourceId->getResourceURL();
900         if (rxResourceId->hasAnchor())
901         {
902             Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
903             for (sal_Int32 nIndex=0; nIndex<aAnchorURLs.getLength(); ++nIndex)
904             {
905                 sString += OUString::createFromAscii(" | ");
906                 sString += aAnchorURLs[nIndex];
907             }
908         }
909     }
910     return sString;
911 }
912 
913 
914 
915 
916 Reference<XResourceId> FrameworkHelper::CreateResourceId (const ::rtl::OUString& rsResourceURL)
917 {
918     return new ::sd::framework::ResourceId(rsResourceURL);
919 }
920 
921 
922 
923 
924 Reference<XResourceId> FrameworkHelper::CreateResourceId (
925     const OUString& rsResourceURL,
926     const OUString& rsAnchorURL)
927 {
928     return new ::sd::framework::ResourceId(rsResourceURL, rsAnchorURL);
929 }
930 
931 
932 
933 
934 Reference<XResourceId> FrameworkHelper::CreateResourceId (
935     const OUString& rsResourceURL,
936     const OUString& rsFirstAnchorURL,
937     const OUString& rsSecondAnchorURL)
938 {
939     ::std::vector<OUString> aAnchorURLs (2);
940     aAnchorURLs[0] = rsFirstAnchorURL;
941     aAnchorURLs[1] = rsSecondAnchorURL;
942     return new ::sd::framework::ResourceId(rsResourceURL, aAnchorURLs);
943 }
944 
945 
946 
947 
948 Reference<XResourceId> FrameworkHelper::CreateResourceId (
949     const ::rtl::OUString& rsResourceURL,
950     const Reference<XResourceId>& rxAnchorId)
951 {
952     if (rxAnchorId.is())
953         return new ::sd::framework::ResourceId(
954             rsResourceURL,
955             rxAnchorId->getResourceURL(),
956             rxAnchorId->getAnchorURLs());
957     else
958         return new ::sd::framework::ResourceId(rsResourceURL);
959 }
960 
961 
962 
963 
964 Reference<XConfigurationController> FrameworkHelper::GetConfigurationController (void) const
965 {
966     return mxConfigurationController;
967 }
968 
969 
970 
971 
972 //----- FrameworkHelper::DisposeListener --------------------------------------
973 
974 FrameworkHelper::DisposeListener::DisposeListener (
975     const ::boost::shared_ptr<FrameworkHelper>& rpHelper)
976     : FrameworkHelperDisposeListenerInterfaceBase(maMutex),
977       mpHelper(rpHelper)
978 {
979     Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
980     if (xComponent.is())
981         xComponent->addEventListener(this);
982 }
983 
984 
985 
986 
987 FrameworkHelper::DisposeListener::~DisposeListener (void)
988 {
989 }
990 
991 
992 
993 
994 void SAL_CALL FrameworkHelper::DisposeListener::disposing (void)
995 {
996     Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
997     if (xComponent.is())
998         xComponent->removeEventListener(this);
999 
1000     mpHelper.reset();
1001 }
1002 
1003 
1004 
1005 
1006 void SAL_CALL FrameworkHelper::DisposeListener::disposing (const lang::EventObject& rEventObject)
1007     throw(RuntimeException)
1008 {
1009     if (mpHelper.get() != NULL)
1010         mpHelper->disposing(rEventObject);
1011 }
1012 
1013 
1014 
1015 
1016 //===== FrameworkHelperResourceIdFilter =======================================
1017 
1018 FrameworkHelperResourceIdFilter::FrameworkHelperResourceIdFilter (
1019     const Reference<XResourceId>& rxResourceId)
1020     : mxResourceId(rxResourceId)
1021 {
1022 }
1023 
1024 
1025 } } // end of namespace sd::framework
1026 
1027 namespace {
1028 
1029 //===== CallbackCaller ========================================================
1030 
1031 CallbackCaller::CallbackCaller (
1032     ::sd::ViewShellBase& rBase,
1033     const OUString& rsEventType,
1034     const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter,
1035     const ::sd::framework::FrameworkHelper::Callback& rCallback)
1036     : CallbackCallerInterfaceBase(MutexOwner::maMutex),
1037       msEventType(rsEventType),
1038       mxConfigurationController(),
1039       maFilter(rFilter),
1040       maCallback(rCallback)
1041 {
1042     try
1043     {
1044         Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY_THROW);
1045         mxConfigurationController = xControllerManager->getConfigurationController();
1046         if (mxConfigurationController.is())
1047         {
1048             if (mxConfigurationController->hasPendingRequests())
1049                 mxConfigurationController->addConfigurationChangeListener(this,msEventType,Any());
1050             else
1051             {
1052                 // There are no requests waiting to be processed.  Therefore
1053                 // no event, especially not the one we are waiting for, will
1054                 // be sent in the near future and the callback would never be
1055                 // called.
1056                 // Call the callback now and tell him that the event it is
1057                 // waiting for was not sent.
1058                 mxConfigurationController = NULL;
1059                 maCallback(false);
1060             }
1061         }
1062     }
1063     catch (RuntimeException&)
1064     {
1065         DBG_UNHANDLED_EXCEPTION();
1066     }
1067 }
1068 
1069 
1070 
1071 
1072 CallbackCaller::~CallbackCaller (void)
1073 {
1074 }
1075 
1076 
1077 
1078 
1079 void CallbackCaller::disposing (void)
1080 {
1081     try
1082     {
1083         if (mxConfigurationController.is())
1084         {
1085             Reference<XConfigurationController> xCC (mxConfigurationController);
1086             mxConfigurationController = NULL;
1087             xCC->removeConfigurationChangeListener(this);
1088         }
1089     }
1090     catch (RuntimeException&)
1091     {
1092         DBG_UNHANDLED_EXCEPTION();
1093     }
1094 }
1095 
1096 
1097 
1098 
1099 void SAL_CALL CallbackCaller::disposing (const lang::EventObject& rEvent)
1100     throw (RuntimeException)
1101 {
1102     if (rEvent.Source == mxConfigurationController)
1103     {
1104         mxConfigurationController = NULL;
1105         maCallback(false);
1106     }
1107 }
1108 
1109 
1110 
1111 
1112 void SAL_CALL CallbackCaller::notifyConfigurationChange (
1113     const ConfigurationChangeEvent& rEvent)
1114     throw (RuntimeException)
1115 {
1116     if (rEvent.Type.equals(msEventType) && maFilter(rEvent))
1117     {
1118         maCallback(true);
1119         if (mxConfigurationController.is())
1120         {
1121             // Reset the reference to the configuration controller so that
1122             // dispose() will not try to remove the listener a second time.
1123             Reference<XConfigurationController> xCC (mxConfigurationController);
1124             mxConfigurationController = NULL;
1125 
1126             // Removing this object from the controller may very likely lead
1127             // to its destruction, so no calls after that.
1128             xCC->removeConfigurationChangeListener(this);
1129         }
1130     }
1131 }
1132 
1133 
1134 
1135 
1136 //----- LifetimeController -------------------------------------------------
1137 
1138 LifetimeController::LifetimeController (::sd::ViewShellBase& rBase)
1139     : LifetimeControllerInterfaceBase(maMutex),
1140       mrBase(rBase),
1141       mbListeningToViewShellBase(false),
1142       mbListeningToController(false)
1143 {
1144     // Register as listener at the ViewShellBase.  Because that is not done
1145     // via a reference we have to increase the reference count manually.
1146     // This is necessary even though listening to the XController did
1147     // increase the reference count because the controller may release its
1148     // reference to us before the ViewShellBase is destroyed.
1149     StartListening(mrBase);
1150     acquire();
1151     mbListeningToViewShellBase = true;
1152 
1153     Reference<XComponent> xComponent (rBase.GetController(), UNO_QUERY);
1154     if (xComponent.is())
1155     {
1156         xComponent->addEventListener(this);
1157         mbListeningToController = true;
1158     }
1159 }
1160 
1161 
1162 
1163 
1164 LifetimeController::~LifetimeController (void)
1165 {
1166     OSL_ASSERT(!mbListeningToController && !mbListeningToViewShellBase);
1167 }
1168 
1169 
1170 
1171 
1172 void LifetimeController::disposing (void)
1173 {
1174 }
1175 
1176 
1177 
1178 
1179 void SAL_CALL LifetimeController::disposing (const lang::EventObject& rEvent)
1180     throw(RuntimeException)
1181 {
1182     (void)rEvent;
1183     mbListeningToController = false;
1184     Update();
1185 }
1186 
1187 
1188 
1189 
1190 void LifetimeController::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
1191 {
1192     (void)rBroadcaster;
1193     const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
1194     if (pSimpleHint != NULL && pSimpleHint->GetId() == SFX_HINT_DYING)
1195     {
1196         mbListeningToViewShellBase = false;
1197         Update();
1198         release();
1199     }
1200 }
1201 
1202 
1203 
1204 
1205 void LifetimeController::Update (void)
1206 {
1207     if (mbListeningToViewShellBase && mbListeningToController)
1208     {
1209         // Both the controller and the ViewShellBase are alive.  Keep
1210         // waiting for their destruction.
1211     }
1212     else if (mbListeningToViewShellBase)
1213     {
1214         // The controller has been destroyed but the ViewShellBase is still
1215         // alive.  Dispose the associated FrameworkHelper but keep it around
1216         // so that no new instance is created for the dying framework.
1217         ::sd::framework::FrameworkHelper::DisposeInstance(mrBase);
1218     }
1219     else
1220     {
1221         // Both the controller and the ViewShellBase have been destroyed.
1222         // Remove the FrameworkHelper so that the next call its Instance()
1223         // method can create a new instance.
1224         ::sd::framework::FrameworkHelper::ReleaseInstance(mrBase);
1225     }
1226 }
1227 
1228 
1229 
1230 } // end of anonymous namespace.
1231