xref: /trunk/main/comphelper/source/misc/accessiblewrapper.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
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.
14  *
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).
20  *
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.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
30 #include "comphelper/accessiblewrapper.hxx"
31 #include <com/sun/star/reflection/XProxyFactory.hpp>
32 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
33 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
34 
35 #include <algorithm>
36 
37 using namespace ::comphelper;
38 using namespace ::com::sun::star::accessibility;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::lang;
41 
42 //.............................................................................
43 namespace comphelper
44 {
45 //.............................................................................
46 
47     //=========================================================================
48     //= OWrappedAccessibleChildrenManager
49     //=========================================================================
50     //--------------------------------------------------------------------
51     struct RemoveEventListener
52             : public ::std::unary_function< AccessibleMap::value_type, void >
53     {
54     private:
55         Reference< XEventListener > m_xListener;
56 
57     public:
58         RemoveEventListener( const Reference< XEventListener >& _rxListener )
59             :m_xListener( _rxListener  )
60         {
61         }
62 
63         void operator()( const AccessibleMap::value_type& _rMapEntry ) const
64         {
65             Reference< XComponent > xComp( _rMapEntry.first, UNO_QUERY );
66             if ( xComp.is() )
67                 xComp->removeEventListener( m_xListener );
68         }
69     };
70 
71     //--------------------------------------------------------------------
72     struct DisposeMappedChild
73             : public ::std::unary_function< AccessibleMap::value_type, void >
74     {
75         void operator()( const AccessibleMap::value_type& _rMapEntry ) const
76         {
77             Reference< XComponent > xContextComponent;
78             if ( _rMapEntry.second.is() )
79                 xContextComponent = xContextComponent.query( _rMapEntry.second->getAccessibleContext() );
80             if ( xContextComponent.is() )
81                 xContextComponent->dispose();
82         }
83     };
84 
85     //-------------------------------------------------------------------------
86     OWrappedAccessibleChildrenManager::OWrappedAccessibleChildrenManager( const Reference< XMultiServiceFactory >& _rxORB )
87         :m_xORB( _rxORB )
88         ,m_bTransientChildren( sal_True )
89     {
90     }
91 
92     //-------------------------------------------------------------------------
93     OWrappedAccessibleChildrenManager::~OWrappedAccessibleChildrenManager( )
94     {
95     }
96 
97     //-------------------------------------------------------------------------
98     void OWrappedAccessibleChildrenManager::setTransientChildren( sal_Bool _bSet )
99     {
100         m_bTransientChildren = _bSet;
101     }
102 
103     //-------------------------------------------------------------------------
104     void OWrappedAccessibleChildrenManager::setOwningAccessible( const Reference< XAccessible >& _rxAcc )
105     {
106         OSL_ENSURE( !m_aOwningAccessible.get().is(), "OWrappedAccessibleChildrenManager::setOwningAccessible: to be called only once!" );
107         m_aOwningAccessible = WeakReference< XAccessible >( _rxAcc );
108     }
109 
110     //-------------------------------------------------------------------------
111     void OWrappedAccessibleChildrenManager::removeFromCache( const Reference< XAccessible >& _rxKey )
112     {
113         AccessibleMap::iterator aRemovedPos = m_aChildrenMap.find( _rxKey );
114         if ( m_aChildrenMap.end() != aRemovedPos )
115         {   // it was cached
116             // remove ourself as event listener
117             RemoveEventListener aOperator( this );
118             aOperator( *aRemovedPos );
119             // and remove the entry from the map
120             m_aChildrenMap.erase( aRemovedPos );
121         }
122     }
123 
124     //-------------------------------------------------------------------------
125     void OWrappedAccessibleChildrenManager::invalidateAll( )
126     {
127         // remove as event listener from the map elements
128         ::std::for_each( m_aChildrenMap.begin(), m_aChildrenMap.end(), RemoveEventListener( this ) );
129         // clear the map
130         AccessibleMap aMap;
131         m_aChildrenMap.swap( aMap );
132     }
133 
134     //-------------------------------------------------------------------------
135     Reference< XAccessible > OWrappedAccessibleChildrenManager::getAccessibleWrapperFor(
136         const Reference< XAccessible >& _rxKey, sal_Bool _bCreate )
137     {
138         Reference< XAccessible > xValue;
139 
140         if( !_rxKey.is() )
141         {
142             // fprintf( stderr, "It was this path that was crashing stuff\n" );
143             return xValue;
144         }
145 
146         // do we have this child in the cahce?
147         AccessibleMap::const_iterator aPos = m_aChildrenMap.find( _rxKey );
148         if ( m_aChildrenMap.end() != aPos )
149         {
150             xValue = aPos->second;
151         }
152         else if ( _bCreate )
153         {   // not found in the cache, and allowed to create
154             // -> new wrapper
155             xValue = new OAccessibleWrapper( m_xORB, _rxKey, (Reference< XAccessible >)m_aOwningAccessible );
156 
157             // see if we do cache children
158             if ( !m_bTransientChildren )
159             {
160                 if (!m_aChildrenMap.insert(
161                         AccessibleMap::value_type( _rxKey, xValue ) ).second)
162                 {
163                     OSL_ENSURE(
164                         false,
165                         "OWrappedAccessibleChildrenManager::"
166                             "getAccessibleWrapperFor: element was already"
167                             " inserted!" );
168                 }
169 
170                 // listen for disposals of inner children - this may happen when the inner context
171                 // is the owner for the inner children (it will dispose these children, and of course
172                 // not our wrapper for these children)
173                 Reference< XComponent > xComp( _rxKey, UNO_QUERY );
174                 if ( xComp.is() )
175                     xComp->addEventListener( this );
176             }
177         }
178 
179         return xValue;
180     }
181 
182     //-------------------------------------------------------------------------
183     void OWrappedAccessibleChildrenManager::dispose()
184     {
185         // dispose our children
186         ::std::for_each( m_aChildrenMap.begin(), m_aChildrenMap.end(), RemoveEventListener( this ) );
187         ::std::for_each( m_aChildrenMap.begin(), m_aChildrenMap.end(), DisposeMappedChild( ) );
188         // clear our children
189         AccessibleMap aMap;
190         m_aChildrenMap.swap( aMap );
191     }
192 
193     //--------------------------------------------------------------------
194     void OWrappedAccessibleChildrenManager::implTranslateChildEventValue( const Any& _rInValue, Any& _rOutValue )
195     {
196         _rOutValue.clear();
197         Reference< XAccessible > xChild;
198         if ( _rInValue >>= xChild )
199             _rOutValue <<= getAccessibleWrapperFor( xChild, sal_True );
200     }
201 
202     //-------------------------------------------------------------------------
203     void OWrappedAccessibleChildrenManager::translateAccessibleEvent( const AccessibleEventObject& _rEvent, AccessibleEventObject& _rTranslatedEvent )
204     {
205         // just in case we can't translate some of the values:
206         _rTranslatedEvent.NewValue = _rEvent.NewValue;
207         _rTranslatedEvent.OldValue = _rEvent.OldValue;
208 
209         switch ( _rEvent.EventId )
210         {
211             case AccessibleEventId::CHILD:
212             case AccessibleEventId::ACTIVE_DESCENDANT_CHANGED:
213             case AccessibleEventId::CONTROLLED_BY_RELATION_CHANGED:
214             case AccessibleEventId::CONTROLLER_FOR_RELATION_CHANGED:
215             case AccessibleEventId::LABEL_FOR_RELATION_CHANGED:
216             case AccessibleEventId::LABELED_BY_RELATION_CHANGED:
217             case AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED:
218             case AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED:
219                 // these are events where both the old and the new value contain child references
220                 implTranslateChildEventValue( _rEvent.OldValue, _rTranslatedEvent.OldValue );
221                 implTranslateChildEventValue( _rEvent.NewValue, _rTranslatedEvent.NewValue );
222                 break;
223 
224             case AccessibleEventId::NAME_CHANGED:
225             case AccessibleEventId::DESCRIPTION_CHANGED:
226             case AccessibleEventId::ACTION_CHANGED:
227             case AccessibleEventId::STATE_CHANGED:
228             case AccessibleEventId::BOUNDRECT_CHANGED:
229             case AccessibleEventId::INVALIDATE_ALL_CHILDREN:
230             case AccessibleEventId::SELECTION_CHANGED:
231             case AccessibleEventId::VISIBLE_DATA_CHANGED:
232             case AccessibleEventId::VALUE_CHANGED:
233             case AccessibleEventId::MEMBER_OF_RELATION_CHANGED:
234             case AccessibleEventId::CARET_CHANGED:
235             case AccessibleEventId::TEXT_CHANGED:
236             case AccessibleEventId::HYPERTEXT_CHANGED:
237             case AccessibleEventId::TABLE_CAPTION_CHANGED:
238             case AccessibleEventId::TABLE_COLUMN_DESCRIPTION_CHANGED:
239             case AccessibleEventId::TABLE_COLUMN_HEADER_CHANGED:
240             case AccessibleEventId::TABLE_MODEL_CHANGED:
241             case AccessibleEventId::TABLE_ROW_DESCRIPTION_CHANGED:
242             case AccessibleEventId::TABLE_ROW_HEADER_CHANGED:
243             case AccessibleEventId::TABLE_SUMMARY_CHANGED:
244             // --> PB 2006-03-21 #130798# EventId TEXT_SELECTION_CHANGED was missed
245             // these Ids are also missed: SUB_WINDOW_OF_RELATION_CHANGED & TEXT_ATTRIBUTE_CHANGED
246             case AccessibleEventId::TEXT_SELECTION_CHANGED:
247             // <--
248                 // nothing to translate
249                 break;
250 
251             default:
252                 OSL_ENSURE( sal_False, "OWrappedAccessibleChildrenManager::translateAccessibleEvent: unknown (or unexpected) event id!" );
253                 break;
254         }
255     }
256 
257     //-------------------------------------------------------------------------
258     void OWrappedAccessibleChildrenManager::handleChildNotification( const AccessibleEventObject& _rEvent )
259     {
260         if ( AccessibleEventId::INVALIDATE_ALL_CHILDREN == _rEvent.EventId )
261         {   // clear our child map
262             invalidateAll( );
263         }
264         else if ( AccessibleEventId::CHILD == _rEvent.EventId )
265         {
266             // check if the removed or replaced element is cached
267             Reference< XAccessible > xRemoved;
268             if ( _rEvent.OldValue >>= xRemoved )
269                 removeFromCache( xRemoved );
270         }
271     }
272 
273     //--------------------------------------------------------------------
274     void SAL_CALL OWrappedAccessibleChildrenManager::disposing( const EventObject& _rSource ) throw (RuntimeException)
275     {
276         // this should come from one of the inner XAccessible's of our children
277         Reference< XAccessible > xSource( _rSource.Source, UNO_QUERY );
278         AccessibleMap::iterator aDisposedPos = m_aChildrenMap.find( xSource );
279 #if OSL_DEBUG_LEVEL > 0
280         if ( m_aChildrenMap.end() == aDisposedPos )
281         {
282             OSL_ENSURE( sal_False,
283                 "OWrappedAccessibleChildrenManager::disposing: where did this come from?" );
284             // helper for dignostics
285             Reference< XAccessible > xOwningAccessible( m_aOwningAccessible );
286             Reference< XAccessibleContext > xContext;
287             try
288             {
289                 if ( xOwningAccessible.is() )
290                     xContext = xOwningAccessible->getAccessibleContext();
291                 if ( xContext.is() )
292                 {
293                     ::rtl::OUString sName = xContext->getAccessibleName();
294                     ::rtl::OUString sDescription = xContext->getAccessibleDescription();
295 //                  sal_Int32 nPlaceYourBreakpointHere = 0;
296                 }
297             }
298             catch( const Exception& /*e*/ )
299             {
300                 // silent this, it's only diagnostics which failed
301             }
302         }
303 #endif
304         if ( m_aChildrenMap.end() != aDisposedPos )
305         {
306             m_aChildrenMap.erase( aDisposedPos );
307         }
308     }
309 
310     //=========================================================================
311     //= OAccessibleWrapper (implementation)
312     //=========================================================================
313     //-------------------------------------------------------------------------
314     OAccessibleWrapper::OAccessibleWrapper( const Reference< XMultiServiceFactory >& _rxORB,
315             const Reference< XAccessible >& _rxInnerAccessible, const Reference< XAccessible >& _rxParentAccessible )
316         :OAccessibleWrapper_Base( )
317         ,OComponentProxyAggregation( _rxORB, Reference< XComponent >( _rxInnerAccessible, UNO_QUERY ) )
318         ,m_xParentAccessible( _rxParentAccessible )
319         ,m_xInnerAccessible( _rxInnerAccessible )
320     {
321     }
322 
323     //--------------------------------------------------------------------
324     OAccessibleWrapper::~OAccessibleWrapper( )
325     {
326         if ( !m_rBHelper.bDisposed )
327         {
328             acquire();  // to prevent duplicate dtor calls
329             dispose();
330         }
331     }
332 
333     //--------------------------------------------------------------------
334     IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleWrapper, OComponentProxyAggregation, OAccessibleWrapper_Base )
335     IMPLEMENT_FORWARD_REFCOUNT( OAccessibleWrapper, OComponentProxyAggregation )
336 
337     //--------------------------------------------------------------------
338     Any OAccessibleWrapper::queryInterface( const Type& _rType ) throw (RuntimeException)
339     {
340         // #111089# instead of the inner XAccessible the proxy XAccessible must be returned
341         Any aReturn = OAccessibleWrapper_Base::queryInterface( _rType );
342         if ( !aReturn.hasValue() )
343             aReturn = OComponentProxyAggregation::queryInterface( _rType );
344 
345         return aReturn;
346     }
347 
348     //--------------------------------------------------------------------
349     Reference< XAccessibleContext > OAccessibleWrapper::getContextNoCreate( ) const
350     {
351         return (Reference< XAccessibleContext >)m_aContext;
352     }
353 
354     //--------------------------------------------------------------------
355     OAccessibleContextWrapper* OAccessibleWrapper::createAccessibleContext( const Reference< XAccessibleContext >& _rxInnerContext )
356     {
357         return new OAccessibleContextWrapper( getORB(), _rxInnerContext, this, m_xParentAccessible );
358     }
359 
360     //--------------------------------------------------------------------
361     Reference< XAccessibleContext > SAL_CALL OAccessibleWrapper::getAccessibleContext(  ) throw (RuntimeException)
362     {
363         // see if the context is still alive (we cache it)
364         Reference< XAccessibleContext > xContext = (Reference< XAccessibleContext >)m_aContext;
365         if ( !xContext.is() )
366         {
367             // create a new context
368             Reference< XAccessibleContext > xInnerContext = m_xInnerAccessible->getAccessibleContext( );
369             if ( xInnerContext.is() )
370             {
371                 xContext = createAccessibleContext( xInnerContext );
372                 // cache it
373                 m_aContext = WeakReference< XAccessibleContext >( xContext );
374             }
375         }
376 
377         return xContext;
378     }
379 
380     //=========================================================================
381     //= OAccessibleWrapper (implementation)
382     //=========================================================================
383     //-------------------------------------------------------------------------
384     OAccessibleContextWrapperHelper::OAccessibleContextWrapperHelper(
385                 const Reference< XMultiServiceFactory >& _rxORB,
386                 ::cppu::OBroadcastHelper& _rBHelper,
387                 const Reference< XAccessibleContext >& _rxInnerAccessibleContext,
388                 const Reference< XAccessible >& _rxOwningAccessible,
389                 const Reference< XAccessible >& _rxParentAccessible )
390         :OComponentProxyAggregationHelper( _rxORB, _rBHelper )
391         ,m_xInnerContext( _rxInnerAccessibleContext )
392         ,m_xOwningAccessible( _rxOwningAccessible )
393         ,m_xParentAccessible( _rxParentAccessible )
394         ,m_pChildMapper( NULL )
395     {
396         // initialize the mapper for our children
397         m_pChildMapper = new OWrappedAccessibleChildrenManager( getORB() );
398         m_pChildMapper->acquire();
399 
400         // determine if we're allowed to cache children
401         Reference< XAccessibleStateSet > xStates( m_xInnerContext->getAccessibleStateSet( ) );
402         OSL_ENSURE( xStates.is(), "OAccessibleContextWrapperHelper::OAccessibleContextWrapperHelper: no inner state set!" );
403         m_pChildMapper->setTransientChildren( !xStates.is() || xStates->contains( AccessibleStateType::MANAGES_DESCENDANTS) );
404 
405         m_pChildMapper->setOwningAccessible( m_xOwningAccessible );
406     }
407 
408     //--------------------------------------------------------------------
409     void OAccessibleContextWrapperHelper::aggregateProxy( oslInterlockedCount& _rRefCount, ::cppu::OWeakObject& _rDelegator )
410     {
411         Reference< XComponent > xInnerComponent( m_xInnerContext, UNO_QUERY );
412         OSL_ENSURE( xInnerComponent.is(), "OComponentProxyAggregation::aggregateProxy: accessible is no XComponent!" );
413         if ( xInnerComponent.is() )
414             componentAggregateProxyFor( xInnerComponent, _rRefCount, _rDelegator );
415 
416         // add as event listener to the inner context, because we want to multiplex the AccessibleEvents
417         osl_incrementInterlockedCount( &_rRefCount );
418         {
419             Reference< XAccessibleEventBroadcaster > xBroadcaster( m_xInner, UNO_QUERY );
420             if ( xBroadcaster.is() )
421                 xBroadcaster->addEventListener( this );
422         }
423         osl_decrementInterlockedCount( &_rRefCount );
424     }
425 
426     //--------------------------------------------------------------------
427     OAccessibleContextWrapperHelper::~OAccessibleContextWrapperHelper( )
428     {
429         OSL_ENSURE( m_rBHelper.bDisposed, "OAccessibleContextWrapperHelper::~OAccessibleContextWrapperHelper: you should ensure (in your dtor) that the object is disposed!" );
430 
431         m_pChildMapper->release();
432         m_pChildMapper = NULL;
433     }
434 
435     //--------------------------------------------------------------------
436     Any SAL_CALL OAccessibleContextWrapperHelper::queryInterface( const Type& _rType ) throw (RuntimeException)
437     {
438         Any aReturn = OComponentProxyAggregationHelper::queryInterface( _rType );
439         if ( !aReturn.hasValue() )
440             aReturn = OAccessibleContextWrapperHelper_Base::queryInterface( _rType );
441         return aReturn;
442     }
443 
444     //--------------------------------------------------------------------
445     IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleContextWrapperHelper, OComponentProxyAggregationHelper, OAccessibleContextWrapperHelper_Base )
446 
447     //--------------------------------------------------------------------
448     sal_Int32 SAL_CALL OAccessibleContextWrapperHelper::getAccessibleChildCount(  ) throw (RuntimeException)
449     {
450         return m_xInnerContext->getAccessibleChildCount();
451     }
452 
453     //--------------------------------------------------------------------
454     Reference< XAccessible > SAL_CALL OAccessibleContextWrapperHelper::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
455     {
456         // get the child of the wrapped component
457         Reference< XAccessible > xInnerChild = m_xInnerContext->getAccessibleChild( i );
458         return m_pChildMapper->getAccessibleWrapperFor( xInnerChild );
459     }
460 
461     //--------------------------------------------------------------------
462     Reference< XAccessibleRelationSet > SAL_CALL OAccessibleContextWrapperHelper::getAccessibleRelationSet(  ) throw (RuntimeException)
463     {
464         return m_xInnerContext->getAccessibleRelationSet();
465             // TODO: if this relation set would contain relations to siblings, we would normally need
466             // to wrap them, too ....
467     }
468 
469     //--------------------------------------------------------------------
470     void SAL_CALL OAccessibleContextWrapperHelper::notifyEvent( const AccessibleEventObject& _rEvent ) throw (RuntimeException)
471     {
472 #if OSL_DEBUG_LEVEL > 0
473         if ( AccessibleEventId::STATE_CHANGED == _rEvent.EventId )
474         {
475             sal_Bool bChildTransienceChanged = sal_False;
476             sal_Int16 nChangeState = 0;
477             if ( _rEvent.OldValue >>= nChangeState )
478                 bChildTransienceChanged = bChildTransienceChanged || AccessibleStateType::MANAGES_DESCENDANTS == nChangeState;
479             if ( _rEvent.NewValue >>= nChangeState )
480                 bChildTransienceChanged = bChildTransienceChanged || AccessibleStateType::MANAGES_DESCENDANTS == nChangeState;
481             OSL_ENSURE( !bChildTransienceChanged, "OAccessibleContextWrapperHelper::notifyEvent: MANAGES_DESCENDANTS is not expected to change during runtime!" );
482                 // if this asserts, then we would need to update our m_bTransientChildren flag here,
483                 // as well as (potentially) our child cache
484         }
485 #endif
486         AccessibleEventObject aTranslatedEvent( _rEvent );
487 
488         {
489             ::osl::MutexGuard aGuard( m_rBHelper.rMutex );
490 
491             // translate the event
492             queryInterface( ::getCppuType( static_cast< Reference< XInterface >* >( NULL ) ) ) >>= aTranslatedEvent.Source;
493             m_pChildMapper->translateAccessibleEvent( _rEvent, aTranslatedEvent );
494 
495             // see if any of these notifications affect our child manager
496             m_pChildMapper->handleChildNotification( _rEvent );
497 
498             if ( aTranslatedEvent.NewValue == m_xInner )
499                 aTranslatedEvent.NewValue = makeAny(aTranslatedEvent.Source);
500             if ( aTranslatedEvent.OldValue == m_xInner )
501                 aTranslatedEvent.OldValue = makeAny(aTranslatedEvent.Source);
502         }
503 
504         notifyTranslatedEvent( aTranslatedEvent );
505     }
506 
507     //--------------------------------------------------------------------
508     void SAL_CALL OAccessibleContextWrapperHelper::dispose() throw( RuntimeException )
509     {
510         ::osl::MutexGuard aGuard( m_rBHelper.rMutex );
511 
512         // stop multiplexing events
513         Reference< XAccessibleEventBroadcaster > xBroadcaster( m_xInner, UNO_QUERY );
514         OSL_ENSURE( xBroadcaster.is(), "OAccessibleContextWrapperHelper::disposing(): inner context is no broadcaster!" );
515         if ( xBroadcaster.is() )
516             xBroadcaster->removeEventListener( this );
517 
518         // dispose the child cache/map
519         m_pChildMapper->dispose();
520 
521         // let the base class dispose the inner component
522         OComponentProxyAggregationHelper::dispose();
523     }
524 
525     //--------------------------------------------------------------------
526     void SAL_CALL OAccessibleContextWrapperHelper::disposing( const EventObject& _rEvent )  throw (RuntimeException)
527     {
528         // simply disambiguate this
529         OComponentProxyAggregationHelper::disposing( _rEvent );
530     }
531 
532     //====================================================================
533     //= OAccessibleContextWrapper
534     //====================================================================
535     //--------------------------------------------------------------------
536     IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleContextWrapper, OAccessibleContextWrapper_CBase, OAccessibleContextWrapperHelper )
537 
538     //--------------------------------------------------------------------
539     IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleContextWrapper, OAccessibleContextWrapper_CBase, OAccessibleContextWrapperHelper )
540 
541     //--------------------------------------------------------------------
542     OAccessibleContextWrapper::OAccessibleContextWrapper( const Reference< XMultiServiceFactory >& _rxORB,
543             const Reference< XAccessibleContext >& _rxInnerAccessibleContext, const Reference< XAccessible >& _rxOwningAccessible,
544             const Reference< XAccessible >& _rxParentAccessible )
545         :OAccessibleContextWrapper_CBase( m_aMutex )
546         ,OAccessibleContextWrapperHelper( _rxORB, rBHelper, _rxInnerAccessibleContext, _rxOwningAccessible, _rxParentAccessible )
547         ,m_nNotifierClient( 0 )
548     {
549         aggregateProxy( m_refCount, *this );
550     }
551 
552     //--------------------------------------------------------------------
553     OAccessibleContextWrapper::~OAccessibleContextWrapper()
554     {
555     }
556 
557     //--------------------------------------------------------------------
558     sal_Int32 SAL_CALL OAccessibleContextWrapper::getAccessibleChildCount(  ) throw (RuntimeException)
559     {
560         return OAccessibleContextWrapperHelper::getAccessibleChildCount();
561     }
562 
563     //--------------------------------------------------------------------
564     Reference< XAccessible > SAL_CALL OAccessibleContextWrapper::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
565     {
566         return OAccessibleContextWrapperHelper::getAccessibleChild( i );
567     }
568 
569     //--------------------------------------------------------------------
570     Reference< XAccessible > SAL_CALL OAccessibleContextWrapper::getAccessibleParent(  ) throw (RuntimeException)
571     {
572         return m_xParentAccessible;
573     }
574 
575     //--------------------------------------------------------------------
576     sal_Int32 SAL_CALL OAccessibleContextWrapper::getAccessibleIndexInParent(  ) throw (RuntimeException)
577     {
578         return m_xInnerContext->getAccessibleIndexInParent();
579     }
580 
581     //--------------------------------------------------------------------
582     sal_Int16 SAL_CALL OAccessibleContextWrapper::getAccessibleRole(  ) throw (RuntimeException)
583     {
584         return m_xInnerContext->getAccessibleRole();
585     }
586 
587     //--------------------------------------------------------------------
588     ::rtl::OUString SAL_CALL OAccessibleContextWrapper::getAccessibleDescription(  ) throw (RuntimeException)
589     {
590         return m_xInnerContext->getAccessibleDescription();
591     }
592 
593     //--------------------------------------------------------------------
594     ::rtl::OUString SAL_CALL OAccessibleContextWrapper::getAccessibleName(  ) throw (RuntimeException)
595     {
596         return m_xInnerContext->getAccessibleName();
597     }
598 
599     //--------------------------------------------------------------------
600     Reference< XAccessibleRelationSet > SAL_CALL OAccessibleContextWrapper::getAccessibleRelationSet(  ) throw (RuntimeException)
601     {
602         return OAccessibleContextWrapperHelper::getAccessibleRelationSet();
603     }
604 
605     //--------------------------------------------------------------------
606     Reference< XAccessibleStateSet > SAL_CALL OAccessibleContextWrapper::getAccessibleStateSet(  ) throw (RuntimeException)
607     {
608         return m_xInnerContext->getAccessibleStateSet();
609     }
610 
611     //--------------------------------------------------------------------
612     Locale SAL_CALL OAccessibleContextWrapper::getLocale(  ) throw (IllegalAccessibleComponentStateException, RuntimeException)
613     {
614         return m_xInnerContext->getLocale();
615     }
616 
617     //--------------------------------------------------------------------
618     void OAccessibleContextWrapper::notifyTranslatedEvent( const AccessibleEventObject& _rEvent ) throw (RuntimeException)
619     {
620         if ( m_nNotifierClient )
621             AccessibleEventNotifier::addEvent( m_nNotifierClient, _rEvent );
622     }
623 
624     //--------------------------------------------------------------------
625     void SAL_CALL OAccessibleContextWrapper::addEventListener( const Reference< XAccessibleEventListener >& _rxListener ) throw (RuntimeException)
626     {
627         ::osl::MutexGuard aGuard( m_aMutex );
628         if ( !m_nNotifierClient )
629             m_nNotifierClient = AccessibleEventNotifier::registerClient( );
630         AccessibleEventNotifier::addEventListener( m_nNotifierClient, _rxListener );
631     }
632 
633     //--------------------------------------------------------------------
634     void SAL_CALL OAccessibleContextWrapper::removeEventListener( const Reference< XAccessibleEventListener >& _rxListener ) throw (RuntimeException)
635     {
636         ::osl::MutexGuard aGuard( m_aMutex );
637         if ( m_nNotifierClient )
638         {
639             if ( 0 == AccessibleEventNotifier::removeEventListener( m_nNotifierClient, _rxListener ) )
640             {
641                 AccessibleEventNotifier::TClientId nId( m_nNotifierClient );
642                 m_nNotifierClient = 0;
643                 AccessibleEventNotifier::revokeClient( nId );
644             }
645         }
646     }
647 
648     //--------------------------------------------------------------------
649     void SAL_CALL OAccessibleContextWrapper::disposing()  throw (RuntimeException)
650     {
651         AccessibleEventNotifier::TClientId nClientId( 0 );
652 
653         // --- <mutex lock> -----------------------------------------
654         {
655             ::osl::MutexGuard aGuard( m_aMutex );
656 
657             // prepare notifying our AccessibleListeners
658             if ( m_nNotifierClient )
659             {
660                 nClientId = m_nNotifierClient;
661                 m_nNotifierClient = 0;
662             }
663         }
664         // --- </mutex lock> -----------------------------------------
665 
666         // let the base class do
667         OAccessibleContextWrapperHelper::dispose();
668 
669         // notify the disposal
670         if ( nClientId )
671             AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this );
672     }
673 
674     //--------------------------------------------------------------------
675     void SAL_CALL OAccessibleContextWrapper::dispose() throw( RuntimeException )
676     {
677         // simply disambiguate
678         OComponentProxyAggregation_CBase::dispose();
679     }
680 
681 //.............................................................................
682 }   // namespace accessibility
683 //.............................................................................
684