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