1
0
Fork 0
libreoffice/basctl/source/accessibility/accessibledialogcontrolshape.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

507 lines
13 KiB
C++

/* -*- 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/awt/XVclWindowPeer.hpp>
#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/accessiblerelationsethelper.hxx>
#include <toolkit/awt/vclxfont.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <comphelper/accessiblecontexthelper.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>
#include <vcl/unohelp.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 = vcl::unohelper::ConvertToAWTRect(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( sal_Int64& rStateSet )
{
rStateSet |= AccessibleStateType::ENABLED;
rStateSet |= AccessibleStateType::VISIBLE;
rStateSet |= AccessibleStateType::SHOWING;
rStateSet |= AccessibleStateType::FOCUSABLE;
if ( IsFocused() )
rStateSet |= AccessibleStateType::FOCUSED;
rStateSet |= AccessibleStateType::SELECTABLE;
if ( IsSelected() )
rStateSet |= AccessibleStateType::SELECTED;
rStateSet |= AccessibleStateType::RESIZABLE;
}
// OCommonAccessibleComponent
awt::Rectangle AccessibleDialogControlShape::implGetBounds()
{
return GetBounds();
}
// 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 u"com.sun.star.comp.basctl.AccessibleShape"_ustr;
}
sal_Bool AccessibleDialogControlShape::supportsService( const OUString& rServiceName )
{
return cppu::supportsService(this, rServiceName);
}
Sequence< OUString > AccessibleDialogControlShape::getSupportedServiceNames()
{
return { u"com.sun.star.drawing.AccessibleShape"_ustr };
}
// XAccessible
Reference< XAccessibleContext > AccessibleDialogControlShape::getAccessibleContext( )
{
return this;
}
// XAccessibleContext
sal_Int64 AccessibleDialogControlShape::getAccessibleChildCount()
{
return 0;
}
Reference< XAccessible > AccessibleDialogControlShape::getAccessibleChild( sal_Int64 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_Int64 AccessibleDialogControlShape::getAccessibleIndexInParent( )
{
OExternalLockGuard aGuard( this );
sal_Int64 nIndexInParent = -1;
Reference< XAccessible > xParent( getAccessibleParent() );
if ( xParent.is() )
{
Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
if ( xParentContext.is() )
{
for ( sal_Int64 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( u"HelpText"_ustr );
}
OUString AccessibleDialogControlShape::getAccessibleName( )
{
OExternalLockGuard aGuard( this );
return GetModelStringProperty( u"Name"_ustr );
}
Reference< XAccessibleRelationSet > AccessibleDialogControlShape::getAccessibleRelationSet( )
{
OExternalLockGuard aGuard( this );
return new utl::AccessibleRelationSetHelper;
}
sal_Int64 AccessibleDialogControlShape::getAccessibleStateSet( )
{
OExternalLockGuard aGuard( this );
sal_Int64 nStateSet = 0;
if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
{
FillAccessibleStateSet( nStateSet );
}
else
{
nStateSet |= AccessibleStateType::DEFUNC;
}
return nStateSet;
}
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
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: */