1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "svxrectctaccessiblecontext.hxx"
21 #include <com/sun/star/accessibility/AccessibleRole.hpp>
22 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
23 #include <unotools/accessiblestatesethelper.hxx>
24 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
25 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
26 #include <com/sun/star/awt/XWindow.hpp>
27 #include <cppuhelper/typeprovider.hxx>
28 #include <cppuhelper/supportsservice.hxx>
29 #include <toolkit/helper/vclunohelper.hxx>
30 #include <toolkit/helper/convert.hxx>
31 #include <vcl/svapp.hxx>
32 #include <osl/mutex.hxx>
33 #include <tools/debug.hxx>
34 #include <tools/gen.hxx>
36 #include <svx/dialogs.hrc>
37 #include "accessibility.hrc"
38 #include <svx/dlgctrl.hxx>
39 #include <svx/dialmgr.hxx>
40 #include <comphelper/accessibleeventnotifier.hxx>
41 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
42 #include <unotools/accessiblerelationsethelper.hxx>
44 using namespace ::cppu
;
45 using namespace ::osl
;
46 using namespace ::com::sun::star
;
47 using namespace ::com::sun::star::uno
;
48 using namespace ::com::sun::star::accessibility
;
50 using namespace ::com::sun::star::lang
;
52 #define MAX_NUM_OF_CHILDREN 9
53 #define NOCHILDSELECTED -1
58 struct ChildIndexToPointData
67 static const ChildIndexToPointData
* IndexToPoint( long nIndex
, bool bAngleControl
)
69 DBG_ASSERT( nIndex
< ( bAngleControl
? 8 : 9 ) && nIndex
>= 0, "-IndexToPoint(): invalid child index! You have been warned..." );
71 // angles are counted reverse counter clock wise
72 static const ChildIndexToPointData pAngleData
[] =
74 { RID_SVXSTR_RECTCTL_ACC_CHLD_A000
, RID_SVXSTR_RECTCTL_ACC_CHLD_A000
, RP_RM
}, // 0
75 { RID_SVXSTR_RECTCTL_ACC_CHLD_A045
, RID_SVXSTR_RECTCTL_ACC_CHLD_A045
, RP_RT
}, // 1
76 { RID_SVXSTR_RECTCTL_ACC_CHLD_A090
, RID_SVXSTR_RECTCTL_ACC_CHLD_A090
, RP_MT
}, // 2
77 { RID_SVXSTR_RECTCTL_ACC_CHLD_A135
, RID_SVXSTR_RECTCTL_ACC_CHLD_A135
, RP_LT
}, // 3
78 { RID_SVXSTR_RECTCTL_ACC_CHLD_A180
, RID_SVXSTR_RECTCTL_ACC_CHLD_A180
, RP_LM
}, // 4
79 { RID_SVXSTR_RECTCTL_ACC_CHLD_A225
, RID_SVXSTR_RECTCTL_ACC_CHLD_A225
, RP_LB
}, // 5
80 { RID_SVXSTR_RECTCTL_ACC_CHLD_A270
, RID_SVXSTR_RECTCTL_ACC_CHLD_A270
, RP_MB
}, // 6
81 { RID_SVXSTR_RECTCTL_ACC_CHLD_A315
, RID_SVXSTR_RECTCTL_ACC_CHLD_A315
, RP_RB
} // 7
84 // corners are counted from left to right and top to bottom
85 static const ChildIndexToPointData pCornerData
[] =
87 { RID_SVXSTR_RECTCTL_ACC_CHLD_LT
, RID_SVXSTR_RECTCTL_ACC_CHLD_LT
, RP_LT
}, // 0
88 { RID_SVXSTR_RECTCTL_ACC_CHLD_MT
, RID_SVXSTR_RECTCTL_ACC_CHLD_MT
, RP_MT
}, // 1
89 { RID_SVXSTR_RECTCTL_ACC_CHLD_RT
, RID_SVXSTR_RECTCTL_ACC_CHLD_RT
, RP_RT
}, // 2
90 { RID_SVXSTR_RECTCTL_ACC_CHLD_LM
, RID_SVXSTR_RECTCTL_ACC_CHLD_LM
, RP_LM
}, // 3
91 { RID_SVXSTR_RECTCTL_ACC_CHLD_MM
, RID_SVXSTR_RECTCTL_ACC_CHLD_MM
, RP_MM
}, // 4
92 { RID_SVXSTR_RECTCTL_ACC_CHLD_RM
, RID_SVXSTR_RECTCTL_ACC_CHLD_RM
, RP_RM
}, // 5
93 { RID_SVXSTR_RECTCTL_ACC_CHLD_LB
, RID_SVXSTR_RECTCTL_ACC_CHLD_LB
, RP_LB
}, // 6
94 { RID_SVXSTR_RECTCTL_ACC_CHLD_MB
, RID_SVXSTR_RECTCTL_ACC_CHLD_MB
, RP_MB
}, // 7
95 { RID_SVXSTR_RECTCTL_ACC_CHLD_RB
, RID_SVXSTR_RECTCTL_ACC_CHLD_RB
, RP_RB
} // 8
98 return ( bAngleControl
? pAngleData
: pCornerData
) + nIndex
;
102 static long PointToIndex( RECT_POINT ePoint
, bool bAngleControl
)
104 long nRet( (long) ePoint
);
107 // angles are counted reverse counter clock wise
110 case RP_LT
: nRet
= 3; break;
111 case RP_MT
: nRet
= 2; break;
112 case RP_RT
: nRet
= 1; break;
113 case RP_LM
: nRet
= 4; break;
114 case RP_MM
: nRet
= NOCHILDSELECTED
; break;
115 case RP_RM
: nRet
= 0; break;
116 case RP_LB
: nRet
= 5; break;
117 case RP_MB
: nRet
= 6; break;
118 case RP_RB
: nRet
= 7; break;
123 // corners are counted from left to right and top to bottom
124 DBG_ASSERT( RP_LT
== 0 && RP_MT
== 1 && RP_RT
== 2 && RP_LM
== 3 && RP_MM
== 4 && RP_RM
== 5 &&
125 RP_LB
== 6 && RP_MB
== 7 && RP_RB
== 8, "*PointToIndex(): unexpected enum value!" );
127 nRet
= ( long ) ePoint
;
134 SvxRectCtlAccessibleContext::SvxRectCtlAccessibleContext(
135 const Reference
< XAccessible
>& rxParent
,
137 const OUString
* pName
,
138 const OUString
* pDesc
) :
140 SvxRectCtlAccessibleContext_Base( m_aMutex
),
141 mxParent( rxParent
),
145 mnSelectedChild( NOCHILDSELECTED
),
146 mbAngleMode( rRepr
.GetNumOfChildren() == 8 )
153 ::SolarMutexGuard aSolarGuard
;
154 msName
= SVX_RESSTR( mbAngleMode
? RID_SVXSTR_RECTCTL_ACC_ANGL_NAME
: RID_SVXSTR_RECTCTL_ACC_CORN_NAME
);
158 msDescription
= *pDesc
;
161 ::SolarMutexGuard aSolarGuard
;
162 msDescription
= SVX_RESSTR( mbAngleMode
? RID_SVXSTR_RECTCTL_ACC_ANGL_DESCR
: RID_SVXSTR_RECTCTL_ACC_CORN_DESCR
);
165 mpChildren
= new SvxRectCtlChildAccessibleContext
*[ MAX_NUM_OF_CHILDREN
];
167 SvxRectCtlChildAccessibleContext
** p
= mpChildren
;
168 for( int i
= MAX_NUM_OF_CHILDREN
; i
; --i
, ++p
)
173 SvxRectCtlAccessibleContext::~SvxRectCtlAccessibleContext()
178 osl_atomic_increment( &m_refCount
);
179 dispose(); // set mpRepr = NULL & release all children
184 Reference
< XAccessibleContext
> SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleContext() throw( RuntimeException
, std::exception
)
189 // XAccessibleComponent
190 sal_Bool SAL_CALL
SvxRectCtlAccessibleContext::containsPoint( const awt::Point
& rPoint
) throw( RuntimeException
, std::exception
)
192 // no guard -> done in getBounds()
193 // return GetBoundingBox().IsInside( VCLPoint( rPoint ) );
194 return Rectangle( Point( 0, 0 ), GetBoundingBox().GetSize() ).IsInside( VCLPoint( rPoint
) );
197 Reference
< XAccessible
> SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleAtPoint( const awt::Point
& rPoint
) throw( RuntimeException
, std::exception
)
199 ::osl::MutexGuard
aGuard( m_aMutex
);
201 ThrowExceptionIfNotAlive();
203 Reference
< XAccessible
> xRet
;
205 long nChild
= PointToIndex( mpRepr
->GetApproxRPFromPixPt( rPoint
), mbAngleMode
);
207 if( nChild
!= NOCHILDSELECTED
)
208 xRet
= getAccessibleChild( nChild
);
213 awt::Rectangle SAL_CALL
SvxRectCtlAccessibleContext::getBounds() throw( RuntimeException
, std::exception
)
215 // no guard -> done in GetBoundingBox()
216 return AWTRectangle( GetBoundingBox() );
219 awt::Point SAL_CALL
SvxRectCtlAccessibleContext::getLocation() throw( RuntimeException
, std::exception
)
221 // no guard -> done in GetBoundingBox()
222 return AWTPoint( GetBoundingBox().TopLeft() );
225 awt::Point SAL_CALL
SvxRectCtlAccessibleContext::getLocationOnScreen() throw( RuntimeException
, std::exception
)
227 // no guard -> done in GetBoundingBoxOnScreen()
228 return AWTPoint( GetBoundingBoxOnScreen().TopLeft() );
231 awt::Size SAL_CALL
SvxRectCtlAccessibleContext::getSize() throw( RuntimeException
, std::exception
)
233 // no guard -> done in GetBoundingBox()
234 return AWTSize( GetBoundingBox().GetSize() );
237 bool SAL_CALL
SvxRectCtlAccessibleContext::isVisible() throw( RuntimeException
)
239 ::osl::MutexGuard
aGuard( m_aMutex
);
241 ThrowExceptionIfNotAlive();
243 return mpRepr
->IsVisible();
246 // XAccessibleContext
247 sal_Int32 SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleChildCount() throw( RuntimeException
, std::exception
)
249 ::osl::MutexGuard
aGuard( m_aMutex
);
251 ThrowExceptionIfNotAlive();
253 return mpRepr
->GetNumOfChildren();
256 Reference
< XAccessible
> SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleChild( sal_Int32 nIndex
)
257 throw( RuntimeException
, lang::IndexOutOfBoundsException
, std::exception
)
259 checkChildIndex( nIndex
);
261 Reference
< XAccessible
> xChild
= mpChildren
[ nIndex
];
264 ::SolarMutexGuard aSolarGuard
;
266 ::osl::MutexGuard
aGuard( m_aMutex
);
268 ThrowExceptionIfNotAlive();
270 xChild
= mpChildren
[ nIndex
];
274 const ChildIndexToPointData
* p
= IndexToPoint( nIndex
, mbAngleMode
);
275 OUString
aName(SVX_RESSTR(p
->nResIdName
));
276 OUString
aDescr(SVX_RESSTR(p
->nResIdDescr
));
278 Rectangle
aFocusRect( mpRepr
->CalculateFocusRectangle( p
->ePoint
) );
280 SvxRectCtlChildAccessibleContext
* pChild
= new SvxRectCtlChildAccessibleContext(
281 this, *mpRepr
, aName
, aDescr
, aFocusRect
, nIndex
);
282 xChild
= mpChildren
[ nIndex
] = pChild
;
286 if( mnSelectedChild
== nIndex
)
287 pChild
->setStateChecked( true );
294 Reference
< XAccessible
> SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleParent() throw( RuntimeException
, std::exception
)
299 sal_Int32 SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleIndexInParent() throw( RuntimeException
, std::exception
)
301 ::osl::MutexGuard
aGuard( m_aMutex
);
302 // Use a simple but slow solution for now. Optimize later.
304 // Iterate over all the parent's children and search for this object.
307 Reference
< XAccessibleContext
> xParentContext( mxParent
->getAccessibleContext() );
308 if( xParentContext
.is() )
310 sal_Int32 nChildCount
= xParentContext
->getAccessibleChildCount();
311 for( sal_Int32 i
= 0 ; i
< nChildCount
; ++i
)
313 Reference
< XAccessible
> xChild( xParentContext
->getAccessibleChild( i
) );
314 if( xChild
.get() == ( XAccessible
* ) this )
320 // Return -1 to indicate that this object's parent does not know about the
325 sal_Int16 SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleRole() throw( RuntimeException
, std::exception
)
327 return AccessibleRole::PANEL
;
330 OUString SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleDescription() throw( RuntimeException
, std::exception
)
332 ::osl::MutexGuard
aGuard( m_aMutex
);
333 return msDescription
+ " Please use arrow key to selection.";
336 OUString SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleName() throw( RuntimeException
, std::exception
)
338 ::osl::MutexGuard
aGuard( m_aMutex
);
342 /** Return empty reference to indicate that the relation set is not
345 Reference
< XAccessibleRelationSet
> SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleRelationSet() throw( RuntimeException
, std::exception
)
347 //return Reference< XAccessibleRelationSet >();
348 utl::AccessibleRelationSetHelper
* pRelationSetHelper
= new utl::AccessibleRelationSetHelper
;
349 uno::Reference
< css::accessibility::XAccessibleRelationSet
> xSet
= pRelationSetHelper
;
350 vcl::Window
* pWindow
= mpRepr
;
353 // vcl::Window *pLabeledBy = pWindow->GetAccRelationLabeledBy();
354 vcl::Window
*pLabeledBy
= pWindow
->GetAccessibleRelationLabeledBy();
355 if ( pLabeledBy
&& pLabeledBy
!= pWindow
)
357 uno::Sequence
< uno::Reference
< uno::XInterface
> > aSequence(1);
358 aSequence
[0] = pLabeledBy
->GetAccessible();
359 pRelationSetHelper
->AddRelation( css::accessibility::AccessibleRelation( css::accessibility::AccessibleRelationType::LABELED_BY
, aSequence
) );
361 vcl::Window
* pMemberOf
= pWindow
->GetAccessibleRelationMemberOf();
362 if ( pMemberOf
&& pMemberOf
!= pWindow
)
364 uno::Sequence
< uno::Reference
< uno::XInterface
> > aSequence(1);
365 aSequence
[0] = pMemberOf
->GetAccessible();
366 pRelationSetHelper
->AddRelation( css::accessibility::AccessibleRelation( css::accessibility::AccessibleRelationType::MEMBER_OF
, aSequence
) );
372 Reference
< XAccessibleStateSet
> SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleStateSet() throw( RuntimeException
, std::exception
)
374 ::osl::MutexGuard
aGuard( m_aMutex
);
375 utl::AccessibleStateSetHelper
* pStateSetHelper
= new utl::AccessibleStateSetHelper
;
379 pStateSetHelper
->AddState( AccessibleStateType::ENABLED
);
380 pStateSetHelper
->AddState( AccessibleStateType::FOCUSABLE
);
381 if( mpRepr
->HasFocus() )
382 pStateSetHelper
->AddState( AccessibleStateType::FOCUSED
);
383 pStateSetHelper
->AddState( AccessibleStateType::OPAQUE
);
385 pStateSetHelper
->AddState( AccessibleStateType::SHOWING
);
388 pStateSetHelper
->AddState( AccessibleStateType::VISIBLE
);
391 pStateSetHelper
->AddState( AccessibleStateType::DEFUNC
);
393 return pStateSetHelper
;
396 lang::Locale SAL_CALL
SvxRectCtlAccessibleContext::getLocale() throw( IllegalAccessibleComponentStateException
, RuntimeException
, std::exception
)
398 ::osl::MutexGuard
aGuard( m_aMutex
);
401 Reference
< XAccessibleContext
> xParentContext( mxParent
->getAccessibleContext() );
402 if( xParentContext
.is() )
403 return xParentContext
->getLocale();
406 // No parent. Therefore throw exception to indicate this cluelessness.
407 throw IllegalAccessibleComponentStateException();
410 void SAL_CALL
SvxRectCtlAccessibleContext::addAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
411 throw( RuntimeException
, std::exception
)
415 ::osl::MutexGuard
aGuard( m_aMutex
);
417 mnClientId
= comphelper::AccessibleEventNotifier::registerClient( );
418 comphelper::AccessibleEventNotifier::addEventListener( mnClientId
, xListener
);
422 void SAL_CALL
SvxRectCtlAccessibleContext::removeAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
423 throw( RuntimeException
, std::exception
)
427 ::osl::MutexGuard
aGuard( m_aMutex
);
429 sal_Int32 nListenerCount
= comphelper::AccessibleEventNotifier::removeEventListener( mnClientId
, xListener
);
430 if ( !nListenerCount
)
432 // no listeners anymore
433 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
434 // and at least to us not firing any events anymore, in case somebody calls
435 // NotifyAccessibleEvent, again
436 comphelper::AccessibleEventNotifier::revokeClient( mnClientId
);
442 void SAL_CALL
SvxRectCtlAccessibleContext::grabFocus() throw( RuntimeException
, std::exception
)
444 ::SolarMutexGuard aSolarGuard
;
445 ::osl::MutexGuard
aGuard( m_aMutex
);
447 ThrowExceptionIfNotAlive();
452 sal_Int32
SvxRectCtlAccessibleContext::getForeground( )
453 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
455 ::SolarMutexGuard aSolarGuard
;
456 ::osl::MutexGuard
aGuard( m_aMutex
);
457 ThrowExceptionIfNotAlive();
459 return mpRepr
->GetControlForeground().GetColor();
461 sal_Int32
SvxRectCtlAccessibleContext::getBackground( )
462 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
464 ::SolarMutexGuard aSolarGuard
;
465 ::osl::MutexGuard
aGuard( m_aMutex
);
466 ThrowExceptionIfNotAlive();
468 return mpRepr
->GetControlBackground().GetColor();
472 OUString SAL_CALL
SvxRectCtlAccessibleContext::getImplementationName() throw( RuntimeException
, std::exception
)
474 return OUString( "com.sun.star.comp.ui.SvxRectCtlAccessibleContext" );
477 sal_Bool SAL_CALL
SvxRectCtlAccessibleContext::supportsService( const OUString
& sServiceName
) throw( RuntimeException
, std::exception
)
479 return cppu::supportsService(this, sServiceName
);
482 Sequence
< OUString
> SAL_CALL
SvxRectCtlAccessibleContext::getSupportedServiceNames() throw( RuntimeException
, std::exception
)
484 const OUString
sServiceName( "com.sun.star.accessibility.AccessibleContext" );
485 return Sequence
< OUString
>( &sServiceName
, 1 );
489 Sequence
< sal_Int8
> SAL_CALL
SvxRectCtlAccessibleContext::getImplementationId() throw( RuntimeException
, std::exception
)
491 return css::uno::Sequence
<sal_Int8
>();
494 // XAccessibleSelection
495 void SAL_CALL
SvxRectCtlAccessibleContext::selectAccessibleChild( sal_Int32 nIndex
) throw( lang::IndexOutOfBoundsException
, RuntimeException
, std::exception
)
497 ::SolarMutexGuard aSolarGuard
;
499 ::osl::MutexGuard
aGuard( m_aMutex
);
501 checkChildIndex( nIndex
);
503 ThrowExceptionIfNotAlive();
505 const ChildIndexToPointData
* pData
= IndexToPoint( nIndex
, mbAngleMode
);
508 "SvxRectCtlAccessibleContext::selectAccessibleChild(): this is an impossible state! Or at least should be..." );
510 // this does all what is needed, including the change of the child's state!
511 mpRepr
->SetActualRP( pData
->ePoint
);
514 sal_Bool SAL_CALL
SvxRectCtlAccessibleContext::isAccessibleChildSelected( sal_Int32 nIndex
) throw( lang::IndexOutOfBoundsException
, RuntimeException
, std::exception
)
516 ::osl::MutexGuard
aGuard( m_aMutex
);
518 checkChildIndex( nIndex
);
520 return nIndex
== mnSelectedChild
;
523 void SAL_CALL
SvxRectCtlAccessibleContext::clearAccessibleSelection() throw( RuntimeException
, std::exception
)
525 DBG_ASSERT( false, "SvxRectCtlAccessibleContext::clearAccessibleSelection() is not possible!" );
528 void SAL_CALL
SvxRectCtlAccessibleContext::selectAllAccessibleChildren() throw( RuntimeException
, std::exception
)
530 // guard in selectAccessibleChild()!
532 selectAccessibleChild( 0 ); // default per definition
535 sal_Int32 SAL_CALL
SvxRectCtlAccessibleContext::getSelectedAccessibleChildCount() throw( RuntimeException
, std::exception
)
537 ::osl::MutexGuard
aGuard( m_aMutex
);
539 return mnSelectedChild
== NOCHILDSELECTED
? 0 : 1;
542 Reference
< XAccessible
> SAL_CALL
SvxRectCtlAccessibleContext::getSelectedAccessibleChild( sal_Int32 nIndex
)
543 throw( lang::IndexOutOfBoundsException
, RuntimeException
, std::exception
)
545 ::osl::MutexGuard
aGuard( m_aMutex
);
547 checkChildIndexOnSelection( nIndex
);
549 return getAccessibleChild( mnSelectedChild
);
552 void SAL_CALL
SvxRectCtlAccessibleContext::deselectAccessibleChild( sal_Int32
/*nIndex*/ ) throw( lang::IndexOutOfBoundsException
, RuntimeException
, std::exception
)
554 OUString
aMessage( "deselectAccessibleChild is not possible in this context" );
556 DBG_ASSERT( false, "SvxRectCtlAccessibleContext::deselectAccessibleChild() is not possible!" );
558 throw lang::IndexOutOfBoundsException( aMessage
, *this ); // never possible
562 void SvxRectCtlAccessibleContext::checkChildIndex( long nIndex
) throw( lang::IndexOutOfBoundsException
)
564 if( nIndex
< 0 || nIndex
>= getAccessibleChildCount() )
565 throw lang::IndexOutOfBoundsException();
568 void SvxRectCtlAccessibleContext::checkChildIndexOnSelection( long nIndex
) throw( lang::IndexOutOfBoundsException
)
570 if( nIndex
|| mnSelectedChild
== NOCHILDSELECTED
)
571 // in our case only for the first (0) _selected_ child this is a valid request
572 throw lang::IndexOutOfBoundsException();
575 void SvxRectCtlAccessibleContext::FireChildFocus( RECT_POINT eButton
)
577 ::osl::MutexGuard
aGuard( m_aMutex
);
578 long nNew
= PointToIndex( eButton
, mbAngleMode
);
579 long nNumOfChildren
= getAccessibleChildCount();
580 if( nNew
< nNumOfChildren
)
583 mnSelectedChild
= nNew
;
584 if( nNew
!= NOCHILDSELECTED
)
586 SvxRectCtlChildAccessibleContext
* pChild
= mpChildren
[ nNew
];
589 pChild
->FireFocusEvent();
594 const Reference
< XInterface
> xSource( *this );
597 aNew
<<= AccessibleStateType::FOCUSED
;
598 CommitChange( AccessibleEventObject( xSource
, AccessibleEventId::STATE_CHANGED
, aNew
, aOld
) );
602 mnSelectedChild
= NOCHILDSELECTED
;
604 void SvxRectCtlAccessibleContext::selectChild( long nNew
, bool bFireFocus
)
606 ::osl::MutexGuard
aGuard( m_aMutex
);
607 if( nNew
!= mnSelectedChild
)
609 long nNumOfChildren
= getAccessibleChildCount();
610 if( nNew
< nNumOfChildren
)
612 SvxRectCtlChildAccessibleContext
* pChild
;
613 if( mnSelectedChild
!= NOCHILDSELECTED
)
614 { // deselect old selected child if one is selected
615 pChild
= mpChildren
[ mnSelectedChild
];
617 pChild
->setStateChecked( false, bFireFocus
);
621 mnSelectedChild
= nNew
;
623 if( nNew
!= NOCHILDSELECTED
)
625 pChild
= mpChildren
[ nNew
];
627 pChild
->setStateChecked( true, bFireFocus
);
631 mnSelectedChild
= NOCHILDSELECTED
;
635 void SvxRectCtlAccessibleContext::selectChild(RECT_POINT eButton
, bool bFireFocus
)
637 // no guard -> is done in next selectChild
638 selectChild(PointToIndex( eButton
, mbAngleMode
), bFireFocus
);
641 void SvxRectCtlAccessibleContext::CommitChange( const AccessibleEventObject
& rEvent
)
644 comphelper::AccessibleEventNotifier::addEvent( mnClientId
, rEvent
);
647 void SAL_CALL
SvxRectCtlAccessibleContext::disposing()
649 if( !rBHelper
.bDisposed
)
652 ::osl::MutexGuard
aGuard( m_aMutex
);
653 mpRepr
= NULL
; // object dies with representation
655 SvxRectCtlChildAccessibleContext
** p
= mpChildren
;
656 for( int i
= MAX_NUM_OF_CHILDREN
; i
; --i
, ++p
)
658 SvxRectCtlChildAccessibleContext
* pChild
= *p
;
672 ::osl::MutexGuard
aGuard( m_aMutex
);
674 // Send a disposing to all listeners.
677 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId
, *this );
686 Rectangle
SvxRectCtlAccessibleContext::GetBoundingBoxOnScreen() throw( RuntimeException
)
688 ::SolarMutexGuard aSolarGuard
;
689 ::osl::MutexGuard
aGuard( m_aMutex
);
691 ThrowExceptionIfNotAlive();
693 return Rectangle( mpRepr
->GetParent()->OutputToScreenPixel( mpRepr
->GetPosPixel() ), mpRepr
->GetSizePixel() );
696 Rectangle
SvxRectCtlAccessibleContext::GetBoundingBox() throw( RuntimeException
)
698 ::SolarMutexGuard aSolarGuard
;
699 ::osl::MutexGuard
aGuard( m_aMutex
);
701 ThrowExceptionIfNotAlive();
703 return Rectangle( mpRepr
->GetPosPixel(), mpRepr
->GetSizePixel() );
706 void SvxRectCtlAccessibleContext::ThrowExceptionIfNotAlive() throw( lang::DisposedException
)
709 throw lang::DisposedException();
717 SvxRectCtlChildAccessibleContext::SvxRectCtlChildAccessibleContext(
718 const Reference
<XAccessible
>& rxParent
,
719 const vcl::Window
& rParentWindow
,
720 const OUString
& rName
,
721 const OUString
& rDescription
,
722 const Rectangle
& rBoundingBox
,
723 long nIndexInParent
) :
725 SvxRectCtlChildAccessibleContext_Base( maMutex
),
726 msDescription( rDescription
),
729 mpBoundingBox( new Rectangle( rBoundingBox
) ),
730 mrParentWindow( rParentWindow
),
732 mnIndexInParent( nIndexInParent
),
738 SvxRectCtlChildAccessibleContext::~SvxRectCtlChildAccessibleContext()
743 osl_atomic_increment( &m_refCount
);
744 dispose(); // set mpRepr = NULL & release all children
749 Reference
< XAccessibleContext
> SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleContext() throw( RuntimeException
, std::exception
)
754 // XAccessibleComponent
755 sal_Bool SAL_CALL
SvxRectCtlChildAccessibleContext::containsPoint( const awt::Point
& rPoint
) throw( RuntimeException
, std::exception
)
757 // no guard -> done in getBounds()
758 return Rectangle( Point( 0, 0 ), GetBoundingBox().GetSize() ).IsInside( VCLPoint( rPoint
) );
761 Reference
< XAccessible
> SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleAtPoint( const awt::Point
& /*rPoint*/ ) throw( RuntimeException
, std::exception
)
763 return Reference
< XAccessible
>();
766 awt::Rectangle SAL_CALL
SvxRectCtlChildAccessibleContext::getBounds() throw( RuntimeException
, std::exception
)
768 // no guard -> done in getBoundingBox()
769 return AWTRectangle( GetBoundingBox() );
772 awt::Point SAL_CALL
SvxRectCtlChildAccessibleContext::getLocation() throw( RuntimeException
, std::exception
)
774 // no guard -> done in getBoundingBox()
775 return AWTPoint( GetBoundingBox().TopLeft() );
778 awt::Point SAL_CALL
SvxRectCtlChildAccessibleContext::getLocationOnScreen() throw( RuntimeException
, std::exception
)
780 // no guard -> done in getBoundingBoxOnScreen()
781 return AWTPoint( GetBoundingBoxOnScreen().TopLeft() );
784 awt::Size SAL_CALL
SvxRectCtlChildAccessibleContext::getSize() throw( RuntimeException
, std::exception
)
786 // no guard -> done in getBoundingBox()
787 return AWTSize( GetBoundingBox().GetSize() );
790 void SAL_CALL
SvxRectCtlChildAccessibleContext::grabFocus() throw( RuntimeException
, std::exception
)
794 sal_Int32
SvxRectCtlChildAccessibleContext::getForeground( )
795 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
797 ::SolarMutexGuard aSolarGuard
;
798 ::osl::MutexGuard
aGuard( maMutex
);
799 ThrowExceptionIfNotAlive();
800 return mrParentWindow
.GetControlForeground().GetColor();
802 sal_Int32
SvxRectCtlChildAccessibleContext::getBackground( )
803 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
805 ::SolarMutexGuard aSolarGuard
;
806 ::osl::MutexGuard
aGuard( maMutex
);
808 ThrowExceptionIfNotAlive();
809 return mrParentWindow
.GetControlBackground().GetColor();
812 // XAccessibleContext
813 sal_Int32 SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleChildCount() throw( RuntimeException
, std::exception
)
818 Reference
< XAccessible
> SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleChild( sal_Int32
/*nIndex*/ ) throw ( RuntimeException
, lang::IndexOutOfBoundsException
, std::exception
)
820 throw lang::IndexOutOfBoundsException();
823 Reference
< XAccessible
> SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleParent() throw( RuntimeException
, std::exception
)
828 sal_Int32 SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleIndexInParent() throw( RuntimeException
, std::exception
)
830 return mnIndexInParent
;
833 sal_Int16 SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleRole() throw( RuntimeException
, std::exception
)
835 return AccessibleRole::RADIO_BUTTON
;
838 OUString SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleDescription() throw( RuntimeException
, std::exception
)
840 ::osl::MutexGuard
aGuard( maMutex
);
841 return msDescription
;
844 OUString SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleName() throw( RuntimeException
, std::exception
)
846 ::osl::MutexGuard
aGuard( maMutex
);
850 /** Return empty reference to indicate that the relation set is not
853 Reference
<XAccessibleRelationSet
> SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleRelationSet() throw( RuntimeException
, std::exception
)
855 utl::AccessibleRelationSetHelper
* pRelationSetHelper
= new utl::AccessibleRelationSetHelper
;
856 uno::Reference
< css::accessibility::XAccessibleRelationSet
> xSet
= pRelationSetHelper
;
859 uno::Sequence
< uno::Reference
< uno::XInterface
> > aSequence(1);
860 aSequence
[0] = mxParent
;
861 pRelationSetHelper
->AddRelation( css::accessibility::AccessibleRelation( css::accessibility::AccessibleRelationType::MEMBER_OF
, aSequence
) );
868 Reference
< XAccessibleStateSet
> SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleStateSet() throw( RuntimeException
, std::exception
)
870 ::osl::MutexGuard
aGuard( maMutex
);
871 utl::AccessibleStateSetHelper
* pStateSetHelper
= new utl::AccessibleStateSetHelper
;
877 pStateSetHelper
->AddState( AccessibleStateType::CHECKED
);
878 // pStateSetHelper->AddState( AccessibleStateType::SELECTED );
881 pStateSetHelper
->AddState( AccessibleStateType::ENABLED
);
882 pStateSetHelper
->AddState( AccessibleStateType::SENSITIVE
);
883 pStateSetHelper
->AddState( AccessibleStateType::OPAQUE
);
884 pStateSetHelper
->AddState( AccessibleStateType::SELECTABLE
);
885 pStateSetHelper
->AddState( AccessibleStateType::SHOWING
);
886 pStateSetHelper
->AddState( AccessibleStateType::VISIBLE
);
889 pStateSetHelper
->AddState( AccessibleStateType::DEFUNC
);
891 return pStateSetHelper
;
894 lang::Locale SAL_CALL
SvxRectCtlChildAccessibleContext::getLocale() throw( IllegalAccessibleComponentStateException
, RuntimeException
, std::exception
)
896 ::osl::MutexGuard
aGuard( maMutex
);
899 Reference
< XAccessibleContext
> xParentContext( mxParent
->getAccessibleContext() );
900 if( xParentContext
.is() )
901 return xParentContext
->getLocale();
904 // No locale and no parent. Therefore throw exception to indicate this
906 throw IllegalAccessibleComponentStateException();
909 void SAL_CALL
SvxRectCtlChildAccessibleContext::addAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
910 throw( RuntimeException
, std::exception
)
914 ::osl::MutexGuard
aGuard( maMutex
);
916 mnClientId
= comphelper::AccessibleEventNotifier::registerClient( );
917 comphelper::AccessibleEventNotifier::addEventListener( mnClientId
, xListener
);
924 void SAL_CALL
SvxRectCtlChildAccessibleContext::removeAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
925 throw( RuntimeException
, std::exception
)
929 ::osl::MutexGuard
aGuard( maMutex
);
931 sal_Int32 nListenerCount
= comphelper::AccessibleEventNotifier::removeEventListener( mnClientId
, xListener
);
932 if ( !nListenerCount
)
934 // no listeners anymore
935 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
936 // and at least to us not firing any events anymore, in case somebody calls
937 // NotifyAccessibleEvent, again
938 comphelper::AccessibleEventNotifier::revokeClient( mnClientId
);
945 Any SAL_CALL
SvxRectCtlChildAccessibleContext::getCurrentValue() throw( RuntimeException
, std::exception
)
947 ThrowExceptionIfNotAlive();
950 aRet
<<= ( mbIsChecked
? 1.0 : 0.0 );
954 sal_Bool SAL_CALL
SvxRectCtlChildAccessibleContext::setCurrentValue( const Any
& /*aNumber*/ ) throw( RuntimeException
, std::exception
)
959 Any SAL_CALL
SvxRectCtlChildAccessibleContext::getMaximumValue() throw( RuntimeException
, std::exception
)
966 Any SAL_CALL
SvxRectCtlChildAccessibleContext::getMinimumValue() throw( RuntimeException
, std::exception
)
977 sal_Int32
SvxRectCtlChildAccessibleContext::getAccessibleActionCount( ) throw (RuntimeException
, std::exception
)
979 ::osl::MutexGuard
aGuard( maMutex
);
986 sal_Bool
SvxRectCtlChildAccessibleContext::doAccessibleAction ( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
988 ::osl::MutexGuard
aGuard( maMutex
);
990 if ( nIndex
< 0 || nIndex
>= getAccessibleActionCount() )
991 throw IndexOutOfBoundsException();
993 Reference
<XAccessibleSelection
> xSelection( mxParent
, UNO_QUERY
);
995 xSelection
->selectAccessibleChild(mnIndexInParent
);
1002 OUString
SvxRectCtlChildAccessibleContext::getAccessibleActionDescription ( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
1004 ::osl::MutexGuard
aGuard( maMutex
);
1006 if ( nIndex
< 0 || nIndex
>= getAccessibleActionCount() )
1007 throw IndexOutOfBoundsException();
1009 return OUString("select");
1014 Reference
< XAccessibleKeyBinding
> SvxRectCtlChildAccessibleContext::getAccessibleActionKeyBinding( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
1016 ::osl::MutexGuard
aGuard( maMutex
);
1018 if ( nIndex
< 0 || nIndex
>= getAccessibleActionCount() )
1019 throw IndexOutOfBoundsException();
1021 return Reference
< XAccessibleKeyBinding
>();
1025 OUString SAL_CALL
SvxRectCtlChildAccessibleContext::getImplementationName() throw( RuntimeException
, std::exception
)
1027 return OUString( "com.sun.star.comp.ui.SvxRectCtlChildAccessibleContext" );
1030 sal_Bool SAL_CALL
SvxRectCtlChildAccessibleContext::supportsService( const OUString
& sServiceName
) throw( RuntimeException
, std::exception
)
1032 return cppu::supportsService(this, sServiceName
);
1035 Sequence
< OUString
> SAL_CALL
SvxRectCtlChildAccessibleContext::getSupportedServiceNames() throw( RuntimeException
, std::exception
)
1037 const OUString
sServiceName ("com.sun.star.accessibility.AccessibleContext");
1038 return Sequence
< OUString
>( &sServiceName
, 1 );
1042 Sequence
< sal_Int8
> SAL_CALL
SvxRectCtlChildAccessibleContext::getImplementationId() throw( RuntimeException
, std::exception
)
1044 return css::uno::Sequence
<sal_Int8
>();
1047 void SvxRectCtlChildAccessibleContext::CommitChange( const AccessibleEventObject
& rEvent
)
1050 comphelper::AccessibleEventNotifier::addEvent( mnClientId
, rEvent
);
1053 void SAL_CALL
SvxRectCtlChildAccessibleContext::disposing()
1055 if( !rBHelper
.bDisposed
)
1057 ::osl::MutexGuard
aGuard( maMutex
);
1059 // Send a disposing to all listeners.
1062 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId
, *this );
1068 delete mpBoundingBox
;
1072 void SvxRectCtlChildAccessibleContext::ThrowExceptionIfNotAlive() throw( lang::DisposedException
)
1075 throw lang::DisposedException();
1078 Rectangle
SvxRectCtlChildAccessibleContext::GetBoundingBoxOnScreen() throw( RuntimeException
)
1080 ::osl::MutexGuard
aGuard( maMutex
);
1082 // no ThrowExceptionIfNotAlive() because its done in GetBoundingBox()
1083 Rectangle
aRect( GetBoundingBox() );
1085 return Rectangle( mrParentWindow
.OutputToScreenPixel( aRect
.TopLeft() ), aRect
.GetSize() );
1088 Rectangle
SvxRectCtlChildAccessibleContext::GetBoundingBox() throw( RuntimeException
)
1090 // no guard necessary, because no one changes mpBoundingBox after creating it
1091 ThrowExceptionIfNotAlive();
1093 return *mpBoundingBox
;
1096 void SvxRectCtlChildAccessibleContext::setStateChecked( bool bChecked
, bool bFireFocus
)
1098 if( mbIsChecked
!= bChecked
)
1100 mbIsChecked
= bChecked
;
1102 const Reference
< XInterface
> xSource( *this );
1106 Any
& rMod
= bChecked
? aNew
: aOld
;
1110 //Send the STATE_CHANGED(Focused) event to accessible
1111 rMod
<<= AccessibleStateType::FOCUSED
;
1112 CommitChange( AccessibleEventObject( xSource
, AccessibleEventId::STATE_CHANGED
, aNew
, aOld
) );
1114 rMod
<<= AccessibleStateType::CHECKED
;
1116 CommitChange( AccessibleEventObject( xSource
, AccessibleEventId::STATE_CHANGED
, aNew
, aOld
) );
1120 void SvxRectCtlChildAccessibleContext::FireFocusEvent()
1122 const Reference
< XInterface
> xSource( *this );
1125 aNew
<<= AccessibleStateType::FOCUSED
;
1126 CommitChange( AccessibleEventObject( xSource
, AccessibleEventId::STATE_CHANGED
, aNew
, aOld
) );
1129 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */