CWS-TOOLING: integrate CWS os146
[LibreOffice.git] / comphelper / source / misc / accessibleeventnotifier.cxx
blob421fb9868d73375ff0d819e39e9611b1353d87f5
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
30 #include <comphelper/accessibleeventnotifier.hxx>
31 #include <osl/diagnose.h>
32 #include <rtl/instance.hxx>
33 #include <comphelper/guarding.hxx>
35 using namespace ::com::sun::star::uno;
36 using namespace ::com::sun::star::lang;
37 using namespace ::com::sun::star::accessibility;
38 using namespace ::comphelper;
40 //=====================================================================
41 //= AccessibleEventNotifier
42 //=====================================================================
43 //---------------------------------------------------------------------
44 namespace
46 struct lclMutex
47 : public rtl::Static< ::osl::Mutex, lclMutex > {};
48 struct Clients
49 : public rtl::Static< AccessibleEventNotifier::ClientMap, Clients > {};
52 //.........................................................................
53 namespace comphelper
55 //.........................................................................
57 //---------------------------------------------------------------------
58 AccessibleEventNotifier::TClientId AccessibleEventNotifier::generateId()
60 TClientId nBiggestUsedId = 0;
61 TClientId nFreeId = 0;
63 // look through all registered clients until we find a "gap" in the ids
65 // Note that the following relies on the fact the elements in the map are traveled with
66 // ascending keys (aka client ids)
67 AccessibleEventNotifier::ClientMap &rClients = Clients::get();
68 for ( ClientMap::const_iterator aLookup = rClients.begin();
69 aLookup != rClients.end();
70 ++aLookup
73 TClientId nCurrent = aLookup->first;
74 OSL_ENSURE( nCurrent > nBiggestUsedId, "AccessibleEventNotifier::generateId: map is expected to be sorted ascending!" );
76 if ( nCurrent - nBiggestUsedId > 1 )
77 { // found a "gap"
78 nFreeId = nBiggestUsedId + 1;
79 break;
82 nBiggestUsedId = nCurrent;
85 if ( !nFreeId )
86 nFreeId = nBiggestUsedId + 1;
88 OSL_ENSURE( rClients.end() == rClients.find( nFreeId ),
89 "AccessibleEventNotifier::generateId: algorithm broken!" );
91 return nFreeId;
94 //---------------------------------------------------------------------
95 AccessibleEventNotifier::TClientId AccessibleEventNotifier::registerClient( )
97 ::osl::MutexGuard aGuard( lclMutex::get() );
99 // generate a new client id
100 TClientId nNewClientId = generateId( );
102 // the event listeners for the new client
103 EventListeners* pNewListeners = new EventListeners( lclMutex::get() );
104 // note that we're using our own mutex here, so the listener containers for all
105 // our clients share this same mutex.
106 // this is a reminiscense to the days where the notifier was asynchronous. Today this is
107 // completely nonsense, and potentially slowing down the Office me thinks ...
109 // add the client
110 Clients::get().insert( ClientMap::value_type( nNewClientId, pNewListeners ) );
112 // outta here
113 return nNewClientId;
116 //---------------------------------------------------------------------
117 sal_Bool AccessibleEventNotifier::implLookupClient( const TClientId _nClient, ClientMap::iterator& _rPos )
119 // look up this client
120 AccessibleEventNotifier::ClientMap &rClients = Clients::get();
121 _rPos = rClients.find( _nClient );
122 OSL_ENSURE( rClients.end() != _rPos, "AccessibleEventNotifier::implLookupClient: invalid client id (did you register your client?)!" );
124 return ( rClients.end() != _rPos );
127 //---------------------------------------------------------------------
128 void AccessibleEventNotifier::revokeClient( const TClientId _nClient )
130 ::osl::MutexGuard aGuard( lclMutex::get() );
132 ClientMap::iterator aClientPos;
133 if ( !implLookupClient( _nClient, aClientPos ) )
134 // already asserted in implLookupClient
135 return;
137 // remove it from the clients map
138 delete aClientPos->second;
139 Clients::get().erase( aClientPos );
142 //---------------------------------------------------------------------
143 void AccessibleEventNotifier::revokeClientNotifyDisposing( const TClientId _nClient,
144 const Reference< XInterface >& _rxEventSource ) SAL_THROW( ( ) )
146 ::osl::MutexGuard aGuard( lclMutex::get() );
148 ClientMap::iterator aClientPos;
149 if ( !implLookupClient( _nClient, aClientPos ) )
150 // already asserted in implLookupClient
151 return;
153 // notify the "disposing" event for this client
154 EventObject aDisposalEvent;
155 aDisposalEvent.Source = _rxEventSource;
157 // notify the listeners
158 EventListeners* pListeners = aClientPos->second;
160 // we do not need the entry in the clients map anymore
161 // (do this before actually notifying, because some client implementations have re-entrance
162 // problems and call into revokeClient while we are notifying from hereing)
163 Clients::get().erase( aClientPos );
165 // now really do the notification
166 pListeners->disposeAndClear( aDisposalEvent );
167 delete pListeners;
171 //---------------------------------------------------------------------
172 sal_Int32 AccessibleEventNotifier::addEventListener(
173 const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) SAL_THROW( ( ) )
175 ::osl::MutexGuard aGuard( lclMutex::get() );
177 ClientMap::iterator aClientPos;
178 if ( !implLookupClient( _nClient, aClientPos ) )
179 // already asserted in implLookupClient
180 return 0;
182 if ( _rxListener.is() )
183 aClientPos->second->addInterface( _rxListener );
185 return aClientPos->second->getLength();
188 //---------------------------------------------------------------------
189 sal_Int32 AccessibleEventNotifier::removeEventListener(
190 const TClientId _nClient, const Reference< XAccessibleEventListener >& _rxListener ) SAL_THROW( ( ) )
192 ::osl::MutexGuard aGuard( lclMutex::get() );
194 ClientMap::iterator aClientPos;
195 if ( !implLookupClient( _nClient, aClientPos ) )
196 // already asserted in implLookupClient
197 return 0;
199 if ( _rxListener.is() )
200 aClientPos->second->removeInterface( _rxListener );
202 return aClientPos->second->getLength();
205 //---------------------------------------------------------------------
206 Sequence< Reference< XInterface > > AccessibleEventNotifier::getEventListeners( const TClientId _nClient ) SAL_THROW( ( ) )
208 Sequence< Reference< XInterface > > aListeners;
210 ::osl::MutexGuard aGuard( lclMutex::get() );
212 ClientMap::iterator aClientPos;
213 if ( implLookupClient( _nClient, aClientPos ) )
214 aListeners = aClientPos->second->getElements();
216 return aListeners;
219 //---------------------------------------------------------------------
220 void AccessibleEventNotifier::addEvent( const TClientId _nClient, const AccessibleEventObject& _rEvent ) SAL_THROW( ( ) )
222 Sequence< Reference< XInterface > > aListeners;
224 // --- <mutex lock> -------------------------------
226 ::osl::MutexGuard aGuard( lclMutex::get() );
228 ClientMap::iterator aClientPos;
229 if ( !implLookupClient( _nClient, aClientPos ) )
230 // already asserted in implLookupClient
231 return;
233 // since we're synchronous, again, we want to notify immediately
234 aListeners = aClientPos->second->getElements();
236 // --- </mutex lock> ------------------------------
238 // default handling: loop through all listeners, and notify them
239 const Reference< XInterface >* pListeners = aListeners.getConstArray();
240 const Reference< XInterface >* pListenersEnd = pListeners + aListeners.getLength();
241 while ( pListeners != pListenersEnd )
245 static_cast< XAccessibleEventListener* >( pListeners->get() )->notifyEvent( _rEvent );
247 catch( const Exception& )
249 // no assertion, because a broken access remote bridge or something like this
250 // can cause this exception
252 ++pListeners;
256 //.........................................................................
257 } // namespace comphelper
258 //.........................................................................