1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: EventMultiplexer.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
34 #include "EventMultiplexer.hxx"
36 #include "MutexOwner.hxx"
37 #include "ViewShellBase.hxx"
38 #include "drawdoc.hxx"
39 #include "DrawController.hxx"
40 #include "SlideSorterViewShell.hxx"
41 #include "framework/FrameworkHelper.hxx"
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/frame/XFrame.hpp>
45 #include <com/sun/star/lang/DisposedException.hpp>
46 #include <com/sun/star/drawing/framework/XConfigurationChangeListener.hpp>
47 #include <cppuhelper/weak.hxx>
48 #include <cppuhelper/compbase4.hxx>
49 #include <sfx2/viewfrm.hxx>
51 using namespace ::com::sun::star
;
52 using namespace ::com::sun::star::lang
;
53 using namespace ::com::sun::star::uno
;
54 using namespace ::com::sun::star::drawing::framework
;
56 using ::rtl::OUString
;
57 using ::sd::framework::FrameworkHelper
;
62 static const sal_Int32 ResourceActivationEvent
= 0;
63 static const sal_Int32 ResourceDeactivationEvent
= 1;
64 static const sal_Int32 ConfigurationUpdateEvent
= 2;
67 namespace sd
{ namespace tools
{
69 typedef cppu::WeakComponentImplHelper4
<
70 ::com::sun::star::beans::XPropertyChangeListener
,
71 ::com::sun::star::frame::XFrameActionListener
,
72 ::com::sun::star::view::XSelectionChangeListener
,
73 ::com::sun::star::drawing::framework::XConfigurationChangeListener
74 > EventMultiplexerImplementationInterfaceBase
;
76 class EventMultiplexer::Implementation
77 : protected MutexOwner
,
78 public EventMultiplexerImplementationInterfaceBase
,
82 Implementation (ViewShellBase
& rBase
);
83 ~Implementation (void);
85 void AddEventListener (
87 EventMultiplexerEvent::EventId aEventTypes
);
89 void RemoveEventListener (
91 EventMultiplexerEvent::EventId aEventTypes
);
93 void CallListeners (EventMultiplexerEvent
& rEvent
);
95 ViewShellBase
& GetViewShellBase() const { return mrBase
; }
97 //===== lang::XEventListener ==============================================
99 disposing (const ::com::sun::star::lang::EventObject
& rEventObject
)
100 throw (::com::sun::star::uno::RuntimeException
);
103 //===== beans::XPropertySetListener =======================================
104 virtual void SAL_CALL
106 const com::sun::star::beans::PropertyChangeEvent
& rEvent
)
107 throw (::com::sun::star::uno::RuntimeException
);
109 //===== view::XSelectionChangeListener ====================================
110 virtual void SAL_CALL
112 const com::sun::star::lang::EventObject
& rEvent
)
113 throw (::com::sun::star::uno::RuntimeException
);
115 //===== frame::XFrameActionListener ======================================
116 /** For certain actions the listener connects to a new controller of the
117 frame it is listening to. This usually happens when the view shell
118 in the center pane is replaced by another view shell.
120 virtual void SAL_CALL
121 frameAction (const ::com::sun::star::frame::FrameActionEvent
& rEvent
)
122 throw (::com::sun::star::uno::RuntimeException
);
124 //===== drawing::framework::XConfigurationChangeListener ==================
125 virtual void SAL_CALL
126 notifyConfigurationChange (
127 const ::com::sun::star::drawing::framework::ConfigurationChangeEvent
& rEvent
)
128 throw (::com::sun::star::uno::RuntimeException
);
131 virtual void SAL_CALL
disposing (void);
134 virtual void Notify (
135 SfxBroadcaster
& rBroadcaster
,
136 const SfxHint
& rHint
);
139 ViewShellBase
& mrBase
;
140 typedef ::std::pair
<Link
,EventMultiplexerEvent::EventId
> ListenerDescriptor
;
141 typedef ::std::vector
<ListenerDescriptor
> ListenerList
;
142 ListenerList maListeners
;
144 /// Remember whether we are listening to the UNO controller.
145 bool mbListeningToController
;
146 /// Remember whether we are listening to the frame.
147 bool mbListeningToFrame
;
149 ::com::sun::star::uno::WeakReference
<
150 ::com::sun::star::frame::XController
> mxControllerWeak
;
151 ::com::sun::star::uno::WeakReference
<
152 ::com::sun::star::frame::XFrame
> mxFrameWeak
;
153 ::com::sun::star::uno::WeakReference
<
154 ::com::sun::star::view::XSelectionSupplier
> mxSlideSorterSelectionWeak
;
155 SdDrawDocument
* mpDocument
;
156 ::com::sun::star::uno::WeakReference
<
157 ::com::sun::star::drawing::framework::XConfigurationController
>
158 mxConfigurationControllerWeak
;
160 static const ::rtl::OUString msCurrentPagePropertyName
;
161 static const ::rtl::OUString msEditModePropertyName
;
163 void ReleaseListeners (void);
165 void ConnectToController (void);
166 void DisconnectFromController (void);
169 EventMultiplexerEvent::EventId eId
,
170 void* pUserData
= NULL
);
172 /** This method throws a DisposedException when the object has already been
175 void ThrowIfDisposed (void)
176 throw (::com::sun::star::lang::DisposedException
);
178 DECL_LINK(SlideSorterSelectionChangeListener
, void*);
182 const ::rtl::OUString
EventMultiplexer::Implementation::msCurrentPagePropertyName (
183 RTL_CONSTASCII_USTRINGPARAM("CurrentPage"));
184 const ::rtl::OUString
EventMultiplexer::Implementation::msEditModePropertyName (
185 RTL_CONSTASCII_USTRINGPARAM("IsMasterPageMode"));
188 //===== EventMultiplexer ======================================================
190 EventMultiplexer::EventMultiplexer (ViewShellBase
& rBase
)
191 : mpImpl (new EventMultiplexer::Implementation(rBase
))
199 EventMultiplexer::~EventMultiplexer (void)
204 // Now we call release twice. One decreases the use count of the
205 // implementation object (if all goes well to zero and thus deletes
206 // it.) The other releases the auto_ptr and prevents the
207 // implementation object from being deleted a second time.
211 catch (RuntimeException aException
)
214 catch (Exception aException
)
222 void EventMultiplexer::AddEventListener (
224 EventMultiplexerEvent::EventId aEventTypes
)
226 mpImpl
->AddEventListener (rCallback
, aEventTypes
);
232 void EventMultiplexer::RemoveEventListener (
234 EventMultiplexerEvent::EventId aEventTypes
)
236 mpImpl
->RemoveEventListener (rCallback
, aEventTypes
);
242 void EventMultiplexer::MultiplexEvent(
243 EventMultiplexerEvent::EventId eEventId
,
246 EventMultiplexerEvent
aEvent (mpImpl
->GetViewShellBase(), eEventId
, pUserData
);
247 mpImpl
->CallListeners(aEvent
);
253 //===== EventMultiplexer::Implementation ======================================
255 EventMultiplexer::Implementation::Implementation (ViewShellBase
& rBase
)
257 EventMultiplexerImplementationInterfaceBase(maMutex
),
260 mbListeningToController (false),
261 mbListeningToFrame (false),
262 mxControllerWeak(NULL
),
264 mxSlideSorterSelectionWeak(NULL
),
266 mxConfigurationControllerWeak()
268 // Connect to the frame to listen for controllers being exchanged.
269 // Listen to changes of certain properties.
270 Reference
<frame::XFrame
> xFrame (
271 mrBase
.GetFrame()->GetTopFrame()->GetFrameInterface(),
273 mxFrameWeak
= xFrame
;
276 xFrame
->addFrameActionListener (
277 Reference
<frame::XFrameActionListener
>(
278 static_cast<XWeak
*>(this), UNO_QUERY
));
279 mbListeningToFrame
= true;
282 // Connect to the current controller.
283 ConnectToController ();
285 // Listen for document changes.
286 mpDocument
= mrBase
.GetDocument();
287 if (mpDocument
!= NULL
)
288 StartListening (*mpDocument
);
290 // Listen for configuration changes.
291 Reference
<XControllerManager
> xControllerManager (
292 Reference
<XWeak
>(&mrBase
.GetDrawController()), UNO_QUERY
);
293 if (xControllerManager
.is())
295 Reference
<XConfigurationController
> xConfigurationController (
296 xControllerManager
->getConfigurationController());
297 mxConfigurationControllerWeak
= xConfigurationController
;
298 if (xConfigurationController
.is())
300 Reference
<XComponent
> xComponent (xConfigurationController
, UNO_QUERY
);
302 xComponent
->addEventListener(static_cast<beans::XPropertyChangeListener
*>(this));
304 xConfigurationController
->addConfigurationChangeListener(
306 FrameworkHelper::msResourceActivationEvent
,
307 makeAny(ResourceActivationEvent
));
308 xConfigurationController
->addConfigurationChangeListener(
310 FrameworkHelper::msResourceDeactivationEvent
,
311 makeAny(ResourceDeactivationEvent
));
312 xConfigurationController
->addConfigurationChangeListener(
314 FrameworkHelper::msConfigurationUpdateEndEvent
,
315 makeAny(ConfigurationUpdateEvent
));
323 EventMultiplexer::Implementation::~Implementation (void)
325 DBG_ASSERT( !mbListeningToFrame
,
326 "sd::EventMultiplexer::Implementation::~Implementation(), disposing was not called!" );
332 void EventMultiplexer::Implementation::ReleaseListeners (void)
334 if (mbListeningToFrame
)
336 mbListeningToFrame
= false;
338 // Stop listening for changes of certain properties.
339 Reference
<frame::XFrame
> xFrame (mxFrameWeak
);
342 xFrame
->removeFrameActionListener (
343 Reference
<frame::XFrameActionListener
>(
344 static_cast<XWeak
*>(this), UNO_QUERY
));
348 DisconnectFromController ();
350 if (mpDocument
!= NULL
)
352 EndListening (*mpDocument
);
356 // Stop listening for configuration changes.
357 Reference
<XConfigurationController
> xConfigurationController (mxConfigurationControllerWeak
);
358 if (xConfigurationController
.is())
360 Reference
<XComponent
> xComponent (xConfigurationController
, UNO_QUERY
);
362 xComponent
->removeEventListener(static_cast<beans::XPropertyChangeListener
*>(this));
364 xConfigurationController
->removeConfigurationChangeListener(this);
371 void EventMultiplexer::Implementation::AddEventListener (
373 EventMultiplexerEvent::EventId aEventTypes
)
375 ListenerList::iterator
iListener (maListeners
.begin());
376 ListenerList::const_iterator
iEnd (maListeners
.end());
377 for (;iListener
!=iEnd
; ++iListener
)
378 if (iListener
->first
== rCallback
)
380 if (iListener
!= maListeners
.end())
382 // Listener exists. Update its event type set.
383 iListener
->second
|= aEventTypes
;
387 maListeners
.push_back (ListenerDescriptor(rCallback
,aEventTypes
));
394 void EventMultiplexer::Implementation::RemoveEventListener (
396 EventMultiplexerEvent::EventId aEventTypes
)
398 ListenerList::iterator
iListener (maListeners
.begin());
399 ListenerList::const_iterator
iEnd (maListeners
.end());
400 for (;iListener
!=iEnd
; ++iListener
)
401 if (iListener
->first
== rCallback
)
403 if (iListener
!= maListeners
.end())
405 // Update the event type set.
406 iListener
->second
&= ~aEventTypes
;
407 // When no events remain in the set then remove the listener.
408 if (iListener
->second
== EID_EMPTY_SET
)
409 maListeners
.erase (iListener
);
416 void EventMultiplexer::Implementation::ConnectToController (void)
418 // Just in case that we missed some event we now disconnect from the old
420 DisconnectFromController ();
422 // Register at the controller of the main view shell.
424 // We have to store a (weak) reference to the controller so that we can
425 // unregister without having to ask the mrBase member (which at that
426 // time may be destroyed.)
427 Reference
<frame::XController
> xController
= mrBase
.GetController();
428 mxControllerWeak
= mrBase
.GetController();
432 // Listen for disposing events.
433 Reference
<lang::XComponent
> xComponent (xController
, UNO_QUERY
);
436 xComponent
->addEventListener (
437 Reference
<lang::XEventListener
>(
438 static_cast<XWeak
*>(this), UNO_QUERY
));
439 mbListeningToController
= true;
442 // Listen to changes of certain properties.
443 Reference
<beans::XPropertySet
> xSet (xController
, UNO_QUERY
);
448 xSet
->addPropertyChangeListener(msCurrentPagePropertyName
, this);
450 catch (beans::UnknownPropertyException
)
452 OSL_TRACE("EventMultiplexer::ConnectToController: CurrentPage unknown");
457 xSet
->addPropertyChangeListener(msEditModePropertyName
, this);
459 catch (beans::UnknownPropertyException
)
461 OSL_TRACE("EventMultiplexer::ConnectToController: IsMasterPageMode unknown");
465 // Listen for selection change events.
466 Reference
<view::XSelectionSupplier
> xSelection (xController
, UNO_QUERY
);
469 xSelection
->addSelectionChangeListener(this);
472 catch (const lang::DisposedException aException
)
474 mbListeningToController
= false;
481 void EventMultiplexer::Implementation::DisconnectFromController (void)
483 if (mbListeningToController
)
485 mbListeningToController
= false;
487 Reference
<frame::XController
> xController
= mxControllerWeak
;
489 Reference
<beans::XPropertySet
> xSet (xController
, UNO_QUERY
);
490 // Remove the property listener.
495 xSet
->removePropertyChangeListener(msCurrentPagePropertyName
, this);
497 catch (beans::UnknownPropertyException aEvent
)
499 OSL_TRACE ("DisconnectFromController: CurrentPage unknown");
504 xSet
->removePropertyChangeListener(msEditModePropertyName
, this);
506 catch (beans::UnknownPropertyException aEvent
)
508 OSL_TRACE ("DisconnectFromController: IsMasterPageMode unknown");
512 // Remove selection change listener.
513 Reference
<view::XSelectionSupplier
> xSelection (xController
, UNO_QUERY
);
516 xSelection
->removeSelectionChangeListener(this);
519 // Remove listener for disposing events.
520 Reference
<lang::XComponent
> xComponent (xController
, UNO_QUERY
);
523 xComponent
->removeEventListener (
524 Reference
<lang::XEventListener
>(static_cast<XWeak
*>(this), UNO_QUERY
));
532 //===== lang::XEventListener ================================================
534 void SAL_CALL
EventMultiplexer::Implementation::disposing (
535 const lang::EventObject
& rEventObject
)
536 throw (RuntimeException
)
538 if (mbListeningToController
)
540 Reference
<frame::XController
> xController (mxControllerWeak
);
541 if (rEventObject
.Source
== xController
)
543 mbListeningToController
= false;
547 Reference
<XConfigurationController
> xConfigurationController (
548 mxConfigurationControllerWeak
);
549 if (xConfigurationController
.is()
550 && rEventObject
.Source
== xConfigurationController
)
552 mxConfigurationControllerWeak
= Reference
<XConfigurationController
>();
559 //===== beans::XPropertySetListener =========================================
561 void SAL_CALL
EventMultiplexer::Implementation::propertyChange (
562 const beans::PropertyChangeEvent
& rEvent
)
563 throw (RuntimeException
)
567 if (rEvent
.PropertyName
.equals(msCurrentPagePropertyName
))
569 CallListeners(EventMultiplexerEvent::EID_CURRENT_PAGE
);
571 else if (rEvent
.PropertyName
.equals(msEditModePropertyName
))
573 bool bIsMasterPageMode (false);
574 rEvent
.NewValue
>>= bIsMasterPageMode
;
575 if (bIsMasterPageMode
)
576 CallListeners(EventMultiplexerEvent::EID_EDIT_MODE_MASTER
);
578 CallListeners(EventMultiplexerEvent::EID_EDIT_MODE_NORMAL
);
585 //===== frame::XFrameActionListener ==========================================
587 void SAL_CALL
EventMultiplexer::Implementation::frameAction (
588 const frame::FrameActionEvent
& rEvent
)
589 throw (::com::sun::star::uno::RuntimeException
)
591 Reference
<frame::XFrame
> xFrame (mxFrameWeak
);
592 if (rEvent
.Frame
== xFrame
)
593 switch (rEvent
.Action
)
595 case frame::FrameAction_COMPONENT_DETACHING
:
596 DisconnectFromController();
597 CallListeners (EventMultiplexerEvent::EID_CONTROLLER_DETACHED
);
600 case frame::FrameAction_COMPONENT_REATTACHED
:
601 CallListeners (EventMultiplexerEvent::EID_CONTROLLER_DETACHED
);
602 DisconnectFromController();
603 ConnectToController();
604 CallListeners (EventMultiplexerEvent::EID_CONTROLLER_ATTACHED
);
607 case frame::FrameAction_COMPONENT_ATTACHED
:
608 ConnectToController();
609 CallListeners (EventMultiplexerEvent::EID_CONTROLLER_ATTACHED
);
620 //===== view::XSelectionChangeListener ========================================
622 void SAL_CALL
EventMultiplexer::Implementation::selectionChanged (
623 const lang::EventObject
& )
624 throw (::com::sun::star::uno::RuntimeException
)
626 CallListeners (EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION
);
632 //===== drawing::framework::XConfigurationChangeListener ==================
634 void SAL_CALL
EventMultiplexer::Implementation::notifyConfigurationChange (
635 const ConfigurationChangeEvent
& rEvent
)
636 throw (RuntimeException
)
638 sal_Int32 nEventType
= 0;
639 rEvent
.UserData
>>= nEventType
;
642 case ResourceActivationEvent
:
643 if (rEvent
.ResourceId
->getResourceURL().match(FrameworkHelper::msViewURLPrefix
))
645 CallListeners (EventMultiplexerEvent::EID_VIEW_ADDED
);
647 if (rEvent
.ResourceId
->isBoundToURL(
648 FrameworkHelper::msCenterPaneURL
, AnchorBindingMode_DIRECT
))
650 CallListeners (EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
);
653 // Add selection change listener at slide sorter.
654 if (rEvent
.ResourceId
->getResourceURL().equals(FrameworkHelper::msSlideSorterURL
))
656 slidesorter::SlideSorterViewShell
* pViewShell
657 = dynamic_cast<slidesorter::SlideSorterViewShell
*>(
658 FrameworkHelper::GetViewShell(
659 Reference
<XView
>(rEvent
.ResourceObject
,UNO_QUERY
)).get());
660 if (pViewShell
!= NULL
)
661 pViewShell
->AddSelectionChangeListener (
663 EventMultiplexer::Implementation
,
664 SlideSorterSelectionChangeListener
));
669 case ResourceDeactivationEvent
:
670 if (rEvent
.ResourceId
->getResourceURL().match(FrameworkHelper::msViewURLPrefix
))
672 CallListeners (EventMultiplexerEvent::EID_VIEW_REMOVED
);
674 if (rEvent
.ResourceId
->isBoundToURL(
675 FrameworkHelper::msCenterPaneURL
, AnchorBindingMode_DIRECT
))
677 CallListeners (EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
);
680 // Remove selection change listener from slide sorter. Add
681 // selection change listener at slide sorter.
682 if (rEvent
.ResourceId
->getResourceURL().equals(FrameworkHelper::msSlideSorterURL
))
684 slidesorter::SlideSorterViewShell
* pViewShell
685 = dynamic_cast<slidesorter::SlideSorterViewShell
*>(
686 FrameworkHelper::GetViewShell(
687 Reference
<XView
>(rEvent
.ResourceObject
, UNO_QUERY
)).get());
688 if (pViewShell
!= NULL
)
689 pViewShell
->RemoveSelectionChangeListener (
691 EventMultiplexer::Implementation
,
692 SlideSorterSelectionChangeListener
));
697 case ConfigurationUpdateEvent
:
698 CallListeners (EventMultiplexerEvent::EID_CONFIGURATION_UPDATED
);
707 void SAL_CALL
EventMultiplexer::Implementation::disposing (void)
709 CallListeners (EventMultiplexerEvent::EID_DISPOSING
);
716 void EventMultiplexer::Implementation::ThrowIfDisposed (void)
717 throw (::com::sun::star::lang::DisposedException
)
719 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
721 throw lang::DisposedException (
722 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
723 "SlideSorterController object has already been disposed")),
724 static_cast<uno::XWeak
*>(this));
731 void EventMultiplexer::Implementation::Notify (
733 const SfxHint
& rHint
)
735 if (rHint
.ISA(SdrHint
))
737 SdrHint
& rSdrHint (*PTR_CAST(SdrHint
,&rHint
));
738 switch (rSdrHint
.GetKind())
740 case HINT_MODELCLEARED
:
741 case HINT_PAGEORDERCHG
:
742 CallListeners (EventMultiplexerEvent::EID_PAGE_ORDER
);
745 case HINT_SWITCHTOPAGE
:
746 CallListeners (EventMultiplexerEvent::EID_CURRENT_PAGE
);
750 CallListeners(EventMultiplexerEvent::EID_SHAPE_CHANGED
,
751 const_cast<void*>(static_cast<const void*>(rSdrHint
.GetPage())));
754 case HINT_OBJINSERTED
:
755 CallListeners(EventMultiplexerEvent::EID_SHAPE_INSERTED
,
756 const_cast<void*>(static_cast<const void*>(rSdrHint
.GetPage())));
759 case HINT_OBJREMOVED
:
760 CallListeners(EventMultiplexerEvent::EID_SHAPE_REMOVED
,
761 const_cast<void*>(static_cast<const void*>(rSdrHint
.GetPage())));
767 else if (rHint
.ISA(SfxSimpleHint
))
769 SfxSimpleHint
& rSimpleHint (*PTR_CAST(SfxSimpleHint
, &rHint
));
770 if (rSimpleHint
.GetId() == SFX_HINT_DYING
)
778 void EventMultiplexer::Implementation::CallListeners (
779 EventMultiplexerEvent::EventId eId
,
782 EventMultiplexerEvent
aEvent (mrBase
, eId
, pUserData
);
783 CallListeners(aEvent
);
789 void EventMultiplexer::Implementation::CallListeners (EventMultiplexerEvent
& rEvent
)
791 ListenerList
aCopyListeners( maListeners
);
792 ListenerList::iterator
iListener (aCopyListeners
.begin());
793 ListenerList::const_iterator
iListenerEnd (aCopyListeners
.end());
794 for (; iListener
!=iListenerEnd
; ++iListener
)
796 if ((iListener
->second
&& rEvent
.meEventId
) != 0)
797 iListener
->first
.Call(&rEvent
);
804 IMPL_LINK(EventMultiplexer::Implementation
, SlideSorterSelectionChangeListener
, void*, EMPTYARG
)
806 CallListeners (EventMultiplexerEvent::EID_SLIDE_SORTER_SELECTION
);
813 //===== EventMultiplexerEvent =================================================
815 EventMultiplexerEvent::EventMultiplexerEvent (
816 const ViewShellBase
& rBase
,
818 const void* pUserData
)
821 mpUserData(pUserData
)
826 } } // end of namespace ::sd::tools