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_DBACCESS_SOURCE_UI_INC_SBAMULTIPLEX_HXX
21 #define INCLUDED_DBACCESS_SOURCE_UI_INC_SBAMULTIPLEX_HXX
23 #include <com/sun/star/beans/XVetoableChangeListener.hpp>
24 #include <com/sun/star/form/XUpdateListener.hpp>
25 #include <com/sun/star/form/XErrorListener.hpp>
26 #include <com/sun/star/form/XRestoreListener.hpp>
27 #include <com/sun/star/form/XInsertListener.hpp>
28 #include <com/sun/star/form/XDeleteListener.hpp>
29 #include <com/sun/star/form/XPositioningListener.hpp>
30 #include <com/sun/star/form/XDatabaseParameterListener.hpp>
31 #include <com/sun/star/form/XLoadListener.hpp>
32 #include <com/sun/star/beans/XPropertyStateChangeListener.hpp>
33 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
34 #include <com/sun/star/beans/XPropertyChangeListener.hpp>
35 #include <com/sun/star/form/XSubmitListener.hpp>
36 #include <com/sun/star/form/XResetListener.hpp>
37 #include <com/sun/star/util/XRefreshListener.hpp>
38 #include <com/sun/star/sdb/XSQLErrorListener.hpp>
39 #include <com/sun/star/sdb/XRowSetApproveListener.hpp>
40 #include <com/sun/star/sdbc/XRowSetListener.hpp>
41 #include <com/sun/star/frame/XStatusListener.hpp>
42 #include <comphelper/uno3.hxx>
43 #include <cppuhelper/interfacecontainer.hxx>
44 #include <comphelper/interfacecontainer2.hxx>
45 #include <cppuhelper/queryinterface.hxx>
46 #include <cppuhelper/weak.hxx>
50 // TODO : replace this class if MM provides an WeakSubObject in cppu
51 class OSbaWeakSubObject
: public ::cppu::OWeakObject
54 ::cppu::OWeakObject
& m_rParent
;
57 OSbaWeakSubObject(::cppu::OWeakObject
& rParent
) : m_rParent(rParent
) { }
59 virtual void SAL_CALL
acquire() throw() override
{ m_rParent
.acquire(); }
60 virtual void SAL_CALL
release() throw() override
{ m_rParent
.release(); }
63 // declaration of a listener multiplexer class
64 #define BEGIN_DECLARE_LISTENER_MULTIPLEXER(classname, listenerclass) \
66 :public OSbaWeakSubObject \
67 ,public listenerclass \
68 ,public ::comphelper::OInterfaceContainerHelper2 \
71 classname( ::cppu::OWeakObject& rSource, \
72 ::osl::Mutex& rMutex); \
73 DECLARE_UNO3_DEFAULTS(classname, OSbaWeakSubObject) \
74 virtual css::uno::Any SAL_CALL queryInterface( \
75 const css::uno::Type& _rType) throw (css::uno::RuntimeException, std::exception) override; \
77 /* css::lang::XEventListener */ \
78 virtual void SAL_CALL disposing(const css::lang::EventObject& Source) throw(css::uno::RuntimeException, std::exception) override; \
80 #define DECLARE_MULTIPLEXER_VOID_METHOD(methodname, eventtype) \
81 virtual void SAL_CALL methodname(const eventtype& e) throw (css::uno::RuntimeException, std::exception) override; \
83 #define DECLARE_MULTIPLEXER_BOOL_METHOD(methodname, eventtype) \
84 virtual sal_Bool SAL_CALL methodname(const eventtype& e) throw (css::uno::RuntimeException, std::exception) override; \
86 #define END_DECLARE_LISTENER_MULTIPLEXER() \
87 /* resolve ambiguity : both OWeakObject and OInterfaceContainerHelper2 have these memory operators */ \
88 void * SAL_CALL operator new( size_t size ) throw() { return OSbaWeakSubObject::operator new(size); } \
89 void SAL_CALL operator delete( void * p ) throw() { OSbaWeakSubObject::operator delete(p); } \
92 // implementation of a listener multiplexer class
94 #define IMPLEMENT_LISTENER_MULTIPLEXER_CORE(classname, listenerclass) \
96 classname::classname(::cppu::OWeakObject& rSource, ::osl::Mutex& _rMutex) \
97 :OSbaWeakSubObject(rSource) \
98 ,OInterfaceContainerHelper2(_rMutex) \
102 css::uno::Any SAL_CALL classname::queryInterface( \
103 const css::uno::Type& _rType) throw (css::uno::RuntimeException, std::exception) \
105 css::uno::Any aReturn = \
106 OSbaWeakSubObject::queryInterface(_rType); \
107 if (!aReturn.hasValue()) \
108 aReturn = ::cppu::queryInterface(_rType, \
109 static_cast< listenerclass* >(this), \
110 static_cast< css::lang::XEventListener* >(static_cast< listenerclass* >(this)) \
115 void SAL_CALL classname::disposing(const css::lang::EventObject& ) throw(css::uno::RuntimeException, std::exception)\
119 #define IMPLEMENT_LISTENER_MULTIPLEXER_VOID_METHOD(classname, listenerclass, methodname, eventtype) \
120 void SAL_CALL classname::methodname(const eventtype& e) throw (css::uno::RuntimeException, std::exception) \
122 eventtype aMulti(e); \
123 aMulti.Source = &m_rParent; \
124 ::comphelper::OInterfaceIteratorHelper2 aIt(*this); \
125 while (aIt.hasMoreElements()) \
126 static_cast< listenerclass*>(aIt.next())->methodname(aMulti); \
129 #define IMPLEMENT_LISTENER_MULTIPLEXER_BOOL_METHOD(classname, listenerclass, methodname, eventtype) \
130 sal_Bool SAL_CALL classname::methodname(const eventtype& e) throw (css::uno::RuntimeException, std::exception) \
132 eventtype aMulti(e); \
133 aMulti.Source = &m_rParent; \
134 ::comphelper::OInterfaceIteratorHelper2 aIt(*this); \
135 bool bResult = true; \
136 while (bResult && aIt.hasMoreElements()) \
137 bResult = static_cast< listenerclass*>(aIt.next())->methodname(aMulti); \
141 // helper for classes which do event multiplexing
142 #define IMPLEMENT_LISTENER_ADMINISTRATION(classname, listenernamespace, listenerdesc, multiplexer, braodcasterclass, broadcaster) \
143 void SAL_CALL classname::add##listenerdesc(const css::uno::Reference< css::listenernamespace::X##listenerdesc >& l) throw(css::uno::RuntimeException, std::exception)\
145 multiplexer.addInterface(l); \
146 if (multiplexer.getLength() == 1) \
148 css::uno::Reference< braodcasterclass > xBroadcaster(broadcaster, css::uno::UNO_QUERY); \
149 if (xBroadcaster.is()) \
150 xBroadcaster->add##listenerdesc(&multiplexer); \
153 void SAL_CALL classname::remove##listenerdesc(const css::uno::Reference< css::listenernamespace::X##listenerdesc >& l) throw(css::uno::RuntimeException, std::exception)\
155 if (multiplexer.getLength() == 1) \
157 css::uno::Reference< braodcasterclass > xBroadcaster(broadcaster, css::uno::UNO_QUERY); \
158 if (xBroadcaster.is()) \
159 xBroadcaster->remove##listenerdesc(&multiplexer); \
161 multiplexer.removeInterface(l); \
164 #define STOP_MULTIPLEXER_LISTENING(listenerdesc, multiplexer, braodcasterclass, broadcaster) \
165 if (multiplexer.getLength()) \
167 css::uno::Reference< braodcasterclass > xBroadcaster(broadcaster, css::uno::UNO_QUERY); \
168 if (xBroadcaster.is()) \
169 xBroadcaster->remove##listenerdesc(&multiplexer); \
172 #define START_MULTIPLEXER_LISTENING(listenerdesc, multiplexer, braodcasterclass, broadcaster) \
173 if (multiplexer.getLength()) \
175 css::uno::Reference< braodcasterclass > xBroadcaster(broadcaster, css::uno::UNO_QUERY); \
176 if (xBroadcaster.is()) \
177 xBroadcaster->add##listenerdesc(&multiplexer); \
180 // declaration of property listener multiplexers
181 // (with support for specialized and unspecialized property listeners)
183 #define DECLARE_PROPERTY_MULTIPLEXER(classname, listenerclass, methodname, eventtype, exceptions) \
185 :public OSbaWeakSubObject \
186 ,public listenerclass \
188 typedef ::cppu::OMultiTypeInterfaceContainerHelperVar< \
189 OUString > ListenerContainerMap; \
190 ListenerContainerMap m_aListeners; \
193 classname( ::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex ); \
194 DECLARE_UNO3_DEFAULTS(classname, OSbaWeakSubObject) \
195 virtual css::uno::Any SAL_CALL queryInterface( \
196 const css::uno::Type& _rType) throw (css::uno::RuntimeException, std::exception) override; \
198 /* css::lang::XEventListener */ \
199 virtual void SAL_CALL disposing(const css::lang::EventObject& Source) throw(css::uno::RuntimeException, std::exception) override; \
201 virtual void SAL_CALL methodname(const eventtype& e) throw exceptions override; \
204 void addInterface(const OUString& rName, const css::uno::Reference< css::uno::XInterface >& rListener); \
205 void removeInterface(const OUString& rName, const css::uno::Reference< css::uno::XInterface >& rListener); \
207 void disposeAndClear(); \
209 sal_Int32 getOverallLen() const; \
211 ::cppu::OInterfaceContainerHelper* getContainer(const OUString& rName) \
212 { return m_aListeners.getContainer(rName); } \
215 void Notify(::cppu::OInterfaceContainerHelper& rListeners, const eventtype& e); \
218 // implementation of property listener multiplexers
219 #define IMPLEMENT_PROPERTY_MULTIPLEXER(classname, listenerclass, methodname, eventtype, exceptions) \
220 classname::classname(::cppu::OWeakObject& rSource, ::osl::Mutex& rMutex) \
221 :OSbaWeakSubObject(rSource) \
222 ,m_aListeners(rMutex) \
226 css::uno::Any SAL_CALL classname::queryInterface( \
227 const css::uno::Type& _rType) throw (css::uno::RuntimeException, std::exception) \
229 css::uno::Any aReturn = \
230 OSbaWeakSubObject::queryInterface(_rType); \
231 if (!aReturn.hasValue()) \
232 aReturn = ::cppu::queryInterface(_rType, \
233 static_cast< listenerclass* >(this), \
234 static_cast< css::lang::XEventListener* >(static_cast< listenerclass* >(this)) \
239 void SAL_CALL classname::disposing(const css::lang::EventObject& ) throw(css::uno::RuntimeException, std::exception)\
243 void SAL_CALL classname::methodname(const eventtype& e) throw exceptions \
245 ::cppu::OInterfaceContainerHelper* pListeners = m_aListeners.getContainer(e.PropertyName); \
247 Notify(*pListeners, e); \
249 /* do the notification for the unspecialized listeners, too */ \
250 pListeners = m_aListeners.getContainer(OUString()); \
252 Notify(*pListeners, e); \
255 void classname::addInterface(const OUString& rName, \
256 const css::uno::Reference< css::uno::XInterface > & rListener) \
258 m_aListeners.addInterface(rName, rListener); \
261 void classname::removeInterface(const OUString& rName, \
262 const css::uno::Reference< css::uno::XInterface > & rListener) \
264 m_aListeners.removeInterface(rName, rListener); \
267 void classname::disposeAndClear() \
269 css::lang::EventObject aEvt(m_rParent); \
270 m_aListeners.disposeAndClear(aEvt); \
273 sal_Int32 classname::getOverallLen() const \
275 sal_Int32 nLen = 0; \
276 css::uno::Sequence< OUString > aContained = m_aListeners.getContainedTypes(); \
277 const OUString* pContained = aContained.getConstArray(); \
278 for ( sal_Int32 i=0; i<aContained.getLength(); ++i, ++pContained) \
280 ::cppu::OInterfaceContainerHelper* pListeners = m_aListeners.getContainer(*pContained); \
283 nLen += pListeners->getLength(); \
288 void classname::Notify(::cppu::OInterfaceContainerHelper& rListeners, const eventtype& e) \
290 eventtype aMulti(e); \
291 aMulti.Source = &m_rParent; \
292 ::cppu::OInterfaceIteratorHelper aIt(rListeners); \
293 while (aIt.hasMoreElements()) \
294 static_cast< listenerclass*>(aIt.next())->methodname(aMulti); \
297 // helper for classes which do property event multiplexing
298 #define IMPLEMENT_PROPERTY_LISTENER_ADMINISTRATION(classname, listenerdesc, multiplexer, braodcasterclass, broadcaster) \
299 void SAL_CALL classname::add##listenerdesc(const OUString& rName, const css::uno::Reference< css::beans::X##listenerdesc >& l ) throw(css::beans::UnknownPropertyException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception)\
301 multiplexer.addInterface(rName, l); \
302 if (multiplexer.getOverallLen() == 1) \
304 css::uno::Reference< braodcasterclass > xBroadcaster(broadcaster, css::uno::UNO_QUERY); \
305 if (xBroadcaster.is()) \
306 xBroadcaster->add##listenerdesc(OUString(), &multiplexer); \
309 void SAL_CALL classname::remove##listenerdesc(const OUString& rName, const css::uno::Reference< css::beans::X##listenerdesc >& l ) throw(css::beans::UnknownPropertyException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception)\
311 if (multiplexer.getOverallLen() == 1) \
313 css::uno::Reference< braodcasterclass > xBroadcaster(broadcaster, css::uno::UNO_QUERY); \
314 if (xBroadcaster.is()) \
315 xBroadcaster->remove##listenerdesc(OUString(), &multiplexer); \
317 multiplexer.removeInterface(rName, l); \
320 #define STOP_PROPERTY_MULTIPLEXER_LISTENING(listenerdesc, multiplexer, braodcasterclass, broadcaster) \
321 if (multiplexer.getOverallLen()) \
323 css::uno::Reference< braodcasterclass > xBroadcaster(broadcaster, css::uno::UNO_QUERY); \
324 if (xBroadcaster.is()) \
325 xBroadcaster->remove##listenerdesc(OUString(), &multiplexer); \
328 #define START_PROPERTY_MULTIPLEXER_LISTENING(listenerdesc, multiplexer, braodcasterclass, broadcaster) \
329 if (multiplexer.getOverallLen()) \
331 css::uno::Reference< braodcasterclass > xBroadcaster(broadcaster, css::uno::UNO_QUERY); \
332 if (xBroadcaster.is()) \
333 xBroadcaster->add##listenerdesc(OUString(), &multiplexer); \
336 // some listener multiplexers
337 // css::frame::XStatusListener
338 BEGIN_DECLARE_LISTENER_MULTIPLEXER(SbaXStatusMultiplexer
, css::frame::XStatusListener
)
339 DECLARE_MULTIPLEXER_VOID_METHOD(statusChanged
, css::frame::FeatureStateEvent
)
342 css::frame::FeatureStateEvent m_aLastKnownStatus
;
344 const css::frame::FeatureStateEvent
& getLastEvent( ) const { return m_aLastKnownStatus
; }
345 END_DECLARE_LISTENER_MULTIPLEXER()
347 // css::form::XLoadListener
348 BEGIN_DECLARE_LISTENER_MULTIPLEXER(SbaXLoadMultiplexer
, css::form::XLoadListener
)
349 DECLARE_MULTIPLEXER_VOID_METHOD(loaded
, css::lang::EventObject
)
350 DECLARE_MULTIPLEXER_VOID_METHOD(unloaded
, css::lang::EventObject
)
351 DECLARE_MULTIPLEXER_VOID_METHOD(unloading
, css::lang::EventObject
)
352 DECLARE_MULTIPLEXER_VOID_METHOD(reloading
, css::lang::EventObject
)
353 DECLARE_MULTIPLEXER_VOID_METHOD(reloaded
, css::lang::EventObject
)
354 END_DECLARE_LISTENER_MULTIPLEXER()
356 // css::form::XDatabaseParameterListener
357 BEGIN_DECLARE_LISTENER_MULTIPLEXER(SbaXParameterMultiplexer
, css::form::XDatabaseParameterListener
)
358 DECLARE_MULTIPLEXER_BOOL_METHOD(approveParameter
, css::form::DatabaseParameterEvent
)
359 END_DECLARE_LISTENER_MULTIPLEXER()
361 // css::form::XSubmitListener
362 BEGIN_DECLARE_LISTENER_MULTIPLEXER(SbaXSubmitMultiplexer
, css::form::XSubmitListener
)
363 DECLARE_MULTIPLEXER_BOOL_METHOD(approveSubmit
, css::lang::EventObject
)
364 END_DECLARE_LISTENER_MULTIPLEXER()
366 // css::form::XResetListener
367 BEGIN_DECLARE_LISTENER_MULTIPLEXER(SbaXResetMultiplexer
, css::form::XResetListener
)
368 DECLARE_MULTIPLEXER_BOOL_METHOD(approveReset
, css::lang::EventObject
)
369 DECLARE_MULTIPLEXER_VOID_METHOD(resetted
, css::lang::EventObject
)
370 END_DECLARE_LISTENER_MULTIPLEXER()
372 // css::sdbc::XRowSetListener
373 BEGIN_DECLARE_LISTENER_MULTIPLEXER(SbaXRowSetMultiplexer
, css::sdbc::XRowSetListener
)
374 DECLARE_MULTIPLEXER_VOID_METHOD(cursorMoved
, css::lang::EventObject
)
375 DECLARE_MULTIPLEXER_VOID_METHOD(rowChanged
, css::lang::EventObject
)
376 DECLARE_MULTIPLEXER_VOID_METHOD(rowSetChanged
, css::lang::EventObject
)
377 END_DECLARE_LISTENER_MULTIPLEXER()
379 // css::sdb::XRowSetApproveListener
380 BEGIN_DECLARE_LISTENER_MULTIPLEXER(SbaXRowSetApproveMultiplexer
, css::sdb::XRowSetApproveListener
)
381 DECLARE_MULTIPLEXER_BOOL_METHOD(approveCursorMove
, css::lang::EventObject
)
382 DECLARE_MULTIPLEXER_BOOL_METHOD(approveRowChange
, css::sdb::RowChangeEvent
)
383 DECLARE_MULTIPLEXER_BOOL_METHOD(approveRowSetChange
, css::lang::EventObject
)
384 END_DECLARE_LISTENER_MULTIPLEXER()
386 // css::sdb::XSQLErrorListener
387 BEGIN_DECLARE_LISTENER_MULTIPLEXER(SbaXSQLErrorMultiplexer
, css::sdb::XSQLErrorListener
)
388 DECLARE_MULTIPLEXER_VOID_METHOD(errorOccured
, css::sdb::SQLErrorEvent
)
389 END_DECLARE_LISTENER_MULTIPLEXER()
391 // css::beans::XPropertyChangeListener
392 DECLARE_PROPERTY_MULTIPLEXER(SbaXPropertyChangeMultiplexer
, css::beans::XPropertyChangeListener
, propertyChange
, css::beans::PropertyChangeEvent
, (css::uno::RuntimeException
, std::exception
))
394 // css::beans::XVetoableChangeListener
395 DECLARE_PROPERTY_MULTIPLEXER(SbaXVetoableChangeMultiplexer
, css::beans::XVetoableChangeListener
, vetoableChange
, css::beans::PropertyChangeEvent
, (css::beans::PropertyVetoException
, css::uno::RuntimeException
, std::exception
))
397 // css::beans::XPropertiesChangeListener
398 BEGIN_DECLARE_LISTENER_MULTIPLEXER(SbaXPropertiesChangeMultiplexer
, css::beans::XPropertiesChangeListener
)
399 DECLARE_MULTIPLEXER_VOID_METHOD(propertiesChange
, css::uno::Sequence
< css::beans::PropertyChangeEvent
>)
400 END_DECLARE_LISTENER_MULTIPLEXER()
401 // the SbaXPropertiesChangeMultiplexer doesn't care about the property names a listener logs on for, it simply
402 // forwards _all_ changes to _all_ listeners
405 #endif // _SBA_MULTIPLEXER_HXX
407 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */