23#include <com/sun/star/awt/XWindow.hpp>
24#include <com/sun/star/beans/XPropertySet.hpp>
25#include <com/sun/star/drawing/XControlShape.hpp>
26#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
27#include <com/sun/star/accessibility/AccessibleRole.hpp>
28#include <com/sun/star/accessibility/AccessibleEventId.hpp>
29#include <com/sun/star/accessibility/AccessibleStateType.hpp>
30#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
31#include <com/sun/star/reflection/ProxyFactory.hpp>
32#include <com/sun/star/util/XModeChangeBroadcaster.hpp>
33#include <com/sun/star/container/XContainer.hpp>
44#include <svx/strings.hrc>
64 OUString lcl_getNamePropertyName( )
68 OUString lcl_getDescPropertyName( )
72 OUString lcl_getLabelPropertyName( )
76 OUString lcl_getLabelControlPropertyName( )
78 return "LabelControl";
81 OUString lcl_getPreferredAccNameProperty(
const Reference< XPropertySetInfo >& _rxPSI )
83 if ( _rxPSI.is() && _rxPSI->hasPropertyByName( lcl_getLabelPropertyName() ) )
84 return lcl_getLabelPropertyName();
86 return lcl_getNamePropertyName();
91 bool isComposedState(
const sal_Int64 _nState )
93 return ( ( AccessibleStateType::INVALID != _nState )
94 && ( AccessibleStateType::DEFUNC != _nState )
95 && ( AccessibleStateType::ICONIFIED != _nState )
96 && ( AccessibleStateType::RESIZABLE != _nState )
97 && ( AccessibleStateType::SELECTABLE != _nState )
98 && ( AccessibleStateType::SHOWING != _nState )
99 && ( AccessibleStateType::MANAGES_DESCENDANTS != _nState )
100 && ( AccessibleStateType::VISIBLE != _nState )
105 bool isAliveMode(
const Reference< XControl >& _rxControl )
107 OSL_PRECOND( _rxControl.is(),
"AccessibleControlShape::isAliveMode: invalid control" );
108 return _rxControl.is() && !_rxControl->isDesignMode();
112AccessibleControlShape::AccessibleControlShape (
116 , m_bListeningForName( false )
117 , m_bListeningForDesc( false )
118 , m_bMultiplexingStates( false )
119 , m_bDisposeNativeContext( false )
120 , m_bWaitingForControl( false )
145 Reference< XContainer > lcl_getControlContainer(
const OutputDevice* _pWin,
const SdrView* _pView )
147 Reference< XContainer > xReturn;
148 DBG_ASSERT( _pView,
"lcl_getControlContainer: invalid view!" );
191 OSL_ENSURE( pView && pViewWindow && pUnoObjectImpl,
"AccessibleControlShape::Init: no view, or no view window, no SdrUnoObj!" );
193 if ( pView && pViewWindow && pUnoObjectImpl )
206 OSL_ENSURE( !
m_bWaitingForControl,
"AccessibleControlShape::Init: already waiting for the control!" );
209 OSL_ENSURE( xControlContainer.is(),
"AccessibleControlShape::Init: unable to find my ControlContainer!" );
210 if ( xControlContainer.is() )
212 xControlContainer->addContainerListener(
this );
218 Reference< XModeChangeBroadcaster > xControlModes(
m_xUnoControl, UNO_QUERY );
219 Reference< XAccessible > xControlAccessible( xControlModes, UNO_QUERY );
220 Reference< XAccessibleContext > xNativeControlContext;
221 if ( xControlAccessible.is() )
222 xNativeControlContext = xControlAccessible->getAccessibleContext();
223 OSL_ENSURE( xNativeControlContext.is(),
"AccessibleControlShape::Init: no AccessibleContext for the control!" );
224 m_aControlContext = WeakReference< XAccessibleContext >( xNativeControlContext );
227 if ( isAliveMode(
m_xUnoControl ) && xNativeControlContext.is() )
240 m_pChildManager->setTransientChildren( nStates & AccessibleStateType::MANAGES_DESCENDANTS );
247 if ( xNativeControlContext.is() )
267 xControlModes->addModeChangeListener(
this );
274 OSL_FAIL(
"AccessibleControlShape::Init: could not \"aggregate\" the controls XAccessibleContext!" );
288 OSL_ENSURE( xWindow.is(),
"AccessibleControlShape::grabFocus: invalid control!" );
296 return "com.sun.star.comp.accessibility.AccessibleControlShape";
307 sName =
"ControlShape";
310 sName =
"UnknownAccessibleControlShape";
329 if ( sDesc.isEmpty() )
341 aDG.
Initialize (
u"Unknown accessible control shape");
357 ::osl::MutexGuard aGuard(
m_aMutex );
360 if ( _rEvent.PropertyName == lcl_getNamePropertyName()
361 || _rEvent.PropertyName == lcl_getLabelPropertyName() )
364 CreateAccessibleName(),
367 else if ( _rEvent.PropertyName == lcl_getDescPropertyName() )
369 SetAccessibleDescription(
370 CreateAccessibleDescription(),
373#if OSL_DEBUG_LEVEL > 0
376 OSL_FAIL(
"AccessibleControlShape::propertyChange: where did this come from?" );
384 if ( !aReturn.hasValue() )
398 Sequence< Type > aAggregateTypes;
408 if ( AccessibleEventId::STATE_CHANGED == _rEvent.EventId )
411 sal_Int64 nLostState( 0 ), nGainedState( 0 );
412 _rEvent.OldValue >>= nLostState;
413 _rEvent.NewValue >>= nGainedState;
416 if ( isComposedState( nLostState ) )
419 if ( isComposedState( nGainedState ) )
424 AccessibleEventObject aTranslatedEvent( _rEvent );
427 ::osl::MutexGuard aGuard(
m_aMutex );
430 aTranslatedEvent.Source = *
this;
431 m_pChildManager->translateAccessibleEvent( _rEvent, aTranslatedEvent );
444 SAL_INFO(
"sw.uno",
"AccessibleControlShape::modeChanged");
445 Reference<XControl> xSource(rSource.Source, UNO_QUERY);
448 SAL_WARN(
"sw.uno",
"AccessibleControlShape::modeChanged: where did this come from?");
458 SAL_WARN_IF(!bReplaced,
"sw.uno",
"AccessibleControlShape::modeChanged: replacing ourselves away did fail");
467 const bool _bCurrentlyListening,
const bool _bNeedNewListening,
468 const OUString& _rPropertyName )
472 return _bCurrentlyListening;
479 if ( _bNeedNewListening )
480 m_xControlModel->addPropertyChangeListener( _rPropertyName,
static_cast< XPropertyChangeListener*
>(
this ) );
482 m_xControlModel->removePropertyChangeListener( _rPropertyName,
static_cast< XPropertyChangeListener*
>(
this ) );
485 OSL_FAIL(
"AccessibleControlShape::ensureListeningState: this property does not exist at this model!" );
489 OSL_FAIL(
"AccessibleControlShape::ensureListeningState: could not change the listening state!" );
492 return _bNeedNewListening;
507 OSL_ENSURE( xControlContext.is(),
"AccessibleControlShape::getAccessibleChildCount: control context already dead! How this!" );
508 return xControlContext.is() ? xControlContext->getAccessibleChildCount() : 0;
514 Reference< XAccessible > xChild;
517 throw IndexOutOfBoundsException();
530 OSL_ENSURE( xControlContext.is(),
"AccessibleControlShape::getAccessibleChild: control context already dead! How this!" );
531 if ( xControlContext.is() )
533 Reference< XAccessible > xInnerChild( xControlContext->getAccessibleChild(
i ) );
534 OSL_ENSURE( xInnerChild.is(),
"AccessibleControlShape::getAccessibleChild: control context returned nonsense!" );
535 if ( xInnerChild.is() )
543#if OSL_DEBUG_LEVEL > 0
544 sal_Int64 nChildIndex = -1;
545 Reference< XAccessibleContext > xContext;
547 xContext = xChild->getAccessibleContext( );
549 nChildIndex = xContext->getAccessibleIndexInParent( );
550 SAL_WARN_IF( nChildIndex !=
i,
"svx",
"AccessibleControlShape::getAccessibleChild: index mismatch,"
551 " nChildIndex=" << nChildIndex <<
" vs i=" <<
i );
565 css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > aSequence { xAcc };
568 pRelationSetHelper->AddRelation( AccessibleRelation( AccessibleRelationType::MEMBER_OF, aSequence ) );
572 pRelationSetHelper->AddRelation( AccessibleRelation( AccessibleRelationType::LABELED_BY, aSequence ) );
575 return pRelationSetHelper;
584 if ( aAccessibleRole != AccessibleRole::SHAPE
585 && aAccessibleRole != AccessibleRole::RADIO_BUTTON )
597 const OUString& rAccNameProperty = lcl_getPreferredAccNameProperty(
m_xModelPropsMeta );
599 if ( !
sName.getLength() )
631 OSL_FAIL(
"AccessibleControlShape::disposing: this should never happen!" );
635 if ( xContainer.is() )
638 xContainer->removeContainerListener(
this );
647 Reference< XModeChangeBroadcaster > xControlModes(
m_xUnoControl, UNO_QUERY );
648 OSL_ENSURE( xControlModes.is(),
"AccessibleControlShape::disposing: don't have a mode broadcaster anymore!" );
649 if ( xControlModes.is() )
650 xControlModes->removeModeChangeListener(
this );
673 Reference< XControlShape > xShape(
mxShape, UNO_QUERY );
690 OSL_PRECOND( !
m_bMultiplexingStates,
"AccessibleControlShape::startStateMultiplexing: already multiplexing!" );
692#if OSL_DEBUG_LEVEL > 0
695 "AccessibleControlShape::startStateMultiplexing: should be done in alive mode only!" );
698 Reference< XAccessibleEventBroadcaster > xBroadcaster(
m_aControlContext.get(), UNO_QUERY );
699 OSL_ENSURE( xBroadcaster.is(),
"AccessibleControlShape::startStateMultiplexing: no AccessibleEventBroadcaster on the native context!" );
701 if ( xBroadcaster.is() )
703 xBroadcaster->addAccessibleEventListener(
this );
710 OSL_PRECOND(
m_bMultiplexingStates,
"AccessibleControlShape::stopStateMultiplexing: not multiplexing!" );
713 Reference< XAccessibleEventBroadcaster > xBroadcaster(
m_aControlContext.get(), UNO_QUERY );
714 OSL_ENSURE( xBroadcaster.is(),
"AccessibleControlShape::stopStateMultiplexing: no AccessibleEventBroadcaster on the native context!" );
716 if ( xBroadcaster.is() )
718 xBroadcaster->removeAccessibleEventListener(
this );
751 OSL_PRECOND( xNativeContext.is(),
"AccessibleControlShape::adjustAccessibleRole: no inner context!" );
752 if ( xNativeContext.is() )
760 OSL_ENSURE( !isAliveMode(
m_xUnoControl ) || !isComposedState( _nState ),
761 "AccessibleControlShape::SetState: a state which should be determined by the control context is set from outside!" );
775 mnStateSet &= ~AccessibleStateType::SENSITIVE;
776 mnStateSet &= ~AccessibleStateType::FOCUSABLE;
777 mnStateSet &= ~AccessibleStateType::SELECTABLE;
781 OSL_PRECOND( xInnerContext.is(),
"AccessibleControlShape::initializeComposedState: no inner context!" );
782 if ( !xInnerContext.is() )
786 sal_Int64 nInnerStates( xInnerContext->getAccessibleStateSet() );
789 for (
int i = 0;
i < 63; ++
i )
791 sal_Int64
nState = sal_Int64(1) <<
i;
792 if ( (nInnerStates &
nState) && isComposedState(
nState ) )
801 Reference< XContainer > xContainer( _rEvent.Source, UNO_QUERY );
802 Reference< XControl > xControl( _rEvent.Element, UNO_QUERY );
804 OSL_ENSURE( xContainer.is() && xControl.is(),
805 "AccessibleControlShape::elementInserted: invalid event description!" );
807 if ( !xControl.is() )
812 Reference< XInterface > xNewNormalized( xControl->getModel(), UNO_QUERY );
813 Reference< XInterface > xMyModelNormalized(
m_xControlModel, UNO_QUERY );
814 if ( !(xNewNormalized && xMyModelNormalized) )
818 Reference< XInterface > xKeepAlive( *
this );
821 if ( xContainer.is() )
823 xContainer->removeContainerListener(
this );
846 const OUString& rAccLabelControlProperty = lcl_getLabelControlPropertyName();
849 if (::comphelper::hasProperty(rAccLabelControlProperty,
m_xControlModel))
851 sCtlLabelBy =
m_xControlModel->getPropertyValue(rAccLabelControlProperty);
852 if( sCtlLabelBy.hasValue() )
854 Reference< XPropertySet > xAsSet (sCtlLabelBy, UNO_QUERY);
static SdrObject * getSdrObjectFromXShape(const css::uno::Reference< css::uno::XInterface > &xInt)
css::uno::Reference< css::awt::XControlContainer > GetControlContainer(const OutputDevice &_rDevice) const
Looks up the control container belonging to given output device.
SdrPageView * GetSdrPageView() const
css::uno::Reference< css::awt::XControl > GetUnoControl(const SdrView &_rView, const OutputDevice &_rOut) const
virtual void SAL_CALL grabFocus() override
virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext() override
void FireEvent(const css::accessibility::AccessibleEventObject &aEvent)
void SetAccessibleRole(sal_Int16 _nRole)
css::uno::WeakReference< css::accessibility::XAccessibleContext > m_aControlContext
bool ensureListeningState(const bool _bCurrentlyListening, const bool _bNeedNewListening, const OUString &_rPropertyName)
ensures that we're listening for the given property if(and only if!) necessary
virtual void SAL_CALL notifyEvent(const css::accessibility::AccessibleEventObject &aEvent) override
bool ensureControlModelAccess()
ensure that our control model exists(will be retrieved upon need only)
void initializeComposedState()
initializes composed states of the context
virtual void SAL_CALL elementReplaced(const css::container::ContainerEvent &Event) override
virtual OUString SAL_CALL getImplementationName() override
Returns an identifier for the implementation of this object.
bool m_bWaitingForControl
css::uno::Reference< css::lang::XComponent > m_xControlContextComponent
virtual void Init() override
Initialize a new shape.
AccessibleControlShape * GetLabeledByControlShape()
virtual void SAL_CALL grabFocus() override
forward the focus to the contained control(in alive mode)
virtual void SAL_CALL modeChanged(const css::util::ModeChangeEvent &_rSource) override
virtual void SAL_CALL disposing() override
This method is called from the component helper base class while disposing.
void adjustAccessibleRole()
adjusts our AccessibleRole, depending on the control type we're working for
virtual ~AccessibleControlShape() override
virtual void SAL_CALL elementRemoved(const css::container::ContainerEvent &Event) override
rtl::Reference<::comphelper::OWrappedAccessibleChildrenManager > m_pChildManager
virtual void SAL_CALL elementInserted(const css::container::ContainerEvent &Event) override
virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() override
OUString getControlModelStringProperty(const OUString &_rPropertyName) const
(safely) reads the given property from the model of the UNO control
bool m_bMultiplexingStates
virtual bool SetState(sal_Int64 _nState) override
Set the specified state.
virtual sal_Int64 SAL_CALL getAccessibleChildCount() override
Return the number of currently visible children.
OUString CreateAccessibleDescription()
Create a description string that contains the accessible description.
css::uno::Reference< css::beans::XPropertySet > m_xControlModel
virtual OUString CreateAccessibleName() override
Create a unique name string that contains the accessible name.
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int64 i) override
Return the specified child.
css::uno::Reference< css::lang::XTypeProvider > m_xControlContextTypeAccess
css::uno::Reference< css::beans::XPropertySetInfo > m_xModelPropsMeta
css::uno::Reference< css::uno::XAggregation > m_xControlContextProxy
bool m_bDisposeNativeContext
virtual OUString CreateAccessibleBaseName() override
Create a name string that contains the accessible name.
void stopStateMultiplexing()
stops multiplexing the state changes of our aggregate context
css::uno::Reference< css::awt::XControl > m_xUnoControl
void startStateMultiplexing()
starts multiplexing the state changes of our aggregate context
@descr This class is a container for the information specific for a single shape that is passed to th...
This class bundles all information that is passed down the tree of accessible shapes so that each sha...
SdrView * GetSdrView() const
Return the current SdrView.
vcl::Window * GetWindow() const
Return the current Window.
This base class provides a base implementation for all shapes.
virtual OUString CreateAccessibleName() override
Create a unique name string that contains the accessible name.
virtual void Init()
Initialize a new shape.
css::uno::Reference< css::drawing::XShape > mxShape
Reference to the actual shape.
virtual bool ResetState(sal_Int64 aState) override
Reset the specified state.
virtual sal_Int64 SAL_CALL getAccessibleStateSet() override
Return the set of current states.
virtual sal_Int64 SAL_CALL getAccessibleChildCount() override
Return the number of currently visible children.
AccessibleShapeTreeInfo maShapeTreeInfo
Bundle of information passed to all shapes in a document tree.
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) override
virtual void SAL_CALL disposing() override
This method is called from the component helper base class while disposing.
IAccessibleParent * mpParent
This object can be used to modify the child list of our parent.
virtual bool SetState(sal_Int64 aState) override
Set the specified state.
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
virtual sal_Int16 SAL_CALL getAccessibleRole() override
Return this object's role.
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int64 nIndex) override
Return the specified child.
This class creates description strings for shapes.
void AddProperty(const OUString &sPropertyName, PropertyType aType)
Add the given property name and its associated value to the description string.
void Initialize(std::u16string_view sPrefix)
Initialize the description with the given prefix followed by the shape style in parentheses and a col...
void AppendString(std::u16string_view sString)
Append the given string as is to the current description.
virtual bool ReplaceChild(AccessibleShape *pCurrentChild, const css::uno::Reference< css::drawing::XShape > &_rxShape, const tools::Long _nIndex, const AccessibleShapeTreeInfo &_rShapeTreeInfo)=0
A call to this method requests the implementor to replace one child with another and send the appropr...
virtual AccessibleControlShape * GetAccControlShapeFromModel(css::beans::XPropertySet *)
ShapeTypeId GetTypeId(const OUString &aServiceName) const
Determines the type id of a shape with the given service name.
static ShapeTypeHandler & Instance()
This function returns a reference to the only instance of this class.
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
::OutputDevice const * GetOutDev() const
#define DBG_ASSERT(sCon, aError)
#define TOOLS_WARN_EXCEPTION(area, stream)
Reference< XSingleServiceFactory > xFactory
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
int ShapeTypeId
Use an integer to represent shape type ids.
css::uno::Sequence< T > concatSequences(const css::uno::Sequence< T > &rS1, const Ss &... rSn)
Reference< XComponentContext > getProcessComponentContext()
css::uno::Sequence< T > combineSequences(css::uno::Sequence< T > const &left, css::uno::Sequence< T > const &right)
IMPLEMENT_GET_IMPLEMENTATION_ID(DrawController)
#define IMPLEMENT_FORWARD_REFCOUNT(classname, refcountbase)