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 CallListeners(EventMultiplexerEvent::EID_EDIT_MODE
);
580 //===== frame::XFrameActionListener ==========================================
582 void SAL_CALL
EventMultiplexer::Implementation::frameAction (
583 const frame::FrameActionEvent
& rEvent
)
584 throw (::com::sun::star::uno::RuntimeException
)
586 Reference
<frame::XFrame
> xFrame (mxFrameWeak
);
587 if (rEvent
.Frame
== xFrame
)
588 switch (rEvent
.Action
)
590 case frame::FrameAction_COMPONENT_DETACHING
:
591 DisconnectFromController();
592 CallListeners (EventMultiplexerEvent::EID_CONTROLLER_DETACHED
);
595 case frame::FrameAction_COMPONENT_REATTACHED
:
596 CallListeners (EventMultiplexerEvent::EID_CONTROLLER_DETACHED
);
597 DisconnectFromController();
598 ConnectToController();
599 CallListeners (EventMultiplexerEvent::EID_CONTROLLER_ATTACHED
);
602 case frame::FrameAction_COMPONENT_ATTACHED
:
603 ConnectToController();
604 CallListeners (EventMultiplexerEvent::EID_CONTROLLER_ATTACHED
);
615 //===== view::XSelectionChangeListener ========================================
617 void SAL_CALL
EventMultiplexer::Implementation::selectionChanged (
618 const lang::EventObject
& )
619 throw (::com::sun::star::uno::RuntimeException
)
621 CallListeners (EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION
);
627 //===== drawing::framework::XConfigurationChangeListener ==================
629 void SAL_CALL
EventMultiplexer::Implementation::notifyConfigurationChange (
630 const ConfigurationChangeEvent
& rEvent
)
631 throw (RuntimeException
)
633 sal_Int32 nEventType
= 0;
634 rEvent
.UserData
>>= nEventType
;
637 case ResourceActivationEvent
:
638 if (rEvent
.ResourceId
->getResourceURL().match(FrameworkHelper::msViewURLPrefix
))
640 CallListeners (EventMultiplexerEvent::EID_VIEW_ADDED
);
642 if (rEvent
.ResourceId
->isBoundToURL(
643 FrameworkHelper::msCenterPaneURL
, AnchorBindingMode_DIRECT
))
645 CallListeners (EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
);
648 // Add selection change listener at slide sorter.
649 if (rEvent
.ResourceId
->getResourceURL().equals(FrameworkHelper::msSlideSorterURL
))
651 slidesorter::SlideSorterViewShell
* pViewShell
652 = dynamic_cast<slidesorter::SlideSorterViewShell
*>(
653 FrameworkHelper::GetViewShell(
654 Reference
<XView
>(rEvent
.ResourceObject
,UNO_QUERY
)).get());
655 if (pViewShell
!= NULL
)
656 pViewShell
->AddSelectionChangeListener (
658 EventMultiplexer::Implementation
,
659 SlideSorterSelectionChangeListener
));
664 case ResourceDeactivationEvent
:
665 if (rEvent
.ResourceId
->getResourceURL().match(FrameworkHelper::msViewURLPrefix
))
667 CallListeners (EventMultiplexerEvent::EID_VIEW_REMOVED
);
669 if (rEvent
.ResourceId
->isBoundToURL(
670 FrameworkHelper::msCenterPaneURL
, AnchorBindingMode_DIRECT
))
672 CallListeners (EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
);
675 // Remove selection change listener from slide sorter. Add
676 // selection change listener at slide sorter.
677 if (rEvent
.ResourceId
->getResourceURL().equals(FrameworkHelper::msSlideSorterURL
))
679 slidesorter::SlideSorterViewShell
* pViewShell
680 = dynamic_cast<slidesorter::SlideSorterViewShell
*>(
681 FrameworkHelper::GetViewShell(
682 Reference
<XView
>(rEvent
.ResourceObject
, UNO_QUERY
)).get());
683 if (pViewShell
!= NULL
)
684 pViewShell
->RemoveSelectionChangeListener (
686 EventMultiplexer::Implementation
,
687 SlideSorterSelectionChangeListener
));
692 case ConfigurationUpdateEvent
:
693 CallListeners (EventMultiplexerEvent::EID_CONFIGURATION_UPDATED
);
702 void SAL_CALL
EventMultiplexer::Implementation::disposing (void)
704 CallListeners (EventMultiplexerEvent::EID_DISPOSING
);
711 void EventMultiplexer::Implementation::ThrowIfDisposed (void)
712 throw (::com::sun::star::lang::DisposedException
)
714 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
716 throw lang::DisposedException (
717 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
718 "SlideSorterController object has already been disposed")),
719 static_cast<uno::XWeak
*>(this));
726 void EventMultiplexer::Implementation::Notify (
728 const SfxHint
& rHint
)
730 if (rHint
.ISA(SdrHint
))
732 SdrHint
& rSdrHint (*PTR_CAST(SdrHint
,&rHint
));
733 switch (rSdrHint
.GetKind())
735 case HINT_MODELCLEARED
:
736 case HINT_PAGEORDERCHG
:
737 CallListeners (EventMultiplexerEvent::EID_PAGE_ORDER
);
740 case HINT_SWITCHTOPAGE
:
741 CallListeners (EventMultiplexerEvent::EID_CURRENT_PAGE
);
745 CallListeners(EventMultiplexerEvent::EID_SHAPE_CHANGED
,
746 const_cast<void*>(static_cast<const void*>(rSdrHint
.GetPage())));
749 case HINT_OBJINSERTED
:
750 CallListeners(EventMultiplexerEvent::EID_SHAPE_INSERTED
,
751 const_cast<void*>(static_cast<const void*>(rSdrHint
.GetPage())));
754 case HINT_OBJREMOVED
:
755 CallListeners(EventMultiplexerEvent::EID_SHAPE_REMOVED
,
756 const_cast<void*>(static_cast<const void*>(rSdrHint
.GetPage())));
762 else if (rHint
.ISA(SfxSimpleHint
))
764 SfxSimpleHint
& rSimpleHint (*PTR_CAST(SfxSimpleHint
, &rHint
));
765 if (rSimpleHint
.GetId() == SFX_HINT_DYING
)
773 void EventMultiplexer::Implementation::CallListeners (
774 EventMultiplexerEvent::EventId eId
,
777 EventMultiplexerEvent
aEvent (mrBase
, eId
, pUserData
);
778 CallListeners(aEvent
);
784 void EventMultiplexer::Implementation::CallListeners (EventMultiplexerEvent
& rEvent
)
786 ListenerList
aCopyListeners( maListeners
);
787 ListenerList::iterator
iListener (aCopyListeners
.begin());
788 ListenerList::const_iterator
iListenerEnd (aCopyListeners
.end());
789 for (; iListener
!=iListenerEnd
; ++iListener
)
791 if ((iListener
->second
&& rEvent
.meEventId
) != 0)
792 iListener
->first
.Call(&rEvent
);
799 IMPL_LINK(EventMultiplexer::Implementation
, SlideSorterSelectionChangeListener
, void*, EMPTYARG
)
801 CallListeners (EventMultiplexerEvent::EID_SLIDE_SORTER_SELECTION
);
808 //===== EventMultiplexerEvent =================================================
810 EventMultiplexerEvent::EventMultiplexerEvent (
811 const ViewShellBase
& rBase
,
813 const void* pUserData
)
816 mpUserData(pUserData
)
821 } } // end of namespace ::sd::tools