diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /chart2/source/controller/accessibility | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'chart2/source/controller/accessibility')
11 files changed, 2326 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..6f9192eba --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleBase.cxx @@ -0,0 +1,865 @@ +/* -*- 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 <com/sun/star/chart2/XChartDocument.hpp> +#include <sal/log.hxx> +#include <vcl/svapp.hxx> +#include <comphelper/servicehelper.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <vcl/unohelp.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, true ); + + 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, true ); + 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 ) ); + } + 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, + bool bSendGlobally ) const +{ + ClearableMutexGuard aGuard( m_aMutex ); + + if ( !m_nEventNotifierId && !bSendGlobally ) + 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 + //except SendGlobally for focus handling? + + // 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 ); + + if ( m_nEventNotifierId ) // let the notifier handle this event + ::comphelper::AccessibleEventNotifier::addEvent( m_nEventNotifierId, aEvent ); + + aGuard.clear(); + + // send event to global message queue + if( bSendGlobally ) + { + vcl::unohelper::NotifyAccessibleStateEventGlobally( aEvent ); + } +} + +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(), + true /* global notification */ ); +} + +// ________ (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 + ::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.get(); +} + +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::getUnoTunnelImplementation<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.getX() - aOffset.X, aRect.getY() - 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 + OUString aParentParticle( ObjectIdentifier::getFullParentParticle( aObjectCID )); + aObjectCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle ); + } + + xObjProp = + ObjectIdentifier::getObjectPropertySet( + aObjectCID, Reference< chart2::XChartDocument >( 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: */ diff --git a/chart2/source/controller/accessibility/AccessibleChartElement.cxx b/chart2/source/controller/accessibility/AccessibleChartElement.cxx new file mode 100644 index 000000000..cbee2ddbb --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleChartElement.cxx @@ -0,0 +1,244 @@ +/* -*- 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 "AccessibleChartElement.hxx" +#include <CharacterProperties.hxx> +#include <ObjectIdentifier.hxx> +#include <ObjectNameProvider.hxx> +#include <servicenames.hxx> + +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/chart2/XTitle.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> + +#include <tools/diagnose_ex.h> + +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 ::com::sun::star::uno::Sequence; + +namespace chart +{ + +AccessibleChartElement::AccessibleChartElement( + const AccessibleElementInfo & rAccInfo, + bool bMayHaveChildren ) : + impl::AccessibleChartElement_Base( rAccInfo, bMayHaveChildren, false/*bAlwaysTransparent*/ ), + m_bHasText( false ) +{ + AddState( AccessibleStateType::TRANSIENT ); +} + +AccessibleChartElement::~AccessibleChartElement() +{ + OSL_ASSERT( CheckDisposeState( false /* don't throw exceptions */ ) ); +} + +// ________ protected ________ + +bool AccessibleChartElement::ImplUpdateChildren() +{ + bool bResult = false; + Reference< chart2::XTitle > xTitle( + ObjectIdentifier::getObjectPropertySet( + GetInfo().m_aOID.getObjectCID(), Reference< chart2::XChartDocument >( GetInfo().m_xChartDocument )), + uno::UNO_QUERY ); + m_bHasText = xTitle.is(); + + if( m_bHasText ) + { + InitTextEdit(); + bResult = true; + } + else + bResult = AccessibleBase::ImplUpdateChildren(); + + return bResult; +} + +void AccessibleChartElement::InitTextEdit() +{ + if( ! m_xTextHelper.is()) + { + // get hard reference + Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier ); + // get factory from selection supplier (controller) + Reference< lang::XMultiServiceFactory > xFact( xSelSupp, uno::UNO_QUERY ); + if( xFact.is()) + { + m_xTextHelper.set( + xFact->createInstance( CHART_ACCESSIBLE_TEXT_SERVICE_NAME ), uno::UNO_QUERY ); + } + } + + if( !m_xTextHelper.is()) + return; + + try + { + Reference< lang::XInitialization > xInit( m_xTextHelper, uno::UNO_QUERY_THROW ); + Sequence< uno::Any > aArgs( 3 ); + aArgs[0] <<= GetInfo().m_aOID.getObjectCID(); + aArgs[1] <<= Reference< XAccessible >( this ); + aArgs[2] <<= Reference< awt::XWindow >( GetInfo().m_xWindow ); + xInit->initialize( aArgs ); + } + catch( const uno::Exception & ) + { + DBG_UNHANDLED_EXCEPTION("chart2"); + } +} + +// Interfaces + +// ________ AccessibleBase::XAccessibleContext ________ +Reference< XAccessible > AccessibleChartElement::ImplGetAccessibleChildById( sal_Int32 i ) const +{ + Reference< XAccessible > xResult; + + if( m_bHasText ) + xResult.set( m_xTextHelper->getAccessibleChild( i )); + else + xResult.set( AccessibleBase::ImplGetAccessibleChildById( i )); + + return xResult; +} + +sal_Int32 AccessibleChartElement::ImplGetAccessibleChildCount() const +{ + if( m_bHasText ) + { + if( m_xTextHelper.is()) + return m_xTextHelper->getAccessibleChildCount(); + return 0; + } + + return AccessibleBase::ImplGetAccessibleChildCount(); +} + +// ________ XServiceInfo ________ +OUString SAL_CALL AccessibleChartElement::getImplementationName() +{ + return "AccessibleChartElement"; +} + +// ________ AccessibleChartElement::XAccessibleContext (override) ________ +OUString SAL_CALL AccessibleChartElement::getAccessibleName() +{ + return ObjectNameProvider::getNameForCID( + GetInfo().m_aOID.getObjectCID(), GetInfo().m_xChartDocument ); +} + +// ________ AccessibleChartElement::XAccessibleContext (override) ________ +OUString SAL_CALL AccessibleChartElement::getAccessibleDescription() +{ + return getToolTipText(); +} + +// ________ AccessibleChartElement::XAccessibleExtendedComponent ________ +Reference< awt::XFont > SAL_CALL AccessibleChartElement::getFont() +{ + CheckDisposeState(); + + Reference< awt::XFont > xFont; + Reference< awt::XDevice > xDevice( Reference< awt::XWindow >( GetInfo().m_xWindow ), uno::UNO_QUERY ); + + if( xDevice.is()) + { + Reference< beans::XMultiPropertySet > xObjProp( + ObjectIdentifier::getObjectPropertySet( + GetInfo().m_aOID.getObjectCID(), Reference< chart2::XChartDocument >( GetInfo().m_xChartDocument )), uno::UNO_QUERY ); + awt::FontDescriptor aDescr( + CharacterProperties::createFontDescriptorFromPropertySet( xObjProp )); + xFont = xDevice->getFont( aDescr ); + } + + return xFont; +} + +OUString SAL_CALL AccessibleChartElement::getTitledBorderText() +{ + return OUString(); +} + +OUString SAL_CALL AccessibleChartElement::getToolTipText() +{ + CheckDisposeState(); + + return ObjectNameProvider::getHelpText( + GetInfo().m_aOID.getObjectCID(), Reference< chart2::XChartDocument >( GetInfo().m_xChartDocument )); +} + +// ________ XAccessibleComponent ________ +sal_Bool SAL_CALL AccessibleChartElement::containsPoint( const awt::Point& aPoint ) +{ + return AccessibleBase::containsPoint( aPoint ); +} + +Reference< XAccessible > SAL_CALL AccessibleChartElement::getAccessibleAtPoint( const awt::Point& aPoint ) +{ + return AccessibleBase::getAccessibleAtPoint( aPoint ); +} + +awt::Rectangle SAL_CALL AccessibleChartElement::getBounds() +{ + return AccessibleBase::getBounds(); +} + +awt::Point SAL_CALL AccessibleChartElement::getLocation() +{ + return AccessibleBase::getLocation(); +} + +awt::Point SAL_CALL AccessibleChartElement::getLocationOnScreen() +{ + return AccessibleBase::getLocationOnScreen(); +} + +awt::Size SAL_CALL AccessibleChartElement::getSize() +{ + return AccessibleBase::getSize(); +} + +void SAL_CALL AccessibleChartElement::grabFocus() +{ + return AccessibleBase::grabFocus(); +} + +sal_Int32 SAL_CALL AccessibleChartElement::getForeground() +{ + return AccessibleBase::getForeground(); +} + +sal_Int32 SAL_CALL AccessibleChartElement::getBackground() +{ + return AccessibleBase::getBackground(); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/accessibility/AccessibleChartElement.hxx b/chart2/source/controller/accessibility/AccessibleChartElement.hxx new file mode 100644 index 000000000..3e42ea784 --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleChartElement.hxx @@ -0,0 +1,107 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_ACCESSIBLECHARTELEMENT_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_ACCESSIBLECHARTELEMENT_HXX + +#include <AccessibleBase.hxx> +#include <com/sun/star/accessibility/XAccessibleExtendedComponent.hpp> + +namespace com::sun::star::accessibility { class XAccessible; } +namespace com::sun::star::accessibility { class XAccessibleContext; } +namespace com::sun::star::awt { class XFont; } + +namespace chart +{ + +/** Base class for all Chart Accessibility objects except the root node (see AccessibleChartView) + + This class contains a reference to the ChartModel, thus, components can easily access all core functionality. + + Usage Instructions: + + <ul> + <li>define the getAccessibleName() method of XAccessibleContext</li> + <li>set the ChartModel using SetChartModel() for the first node before + creating any children</li> + <li>override UpdateChildren()</li> + </ul> + */ + +namespace impl +{ +typedef ::cppu::ImplInheritanceHelper< + AccessibleBase, + css::accessibility::XAccessibleExtendedComponent + > AccessibleChartElement_Base; +} + +class AccessibleChartElement : + public impl::AccessibleChartElement_Base +{ +public: + AccessibleChartElement( const AccessibleElementInfo & rAccInfo, + bool bMayHaveChildren ); + virtual ~AccessibleChartElement() override; + + // ________ AccessibleBase ________ + virtual bool ImplUpdateChildren() override; + virtual css::uno::Reference< css::accessibility::XAccessible > + ImplGetAccessibleChildById( sal_Int32 i ) const override; + virtual sal_Int32 ImplGetAccessibleChildCount() const override; + + // ________ XAccessibleContext ________ + virtual OUString SAL_CALL getAccessibleName() override; + virtual OUString SAL_CALL getAccessibleDescription() override; + + // ________ XAccessibleExtendedComponent ________ + virtual css::uno::Reference< css::awt::XFont > SAL_CALL getFont() override; + virtual OUString SAL_CALL getTitledBorderText() override; + virtual OUString SAL_CALL getToolTipText() override; + + // the following interface is implemented in AccessibleBase, however it is + // also a (non-virtual) base class of XAccessibleExtendedComponent Thus + // these methods have to be overridden and forward to AccessibleBase + + // ________ XAccessibleComponent ________ + virtual sal_Bool SAL_CALL containsPoint( const css::awt::Point& aPoint ) override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override; + virtual css::awt::Rectangle SAL_CALL getBounds() override; + virtual css::awt::Point SAL_CALL getLocation() override; + virtual css::awt::Point SAL_CALL getLocationOnScreen() override; + virtual css::awt::Size SAL_CALL getSize() override; + virtual void SAL_CALL grabFocus() override; + virtual sal_Int32 SAL_CALL getForeground() override; + virtual sal_Int32 SAL_CALL getBackground() override; + + // ________ XServiceInfo ________ + virtual OUString SAL_CALL getImplementationName() override; + +private: + bool m_bHasText; + css::uno::Reference< css::accessibility::XAccessibleContext > + m_xTextHelper; + + void InitTextEdit(); +}; + +} // namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/accessibility/AccessibleChartShape.cxx b/chart2/source/controller/accessibility/AccessibleChartShape.cxx new file mode 100644 index 000000000..d9c2f7071 --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleChartShape.cxx @@ -0,0 +1,251 @@ +/* -*- 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 "AccessibleChartShape.hxx" + +#include <com/sun/star/awt/XWindow.hpp> +#include <toolkit/helper/vclunohelper.hxx> +#include <svx/ShapeTypeHandler.hxx> +#include <svx/AccessibleShape.hxx> +#include <svx/AccessibleShapeInfo.hxx> +#include <vcl/window.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +using ::com::sun::star::uno::Reference; + +namespace chart +{ + +AccessibleChartShape::AccessibleChartShape( + const AccessibleElementInfo& rAccInfo ) + :impl::AccessibleChartShape_Base( rAccInfo, true/*bMayHaveChildren*/, false/*bAlwaysTransparent*/ ) +{ + if ( !rAccInfo.m_aOID.isAdditionalShape() ) + return; + + Reference< drawing::XShape > xShape( rAccInfo.m_aOID.getAdditionalShape() ); + Reference< XAccessible > xParent; + if ( rAccInfo.m_pParent ) + { + xParent.set( rAccInfo.m_pParent ); + } + ::accessibility::AccessibleShapeInfo aShapeInfo( xShape, xParent ); + + m_aShapeTreeInfo.SetSdrView( rAccInfo.m_pSdrView ); + m_aShapeTreeInfo.SetController( nullptr ); + m_aShapeTreeInfo.SetDevice( VCLUnoHelper::GetWindow( rAccInfo.m_xWindow ) ); + m_aShapeTreeInfo.SetViewForwarder( rAccInfo.m_pViewForwarder ); + + ::accessibility::ShapeTypeHandler& rShapeHandler = ::accessibility::ShapeTypeHandler::Instance(); + m_pAccShape = rShapeHandler.CreateAccessibleObject( aShapeInfo, m_aShapeTreeInfo ); + if ( m_pAccShape.is() ) + { + m_pAccShape->Init(); + } +} + +AccessibleChartShape::~AccessibleChartShape() +{ + OSL_ASSERT( CheckDisposeState( false /* don't throw exceptions */ ) ); + + if ( m_pAccShape.is() ) + { + m_pAccShape->dispose(); + } +} + +// ________ XServiceInfo ________ +OUString AccessibleChartShape::getImplementationName() +{ + return "AccessibleChartShape"; +} + +// ________ XAccessibleContext ________ +sal_Int32 AccessibleChartShape::getAccessibleChildCount() +{ + sal_Int32 nCount(0); + if ( m_pAccShape.is() ) + { + nCount = m_pAccShape->getAccessibleChildCount(); + } + return nCount; +} + +Reference< XAccessible > AccessibleChartShape::getAccessibleChild( sal_Int32 i ) +{ + Reference< XAccessible > xChild; + if ( m_pAccShape.is() ) + { + xChild = m_pAccShape->getAccessibleChild( i ); + } + return xChild; +} + +sal_Int16 AccessibleChartShape::getAccessibleRole() +{ + sal_Int16 nRole(0); + if ( m_pAccShape.is() ) + { + nRole = m_pAccShape->getAccessibleRole(); + } + return nRole; +} + +OUString AccessibleChartShape::getAccessibleDescription() +{ + OUString aDescription; + if ( m_pAccShape.is() ) + { + aDescription = m_pAccShape->getAccessibleDescription(); + } + return aDescription; +} + +OUString AccessibleChartShape::getAccessibleName() +{ + OUString aName; + if ( m_pAccShape.is() ) + { + aName = m_pAccShape->getAccessibleName(); + } + return aName; +} + +// ________ XAccessibleComponent ________ +sal_Bool AccessibleChartShape::containsPoint( const awt::Point& aPoint ) +{ + bool bReturn = false; + if ( m_pAccShape.is() ) + { + bReturn = m_pAccShape->containsPoint( aPoint ); + } + return bReturn; +} + +Reference< XAccessible > AccessibleChartShape::getAccessibleAtPoint( const awt::Point& aPoint ) +{ + Reference< XAccessible > xResult; + if ( m_pAccShape.is() ) + { + xResult.set( m_pAccShape->getAccessibleAtPoint( aPoint ) ); + } + return xResult; +} + +awt::Rectangle AccessibleChartShape::getBounds() +{ + awt::Rectangle aBounds; + if ( m_pAccShape.is() ) + { + aBounds = m_pAccShape->getBounds(); + } + return aBounds; +} + +awt::Point AccessibleChartShape::getLocation() +{ + awt::Point aLocation; + if ( m_pAccShape.is() ) + { + aLocation = m_pAccShape->getLocation(); + } + return aLocation; +} + +awt::Point AccessibleChartShape::getLocationOnScreen() +{ + awt::Point aLocation; + if ( m_pAccShape.is() ) + { + aLocation = m_pAccShape->getLocationOnScreen(); + } + return aLocation; +} + +awt::Size AccessibleChartShape::getSize() +{ + awt::Size aSize; + if ( m_pAccShape.is() ) + { + aSize = m_pAccShape->getSize(); + } + return aSize; +} + +void AccessibleChartShape::grabFocus() +{ + return AccessibleBase::grabFocus(); +} + +sal_Int32 AccessibleChartShape::getForeground() +{ + sal_Int32 nColor(0); + if ( m_pAccShape.is() ) + { + nColor = m_pAccShape->getForeground(); + } + return nColor; +} + +sal_Int32 AccessibleChartShape::getBackground() +{ + sal_Int32 nColor(0); + if ( m_pAccShape.is() ) + { + nColor = m_pAccShape->getBackground(); + } + return nColor; +} + +// ________ XAccessibleExtendedComponent ________ +Reference< awt::XFont > AccessibleChartShape::getFont() +{ + Reference< awt::XFont > xFont; + if ( m_pAccShape.is() ) + { + xFont.set( m_pAccShape->getFont() ); + } + return xFont; +} + +OUString AccessibleChartShape::getTitledBorderText() +{ + OUString aText; + if ( m_pAccShape.is() ) + { + aText = m_pAccShape->getTitledBorderText(); + } + return aText; +} + +OUString AccessibleChartShape::getToolTipText() +{ + OUString aText; + if ( m_pAccShape.is() ) + { + aText = m_pAccShape->getToolTipText(); + } + return aText; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/accessibility/AccessibleChartShape.hxx b/chart2/source/controller/accessibility/AccessibleChartShape.hxx new file mode 100644 index 000000000..d113c03f8 --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleChartShape.hxx @@ -0,0 +1,86 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_ACCESSIBLECHARTSHAPE_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_ACCESSIBLECHARTSHAPE_HXX + +#include <AccessibleBase.hxx> + +#include <com/sun/star/accessibility/XAccessibleExtendedComponent.hpp> +#include <cppuhelper/implbase.hxx> +#include <svx/AccessibleShapeTreeInfo.hxx> + +namespace accessibility +{ +class AccessibleShape; +} + +namespace chart +{ + +namespace impl +{ +typedef ::cppu::ImplInheritanceHelper< + AccessibleBase, + css::accessibility::XAccessibleExtendedComponent > AccessibleChartShape_Base; +} + +class AccessibleChartShape : + public impl::AccessibleChartShape_Base +{ +public: + explicit AccessibleChartShape( const AccessibleElementInfo& rAccInfo ); + virtual ~AccessibleChartShape() override; + + // ________ XServiceInfo ________ + virtual OUString SAL_CALL getImplementationName() override; + + // ________ XAccessibleContext ________ + virtual sal_Int32 SAL_CALL getAccessibleChildCount() override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL + getAccessibleChild( sal_Int32 i ) override; + virtual sal_Int16 SAL_CALL getAccessibleRole() override; + virtual OUString SAL_CALL getAccessibleDescription() override; + virtual OUString SAL_CALL getAccessibleName() override; + + // ________ XAccessibleComponent ________ + virtual sal_Bool SAL_CALL containsPoint( const css::awt::Point& aPoint ) override; + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override; + virtual css::awt::Rectangle SAL_CALL getBounds() override; + virtual css::awt::Point SAL_CALL getLocation() override; + virtual css::awt::Point SAL_CALL getLocationOnScreen() override; + virtual css::awt::Size SAL_CALL getSize() override; + virtual void SAL_CALL grabFocus() override; + virtual sal_Int32 SAL_CALL getForeground() override; + virtual sal_Int32 SAL_CALL getBackground() override; + + // ________ XAccessibleExtendedComponent ________ + virtual css::uno::Reference< css::awt::XFont > SAL_CALL getFont() override; + virtual OUString SAL_CALL getTitledBorderText() override; + virtual OUString SAL_CALL getToolTipText() override; + +private: + rtl::Reference<accessibility::AccessibleShape> m_pAccShape; + ::accessibility::AccessibleShapeTreeInfo m_aShapeTreeInfo; +}; + +} // namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/accessibility/AccessibleChartView.cxx b/chart2/source/controller/accessibility/AccessibleChartView.cxx new file mode 100644 index 000000000..0738f52ab --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleChartView.cxx @@ -0,0 +1,358 @@ +/* -*- 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 <AccessibleChartView.hxx> +#include <chartview/ExplicitValueProvider.hxx> +#include <ObjectHierarchy.hxx> +#include <ObjectIdentifier.hxx> +#include <ResId.hxx> +#include <strings.hrc> +#include "AccessibleViewForwarder.hxx" + +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> + +#include <comphelper/servicehelper.hxx> + +#include <rtl/ustring.hxx> +#include <vcl/window.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/svapp.hxx> +#include <osl/mutex.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::WeakReference; +using ::com::sun::star::uno::Any; +using osl::MutexGuard; + +namespace chart +{ + +AccessibleChartView::AccessibleChartView(SdrView* pView ) : + impl::AccessibleChartView_Base( + AccessibleElementInfo(), // empty for now + true, // has children + true // always transparent + ), + m_pSdrView( pView ) +{ + AddState( AccessibleStateType::OPAQUE ); +} + +AccessibleChartView::~AccessibleChartView() +{ +} + +awt::Rectangle AccessibleChartView::GetWindowPosSize() const +{ + Reference< awt::XWindow > xWindow( GetInfo().m_xWindow ); + if( ! xWindow.is()) + return awt::Rectangle(); + + awt::Rectangle aBBox( xWindow->getPosSize() ); + + VclPtr<vcl::Window> pWindow( VCLUnoHelper::GetWindow( GetInfo().m_xWindow )); + if( pWindow ) + { + SolarMutexGuard aSolarGuard; + Point aVCLPoint( pWindow->OutputToAbsoluteScreenPixel( Point( 0, 0 ) )); + aBBox.X = aVCLPoint.getX(); + aBBox.Y = aVCLPoint.getY(); + } + + return aBBox; +} + +awt::Point AccessibleChartView::GetUpperLeftOnScreen() const +{ + awt::Point aParentPosition; + + awt::Rectangle aBBox( GetWindowPosSize() ); + aParentPosition.X = aBBox.X; + aParentPosition.Y = aBBox.Y; + + return aParentPosition; +} + +// ________ XAccessibleContext ________ +OUString SAL_CALL AccessibleChartView::getAccessibleName() +{ + return SchResId(STR_OBJECT_DIAGRAM); +} + +OUString SAL_CALL AccessibleChartView::getAccessibleDescription() +{ + return getAccessibleName(); +} + +Reference< XAccessible > SAL_CALL AccessibleChartView::getAccessibleParent() +{ + return Reference< XAccessible >( m_xParent ); +} + +sal_Int32 SAL_CALL AccessibleChartView::getAccessibleIndexInParent() +{ + // the document is always the only child of the window + return 0; +} + +sal_Int16 SAL_CALL AccessibleChartView::getAccessibleRole() +{ + return AccessibleRole::DOCUMENT; +} + +// ________ XAccessibleComponent ________ +awt::Rectangle SAL_CALL AccessibleChartView::getBounds() +{ + awt::Rectangle aResult( GetWindowPosSize()); + Reference< XAccessible > xParent( m_xParent ); + if( xParent.is()) + { + Reference< XAccessibleComponent > xContext( xParent->getAccessibleContext(), uno::UNO_QUERY ); + if( xContext.is()) + { + awt::Point aParentPosition = xContext->getLocationOnScreen(); + aResult.X -= aParentPosition.X; + aResult.Y -= aParentPosition.Y; + } + } + return aResult; +} + +awt::Point SAL_CALL AccessibleChartView::getLocationOnScreen() +{ + awt::Rectangle aBounds( getBounds()); + awt::Point aResult; + Reference< XAccessible > xParent( m_xParent ); + if( xParent.is()) + { + Reference< XAccessibleComponent > xAccComp( + xParent->getAccessibleContext(), uno::UNO_QUERY ); + aResult = xAccComp->getLocationOnScreen(); + aResult.X += aBounds.X; + aResult.Y += aBounds.Y; + } + return aResult; +} + +// lang::XInitialization + +void SAL_CALL AccessibleChartView::initialize( const Sequence< Any >& rArguments ) +{ + //0: view::XSelectionSupplier offers notifications for selection changes and access to the selection itself + //1: frame::XModel representing the chart model - offers access to object data + //2: lang::XInterface representing the normal chart view - offers access to some extra object data + + //all arguments are only valid until next initialization + bool bChanged = false; + bool bOldInvalid = false; + bool bNewInvalid = false; + + Reference< view::XSelectionSupplier > xSelectionSupplier; + Reference< frame::XModel > xChartModel; + Reference< uno::XInterface > xChartView; + Reference< XAccessible > xParent; + Reference< awt::XWindow > xWindow; + { + MutexGuard aGuard( m_aMutex); + xSelectionSupplier.set( m_xSelectionSupplier ); + xChartModel.set( m_xChartModel ); + xChartView.set( m_xChartView ); + xParent.set( m_xParent ); + xWindow.set( m_xWindow ); + } + + if( !xSelectionSupplier.is() || !xChartModel.is() || !xChartView.is() ) + { + bOldInvalid = true; + } + + if( rArguments.getLength() > 1 ) + { + Reference< frame::XModel > xNewChartModel; + rArguments[1] >>= xNewChartModel; + if( xNewChartModel != xChartModel ) + { + xChartModel = xNewChartModel; + bChanged = true; + } + } + else if( xChartModel.is() ) + { + bChanged = true; + xChartModel = nullptr; + } + + if( rArguments.getLength() > 2 ) + { + Reference< uno::XInterface > xNewChartView; + rArguments[2] >>= xNewChartView; + if( xNewChartView != xChartView ) + { + xChartView = xNewChartView; + bChanged = true; + } + } + else if( xChartView.is() ) + { + bChanged = true; + xChartView = nullptr; + } + + if( rArguments.getLength() > 3 ) + { + Reference< XAccessible > xNewParent; + rArguments[3] >>= xNewParent; + if( xNewParent != xParent ) + { + xParent = xNewParent; + bChanged = true; + } + } + + if( rArguments.getLength() > 4 ) + { + Reference< awt::XWindow > xNewWindow; + rArguments[4] >>= xNewWindow; + if( xNewWindow != xWindow ) + { + xWindow.set( xNewWindow ); + bChanged = true; + } + } + + if( rArguments.hasElements() && xChartModel.is() && xChartView.is() ) + { + Reference< view::XSelectionSupplier > xNewSelectionSupplier; + rArguments[0] >>= xNewSelectionSupplier; + if(xSelectionSupplier!=xNewSelectionSupplier) + { + bChanged = true; + if(xSelectionSupplier.is()) + xSelectionSupplier->removeSelectionChangeListener(this); + if(xNewSelectionSupplier.is()) + xNewSelectionSupplier->addSelectionChangeListener(this); + xSelectionSupplier = xNewSelectionSupplier; + } + } + else if( xSelectionSupplier.is() ) + { + bChanged = true; + xSelectionSupplier->removeSelectionChangeListener(this); + xSelectionSupplier = nullptr; + } + + if( !xSelectionSupplier.is() || !xChartModel.is() || !xChartView.is() ) + { + if(xSelectionSupplier.is()) + xSelectionSupplier->removeSelectionChangeListener(this); + xSelectionSupplier = nullptr; + xChartModel.clear(); + xChartView.clear(); + xParent.clear(); + xWindow.clear(); + + bNewInvalid = true; + } + + { + MutexGuard aGuard( m_aMutex); + m_xSelectionSupplier = WeakReference< view::XSelectionSupplier >(xSelectionSupplier); + m_xChartModel = WeakReference< frame::XModel >(xChartModel); + m_xChartView = WeakReference< uno::XInterface >(xChartView); + m_xParent = WeakReference< XAccessible >(xParent); + m_xWindow = WeakReference< awt::XWindow >(xWindow); + } + + if( bOldInvalid && bNewInvalid ) + bChanged = false; + + if( !bChanged ) + return; + + { + //before notification we prepare for creation of new context + //the old context will be deleted after notification than + MutexGuard aGuard( m_aMutex); + Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY ); + if( xChartDoc.is()) + m_spObjectHierarchy = + std::make_shared<ObjectHierarchy>( xChartDoc, comphelper::getUnoTunnelImplementation<ExplicitValueProvider>(m_xChartView) ); + else + m_spObjectHierarchy.reset(); + } + + { + AccessibleElementInfo aAccInfo; + aAccInfo.m_aOID = ObjectIdentifier("ROOT"); + aAccInfo.m_xChartDocument = uno::WeakReference< chart2::XChartDocument >( + uno::Reference< chart2::XChartDocument >( m_xChartModel.get(), uno::UNO_QUERY )); + aAccInfo.m_xSelectionSupplier = m_xSelectionSupplier; + aAccInfo.m_xView = m_xChartView; + aAccInfo.m_xWindow = m_xWindow; + aAccInfo.m_pParent = nullptr; + aAccInfo.m_spObjectHierarchy = m_spObjectHierarchy; + aAccInfo.m_pSdrView = m_pSdrView; + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( m_xWindow ); + m_pViewForwarder.reset( new AccessibleViewForwarder( this, pWindow ) ); + aAccInfo.m_pViewForwarder = m_pViewForwarder.get(); + // broadcasts an INVALIDATE_ALL_CHILDREN event globally + SetInfo( aAccInfo ); + } +} + +// view::XSelectionChangeListener + +void SAL_CALL AccessibleChartView::selectionChanged( const lang::EventObject& /*rEvent*/ ) +{ + Reference< view::XSelectionSupplier > xSelectionSupplier; + { + MutexGuard aGuard( m_aMutex); + xSelectionSupplier.set(m_xSelectionSupplier); + } + + if( !xSelectionSupplier.is() ) + return; + + ObjectIdentifier aSelectedOID( xSelectionSupplier->getSelection() ); + if ( m_aCurrentSelectionOID.isValid() ) + { + NotifyEvent( EventType::LOST_SELECTION, m_aCurrentSelectionOID ); + } + if( aSelectedOID.isValid() ) + { + NotifyEvent( EventType::GOT_SELECTION, aSelectedOID ); + } + m_aCurrentSelectionOID = aSelectedOID; +} + +// XEventListener +void SAL_CALL AccessibleChartView::disposing( const lang::EventObject& /*Source*/ ) +{ +} + +} //namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/accessibility/AccessibleTextHelper.cxx b/chart2/source/controller/accessibility/AccessibleTextHelper.cxx new file mode 100644 index 000000000..620897210 --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleTextHelper.cxx @@ -0,0 +1,167 @@ +/* -*- 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 <sal/config.h> + +#include <memory> + +#include <AccessibleTextHelper.hxx> +#include <DrawViewWrapper.hxx> + +#include <vcl/svapp.hxx> + +#include <svx/AccessibleTextHelper.hxx> +#include <svx/unoshtxt.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/window.hxx> + +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; + +namespace chart +{ + +AccessibleTextHelper::AccessibleTextHelper( + DrawViewWrapper * pDrawViewWrapper ) : + impl::AccessibleTextHelper_Base( m_aMutex ), + m_pDrawViewWrapper( pDrawViewWrapper ) +{} + +AccessibleTextHelper::~AccessibleTextHelper() +{ +} + +// ____ XInitialization ____ +void SAL_CALL AccessibleTextHelper::initialize( const Sequence< uno::Any >& aArguments ) +{ + OUString aCID; + Reference< XAccessible > xEventSource; + Reference< awt::XWindow > xWindow; + + if( aArguments.getLength() >= 3 ) + { + aArguments[0] >>= aCID; + aArguments[1] >>= xEventSource; + aArguments[2] >>= xWindow; + } + OSL_ENSURE( !aCID.isEmpty(), "Empty CID" ); + OSL_ENSURE( xEventSource.is(), "Empty Event Source" ); + OSL_ENSURE( xWindow.is(), "Empty Window" ); + if( !xEventSource.is() || aCID.isEmpty() ) + return; + + SolarMutexGuard aSolarGuard; + + m_pTextHelper.reset(); + + VclPtr<vcl::Window> pWindow( VCLUnoHelper::GetWindow( xWindow )); + if( pWindow ) + { + SdrView * pView = m_pDrawViewWrapper; + if( pView ) + { + SdrObject * pTextObj = m_pDrawViewWrapper->getNamedSdrObject( aCID ); + if( pTextObj ) + { + m_pTextHelper.reset( new ::accessibility::AccessibleTextHelper(std::make_unique<SvxTextEditSource>(*pTextObj, nullptr, *pView, *pWindow)) ); + m_pTextHelper->SetEventSource( xEventSource ); + } + } + } + + OSL_ENSURE( m_pTextHelper, "Couldn't create text helper" ); +} + +// ____ XAccessibleContext ____ +::sal_Int32 SAL_CALL AccessibleTextHelper::getAccessibleChildCount() +{ + if( m_pTextHelper ) + { + SolarMutexGuard aSolarGuard; + return m_pTextHelper->GetChildCount(); + } + return 0; +} + +Reference< XAccessible > SAL_CALL AccessibleTextHelper::getAccessibleChild( ::sal_Int32 i ) +{ + if( m_pTextHelper ) + { + SolarMutexGuard aSolarGuard; + return m_pTextHelper->GetChild( i ); + } + return Reference< XAccessible >(); +} + +Reference< XAccessible > SAL_CALL AccessibleTextHelper::getAccessibleParent() +{ + OSL_FAIL( "Not implemented in this helper" ); + return Reference< XAccessible >(); +} + +::sal_Int32 SAL_CALL AccessibleTextHelper::getAccessibleIndexInParent() +{ + OSL_FAIL( "Not implemented in this helper" ); + return -1; +} + +::sal_Int16 SAL_CALL AccessibleTextHelper::getAccessibleRole() +{ + OSL_FAIL( "Not implemented in this helper" ); + return AccessibleRole::UNKNOWN; +} + +OUString SAL_CALL AccessibleTextHelper::getAccessibleDescription() +{ + OSL_FAIL( "Not implemented in this helper" ); + return OUString(); +} + +OUString SAL_CALL AccessibleTextHelper::getAccessibleName() +{ + OSL_FAIL( "Not implemented in this helper" ); + return OUString(); +} + +Reference< XAccessibleRelationSet > SAL_CALL AccessibleTextHelper::getAccessibleRelationSet() +{ + OSL_FAIL( "Not implemented in this helper" ); + return Reference< XAccessibleRelationSet >(); +} + +Reference< XAccessibleStateSet > SAL_CALL AccessibleTextHelper::getAccessibleStateSet() +{ + OSL_FAIL( "Not implemented in this helper" ); + return Reference< XAccessibleStateSet >(); +} + +lang::Locale SAL_CALL AccessibleTextHelper::getLocale() +{ + OSL_FAIL( "Not implemented in this helper" ); + return lang::Locale(); +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/accessibility/AccessibleViewForwarder.cxx b/chart2/source/controller/accessibility/AccessibleViewForwarder.cxx new file mode 100644 index 000000000..31395f118 --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleViewForwarder.cxx @@ -0,0 +1,79 @@ +/* -*- 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 "AccessibleViewForwarder.hxx" +#include <AccessibleChartView.hxx> + +#include <vcl/window.hxx> + +using namespace ::com::sun::star; + +namespace chart +{ + +AccessibleViewForwarder::AccessibleViewForwarder( AccessibleChartView* pAccChartView, vcl::Window* pWindow ) + :m_pAccChartView( pAccChartView ) + ,m_pWindow( pWindow ) + ,m_aMapMode( MapUnit::Map100thMM ) +{ +} + +AccessibleViewForwarder::~AccessibleViewForwarder() +{ +} + +// ________ IAccessibleViewforwarder ________ + +tools::Rectangle AccessibleViewForwarder::GetVisibleArea() const +{ + tools::Rectangle aVisibleArea; + if ( m_pWindow ) + { + aVisibleArea.SetPos( Point( 0, 0 ) ); + aVisibleArea.SetSize( m_pWindow->GetOutputSizePixel() ); + aVisibleArea = m_pWindow->PixelToLogic( aVisibleArea, m_aMapMode ); + } + return aVisibleArea; +} + +Point AccessibleViewForwarder::LogicToPixel( const Point& rPoint ) const +{ + Point aPoint; + if ( m_pAccChartView && m_pWindow ) + { + awt::Point aLocation = m_pAccChartView->getLocationOnScreen(); + Point aTopLeft( aLocation.X, aLocation.Y ); + aPoint = m_pWindow->LogicToPixel( rPoint, m_aMapMode ) + aTopLeft; + } + return aPoint; +} + +Size AccessibleViewForwarder::LogicToPixel( const Size& rSize ) const +{ + Size aSize; + if ( m_pWindow ) + { + aSize = m_pWindow->LogicToPixel( rSize, m_aMapMode ); + } + return aSize; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/accessibility/AccessibleViewForwarder.hxx b/chart2/source/controller/accessibility/AccessibleViewForwarder.hxx new file mode 100644 index 000000000..147b252a6 --- /dev/null +++ b/chart2/source/controller/accessibility/AccessibleViewForwarder.hxx @@ -0,0 +1,57 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_ACCESSIBLEVIEWFORWARDER_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_ACCESSIBLEVIEWFORWARDER_HXX + +#include <vcl/mapmod.hxx> +#include <vcl/vclptr.hxx> +#include <svx/IAccessibleViewForwarder.hxx> + +namespace vcl { class Window; } + +namespace chart +{ + +class AccessibleChartView; + +class AccessibleViewForwarder : public ::accessibility::IAccessibleViewForwarder +{ +public: + AccessibleViewForwarder( AccessibleChartView* pAccChartView, vcl::Window* pWindow ); + virtual ~AccessibleViewForwarder() override; + + // ________ IAccessibleViewforwarder ________ + virtual tools::Rectangle GetVisibleArea() const override; + virtual Point LogicToPixel( const Point& rPoint ) const override; + virtual Size LogicToPixel( const Size& rSize ) const override; + +private: + AccessibleViewForwarder( AccessibleViewForwarder const & ) = delete; + AccessibleViewForwarder& operator=( AccessibleViewForwarder const & ) = delete; + + AccessibleChartView* m_pAccChartView; + VclPtr<vcl::Window> m_pWindow; + MapMode m_aMapMode; +}; + +} // namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/accessibility/ChartElementFactory.cxx b/chart2/source/controller/accessibility/ChartElementFactory.cxx new file mode 100644 index 000000000..c935074e4 --- /dev/null +++ b/chart2/source/controller/accessibility/ChartElementFactory.cxx @@ -0,0 +1,71 @@ +/* -*- 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 "ChartElementFactory.hxx" +#include <ObjectIdentifier.hxx> +#include "AccessibleChartElement.hxx" + +namespace chart +{ + +AccessibleBase* ChartElementFactory::CreateChartElement( const AccessibleElementInfo& rAccInfo ) +{ + ObjectIdentifier aOID( rAccInfo.m_aOID ); + ObjectType eType( aOID.getObjectType() ); + + switch( eType ) + { + case OBJECTTYPE_DATA_POINT: + case OBJECTTYPE_LEGEND_ENTRY: + return new AccessibleChartElement( rAccInfo, false ); + case OBJECTTYPE_PAGE: + case OBJECTTYPE_TITLE: + case OBJECTTYPE_LEGEND: + case OBJECTTYPE_DIAGRAM: + case OBJECTTYPE_DIAGRAM_WALL: + case OBJECTTYPE_DIAGRAM_FLOOR: + case OBJECTTYPE_AXIS: + case OBJECTTYPE_AXIS_UNITLABEL: + case OBJECTTYPE_GRID: + case OBJECTTYPE_SUBGRID: + case OBJECTTYPE_DATA_SERIES: + case OBJECTTYPE_DATA_LABELS: + case OBJECTTYPE_DATA_LABEL: + case OBJECTTYPE_DATA_ERRORS_X: + case OBJECTTYPE_DATA_ERRORS_Y: + case OBJECTTYPE_DATA_ERRORS_Z: + case OBJECTTYPE_DATA_CURVE: // e.g. a statistical method printed as line + case OBJECTTYPE_DATA_AVERAGE_LINE: + case OBJECTTYPE_DATA_STOCK_RANGE: + case OBJECTTYPE_DATA_STOCK_LOSS: + case OBJECTTYPE_DATA_STOCK_GAIN: + case OBJECTTYPE_DATA_CURVE_EQUATION: + return new AccessibleChartElement( rAccInfo, true ); + case OBJECTTYPE_UNKNOWN: + break; + default: + break; + } + + return nullptr; +} + +} // namespace chart + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/controller/accessibility/ChartElementFactory.hxx b/chart2/source/controller/accessibility/ChartElementFactory.hxx new file mode 100644 index 000000000..2d0b29b9c --- /dev/null +++ b/chart2/source/controller/accessibility/ChartElementFactory.hxx @@ -0,0 +1,41 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_CHARTELEMENTFACTORY_HXX +#define INCLUDED_CHART2_SOURCE_CONTROLLER_ACCESSIBILITY_CHARTELEMENTFACTORY_HXX + +namespace chart +{ + +class AccessibleBase; +struct AccessibleElementInfo; + +class ChartElementFactory +{ +public: + /** @return a newly created object (using the new operator) that corresponds + to the given unique id + */ + static AccessibleBase* CreateChartElement( const AccessibleElementInfo& rAccInfo ); +}; + +} // namespace chart + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |