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>
26 #include <chartview/ExplicitValueProvider.hxx>
28 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
29 #include <com/sun/star/accessibility/AccessibleEventObject.hpp>
30 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
31 #include <com/sun/star/accessibility/AccessibleRole.hpp>
32 #include <com/sun/star/drawing/LineStyle.hpp>
33 #include <com/sun/star/drawing/FillStyle.hpp>
34 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
35 #include <com/sun/star/view/XSelectionSupplier.hpp>
36 #include <sal/log.hxx>
38 #include <vcl/svapp.hxx>
39 #include <comphelper/servicehelper.hxx>
40 #include <cppuhelper/supportsservice.hxx>
41 #include <i18nlangtag/languagetag.hxx>
42 #include <toolkit/helper/vclunohelper.hxx>
43 #include <vcl/window.hxx>
44 #include <vcl/settings.hxx>
45 #include <o3tl/functional.hxx>
46 #include <o3tl/safeint.hxx>
47 #include <comphelper/diagnose_ex.hxx>
52 #include "ChartElementFactory.hxx"
54 using namespace ::com::sun::star
;
55 using namespace ::com::sun::star::accessibility
;
57 using ::com::sun::star::uno::UNO_QUERY
;
58 using ::com::sun::star::uno::Reference
;
59 using ::osl::MutexGuard
;
60 using ::osl::ClearableMutexGuard
;
61 using ::com::sun::star::uno::Any
;
66 /** @param bMayHaveChildren is false per default
68 AccessibleBase::AccessibleBase(
69 AccessibleElementInfo aAccInfo
,
70 bool bMayHaveChildren
,
71 bool bAlwaysTransparent
/* default: false */ ) :
72 impl::AccessibleBase_Base( m_aMutex
),
73 m_bIsDisposed( false ),
74 m_bMayHaveChildren( bMayHaveChildren
),
75 m_bChildrenInitialized( false ),
76 m_nEventNotifierId(0),
78 m_aAccInfo(std::move( aAccInfo
)),
79 m_bAlwaysTransparent( bAlwaysTransparent
),
80 m_bStateSetInitialized( false )
82 // initialize some states
83 m_nStateSet
|= AccessibleStateType::ENABLED
;
84 m_nStateSet
|= AccessibleStateType::SHOWING
;
85 m_nStateSet
|= AccessibleStateType::VISIBLE
;
86 m_nStateSet
|= AccessibleStateType::SELECTABLE
;
87 m_nStateSet
|= AccessibleStateType::FOCUSABLE
;
90 AccessibleBase::~AccessibleBase()
92 OSL_ASSERT( m_bIsDisposed
);
95 bool AccessibleBase::CheckDisposeState( bool bThrowException
/* default: true */ ) const
97 if( bThrowException
&&
100 throw lang::DisposedException("component has state DEFUNC",
101 static_cast< uno::XWeak
* >( const_cast< AccessibleBase
* >( this )));
103 return m_bIsDisposed
;
106 bool AccessibleBase::NotifyEvent( EventType eEventType
, const AccessibleUniqueId
& rId
)
110 // event is addressed to this object
112 css::uno::Any aEmpty
;
113 css::uno::Any aSelected
;
114 aSelected
<<= AccessibleStateType::SELECTED
;
117 case EventType::GOT_SELECTION
:
119 AddState( AccessibleStateType::SELECTED
);
120 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED
, aSelected
, aEmpty
);
122 AddState( AccessibleStateType::FOCUSED
);
123 aSelected
<<= AccessibleStateType::FOCUSED
;
124 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED
, aSelected
, aEmpty
);
126 SAL_INFO("chart2.accessibility", "Selection acquired by: " << getAccessibleName());
130 case EventType::LOST_SELECTION
:
132 RemoveState( AccessibleStateType::SELECTED
);
133 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED
, aEmpty
, aSelected
);
135 AddState( AccessibleStateType::FOCUSED
);
136 aSelected
<<= AccessibleStateType::FOCUSED
;
137 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED
, aEmpty
, aSelected
);
138 SAL_INFO("chart2.accessibility", "Selection lost by: " << getAccessibleName());
144 else if( m_bMayHaveChildren
)
148 ClearableMutexGuard
aGuard( m_aMutex
);
149 // make local copy for notification
150 ChildListVectorType
aLocalChildList( m_aChildList
);
153 for (auto const& localChild
: aLocalChildList
)
155 // Note: at this place we must be sure to have an AccessibleBase
156 // object in the UNO reference to XAccessible !
157 bStop
= (*static_cast< AccessibleBase
* >
158 ( localChild
.get() )).NotifyEvent( eEventType
, rId
);
168 void AccessibleBase::AddState( sal_Int64 aState
)
171 m_nStateSet
|= aState
;
174 void AccessibleBase::RemoveState( sal_Int64 aState
)
177 m_nStateSet
&= ~aState
;
180 bool AccessibleBase::UpdateChildren()
182 bool bMustUpdateChildren
= false;
184 MutexGuard
aGuard( m_aMutex
);
185 if( ! m_bMayHaveChildren
||
189 bMustUpdateChildren
= ( m_bMayHaveChildren
&&
190 ! m_bChildrenInitialized
);
194 if( bMustUpdateChildren
)
195 m_bChildrenInitialized
= ImplUpdateChildren();
197 return m_bChildrenInitialized
;
200 bool AccessibleBase::ImplUpdateChildren()
202 bool bResult
= false;
204 if( m_aAccInfo
.m_spObjectHierarchy
)
206 ObjectHierarchy::tChildContainer
aModelChildren(
207 m_aAccInfo
.m_spObjectHierarchy
->getChildren( GetId() ));
208 std::vector
< ChildOIDMap::key_type
> aAccChildren
;
209 aAccChildren
.reserve( aModelChildren
.size());
210 std::transform( m_aChildOIDMap
.begin(), m_aChildOIDMap
.end(),
211 std::back_inserter( aAccChildren
),
212 ::o3tl::select1st
< ChildOIDMap::value_type
>() );
214 std::sort( aModelChildren
.begin(), aModelChildren
.end());
216 std::vector
< ObjectIdentifier
> aChildrenToRemove
, aChildrenToAdd
;
217 std::set_difference( aModelChildren
.begin(), aModelChildren
.end(),
218 aAccChildren
.begin(), aAccChildren
.end(),
219 std::back_inserter( aChildrenToAdd
));
220 std::set_difference( aAccChildren
.begin(), aAccChildren
.end(),
221 aModelChildren
.begin(), aModelChildren
.end(),
222 std::back_inserter( aChildrenToRemove
));
224 for (auto const& childToRemove
: aChildrenToRemove
)
226 RemoveChildByOId(childToRemove
);
229 AccessibleElementInfo
aAccInfo( GetInfo());
230 aAccInfo
.m_pParent
= this;
232 for (auto const& childToAdd
: aChildrenToAdd
)
234 aAccInfo
.m_aOID
= childToAdd
;
235 if ( childToAdd
.isAutoGeneratedObject() )
237 AddChild( ChartElementFactory::CreateChartElement( aAccInfo
).get() );
239 else if ( childToAdd
.isAdditionalShape() )
241 AddChild( new AccessibleChartShape( aAccInfo
) );
250 void AccessibleBase::AddChild( AccessibleBase
* pChild
)
252 OSL_ENSURE( pChild
!= nullptr, "Invalid Child" );
256 ClearableMutexGuard
aGuard( m_aMutex
);
258 Reference
< XAccessible
> xChild( pChild
);
259 m_aChildList
.push_back( xChild
);
261 m_aChildOIDMap
[ pChild
->GetId() ] = xChild
;
263 // inform listeners of new child
264 if( m_bChildrenInitialized
)
270 BroadcastAccEvent( AccessibleEventId::CHILD
, aNew
, aEmpty
);
274 /** in this method we imply that the Reference< XAccessible > elements in the
275 vector are AccessibleBase objects !
277 void AccessibleBase::RemoveChildByOId( const ObjectIdentifier
& rOId
)
279 ClearableMutexGuard
aGuard( m_aMutex
);
281 ChildOIDMap::iterator
aIt( m_aChildOIDMap
.find( rOId
));
282 if( aIt
== m_aChildOIDMap
.end())
285 Reference
< XAccessible
> xChild( aIt
->second
);
288 m_aChildOIDMap
.erase( aIt
);
290 // search child in vector
291 ChildListVectorType::iterator aVecIter
=
292 std::find( m_aChildList
.begin(), m_aChildList
.end(), xChild
);
294 OSL_ENSURE( aVecIter
!= m_aChildList
.end(),
295 "Inconsistent ChildMap" );
297 // remove child from vector
298 m_aChildList
.erase( aVecIter
);
299 bool bInitialized
= m_bChildrenInitialized
;
301 // call listeners unguarded
304 // inform listeners of removed child
310 BroadcastAccEvent( AccessibleEventId::CHILD
, aEmpty
, aOld
);
314 Reference
< lang::XComponent
> xComp( xChild
, UNO_QUERY
);
319 awt::Point
AccessibleBase::GetUpperLeftOnScreen() const
322 if( m_aAccInfo
.m_pParent
)
324 ClearableMutexGuard
aGuard( m_aMutex
);
325 AccessibleBase
* pParent
= m_aAccInfo
.m_pParent
;
330 aResult
= pParent
->GetUpperLeftOnScreen();
333 OSL_FAIL( "Default position used is probably incorrect." );
339 void AccessibleBase::BroadcastAccEvent(
342 const Any
& rOld
) const
344 ClearableMutexGuard
aGuard( m_aMutex
);
346 if ( !m_nEventNotifierId
)
348 // if we don't have a client id for the notifier, then we don't have listeners, then
349 // we don't need to notify anything
351 // the const cast is needed, because UNO parameters are never const
352 const AccessibleEventObject
aEvent(
353 const_cast< uno::XWeak
* >( static_cast< const uno::XWeak
* >( this )),
354 nId
, rNew
, rOld
, -1 );
356 // let the notifier handle this event
357 ::comphelper::AccessibleEventNotifier::addEvent( m_nEventNotifierId
, aEvent
);
362 void AccessibleBase::KillAllChildren()
364 ClearableMutexGuard
aGuard( m_aMutex
);
366 // make local copy for notification, and remove all children
367 ChildListVectorType aLocalChildList
;
368 aLocalChildList
.swap( m_aChildList
);
369 m_aChildOIDMap
.clear();
373 // call dispose for all children
374 // and notify listeners
375 Reference
< lang::XComponent
> xComp
;
377 for (auto const& localChild
: aLocalChildList
)
380 BroadcastAccEvent( AccessibleEventId::CHILD
, aEmpty
, aOld
);
382 xComp
.set(localChild
, UNO_QUERY
);
386 m_bChildrenInitialized
= false;
389 void AccessibleBase::SetInfo( const AccessibleElementInfo
& rNewInfo
)
391 m_aAccInfo
= rNewInfo
;
392 if( m_bMayHaveChildren
)
396 BroadcastAccEvent( AccessibleEventId::INVALIDATE_ALL_CHILDREN
, uno::Any(), uno::Any());
399 // ________ (XComponent::dispose) ________
400 void SAL_CALL
AccessibleBase::disposing()
403 MutexGuard
aGuard(m_aMutex
);
404 OSL_ENSURE(!m_bIsDisposed
, "dispose() called twice");
406 // notify disposing to all AccessibleEvent listeners asynchronous
407 if (m_nEventNotifierId
)
409 ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(m_nEventNotifierId
,
411 m_nEventNotifierId
= 0;
415 m_aAccInfo
.m_pParent
= nullptr;
417 m_nStateSet
= AccessibleStateType::DEFUNC
;
419 m_bIsDisposed
= true;
422 // call listeners unguarded
424 if( m_bMayHaveChildren
)
429 OSL_ENSURE( m_aChildList
.empty(), "Child list should be empty" );
432 // ________ XAccessible ________
433 Reference
< XAccessibleContext
> SAL_CALL
AccessibleBase::getAccessibleContext()
438 // ________ AccessibleBase::XAccessibleContext ________
439 sal_Int64 SAL_CALL
AccessibleBase::getAccessibleChildCount()
441 ClearableMutexGuard
aGuard( m_aMutex
);
442 if( ! m_bMayHaveChildren
||
446 bool bMustUpdateChildren
= ( m_bMayHaveChildren
&&
447 ! m_bChildrenInitialized
);
452 if( bMustUpdateChildren
)
455 return ImplGetAccessibleChildCount();
458 sal_Int64
AccessibleBase::ImplGetAccessibleChildCount() const
460 return m_aChildList
.size();
463 Reference
< XAccessible
> SAL_CALL
AccessibleBase::getAccessibleChild( sal_Int64 i
)
466 Reference
< XAccessible
> xResult
;
468 ClearableMutexGuard
aGuard( m_aMutex
);
469 bool bMustUpdateChildren
= ( m_bMayHaveChildren
&&
470 ! m_bChildrenInitialized
);
474 if( bMustUpdateChildren
)
477 xResult
.set( ImplGetAccessibleChildById( i
));
482 Reference
< XAccessible
> AccessibleBase::ImplGetAccessibleChildById( sal_Int64 i
) const
484 Reference
< XAccessible
> xResult
;
486 MutexGuard
aGuard( m_aMutex
);
487 if( ! m_bMayHaveChildren
||
489 o3tl::make_unsigned( i
) >= m_aChildList
.size() )
491 OUString aBuf
= "Index " + OUString::number( i
) + " is invalid for range [ 0, " +
492 OUString::number( m_aChildList
.size() - 1 ) +
494 lang::IndexOutOfBoundsException
aEx( aBuf
,
495 const_cast< ::cppu::OWeakObject
* >(
496 static_cast< const ::cppu::OWeakObject
* >( this )));
500 xResult
.set( m_aChildList
[ i
] );
505 Reference
< XAccessible
> SAL_CALL
AccessibleBase::getAccessibleParent()
508 Reference
< XAccessible
> aResult
;
509 if( m_aAccInfo
.m_pParent
)
510 aResult
.set( m_aAccInfo
.m_pParent
);
515 sal_Int64 SAL_CALL
AccessibleBase::getAccessibleIndexInParent()
519 if( m_aAccInfo
.m_spObjectHierarchy
)
520 return m_aAccInfo
.m_spObjectHierarchy
->getIndexInParent( GetId() );
524 sal_Int16 SAL_CALL
AccessibleBase::getAccessibleRole()
526 return AccessibleRole::SHAPE
;
529 Reference
< XAccessibleRelationSet
> SAL_CALL
AccessibleBase::getAccessibleRelationSet()
531 Reference
< XAccessibleRelationSet
> aResult
;
535 sal_Int64 SAL_CALL
AccessibleBase::getAccessibleStateSet()
537 if( ! m_bStateSetInitialized
)
539 rtl::Reference
< ::chart::ChartController
> xSelSupp( GetInfo().m_xChartController
);
542 ObjectIdentifier
aOID( xSelSupp
->getSelection() );
543 if ( aOID
.isValid() && GetId() == aOID
)
545 AddState( AccessibleStateType::SELECTED
);
546 AddState( AccessibleStateType::FOCUSED
);
549 m_bStateSetInitialized
= true;
555 lang::Locale SAL_CALL
AccessibleBase::getLocale()
559 return Application::GetSettings().GetLanguageTag().getLocale();
562 // ________ AccessibleBase::XAccessibleComponent ________
563 sal_Bool SAL_CALL
AccessibleBase::containsPoint( const awt::Point
& aPoint
)
565 awt::Rectangle
aRect( getBounds() );
567 // contains() works with relative coordinates
571 return ( aPoint
.X
>= aRect
.X
&&
572 aPoint
.Y
>= aRect
.Y
&&
573 aPoint
.X
< (aRect
.X
+ aRect
.Width
) &&
574 aPoint
.Y
< (aRect
.Y
+ aRect
.Height
) );
577 Reference
< XAccessible
> SAL_CALL
AccessibleBase::getAccessibleAtPoint( const awt::Point
& aPoint
)
580 Reference
< XAccessible
> aResult
;
581 awt::Rectangle
aRect( getBounds());
583 // children are positioned relative to this object, so translate bound rect
587 // children must be inside the own bound rect
588 if( ( aRect
.X
<= aPoint
.X
&& aPoint
.X
<= (aRect
.X
+ aRect
.Width
) ) &&
589 ( aRect
.Y
<= aPoint
.Y
&& aPoint
.Y
<= (aRect
.Y
+ aRect
.Height
)))
591 ClearableMutexGuard
aGuard( m_aMutex
);
592 ChildListVectorType
aLocalChildList( m_aChildList
);
595 Reference
< XAccessibleComponent
> aComp
;
596 for (auto const& localChild
: aLocalChildList
)
598 aComp
.set(localChild
, UNO_QUERY
);
601 aRect
= aComp
->getBounds();
602 if( ( aRect
.X
<= aPoint
.X
&& aPoint
.X
<= (aRect
.X
+ aRect
.Width
) ) &&
603 ( aRect
.Y
<= aPoint
.Y
&& aPoint
.Y
<= (aRect
.Y
+ aRect
.Height
)))
605 aResult
= localChild
;
615 awt::Rectangle SAL_CALL
AccessibleBase::getBounds()
617 rtl::Reference
<ChartView
> pChartView
= m_aAccInfo
.m_xView
.get();
620 VclPtr
<vcl::Window
> pWindow( VCLUnoHelper::GetWindow( m_aAccInfo
.m_xWindow
));
621 awt::Rectangle
aLogicRect( pChartView
->getRectangleOfObject( m_aAccInfo
.m_aOID
.getObjectCID() ));
624 tools::Rectangle
aRect( aLogicRect
.X
, aLogicRect
.Y
,
625 aLogicRect
.X
+ aLogicRect
.Width
,
626 aLogicRect
.Y
+ aLogicRect
.Height
);
627 SolarMutexGuard aSolarGuard
;
628 aRect
= pWindow
->LogicToPixel( aRect
);
630 // aLogicRect is relative to the page, but we need a value relative
631 // to the parent object
632 awt::Point aParentLocOnScreen
;
633 uno::Reference
< XAccessibleComponent
> xParent( getAccessibleParent(), uno::UNO_QUERY
);
635 aParentLocOnScreen
= xParent
->getLocationOnScreen();
637 awt::Point aULOnScreen
= GetUpperLeftOnScreen();
638 awt::Point
aOffset( aParentLocOnScreen
.X
- aULOnScreen
.X
,
639 aParentLocOnScreen
.Y
- aULOnScreen
.Y
);
641 return awt::Rectangle( aRect
.Left() - aOffset
.X
, aRect
.Top() - aOffset
.Y
,
642 aRect
.getOpenWidth(), aRect
.getOpenHeight());
646 return awt::Rectangle();
649 awt::Point SAL_CALL
AccessibleBase::getLocation()
652 awt::Rectangle
aBBox( getBounds() );
653 return awt::Point( aBBox
.X
, aBBox
.Y
);
656 awt::Point SAL_CALL
AccessibleBase::getLocationOnScreen()
660 if (AccessibleBase
* pParent
= m_aAccInfo
.m_pParent
)
662 awt::Point
aLocThisRel( getLocation());
663 awt::Point
aUpperLeft(pParent
->getLocationOnScreen());
665 return awt::Point( aUpperLeft
.X
+ aLocThisRel
.X
,
666 aUpperLeft
.Y
+ aLocThisRel
.Y
);
669 return getLocation();
672 awt::Size SAL_CALL
AccessibleBase::getSize()
675 awt::Rectangle
aBBox( getBounds() );
676 return awt::Size( aBBox
.Width
, aBBox
.Height
);
679 void SAL_CALL
AccessibleBase::grabFocus()
683 rtl::Reference
< ::chart::ChartController
> xSelSupp( GetInfo().m_xChartController
);
686 xSelSupp
->select( GetId().getAny() );
690 sal_Int32 SAL_CALL
AccessibleBase::getForeground()
692 return sal_Int32(getColor( ACC_BASE_FOREGROUND
));
695 sal_Int32 SAL_CALL
AccessibleBase::getBackground()
697 return sal_Int32(getColor( ACC_BASE_BACKGROUND
));
700 Color
AccessibleBase::getColor( eColorType eColType
)
702 Color nResult
= COL_TRANSPARENT
;
703 if( m_bAlwaysTransparent
)
706 ObjectIdentifier
aOID( m_aAccInfo
.m_aOID
);
707 ObjectType
eType( aOID
.getObjectType() );
708 Reference
< beans::XPropertySet
> xObjProp
;
709 OUString aObjectCID
= aOID
.getObjectCID();
710 if( eType
== OBJECTTYPE_LEGEND_ENTRY
)
712 // for colors get the data series/point properties
713 std::u16string_view
aParentParticle( ObjectIdentifier::getFullParentParticle( aObjectCID
));
714 aObjectCID
= ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle
);
718 ObjectIdentifier::getObjectPropertySet(
719 aObjectCID
, m_aAccInfo
.m_xChartDocument
);
725 OUString aStylePropName
;
729 case OBJECTTYPE_LEGEND_ENTRY
:
730 case OBJECTTYPE_DATA_SERIES
:
731 case OBJECTTYPE_DATA_POINT
:
732 if( eColType
== ACC_BASE_FOREGROUND
)
734 aPropName
= "BorderColor";
735 aStylePropName
= "BorderTransparency";
740 aStylePropName
= "Transparency";
744 if( eColType
== ACC_BASE_FOREGROUND
)
746 aPropName
= "LineColor";
747 aStylePropName
= "LineTransparence";
751 aPropName
= "FillColor";
752 aStylePropName
= "FillTransparence";
757 bool bTransparent
= m_bAlwaysTransparent
;
758 Reference
< beans::XPropertySetInfo
> xInfo
= xObjProp
->getPropertySetInfo();
760 xInfo
->hasPropertyByName( aStylePropName
))
762 if( eColType
== ACC_BASE_FOREGROUND
)
764 drawing::LineStyle aLStyle
;
765 if( xObjProp
->getPropertyValue( aStylePropName
) >>= aLStyle
)
766 bTransparent
= (aLStyle
== drawing::LineStyle_NONE
);
770 drawing::FillStyle aFStyle
;
771 if( xObjProp
->getPropertyValue( aStylePropName
) >>= aFStyle
)
772 bTransparent
= (aFStyle
== drawing::FillStyle_NONE
);
778 xInfo
->hasPropertyByName( aPropName
))
780 xObjProp
->getPropertyValue( aPropName
) >>= nResult
;
783 catch( const uno::Exception
& )
785 DBG_UNHANDLED_EXCEPTION("chart2");
792 // ________ AccessibleBase::XServiceInfo ________
793 OUString SAL_CALL
AccessibleBase::getImplementationName()
795 return "AccessibleBase";
798 sal_Bool SAL_CALL
AccessibleBase::supportsService( const OUString
& ServiceName
)
800 return cppu::supportsService( this, ServiceName
);
803 uno::Sequence
< OUString
> SAL_CALL
AccessibleBase::getSupportedServiceNames()
806 "com.sun.star.accessibility.Accessible",
807 "com.sun.star.accessibility.AccessibleContext"
811 // ________ AccessibleBase::XEventListener ________
812 void SAL_CALL
AccessibleBase::disposing( const lang::EventObject
& /*Source*/ )
816 // ________ XAccessibleEventBroadcasters ________
817 void SAL_CALL
AccessibleBase::addAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
819 MutexGuard
aGuard( m_aMutex
);
821 if ( xListener
.is() )
823 if ( !m_nEventNotifierId
)
824 m_nEventNotifierId
= ::comphelper::AccessibleEventNotifier::registerClient();
826 ::comphelper::AccessibleEventNotifier::addEventListener( m_nEventNotifierId
, xListener
);
830 void SAL_CALL
AccessibleBase::removeAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
832 MutexGuard
aGuard( m_aMutex
);
834 if ( xListener
.is() && m_nEventNotifierId
)
836 sal_Int32 nListenerCount
= ::comphelper::AccessibleEventNotifier::removeEventListener( m_nEventNotifierId
, xListener
);
837 if ( !nListenerCount
)
839 // no listeners anymore
840 ::comphelper::AccessibleEventNotifier::revokeClient( m_nEventNotifierId
);
841 m_nEventNotifierId
= 0;
848 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */