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