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 void FrameworkHelper::RequestResourceDeactivation (const cssu::Reference<cssdf::XResourceId>& rxResourceId)
641 {
642     try
643     {
644         if (mxConfigurationController.is() && rxResourceId.is())
645             mxConfigurationController->requestResourceDeactivation(rxResourceId);
646     }
647     catch (lang::DisposedException&)
648     {
649         Dispose();
650     }
651     catch (RuntimeException&)
652     {}
653 }
654 
655 
656 
657 
658 ViewShell::ShellType FrameworkHelper::GetViewId (const rtl::OUString& rsViewURL)
659 {
660     if (mpViewURLMap->empty())
661     {
662         (*mpViewURLMap)[msImpressViewURL] = ViewShell::ST_IMPRESS;
663         (*mpViewURLMap)[msDrawViewURL] = ViewShell::ST_DRAW;
664         (*mpViewURLMap)[msOutlineViewURL] = ViewShell::ST_OUTLINE;
665         (*mpViewURLMap)[msNotesViewURL] = ViewShell::ST_NOTES;
666         (*mpViewURLMap)[msHandoutViewURL] = ViewShell::ST_HANDOUT;
667         (*mpViewURLMap)[msSlideSorterURL] = ViewShell::ST_SLIDE_SORTER;
668         (*mpViewURLMap)[msPresentationViewURL] = ViewShell::ST_PRESENTATION;
669         (*mpViewURLMap)[msSidebarViewURL] = ViewShell::ST_SIDEBAR;
670     }
671     ViewURLMap::const_iterator iView (mpViewURLMap->find(rsViewURL));
672     if (iView != mpViewURLMap->end())
673         return iView->second;
674     else
675         return ViewShell::ST_NONE;
676 }
677 
678 
679 
680 
681 ::rtl::OUString FrameworkHelper::GetViewURL (ViewShell::ShellType eType)
682 {
683     switch (eType)
684     {
685         case ViewShell::ST_IMPRESS : return msImpressViewURL;
686         case ViewShell::ST_DRAW : return msDrawViewURL;
687         case ViewShell::ST_OUTLINE : return msOutlineViewURL;
688         case ViewShell::ST_NOTES : return msNotesViewURL;
689         case ViewShell::ST_HANDOUT : return msHandoutViewURL;
690         case ViewShell::ST_SLIDE_SORTER : return msSlideSorterURL;
691         case ViewShell::ST_PRESENTATION : return msPresentationViewURL;
692         case ViewShell::ST_SIDEBAR : return msSidebarViewURL;
693         default:
694             return OUString();
695     }
696 }
697 
698 
699 
700 
701 void FrameworkHelper::HandleModeChangeSlot (
702     sal_uLong nSlotId,
703     SfxRequest& rRequest)
704 {
705     sal_Bool bIsActive = sal_True;
706 
707     if ( ! mxConfigurationController.is())
708         return;
709 
710     switch (nSlotId)
711     {
712         case SID_DRAWINGMODE:
713         case SID_NOTESMODE:
714 		case SID_HANDOUTMODE:
715 		case SID_DIAMODE:
716 		case SID_OUTLINEMODE:
717         {
718 			const SfxItemSet* pRequestArguments = rRequest.GetArgs();
719 			if (pRequestArguments)
720             {
721                 SFX_REQUEST_ARG (rRequest,
722                     pIsActive,
723                     SfxBoolItem,
724                     (sal_uInt16)nSlotId,
725                     sal_False);
726 				bIsActive = pIsActive->GetValue ();
727 			}
728         }
729         break;
730     }
731 
732     try
733     {
734         if ( ! mxConfigurationController.is())
735             throw RuntimeException();
736 
737 
738         Reference<XResourceId> xPaneId (
739             CreateResourceId(framework::FrameworkHelper::msCenterPaneURL));
740         Reference<XView> xView (GetView(xPaneId));
741         ::boost::shared_ptr<ViewShell> pCenterViewShell (GetViewShell(xView));
742 
743         ::rtl::OUString sRequestedView;
744         if (bIsActive)
745         {
746             switch (nSlotId)
747             {
748                 case SID_NORMAL_MULTI_PANE_GUI:
749                 case SID_DRAWINGMODE:
750                     sRequestedView = FrameworkHelper::msImpressViewURL;
751                     break;
752 
753                 case SID_NOTESMODE:
754                     sRequestedView = FrameworkHelper::msNotesViewURL;
755                 break;
756 
757                 case SID_HANDOUTMODE:
758                     sRequestedView = FrameworkHelper::msHandoutViewURL;
759                     break;
760 
761                 case SID_SLIDE_SORTER_MULTI_PANE_GUI:
762                 case SID_DIAMODE:
763                     sRequestedView = FrameworkHelper::msSlideSorterURL;
764                     break;
765 
766                 case SID_OUTLINEMODE:
767                     sRequestedView = FrameworkHelper::msOutlineViewURL;
768                     break;
769             }
770         }
771 
772         if (xView.is()
773             && xView->getResourceId()->getResourceURL().equals(sRequestedView))
774         {
775             // We do not have to switch the view shell but maybe the edit mode
776             // has changed.
777             DrawViewShell* pDrawViewShell
778                 = dynamic_cast<DrawViewShell*>(pCenterViewShell.get());
779             if (pDrawViewShell != NULL)
780             {
781                 pCenterViewShell->Broadcast (
782                     ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_START));
783 
784                 pDrawViewShell->ChangeEditMode (
785                     EM_PAGE, pDrawViewShell->IsLayerModeActive());
786 
787                 pCenterViewShell->Broadcast (
788                     ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_END));
789             }
790         }
791         else
792         {
793             mxConfigurationController->requestResourceActivation(
794                 CreateResourceId(sRequestedView, msCenterPaneURL),
795                 ResourceActivationMode_REPLACE);
796         }
797     }
798     catch (RuntimeException&)
799     {
800         DBG_UNHANDLED_EXCEPTION();
801     }
802 }
803 
804 
805 
806 
807 void FrameworkHelper::RunOnConfigurationEvent(
808     const ::rtl::OUString& rsEventType,
809     const Callback& rCallback)
810 {
811     RunOnEvent(
812         rsEventType,
813         FrameworkHelperAllPassFilter(),
814         rCallback);
815 }
816 
817 
818 
819 
820 void FrameworkHelper::RunOnResourceActivation(
821     const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
822     const Callback& rCallback)
823 {
824     if (mxConfigurationController.is()
825         && mxConfigurationController->getResource(rxResourceId).is())
826     {
827         rCallback(false);
828     }
829     else
830     {
831         RunOnEvent(
832             msResourceActivationEvent,
833             FrameworkHelperResourceIdFilter(rxResourceId),
834             rCallback);
835     }
836 }
837 
838 
839 
840 
841 void FrameworkHelper::RunOnResourceDeactivation(
842     const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
843     const Callback& rCallback,
844     const bool bRunOnDeactivationEnd)
845 {
846     if (mxConfigurationController.is()
847         && ! mxConfigurationController->getResource(rxResourceId).is())
848     {
849         rCallback(false);
850     }
851     else
852     {
853         RunOnEvent(
854             bRunOnDeactivationEnd
855                 ? msResourceDeactivationEndEvent
856                 : msResourceDeactivationEvent,
857             FrameworkHelperResourceIdFilter(rxResourceId),
858             rCallback);
859     }
860 }
861 
862 
863 
864 
865 /** A callback that sets a flag to a specified value when the callback is
866     called.
867 */
868 class FlagUpdater
869 {
870 public:
871     FlagUpdater (bool& rFlag) : mrFlag(rFlag) {}
872     void operator() (bool) {mrFlag = true;}
873 private:
874     bool& mrFlag;
875 };
876 
877 
878 
879 
880 void FrameworkHelper::RequestSynchronousUpdate (void)
881 {
882     rtl::Reference<ConfigurationController> pCC (
883         dynamic_cast<ConfigurationController*>(mxConfigurationController.get()));
884     if (pCC.is())
885         pCC->RequestSynchronousUpdate();
886 }
887 
888 
889 
890 
891 void FrameworkHelper::WaitForEvent (const OUString& rsEventType) const
892 {
893     bool bConfigurationUpdateSeen (false);
894 
895     RunOnEvent(
896         rsEventType,
897         FrameworkHelperAllPassFilter(),
898         FlagUpdater(bConfigurationUpdateSeen));
899 
900 	sal_uInt32 nStartTime = osl_getGlobalTimer();
901     while ( ! bConfigurationUpdateSeen)
902     {
903         Application::Reschedule();
904 
905 		if( (osl_getGlobalTimer() - nStartTime) > 60000  )
906 		{
907 			DBG_ERROR("FrameworkHelper::WaitForEvent(), no event for a minute? giving up!");
908 			break;
909 		}
910     }
911 }
912 
913 
914 
915 
916 void FrameworkHelper::WaitForUpdate (void) const
917 {
918     WaitForEvent(msConfigurationUpdateEndEvent);
919 }
920 
921 
922 
923 
924 void FrameworkHelper::RunOnEvent(
925     const ::rtl::OUString& rsEventType,
926     const ConfigurationChangeEventFilter& rFilter,
927     const Callback& rCallback) const
928 {
929     new CallbackCaller(mrBase,rsEventType,rFilter,rCallback);
930 }
931 
932 
933 
934 
935 void FrameworkHelper::disposing (const lang::EventObject& rEventObject)
936 {
937     if (rEventObject.Source == mxConfigurationController)
938         mxConfigurationController = NULL;
939 }
940 
941 
942 
943 
944 void FrameworkHelper::UpdateConfiguration (void)
945 {
946     if (mxConfigurationController.is())
947     {
948         try
949         {
950             if (mxConfigurationController.is())
951                 mxConfigurationController->update();
952         }
953         catch (lang::DisposedException&)
954         {
955             Dispose();
956         }
957         catch (RuntimeException&)
958         {
959             DBG_UNHANDLED_EXCEPTION();
960         }
961     }
962 }
963 
964 
965 
966 
967 OUString FrameworkHelper::ResourceIdToString (const Reference<XResourceId>& rxResourceId)
968 {
969     OUString sString;
970     if (rxResourceId.is())
971     {
972         sString += rxResourceId->getResourceURL();
973         if (rxResourceId->hasAnchor())
974         {
975             Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
976             for (sal_Int32 nIndex=0; nIndex<aAnchorURLs.getLength(); ++nIndex)
977             {
978                 sString += OUString::createFromAscii(" | ");
979                 sString += aAnchorURLs[nIndex];
980             }
981         }
982     }
983     return sString;
984 }
985 
986 
987 
988 
989 Reference<XResourceId> FrameworkHelper::CreateResourceId (const ::rtl::OUString& rsResourceURL)
990 {
991     return new ::sd::framework::ResourceId(rsResourceURL);
992 }
993 
994 
995 
996 
997 Reference<XResourceId> FrameworkHelper::CreateResourceId (
998     const OUString& rsResourceURL,
999     const OUString& rsAnchorURL)
1000 {
1001     return new ::sd::framework::ResourceId(rsResourceURL, rsAnchorURL);
1002 }
1003 
1004 
1005 
1006 
1007 Reference<XResourceId> FrameworkHelper::CreateResourceId (
1008     const OUString& rsResourceURL,
1009     const OUString& rsFirstAnchorURL,
1010     const OUString& rsSecondAnchorURL)
1011 {
1012     ::std::vector<OUString> aAnchorURLs (2);
1013     aAnchorURLs[0] = rsFirstAnchorURL;
1014     aAnchorURLs[1] = rsSecondAnchorURL;
1015     return new ::sd::framework::ResourceId(rsResourceURL, aAnchorURLs);
1016 }
1017 
1018 
1019 
1020 
1021 Reference<XResourceId> FrameworkHelper::CreateResourceId (
1022     const ::rtl::OUString& rsResourceURL,
1023     const Reference<XResourceId>& rxAnchorId)
1024 {
1025     if (rxAnchorId.is())
1026         return new ::sd::framework::ResourceId(
1027             rsResourceURL,
1028             rxAnchorId->getResourceURL(),
1029             rxAnchorId->getAnchorURLs());
1030     else
1031         return new ::sd::framework::ResourceId(rsResourceURL);
1032 }
1033 
1034 
1035 
1036 
1037 Reference<XConfigurationController> FrameworkHelper::GetConfigurationController (void) const
1038 {
1039     return mxConfigurationController;
1040 }
1041 
1042 
1043 
1044 
1045 //----- FrameworkHelper::DisposeListener --------------------------------------
1046 
1047 FrameworkHelper::DisposeListener::DisposeListener (
1048     const ::boost::shared_ptr<FrameworkHelper>& rpHelper)
1049     : FrameworkHelperDisposeListenerInterfaceBase(maMutex),
1050       mpHelper(rpHelper)
1051 {
1052     Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
1053     if (xComponent.is())
1054         xComponent->addEventListener(this);
1055 }
1056 
1057 
1058 
1059 
1060 FrameworkHelper::DisposeListener::~DisposeListener (void)
1061 {
1062 }
1063 
1064 
1065 
1066 
1067 void SAL_CALL FrameworkHelper::DisposeListener::disposing (void)
1068 {
1069     Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
1070     if (xComponent.is())
1071         xComponent->removeEventListener(this);
1072 
1073     mpHelper.reset();
1074 }
1075 
1076 
1077 
1078 
1079 void SAL_CALL FrameworkHelper::DisposeListener::disposing (const lang::EventObject& rEventObject)
1080     throw(RuntimeException)
1081 {
1082     if (mpHelper.get() != NULL)
1083         mpHelper->disposing(rEventObject);
1084 }
1085 
1086 
1087 
1088 
1089 //===== FrameworkHelperResourceIdFilter =======================================
1090 
1091 FrameworkHelperResourceIdFilter::FrameworkHelperResourceIdFilter (
1092     const Reference<XResourceId>& rxResourceId)
1093     : mxResourceId(rxResourceId)
1094 {
1095 }
1096 
1097 
1098 } } // end of namespace sd::framework
1099 
1100 namespace {
1101 
1102 //===== CallbackCaller ========================================================
1103 
1104 CallbackCaller::CallbackCaller (
1105     ::sd::ViewShellBase& rBase,
1106     const OUString& rsEventType,
1107     const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter,
1108     const ::sd::framework::FrameworkHelper::Callback& rCallback)
1109     : CallbackCallerInterfaceBase(MutexOwner::maMutex),
1110       msEventType(rsEventType),
1111       mxConfigurationController(),
1112       maFilter(rFilter),
1113       maCallback(rCallback)
1114 {
1115     try
1116     {
1117         Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY_THROW);
1118         mxConfigurationController = xControllerManager->getConfigurationController();
1119         if (mxConfigurationController.is())
1120         {
1121             if (mxConfigurationController->hasPendingRequests())
1122                 mxConfigurationController->addConfigurationChangeListener(this,msEventType,Any());
1123             else
1124             {
1125                 // There are no requests waiting to be processed.  Therefore
1126                 // no event, especially not the one we are waiting for, will
1127                 // be sent in the near future and the callback would never be
1128                 // called.
1129                 // Call the callback now and tell him that the event it is
1130                 // waiting for was not sent.
1131                 mxConfigurationController = NULL;
1132                 maCallback(false);
1133             }
1134         }
1135     }
1136     catch (RuntimeException&)
1137     {
1138         DBG_UNHANDLED_EXCEPTION();
1139     }
1140 }
1141 
1142 
1143 
1144 
1145 CallbackCaller::~CallbackCaller (void)
1146 {
1147 }
1148 
1149 
1150 
1151 
1152 void CallbackCaller::disposing (void)
1153 {
1154     try
1155     {
1156         if (mxConfigurationController.is())
1157         {
1158             Reference<XConfigurationController> xCC (mxConfigurationController);
1159             mxConfigurationController = NULL;
1160             xCC->removeConfigurationChangeListener(this);
1161         }
1162     }
1163     catch (RuntimeException&)
1164     {
1165         DBG_UNHANDLED_EXCEPTION();
1166     }
1167 }
1168 
1169 
1170 
1171 
1172 void SAL_CALL CallbackCaller::disposing (const lang::EventObject& rEvent)
1173     throw (RuntimeException)
1174 {
1175     if (rEvent.Source == mxConfigurationController)
1176     {
1177         mxConfigurationController = NULL;
1178         maCallback(false);
1179     }
1180 }
1181 
1182 
1183 
1184 
1185 void SAL_CALL CallbackCaller::notifyConfigurationChange (
1186     const ConfigurationChangeEvent& rEvent)
1187     throw (RuntimeException)
1188 {
1189     if (rEvent.Type.equals(msEventType) && maFilter(rEvent))
1190     {
1191         maCallback(true);
1192         if (mxConfigurationController.is())
1193         {
1194             // Reset the reference to the configuration controller so that
1195             // dispose() will not try to remove the listener a second time.
1196             Reference<XConfigurationController> xCC (mxConfigurationController);
1197             mxConfigurationController = NULL;
1198 
1199             // Removing this object from the controller may very likely lead
1200             // to its destruction, so no calls after that.
1201             xCC->removeConfigurationChangeListener(this);
1202         }
1203     }
1204 }
1205 
1206 
1207 
1208 
1209 //----- LifetimeController -------------------------------------------------
1210 
1211 LifetimeController::LifetimeController (::sd::ViewShellBase& rBase)
1212     : LifetimeControllerInterfaceBase(maMutex),
1213       mrBase(rBase),
1214       mbListeningToViewShellBase(false),
1215       mbListeningToController(false)
1216 {
1217     // Register as listener at the ViewShellBase.  Because that is not done
1218     // via a reference we have to increase the reference count manually.
1219     // This is necessary even though listening to the XController did
1220     // increase the reference count because the controller may release its
1221     // reference to us before the ViewShellBase is destroyed.
1222     StartListening(mrBase);
1223     acquire();
1224     mbListeningToViewShellBase = true;
1225 
1226     Reference<XComponent> xComponent (rBase.GetController(), UNO_QUERY);
1227     if (xComponent.is())
1228     {
1229         xComponent->addEventListener(this);
1230         mbListeningToController = true;
1231     }
1232 }
1233 
1234 
1235 
1236 
1237 LifetimeController::~LifetimeController (void)
1238 {
1239     OSL_ASSERT(!mbListeningToController && !mbListeningToViewShellBase);
1240 }
1241 
1242 
1243 
1244 
1245 void LifetimeController::disposing (void)
1246 {
1247 }
1248 
1249 
1250 
1251 
1252 void SAL_CALL LifetimeController::disposing (const lang::EventObject& rEvent)
1253     throw(RuntimeException)
1254 {
1255     (void)rEvent;
1256     mbListeningToController = false;
1257     Update();
1258 }
1259 
1260 
1261 
1262 
1263 void LifetimeController::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
1264 {
1265     (void)rBroadcaster;
1266     const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
1267     if (pSimpleHint != NULL && pSimpleHint->GetId() == SFX_HINT_DYING)
1268     {
1269         mbListeningToViewShellBase = false;
1270         Update();
1271         release();
1272     }
1273 }
1274 
1275 
1276 
1277 
1278 void LifetimeController::Update (void)
1279 {
1280     if (mbListeningToViewShellBase && mbListeningToController)
1281     {
1282         // Both the controller and the ViewShellBase are alive.  Keep
1283         // waiting for their destruction.
1284     }
1285     else if (mbListeningToViewShellBase)
1286     {
1287         // The controller has been destroyed but the ViewShellBase is still
1288         // alive.  Dispose the associated FrameworkHelper but keep it around
1289         // so that no new instance is created for the dying framework.
1290         ::sd::framework::FrameworkHelper::DisposeInstance(mrBase);
1291     }
1292     else
1293     {
1294         // Both the controller and the ViewShellBase have been destroyed.
1295         // Remove the FrameworkHelper so that the next call its Instance()
1296         // method can create a new instance.
1297         ::sd::framework::FrameworkHelper::ReleaseInstance(mrBase);
1298     }
1299 }
1300 
1301 
1302 
1303 } // end of anonymous namespace.
1304