diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /chart2/source/controller/accessibility/AccessibleBase.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'chart2/source/controller/accessibility/AccessibleBase.cxx')
-rw-r--r-- | chart2/source/controller/accessibility/AccessibleBase.cxx | 854 |
1 files changed, 854 insertions, 0 deletions
diff --git a/chart2/source/controller/accessibility/AccessibleBase.cxx b/chart2/source/controller/accessibility/AccessibleBase.cxx new file mode 100644 index 000000000..4e8b20574 --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleBase.cxx @@ -0,0 +1,854 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <AccessibleBase.hxx> +#include "AccessibleChartShape.hxx" +#include <ObjectHierarchy.hxx> +#include <ObjectIdentifier.hxx> +#include <chartview/ExplicitValueProvider.hxx> + +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleEventObject.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <sal/log.hxx> +#include <vcl/svapp.hxx> +#include <comphelper/servicehelper.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/window.hxx> +#include <vcl/settings.hxx> +#include <o3tl/functional.hxx> +#include <o3tl/safeint.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/accessiblestatesethelper.hxx> + +#include <algorithm> +#include <iterator> + +#include "ChartElementFactory.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::Reference; +using ::osl::MutexGuard; +using ::osl::ClearableMutexGuard; +using ::com::sun::star::uno::Any; + +namespace chart +{ + +/** @param bMayHaveChildren is false per default + */ +AccessibleBase::AccessibleBase( + const AccessibleElementInfo & rAccInfo, + bool bMayHaveChildren, + bool bAlwaysTransparent /* default: false */ ) : + impl::AccessibleBase_Base( m_aMutex ), + m_bIsDisposed( false ), + m_bMayHaveChildren( bMayHaveChildren ), + m_bChildrenInitialized( false ), + m_nEventNotifierId(0), + m_xStateSetHelper( new ::utl::AccessibleStateSetHelper() ), + m_aAccInfo( rAccInfo ), + m_bAlwaysTransparent( bAlwaysTransparent ), + m_bStateSetInitialized( false ) +{ + // initialize some states + OSL_ASSERT( m_xStateSetHelper.is() ); + m_xStateSetHelper->AddState( AccessibleStateType::ENABLED ); + m_xStateSetHelper->AddState( AccessibleStateType::SHOWING ); + m_xStateSetHelper->AddState( AccessibleStateType::VISIBLE ); + m_xStateSetHelper->AddState( AccessibleStateType::SELECTABLE ); + m_xStateSetHelper->AddState( AccessibleStateType::FOCUSABLE ); +} + +AccessibleBase::~AccessibleBase() +{ + OSL_ASSERT( m_bIsDisposed ); +} + +bool AccessibleBase::CheckDisposeState( bool bThrowException /* default: true */ ) const +{ + if( bThrowException && + m_bIsDisposed ) + { + throw lang::DisposedException("component has state DEFUNC", + static_cast< uno::XWeak * >( const_cast< AccessibleBase * >( this ))); + } + return m_bIsDisposed; +} + +bool AccessibleBase::NotifyEvent( EventType eEventType, const AccessibleUniqueId & rId ) +{ + if( GetId() == rId ) + { + // event is addressed to this object + + css::uno::Any aEmpty; + css::uno::Any aSelected; + aSelected <<= AccessibleStateType::SELECTED; + switch( eEventType ) + { + case EventType::GOT_SELECTION: + { + AddState( AccessibleStateType::SELECTED ); + BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aSelected, aEmpty ); + + AddState( AccessibleStateType::FOCUSED ); + aSelected <<= AccessibleStateType::FOCUSED; + BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aSelected, aEmpty ); + + SAL_INFO("chart2.accessibility", "Selection acquired by: " << getAccessibleName()); + } + break; + + case EventType::LOST_SELECTION: + { + RemoveState( AccessibleStateType::SELECTED ); + BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aEmpty, aSelected ); + + AddState( AccessibleStateType::FOCUSED ); + aSelected <<= AccessibleStateType::FOCUSED; + BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aEmpty, aSelected ); + SAL_INFO("chart2.accessibility", "Selection lost by: " << getAccessibleName()); + } + break; + } + return true; + } + else if( m_bMayHaveChildren ) + { + bool bStop = false; + + ClearableMutexGuard aGuard( m_aMutex ); + // make local copy for notification + ChildListVectorType aLocalChildList( m_aChildList ); + aGuard.clear(); + + for (auto const& localChild : aLocalChildList) + { + // Note: at this place we must be sure to have an AccessibleBase + // object in the UNO reference to XAccessible ! + bStop = (*static_cast< AccessibleBase * > + ( localChild.get() )).NotifyEvent( eEventType, rId ); + if (bStop) + break; + } + return bStop; + } + + return false; +} + +void AccessibleBase::AddState( sal_Int16 aState ) +{ + CheckDisposeState(); + OSL_ASSERT( m_xStateSetHelper.is() ); + m_xStateSetHelper->AddState( aState ); +} + +void AccessibleBase::RemoveState( sal_Int16 aState ) +{ + CheckDisposeState(); + OSL_ASSERT( m_xStateSetHelper.is() ); + m_xStateSetHelper->RemoveState( aState ); +} + +bool AccessibleBase::UpdateChildren() +{ + bool bMustUpdateChildren = false; + { + MutexGuard aGuard( m_aMutex ); + if( ! m_bMayHaveChildren || + m_bIsDisposed ) + return false; + + bMustUpdateChildren = ( m_bMayHaveChildren && + ! m_bChildrenInitialized ); + } + + // update unguarded + if( bMustUpdateChildren ) + m_bChildrenInitialized = ImplUpdateChildren(); + + return m_bChildrenInitialized; +} + +bool AccessibleBase::ImplUpdateChildren() +{ + bool bResult = false; + + if( m_aAccInfo.m_spObjectHierarchy ) + { + ObjectHierarchy::tChildContainer aModelChildren( + m_aAccInfo.m_spObjectHierarchy->getChildren( GetId() )); + std::vector< ChildOIDMap::key_type > aAccChildren; + aAccChildren.reserve( aModelChildren.size()); + std::transform( m_aChildOIDMap.begin(), m_aChildOIDMap.end(), + std::back_inserter( aAccChildren ), + ::o3tl::select1st< ChildOIDMap::value_type >() ); + + std::sort( aModelChildren.begin(), aModelChildren.end()); + + std::vector< ObjectIdentifier > aChildrenToRemove, aChildrenToAdd; + std::set_difference( aModelChildren.begin(), aModelChildren.end(), + aAccChildren.begin(), aAccChildren.end(), + std::back_inserter( aChildrenToAdd )); + std::set_difference( aAccChildren.begin(), aAccChildren.end(), + aModelChildren.begin(), aModelChildren.end(), + std::back_inserter( aChildrenToRemove )); + + for (auto const& childToRemove : aChildrenToRemove) + { + RemoveChildByOId(childToRemove); + } + + AccessibleElementInfo aAccInfo( GetInfo()); + aAccInfo.m_pParent = this; + + for (auto const& childToAdd : aChildrenToAdd) + { + aAccInfo.m_aOID = childToAdd; + if ( childToAdd.isAutoGeneratedObject() ) + { + AddChild( ChartElementFactory::CreateChartElement( aAccInfo ).get() ); + } + else if ( childToAdd.isAdditionalShape() ) + { + AddChild( new AccessibleChartShape( aAccInfo ) ); + } + } + bResult = true; + } + + return bResult; +} + +void AccessibleBase::AddChild( AccessibleBase * pChild ) +{ + OSL_ENSURE( pChild != nullptr, "Invalid Child" ); + if( !pChild ) + return; + + ClearableMutexGuard aGuard( m_aMutex ); + + Reference< XAccessible > xChild( pChild ); + m_aChildList.push_back( xChild ); + + m_aChildOIDMap[ pChild->GetId() ] = xChild; + + // inform listeners of new child + if( m_bChildrenInitialized ) + { + Any aEmpty, aNew; + aNew <<= xChild; + + aGuard.clear(); + BroadcastAccEvent( AccessibleEventId::CHILD, aNew, aEmpty ); + } +} + +/** in this method we imply that the Reference< XAccessible > elements in the + vector are AccessibleBase objects ! + */ +void AccessibleBase::RemoveChildByOId( const ObjectIdentifier& rOId ) +{ + ClearableMutexGuard aGuard( m_aMutex ); + + ChildOIDMap::iterator aIt( m_aChildOIDMap.find( rOId )); + if( aIt == m_aChildOIDMap.end()) + return; + + Reference< XAccessible > xChild( aIt->second ); + + // remove from map + m_aChildOIDMap.erase( aIt ); + + // search child in vector + ChildListVectorType::iterator aVecIter = + std::find( m_aChildList.begin(), m_aChildList.end(), xChild ); + + OSL_ENSURE( aVecIter != m_aChildList.end(), + "Inconsistent ChildMap" ); + + // remove child from vector + m_aChildList.erase( aVecIter ); + bool bInitialized = m_bChildrenInitialized; + + // call listeners unguarded + aGuard.clear(); + + // inform listeners of removed child + if( bInitialized ) + { + Any aEmpty, aOld; + aOld <<= xChild; + + BroadcastAccEvent( AccessibleEventId::CHILD, aEmpty, aOld ); + } + + // dispose the child + Reference< lang::XComponent > xComp( xChild, UNO_QUERY ); + if( xComp.is()) + xComp->dispose(); +} + +awt::Point AccessibleBase::GetUpperLeftOnScreen() const +{ + awt::Point aResult; + if( m_aAccInfo.m_pParent ) + { + ClearableMutexGuard aGuard( m_aMutex ); + AccessibleBase * pParent = m_aAccInfo.m_pParent; + aGuard.clear(); + + if( pParent ) + { + aResult = pParent->GetUpperLeftOnScreen(); + } + else + OSL_FAIL( "Default position used is probably incorrect." ); + } + + return aResult; +} + +void AccessibleBase::BroadcastAccEvent( + sal_Int16 nId, + const Any & rNew, + const Any & rOld ) const +{ + ClearableMutexGuard aGuard( m_aMutex ); + + if ( !m_nEventNotifierId ) + return; + // if we don't have a client id for the notifier, then we don't have listeners, then + // we don't need to notify anything + + // the const cast is needed, because UNO parameters are never const + const AccessibleEventObject aEvent( + const_cast< uno::XWeak * >( static_cast< const uno::XWeak * >( this )), + nId, rNew, rOld ); + + // let the notifier handle this event + ::comphelper::AccessibleEventNotifier::addEvent( m_nEventNotifierId, aEvent ); + + aGuard.clear(); +} + +void AccessibleBase::KillAllChildren() +{ + ClearableMutexGuard aGuard( m_aMutex ); + + // make local copy for notification, and remove all children + ChildListVectorType aLocalChildList; + aLocalChildList.swap( m_aChildList ); + m_aChildOIDMap.clear(); + + aGuard.clear(); + + // call dispose for all children + // and notify listeners + Reference< lang::XComponent > xComp; + Any aEmpty, aOld; + for (auto const& localChild : aLocalChildList) + { + aOld <<= localChild; + BroadcastAccEvent( AccessibleEventId::CHILD, aEmpty, aOld ); + + xComp.set(localChild, UNO_QUERY); + if( xComp.is()) + xComp->dispose(); + } + m_bChildrenInitialized = false; +} + +void AccessibleBase::SetInfo( const AccessibleElementInfo & rNewInfo ) +{ + m_aAccInfo = rNewInfo; + if( m_bMayHaveChildren ) + { + KillAllChildren(); + } + BroadcastAccEvent( AccessibleEventId::INVALIDATE_ALL_CHILDREN, uno::Any(), uno::Any()); +} + +// ________ (XComponent::dispose) ________ +void SAL_CALL AccessibleBase::disposing() +{ + { + MutexGuard aGuard(m_aMutex); + OSL_ENSURE(!m_bIsDisposed, "dispose() called twice"); + + // notify disposing to all AccessibleEvent listeners asynchronous + if (m_nEventNotifierId) + { + ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(m_nEventNotifierId, + *this); + m_nEventNotifierId = 0; + } + + // reset pointers + m_aAccInfo.m_pParent = nullptr; + + // attach new empty state set helper to member reference + rtl::Reference<::utl::AccessibleStateSetHelper> pHelper = new ::utl::AccessibleStateSetHelper(); + pHelper->AddState(AccessibleStateType::DEFUNC); + // release old helper and attach new one + m_xStateSetHelper = pHelper; + + m_bIsDisposed = true; + + } + // call listeners unguarded + + if( m_bMayHaveChildren ) + { + KillAllChildren(); + } + else + OSL_ENSURE( m_aChildList.empty(), "Child list should be empty" ); +} + +// ________ XAccessible ________ +Reference< XAccessibleContext > SAL_CALL AccessibleBase::getAccessibleContext() +{ + return this; +} + +// ________ AccessibleBase::XAccessibleContext ________ +sal_Int32 SAL_CALL AccessibleBase::getAccessibleChildCount() +{ + ClearableMutexGuard aGuard( m_aMutex ); + if( ! m_bMayHaveChildren || + m_bIsDisposed ) + return 0; + + bool bMustUpdateChildren = ( m_bMayHaveChildren && + ! m_bChildrenInitialized ); + + aGuard.clear(); + + // update unguarded + if( bMustUpdateChildren ) + UpdateChildren(); + + return ImplGetAccessibleChildCount(); +} + +sal_Int32 AccessibleBase::ImplGetAccessibleChildCount() const +{ + return m_aChildList.size(); +} + +Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleChild( sal_Int32 i ) +{ + CheckDisposeState(); + Reference< XAccessible > xResult; + + ClearableMutexGuard aGuard( m_aMutex ); + bool bMustUpdateChildren = ( m_bMayHaveChildren && + ! m_bChildrenInitialized ); + + aGuard.clear(); + + if( bMustUpdateChildren ) + UpdateChildren(); + + xResult.set( ImplGetAccessibleChildById( i )); + + return xResult; +} + +Reference< XAccessible > AccessibleBase::ImplGetAccessibleChildById( sal_Int32 i ) const +{ + Reference< XAccessible > xResult; + + MutexGuard aGuard( m_aMutex); + if( ! m_bMayHaveChildren || + i < 0 || + o3tl::make_unsigned( i ) >= m_aChildList.size() ) + { + OUString aBuf = "Index " + OUString::number( i ) + " is invalid for range [ 0, " + + OUString::number( m_aChildList.size() - 1 ) + + " ]"; + lang::IndexOutOfBoundsException aEx( aBuf, + const_cast< ::cppu::OWeakObject * >( + static_cast< const ::cppu::OWeakObject * >( this ))); + throw aEx; + } + else + xResult.set( m_aChildList[ i ] ); + + return xResult; +} + +Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleParent() +{ + CheckDisposeState(); + Reference< XAccessible > aResult; + if( m_aAccInfo.m_pParent ) + aResult.set( m_aAccInfo.m_pParent ); + + return aResult; +} + +sal_Int32 SAL_CALL AccessibleBase::getAccessibleIndexInParent() +{ + CheckDisposeState(); + + if( m_aAccInfo.m_spObjectHierarchy ) + return m_aAccInfo.m_spObjectHierarchy->getIndexInParent( GetId() ); + return -1; +} + +sal_Int16 SAL_CALL AccessibleBase::getAccessibleRole() +{ + return AccessibleRole::SHAPE; +} + +Reference< XAccessibleRelationSet > SAL_CALL AccessibleBase::getAccessibleRelationSet() +{ + Reference< XAccessibleRelationSet > aResult; + return aResult; +} + +Reference< XAccessibleStateSet > SAL_CALL AccessibleBase::getAccessibleStateSet() +{ + if( ! m_bStateSetInitialized ) + { + Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier ); + if ( xSelSupp.is() ) + { + ObjectIdentifier aOID( xSelSupp->getSelection() ); + if ( aOID.isValid() && GetId() == aOID ) + { + AddState( AccessibleStateType::SELECTED ); + AddState( AccessibleStateType::FOCUSED ); + } + } + m_bStateSetInitialized = true; + } + + return m_xStateSetHelper; +} + +lang::Locale SAL_CALL AccessibleBase::getLocale() +{ + CheckDisposeState(); + + return Application::GetSettings().GetLanguageTag().getLocale(); +} + +// ________ AccessibleBase::XAccessibleComponent ________ +sal_Bool SAL_CALL AccessibleBase::containsPoint( const awt::Point& aPoint ) +{ + awt::Rectangle aRect( getBounds() ); + + // contains() works with relative coordinates + aRect.X = 0; + aRect.Y = 0; + + return ( aPoint.X >= aRect.X && + aPoint.Y >= aRect.Y && + aPoint.X < (aRect.X + aRect.Width) && + aPoint.Y < (aRect.Y + aRect.Height) ); +} + +Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleAtPoint( const awt::Point& aPoint ) +{ + CheckDisposeState(); + Reference< XAccessible > aResult; + awt::Rectangle aRect( getBounds()); + + // children are positioned relative to this object, so translate bound rect + aRect.X = 0; + aRect.Y = 0; + + // children must be inside the own bound rect + if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) && + ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height))) + { + ClearableMutexGuard aGuard( m_aMutex ); + ChildListVectorType aLocalChildList( m_aChildList ); + aGuard.clear(); + + Reference< XAccessibleComponent > aComp; + for (auto const& localChild : aLocalChildList) + { + aComp.set(localChild, UNO_QUERY); + if( aComp.is()) + { + aRect = aComp->getBounds(); + if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) && + ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height))) + { + aResult = localChild; + break; + } + } + } + } + + return aResult; +} + +awt::Rectangle SAL_CALL AccessibleBase::getBounds() +{ + ExplicitValueProvider *pExplicitValueProvider( + comphelper::getFromUnoTunnel<ExplicitValueProvider>( m_aAccInfo.m_xView )); + if( pExplicitValueProvider ) + { + VclPtr<vcl::Window> pWindow( VCLUnoHelper::GetWindow( m_aAccInfo.m_xWindow )); + awt::Rectangle aLogicRect( pExplicitValueProvider->getRectangleOfObject( m_aAccInfo.m_aOID.getObjectCID() )); + if( pWindow ) + { + tools::Rectangle aRect( aLogicRect.X, aLogicRect.Y, + aLogicRect.X + aLogicRect.Width, + aLogicRect.Y + aLogicRect.Height ); + SolarMutexGuard aSolarGuard; + aRect = pWindow->LogicToPixel( aRect ); + + // aLogicRect is relative to the page, but we need a value relative + // to the parent object + awt::Point aParentLocOnScreen; + uno::Reference< XAccessibleComponent > xParent( getAccessibleParent(), uno::UNO_QUERY ); + if( xParent.is() ) + aParentLocOnScreen = xParent->getLocationOnScreen(); + + awt::Point aULOnScreen = GetUpperLeftOnScreen(); + awt::Point aOffset( aParentLocOnScreen.X - aULOnScreen.X, + aParentLocOnScreen.Y - aULOnScreen.Y ); + + return awt::Rectangle( aRect.Left() - aOffset.X, aRect.Top() - aOffset.Y, + aRect.getWidth(), aRect.getHeight()); + } + } + + return awt::Rectangle(); +} + +awt::Point SAL_CALL AccessibleBase::getLocation() +{ + CheckDisposeState(); + awt::Rectangle aBBox( getBounds() ); + return awt::Point( aBBox.X, aBBox.Y ); +} + +awt::Point SAL_CALL AccessibleBase::getLocationOnScreen() +{ + CheckDisposeState(); + + if (AccessibleBase* pParent = m_aAccInfo.m_pParent) + { + awt::Point aLocThisRel( getLocation()); + awt::Point aUpperLeft(pParent->getLocationOnScreen()); + + return awt::Point( aUpperLeft.X + aLocThisRel.X, + aUpperLeft.Y + aLocThisRel.Y ); + } + else + return getLocation(); +} + +awt::Size SAL_CALL AccessibleBase::getSize() +{ + CheckDisposeState(); + awt::Rectangle aBBox( getBounds() ); + return awt::Size( aBBox.Width, aBBox.Height ); +} + +void SAL_CALL AccessibleBase::grabFocus() +{ + CheckDisposeState(); + + Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier ); + if ( xSelSupp.is() ) + { + xSelSupp->select( GetId().getAny() ); + } +} + +sal_Int32 SAL_CALL AccessibleBase::getForeground() +{ + return sal_Int32(getColor( ACC_BASE_FOREGROUND )); +} + +sal_Int32 SAL_CALL AccessibleBase::getBackground() +{ + return sal_Int32(getColor( ACC_BASE_BACKGROUND )); +} + +Color AccessibleBase::getColor( eColorType eColType ) +{ + Color nResult = COL_TRANSPARENT; + if( m_bAlwaysTransparent ) + return nResult; + + ObjectIdentifier aOID( m_aAccInfo.m_aOID ); + ObjectType eType( aOID.getObjectType() ); + Reference< beans::XPropertySet > xObjProp; + OUString aObjectCID = aOID.getObjectCID(); + if( eType == OBJECTTYPE_LEGEND_ENTRY ) + { + // for colors get the data series/point properties + std::u16string_view aParentParticle( ObjectIdentifier::getFullParentParticle( aObjectCID )); + aObjectCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle ); + } + + xObjProp = + ObjectIdentifier::getObjectPropertySet( + aObjectCID, m_aAccInfo.m_xChartDocument ); + if( xObjProp.is()) + { + try + { + OUString aPropName; + OUString aStylePropName; + + switch( eType ) + { + case OBJECTTYPE_LEGEND_ENTRY: + case OBJECTTYPE_DATA_SERIES: + case OBJECTTYPE_DATA_POINT: + if( eColType == ACC_BASE_FOREGROUND ) + { + aPropName = "BorderColor"; + aStylePropName = "BorderTransparency"; + } + else + { + aPropName = "Color"; + aStylePropName = "Transparency"; + } + break; + default: + if( eColType == ACC_BASE_FOREGROUND ) + { + aPropName = "LineColor"; + aStylePropName = "LineTransparence"; + } + else + { + aPropName = "FillColor"; + aStylePropName = "FillTransparence"; + } + break; + } + + bool bTransparent = m_bAlwaysTransparent; + Reference< beans::XPropertySetInfo > xInfo = xObjProp->getPropertySetInfo(); + if( xInfo.is() && + xInfo->hasPropertyByName( aStylePropName )) + { + if( eColType == ACC_BASE_FOREGROUND ) + { + drawing::LineStyle aLStyle; + if( xObjProp->getPropertyValue( aStylePropName ) >>= aLStyle ) + bTransparent = (aLStyle == drawing::LineStyle_NONE); + } + else + { + drawing::FillStyle aFStyle; + if( xObjProp->getPropertyValue( aStylePropName ) >>= aFStyle ) + bTransparent = (aFStyle == drawing::FillStyle_NONE); + } + } + + if( !bTransparent && + xInfo.is() && + xInfo->hasPropertyByName( aPropName )) + { + xObjProp->getPropertyValue( aPropName ) >>= nResult; + } + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } + } + + return nResult; +} + +// ________ AccessibleBase::XServiceInfo ________ +OUString SAL_CALL AccessibleBase::getImplementationName() +{ + return "AccessibleBase"; +} + +sal_Bool SAL_CALL AccessibleBase::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName ); +} + +uno::Sequence< OUString > SAL_CALL AccessibleBase::getSupportedServiceNames() +{ + return { + "com.sun.star.accessibility.Accessible", + "com.sun.star.accessibility.AccessibleContext" + }; +} + +// ________ AccessibleBase::XEventListener ________ +void SAL_CALL AccessibleBase::disposing( const lang::EventObject& /*Source*/ ) +{ +} + +// ________ XAccessibleEventBroadcasters ________ +void SAL_CALL AccessibleBase::addAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener ) +{ + MutexGuard aGuard( m_aMutex ); + + if ( xListener.is() ) + { + if ( !m_nEventNotifierId ) + m_nEventNotifierId = ::comphelper::AccessibleEventNotifier::registerClient(); + + ::comphelper::AccessibleEventNotifier::addEventListener( m_nEventNotifierId, xListener ); + } +} + +void SAL_CALL AccessibleBase::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener ) +{ + MutexGuard aGuard( m_aMutex ); + + if ( xListener.is() && m_nEventNotifierId) + { + sal_Int32 nListenerCount = ::comphelper::AccessibleEventNotifier::removeEventListener( m_nEventNotifierId, xListener ); + if ( !nListenerCount ) + { + // no listeners anymore + ::comphelper::AccessibleEventNotifier::revokeClient( m_nEventNotifierId ); + m_nEventNotifierId = 0; + } + } +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |