diff options
Diffstat (limited to 'basctl/source/accessibility')
-rw-r--r-- | basctl/source/accessibility/accessibledialogcontrolshape.cxx | 539 | ||||
-rw-r--r-- | basctl/source/accessibility/accessibledialogwindow.cxx | 945 |
2 files changed, 1484 insertions, 0 deletions
diff --git a/basctl/source/accessibility/accessibledialogcontrolshape.cxx b/basctl/source/accessibility/accessibledialogcontrolshape.cxx new file mode 100644 index 000000000..f885ff4bd --- /dev/null +++ b/basctl/source/accessibility/accessibledialogcontrolshape.cxx @@ -0,0 +1,539 @@ +/* -*- 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 <accessibledialogcontrolshape.hxx> +#include <baside3.hxx> +#include <dlgeddef.hxx> +#include <dlgedview.hxx> +#include <dlgedobj.hxx> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <unotools/accessiblestatesethelper.hxx> +#include <unotools/accessiblerelationsethelper.hxx> +#include <toolkit/awt/vclxfont.hxx> +#include <toolkit/helper/convert.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/diagnose_ex.h> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <i18nlangtag/languagetag.hxx> + +namespace basctl +{ + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::accessibility; +using namespace ::comphelper; + + + + +AccessibleDialogControlShape::AccessibleDialogControlShape (DialogWindow* pDialogWindow, DlgEdObj* pDlgEdObj) + :m_pDialogWindow( pDialogWindow ) + ,m_pDlgEdObj( pDlgEdObj ) +{ + if ( m_pDlgEdObj ) + m_xControlModel.set( m_pDlgEdObj->GetUnoControlModel(), UNO_QUERY ); + + if ( m_xControlModel.is() ) + m_xControlModel->addPropertyChangeListener( OUString(), static_cast< beans::XPropertyChangeListener* >( this ) ); + + m_bFocused = IsFocused(); + m_bSelected = IsSelected(); + m_aBounds = GetBounds(); +} + + +AccessibleDialogControlShape::~AccessibleDialogControlShape() +{ + if ( m_xControlModel.is() ) + m_xControlModel->removePropertyChangeListener( OUString(), static_cast< beans::XPropertyChangeListener* >( this ) ); +} + + +bool AccessibleDialogControlShape::IsFocused() const +{ + bool bFocused = false; + if ( m_pDialogWindow ) + { + SdrView& rView = m_pDialogWindow->GetView(); + if (rView.IsObjMarked(m_pDlgEdObj) && rView.GetMarkedObjectList().GetMarkCount() == 1) + bFocused = true; + } + + return bFocused; +} + + +bool AccessibleDialogControlShape::IsSelected() const +{ + if ( m_pDialogWindow ) + return m_pDialogWindow->GetView().IsObjMarked(m_pDlgEdObj); + return false; +} + + +void AccessibleDialogControlShape::SetFocused( bool bFocused ) +{ + if ( m_bFocused != bFocused ) + { + Any aOldValue, aNewValue; + if ( m_bFocused ) + aOldValue <<= AccessibleStateType::FOCUSED; + else + aNewValue <<= AccessibleStateType::FOCUSED; + m_bFocused = bFocused; + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + } +} + + +void AccessibleDialogControlShape::SetSelected( bool bSelected ) +{ + if ( m_bSelected != bSelected ) + { + Any aOldValue, aNewValue; + if ( m_bSelected ) + aOldValue <<= AccessibleStateType::SELECTED; + else + aNewValue <<= AccessibleStateType::SELECTED; + m_bSelected = bSelected; + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + } +} + + +awt::Rectangle AccessibleDialogControlShape::GetBounds() const +{ + awt::Rectangle aBounds( 0, 0, 0, 0 ); + if ( m_pDlgEdObj ) + { + // get the bounding box of the shape in logic units + tools::Rectangle aRect = m_pDlgEdObj->GetSnapRect(); + + if ( m_pDialogWindow ) + { + // transform coordinates relative to the parent + MapMode aMap = m_pDialogWindow->GetMapMode(); + Point aOrg = aMap.GetOrigin(); + aRect.Move( aOrg.X(), aOrg.Y() ); + + // convert logic units to pixel + aRect = m_pDialogWindow->LogicToPixel( aRect, MapMode(MapUnit::Map100thMM) ); + + // clip the shape's bounding box with the bounding box of its parent + tools::Rectangle aParentRect( Point( 0, 0 ), m_pDialogWindow->GetSizePixel() ); + aRect = aRect.GetIntersection( aParentRect ); + aBounds = AWTRectangle( aRect ); + } + } + + return aBounds; +} + + +void AccessibleDialogControlShape::SetBounds( const awt::Rectangle& aBounds ) +{ + if ( m_aBounds.X != aBounds.X || m_aBounds.Y != aBounds.Y || m_aBounds.Width != aBounds.Width || m_aBounds.Height != aBounds.Height ) + { + m_aBounds = aBounds; + NotifyAccessibleEvent( AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any() ); + } +} + + +vcl::Window* AccessibleDialogControlShape::GetWindow() const +{ + vcl::Window* pWindow = nullptr; + if ( m_pDlgEdObj ) + { + Reference< awt::XControl > xControl = m_pDlgEdObj->GetControl(); + if ( xControl.is() ) + pWindow = VCLUnoHelper::GetWindow( xControl->getPeer() ); + } + + return pWindow; +} + + +OUString AccessibleDialogControlShape::GetModelStringProperty( OUString const & pPropertyName ) +{ + OUString sReturn; + + try + { + if ( m_xControlModel.is() ) + { + Reference< XPropertySetInfo > xInfo = m_xControlModel->getPropertySetInfo(); + if ( xInfo.is() && xInfo->hasPropertyByName( pPropertyName ) ) + m_xControlModel->getPropertyValue( pPropertyName ) >>= sReturn; + } + } + catch ( const Exception& ) + { + TOOLS_WARN_EXCEPTION( "basctl", "AccessibleDialogControlShape::GetModelStringProperty" ); + } + + return sReturn; +} + + +void AccessibleDialogControlShape::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet ) +{ + rStateSet.AddState( AccessibleStateType::ENABLED ); + + rStateSet.AddState( AccessibleStateType::VISIBLE ); + + rStateSet.AddState( AccessibleStateType::SHOWING ); + + rStateSet.AddState( AccessibleStateType::FOCUSABLE ); + + if ( IsFocused() ) + rStateSet.AddState( AccessibleStateType::FOCUSED ); + + rStateSet.AddState( AccessibleStateType::SELECTABLE ); + + if ( IsSelected() ) + rStateSet.AddState( AccessibleStateType::SELECTED ); + + rStateSet.AddState( AccessibleStateType::RESIZABLE ); +} + +// OCommonAccessibleComponent +awt::Rectangle AccessibleDialogControlShape::implGetBounds() +{ + return GetBounds(); +} + +// XInterface +IMPLEMENT_FORWARD_XINTERFACE2( AccessibleDialogControlShape, OAccessibleExtendedComponentHelper, AccessibleDialogControlShape_BASE ) + +// XTypeProvider +IMPLEMENT_FORWARD_XTYPEPROVIDER2( AccessibleDialogControlShape, OAccessibleExtendedComponentHelper, AccessibleDialogControlShape_BASE ) + +// XComponent +void AccessibleDialogControlShape::disposing() +{ + OAccessibleExtendedComponentHelper::disposing(); + + m_pDialogWindow = nullptr; + m_pDlgEdObj = nullptr; + + if ( m_xControlModel.is() ) + m_xControlModel->removePropertyChangeListener( OUString(), static_cast< beans::XPropertyChangeListener* >( this ) ); + m_xControlModel.clear(); +} + + +// XEventListener + + +void AccessibleDialogControlShape::disposing( const lang::EventObject& ) +{ + if ( m_xControlModel.is() ) + m_xControlModel->removePropertyChangeListener( OUString(), static_cast< beans::XPropertyChangeListener* >( this ) ); + m_xControlModel.clear(); +} + + +// XPropertyChangeListener + + +void AccessibleDialogControlShape::propertyChange( const beans::PropertyChangeEvent& rEvent ) +{ + if ( rEvent.PropertyName == DLGED_PROP_NAME ) + { + NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, rEvent.OldValue, rEvent.NewValue ); + } + else if ( rEvent.PropertyName == DLGED_PROP_POSITIONX || + rEvent.PropertyName == DLGED_PROP_POSITIONY || + rEvent.PropertyName == DLGED_PROP_WIDTH || + rEvent.PropertyName == DLGED_PROP_HEIGHT ) + { + SetBounds( GetBounds() ); + } + else if ( rEvent.PropertyName == DLGED_PROP_BACKGROUNDCOLOR || + rEvent.PropertyName == DLGED_PROP_TEXTCOLOR || + rEvent.PropertyName == DLGED_PROP_TEXTLINECOLOR ) + { + NotifyAccessibleEvent( AccessibleEventId::VISIBLE_DATA_CHANGED, Any(), Any() ); + } +} + +// XServiceInfo +OUString AccessibleDialogControlShape::getImplementationName() +{ + return "com.sun.star.comp.basctl.AccessibleShape"; +} + +sal_Bool AccessibleDialogControlShape::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +Sequence< OUString > AccessibleDialogControlShape::getSupportedServiceNames() +{ + return { "com.sun.star.drawing.AccessibleShape" }; +} + +// XAccessible +Reference< XAccessibleContext > AccessibleDialogControlShape::getAccessibleContext( ) +{ + return this; +} + +// XAccessibleContext +sal_Int32 AccessibleDialogControlShape::getAccessibleChildCount() +{ + return 0; +} + + +Reference< XAccessible > AccessibleDialogControlShape::getAccessibleChild( sal_Int32 i ) +{ + OExternalLockGuard aGuard( this ); + + if ( i < 0 || i >= getAccessibleChildCount() ) + throw IndexOutOfBoundsException(); + + return Reference< XAccessible >(); +} + + +Reference< XAccessible > AccessibleDialogControlShape::getAccessibleParent( ) +{ + OExternalLockGuard aGuard( this ); + + Reference< XAccessible > xParent; + if ( m_pDialogWindow ) + xParent = m_pDialogWindow->GetAccessible(); + + return xParent; +} + + +sal_Int32 AccessibleDialogControlShape::getAccessibleIndexInParent( ) +{ + OExternalLockGuard aGuard( this ); + + sal_Int32 nIndexInParent = -1; + Reference< XAccessible > xParent( getAccessibleParent() ); + if ( xParent.is() ) + { + Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); + if ( xParentContext.is() ) + { + for ( sal_Int32 i = 0, nCount = xParentContext->getAccessibleChildCount(); i < nCount; ++i ) + { + Reference< XAccessible > xChild( xParentContext->getAccessibleChild( i ) ); + if ( xChild.is() ) + { + Reference< XAccessibleContext > xChildContext = xChild->getAccessibleContext(); + if ( xChildContext == static_cast<XAccessibleContext*>(this) ) + { + nIndexInParent = i; + break; + } + } + } + } + } + + return nIndexInParent; +} + + +sal_Int16 AccessibleDialogControlShape::getAccessibleRole( ) +{ + OExternalLockGuard aGuard( this ); + + return AccessibleRole::SHAPE; +} + + +OUString AccessibleDialogControlShape::getAccessibleDescription( ) +{ + OExternalLockGuard aGuard( this ); + + return GetModelStringProperty( "HelpText" ); +} + + +OUString AccessibleDialogControlShape::getAccessibleName( ) +{ + OExternalLockGuard aGuard( this ); + + return GetModelStringProperty( "Name" ); +} + + +Reference< XAccessibleRelationSet > AccessibleDialogControlShape::getAccessibleRelationSet( ) +{ + OExternalLockGuard aGuard( this ); + + return new utl::AccessibleRelationSetHelper; +} + + +Reference< XAccessibleStateSet > AccessibleDialogControlShape::getAccessibleStateSet( ) +{ + OExternalLockGuard aGuard( this ); + + rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper; + + if ( !rBHelper.bDisposed && !rBHelper.bInDispose ) + { + FillAccessibleStateSet( *pStateSetHelper ); + } + else + { + pStateSetHelper->AddState( AccessibleStateType::DEFUNC ); + } + + return pStateSetHelper; +} + + +Locale AccessibleDialogControlShape::getLocale( ) +{ + OExternalLockGuard aGuard( this ); + + return Application::GetSettings().GetLanguageTag().getLocale(); +} + + +// XAccessibleComponent + + +Reference< XAccessible > AccessibleDialogControlShape::getAccessibleAtPoint( const awt::Point& ) +{ + OExternalLockGuard aGuard( this ); + + return Reference< XAccessible >(); +} + + +void AccessibleDialogControlShape::grabFocus( ) +{ + // no focus for shapes +} + + +sal_Int32 AccessibleDialogControlShape::getForeground( ) +{ + OExternalLockGuard aGuard( this ); + + Color nColor; + vcl::Window* pWindow = GetWindow(); + if ( pWindow ) + { + if ( pWindow->IsControlForeground() ) + nColor = pWindow->GetControlForeground(); + else + { + vcl::Font aFont; + if ( pWindow->IsControlFont() ) + aFont = pWindow->GetControlFont(); + else + aFont = pWindow->GetFont(); + nColor = aFont.GetColor(); + } + } + + return sal_Int32(nColor); +} + + +sal_Int32 AccessibleDialogControlShape::getBackground( ) +{ + OExternalLockGuard aGuard( this ); + + Color nColor; + vcl::Window* pWindow = GetWindow(); + if ( pWindow ) + { + if ( pWindow->IsControlBackground() ) + nColor = pWindow->GetControlBackground(); + else + nColor = pWindow->GetBackground().GetColor(); + } + + return sal_Int32(nColor); +} + + +// XAccessibleExtendedComponent + + +Reference< awt::XFont > AccessibleDialogControlShape::getFont( ) +{ + OExternalLockGuard aGuard( this ); + + Reference< awt::XFont > xFont; + vcl::Window* pWindow = GetWindow(); + if ( pWindow ) + { + Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), UNO_QUERY ); + if ( xDev.is() ) + { + vcl::Font aFont; + if ( pWindow->IsControlFont() ) + aFont = pWindow->GetControlFont(); + else + aFont = pWindow->GetFont(); + rtl::Reference<VCLXFont> pVCLXFont = new VCLXFont; + pVCLXFont->Init( *xDev, aFont ); + xFont = pVCLXFont; + } + } + + return xFont; +} + + +OUString AccessibleDialogControlShape::getTitledBorderText( ) +{ + OExternalLockGuard aGuard( this ); + + return OUString(); +} + + +OUString AccessibleDialogControlShape::getToolTipText( ) +{ + OExternalLockGuard aGuard( this ); + + OUString sText; + vcl::Window* pWindow = GetWindow(); + if ( pWindow ) + sText = pWindow->GetQuickHelpText(); + + return sText; +} + + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/basctl/source/accessibility/accessibledialogwindow.cxx b/basctl/source/accessibility/accessibledialogwindow.cxx new file mode 100644 index 000000000..e52d08bfe --- /dev/null +++ b/basctl/source/accessibility/accessibledialogwindow.cxx @@ -0,0 +1,945 @@ +/* -*- 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 <accessibledialogwindow.hxx> +#include <accessibledialogcontrolshape.hxx> +#include <baside3.hxx> +#include <dlged.hxx> +#include <dlgedmod.hxx> +#include <dlgedpage.hxx> +#include <dlgedview.hxx> +#include <dlgedobj.hxx> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <tools/debug.hxx> +#include <unotools/accessiblestatesethelper.hxx> +#include <unotools/accessiblerelationsethelper.hxx> +#include <toolkit/awt/vclxfont.hxx> +#include <toolkit/helper/convert.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <i18nlangtag/languagetag.hxx> + +namespace basctl +{ + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::accessibility; +using namespace ::comphelper; + +AccessibleDialogWindow::ChildDescriptor::ChildDescriptor( DlgEdObj* _pDlgEdObj ) + :pDlgEdObj( _pDlgEdObj ) +{ +} + +bool AccessibleDialogWindow::ChildDescriptor::operator==( const ChildDescriptor& rDesc ) +{ + bool bRet = false; + if ( pDlgEdObj == rDesc.pDlgEdObj ) + bRet = true; + + return bRet; +} + + +bool AccessibleDialogWindow::ChildDescriptor::operator<( const ChildDescriptor& rDesc ) const +{ + bool bRet = false; + if ( pDlgEdObj && rDesc.pDlgEdObj && pDlgEdObj->GetOrdNum() < rDesc.pDlgEdObj->GetOrdNum() ) + bRet = true; + + return bRet; +} + + + + +AccessibleDialogWindow::AccessibleDialogWindow (basctl::DialogWindow* pDialogWindow) + : m_pDialogWindow(pDialogWindow) + , m_pDlgEdModel(nullptr) +{ + if ( !m_pDialogWindow ) + return; + + SdrPage& rPage = m_pDialogWindow->GetPage(); + const size_t nCount = rPage.GetObjCount(); + + for ( size_t i = 0; i < nCount; ++i ) + { + if (DlgEdObj* pDlgEdObj = dynamic_cast<DlgEdObj*>(rPage.GetObj(i))) + { + ChildDescriptor aDesc( pDlgEdObj ); + if ( IsChildVisible( aDesc ) ) + m_aAccessibleChildren.push_back( aDesc ); + } + } + + m_pDialogWindow->AddEventListener( LINK( this, AccessibleDialogWindow, WindowEventListener ) ); + + StartListening(m_pDialogWindow->GetEditor()); + + m_pDlgEdModel = &m_pDialogWindow->GetModel(); + StartListening(*m_pDlgEdModel); +} + + +AccessibleDialogWindow::~AccessibleDialogWindow() +{ + if ( m_pDialogWindow ) + m_pDialogWindow->RemoveEventListener( LINK( this, AccessibleDialogWindow, WindowEventListener ) ); + + if ( m_pDlgEdModel ) + EndListening( *m_pDlgEdModel ); +} + + +void AccessibleDialogWindow::UpdateFocused() +{ + for (const ChildDescriptor & i : m_aAccessibleChildren) + { + Reference< XAccessible > xChild( i.rxAccessible ); + if ( xChild.is() ) + { + AccessibleDialogControlShape* pShape = static_cast< AccessibleDialogControlShape* >( xChild.get() ); + if ( pShape ) + pShape->SetFocused( pShape->IsFocused() ); + } + } +} + + +void AccessibleDialogWindow::UpdateSelected() +{ + NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() ); + + for (const ChildDescriptor & i : m_aAccessibleChildren) + { + Reference< XAccessible > xChild( i.rxAccessible ); + if ( xChild.is() ) + { + AccessibleDialogControlShape* pShape = static_cast< AccessibleDialogControlShape* >( xChild.get() ); + if ( pShape ) + pShape->SetSelected( pShape->IsSelected() ); + } + } +} + + +void AccessibleDialogWindow::UpdateBounds() +{ + for (const ChildDescriptor & i : m_aAccessibleChildren) + { + Reference< XAccessible > xChild( i.rxAccessible ); + if ( xChild.is() ) + { + AccessibleDialogControlShape* pShape = static_cast< AccessibleDialogControlShape* >( xChild.get() ); + if ( pShape ) + pShape->SetBounds( pShape->GetBounds() ); + } + } +} + + +bool AccessibleDialogWindow::IsChildVisible( const ChildDescriptor& rDesc ) +{ + bool bVisible = false; + + if ( m_pDialogWindow ) + { + // first check, if the shape is in a visible layer + SdrLayerAdmin& rLayerAdmin = m_pDialogWindow->GetModel().GetLayerAdmin(); + DlgEdObj* pDlgEdObj = rDesc.pDlgEdObj; + if ( pDlgEdObj ) + { + SdrLayerID nLayerId = pDlgEdObj->GetLayer(); + const SdrLayer* pSdrLayer = rLayerAdmin.GetLayerPerID( nLayerId ); + if ( pSdrLayer ) + { + const OUString& aLayerName = pSdrLayer->GetName(); + SdrView& rView = m_pDialogWindow->GetView(); + if (rView.IsLayerVisible(aLayerName)) + { + // get the bounding box of the shape in logic units + tools::Rectangle aRect = pDlgEdObj->GetSnapRect(); + + // transform coordinates relative to the parent + MapMode aMap = m_pDialogWindow->GetMapMode(); + Point aOrg = aMap.GetOrigin(); + aRect.Move( aOrg.X(), aOrg.Y() ); + + // convert logic units to pixel + aRect = m_pDialogWindow->LogicToPixel( aRect, MapMode(MapUnit::Map100thMM) ); + + // check, if the shape's bounding box intersects with the bounding box of its parent + tools::Rectangle aParentRect( Point( 0, 0 ), m_pDialogWindow->GetSizePixel() ); + if ( aParentRect.Overlaps( aRect ) ) + bVisible = true; + } + } + } + } + + return bVisible; +} + + +void AccessibleDialogWindow::InsertChild( const ChildDescriptor& rDesc ) +{ + // check, if object is already in child list + AccessibleChildren::iterator aIter = std::find( m_aAccessibleChildren.begin(), m_aAccessibleChildren.end(), rDesc ); + + // if not found, insert in child list + if ( aIter != m_aAccessibleChildren.end() ) + return; + + // insert entry in child list + m_aAccessibleChildren.push_back( rDesc ); + + // get the accessible of the inserted child + Reference< XAccessible > xChild( getAccessibleChild( m_aAccessibleChildren.size() - 1 ) ); + + // sort child list + SortChildren(); + + // send accessible child event + if ( xChild.is() ) + { + Any aOldValue, aNewValue; + aNewValue <<= xChild; + NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue ); + } +} + + +void AccessibleDialogWindow::RemoveChild( const ChildDescriptor& rDesc ) +{ + // find object in child list + AccessibleChildren::iterator aIter = std::find( m_aAccessibleChildren.begin(), m_aAccessibleChildren.end(), rDesc ); + + // if found, remove from child list + if ( aIter == m_aAccessibleChildren.end() ) + return; + + // get the accessible of the removed child + Reference< XAccessible > xChild( aIter->rxAccessible ); + + // remove entry from child list + m_aAccessibleChildren.erase( aIter ); + + // send accessible child event + if ( xChild.is() ) + { + Any aOldValue, aNewValue; + aOldValue <<= xChild; + NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue ); + + Reference< XComponent > xComponent( xChild, UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); + } +} + + +void AccessibleDialogWindow::UpdateChild( const ChildDescriptor& rDesc ) +{ + if ( IsChildVisible( rDesc ) ) + { + // if the object is not in the child list, insert child + InsertChild( rDesc ); + } + else + { + // if the object is in the child list, remove child + RemoveChild( rDesc ); + } +} + + +void AccessibleDialogWindow::UpdateChildren() +{ + if ( m_pDialogWindow ) + { + SdrPage& rPage = m_pDialogWindow->GetPage(); + for ( size_t i = 0, nCount = rPage.GetObjCount(); i < nCount; ++i ) + if (DlgEdObj* pDlgEdObj = dynamic_cast<DlgEdObj*>(rPage.GetObj(i))) + UpdateChild( ChildDescriptor( pDlgEdObj ) ); + } +} + + +void AccessibleDialogWindow::SortChildren() +{ + // sort child list + std::sort( m_aAccessibleChildren.begin(), m_aAccessibleChildren.end() ); +} + + +IMPL_LINK( AccessibleDialogWindow, WindowEventListener, VclWindowEvent&, rEvent, void ) +{ + DBG_ASSERT(rEvent.GetWindow(), "AccessibleDialogWindow::WindowEventListener: no window!"); + if (!rEvent.GetWindow()->IsAccessibilityEventsSuppressed() || rEvent.GetId() == VclEventId::ObjectDying) + ProcessWindowEvent(rEvent); +} + + +void AccessibleDialogWindow::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) +{ + Any aOldValue, aNewValue; + + switch ( rVclWindowEvent.GetId() ) + { + case VclEventId::WindowEnabled: + { + aNewValue <<= AccessibleStateType::ENABLED; + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + } + break; + case VclEventId::WindowDisabled: + { + aOldValue <<= AccessibleStateType::ENABLED; + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + } + break; + case VclEventId::WindowActivate: + { + aNewValue <<= AccessibleStateType::ACTIVE; + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + } + break; + case VclEventId::WindowDeactivate: + { + aOldValue <<= AccessibleStateType::ACTIVE; + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + } + break; + case VclEventId::WindowGetFocus: + { + aNewValue <<= AccessibleStateType::FOCUSED; + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + } + break; + case VclEventId::WindowLoseFocus: + { + aOldValue <<= AccessibleStateType::FOCUSED; + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + } + break; + case VclEventId::WindowShow: + { + aNewValue <<= AccessibleStateType::SHOWING; + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + } + break; + case VclEventId::WindowHide: + { + aOldValue <<= AccessibleStateType::SHOWING; + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); + } + break; + case VclEventId::WindowResize: + { + NotifyAccessibleEvent( AccessibleEventId::BOUNDRECT_CHANGED, aOldValue, aNewValue ); + UpdateChildren(); + UpdateBounds(); + } + break; + case VclEventId::ObjectDying: + { + if ( m_pDialogWindow ) + { + m_pDialogWindow->RemoveEventListener( LINK( this, AccessibleDialogWindow, WindowEventListener ) ); + m_pDialogWindow = nullptr; + + if ( m_pDlgEdModel ) + EndListening( *m_pDlgEdModel ); + m_pDlgEdModel = nullptr; + + // dispose all children + for (const ChildDescriptor & i : m_aAccessibleChildren) + { + Reference< XComponent > xComponent( i.rxAccessible, UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); + } + m_aAccessibleChildren.clear(); + } + } + break; + default: + { + } + break; + } +} + + +void AccessibleDialogWindow::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet ) +{ + if ( !m_pDialogWindow ) + return; + + if ( m_pDialogWindow->IsEnabled() ) + rStateSet.AddState( AccessibleStateType::ENABLED ); + + rStateSet.AddState( AccessibleStateType::FOCUSABLE ); + + if ( m_pDialogWindow->HasFocus() ) + rStateSet.AddState( AccessibleStateType::FOCUSED ); + + rStateSet.AddState( AccessibleStateType::VISIBLE ); + + if ( m_pDialogWindow->IsVisible() ) + rStateSet.AddState( AccessibleStateType::SHOWING ); + + rStateSet.AddState( AccessibleStateType::OPAQUE ); + + rStateSet.AddState( AccessibleStateType::RESIZABLE ); +} + + +// OCommonAccessibleComponent + + +awt::Rectangle AccessibleDialogWindow::implGetBounds() +{ + awt::Rectangle aBounds; + if ( m_pDialogWindow ) + aBounds = AWTRectangle( tools::Rectangle( m_pDialogWindow->GetPosPixel(), m_pDialogWindow->GetSizePixel() ) ); + + return aBounds; +} + + +// SfxListener + + +void AccessibleDialogWindow::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if (SdrHint const* pSdrHint = dynamic_cast<SdrHint const*>(&rHint)) + { + switch ( pSdrHint->GetKind() ) + { + case SdrHintKind::ObjectInserted: + { + if (DlgEdObj const* pDlgEdObj = dynamic_cast<DlgEdObj const*>(pSdrHint->GetObject())) + { + ChildDescriptor aDesc(const_cast<DlgEdObj*>(pDlgEdObj)); + if ( IsChildVisible( aDesc ) ) + InsertChild( aDesc ); + } + } + break; + case SdrHintKind::ObjectRemoved: + { + if (DlgEdObj const* pDlgEdObj = dynamic_cast<DlgEdObj const*>(pSdrHint->GetObject())) + RemoveChild( ChildDescriptor(const_cast<DlgEdObj*>(pDlgEdObj)) ); + } + break; + default: ; + } + } + else if (DlgEdHint const* pDlgEdHint = dynamic_cast<DlgEdHint const*>(&rHint)) + { + switch (pDlgEdHint->GetKind()) + { + case DlgEdHint::WINDOWSCROLLED: + { + UpdateChildren(); + UpdateBounds(); + } + break; + case DlgEdHint::LAYERCHANGED: + { + if (DlgEdObj* pDlgEdObj = pDlgEdHint->GetObject()) + UpdateChild( ChildDescriptor( pDlgEdObj ) ); + } + break; + case DlgEdHint::OBJORDERCHANGED: + { + SortChildren(); + } + break; + case DlgEdHint::SELECTIONCHANGED: + { + UpdateFocused(); + UpdateSelected(); + } + break; + default: ; + } + } +} + + +// XInterface + + +IMPLEMENT_FORWARD_XINTERFACE2( AccessibleDialogWindow, OAccessibleExtendedComponentHelper, AccessibleDialogWindow_BASE ) + + +// XTypeProvider + + +IMPLEMENT_FORWARD_XTYPEPROVIDER2( AccessibleDialogWindow, OAccessibleExtendedComponentHelper, AccessibleDialogWindow_BASE ) + + +// XComponent + + +void AccessibleDialogWindow::disposing() +{ + OAccessibleExtendedComponentHelper::disposing(); + + if ( !m_pDialogWindow ) + return; + + m_pDialogWindow->RemoveEventListener( LINK( this, AccessibleDialogWindow, WindowEventListener ) ); + m_pDialogWindow = nullptr; + + if ( m_pDlgEdModel ) + EndListening( *m_pDlgEdModel ); + m_pDlgEdModel = nullptr; + + // dispose all children + for (const ChildDescriptor & i : m_aAccessibleChildren) + { + Reference< XComponent > xComponent( i.rxAccessible, UNO_QUERY ); + if ( xComponent.is() ) + xComponent->dispose(); + } + m_aAccessibleChildren.clear(); +} + +// XServiceInfo +OUString AccessibleDialogWindow::getImplementationName() +{ + return "com.sun.star.comp.basctl.AccessibleWindow"; +} + +sal_Bool AccessibleDialogWindow::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +Sequence< OUString > AccessibleDialogWindow::getSupportedServiceNames() +{ + return { "com.sun.star.awt.AccessibleWindow" }; +} + +// XAccessible +Reference< XAccessibleContext > AccessibleDialogWindow::getAccessibleContext( ) +{ + return this; +} + +// XAccessibleContext +sal_Int32 AccessibleDialogWindow::getAccessibleChildCount() +{ + OExternalLockGuard aGuard( this ); + + return m_aAccessibleChildren.size(); +} + + +Reference< XAccessible > AccessibleDialogWindow::getAccessibleChild( sal_Int32 i ) +{ + OExternalLockGuard aGuard( this ); + + if ( i < 0 || i >= getAccessibleChildCount() ) + throw IndexOutOfBoundsException(); + + Reference< XAccessible > xChild = m_aAccessibleChildren[i].rxAccessible; + if ( !xChild.is() ) + { + if ( m_pDialogWindow ) + { + DlgEdObj* pDlgEdObj = m_aAccessibleChildren[i].pDlgEdObj; + if ( pDlgEdObj ) + { + xChild = new AccessibleDialogControlShape( m_pDialogWindow, pDlgEdObj ); + + // insert into child list + m_aAccessibleChildren[i].rxAccessible = xChild; + } + } + } + + return xChild; +} + + +Reference< XAccessible > AccessibleDialogWindow::getAccessibleParent( ) +{ + OExternalLockGuard aGuard( this ); + + Reference< XAccessible > xParent; + if ( m_pDialogWindow ) + { + vcl::Window* pParent = m_pDialogWindow->GetAccessibleParentWindow(); + if ( pParent ) + xParent = pParent->GetAccessible(); + } + + return xParent; +} + + +sal_Int32 AccessibleDialogWindow::getAccessibleIndexInParent( ) +{ + OExternalLockGuard aGuard( this ); + + sal_Int32 nIndexInParent = -1; + if ( m_pDialogWindow ) + { + vcl::Window* pParent = m_pDialogWindow->GetAccessibleParentWindow(); + if ( pParent ) + { + for ( sal_uInt16 i = 0, nCount = pParent->GetAccessibleChildWindowCount(); i < nCount; ++i ) + { + vcl::Window* pChild = pParent->GetAccessibleChildWindow( i ); + if ( pChild == static_cast< vcl::Window* >( m_pDialogWindow ) ) + { + nIndexInParent = i; + break; + } + } + } + } + + return nIndexInParent; +} + + +sal_Int16 AccessibleDialogWindow::getAccessibleRole( ) +{ + OExternalLockGuard aGuard( this ); + + return AccessibleRole::PANEL; +} + + +OUString AccessibleDialogWindow::getAccessibleDescription( ) +{ + OExternalLockGuard aGuard( this ); + + OUString sDescription; + if ( m_pDialogWindow ) + sDescription = m_pDialogWindow->GetAccessibleDescription(); + + return sDescription; +} + + +OUString AccessibleDialogWindow::getAccessibleName( ) +{ + OExternalLockGuard aGuard( this ); + + OUString sName; + if ( m_pDialogWindow ) + sName = m_pDialogWindow->GetAccessibleName(); + + return sName; +} + + +Reference< XAccessibleRelationSet > AccessibleDialogWindow::getAccessibleRelationSet( ) +{ + OExternalLockGuard aGuard( this ); + + return new utl::AccessibleRelationSetHelper; +} + + +Reference< XAccessibleStateSet > AccessibleDialogWindow::getAccessibleStateSet( ) +{ + OExternalLockGuard aGuard( this ); + + rtl::Reference<utl::AccessibleStateSetHelper> pStateSetHelper = new utl::AccessibleStateSetHelper; + + if ( !rBHelper.bDisposed && !rBHelper.bInDispose ) + { + FillAccessibleStateSet( *pStateSetHelper ); + } + else + { + pStateSetHelper->AddState( AccessibleStateType::DEFUNC ); + } + + return pStateSetHelper; +} + + +Locale AccessibleDialogWindow::getLocale( ) +{ + OExternalLockGuard aGuard( this ); + + return Application::GetSettings().GetLanguageTag().getLocale(); +} + + +// XAccessibleComponent + + +Reference< XAccessible > AccessibleDialogWindow::getAccessibleAtPoint( const awt::Point& rPoint ) +{ + OExternalLockGuard aGuard( this ); + + Reference< XAccessible > xChild; + for ( size_t i = 0; i < m_aAccessibleChildren.size(); ++i ) + { + Reference< XAccessible > xAcc = getAccessibleChild( i ); + if ( xAcc.is() ) + { + Reference< XAccessibleComponent > xComp( xAcc->getAccessibleContext(), UNO_QUERY ); + if ( xComp.is() ) + { + tools::Rectangle aRect = VCLRectangle( xComp->getBounds() ); + Point aPos = VCLPoint( rPoint ); + if ( aRect.Contains( aPos ) ) + { + xChild = xAcc; + break; + } + } + } + } + + return xChild; +} + + +void AccessibleDialogWindow::grabFocus( ) +{ + OExternalLockGuard aGuard( this ); + + if ( m_pDialogWindow ) + m_pDialogWindow->GrabFocus(); +} + + +sal_Int32 AccessibleDialogWindow::getForeground( ) +{ + OExternalLockGuard aGuard( this ); + + Color nColor; + if ( m_pDialogWindow ) + { + if ( m_pDialogWindow->IsControlForeground() ) + nColor = m_pDialogWindow->GetControlForeground(); + else + { + vcl::Font aFont; + if ( m_pDialogWindow->IsControlFont() ) + aFont = m_pDialogWindow->GetControlFont(); + else + aFont = m_pDialogWindow->GetFont(); + nColor = aFont.GetColor(); + } + } + + return sal_Int32(nColor); +} + + +sal_Int32 AccessibleDialogWindow::getBackground( ) +{ + OExternalLockGuard aGuard( this ); + + Color nColor; + if ( m_pDialogWindow ) + { + if ( m_pDialogWindow->IsControlBackground() ) + nColor = m_pDialogWindow->GetControlBackground(); + else + nColor = m_pDialogWindow->GetBackground().GetColor(); + } + + return sal_Int32(nColor); +} + + +// XAccessibleExtendedComponent + + +Reference< awt::XFont > AccessibleDialogWindow::getFont( ) +{ + OExternalLockGuard aGuard( this ); + + Reference< awt::XFont > xFont; + if ( m_pDialogWindow ) + { + Reference< awt::XDevice > xDev( m_pDialogWindow->GetComponentInterface(), UNO_QUERY ); + if ( xDev.is() ) + { + vcl::Font aFont; + if ( m_pDialogWindow->IsControlFont() ) + aFont = m_pDialogWindow->GetControlFont(); + else + aFont = m_pDialogWindow->GetFont(); + rtl::Reference<VCLXFont> pVCLXFont = new VCLXFont; + pVCLXFont->Init( *xDev, aFont ); + xFont = pVCLXFont; + } + } + + return xFont; +} + + +OUString AccessibleDialogWindow::getTitledBorderText( ) +{ + OExternalLockGuard aGuard( this ); + + return OUString(); +} + + +OUString AccessibleDialogWindow::getToolTipText( ) +{ + OExternalLockGuard aGuard( this ); + + OUString sText; + if ( m_pDialogWindow ) + sText = m_pDialogWindow->GetQuickHelpText(); + + return sText; +} + + +// XAccessibleSelection + + +void AccessibleDialogWindow::selectAccessibleChild( sal_Int32 nChildIndex ) +{ + OExternalLockGuard aGuard( this ); + + if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() ) + throw IndexOutOfBoundsException(); + + if ( m_pDialogWindow ) + { + if (DlgEdObj* pDlgEdObj = m_aAccessibleChildren[nChildIndex].pDlgEdObj) + { + SdrView& rView = m_pDialogWindow->GetView(); + if (SdrPageView* pPgView = rView.GetSdrPageView()) + rView.MarkObj(pDlgEdObj, pPgView); + } + } +} + + +sal_Bool AccessibleDialogWindow::isAccessibleChildSelected( sal_Int32 nChildIndex ) +{ + OExternalLockGuard aGuard( this ); + + if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() ) + throw IndexOutOfBoundsException(); + + if (m_pDialogWindow) + if (DlgEdObj* pDlgEdObj = m_aAccessibleChildren[nChildIndex].pDlgEdObj) + return m_pDialogWindow->GetView().IsObjMarked(pDlgEdObj); + return false; +} + + +void AccessibleDialogWindow::clearAccessibleSelection() +{ + OExternalLockGuard aGuard( this ); + + if ( m_pDialogWindow ) + m_pDialogWindow->GetView().UnmarkAll(); +} + + +void AccessibleDialogWindow::selectAllAccessibleChildren( ) +{ + OExternalLockGuard aGuard( this ); + + if ( m_pDialogWindow ) + m_pDialogWindow->GetView().MarkAll(); +} + + +sal_Int32 AccessibleDialogWindow::getSelectedAccessibleChildCount( ) +{ + OExternalLockGuard aGuard( this ); + + sal_Int32 nRet = 0; + + for ( sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i ) + { + if ( isAccessibleChildSelected( i ) ) + ++nRet; + } + + return nRet; +} + + +Reference< XAccessible > AccessibleDialogWindow::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) +{ + OExternalLockGuard aGuard( this ); + + if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() ) + throw IndexOutOfBoundsException(); + + Reference< XAccessible > xChild; + + for ( sal_Int32 i = 0, j = 0, nCount = getAccessibleChildCount(); i < nCount; ++i ) + { + if ( isAccessibleChildSelected( i ) && ( j++ == nSelectedChildIndex ) ) + { + xChild = getAccessibleChild( i ); + break; + } + } + + return xChild; +} + + +void AccessibleDialogWindow::deselectAccessibleChild( sal_Int32 nChildIndex ) +{ + OExternalLockGuard aGuard( this ); + + if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() ) + throw IndexOutOfBoundsException(); + + if ( m_pDialogWindow ) + { + if (DlgEdObj* pDlgEdObj = m_aAccessibleChildren[nChildIndex].pDlgEdObj) + { + SdrView& rView = m_pDialogWindow->GetView(); + SdrPageView* pPgView = rView.GetSdrPageView(); + if (pPgView) + rView.MarkObj( pDlgEdObj, pPgView, true ); + } + } +} + + +} // namespace basctl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |