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 #include <AccessibleBase.hxx>
21 #include "AccessibleChartShape.hxx"
22 #include <ObjectHierarchy.hxx>
23 #include <ObjectIdentifier.hxx>
24 #include <ChartView.hxx>
25 #include <ChartController.hxx>
27 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
28 #include <com/sun/star/accessibility/AccessibleEventObject.hpp>
29 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
30 #include <com/sun/star/accessibility/AccessibleRole.hpp>
31 #include <com/sun/star/drawing/LineStyle.hpp>
32 #include <com/sun/star/drawing/FillStyle.hpp>
33 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
34 #include <sal/log.hxx>
36 #include <vcl/svapp.hxx>
37 #include <cppuhelper/supportsservice.hxx>
38 #include <i18nlangtag/languagetag.hxx>
39 #include <toolkit/helper/vclunohelper.hxx>
40 #include <vcl/window.hxx>
41 #include <vcl/settings.hxx>
42 #include <o3tl/functional.hxx>
43 #include <o3tl/safeint.hxx>
44 #include <comphelper/diagnose_ex.hxx>
49 #include "ChartElementFactory.hxx"
51 using namespace ::com::sun::star
;
52 using namespace ::com::sun::star::accessibility
;
54 using ::com::sun::star::uno::UNO_QUERY
;
55 using ::com::sun::star::uno::Reference
;
56 using ::osl::MutexGuard
;
57 using ::osl::ClearableMutexGuard
;
58 using ::com::sun::star::uno::Any
;
63 /** @param bMayHaveChildren is false per default
65 AccessibleBase::AccessibleBase(
66 AccessibleElementInfo aAccInfo
,
67 bool bMayHaveChildren
,
68 bool bAlwaysTransparent
/* default: false */ ) :
69 impl::AccessibleBase_Base( m_aMutex
),
70 m_bIsDisposed( false ),
71 m_bMayHaveChildren( bMayHaveChildren
),
72 m_bChildrenInitialized( false ),
73 m_nEventNotifierId(0),
75 m_aAccInfo(std::move( aAccInfo
)),
76 m_bAlwaysTransparent( bAlwaysTransparent
),
77 m_bStateSetInitialized( false )
79 // initialize some states
80 m_nStateSet
|= AccessibleStateType::ENABLED
;
81 m_nStateSet
|= AccessibleStateType::SHOWING
;
82 m_nStateSet
|= AccessibleStateType::VISIBLE
;
83 m_nStateSet
|= AccessibleStateType::SELECTABLE
;
84 m_nStateSet
|= AccessibleStateType::FOCUSABLE
;
87 AccessibleBase::~AccessibleBase()
89 OSL_ASSERT( m_bIsDisposed
);
92 bool AccessibleBase::CheckDisposeState( bool bThrowException
/* default: true */ ) const
94 if( bThrowException
&&
97 throw lang::DisposedException(u
"component has state DEFUNC"_ustr
,
98 static_cast< uno::XWeak
* >( const_cast< AccessibleBase
* >( this )));
100 return m_bIsDisposed
;
103 bool AccessibleBase::NotifyEvent( EventType eEventType
, const AccessibleUniqueId
& rId
)
107 // event is addressed to this object
109 css::uno::Any aEmpty
;
110 css::uno::Any aSelected
;
111 aSelected
<<= AccessibleStateType::SELECTED
;
114 case EventType::GOT_SELECTION
:
116 AddState( AccessibleStateType::SELECTED
);
117 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED
, aSelected
, aEmpty
);
119 AddState( AccessibleStateType::FOCUSED
);
120 aSelected
<<= AccessibleStateType::FOCUSED
;
121 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED
, aSelected
, aEmpty
);
123 SAL_INFO("chart2.accessibility", "Selection acquired by: " << getAccessibleName());
127 case EventType::LOST_SELECTION
:
129 RemoveState( AccessibleStateType::SELECTED
);
130 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED
, aEmpty
, aSelected
);
132 AddState( AccessibleStateType::FOCUSED
);
133 aSelected
<<= AccessibleStateType::FOCUSED
;
134 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED
, aEmpty
, aSelected
);
135 SAL_INFO("chart2.accessibility", "Selection lost by: " << getAccessibleName());
141 else if( m_bMayHaveChildren
)
145 ClearableMutexGuard
aGuard( m_aMutex
);
146 // make local copy for notification
147 std::vector
<Reference
<XAccessible
>> aLocalChildList(m_aChildList
);
150 for (auto const& localChild
: aLocalChildList
)
152 // Note: at this place we must be sure to have an AccessibleBase
153 // object in the UNO reference to XAccessible !
154 bStop
= (*static_cast< AccessibleBase
* >
155 ( localChild
.get() )).NotifyEvent( eEventType
, rId
);
165 void AccessibleBase::AddState( sal_Int64 aState
)
168 m_nStateSet
|= aState
;
171 void AccessibleBase::RemoveState( sal_Int64 aState
)
174 m_nStateSet
&= ~aState
;
177 bool AccessibleBase::UpdateChildren()
179 bool bMustUpdateChildren
= false;
181 MutexGuard
aGuard( m_aMutex
);
182 if( ! m_bMayHaveChildren
||
186 bMustUpdateChildren
= ( m_bMayHaveChildren
&&
187 ! m_bChildrenInitialized
);
191 if( bMustUpdateChildren
)
192 m_bChildrenInitialized
= ImplUpdateChildren();
194 return m_bChildrenInitialized
;
197 bool AccessibleBase::ImplUpdateChildren()
199 bool bResult
= false;
201 if( m_aAccInfo
.m_spObjectHierarchy
)
203 ObjectHierarchy::tChildContainer
aModelChildren(
204 m_aAccInfo
.m_spObjectHierarchy
->getChildren( GetId() ));
205 std::vector
< ChildOIDMap::key_type
> aAccChildren
;
206 aAccChildren
.reserve( aModelChildren
.size());
207 std::transform( m_aChildOIDMap
.begin(), m_aChildOIDMap
.end(),
208 std::back_inserter( aAccChildren
),
209 ::o3tl::select1st
< ChildOIDMap::value_type
>() );
211 std::sort( aModelChildren
.begin(), aModelChildren
.end());
213 std::vector
< ObjectIdentifier
> aChildrenToRemove
, aChildrenToAdd
;
214 std::set_difference( aModelChildren
.begin(), aModelChildren
.end(),
215 aAccChildren
.begin(), aAccChildren
.end(),
216 std::back_inserter( aChildrenToAdd
));
217 std::set_difference( aAccChildren
.begin(), aAccChildren
.end(),
218 aModelChildren
.begin(), aModelChildren
.end(),
219 std::back_inserter( aChildrenToRemove
));
221 for (auto const& childToRemove
: aChildrenToRemove
)
223 RemoveChildByOId(childToRemove
);
226 AccessibleElementInfo
aAccInfo( GetInfo());
227 aAccInfo
.m_pParent
= this;
229 for (auto const& childToAdd
: aChildrenToAdd
)
231 aAccInfo
.m_aOID
= childToAdd
;
232 if ( childToAdd
.isAutoGeneratedObject() )
234 AddChild( ChartElementFactory::CreateChartElement( aAccInfo
).get() );
236 else if ( childToAdd
.isAdditionalShape() )
238 AddChild( new AccessibleChartShape( aAccInfo
) );
247 void AccessibleBase::AddChild( AccessibleBase
* pChild
)
249 OSL_ENSURE( pChild
!= nullptr, "Invalid Child" );
253 ClearableMutexGuard
aGuard( m_aMutex
);
255 Reference
< XAccessible
> xChild( pChild
);
256 m_aChildList
.push_back( xChild
);
258 m_aChildOIDMap
[ pChild
->GetId() ] = xChild
;
260 // inform listeners of new child
261 if( m_bChildrenInitialized
)
267 BroadcastAccEvent( AccessibleEventId::CHILD
, aNew
, aEmpty
);
271 /** in this method we imply that the Reference< XAccessible > elements in the
272 vector are AccessibleBase objects !
274 void AccessibleBase::RemoveChildByOId( const ObjectIdentifier
& rOId
)
276 ClearableMutexGuard
aGuard( m_aMutex
);
278 ChildOIDMap::iterator
aIt( m_aChildOIDMap
.find( rOId
));
279 if( aIt
== m_aChildOIDMap
.end())
282 Reference
< XAccessible
> xChild( aIt
->second
);
285 m_aChildOIDMap
.erase( aIt
);
287 // search child in vector
288 auto aVecIter
= std::find(m_aChildList
.begin(), m_aChildList
.end(), xChild
);
290 OSL_ENSURE( aVecIter
!= m_aChildList
.end(),
291 "Inconsistent ChildMap" );
293 // remove child from vector
294 m_aChildList
.erase( aVecIter
);
295 bool bInitialized
= m_bChildrenInitialized
;
297 // call listeners unguarded
300 // inform listeners of removed child
306 BroadcastAccEvent( AccessibleEventId::CHILD
, aEmpty
, aOld
);
310 Reference
< lang::XComponent
> xComp( xChild
, UNO_QUERY
);
315 awt::Point
AccessibleBase::GetUpperLeftOnScreen() const
318 if( m_aAccInfo
.m_pParent
)
320 ClearableMutexGuard
aGuard( m_aMutex
);
321 AccessibleBase
* pParent
= m_aAccInfo
.m_pParent
;
326 aResult
= pParent
->GetUpperLeftOnScreen();
329 OSL_FAIL( "Default position used is probably incorrect." );
335 void AccessibleBase::BroadcastAccEvent(
338 const Any
& rOld
) const
340 ClearableMutexGuard
aGuard( m_aMutex
);
342 if ( !m_nEventNotifierId
)
344 // if we don't have a client id for the notifier, then we don't have listeners, then
345 // we don't need to notify anything
347 // the const cast is needed, because UNO parameters are never const
348 const AccessibleEventObject
aEvent(
349 const_cast< uno::XWeak
* >( static_cast< const uno::XWeak
* >( this )),
350 nId
, rNew
, rOld
, -1 );
352 // let the notifier handle this event
353 ::comphelper::AccessibleEventNotifier::addEvent( m_nEventNotifierId
, aEvent
);
358 void AccessibleBase::KillAllChildren()
360 ClearableMutexGuard
aGuard( m_aMutex
);
362 // make local copy for notification, and remove all children
363 std::vector
<Reference
<XAccessible
>> aLocalChildList
;
364 aLocalChildList
.swap( m_aChildList
);
365 m_aChildOIDMap
.clear();
369 // call dispose for all children
370 // and notify listeners
371 Reference
< lang::XComponent
> xComp
;
373 for (auto const& localChild
: aLocalChildList
)
376 BroadcastAccEvent( AccessibleEventId::CHILD
, aEmpty
, aOld
);
378 xComp
.set(localChild
, UNO_QUERY
);
382 m_bChildrenInitialized
= false;
385 void AccessibleBase::SetInfo( const AccessibleElementInfo
& rNewInfo
)
387 m_aAccInfo
= rNewInfo
;
388 if( m_bMayHaveChildren
)
392 BroadcastAccEvent( AccessibleEventId::INVALIDATE_ALL_CHILDREN
, uno::Any(), uno::Any());
395 // ________ (XComponent::dispose) ________
396 void SAL_CALL
AccessibleBase::disposing()
399 MutexGuard
aGuard(m_aMutex
);
400 OSL_ENSURE(!m_bIsDisposed
, "dispose() called twice");
402 // notify disposing to all AccessibleEvent listeners asynchronous
403 if (m_nEventNotifierId
)
405 ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(m_nEventNotifierId
,
407 m_nEventNotifierId
= 0;
411 m_aAccInfo
.m_pParent
= nullptr;
413 m_nStateSet
= AccessibleStateType::DEFUNC
;
415 m_bIsDisposed
= true;
418 // call listeners unguarded
420 if( m_bMayHaveChildren
)
425 OSL_ENSURE( m_aChildList
.empty(), "Child list should be empty" );
428 // ________ XAccessible ________
429 Reference
< XAccessibleContext
> SAL_CALL
AccessibleBase::getAccessibleContext()
434 // ________ AccessibleBase::XAccessibleContext ________
435 sal_Int64 SAL_CALL
AccessibleBase::getAccessibleChildCount()
437 ClearableMutexGuard
aGuard( m_aMutex
);
438 if( ! m_bMayHaveChildren
||
442 bool bMustUpdateChildren
= ( m_bMayHaveChildren
&&
443 ! m_bChildrenInitialized
);
448 if( bMustUpdateChildren
)
451 return ImplGetAccessibleChildCount();
454 sal_Int64
AccessibleBase::ImplGetAccessibleChildCount() const
456 return m_aChildList
.size();
459 Reference
< XAccessible
> SAL_CALL
AccessibleBase::getAccessibleChild( sal_Int64 i
)
462 Reference
< XAccessible
> xResult
;
464 ClearableMutexGuard
aGuard( m_aMutex
);
465 bool bMustUpdateChildren
= ( m_bMayHaveChildren
&&
466 ! m_bChildrenInitialized
);
470 if( bMustUpdateChildren
)
473 xResult
.set( ImplGetAccessibleChildById( i
));
478 Reference
< XAccessible
> AccessibleBase::ImplGetAccessibleChildById( sal_Int64 i
) const
480 Reference
< XAccessible
> xResult
;
482 MutexGuard
aGuard( m_aMutex
);
483 if( ! m_bMayHaveChildren
||
485 o3tl::make_unsigned( i
) >= m_aChildList
.size() )
487 OUString aBuf
= "Index " + OUString::number( i
) + " is invalid for range [ 0, " +
488 OUString::number( m_aChildList
.size() - 1 ) +
490 lang::IndexOutOfBoundsException
aEx( aBuf
,
491 const_cast< ::cppu::OWeakObject
* >(
492 static_cast< const ::cppu::OWeakObject
* >( this )));
496 xResult
.set( m_aChildList
[ i
] );
501 Reference
< XAccessible
> SAL_CALL
AccessibleBase::getAccessibleParent()
504 Reference
< XAccessible
> aResult
;
505 if( m_aAccInfo
.m_pParent
)
506 aResult
.set( m_aAccInfo
.m_pParent
);
511 sal_Int64 SAL_CALL
AccessibleBase::getAccessibleIndexInParent()
515 if( m_aAccInfo
.m_spObjectHierarchy
)
516 return m_aAccInfo
.m_spObjectHierarchy
->getIndexInParent( GetId() );
520 sal_Int16 SAL_CALL
AccessibleBase::getAccessibleRole()
522 return AccessibleRole::SHAPE
;
525 Reference
< XAccessibleRelationSet
> SAL_CALL
AccessibleBase::getAccessibleRelationSet()
527 Reference
< XAccessibleRelationSet
> aResult
;
531 sal_Int64 SAL_CALL
AccessibleBase::getAccessibleStateSet()
533 if( ! m_bStateSetInitialized
)
535 rtl::Reference
< ::chart::ChartController
> xSelSupp( GetInfo().m_xChartController
);
538 ObjectIdentifier
aOID( xSelSupp
->getSelection() );
539 if ( aOID
.isValid() && GetId() == aOID
)
541 AddState( AccessibleStateType::SELECTED
);
542 AddState( AccessibleStateType::FOCUSED
);
545 m_bStateSetInitialized
= true;
551 lang::Locale SAL_CALL
AccessibleBase::getLocale()
555 return Application::GetSettings().GetLanguageTag().getLocale();
558 // ________ AccessibleBase::XAccessibleComponent ________
559 sal_Bool SAL_CALL
AccessibleBase::containsPoint( const awt::Point
& aPoint
)
561 awt::Rectangle
aRect( getBounds() );
563 // contains() works with relative coordinates
567 return ( aPoint
.X
>= aRect
.X
&&
568 aPoint
.Y
>= aRect
.Y
&&
569 aPoint
.X
< (aRect
.X
+ aRect
.Width
) &&
570 aPoint
.Y
< (aRect
.Y
+ aRect
.Height
) );
573 Reference
< XAccessible
> SAL_CALL
AccessibleBase::getAccessibleAtPoint( const awt::Point
& aPoint
)
576 Reference
< XAccessible
> aResult
;
577 awt::Rectangle
aRect( getBounds());
579 // children are positioned relative to this object, so translate bound rect
583 // children must be inside the own bound rect
584 if( ( aRect
.X
<= aPoint
.X
&& aPoint
.X
<= (aRect
.X
+ aRect
.Width
) ) &&
585 ( aRect
.Y
<= aPoint
.Y
&& aPoint
.Y
<= (aRect
.Y
+ aRect
.Height
)))
587 ClearableMutexGuard
aGuard( m_aMutex
);
588 std::vector
<Reference
<XAccessible
>> aLocalChildList( m_aChildList
);
591 Reference
< XAccessibleComponent
> aComp
;
592 for (auto const& localChild
: aLocalChildList
)
594 aComp
.set(localChild
, UNO_QUERY
);
597 aRect
= aComp
->getBounds();
598 if( ( aRect
.X
<= aPoint
.X
&& aPoint
.X
<= (aRect
.X
+ aRect
.Width
) ) &&
599 ( aRect
.Y
<= aPoint
.Y
&& aPoint
.Y
<= (aRect
.Y
+ aRect
.Height
)))
601 aResult
= localChild
;
611 awt::Rectangle SAL_CALL
AccessibleBase::getBounds()
613 rtl::Reference
<ChartView
> pChartView
= m_aAccInfo
.m_xView
.get();
616 VclPtr
<vcl::Window
> pWindow( VCLUnoHelper::GetWindow( m_aAccInfo
.m_xWindow
));
617 awt::Rectangle
aLogicRect( pChartView
->getRectangleOfObject( m_aAccInfo
.m_aOID
.getObjectCID() ));
620 tools::Rectangle
aRect( aLogicRect
.X
, aLogicRect
.Y
,
621 aLogicRect
.X
+ aLogicRect
.Width
,
622 aLogicRect
.Y
+ aLogicRect
.Height
);
623 SolarMutexGuard aSolarGuard
;
624 aRect
= pWindow
->LogicToPixel( aRect
);
626 // aLogicRect is relative to the page, but we need a value relative
627 // to the parent object
628 awt::Point aParentLocOnScreen
;
629 uno::Reference
< XAccessibleComponent
> xParent( getAccessibleParent(), uno::UNO_QUERY
);
631 aParentLocOnScreen
= xParent
->getLocationOnScreen();
633 awt::Point aULOnScreen
= GetUpperLeftOnScreen();
634 awt::Point
aOffset( aParentLocOnScreen
.X
- aULOnScreen
.X
,
635 aParentLocOnScreen
.Y
- aULOnScreen
.Y
);
637 return awt::Rectangle( aRect
.Left() - aOffset
.X
, aRect
.Top() - aOffset
.Y
,
638 aRect
.getOpenWidth(), aRect
.getOpenHeight());
642 return awt::Rectangle();
645 awt::Point SAL_CALL
AccessibleBase::getLocation()
648 awt::Rectangle
aBBox( getBounds() );
649 return awt::Point( aBBox
.X
, aBBox
.Y
);
652 awt::Point SAL_CALL
AccessibleBase::getLocationOnScreen()
656 if (AccessibleBase
* pParent
= m_aAccInfo
.m_pParent
)
658 awt::Point
aLocThisRel( getLocation());
659 awt::Point
aUpperLeft(pParent
->getLocationOnScreen());
661 return awt::Point( aUpperLeft
.X
+ aLocThisRel
.X
,
662 aUpperLeft
.Y
+ aLocThisRel
.Y
);
665 return getLocation();
668 awt::Size SAL_CALL
AccessibleBase::getSize()
671 awt::Rectangle
aBBox( getBounds() );
672 return awt::Size( aBBox
.Width
, aBBox
.Height
);
675 void SAL_CALL
AccessibleBase::grabFocus()
679 rtl::Reference
< ::chart::ChartController
> xSelSupp( GetInfo().m_xChartController
);
682 xSelSupp
->select( GetId().getAny() );
686 sal_Int32 SAL_CALL
AccessibleBase::getForeground()
688 return sal_Int32(getColor( ACC_BASE_FOREGROUND
));
691 sal_Int32 SAL_CALL
AccessibleBase::getBackground()
693 return sal_Int32(getColor( ACC_BASE_BACKGROUND
));
696 Color
AccessibleBase::getColor( eColorType eColType
)
698 Color nResult
= COL_TRANSPARENT
;
699 if( m_bAlwaysTransparent
)
702 ObjectIdentifier
aOID( m_aAccInfo
.m_aOID
);
703 ObjectType
eType( aOID
.getObjectType() );
704 Reference
< beans::XPropertySet
> xObjProp
;
705 OUString aObjectCID
= aOID
.getObjectCID();
706 if( eType
== OBJECTTYPE_LEGEND_ENTRY
)
708 // for colors get the data series/point properties
709 std::u16string_view
aParentParticle( ObjectIdentifier::getFullParentParticle( aObjectCID
));
710 aObjectCID
= ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle
);
714 ObjectIdentifier::getObjectPropertySet(
715 aObjectCID
, m_aAccInfo
.m_xChartDocument
);
721 OUString aStylePropName
;
725 case OBJECTTYPE_LEGEND_ENTRY
:
726 case OBJECTTYPE_DATA_SERIES
:
727 case OBJECTTYPE_DATA_POINT
:
728 if( eColType
== ACC_BASE_FOREGROUND
)
730 aPropName
= "BorderColor";
731 aStylePropName
= "BorderTransparency";
736 aStylePropName
= "Transparency";
740 if( eColType
== ACC_BASE_FOREGROUND
)
742 aPropName
= "LineColor";
743 aStylePropName
= "LineTransparence";
747 aPropName
= "FillColor";
748 aStylePropName
= "FillTransparence";
753 bool bTransparent
= m_bAlwaysTransparent
;
754 Reference
< beans::XPropertySetInfo
> xInfo
= xObjProp
->getPropertySetInfo();
756 xInfo
->hasPropertyByName( aStylePropName
))
758 if( eColType
== ACC_BASE_FOREGROUND
)
760 drawing::LineStyle aLStyle
= drawing::LineStyle_SOLID
;
761 if( xObjProp
->getPropertyValue( aStylePropName
) >>= aLStyle
)
762 bTransparent
= (aLStyle
== drawing::LineStyle_NONE
);
766 drawing::FillStyle aFStyle
= drawing::FillStyle_SOLID
;
767 if( xObjProp
->getPropertyValue( aStylePropName
) >>= aFStyle
)
768 bTransparent
= (aFStyle
== drawing::FillStyle_NONE
);
774 xInfo
->hasPropertyByName( aPropName
))
776 xObjProp
->getPropertyValue( aPropName
) >>= nResult
;
779 catch( const uno::Exception
& )
781 DBG_UNHANDLED_EXCEPTION("chart2");
788 // ________ AccessibleBase::XServiceInfo ________
789 OUString SAL_CALL
AccessibleBase::getImplementationName()
791 return u
"AccessibleBase"_ustr
;
794 sal_Bool SAL_CALL
AccessibleBase::supportsService( const OUString
& ServiceName
)
796 return cppu::supportsService( this, ServiceName
);
799 uno::Sequence
< OUString
> SAL_CALL
AccessibleBase::getSupportedServiceNames()
802 u
"com.sun.star.accessibility.Accessible"_ustr
,
803 u
"com.sun.star.accessibility.AccessibleContext"_ustr
807 // ________ AccessibleBase::XEventListener ________
808 void SAL_CALL
AccessibleBase::disposing( const lang::EventObject
& /*Source*/ )
812 // ________ XAccessibleEventBroadcasters ________
813 void SAL_CALL
AccessibleBase::addAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
815 MutexGuard
aGuard( m_aMutex
);
817 if ( xListener
.is() )
819 if ( !m_nEventNotifierId
)
820 m_nEventNotifierId
= ::comphelper::AccessibleEventNotifier::registerClient();
822 ::comphelper::AccessibleEventNotifier::addEventListener( m_nEventNotifierId
, xListener
);
826 void SAL_CALL
AccessibleBase::removeAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
828 MutexGuard
aGuard( m_aMutex
);
830 if ( xListener
.is() && m_nEventNotifierId
)
832 sal_Int32 nListenerCount
= ::comphelper::AccessibleEventNotifier::removeEventListener( m_nEventNotifierId
, xListener
);
833 if ( !nListenerCount
)
835 // no listeners anymore
836 ::comphelper::AccessibleEventNotifier::revokeClient( m_nEventNotifierId
);
837 m_nEventNotifierId
= 0;
844 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */