Branch data 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 : : #ifndef COMPHELPER_INC_COMPHELPER_LISTENERNOTIFICATION_HXX
21 : : #define COMPHELPER_INC_COMPHELPER_LISTENERNOTIFICATION_HXX
22 : :
23 : : #include <cppuhelper/interfacecontainer.hxx>
24 : :
25 : : #include <com/sun/star/lang/XEventListener.hpp>
26 : : #include "comphelper/comphelperdllapi.h"
27 : :
28 : : #include <memory>
29 : :
30 : : //........................................................................
31 : : namespace comphelper
32 : : {
33 : : //........................................................................
34 : :
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
41 : :
42 : : Using this class is pretty easy:
43 : : <ul>
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>
49 : : </ul>
50 : :
51 : : See <type>OListenerContainerBase</type> for an implementation which even saves
52 : : you some more work, by doing the casts for you.
53 : :
54 : : @see http://www.openoffice.org/servlets/ReadMsg?list=interface-announce&msgId=494345
55 : : @see OListenerContainerBase
56 : : */
57 : : class COMPHELPER_DLLPUBLIC OListenerContainer
58 : : {
59 : : private:
60 : : ::cppu::OInterfaceContainerHelper m_aListeners;
61 : :
62 : : public:
63 : : /** sends a XEventObject::disposing notification to all listeners, and clears the
64 : : listener container
65 : :
66 : : You'll usually call this from within your own dispose/disposing method
67 : : */
68 : : void disposing( const ::com::sun::star::lang::EventObject& _rEventSource );
69 : :
70 : : /** clears the container without calling <member scope="com::sun::star::lang">XEventListener::disposing</member>
71 : : at the listeners
72 : : */
73 : : void clear();
74 : :
75 : : /** determines whether the listener container is currently empty
76 : : */
77 : : inline bool
78 : : empty() const SAL_THROW(());
79 : :
80 : : /** determines the number of elements in the container
81 : : */
82 : : inline size_t
83 : : size() const SAL_THROW(());
84 : :
85 : : /** creates an iterator for looping through all registered listeners
86 : : */
87 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
88 : 0 : ::std::auto_ptr< ::cppu::OInterfaceIteratorHelper > createIterator()
89 : : {
90 : 0 : ::std::auto_ptr< ::cppu::OInterfaceIteratorHelper > pIterator( new ::cppu::OInterfaceIteratorHelper( m_aListeners ) );
91 : 0 : return pIterator;
92 : : }
93 : : SAL_WNODEPRECATED_DECLARATIONS_POP
94 : :
95 : : protected:
96 : : OListenerContainer( ::osl::Mutex& _rMutex );
97 : :
98 : : virtual ~OListenerContainer();
99 : :
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 );
102 : :
103 : : /** notifies all listeners of the given event, using THB's notification pattern
104 : :
105 : : internally, this method will call <member>implNotify</member> for every listener
106 : :
107 : : @return
108 : : <TRUE/> if all listeners have been notified, <FALSE/> else. The latter can happen
109 : : if <member>implNotify</member> cancelles the notification loop.
110 : :
111 : : @see implNotify
112 : : */
113 : : bool impl_notify( const ::com::sun::star::lang::EventObject& _rEvent ) SAL_THROW(( ::com::sun::star::uno::Exception ));
114 : :
115 : : protected:
116 : : /** call a single listener
117 : :
118 : : @pure
119 : :
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
123 : : pass to the caller.
124 : :
125 : : @param _rxListener
126 : : specifies the listener to call. Is guaranteed to not be <NULL/>
127 : : @param _rEvent
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.
131 : :
132 : : @return
133 : : <TRUE/> if the remaining listeners should be called, <FALSE/> if the notification
134 : : loop should be cancelled
135 : :
136 : : @see notify
137 : : */
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;
142 : : };
143 : :
144 : : //====================================================================
145 : 0 : inline bool OListenerContainer::empty() const SAL_THROW(())
146 : : {
147 : 0 : return ( m_aListeners.getLength() == 0 );
148 : : }
149 : :
150 : : inline size_t OListenerContainer::size() const SAL_THROW(())
151 : : {
152 : : return m_aListeners.getLength();
153 : : }
154 : :
155 : : //====================================================================
156 : : //= OSimpleListenerContainer
157 : : //====================================================================
158 : : /** helper class for simple notification of the form LISTENER::METHOD( EVENT )
159 : :
160 : : This class is not threadsafe!
161 : :
162 : : @param LISTENER
163 : : the listener class to call, e.g. <type scope="com::sun::star::lang">XEventListener</type>
164 : : @param EVENT
165 : : the event type to notify, e.g. <type scope="com::sun::star::lang">EventObject</type>
166 : : */
167 : : template< class LISTENER, class EVENT >
168 : 0 : class OSimpleListenerContainer : protected OListenerContainer
169 : : {
170 : : public:
171 : : typedef LISTENER ListenerClass;
172 : : typedef EVENT EventClass;
173 : : typedef void ( SAL_CALL LISTENER::*NotificationMethod )( const EventClass& );
174 : :
175 : : private:
176 : : NotificationMethod m_pNotificationMethod;
177 : :
178 : : public:
179 : 0 : OSimpleListenerContainer( ::osl::Mutex& _rMutex )
180 : : :OListenerContainer( _rMutex )
181 : 0 : ,m_pNotificationMethod( NULL )
182 : : {
183 : 0 : }
184 : :
185 : 0 : inline void addListener( const ::com::sun::star::uno::Reference< ListenerClass >& _rxListener )
186 : : {
187 : 0 : OListenerContainer::impl_addListener( _rxListener.get() );
188 : 0 : }
189 : :
190 : 0 : inline void removeListener( const ::com::sun::star::uno::Reference< ListenerClass >& _rxListener )
191 : : {
192 : 0 : OListenerContainer::impl_removeListener( _rxListener.get() );
193 : 0 : }
194 : :
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;
201 : :
202 : : /// typed notification
203 : : inline bool notify( const EventClass& _rEvent, NotificationMethod _pNotify ) SAL_THROW(( ::com::sun::star::uno::Exception ));
204 : :
205 : : protected:
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 ) );
210 : : };
211 : :
212 : : //--------------------------------------------------------------------
213 : : template< class LISTENER, class EVENT >
214 : 0 : inline bool OSimpleListenerContainer< LISTENER, EVENT >::notify( const EventClass& _rEvent, NotificationMethod _pNotify ) SAL_THROW(( ::com::sun::star::uno::Exception ))
215 : : {
216 : 0 : m_pNotificationMethod = _pNotify;
217 : 0 : bool bRet = OListenerContainer::impl_notify( _rEvent );
218 : 0 : m_pNotificationMethod = NULL;
219 : 0 : return bRet;
220 : : }
221 : :
222 : : //--------------------------------------------------------------------
223 : : template< class LISTENER, class EVENT >
224 : 0 : 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 ) )
227 : : {
228 : 0 : const EventClass& rTypedEvent( static_cast< const EventClass& >( _rEvent ) );
229 : 0 : ListenerClass* pTypedListener( static_cast< ListenerClass* >( _rxListener.get() ) );
230 : 0 : (pTypedListener->*m_pNotificationMethod)( rTypedEvent );
231 : 0 : return true;
232 : : }
233 : :
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.
239 : : */
240 : : template< class LISTENER, class EVENT >
241 [ - + ][ # # ]: 1729 : class OListenerContainerBase : public OListenerContainer
[ # # ]
242 : : {
243 : : public:
244 : : typedef LISTENER ListenerClass;
245 : : typedef EVENT EventClass;
246 : :
247 : : public:
248 : 1877 : inline OListenerContainerBase( ::osl::Mutex& _rMutex ) : OListenerContainer( _rMutex )
249 : : {
250 : 1877 : }
251 : :
252 : 2 : inline void addTypedListener( const ::com::sun::star::uno::Reference< ListenerClass >& _rxListener )
253 : : {
254 [ + - ][ # # ]: 2 : OListenerContainer::impl_addListener( _rxListener.get() );
[ # # ]
255 : 2 : }
256 : :
257 : 0 : inline void removeTypedListener( const ::com::sun::star::uno::Reference< ListenerClass >& _rxListener )
258 : : {
259 [ # # ][ # # ]: 0 : OListenerContainer::impl_removeListener( _rxListener.get() );
[ # # ]
260 : 0 : }
261 : :
262 : 8 : inline bool notify( const EventClass& _rEvent )
263 : : {
264 : 8 : return OListenerContainer::impl_notify( _rEvent );
265 : : }
266 : :
267 : : using OListenerContainer::impl_notify;
268 : :
269 : : protected:
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 ) );
274 : :
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;
279 : : };
280 : :
281 : : template< class LISTENER, class EVENT >
282 : 0 : 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 ) )
285 : : {
286 : : return implTypedNotify(
287 : : ::com::sun::star::uno::Reference< ListenerClass >( static_cast< ListenerClass* >( _rxListener.get() ) ),
288 : : static_cast< const EventClass& >( _rEvent )
289 [ # # ][ # # ]: 0 : );
[ # # ]
290 : : }
291 : :
292 : : //........................................................................
293 : : } // namespace comphelper
294 : : //........................................................................
295 : :
296 : : #endif // COMPHELPER_INC_COMPHELPER_LISTENERNOTIFICATION_HXX
297 : :
298 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|