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 COMPHELPER_INC_COMPHELPER_LISTENERNOTIFICATION_HXX
21 #define COMPHELPER_INC_COMPHELPER_LISTENERNOTIFICATION_HXX
23 #include <cppuhelper/interfacecontainer.hxx>
25 #include <com/sun/star/lang/XEventListener.hpp>
26 #include "comphelper/comphelperdllapi.h"
30 //........................................................................
33 //........................................................................
35 //====================================================================
36 //= OListenerContainer
37 //====================================================================
38 /** abstract base class which manages a listener container, including
39 THB's listener notification pattern which cares for removing listeners
40 which throw an DisposedException upon notification
42 Using this class is pretty easy:
44 <li>Derive from it, and overwrite implNotify.</li>
45 <li>Use <member>impl_addListener</member> and <member>impl_removeListener</member> in your
46 XFoo::addFooListener and XFoo::removeFooListener methods.</li>
47 <li>call <member>impl_notify</member> whenever the event you want to notify happened</li>
48 <li>call <member>disposing</member> upon the disposal of your broadcaster.</li>
51 See <type>OListenerContainerBase</type> for an implementation which even saves
52 you some more work, by doing the casts for you.
54 @see http://www.openoffice.org/servlets/ReadMsg?list=interface-announce&msgId=494345
55 @see OListenerContainerBase
57 class COMPHELPER_DLLPUBLIC OListenerContainer
60 ::cppu::OInterfaceContainerHelper m_aListeners
;
63 /** sends a XEventObject::disposing notification to all listeners, and clears the
66 You'll usually call this from within your own dispose/disposing method
68 void disposing( const ::com::sun::star::lang::EventObject
& _rEventSource
);
70 /** clears the container without calling <member scope="com::sun::star::lang">XEventListener::disposing</member>
75 /** determines whether the listener container is currently empty
78 empty() const SAL_THROW(());
80 /** determines the number of elements in the container
83 size() const SAL_THROW(());
85 /** creates an iterator for looping through all registered listeners
87 SAL_WNODEPRECATED_DECLARATIONS_PUSH
88 ::std::auto_ptr
< ::cppu::OInterfaceIteratorHelper
> createIterator()
90 ::std::auto_ptr
< ::cppu::OInterfaceIteratorHelper
> pIterator( new ::cppu::OInterfaceIteratorHelper( m_aListeners
) );
93 SAL_WNODEPRECATED_DECLARATIONS_POP
96 OListenerContainer( ::osl::Mutex
& _rMutex
);
98 virtual ~OListenerContainer();
100 void impl_addListener( const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XEventListener
>& _rxListener
);
101 void impl_removeListener( const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XEventListener
>& _rxListener
);
103 /** notifies all listeners of the given event, using THB's notification pattern
105 internally, this method will call <member>implNotify</member> for every listener
108 <TRUE/> if all listeners have been notified, <FALSE/> else. The latter can happen
109 if <member>implNotify</member> cancelles the notification loop.
113 bool impl_notify( const ::com::sun::star::lang::EventObject
& _rEvent
) SAL_THROW(( ::com::sun::star::uno::Exception
));
116 /** call a single listener
120 @throws ::com::sun::star::uno::Exception
121 if the listener throws an exception during notification. Please don't catch
122 any listener exceptions in your implementation of this method, simply let them
126 specifies the listener to call. Is guaranteed to not be <NULL/>
128 the event to broadcast. This is the same as passed to <member>notify</member>, so if
129 your base class knows the type passed into <member>notify</member>, it can safely assume
130 that <arg>_rEvent</arg> is also of this type.
133 <TRUE/> if the remaining listeners should be called, <FALSE/> if the notification
134 loop should be cancelled
138 virtual bool implNotify(
139 const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XEventListener
>& _rxListener
,
140 const ::com::sun::star::lang::EventObject
& _rEvent
141 ) SAL_THROW( ( ::com::sun::star::uno::Exception
) ) = 0;
144 //====================================================================
145 inline bool OListenerContainer::empty() const SAL_THROW(())
147 return ( m_aListeners
.getLength() == 0 );
150 inline size_t OListenerContainer::size() const SAL_THROW(())
152 return m_aListeners
.getLength();
155 //====================================================================
156 //= OSimpleListenerContainer
157 //====================================================================
158 /** helper class for simple notification of the form LISTENER::METHOD( EVENT )
160 This class is not threadsafe!
163 the listener class to call, e.g. <type scope="com::sun::star::lang">XEventListener</type>
165 the event type to notify, e.g. <type scope="com::sun::star::lang">EventObject</type>
167 template< class LISTENER
, class EVENT
>
168 class OSimpleListenerContainer
: protected OListenerContainer
171 typedef LISTENER ListenerClass
;
172 typedef EVENT EventClass
;
173 typedef void ( SAL_CALL
LISTENER::*NotificationMethod
)( const EventClass
& );
176 NotificationMethod m_pNotificationMethod
;
179 OSimpleListenerContainer( ::osl::Mutex
& _rMutex
)
180 :OListenerContainer( _rMutex
)
181 ,m_pNotificationMethod( NULL
)
185 inline void addListener( const ::com::sun::star::uno::Reference
< ListenerClass
>& _rxListener
)
187 OListenerContainer::impl_addListener( _rxListener
.get() );
190 inline void removeListener( const ::com::sun::star::uno::Reference
< ListenerClass
>& _rxListener
)
192 OListenerContainer::impl_removeListener( _rxListener
.get() );
195 // publish some otherwise hidden base functionality
196 using OListenerContainer::disposing
;
197 using OListenerContainer::clear
;
198 using OListenerContainer::empty
;
199 using OListenerContainer::size
;
200 using OListenerContainer::createIterator
;
202 /// typed notification
203 inline bool notify( const EventClass
& _rEvent
, NotificationMethod _pNotify
) SAL_THROW(( ::com::sun::star::uno::Exception
));
206 inline virtual bool implNotify(
207 const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XEventListener
>& _rxListener
,
208 const ::com::sun::star::lang::EventObject
& _rEvent
209 ) SAL_THROW( ( ::com::sun::star::uno::Exception
) );
212 //--------------------------------------------------------------------
213 template< class LISTENER
, class EVENT
>
214 inline bool OSimpleListenerContainer
< LISTENER
, EVENT
>::notify( const EventClass
& _rEvent
, NotificationMethod _pNotify
) SAL_THROW(( ::com::sun::star::uno::Exception
))
216 m_pNotificationMethod
= _pNotify
;
217 bool bRet
= OListenerContainer::impl_notify( _rEvent
);
218 m_pNotificationMethod
= NULL
;
222 //--------------------------------------------------------------------
223 template< class LISTENER
, class EVENT
>
224 inline bool OSimpleListenerContainer
< LISTENER
, EVENT
>::implNotify(
225 const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XEventListener
>& _rxListener
,
226 const ::com::sun::star::lang::EventObject
& _rEvent
) SAL_THROW( ( ::com::sun::star::uno::Exception
) )
228 const EventClass
& rTypedEvent( static_cast< const EventClass
& >( _rEvent
) );
229 ListenerClass
* pTypedListener( static_cast< ListenerClass
* >( _rxListener
.get() ) );
230 (pTypedListener
->*m_pNotificationMethod
)( rTypedEvent
);
234 //====================================================================
235 //= OListenerContainerBase
236 //====================================================================
237 /** is a specialization of OListenerContainer which saves you some additional type casts,
238 by making the required listener and event types template arguments.
240 template< class LISTENER
, class EVENT
>
241 class OListenerContainerBase
: public OListenerContainer
244 typedef LISTENER ListenerClass
;
245 typedef EVENT EventClass
;
248 inline OListenerContainerBase( ::osl::Mutex
& _rMutex
) : OListenerContainer( _rMutex
)
252 inline void addTypedListener( const ::com::sun::star::uno::Reference
< ListenerClass
>& _rxListener
)
254 OListenerContainer::impl_addListener( _rxListener
.get() );
257 inline void removeTypedListener( const ::com::sun::star::uno::Reference
< ListenerClass
>& _rxListener
)
259 OListenerContainer::impl_removeListener( _rxListener
.get() );
262 inline bool notify( const EventClass
& _rEvent
)
264 return OListenerContainer::impl_notify( _rEvent
);
267 using OListenerContainer::impl_notify
;
270 inline virtual bool implNotify(
271 const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XEventListener
>& _rxListener
,
272 const ::com::sun::star::lang::EventObject
& _rEvent
273 ) SAL_THROW( ( ::com::sun::star::uno::Exception
) );
275 virtual bool implTypedNotify(
276 const ::com::sun::star::uno::Reference
< ListenerClass
>& _rxListener
,
277 const EventClass
& _rEvent
278 ) SAL_THROW( ( ::com::sun::star::uno::Exception
) ) = 0;
281 template< class LISTENER
, class EVENT
>
282 inline bool OListenerContainerBase
< LISTENER
, EVENT
>::implNotify(
283 const ::com::sun::star::uno::Reference
< ::com::sun::star::lang::XEventListener
>& _rxListener
,
284 const ::com::sun::star::lang::EventObject
& _rEvent
) SAL_THROW( ( ::com::sun::star::uno::Exception
) )
286 return implTypedNotify(
287 ::com::sun::star::uno::Reference
< ListenerClass
>( static_cast< ListenerClass
* >( _rxListener
.get() ) ),
288 static_cast< const EventClass
& >( _rEvent
)
292 //........................................................................
293 } // namespace comphelper
294 //........................................................................
296 #endif // COMPHELPER_INC_COMPHELPER_LISTENERNOTIFICATION_HXX
298 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */