1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_COMPHELPER_LISTENERNOTIFICATION_HXX
21 #define INCLUDED_COMPHELPER_LISTENERNOTIFICATION_HXX
23 #include <comphelper/interfacecontainer2.hxx>
25 #include <com/sun/star/lang/XEventListener.hpp>
26 #include <comphelper/comphelperdllapi.h>
35 //= OListenerContainer
37 /** abstract base class which manages a listener container, including
38 THB's listener notification pattern which cares for removing listeners
39 which throw an DisposedException upon notification
41 Using this class is pretty easy:
43 <li>Derive from it, and overwrite implNotify.</li>
44 <li>Use <member>impl_addListener</member> and <member>impl_removeListener</member> in your
45 XFoo::addFooListener and XFoo::removeFooListener methods.</li>
46 <li>call <member>impl_notify</member> whenever the event you want to notify happened</li>
47 <li>call <member>disposing</member> upon the disposal of your broadcaster.</li>
50 See OListenerContainerBase for an implementation which even saves
51 you some more work, by doing the casts for you.
53 @see http://www.openoffice.org/servlets/ReadMsg?list=interface-announce&msgId=494345
54 @see OListenerContainerBase
56 class COMPHELPER_DLLPUBLIC OListenerContainer
59 ::comphelper::OInterfaceContainerHelper2 m_aListeners
;
62 /** sends a XEventObject::disposing notification to all listeners, and clears the
65 You'll usually call this from within your own dispose/disposing method
67 void disposing( const css::lang::EventObject
& _rEventSource
);
69 /** clears the container without calling <member scope="css::lang">XEventListener::disposing</member>
74 /** determines whether the listener container is currently empty
79 /** creates an iterator for looping through all registered listeners
81 ::std::unique_ptr
< ::comphelper::OInterfaceIteratorHelper2
> createIterator()
83 ::std::unique_ptr
< ::comphelper::OInterfaceIteratorHelper2
> pIterator( new ::comphelper::OInterfaceIteratorHelper2( m_aListeners
) );
88 OListenerContainer( ::osl::Mutex
& _rMutex
);
90 virtual ~OListenerContainer();
92 void impl_addListener( const css::uno::Reference
< css::lang::XEventListener
>& _rxListener
);
93 void impl_removeListener( const css::uno::Reference
< css::lang::XEventListener
>& _rxListener
);
95 /** notifies all listeners of the given event, using THB's notification pattern
97 internally, this method will call <member>implNotify</member> for every listener
100 <TRUE/> if all listeners have been notified, <FALSE/> else. The latter can happen
101 if <member>implNotify</member> cancelles the notification loop.
105 bool impl_notify( const css::lang::EventObject
& _rEvent
);
108 /** call a single listener
112 @throws css::uno::Exception
113 if the listener throws an exception during notification. Please don't catch
114 any listener exceptions in your implementation of this method, simply let them
118 specifies the listener to call. Is guaranteed to not be <NULL/>
120 the event to broadcast. This is the same as passed to <member>notify</member>, so if
121 your base class knows the type passed into <member>notify</member>, it can safely assume
122 that <arg>_rEvent</arg> is also of this type.
125 <TRUE/> if the remaining listeners should be called, <FALSE/> if the notification
126 loop should be cancelled
130 virtual bool implNotify(
131 const css::uno::Reference
< css::lang::XEventListener
>& _rxListener
,
132 const css::lang::EventObject
& _rEvent
137 inline bool OListenerContainer::empty() const
139 return ( m_aListeners
.getLength() == 0 );
143 //= OSimpleListenerContainer
145 /** helper class for simple notification of the form LISTENER::METHOD( EVENT )
147 This class is not threadsafe!
150 the listener class to call, e.g. css::lang::XEventListener
152 the event type to notify, e.g. css::lang::EventObject
154 template< class LISTENER
, class EVENT
>
155 class OSimpleListenerContainer
: protected OListenerContainer
158 typedef LISTENER ListenerClass
;
159 typedef EVENT EventClass
;
160 typedef void ( SAL_CALL
LISTENER::*NotificationMethod
)( const EventClass
& );
163 NotificationMethod m_pNotificationMethod
;
166 OSimpleListenerContainer( ::osl::Mutex
& _rMutex
)
167 :OListenerContainer( _rMutex
)
168 ,m_pNotificationMethod( nullptr )
172 inline void addListener( const css::uno::Reference
< ListenerClass
>& _rxListener
)
174 OListenerContainer::impl_addListener( _rxListener
.get() );
177 inline void removeListener( const css::uno::Reference
< ListenerClass
>& _rxListener
)
179 OListenerContainer::impl_removeListener( _rxListener
.get() );
182 // publish some otherwise hidden base functionality
183 using OListenerContainer::disposing
;
184 using OListenerContainer::clear
;
185 using OListenerContainer::empty
;
186 using OListenerContainer::createIterator
;
188 /// typed notification
189 inline bool notify( const EventClass
& _rEvent
, NotificationMethod _pNotify
);
192 virtual bool implNotify(
193 const css::uno::Reference
< css::lang::XEventListener
>& _rxListener
,
194 const css::lang::EventObject
& _rEvent
197 const EventClass
& rTypedEvent( static_cast< const EventClass
& >( _rEvent
) );
198 ListenerClass
* pTypedListener( static_cast< ListenerClass
* >( _rxListener
.get() ) );
199 (pTypedListener
->*m_pNotificationMethod
)( rTypedEvent
);
205 template< class LISTENER
, class EVENT
>
206 inline bool OSimpleListenerContainer
< LISTENER
, EVENT
>::notify( const EventClass
& _rEvent
, NotificationMethod _pNotify
)
208 m_pNotificationMethod
= _pNotify
;
209 bool bRet
= OListenerContainer::impl_notify( _rEvent
);
210 m_pNotificationMethod
= nullptr;
214 //= OListenerContainerBase
216 /** is a specialization of OListenerContainer which saves you some additional type casts,
217 by making the required listener and event types template arguments.
219 template< class LISTENER
, class EVENT
>
220 class OListenerContainerBase
: public OListenerContainer
223 typedef LISTENER ListenerClass
;
224 typedef EVENT EventClass
;
227 inline OListenerContainerBase( ::osl::Mutex
& _rMutex
) : OListenerContainer( _rMutex
)
231 inline void addTypedListener( const css::uno::Reference
< ListenerClass
>& _rxListener
)
233 OListenerContainer::impl_addListener( _rxListener
.get() );
236 inline void removeTypedListener( const css::uno::Reference
< ListenerClass
>& _rxListener
)
238 OListenerContainer::impl_removeListener( _rxListener
.get() );
241 inline bool notify( const EventClass
& _rEvent
)
243 return OListenerContainer::impl_notify( _rEvent
);
246 using OListenerContainer::impl_notify
;
249 virtual bool implNotify(
250 const css::uno::Reference
< css::lang::XEventListener
>& _rxListener
,
251 const css::lang::EventObject
& _rEvent
254 return implTypedNotify(
255 css::uno::Reference
< ListenerClass
>( static_cast< ListenerClass
* >( _rxListener
.get() ) ),
256 static_cast< const EventClass
& >( _rEvent
)
260 virtual bool implTypedNotify(
261 const css::uno::Reference
< ListenerClass
>& _rxListener
,
262 const EventClass
& _rEvent
266 } // namespace comphelper
269 #endif // INCLUDED_COMPHELPER_LISTENERNOTIFICATION_HXX
271 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */