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 controlling 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 {
lcl_getViewShell(const Reference<XResource> & i_rViewShellWrapper)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 }
lcl_getFirstViewInPane(const Reference<XConfigurationController> & i_rConfigController,const Reference<XResourceId> & i_rPaneId)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:
ViewURLMap(void)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:
operator ()(FrameworkHelper * pObject)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
Instance(const Reference<frame::XController> & rxController)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
Instance(ViewShellBase & rBase)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
DisposeInstance(ViewShellBase & rBase)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
ReleaseInstance(ViewShellBase & rBase)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
FrameworkHelper(ViewShellBase & rBase)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
Initialize(void)465 void FrameworkHelper::Initialize (void)
466 {
467 mxDisposeListener = new DisposeListener(shared_from_this());
468 }
469
470
471
472
~FrameworkHelper(void)473 FrameworkHelper::~FrameworkHelper (void)
474 {
475 }
476
477
478
479
Dispose(void)480 void FrameworkHelper::Dispose (void)
481 {
482 if (mxDisposeListener.is())
483 mxDisposeListener->dispose();
484 mxConfigurationController = NULL;
485 }
486
487
488
489
IsValid(void)490 bool FrameworkHelper::IsValid (void)
491 {
492 return mxConfigurationController.is();
493 }
494
495
496
497
GetViewShell(const OUString & rsPaneURL)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
GetViewShell(const Reference<XView> & rxView)510 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const Reference<XView>& rxView)
511 {
512 return lcl_getViewShell( rxView.get() );
513 }
514
515
516
517
GetView(const Reference<XResourceId> & rxPaneOrViewId)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
GetPaneWindow(const Reference<XResourceId> & rxPaneId)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
GetResource(const Reference<XResourceId> & rxResourceId)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
RequestView(const OUString & rsResourceURL,const OUString & rsAnchorURL)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
RequestResourceDeactivation(const cssu::Reference<cssdf::XResourceId> & rxResourceId)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
GetViewId(const rtl::OUString & rsViewURL)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
GetViewURL(ViewShell::ShellType eType)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
HandleModeChangeSlot(sal_uLong nSlotId,SfxRequest & rRequest)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
RunOnConfigurationEvent(const::rtl::OUString & rsEventType,const Callback & rCallback)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
RunOnResourceActivation(const css::uno::Reference<css::drawing::framework::XResourceId> & rxResourceId,const Callback & rCallback)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
RunOnResourceDeactivation(const css::uno::Reference<css::drawing::framework::XResourceId> & rxResourceId,const Callback & rCallback,const bool bRunOnDeactivationEnd)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:
FlagUpdater(bool & rFlag)871 FlagUpdater (bool& rFlag) : mrFlag(rFlag) {}
operator ()(bool)872 void operator() (bool) {mrFlag = true;}
873 private:
874 bool& mrFlag;
875 };
876
877
878
879
RequestSynchronousUpdate(void)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
WaitForEvent(const OUString & rsEventType) const891 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
WaitForUpdate(void) const916 void FrameworkHelper::WaitForUpdate (void) const
917 {
918 WaitForEvent(msConfigurationUpdateEndEvent);
919 }
920
921
922
923
RunOnEvent(const::rtl::OUString & rsEventType,const ConfigurationChangeEventFilter & rFilter,const Callback & rCallback) const924 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
disposing(const lang::EventObject & rEventObject)935 void FrameworkHelper::disposing (const lang::EventObject& rEventObject)
936 {
937 if (rEventObject.Source == mxConfigurationController)
938 mxConfigurationController = NULL;
939 }
940
941
942
943
UpdateConfiguration(void)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
ResourceIdToString(const Reference<XResourceId> & rxResourceId)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
CreateResourceId(const::rtl::OUString & rsResourceURL)989 Reference<XResourceId> FrameworkHelper::CreateResourceId (const ::rtl::OUString& rsResourceURL)
990 {
991 return new ::sd::framework::ResourceId(rsResourceURL);
992 }
993
994
995
996
CreateResourceId(const OUString & rsResourceURL,const OUString & rsAnchorURL)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
CreateResourceId(const OUString & rsResourceURL,const OUString & rsFirstAnchorURL,const OUString & rsSecondAnchorURL)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
CreateResourceId(const::rtl::OUString & rsResourceURL,const Reference<XResourceId> & rxAnchorId)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
GetConfigurationController(void) const1037 Reference<XConfigurationController> FrameworkHelper::GetConfigurationController (void) const
1038 {
1039 return mxConfigurationController;
1040 }
1041
1042
1043
1044
1045 //----- FrameworkHelper::DisposeListener --------------------------------------
1046
DisposeListener(const::boost::shared_ptr<FrameworkHelper> & rpHelper)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
~DisposeListener(void)1060 FrameworkHelper::DisposeListener::~DisposeListener (void)
1061 {
1062 }
1063
1064
1065
1066
disposing(void)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
disposing(const lang::EventObject & rEventObject)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
FrameworkHelperResourceIdFilter(const Reference<XResourceId> & rxResourceId)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
CallbackCaller(::sd::ViewShellBase & rBase,const OUString & rsEventType,const::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter & rFilter,const::sd::framework::FrameworkHelper::Callback & rCallback)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
~CallbackCaller(void)1145 CallbackCaller::~CallbackCaller (void)
1146 {
1147 }
1148
1149
1150
1151
disposing(void)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
disposing(const lang::EventObject & rEvent)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
notifyConfigurationChange(const ConfigurationChangeEvent & rEvent)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
LifetimeController(::sd::ViewShellBase & rBase)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
~LifetimeController(void)1237 LifetimeController::~LifetimeController (void)
1238 {
1239 OSL_ASSERT(!mbListeningToController && !mbListeningToViewShellBase);
1240 }
1241
1242
1243
1244
disposing(void)1245 void LifetimeController::disposing (void)
1246 {
1247 }
1248
1249
1250
1251
disposing(const lang::EventObject & rEvent)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
Notify(SfxBroadcaster & rBroadcaster,const SfxHint & rHint)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
Update(void)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