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