Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / chart2 / source / controller / accessibility / AccessibleBase.cxx
blobcac25182d8e1ba8eb347d10775932f01a6512778
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/ExplicitValueProvider.hxx>
26 #include <com/sun/star/awt/XDevice.hpp>
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 <rtl/ustrbuf.hxx>
35 #include <vcl/svapp.hxx>
36 #include <rtl/uuid.h>
37 #include <cppuhelper/queryinterface.hxx>
38 #include <cppuhelper/supportsservice.hxx>
39 #include <svl/itemset.hxx>
40 #include <editeng/unofdesc.hxx>
41 #include <editeng/outliner.hxx>
42 #include <svx/svdoutl.hxx>
43 #include <svx/svdetc.hxx>
44 #include <svx/unoshape.hxx>
45 #include <svx/unoprov.hxx>
46 #include <vcl/unohelp.hxx>
47 #include <toolkit/helper/vclunohelper.hxx>
48 #include <vcl/window.hxx>
49 #include <vcl/graph.hxx>
50 #include <vcl/settings.hxx>
51 #include <o3tl/functional.hxx>
52 #include <tools/diagnose_ex.h>
54 #include <algorithm>
55 #include <iterator>
57 #include "ChartElementFactory.hxx"
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::accessibility;
62 using ::com::sun::star::uno::UNO_QUERY;
63 using ::com::sun::star::uno::Reference;
64 using ::osl::MutexGuard;
65 using ::osl::ClearableMutexGuard;
66 using ::osl::ResettableMutexGuard;
67 using ::com::sun::star::uno::RuntimeException;
68 using ::com::sun::star::uno::Any;
70 namespace chart
73 /** @param bMayHaveChildren is false per default
75 AccessibleBase::AccessibleBase(
76 const AccessibleElementInfo & rAccInfo,
77 bool bMayHaveChildren,
78 bool bAlwaysTransparent /* default: false */ ) :
79 impl::AccessibleBase_Base( m_aMutex ),
80 m_bIsDisposed( false ),
81 m_bMayHaveChildren( bMayHaveChildren ),
82 m_bChildrenInitialized( false ),
83 m_nEventNotifierId(0),
84 m_xStateSetHelper( new ::utl::AccessibleStateSetHelper() ),
85 m_aAccInfo( rAccInfo ),
86 m_bAlwaysTransparent( bAlwaysTransparent ),
87 m_bStateSetInitialized( false )
89 // initialize some states
90 OSL_ASSERT( m_xStateSetHelper.is() );
91 m_xStateSetHelper->AddState( AccessibleStateType::ENABLED );
92 m_xStateSetHelper->AddState( AccessibleStateType::SHOWING );
93 m_xStateSetHelper->AddState( AccessibleStateType::VISIBLE );
94 m_xStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
95 m_xStateSetHelper->AddState( AccessibleStateType::FOCUSABLE );
98 AccessibleBase::~AccessibleBase()
100 OSL_ASSERT( m_bIsDisposed );
103 bool AccessibleBase::CheckDisposeState( bool bThrowException /* default: true */ ) const
105 if( bThrowException &&
106 m_bIsDisposed )
108 throw lang::DisposedException("component has state DEFUNC",
109 static_cast< uno::XWeak * >( const_cast< AccessibleBase * >( this )));
111 return m_bIsDisposed;
114 bool AccessibleBase::NotifyEvent( EventType eEventType, const AccessibleUniqueId & rId )
116 if( GetId() == rId )
118 // event is addressed to this object
120 css::uno::Any aEmpty;
121 css::uno::Any aSelected;
122 aSelected <<= AccessibleStateType::SELECTED;
123 switch( eEventType )
125 case EventType::GOT_SELECTION:
127 AddState( AccessibleStateType::SELECTED );
128 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aSelected, aEmpty );
130 AddState( AccessibleStateType::FOCUSED );
131 aSelected <<= AccessibleStateType::FOCUSED;
132 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aSelected, aEmpty, true );
134 SAL_INFO("chart2.accessibility", "Selection acquired by: " << getAccessibleName());
136 break;
138 case EventType::LOST_SELECTION:
140 RemoveState( AccessibleStateType::SELECTED );
141 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aEmpty, aSelected );
143 AddState( AccessibleStateType::FOCUSED );
144 aSelected <<= AccessibleStateType::FOCUSED;
145 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aEmpty, aSelected, true );
146 SAL_INFO("chart2.accessibility", "Selection lost by: " << getAccessibleName());
148 break;
150 return true;
152 else if( m_bMayHaveChildren )
154 bool bStop = false;
156 ClearableMutexGuard aGuard( GetMutex() );
157 // make local copy for notification
158 ChildListVectorType aLocalChildList( m_aChildList );
159 aGuard.clear();
161 for (auto const& localChild : aLocalChildList)
163 // Note: at this place we must be sure to have an AccessibleBase
164 // object in the UNO reference to XAccessible !
165 bStop = (*static_cast< AccessibleBase * >
166 ( localChild.get() )).NotifyEvent( eEventType, rId );
167 if (bStop)
168 break;
170 return bStop;
173 return false;
176 void AccessibleBase::AddState( sal_Int16 aState )
178 CheckDisposeState();
179 OSL_ASSERT( m_xStateSetHelper.is() );
180 m_xStateSetHelper->AddState( aState );
183 void AccessibleBase::RemoveState( sal_Int16 aState )
185 CheckDisposeState();
186 OSL_ASSERT( m_xStateSetHelper.is() );
187 m_xStateSetHelper->RemoveState( aState );
190 bool AccessibleBase::UpdateChildren()
192 bool bMustUpdateChildren = false;
194 MutexGuard aGuard( GetMutex() );
195 if( ! m_bMayHaveChildren ||
196 m_bIsDisposed )
197 return false;
199 bMustUpdateChildren = ( m_bMayHaveChildren &&
200 ! m_bChildrenInitialized );
203 // update unguarded
204 if( bMustUpdateChildren )
205 m_bChildrenInitialized = ImplUpdateChildren();
207 return m_bChildrenInitialized;
210 bool AccessibleBase::ImplUpdateChildren()
212 bool bResult = false;
214 if( m_aAccInfo.m_spObjectHierarchy )
216 ObjectHierarchy::tChildContainer aModelChildren(
217 m_aAccInfo.m_spObjectHierarchy->getChildren( GetId() ));
218 std::vector< ChildOIDMap::key_type > aAccChildren;
219 aAccChildren.reserve( aModelChildren.size());
220 std::transform( m_aChildOIDMap.begin(), m_aChildOIDMap.end(),
221 std::back_inserter( aAccChildren ),
222 ::o3tl::select1st< ChildOIDMap::value_type >() );
224 std::sort( aModelChildren.begin(), aModelChildren.end());
226 std::vector< ObjectIdentifier > aChildrenToRemove, aChildrenToAdd;
227 std::set_difference( aModelChildren.begin(), aModelChildren.end(),
228 aAccChildren.begin(), aAccChildren.end(),
229 std::back_inserter( aChildrenToAdd ));
230 std::set_difference( aAccChildren.begin(), aAccChildren.end(),
231 aModelChildren.begin(), aModelChildren.end(),
232 std::back_inserter( aChildrenToRemove ));
234 for (auto const& childToRemove : aChildrenToRemove)
236 RemoveChildByOId(childToRemove);
239 AccessibleElementInfo aAccInfo( GetInfo());
240 aAccInfo.m_pParent = this;
242 for (auto const& childToAdd : aChildrenToAdd)
244 aAccInfo.m_aOID = childToAdd;
245 if ( childToAdd.isAutoGeneratedObject() )
247 AddChild( ChartElementFactory::CreateChartElement( aAccInfo ) );
249 else if ( childToAdd.isAdditionalShape() )
251 AddChild( new AccessibleChartShape( aAccInfo ) );
254 bResult = true;
257 return bResult;
260 void AccessibleBase::AddChild( AccessibleBase * pChild )
262 OSL_ENSURE( pChild != nullptr, "Invalid Child" );
263 if( pChild )
265 ClearableMutexGuard aGuard( GetMutex() );
267 Reference< XAccessible > xChild( pChild );
268 m_aChildList.push_back( xChild );
270 m_aChildOIDMap[ pChild->GetId() ] = xChild;
272 // inform listeners of new child
273 if( m_bChildrenInitialized )
275 Any aEmpty, aNew;
276 aNew <<= xChild;
278 aGuard.clear();
279 BroadcastAccEvent( AccessibleEventId::CHILD, aNew, aEmpty );
284 /** in this method we imply that the Reference< XAccessible > elements in the
285 vector are AccessibleBase objects !
287 void AccessibleBase::RemoveChildByOId( const ObjectIdentifier& rOId )
289 ClearableMutexGuard aGuard( GetMutex() );
291 ChildOIDMap::iterator aIt( m_aChildOIDMap.find( rOId ));
292 if( aIt != m_aChildOIDMap.end())
294 Reference< XAccessible > xChild( aIt->second );
296 // remove from map
297 m_aChildOIDMap.erase( aIt );
299 // search child in vector
300 ChildListVectorType::iterator aVecIter =
301 std::find( m_aChildList.begin(), m_aChildList.end(), xChild );
303 OSL_ENSURE( aVecIter != m_aChildList.end(),
304 "Inconsistent ChildMap" );
306 // remove child from vector
307 m_aChildList.erase( aVecIter );
308 bool bInitialized = m_bChildrenInitialized;
310 // call listeners unguarded
311 aGuard.clear();
313 // inform listeners of removed child
314 if( bInitialized )
316 Any aEmpty, aOld;
317 aOld <<= xChild;
319 BroadcastAccEvent( AccessibleEventId::CHILD, aEmpty, aOld );
322 // dispose the child
323 Reference< lang::XComponent > xComp( xChild, UNO_QUERY );
324 if( xComp.is())
325 xComp->dispose();
329 awt::Point AccessibleBase::GetUpperLeftOnScreen() const
331 awt::Point aResult;
332 if( m_aAccInfo.m_pParent )
334 ClearableMutexGuard aGuard( GetMutex() );
335 AccessibleBase * pParent = m_aAccInfo.m_pParent;
336 aGuard.clear();
338 if( pParent )
340 aResult = pParent->GetUpperLeftOnScreen();
342 else
343 OSL_FAIL( "Default position used is probably incorrect." );
346 return aResult;
349 void AccessibleBase::BroadcastAccEvent(
350 sal_Int16 nId,
351 const Any & rNew,
352 const Any & rOld,
353 bool bSendGlobally ) const
355 ClearableMutexGuard aGuard( GetMutex() );
357 if ( !m_nEventNotifierId && !bSendGlobally )
358 return;
359 // if we don't have a client id for the notifier, then we don't have listeners, then
360 // we don't need to notify anything
361 //except SendGlobally for focus handling?
363 // the const cast is needed, because UNO parameters are never const
364 const AccessibleEventObject aEvent(
365 const_cast< uno::XWeak * >( static_cast< const uno::XWeak * >( this )),
366 nId, rNew, rOld );
368 if ( m_nEventNotifierId ) // let the notifier handle this event
369 ::comphelper::AccessibleEventNotifier::addEvent( m_nEventNotifierId, aEvent );
371 aGuard.clear();
373 // send event to global message queue
374 if( bSendGlobally )
376 vcl::unohelper::NotifyAccessibleStateEventGlobally( aEvent );
380 void AccessibleBase::KillAllChildren()
382 ClearableMutexGuard aGuard( GetMutex() );
384 // make local copy for notification
385 ChildListVectorType aLocalChildList( m_aChildList );
387 // remove all children
388 m_aChildList.clear();
389 m_aChildOIDMap.clear();
391 aGuard.clear();
393 // call dispose for all children
394 // and notify listeners
395 Reference< lang::XComponent > xComp;
396 Any aEmpty, aOld;
397 for (auto const& localChild : aLocalChildList)
399 aOld <<= localChild;
400 BroadcastAccEvent( AccessibleEventId::CHILD, aEmpty, aOld );
402 xComp.set(localChild, UNO_QUERY);
403 if( xComp.is())
404 xComp->dispose();
406 m_bChildrenInitialized = false;
409 void AccessibleBase::SetInfo( const AccessibleElementInfo & rNewInfo )
411 m_aAccInfo = rNewInfo;
412 if( m_bMayHaveChildren )
414 KillAllChildren();
416 BroadcastAccEvent( AccessibleEventId::INVALIDATE_ALL_CHILDREN, uno::Any(), uno::Any(),
417 true /* global notification */ );
420 // ________ (XComponent::dispose) ________
421 void SAL_CALL AccessibleBase::disposing()
423 ClearableMutexGuard aGuard( GetMutex() );
424 OSL_ENSURE( ! m_bIsDisposed, "dispose() called twice" );
426 // notify disposing to all AccessibleEvent listeners asynchron
427 if ( m_nEventNotifierId )
429 ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( m_nEventNotifierId, *this );
430 m_nEventNotifierId = 0;
433 // reset pointers
434 m_aAccInfo.m_pParent = nullptr;
436 // attach new empty state set helper to member reference
437 ::utl::AccessibleStateSetHelper * pHelper = new ::utl::AccessibleStateSetHelper();
438 pHelper->AddState( AccessibleStateType::DEFUNC );
439 // release old helper and attach new one
440 m_xStateSetHelper = pHelper;
442 m_bIsDisposed = true;
444 // call listeners unguarded
445 aGuard.clear();
447 if( m_bMayHaveChildren )
449 KillAllChildren();
451 else
452 OSL_ENSURE( m_aChildList.empty(), "Child list should be empty" );
455 // ________ XAccessible ________
456 Reference< XAccessibleContext > SAL_CALL AccessibleBase::getAccessibleContext()
458 return this;
461 // ________ AccessibleBase::XAccessibleContext ________
462 sal_Int32 SAL_CALL AccessibleBase::getAccessibleChildCount()
464 ClearableMutexGuard aGuard( GetMutex() );
465 if( ! m_bMayHaveChildren ||
466 m_bIsDisposed )
467 return 0;
469 bool bMustUpdateChildren = ( m_bMayHaveChildren &&
470 ! m_bChildrenInitialized );
472 aGuard.clear();
474 // update unguarded
475 if( bMustUpdateChildren )
476 UpdateChildren();
478 return ImplGetAccessibleChildCount();
481 sal_Int32 AccessibleBase::ImplGetAccessibleChildCount() const
483 return m_aChildList.size();
486 Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleChild( sal_Int32 i )
488 CheckDisposeState();
489 Reference< XAccessible > xResult;
491 ResettableMutexGuard aGuard( GetMutex() );
492 bool bMustUpdateChildren = ( m_bMayHaveChildren &&
493 ! m_bChildrenInitialized );
495 aGuard.clear();
497 if( bMustUpdateChildren )
498 UpdateChildren();
500 xResult.set( ImplGetAccessibleChildById( i ));
502 return xResult;
505 Reference< XAccessible > AccessibleBase::ImplGetAccessibleChildById( sal_Int32 i ) const
507 Reference< XAccessible > xResult;
509 MutexGuard aGuard( GetMutex());
510 if( ! m_bMayHaveChildren ||
511 i < 0 ||
512 static_cast< ChildListVectorType::size_type >( i ) >= m_aChildList.size() )
514 OUString aBuf = "Index " + OUString::number( i ) + " is invalid for range [ 0, " +
515 OUString::number( m_aChildList.size() - 1 ) +
516 " ]";
517 lang::IndexOutOfBoundsException aEx( aBuf,
518 const_cast< ::cppu::OWeakObject * >(
519 static_cast< const ::cppu::OWeakObject * >( this )));
520 throw aEx;
522 else
523 xResult.set( m_aChildList[ i ] );
525 return xResult;
528 Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleParent()
530 CheckDisposeState();
531 Reference< XAccessible > aResult;
532 if( m_aAccInfo.m_pParent )
533 aResult.set( m_aAccInfo.m_pParent );
535 return aResult;
538 sal_Int32 SAL_CALL AccessibleBase::getAccessibleIndexInParent()
540 CheckDisposeState();
542 if( m_aAccInfo.m_spObjectHierarchy )
543 return m_aAccInfo.m_spObjectHierarchy->getIndexInParent( GetId() );
544 return -1;
547 sal_Int16 SAL_CALL AccessibleBase::getAccessibleRole()
549 return AccessibleRole::SHAPE;
552 Reference< XAccessibleRelationSet > SAL_CALL AccessibleBase::getAccessibleRelationSet()
554 Reference< XAccessibleRelationSet > aResult;
555 return aResult;
558 Reference< XAccessibleStateSet > SAL_CALL AccessibleBase::getAccessibleStateSet()
560 if( ! m_bStateSetInitialized )
562 Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier );
563 if ( xSelSupp.is() )
565 ObjectIdentifier aOID( xSelSupp->getSelection() );
566 if ( aOID.isValid() && GetId() == aOID )
568 AddState( AccessibleStateType::SELECTED );
569 AddState( AccessibleStateType::FOCUSED );
572 m_bStateSetInitialized = true;
575 return m_xStateSetHelper.get();
578 lang::Locale SAL_CALL AccessibleBase::getLocale()
580 CheckDisposeState();
582 return Application::GetSettings().GetLanguageTag().getLocale();
585 // ________ AccessibleBase::XAccessibleComponent ________
586 sal_Bool SAL_CALL AccessibleBase::containsPoint( const awt::Point& aPoint )
588 awt::Rectangle aRect( getBounds() );
590 // contains() works with relative coordinates
591 aRect.X = 0;
592 aRect.Y = 0;
594 return ( aPoint.X >= aRect.X &&
595 aPoint.Y >= aRect.Y &&
596 aPoint.X < (aRect.X + aRect.Width) &&
597 aPoint.Y < (aRect.Y + aRect.Height) );
600 Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleAtPoint( const awt::Point& aPoint )
602 CheckDisposeState();
603 Reference< XAccessible > aResult;
604 awt::Rectangle aRect( getBounds());
606 // children are positioned relative to this object, so translate bound rect
607 aRect.X = 0;
608 aRect.Y = 0;
610 // children must be inside the own bound rect
611 if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) &&
612 ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height)))
614 ClearableMutexGuard aGuard( GetMutex() );
615 ChildListVectorType aLocalChildList( m_aChildList );
616 aGuard.clear();
618 Reference< XAccessibleComponent > aComp;
619 for (auto const& localChild : aLocalChildList)
621 aComp.set(localChild, UNO_QUERY);
622 if( aComp.is())
624 aRect = aComp->getBounds();
625 if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) &&
626 ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height)))
628 aResult = localChild;
629 break;
635 return aResult;
638 awt::Rectangle SAL_CALL AccessibleBase::getBounds()
640 ExplicitValueProvider *pExplicitValueProvider(
641 ExplicitValueProvider::getExplicitValueProvider( m_aAccInfo.m_xView ));
642 if( pExplicitValueProvider )
644 VclPtr<vcl::Window> pWindow( VCLUnoHelper::GetWindow( m_aAccInfo.m_xWindow ));
645 awt::Rectangle aLogicRect( pExplicitValueProvider->getRectangleOfObject( m_aAccInfo.m_aOID.getObjectCID() ));
646 if( pWindow )
648 tools::Rectangle aRect( aLogicRect.X, aLogicRect.Y,
649 aLogicRect.X + aLogicRect.Width,
650 aLogicRect.Y + aLogicRect.Height );
651 SolarMutexGuard aSolarGuard;
652 aRect = pWindow->LogicToPixel( aRect );
654 // aLogicRect is relative to the page, but we need a value relative
655 // to the parent object
656 awt::Point aParentLocOnScreen;
657 uno::Reference< XAccessibleComponent > xParent( getAccessibleParent(), uno::UNO_QUERY );
658 if( xParent.is() )
659 aParentLocOnScreen = xParent->getLocationOnScreen();
661 awt::Point aULOnScreen = GetUpperLeftOnScreen();
662 awt::Point aOffset( aParentLocOnScreen.X - aULOnScreen.X,
663 aParentLocOnScreen.Y - aULOnScreen.Y );
665 return awt::Rectangle( aRect.getX() - aOffset.X, aRect.getY() - aOffset.Y,
666 aRect.getWidth(), aRect.getHeight());
670 return awt::Rectangle();
673 awt::Point SAL_CALL AccessibleBase::getLocation()
675 CheckDisposeState();
676 awt::Rectangle aBBox( getBounds() );
677 return awt::Point( aBBox.X, aBBox.Y );
680 awt::Point SAL_CALL AccessibleBase::getLocationOnScreen()
682 CheckDisposeState();
684 if( m_aAccInfo.m_pParent != nullptr )
686 AccessibleBase * pParent = m_aAccInfo.m_pParent;
687 awt::Point aLocThisRel( getLocation());
688 awt::Point aUpperLeft;
690 if( pParent != nullptr )
691 aUpperLeft = pParent->getLocationOnScreen();
693 return awt::Point( aUpperLeft.X + aLocThisRel.X,
694 aUpperLeft.Y + aLocThisRel.Y );
696 else
697 return getLocation();
700 awt::Size SAL_CALL AccessibleBase::getSize()
702 CheckDisposeState();
703 awt::Rectangle aBBox( getBounds() );
704 return awt::Size( aBBox.Width, aBBox.Height );
707 void SAL_CALL AccessibleBase::grabFocus()
709 CheckDisposeState();
711 Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier );
712 if ( xSelSupp.is() )
714 xSelSupp->select( GetId().getAny() );
718 sal_Int32 SAL_CALL AccessibleBase::getForeground()
720 return sal_Int32(getColor( ACC_BASE_FOREGROUND ));
723 sal_Int32 SAL_CALL AccessibleBase::getBackground()
725 return sal_Int32(getColor( ACC_BASE_BACKGROUND ));
728 Color AccessibleBase::getColor( eColorType eColType )
730 Color nResult = COL_TRANSPARENT;
731 if( m_bAlwaysTransparent )
732 return nResult;
734 ObjectIdentifier aOID( m_aAccInfo.m_aOID );
735 ObjectType eType( aOID.getObjectType() );
736 Reference< beans::XPropertySet > xObjProp;
737 OUString aObjectCID = aOID.getObjectCID();
738 if( eType == OBJECTTYPE_LEGEND_ENTRY )
740 // for colors get the data series/point properties
741 OUString aParentParticle( ObjectIdentifier::getFullParentParticle( aObjectCID ));
742 aObjectCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle );
745 xObjProp.set(
746 ObjectIdentifier::getObjectPropertySet(
747 aObjectCID, Reference< chart2::XChartDocument >( m_aAccInfo.m_xChartDocument )), uno::UNO_QUERY );
748 if( xObjProp.is())
752 OUString aPropName;
753 OUString aStylePropName;
755 switch( eType )
757 case OBJECTTYPE_LEGEND_ENTRY:
758 case OBJECTTYPE_DATA_SERIES:
759 case OBJECTTYPE_DATA_POINT:
760 if( eColType == ACC_BASE_FOREGROUND )
762 aPropName = "BorderColor";
763 aStylePropName = "BorderTransparency";
765 else
767 aPropName = "Color";
768 aStylePropName = "Transparency";
770 break;
771 default:
772 if( eColType == ACC_BASE_FOREGROUND )
774 aPropName = "LineColor";
775 aStylePropName = "LineTransparence";
777 else
779 aPropName = "FillColor";
780 aStylePropName = "FillTransparence";
782 break;
785 bool bTransparent = m_bAlwaysTransparent;
786 Reference< beans::XPropertySetInfo > xInfo( xObjProp->getPropertySetInfo(), uno::UNO_QUERY );
787 if( xInfo.is() &&
788 xInfo->hasPropertyByName( aStylePropName ))
790 if( eColType == ACC_BASE_FOREGROUND )
792 drawing::LineStyle aLStyle;
793 if( xObjProp->getPropertyValue( aStylePropName ) >>= aLStyle )
794 bTransparent = (aLStyle == drawing::LineStyle_NONE);
796 else
798 drawing::FillStyle aFStyle;
799 if( xObjProp->getPropertyValue( aStylePropName ) >>= aFStyle )
800 bTransparent = (aFStyle == drawing::FillStyle_NONE);
804 if( !bTransparent &&
805 xInfo.is() &&
806 xInfo->hasPropertyByName( aPropName ))
808 xObjProp->getPropertyValue( aPropName ) >>= nResult;
811 catch( const uno::Exception & )
813 DBG_UNHANDLED_EXCEPTION("chart2");
817 return nResult;
820 // ________ AccessibleBase::XServiceInfo ________
821 OUString SAL_CALL AccessibleBase::getImplementationName()
823 return OUString( "AccessibleBase" );
826 sal_Bool SAL_CALL AccessibleBase::supportsService( const OUString& ServiceName )
828 return cppu::supportsService( this, ServiceName );
831 uno::Sequence< OUString > SAL_CALL AccessibleBase::getSupportedServiceNames()
833 return {
834 "com.sun.star.accessibility.Accessible",
835 "com.sun.star.accessibility.AccessibleContext"
839 // ________ AccessibleBase::XEventListener ________
840 void SAL_CALL AccessibleBase::disposing( const lang::EventObject& /*Source*/ )
844 // ________ XAccessibleEventBroadcasters ________
845 void SAL_CALL AccessibleBase::addAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
847 MutexGuard aGuard( GetMutex() );
849 if ( xListener.is() )
851 if ( !m_nEventNotifierId )
852 m_nEventNotifierId = ::comphelper::AccessibleEventNotifier::registerClient();
854 ::comphelper::AccessibleEventNotifier::addEventListener( m_nEventNotifierId, xListener );
858 void SAL_CALL AccessibleBase::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
860 MutexGuard aGuard( GetMutex() );
862 if ( xListener.is() && m_nEventNotifierId)
864 sal_Int32 nListenerCount = ::comphelper::AccessibleEventNotifier::removeEventListener( m_nEventNotifierId, xListener );
865 if ( !nListenerCount )
867 // no listeners anymore
868 ::comphelper::AccessibleEventNotifier::revokeClient( m_nEventNotifierId );
869 m_nEventNotifierId = 0;
874 } // namespace chart
876 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */