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