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 // XConfigurationChangeListener
107 virtual void SAL_CALL notifyConfigurationChange (const ConfigurationChangeEvent& rEvent);
108
109 private:
110 OUString msEventType;
111 Reference<XConfigurationController> mxConfigurationController;
112 ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter maFilter;
113 ::sd::framework::FrameworkHelper::Callback maCallback;
114 };
115
116
117
118
119 //----- LifetimeController ----------------------------------------------------
120
121 typedef ::cppu::WeakComponentImplHelper1 <
122 ::com::sun::star::lang::XEventListener
123 > LifetimeControllerInterfaceBase;
124
125 /** This class helps controlling the lifetime of the
126 FrameworkHelper. Register at a ViewShellBase object and an XController
127 object and call Dispose() at the associated FrameworkHelper object when
128 one of them and Release() when both of them are destroyed.
129 */
130 class LifetimeController
131 : public ::sd::MutexOwner,
132 public LifetimeControllerInterfaceBase,
133 public SfxListener
134 {
135 public:
136 explicit LifetimeController (::sd::ViewShellBase& rBase);
137 virtual ~LifetimeController (void);
138
139 virtual void SAL_CALL disposing (void);
140
141 /** XEventListener. This method is called when the frame::XController
142 is being destroyed.
143 */
144 virtual void SAL_CALL disposing (const lang::EventObject& rEvent);
145
146 /** This method is called when the ViewShellBase is being destroyed.
147 */
148 virtual void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint);
149
150 private:
151 ::sd::ViewShellBase& mrBase;
152 bool mbListeningToViewShellBase;
153 bool mbListeningToController;
154
155 /** When one or both of the mbListeningToViewShellBase and
156 mbListeningToController members were modified then call this method
157 to either dispose or release the associated FrameworkHelper.
158 */
159 void Update (void);
160 };
161
162
163
164 } // end of anonymous namespace
165
166 namespace sd { namespace framework {
167
168 // Pane URLS.
169
170 const OUString FrameworkHelper::msPaneURLPrefix(
171 OUString::createFromAscii("private:resource/pane/"));
172 const OUString FrameworkHelper::msCenterPaneURL(
173 msPaneURLPrefix + OUString::createFromAscii("CenterPane"));
174 const OUString FrameworkHelper::msFullScreenPaneURL(
175 msPaneURLPrefix + OUString::createFromAscii("FullScreenPane"));
176 const OUString FrameworkHelper::msLeftImpressPaneURL(
177 msPaneURLPrefix + OUString::createFromAscii("LeftImpressPane"));
178 const OUString FrameworkHelper::msLeftDrawPaneURL(
179 msPaneURLPrefix + OUString::createFromAscii("LeftDrawPane"));
180 const OUString FrameworkHelper::msSidebarPaneURL(
181 msPaneURLPrefix + OUString::createFromAscii("SidebarPane"));
182
183
184 // View URLs.
185
186 const OUString FrameworkHelper::msViewURLPrefix(
187 OUString::createFromAscii("private:resource/view/"));
188 const OUString FrameworkHelper::msImpressViewURL(
189 msViewURLPrefix + OUString::createFromAscii("ImpressView"));
190 const OUString FrameworkHelper::msDrawViewURL(
191 msViewURLPrefix + OUString::createFromAscii("GraphicView"));
192 const OUString FrameworkHelper::msOutlineViewURL(
193 msViewURLPrefix + OUString::createFromAscii("OutlineView"));
194 const OUString FrameworkHelper::msNotesViewURL(
195 msViewURLPrefix + OUString::createFromAscii("NotesView"));
196 const OUString FrameworkHelper::msHandoutViewURL(
197 msViewURLPrefix + OUString::createFromAscii("HandoutView"));
198 const OUString FrameworkHelper::msSlideSorterURL(
199 msViewURLPrefix + OUString::createFromAscii("SlideSorter"));
200 const OUString FrameworkHelper::msPresentationViewURL(
201 msViewURLPrefix + OUString::createFromAscii("PresentationView"));
202 const OUString FrameworkHelper::msSidebarViewURL(
203 msViewURLPrefix + OUString::createFromAscii("SidebarView"));
204
205
206 // Tool bar URLs.
207
208 const OUString FrameworkHelper::msToolBarURLPrefix(
209 OUString::createFromAscii("private:resource/toolbar/"));
210 const OUString FrameworkHelper::msViewTabBarURL(
211 msToolBarURLPrefix + OUString::createFromAscii("ViewTabBar"));
212
213
214 // Task panel URLs.
215 const ::rtl::OUString FrameworkHelper::msTaskPanelURLPrefix(
216 OUString::createFromAscii("private:resource/toolpanel/"));
217 const ::rtl::OUString FrameworkHelper::msAllMasterPagesTaskPanelURL(
218 msTaskPanelURLPrefix + OUString::createFromAscii("AllMasterPages"));
219 const ::rtl::OUString FrameworkHelper::msRecentMasterPagesTaskPanelURL(
220 msTaskPanelURLPrefix + OUString::createFromAscii("RecentMasterPages"));
221 const ::rtl::OUString FrameworkHelper::msUsedMasterPagesTaskPanelURL(
222 msTaskPanelURLPrefix + OUString::createFromAscii("UsedMasterPages"));
223 const ::rtl::OUString FrameworkHelper::msLayoutTaskPanelURL(
224 msTaskPanelURLPrefix + OUString::createFromAscii("Layouts"));
225 const ::rtl::OUString FrameworkHelper::msTableDesignPanelURL(
226 msTaskPanelURLPrefix + OUString::createFromAscii("TableDesign"));
227 const ::rtl::OUString FrameworkHelper::msCustomAnimationTaskPanelURL(
228 msTaskPanelURLPrefix + OUString::createFromAscii("CustomAnimations"));
229 const ::rtl::OUString FrameworkHelper::msSlideTransitionTaskPanelURL(
230 msTaskPanelURLPrefix + OUString::createFromAscii("SlideTransitions"));
231
232
233 // Event URLs.
234 const OUString FrameworkHelper::msResourceActivationRequestEvent(
235 OUString::createFromAscii("ResourceActivationRequested"));
236 const OUString FrameworkHelper::msResourceDeactivationRequestEvent(
237 OUString::createFromAscii("ResourceDeactivationRequest"));
238 const OUString FrameworkHelper::msResourceActivationEvent(
239 OUString::createFromAscii("ResourceActivation"));
240 const OUString FrameworkHelper::msResourceDeactivationEvent(
241 OUString::createFromAscii("ResourceDeactivation"));
242 const OUString FrameworkHelper::msResourceDeactivationEndEvent(
243 OUString::createFromAscii("ResourceDeactivationEnd"));
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 {
lcl_getViewShell(const Reference<XResource> & i_rViewShellWrapper)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 }
lcl_getFirstViewInPane(const Reference<XConfigurationController> & i_rConfigController,const Reference<XResourceId> & i_rPaneId)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:
ViewURLMap(void)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
336 private:
337 ::boost::shared_ptr<FrameworkHelper> mpHelper;
338 };
339
340
341
342
343 //----- FrameworkHelper::Deleter ----------------------------------------------
344
345 class FrameworkHelper::Deleter
346 {
347 public:
operator ()(FrameworkHelper * pObject)348 void operator()(FrameworkHelper* pObject)
349 {
350 delete pObject;
351 }
352 };
353
354
355
356
357 //----- FrameworkHelper -------------------------------------------------------
358
359 ::boost::scoped_ptr<FrameworkHelper::ViewURLMap> FrameworkHelper::mpViewURLMap(new ViewURLMap());
360
361
362 FrameworkHelper::InstanceMap FrameworkHelper::maInstanceMap;
363
364
365
Instance(const Reference<frame::XController> & rxController)366 ::boost::shared_ptr<FrameworkHelper> FrameworkHelper::Instance (
367 const Reference<frame::XController>& rxController)
368 {
369 // Tunnel through the controller to obtain a ViewShellBase.
370 Reference<lang::XUnoTunnel> xTunnel (rxController, UNO_QUERY);
371 if (xTunnel.is())
372 {
373 ::sd::DrawController* pController = reinterpret_cast<sd::DrawController*>(
374 xTunnel->getSomething(sd::DrawController::getUnoTunnelId()));
375 if (pController != NULL)
376 {
377 ViewShellBase* pBase = pController->GetViewShellBase();
378 if (pBase != NULL)
379 return Instance(*pBase);
380 }
381 }
382
383 return ::boost::shared_ptr<FrameworkHelper>();
384 }
385
386
387
388
Instance(ViewShellBase & rBase)389 ::boost::shared_ptr<FrameworkHelper> FrameworkHelper::Instance (ViewShellBase& rBase)
390 {
391
392 ::boost::shared_ptr<FrameworkHelper> pHelper;
393
394 InstanceMap::const_iterator iHelper (maInstanceMap.find(&rBase));
395 if (iHelper == maInstanceMap.end())
396 {
397 ::osl::GetGlobalMutex aMutexFunctor;
398 ::osl::MutexGuard aGuard (aMutexFunctor());
399 if (iHelper == maInstanceMap.end())
400 {
401 pHelper = ::boost::shared_ptr<FrameworkHelper>(
402 new FrameworkHelper(rBase),
403 FrameworkHelper::Deleter());
404 pHelper->Initialize();
405 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
406 maInstanceMap[&rBase] = pHelper;
407 }
408 }
409 else
410 {
411 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
412 pHelper = iHelper->second;
413 }
414
415 return pHelper;
416 }
417
418
419
420
DisposeInstance(ViewShellBase & rBase)421 void FrameworkHelper::DisposeInstance (ViewShellBase& rBase)
422 {
423 InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
424 if (iHelper != maInstanceMap.end())
425 {
426 iHelper->second->Dispose();
427 }
428 }
429
430
431
432
ReleaseInstance(ViewShellBase & rBase)433 void FrameworkHelper::ReleaseInstance (ViewShellBase& rBase)
434 {
435 InstanceMap::iterator iHelper (maInstanceMap.find(&rBase));
436 if (iHelper != maInstanceMap.end())
437 maInstanceMap.erase(iHelper);
438 }
439
440
441
442
FrameworkHelper(ViewShellBase & rBase)443 FrameworkHelper::FrameworkHelper (ViewShellBase& rBase)
444 : mrBase(rBase),
445 mxConfigurationController(),
446 mxDisposeListener()
447
448 {
449 Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY);
450 if (xControllerManager.is())
451 {
452 mxConfigurationController = xControllerManager->getConfigurationController();
453 }
454
455 new LifetimeController(mrBase);
456 }
457
458
459
460
Initialize(void)461 void FrameworkHelper::Initialize (void)
462 {
463 mxDisposeListener = new DisposeListener(shared_from_this());
464 }
465
466
467
468
~FrameworkHelper(void)469 FrameworkHelper::~FrameworkHelper (void)
470 {
471 }
472
473
474
475
Dispose(void)476 void FrameworkHelper::Dispose (void)
477 {
478 if (mxDisposeListener.is())
479 mxDisposeListener->dispose();
480 mxConfigurationController = NULL;
481 }
482
483
484
485
IsValid(void)486 bool FrameworkHelper::IsValid (void)
487 {
488 return mxConfigurationController.is();
489 }
490
491
492
493
GetViewShell(const OUString & rsPaneURL)494 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const OUString& rsPaneURL)
495 {
496 if ( !mxConfigurationController.is() )
497 return ::boost::shared_ptr<ViewShell>();
498
499 Reference<XResourceId> xPaneId( CreateResourceId( rsPaneURL ) );
500 return lcl_getViewShell( lcl_getFirstViewInPane( mxConfigurationController, xPaneId ) );
501 }
502
503
504
505
GetViewShell(const Reference<XView> & rxView)506 ::boost::shared_ptr<ViewShell> FrameworkHelper::GetViewShell (const Reference<XView>& rxView)
507 {
508 return lcl_getViewShell( rxView.get() );
509 }
510
511
512
513
GetView(const Reference<XResourceId> & rxPaneOrViewId)514 Reference<XView> FrameworkHelper::GetView (const Reference<XResourceId>& rxPaneOrViewId)
515 {
516 Reference<XView> xView;
517
518 if ( ! rxPaneOrViewId.is() || ! mxConfigurationController.is())
519 return NULL;
520
521 try
522 {
523 if (rxPaneOrViewId->getResourceURL().match(msViewURLPrefix))
524 {
525 xView.set( mxConfigurationController->getResource( rxPaneOrViewId ), UNO_QUERY );
526 }
527 else
528 {
529 xView.set( lcl_getFirstViewInPane( mxConfigurationController, rxPaneOrViewId ), UNO_QUERY );
530 }
531 }
532 catch (lang::DisposedException&)
533 {
534 Dispose();
535 }
536 catch (RuntimeException&)
537 {
538 }
539
540 return xView;
541 }
542
543
544
545
GetPaneWindow(const Reference<XResourceId> & rxPaneId)546 Reference<awt::XWindow> FrameworkHelper::GetPaneWindow (const Reference<XResourceId>& rxPaneId)
547 {
548 Reference<awt::XWindow> xWindow;
549
550 if (rxPaneId.is() && mxConfigurationController.is())
551 {
552 try
553 {
554 if (rxPaneId->getResourceURL().match(msPaneURLPrefix))
555 {
556 Reference<XPane> xPane (mxConfigurationController->getResource(rxPaneId), UNO_QUERY);
557 if (xPane.is())
558 xWindow = xPane->getWindow();
559 }
560 }
561 catch (lang::DisposedException&)
562 {
563 Dispose();
564 }
565 catch (RuntimeException&)
566 {
567 }
568 }
569
570 return xWindow;
571 }
572
573
574
575
GetResource(const Reference<XResourceId> & rxResourceId)576 Reference<XResource> FrameworkHelper::GetResource (const Reference<XResourceId>& rxResourceId)
577 {
578 Reference<XResource> xResource;
579
580 if (rxResourceId.is() && mxConfigurationController.is())
581 {
582 try
583 {
584 return mxConfigurationController->getResource(rxResourceId);
585 }
586 catch (lang::DisposedException&)
587 {
588 Dispose();
589 }
590 catch (RuntimeException&)
591 {
592 }
593 }
594
595 return NULL;
596 }
597
598
599
600
RequestView(const OUString & rsResourceURL,const OUString & rsAnchorURL)601 Reference<XResourceId> FrameworkHelper::RequestView (
602 const OUString& rsResourceURL,
603 const OUString& rsAnchorURL)
604 {
605 Reference<XResourceId> xViewId;
606
607 try
608 {
609 if (mxConfigurationController.is())
610 {
611 mxConfigurationController->requestResourceActivation(
612 CreateResourceId(rsAnchorURL),
613 ResourceActivationMode_ADD);
614 xViewId = CreateResourceId(rsResourceURL, rsAnchorURL);
615 mxConfigurationController->requestResourceActivation(
616 xViewId,
617 ResourceActivationMode_REPLACE);
618 }
619 }
620 catch (lang::DisposedException&)
621 {
622 Dispose();
623 xViewId = NULL;
624 }
625 catch (RuntimeException&)
626 {
627 xViewId = NULL;
628 }
629
630 return xViewId;
631 }
632
633
634
635
RequestResourceDeactivation(const cssu::Reference<cssdf::XResourceId> & rxResourceId)636 void FrameworkHelper::RequestResourceDeactivation (const cssu::Reference<cssdf::XResourceId>& rxResourceId)
637 {
638 try
639 {
640 if (mxConfigurationController.is() && rxResourceId.is())
641 mxConfigurationController->requestResourceDeactivation(rxResourceId);
642 }
643 catch (lang::DisposedException&)
644 {
645 Dispose();
646 }
647 catch (RuntimeException&)
648 {}
649 }
650
651
652
653
GetViewId(const rtl::OUString & rsViewURL)654 ViewShell::ShellType FrameworkHelper::GetViewId (const rtl::OUString& rsViewURL)
655 {
656 if (mpViewURLMap->empty())
657 {
658 (*mpViewURLMap)[msImpressViewURL] = ViewShell::ST_IMPRESS;
659 (*mpViewURLMap)[msDrawViewURL] = ViewShell::ST_DRAW;
660 (*mpViewURLMap)[msOutlineViewURL] = ViewShell::ST_OUTLINE;
661 (*mpViewURLMap)[msNotesViewURL] = ViewShell::ST_NOTES;
662 (*mpViewURLMap)[msHandoutViewURL] = ViewShell::ST_HANDOUT;
663 (*mpViewURLMap)[msSlideSorterURL] = ViewShell::ST_SLIDE_SORTER;
664 (*mpViewURLMap)[msPresentationViewURL] = ViewShell::ST_PRESENTATION;
665 (*mpViewURLMap)[msSidebarViewURL] = ViewShell::ST_SIDEBAR;
666 }
667 ViewURLMap::const_iterator iView (mpViewURLMap->find(rsViewURL));
668 if (iView != mpViewURLMap->end())
669 return iView->second;
670 else
671 return ViewShell::ST_NONE;
672 }
673
674
675
676
GetViewURL(ViewShell::ShellType eType)677 ::rtl::OUString FrameworkHelper::GetViewURL (ViewShell::ShellType eType)
678 {
679 switch (eType)
680 {
681 case ViewShell::ST_IMPRESS : return msImpressViewURL;
682 case ViewShell::ST_DRAW : return msDrawViewURL;
683 case ViewShell::ST_OUTLINE : return msOutlineViewURL;
684 case ViewShell::ST_NOTES : return msNotesViewURL;
685 case ViewShell::ST_HANDOUT : return msHandoutViewURL;
686 case ViewShell::ST_SLIDE_SORTER : return msSlideSorterURL;
687 case ViewShell::ST_PRESENTATION : return msPresentationViewURL;
688 case ViewShell::ST_SIDEBAR : return msSidebarViewURL;
689 default:
690 return OUString();
691 }
692 }
693
694
695
696
HandleModeChangeSlot(sal_uLong nSlotId,SfxRequest & rRequest)697 void FrameworkHelper::HandleModeChangeSlot (
698 sal_uLong nSlotId,
699 SfxRequest& rRequest)
700 {
701 sal_Bool bIsActive = sal_True;
702
703 if ( ! mxConfigurationController.is())
704 return;
705
706 switch (nSlotId)
707 {
708 case SID_DRAWINGMODE:
709 case SID_NOTESMODE:
710 case SID_HANDOUTMODE:
711 case SID_DIAMODE:
712 case SID_OUTLINEMODE:
713 {
714 const SfxItemSet* pRequestArguments = rRequest.GetArgs();
715 if (pRequestArguments)
716 {
717 SFX_REQUEST_ARG (rRequest,
718 pIsActive,
719 SfxBoolItem,
720 (sal_uInt16)nSlotId,
721 sal_False);
722 bIsActive = pIsActive->GetValue ();
723 }
724 }
725 break;
726 }
727
728 try
729 {
730 if ( ! mxConfigurationController.is())
731 throw RuntimeException();
732
733
734 Reference<XResourceId> xPaneId (
735 CreateResourceId(framework::FrameworkHelper::msCenterPaneURL));
736 Reference<XView> xView (GetView(xPaneId));
737 ::boost::shared_ptr<ViewShell> pCenterViewShell (GetViewShell(xView));
738
739 ::rtl::OUString sRequestedView;
740 if (bIsActive)
741 {
742 switch (nSlotId)
743 {
744 case SID_NORMAL_MULTI_PANE_GUI:
745 case SID_DRAWINGMODE:
746 sRequestedView = FrameworkHelper::msImpressViewURL;
747 break;
748
749 case SID_NOTESMODE:
750 sRequestedView = FrameworkHelper::msNotesViewURL;
751 break;
752
753 case SID_HANDOUTMODE:
754 sRequestedView = FrameworkHelper::msHandoutViewURL;
755 break;
756
757 case SID_SLIDE_SORTER_MULTI_PANE_GUI:
758 case SID_DIAMODE:
759 sRequestedView = FrameworkHelper::msSlideSorterURL;
760 break;
761
762 case SID_OUTLINEMODE:
763 sRequestedView = FrameworkHelper::msOutlineViewURL;
764 break;
765 }
766 }
767
768 if (xView.is()
769 && xView->getResourceId()->getResourceURL().equals(sRequestedView))
770 {
771 // We do not have to switch the view shell but maybe the edit mode
772 // has changed.
773 DrawViewShell* pDrawViewShell
774 = dynamic_cast<DrawViewShell*>(pCenterViewShell.get());
775 if (pDrawViewShell != NULL)
776 {
777 pCenterViewShell->Broadcast (
778 ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_START));
779
780 pDrawViewShell->ChangeEditMode (
781 EM_PAGE, pDrawViewShell->IsLayerModeActive());
782
783 pCenterViewShell->Broadcast (
784 ViewShellHint(ViewShellHint::HINT_CHANGE_EDIT_MODE_END));
785 }
786 }
787 else
788 {
789 mxConfigurationController->requestResourceActivation(
790 CreateResourceId(sRequestedView, msCenterPaneURL),
791 ResourceActivationMode_REPLACE);
792 }
793 }
794 catch (RuntimeException&)
795 {
796 DBG_UNHANDLED_EXCEPTION();
797 }
798 }
799
800
801
802
RunOnConfigurationEvent(const::rtl::OUString & rsEventType,const Callback & rCallback)803 void FrameworkHelper::RunOnConfigurationEvent(
804 const ::rtl::OUString& rsEventType,
805 const Callback& rCallback)
806 {
807 RunOnEvent(
808 rsEventType,
809 FrameworkHelperAllPassFilter(),
810 rCallback);
811 }
812
813
814
815
RunOnResourceActivation(const css::uno::Reference<css::drawing::framework::XResourceId> & rxResourceId,const Callback & rCallback)816 void FrameworkHelper::RunOnResourceActivation(
817 const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
818 const Callback& rCallback)
819 {
820 if (mxConfigurationController.is()
821 && mxConfigurationController->getResource(rxResourceId).is())
822 {
823 rCallback(false);
824 }
825 else
826 {
827 RunOnEvent(
828 msResourceActivationEvent,
829 FrameworkHelperResourceIdFilter(rxResourceId),
830 rCallback);
831 }
832 }
833
834
835
836
RunOnResourceDeactivation(const css::uno::Reference<css::drawing::framework::XResourceId> & rxResourceId,const Callback & rCallback,const bool bRunOnDeactivationEnd)837 void FrameworkHelper::RunOnResourceDeactivation(
838 const css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
839 const Callback& rCallback,
840 const bool bRunOnDeactivationEnd)
841 {
842 if (mxConfigurationController.is()
843 && ! mxConfigurationController->getResource(rxResourceId).is())
844 {
845 rCallback(false);
846 }
847 else
848 {
849 RunOnEvent(
850 bRunOnDeactivationEnd
851 ? msResourceDeactivationEndEvent
852 : msResourceDeactivationEvent,
853 FrameworkHelperResourceIdFilter(rxResourceId),
854 rCallback);
855 }
856 }
857
858
859
860
861 /** A callback that sets a flag to a specified value when the callback is
862 called.
863 */
864 class FlagUpdater
865 {
866 public:
FlagUpdater(bool & rFlag)867 FlagUpdater (bool& rFlag) : mrFlag(rFlag) {}
operator ()(bool)868 void operator() (bool) {mrFlag = true;}
869 private:
870 bool& mrFlag;
871 };
872
873
874
875
RequestSynchronousUpdate(void)876 void FrameworkHelper::RequestSynchronousUpdate (void)
877 {
878 rtl::Reference<ConfigurationController> pCC (
879 dynamic_cast<ConfigurationController*>(mxConfigurationController.get()));
880 if (pCC.is())
881 pCC->RequestSynchronousUpdate();
882 }
883
884
885
886
WaitForEvent(const OUString & rsEventType) const887 void FrameworkHelper::WaitForEvent (const OUString& rsEventType) const
888 {
889 bool bConfigurationUpdateSeen (false);
890
891 RunOnEvent(
892 rsEventType,
893 FrameworkHelperAllPassFilter(),
894 FlagUpdater(bConfigurationUpdateSeen));
895
896 sal_uInt32 nStartTime = osl_getGlobalTimer();
897 while ( ! bConfigurationUpdateSeen)
898 {
899 Application::Reschedule();
900
901 if( (osl_getGlobalTimer() - nStartTime) > 60000 )
902 {
903 DBG_ERROR("FrameworkHelper::WaitForEvent(), no event for a minute? giving up!");
904 break;
905 }
906 }
907 }
908
909
910
911
WaitForUpdate(void) const912 void FrameworkHelper::WaitForUpdate (void) const
913 {
914 WaitForEvent(msConfigurationUpdateEndEvent);
915 }
916
917
918
919
RunOnEvent(const::rtl::OUString & rsEventType,const ConfigurationChangeEventFilter & rFilter,const Callback & rCallback) const920 void FrameworkHelper::RunOnEvent(
921 const ::rtl::OUString& rsEventType,
922 const ConfigurationChangeEventFilter& rFilter,
923 const Callback& rCallback) const
924 {
925 new CallbackCaller(mrBase,rsEventType,rFilter,rCallback);
926 }
927
928
929
930
disposing(const lang::EventObject & rEventObject)931 void FrameworkHelper::disposing (const lang::EventObject& rEventObject)
932 {
933 if (rEventObject.Source == mxConfigurationController)
934 mxConfigurationController = NULL;
935 }
936
937
938
939
UpdateConfiguration(void)940 void FrameworkHelper::UpdateConfiguration (void)
941 {
942 if (mxConfigurationController.is())
943 {
944 try
945 {
946 if (mxConfigurationController.is())
947 mxConfigurationController->update();
948 }
949 catch (lang::DisposedException&)
950 {
951 Dispose();
952 }
953 catch (RuntimeException&)
954 {
955 DBG_UNHANDLED_EXCEPTION();
956 }
957 }
958 }
959
960
961
962
ResourceIdToString(const Reference<XResourceId> & rxResourceId)963 OUString FrameworkHelper::ResourceIdToString (const Reference<XResourceId>& rxResourceId)
964 {
965 OUString sString;
966 if (rxResourceId.is())
967 {
968 sString += rxResourceId->getResourceURL();
969 if (rxResourceId->hasAnchor())
970 {
971 Sequence<OUString> aAnchorURLs (rxResourceId->getAnchorURLs());
972 for (sal_Int32 nIndex=0; nIndex<aAnchorURLs.getLength(); ++nIndex)
973 {
974 sString += OUString::createFromAscii(" | ");
975 sString += aAnchorURLs[nIndex];
976 }
977 }
978 }
979 return sString;
980 }
981
982
983
984
CreateResourceId(const::rtl::OUString & rsResourceURL)985 Reference<XResourceId> FrameworkHelper::CreateResourceId (const ::rtl::OUString& rsResourceURL)
986 {
987 return new ::sd::framework::ResourceId(rsResourceURL);
988 }
989
990
991
992
CreateResourceId(const OUString & rsResourceURL,const OUString & rsAnchorURL)993 Reference<XResourceId> FrameworkHelper::CreateResourceId (
994 const OUString& rsResourceURL,
995 const OUString& rsAnchorURL)
996 {
997 return new ::sd::framework::ResourceId(rsResourceURL, rsAnchorURL);
998 }
999
1000
1001
1002
CreateResourceId(const OUString & rsResourceURL,const OUString & rsFirstAnchorURL,const OUString & rsSecondAnchorURL)1003 Reference<XResourceId> FrameworkHelper::CreateResourceId (
1004 const OUString& rsResourceURL,
1005 const OUString& rsFirstAnchorURL,
1006 const OUString& rsSecondAnchorURL)
1007 {
1008 ::std::vector<OUString> aAnchorURLs (2);
1009 aAnchorURLs[0] = rsFirstAnchorURL;
1010 aAnchorURLs[1] = rsSecondAnchorURL;
1011 return new ::sd::framework::ResourceId(rsResourceURL, aAnchorURLs);
1012 }
1013
1014
1015
1016
CreateResourceId(const::rtl::OUString & rsResourceURL,const Reference<XResourceId> & rxAnchorId)1017 Reference<XResourceId> FrameworkHelper::CreateResourceId (
1018 const ::rtl::OUString& rsResourceURL,
1019 const Reference<XResourceId>& rxAnchorId)
1020 {
1021 if (rxAnchorId.is())
1022 return new ::sd::framework::ResourceId(
1023 rsResourceURL,
1024 rxAnchorId->getResourceURL(),
1025 rxAnchorId->getAnchorURLs());
1026 else
1027 return new ::sd::framework::ResourceId(rsResourceURL);
1028 }
1029
1030
1031
1032
GetConfigurationController(void) const1033 Reference<XConfigurationController> FrameworkHelper::GetConfigurationController (void) const
1034 {
1035 return mxConfigurationController;
1036 }
1037
1038
1039
1040
1041 //----- FrameworkHelper::DisposeListener --------------------------------------
1042
DisposeListener(const::boost::shared_ptr<FrameworkHelper> & rpHelper)1043 FrameworkHelper::DisposeListener::DisposeListener (
1044 const ::boost::shared_ptr<FrameworkHelper>& rpHelper)
1045 : FrameworkHelperDisposeListenerInterfaceBase(maMutex),
1046 mpHelper(rpHelper)
1047 {
1048 Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
1049 if (xComponent.is())
1050 xComponent->addEventListener(this);
1051 }
1052
1053
1054
1055
~DisposeListener(void)1056 FrameworkHelper::DisposeListener::~DisposeListener (void)
1057 {
1058 }
1059
1060
1061
1062
disposing(void)1063 void SAL_CALL FrameworkHelper::DisposeListener::disposing (void)
1064 {
1065 Reference<XComponent> xComponent (mpHelper->mxConfigurationController, UNO_QUERY);
1066 if (xComponent.is())
1067 xComponent->removeEventListener(this);
1068
1069 mpHelper.reset();
1070 }
1071
1072
1073
1074
disposing(const lang::EventObject & rEventObject)1075 void SAL_CALL FrameworkHelper::DisposeListener::disposing (const lang::EventObject& rEventObject)
1076 {
1077 if (mpHelper.get() != NULL)
1078 mpHelper->disposing(rEventObject);
1079 }
1080
1081
1082
1083
1084 //===== FrameworkHelperResourceIdFilter =======================================
1085
FrameworkHelperResourceIdFilter(const Reference<XResourceId> & rxResourceId)1086 FrameworkHelperResourceIdFilter::FrameworkHelperResourceIdFilter (
1087 const Reference<XResourceId>& rxResourceId)
1088 : mxResourceId(rxResourceId)
1089 {
1090 }
1091
1092
1093 } } // end of namespace sd::framework
1094
1095 namespace {
1096
1097 //===== CallbackCaller ========================================================
1098
CallbackCaller(::sd::ViewShellBase & rBase,const OUString & rsEventType,const::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter & rFilter,const::sd::framework::FrameworkHelper::Callback & rCallback)1099 CallbackCaller::CallbackCaller (
1100 ::sd::ViewShellBase& rBase,
1101 const OUString& rsEventType,
1102 const ::sd::framework::FrameworkHelper::ConfigurationChangeEventFilter& rFilter,
1103 const ::sd::framework::FrameworkHelper::Callback& rCallback)
1104 : CallbackCallerInterfaceBase(MutexOwner::maMutex),
1105 msEventType(rsEventType),
1106 mxConfigurationController(),
1107 maFilter(rFilter),
1108 maCallback(rCallback)
1109 {
1110 try
1111 {
1112 Reference<XControllerManager> xControllerManager (rBase.GetController(), UNO_QUERY_THROW);
1113 mxConfigurationController = xControllerManager->getConfigurationController();
1114 if (mxConfigurationController.is())
1115 {
1116 if (mxConfigurationController->hasPendingRequests())
1117 mxConfigurationController->addConfigurationChangeListener(this,msEventType,Any());
1118 else
1119 {
1120 // There are no requests waiting to be processed. Therefore
1121 // no event, especially not the one we are waiting for, will
1122 // be sent in the near future and the callback would never be
1123 // called.
1124 // Call the callback now and tell him that the event it is
1125 // waiting for was not sent.
1126 mxConfigurationController = NULL;
1127 maCallback(false);
1128 }
1129 }
1130 }
1131 catch (RuntimeException&)
1132 {
1133 DBG_UNHANDLED_EXCEPTION();
1134 }
1135 }
1136
1137
1138
1139
~CallbackCaller(void)1140 CallbackCaller::~CallbackCaller (void)
1141 {
1142 }
1143
1144
1145
1146
disposing(void)1147 void CallbackCaller::disposing (void)
1148 {
1149 try
1150 {
1151 if (mxConfigurationController.is())
1152 {
1153 Reference<XConfigurationController> xCC (mxConfigurationController);
1154 mxConfigurationController = NULL;
1155 xCC->removeConfigurationChangeListener(this);
1156 }
1157 }
1158 catch (RuntimeException&)
1159 {
1160 DBG_UNHANDLED_EXCEPTION();
1161 }
1162 }
1163
1164
1165
1166
disposing(const lang::EventObject & rEvent)1167 void SAL_CALL CallbackCaller::disposing (const lang::EventObject& rEvent)
1168 {
1169 if (rEvent.Source == mxConfigurationController)
1170 {
1171 mxConfigurationController = NULL;
1172 maCallback(false);
1173 }
1174 }
1175
1176
1177
1178
notifyConfigurationChange(const ConfigurationChangeEvent & rEvent)1179 void SAL_CALL CallbackCaller::notifyConfigurationChange (
1180 const ConfigurationChangeEvent& rEvent)
1181 {
1182 if (rEvent.Type.equals(msEventType) && maFilter(rEvent))
1183 {
1184 maCallback(true);
1185 if (mxConfigurationController.is())
1186 {
1187 // Reset the reference to the configuration controller so that
1188 // dispose() will not try to remove the listener a second time.
1189 Reference<XConfigurationController> xCC (mxConfigurationController);
1190 mxConfigurationController = NULL;
1191
1192 // Removing this object from the controller may very likely lead
1193 // to its destruction, so no calls after that.
1194 xCC->removeConfigurationChangeListener(this);
1195 }
1196 }
1197 }
1198
1199
1200
1201
1202 //----- LifetimeController -------------------------------------------------
1203
LifetimeController(::sd::ViewShellBase & rBase)1204 LifetimeController::LifetimeController (::sd::ViewShellBase& rBase)
1205 : LifetimeControllerInterfaceBase(maMutex),
1206 mrBase(rBase),
1207 mbListeningToViewShellBase(false),
1208 mbListeningToController(false)
1209 {
1210 // Register as listener at the ViewShellBase. Because that is not done
1211 // via a reference we have to increase the reference count manually.
1212 // This is necessary even though listening to the XController did
1213 // increase the reference count because the controller may release its
1214 // reference to us before the ViewShellBase is destroyed.
1215 StartListening(mrBase);
1216 acquire();
1217 mbListeningToViewShellBase = true;
1218
1219 Reference<XComponent> xComponent (rBase.GetController(), UNO_QUERY);
1220 if (xComponent.is())
1221 {
1222 xComponent->addEventListener(this);
1223 mbListeningToController = true;
1224 }
1225 }
1226
1227
1228
1229
~LifetimeController(void)1230 LifetimeController::~LifetimeController (void)
1231 {
1232 OSL_ASSERT(!mbListeningToController && !mbListeningToViewShellBase);
1233 }
1234
1235
1236
1237
disposing(void)1238 void LifetimeController::disposing (void)
1239 {
1240 }
1241
1242
1243
1244
disposing(const lang::EventObject & rEvent)1245 void SAL_CALL LifetimeController::disposing (const lang::EventObject& rEvent)
1246 {
1247 (void)rEvent;
1248 mbListeningToController = false;
1249 Update();
1250 }
1251
1252
1253
1254
Notify(SfxBroadcaster & rBroadcaster,const SfxHint & rHint)1255 void LifetimeController::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
1256 {
1257 (void)rBroadcaster;
1258 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
1259 if (pSimpleHint != NULL && pSimpleHint->GetId() == SFX_HINT_DYING)
1260 {
1261 mbListeningToViewShellBase = false;
1262 Update();
1263 release();
1264 }
1265 }
1266
1267
1268
1269
Update(void)1270 void LifetimeController::Update (void)
1271 {
1272 if (mbListeningToViewShellBase && mbListeningToController)
1273 {
1274 // Both the controller and the ViewShellBase are alive. Keep
1275 // waiting for their destruction.
1276 }
1277 else if (mbListeningToViewShellBase)
1278 {
1279 // The controller has been destroyed but the ViewShellBase is still
1280 // alive. Dispose the associated FrameworkHelper but keep it around
1281 // so that no new instance is created for the dying framework.
1282 ::sd::framework::FrameworkHelper::DisposeInstance(mrBase);
1283 }
1284 else
1285 {
1286 // Both the controller and the ViewShellBase have been destroyed.
1287 // Remove the FrameworkHelper so that the next call its Instance()
1288 // method can create a new instance.
1289 ::sd::framework::FrameworkHelper::ReleaseInstance(mrBase);
1290 }
1291 }
1292
1293
1294
1295 } // end of anonymous namespace.
1296