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 <toolkit/helper/vclunohelper.hxx>
29 #include <toolkit/helper/convert.hxx>
30 #include <vcl/svapp.hxx>
31 #include <osl/mutex.hxx>
32 #include <tools/debug.hxx>
33 #include <tools/gen.hxx>
35 #include <svx/dialogs.hrc>
36 #include "accessibility.hrc"
37 #include <svx/dlgctrl.hxx>
38 #include <svx/dialmgr.hxx>
39 #include <comphelper/accessibleeventnotifier.hxx>
42 using namespace ::cppu
;
43 using namespace ::osl
;
44 using namespace ::com::sun::star
;
45 using namespace ::com::sun::star::uno
;
46 using namespace ::com::sun::star::accessibility
;
49 #define MAX_NUM_OF_CHILDREN 9
50 #define NOCHILDSELECTED -1
53 DBG_NAME( SvxRectCtlAccessibleContext
)
56 //===== internal ============================================================
60 struct ChildIndexToPointData
69 static const ChildIndexToPointData
* IndexToPoint( long nIndex
, bool bAngleControl
)
71 DBG_ASSERT( nIndex
< ( bAngleControl
? 8 : 9 ) && nIndex
>= 0, "-IndexToPoint(): invalid child index! You have been warned..." );
73 // angles are counted reverse counter clock wise
74 static const ChildIndexToPointData pAngleData
[] =
76 { RID_SVXSTR_RECTCTL_ACC_CHLD_A000
, RID_SVXSTR_RECTCTL_ACC_CHLD_A000
, RP_RM
}, // 0
77 { RID_SVXSTR_RECTCTL_ACC_CHLD_A045
, RID_SVXSTR_RECTCTL_ACC_CHLD_A045
, RP_RT
}, // 1
78 { RID_SVXSTR_RECTCTL_ACC_CHLD_A090
, RID_SVXSTR_RECTCTL_ACC_CHLD_A090
, RP_MT
}, // 2
79 { RID_SVXSTR_RECTCTL_ACC_CHLD_A135
, RID_SVXSTR_RECTCTL_ACC_CHLD_A135
, RP_LT
}, // 3
80 { RID_SVXSTR_RECTCTL_ACC_CHLD_A180
, RID_SVXSTR_RECTCTL_ACC_CHLD_A180
, RP_LM
}, // 4
81 { RID_SVXSTR_RECTCTL_ACC_CHLD_A225
, RID_SVXSTR_RECTCTL_ACC_CHLD_A225
, RP_LB
}, // 5
82 { RID_SVXSTR_RECTCTL_ACC_CHLD_A270
, RID_SVXSTR_RECTCTL_ACC_CHLD_A270
, RP_MB
}, // 6
83 { RID_SVXSTR_RECTCTL_ACC_CHLD_A315
, RID_SVXSTR_RECTCTL_ACC_CHLD_A315
, RP_RB
} // 7
86 // corners are counted from left to right and top to bottom
87 static const ChildIndexToPointData pCornerData
[] =
89 { RID_SVXSTR_RECTCTL_ACC_CHLD_LT
, RID_SVXSTR_RECTCTL_ACC_CHLD_LT
, RP_LT
}, // 0
90 { RID_SVXSTR_RECTCTL_ACC_CHLD_MT
, RID_SVXSTR_RECTCTL_ACC_CHLD_MT
, RP_MT
}, // 1
91 { RID_SVXSTR_RECTCTL_ACC_CHLD_RT
, RID_SVXSTR_RECTCTL_ACC_CHLD_RT
, RP_RT
}, // 2
92 { RID_SVXSTR_RECTCTL_ACC_CHLD_LM
, RID_SVXSTR_RECTCTL_ACC_CHLD_LM
, RP_LM
}, // 3
93 { RID_SVXSTR_RECTCTL_ACC_CHLD_MM
, RID_SVXSTR_RECTCTL_ACC_CHLD_MM
, RP_MM
}, // 4
94 { RID_SVXSTR_RECTCTL_ACC_CHLD_RM
, RID_SVXSTR_RECTCTL_ACC_CHLD_RM
, RP_RM
}, // 5
95 { RID_SVXSTR_RECTCTL_ACC_CHLD_LB
, RID_SVXSTR_RECTCTL_ACC_CHLD_LB
, RP_LB
}, // 6
96 { RID_SVXSTR_RECTCTL_ACC_CHLD_MB
, RID_SVXSTR_RECTCTL_ACC_CHLD_MB
, RP_MB
}, // 7
97 { RID_SVXSTR_RECTCTL_ACC_CHLD_RB
, RID_SVXSTR_RECTCTL_ACC_CHLD_RB
, RP_RB
} // 8
100 return ( bAngleControl
? pAngleData
: pCornerData
) + nIndex
;
104 static long PointToIndex( RECT_POINT ePoint
, bool bAngleControl
)
106 long nRet( (long) ePoint
);
109 // angles are counted reverse counter clock wise
112 case RP_LT
: nRet
= 3; break;
113 case RP_MT
: nRet
= 2; break;
114 case RP_RT
: nRet
= 1; break;
115 case RP_LM
: nRet
= 4; break;
116 case RP_MM
: nRet
= NOCHILDSELECTED
; break;
117 case RP_RM
: nRet
= 0; break;
118 case RP_LB
: nRet
= 5; break;
119 case RP_MB
: nRet
= 6; break;
120 case RP_RB
: nRet
= 7; break;
125 // corners are counted from left to right and top to bottom
126 DBG_ASSERT( RP_LT
== 0 && RP_MT
== 1 && RP_RT
== 2 && RP_LM
== 3 && RP_MM
== 4 && RP_RM
== 5 &&
127 RP_LB
== 6 && RP_MB
== 7 && RP_RB
== 8, "*PointToIndex(): unexpected enum value!" );
129 nRet
= ( long ) ePoint
;
136 SvxRectCtlAccessibleContext::SvxRectCtlAccessibleContext(
137 const Reference
< XAccessible
>& rxParent
,
139 const OUString
* pName
,
140 const OUString
* pDesc
) :
142 SvxRectCtlAccessibleContext_Base( m_aMutex
),
143 mxParent( rxParent
),
147 mnSelectedChild( NOCHILDSELECTED
),
148 mbAngleMode( rRepr
.GetNumOfChildren() == 8 )
150 DBG_CTOR( SvxRectCtlAccessibleContext
, NULL
);
156 ::SolarMutexGuard aSolarGuard
;
157 msName
= SVX_RESSTR( mbAngleMode
? RID_SVXSTR_RECTCTL_ACC_ANGL_NAME
: RID_SVXSTR_RECTCTL_ACC_CORN_NAME
);
161 msDescription
= *pDesc
;
164 ::SolarMutexGuard aSolarGuard
;
165 msDescription
= SVX_RESSTR( mbAngleMode
? RID_SVXSTR_RECTCTL_ACC_ANGL_DESCR
: RID_SVXSTR_RECTCTL_ACC_CORN_DESCR
);
168 mpChildren
= new SvxRectCtlChildAccessibleContext
*[ MAX_NUM_OF_CHILDREN
];
170 SvxRectCtlChildAccessibleContext
** p
= mpChildren
;
171 for( int i
= MAX_NUM_OF_CHILDREN
; i
; --i
, ++p
)
176 SvxRectCtlAccessibleContext::~SvxRectCtlAccessibleContext()
178 DBG_DTOR( SvxRectCtlAccessibleContext
, NULL
);
182 osl_atomic_increment( &m_refCount
);
183 dispose(); // set mpRepr = NULL & release all children
187 //===== XAccessible =========================================================
189 Reference
< XAccessibleContext
> SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleContext( void ) throw( RuntimeException
)
194 //===== XAccessibleComponent ================================================
196 sal_Bool SAL_CALL
SvxRectCtlAccessibleContext::containsPoint( const awt::Point
& rPoint
) throw( RuntimeException
)
198 // no guard -> done in getBounds()
199 // return GetBoundingBox().IsInside( VCLPoint( rPoint ) );
200 return Rectangle( Point( 0, 0 ), GetBoundingBox().GetSize() ).IsInside( VCLPoint( rPoint
) );
203 Reference
< XAccessible
> SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleAtPoint( const awt::Point
& rPoint
) throw( RuntimeException
)
205 ::osl::MutexGuard
aGuard( m_aMutex
);
207 ThrowExceptionIfNotAlive();
209 Reference
< XAccessible
> xRet
;
211 long nChild
= PointToIndex( mpRepr
->GetApproxRPFromPixPt( rPoint
), mbAngleMode
);
213 if( nChild
!= NOCHILDSELECTED
)
214 xRet
= getAccessibleChild( nChild
);
219 awt::Rectangle SAL_CALL
SvxRectCtlAccessibleContext::getBounds() throw( RuntimeException
)
221 // no guard -> done in GetBoundingBox()
222 return AWTRectangle( GetBoundingBox() );
225 awt::Point SAL_CALL
SvxRectCtlAccessibleContext::getLocation() throw( RuntimeException
)
227 // no guard -> done in GetBoundingBox()
228 return AWTPoint( GetBoundingBox().TopLeft() );
231 awt::Point SAL_CALL
SvxRectCtlAccessibleContext::getLocationOnScreen() throw( RuntimeException
)
233 // no guard -> done in GetBoundingBoxOnScreen()
234 return AWTPoint( GetBoundingBoxOnScreen().TopLeft() );
237 awt::Size SAL_CALL
SvxRectCtlAccessibleContext::getSize() throw( RuntimeException
)
239 // no guard -> done in GetBoundingBox()
240 return AWTSize( GetBoundingBox().GetSize() );
243 sal_Bool SAL_CALL
SvxRectCtlAccessibleContext::isShowing() throw( RuntimeException
)
248 sal_Bool SAL_CALL
SvxRectCtlAccessibleContext::isVisible() throw( RuntimeException
)
250 ::osl::MutexGuard
aGuard( m_aMutex
);
252 ThrowExceptionIfNotAlive();
254 return mpRepr
->IsVisible();
257 sal_Bool SAL_CALL
SvxRectCtlAccessibleContext::isFocusTraversable() throw( RuntimeException
)
262 //===== XAccessibleContext ==================================================
264 sal_Int32 SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleChildCount( void ) throw( RuntimeException
)
266 ::osl::MutexGuard
aGuard( m_aMutex
);
268 ThrowExceptionIfNotAlive();
270 return mpRepr
->GetNumOfChildren();
273 Reference
< XAccessible
> SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleChild( sal_Int32 nIndex
)
274 throw( RuntimeException
, lang::IndexOutOfBoundsException
)
276 checkChildIndex( nIndex
);
278 Reference
< XAccessible
> xChild
= mpChildren
[ nIndex
];
281 ::SolarMutexGuard aSolarGuard
;
283 ::osl::MutexGuard
aGuard( m_aMutex
);
285 ThrowExceptionIfNotAlive();
287 xChild
= mpChildren
[ nIndex
];
291 const ChildIndexToPointData
* p
= IndexToPoint( nIndex
, mbAngleMode
);
292 OUString
aName(SVX_RESSTR(p
->nResIdName
));
293 OUString
aDescr(SVX_RESSTR(p
->nResIdDescr
));
295 Rectangle
aFocusRect( mpRepr
->CalculateFocusRectangle( p
->ePoint
) );
297 SvxRectCtlChildAccessibleContext
* pChild
= new SvxRectCtlChildAccessibleContext(
298 this, *mpRepr
, aName
, aDescr
, aFocusRect
, nIndex
);
299 xChild
= mpChildren
[ nIndex
] = pChild
;
303 if( mnSelectedChild
== nIndex
)
304 pChild
->setStateChecked( true );
311 Reference
< XAccessible
> SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleParent( void ) throw( RuntimeException
)
316 sal_Int32 SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleIndexInParent( void ) throw( RuntimeException
)
318 ::osl::MutexGuard
aGuard( m_aMutex
);
319 // Use a simple but slow solution for now. Optimize later.
321 // Iterate over all the parent's children and search for this object.
324 Reference
< XAccessibleContext
> xParentContext( mxParent
->getAccessibleContext() );
325 if( xParentContext
.is() )
327 sal_Int32 nChildCount
= xParentContext
->getAccessibleChildCount();
328 for( sal_Int32 i
= 0 ; i
< nChildCount
; ++i
)
330 Reference
< XAccessible
> xChild( xParentContext
->getAccessibleChild( i
) );
331 if( xChild
.get() == ( XAccessible
* ) this )
337 // Return -1 to indicate that this object's parent does not know about the
342 sal_Int16 SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleRole( void ) throw( RuntimeException
)
344 return AccessibleRole::PANEL
;
347 OUString SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleDescription( void ) throw( RuntimeException
)
349 ::osl::MutexGuard
aGuard( m_aMutex
);
350 return msDescription
;
353 OUString SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleName( void ) throw( RuntimeException
)
355 ::osl::MutexGuard
aGuard( m_aMutex
);
359 /** Return empty reference to indicate that the relation set is not
362 Reference
< XAccessibleRelationSet
> SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleRelationSet( void ) throw( RuntimeException
)
364 return Reference
< XAccessibleRelationSet
>();
367 Reference
< XAccessibleStateSet
> SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleStateSet( void ) throw( RuntimeException
)
369 ::osl::MutexGuard
aGuard( m_aMutex
);
370 utl::AccessibleStateSetHelper
* pStateSetHelper
= new utl::AccessibleStateSetHelper
;
374 pStateSetHelper
->AddState( AccessibleStateType::FOCUSABLE
);
375 if( mpRepr
->HasFocus() )
376 pStateSetHelper
->AddState( AccessibleStateType::FOCUSED
);
377 pStateSetHelper
->AddState( AccessibleStateType::OPAQUE
);
380 pStateSetHelper
->AddState( AccessibleStateType::SHOWING
);
383 pStateSetHelper
->AddState( AccessibleStateType::VISIBLE
);
386 pStateSetHelper
->AddState( AccessibleStateType::DEFUNC
);
388 return pStateSetHelper
;
391 lang::Locale SAL_CALL
SvxRectCtlAccessibleContext::getLocale( void ) throw( IllegalAccessibleComponentStateException
, RuntimeException
)
393 ::osl::MutexGuard
aGuard( m_aMutex
);
396 Reference
< XAccessibleContext
> xParentContext( mxParent
->getAccessibleContext() );
397 if( xParentContext
.is() )
398 return xParentContext
->getLocale();
401 // No parent. Therefore throw exception to indicate this cluelessness.
402 throw IllegalAccessibleComponentStateException();
405 void SAL_CALL
SvxRectCtlAccessibleContext::addAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
406 throw( RuntimeException
)
410 ::osl::MutexGuard
aGuard( m_aMutex
);
412 mnClientId
= comphelper::AccessibleEventNotifier::registerClient( );
413 comphelper::AccessibleEventNotifier::addEventListener( mnClientId
, xListener
);
417 void SAL_CALL
SvxRectCtlAccessibleContext::removeAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
418 throw( RuntimeException
)
422 ::osl::MutexGuard
aGuard( m_aMutex
);
424 sal_Int32 nListenerCount
= comphelper::AccessibleEventNotifier::removeEventListener( mnClientId
, xListener
);
425 if ( !nListenerCount
)
427 // no listeners anymore
428 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
429 // and at least to us not firing any events anymore, in case somebody calls
430 // NotifyAccessibleEvent, again
431 comphelper::AccessibleEventNotifier::revokeClient( mnClientId
);
437 void SAL_CALL
SvxRectCtlAccessibleContext::addFocusListener( const Reference
< awt::XFocusListener
>& xListener
)
438 throw( RuntimeException
)
442 ::osl::MutexGuard
aGuard( m_aMutex
);
444 ThrowExceptionIfNotAlive();
446 Reference
< awt::XWindow
> xWindow
= VCLUnoHelper::GetInterface( mpRepr
);
448 xWindow
->addFocusListener( xListener
);
452 void SAL_CALL
SvxRectCtlAccessibleContext::removeFocusListener( const Reference
< awt::XFocusListener
>& xListener
)
453 throw (RuntimeException
)
457 ::osl::MutexGuard
aGuard( m_aMutex
);
459 ThrowExceptionIfNotAlive();
461 Reference
< awt::XWindow
> xWindow
= VCLUnoHelper::GetInterface( mpRepr
);
463 xWindow
->removeFocusListener( xListener
);
467 void SAL_CALL
SvxRectCtlAccessibleContext::grabFocus() throw( RuntimeException
)
469 ::SolarMutexGuard aSolarGuard
;
470 ::osl::MutexGuard
aGuard( m_aMutex
);
472 ThrowExceptionIfNotAlive();
477 Any SAL_CALL
SvxRectCtlAccessibleContext::getAccessibleKeyBinding() throw( RuntimeException
)
479 // here is no implementation, because here are no KeyBindings for every object
483 sal_Int32
SvxRectCtlAccessibleContext::getForeground( )
484 throw (::com::sun::star::uno::RuntimeException
)
486 ::SolarMutexGuard aSolarGuard
;
487 ::osl::MutexGuard
aGuard( m_aMutex
);
488 ThrowExceptionIfNotAlive();
490 return mpRepr
->GetControlForeground().GetColor();
492 sal_Int32
SvxRectCtlAccessibleContext::getBackground( )
493 throw (::com::sun::star::uno::RuntimeException
)
495 ::SolarMutexGuard aSolarGuard
;
496 ::osl::MutexGuard
aGuard( m_aMutex
);
497 ThrowExceptionIfNotAlive();
499 return mpRepr
->GetControlBackground().GetColor();
502 //===== XServiceInfo ========================================================
504 OUString SAL_CALL
SvxRectCtlAccessibleContext::getImplementationName( void ) throw( RuntimeException
)
506 return OUString( "com.sun.star.comp.ui.SvxRectCtlAccessibleContext" );
509 sal_Bool SAL_CALL
SvxRectCtlAccessibleContext::supportsService( const OUString
& sServiceName
) throw( RuntimeException
)
511 ::osl::MutexGuard
aGuard( m_aMutex
);
512 // Iterate over all supported service names and return true if on of them
513 // matches the given name.
514 Sequence
< OUString
> aSupportedServices( getSupportedServiceNames() );
515 int nLength
= aSupportedServices
.getLength();
516 const OUString
* pStr
= aSupportedServices
.getConstArray();
518 for( int i
= nLength
; i
; --i
, ++pStr
)
520 if( sServiceName
== *pStr
)
527 Sequence
< OUString
> SAL_CALL
SvxRectCtlAccessibleContext::getSupportedServiceNames( void ) throw( RuntimeException
)
529 const OUString
sServiceName( "com.sun.star.accessibility.AccessibleContext" );
530 return Sequence
< OUString
>( &sServiceName
, 1 );
533 //===== XTypeProvider =======================================================
535 Sequence
< sal_Int8
> SAL_CALL
SvxRectCtlAccessibleContext::getImplementationId( void ) throw( RuntimeException
)
537 return getUniqueId();
540 //===== XAccessibleSelection =============================================
542 void SAL_CALL
SvxRectCtlAccessibleContext::selectAccessibleChild( sal_Int32 nIndex
) throw( lang::IndexOutOfBoundsException
, RuntimeException
)
544 ::SolarMutexGuard aSolarGuard
;
546 ::osl::MutexGuard
aGuard( m_aMutex
);
548 checkChildIndex( nIndex
);
550 ThrowExceptionIfNotAlive();
552 const ChildIndexToPointData
* pData
= IndexToPoint( nIndex
, mbAngleMode
);
555 "SvxRectCtlAccessibleContext::selectAccessibleChild(): this is an impossible state! Or at least should be..." );
557 // this does all what is needed, including the change of the child's state!
558 mpRepr
->SetActualRP( pData
->ePoint
);
561 sal_Bool SAL_CALL
SvxRectCtlAccessibleContext::isAccessibleChildSelected( sal_Int32 nIndex
) throw( lang::IndexOutOfBoundsException
, RuntimeException
)
563 ::osl::MutexGuard
aGuard( m_aMutex
);
565 checkChildIndex( nIndex
);
567 return nIndex
== mnSelectedChild
;
570 void SAL_CALL
SvxRectCtlAccessibleContext::clearAccessibleSelection() throw( RuntimeException
)
572 DBG_ASSERT( sal_False
, "SvxRectCtlAccessibleContext::clearAccessibleSelection() is not possible!" );
575 void SAL_CALL
SvxRectCtlAccessibleContext::selectAllAccessibleChildren() throw( RuntimeException
)
577 // guard in selectAccessibleChild()!
579 selectAccessibleChild( 0 ); // default per definition
582 sal_Int32 SAL_CALL
SvxRectCtlAccessibleContext::getSelectedAccessibleChildCount() throw( RuntimeException
)
584 ::osl::MutexGuard
aGuard( m_aMutex
);
586 return mnSelectedChild
== NOCHILDSELECTED
? 0 : 1;
589 Reference
< XAccessible
> SAL_CALL
SvxRectCtlAccessibleContext::getSelectedAccessibleChild( sal_Int32 nIndex
)
590 throw( lang::IndexOutOfBoundsException
, RuntimeException
)
592 ::osl::MutexGuard
aGuard( m_aMutex
);
594 checkChildIndexOnSelection( nIndex
);
596 return getAccessibleChild( mnSelectedChild
);
599 void SAL_CALL
SvxRectCtlAccessibleContext::deselectAccessibleChild( sal_Int32
/*nIndex*/ ) throw( lang::IndexOutOfBoundsException
, RuntimeException
)
601 OUString
aMessage( "deselectAccessibleChild is not possible in this context" );
603 DBG_ASSERT( sal_False
, "SvxRectCtlAccessibleContext::deselectAccessibleChild() is not possible!" );
605 throw lang::IndexOutOfBoundsException( aMessage
, *this ); // never possible
608 //===== internals ========================================================
610 void SvxRectCtlAccessibleContext::checkChildIndex( long nIndex
) throw( lang::IndexOutOfBoundsException
)
612 if( nIndex
< 0 || nIndex
>= getAccessibleChildCount() )
613 throw lang::IndexOutOfBoundsException();
616 void SvxRectCtlAccessibleContext::checkChildIndexOnSelection( long nIndex
) throw( lang::IndexOutOfBoundsException
)
618 if( nIndex
|| mnSelectedChild
== NOCHILDSELECTED
)
619 // in our case only for the first (0) _selected_ child this is a valid request
620 throw lang::IndexOutOfBoundsException();
623 void SvxRectCtlAccessibleContext::selectChild( long nNew
)
625 ::osl::MutexGuard
aGuard( m_aMutex
);
626 if( nNew
!= mnSelectedChild
)
628 long nNumOfChildren
= getAccessibleChildCount();
629 if( nNew
< nNumOfChildren
)
631 SvxRectCtlChildAccessibleContext
* pChild
;
632 if( mnSelectedChild
!= NOCHILDSELECTED
)
633 { // deselect old selected child if one is selected
634 pChild
= mpChildren
[ mnSelectedChild
];
636 pChild
->setStateChecked( false );
640 mnSelectedChild
= nNew
;
642 if( nNew
!= NOCHILDSELECTED
)
644 pChild
= mpChildren
[ nNew
];
646 pChild
->setStateChecked( true );
650 mnSelectedChild
= NOCHILDSELECTED
;
654 void SvxRectCtlAccessibleContext::selectChild( RECT_POINT eButton
)
656 // no guard -> is done in next selectChild
657 selectChild( PointToIndex( eButton
, mbAngleMode
) );
660 void SAL_CALL
SvxRectCtlAccessibleContext::disposing()
662 if( !rBHelper
.bDisposed
)
665 ::osl::MutexGuard
aGuard( m_aMutex
);
666 mpRepr
= NULL
; // object dies with representation
668 SvxRectCtlChildAccessibleContext
** p
= mpChildren
;
669 for( int i
= MAX_NUM_OF_CHILDREN
; i
; --i
, ++p
)
671 SvxRectCtlChildAccessibleContext
* pChild
= *p
;
685 ::osl::MutexGuard
aGuard( m_aMutex
);
687 // Send a disposing to all listeners.
690 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId
, *this );
694 mxParent
= Reference
< XAccessible
>();
699 Rectangle
SvxRectCtlAccessibleContext::GetBoundingBoxOnScreen( void ) throw( RuntimeException
)
701 ::SolarMutexGuard aSolarGuard
;
702 ::osl::MutexGuard
aGuard( m_aMutex
);
704 ThrowExceptionIfNotAlive();
706 return Rectangle( mpRepr
->GetParent()->OutputToScreenPixel( mpRepr
->GetPosPixel() ), mpRepr
->GetSizePixel() );
709 Rectangle
SvxRectCtlAccessibleContext::GetBoundingBox( void ) throw( RuntimeException
)
711 ::SolarMutexGuard aSolarGuard
;
712 ::osl::MutexGuard
aGuard( m_aMutex
);
714 ThrowExceptionIfNotAlive();
716 return Rectangle( mpRepr
->GetPosPixel(), mpRepr
->GetSizePixel() );
719 Sequence
< sal_Int8
> SvxRectCtlAccessibleContext::getUniqueId( void )
721 static OImplementationId
* pId
= 0;
724 MutexGuard
aGuard( Mutex::getGlobalMutex() );
727 static OImplementationId aId
;
731 return pId
->getImplementationId();
734 void SvxRectCtlAccessibleContext::ThrowExceptionIfNotAlive( void ) throw( lang::DisposedException
)
737 throw lang::DisposedException();
740 // -------------------------------------------------------------------------------------------------
743 DBG_NAME( SvxRectCtlChildAccessibleContext
)
746 SvxRectCtlChildAccessibleContext::SvxRectCtlChildAccessibleContext(
747 const Reference
<XAccessible
>& rxParent
,
748 const Window
& rParentWindow
,
749 const OUString
& rName
,
750 const OUString
& rDescription
,
751 const Rectangle
& rBoundingBox
,
752 long nIndexInParent
) :
754 SvxRectCtlChildAccessibleContext_Base( maMutex
),
755 msDescription( rDescription
),
758 mpBoundingBox( new Rectangle( rBoundingBox
) ),
759 mrParentWindow( rParentWindow
),
761 mnIndexInParent( nIndexInParent
),
764 DBG_CTOR( SvxRectCtlChildAccessibleContext
, NULL
);
768 SvxRectCtlChildAccessibleContext::~SvxRectCtlChildAccessibleContext()
770 DBG_DTOR( SvxRectCtlChildAccessibleContext
, NULL
);
774 osl_atomic_increment( &m_refCount
);
775 dispose(); // set mpRepr = NULL & release all children
779 //===== XAccessible =========================================================
781 Reference
< XAccessibleContext
> SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleContext( void ) throw( RuntimeException
)
786 //===== XAccessibleComponent ================================================
788 sal_Bool SAL_CALL
SvxRectCtlChildAccessibleContext::containsPoint( const awt::Point
& rPoint
) throw( RuntimeException
)
790 // no guard -> done in getBounds()
791 return Rectangle( Point( 0, 0 ), GetBoundingBox().GetSize() ).IsInside( VCLPoint( rPoint
) );
794 Reference
< XAccessible
> SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleAtPoint( const awt::Point
& /*rPoint*/ ) throw( RuntimeException
)
796 return Reference
< XAccessible
>();
799 awt::Rectangle SAL_CALL
SvxRectCtlChildAccessibleContext::getBounds() throw( RuntimeException
)
801 // no guard -> done in getBoundingBox()
802 return AWTRectangle( GetBoundingBox() );
805 awt::Point SAL_CALL
SvxRectCtlChildAccessibleContext::getLocation() throw( RuntimeException
)
807 // no guard -> done in getBoundingBox()
808 return AWTPoint( GetBoundingBox().TopLeft() );
811 awt::Point SAL_CALL
SvxRectCtlChildAccessibleContext::getLocationOnScreen() throw( RuntimeException
)
813 // no guard -> done in getBoundingBoxOnScreen()
814 return AWTPoint( GetBoundingBoxOnScreen().TopLeft() );
817 awt::Size SAL_CALL
SvxRectCtlChildAccessibleContext::getSize() throw( RuntimeException
)
819 // no guard -> done in getBoundingBox()
820 return AWTSize( GetBoundingBox().GetSize() );
823 sal_Bool SAL_CALL
SvxRectCtlChildAccessibleContext::isShowing() throw( RuntimeException
)
828 sal_Bool SAL_CALL
SvxRectCtlChildAccessibleContext::isVisible() throw( RuntimeException
)
830 ::osl::MutexGuard
aGuard( maMutex
);
832 ThrowExceptionIfNotAlive();
834 return mxParent
.is()? ( static_cast< SvxRectCtlAccessibleContext
* >( mxParent
.get() ) )->isVisible() : sal_False
;
837 sal_Bool SAL_CALL
SvxRectCtlChildAccessibleContext::isFocusTraversable() throw( RuntimeException
)
842 void SAL_CALL
SvxRectCtlChildAccessibleContext::addFocusListener( const Reference
< awt::XFocusListener
>& /*xListener*/ )
843 throw( RuntimeException
)
845 OSL_FAIL( "SvxRectCtlChildAccessibleContext::addFocusListener: not implemented" );
848 void SAL_CALL
SvxRectCtlChildAccessibleContext::removeFocusListener( const Reference
< awt::XFocusListener
>& /*xListener*/ )
849 throw (RuntimeException
)
851 OSL_FAIL( "SvxRectCtlChildAccessibleContext::removeFocusListener: not implemented" );
854 void SAL_CALL
SvxRectCtlChildAccessibleContext::grabFocus() throw( RuntimeException
)
858 Any SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleKeyBinding() throw( RuntimeException
)
860 // here is no implementation, because here are no KeyBindings for every object
863 sal_Int32
SvxRectCtlChildAccessibleContext::getForeground( )
864 throw (::com::sun::star::uno::RuntimeException
)
866 ::SolarMutexGuard aSolarGuard
;
867 ::osl::MutexGuard
aGuard( maMutex
);
868 ThrowExceptionIfNotAlive();
869 return mrParentWindow
.GetControlForeground().GetColor();
871 sal_Int32
SvxRectCtlChildAccessibleContext::getBackground( )
872 throw (::com::sun::star::uno::RuntimeException
)
874 ::SolarMutexGuard aSolarGuard
;
875 ::osl::MutexGuard
aGuard( maMutex
);
877 ThrowExceptionIfNotAlive();
878 return mrParentWindow
.GetControlBackground().GetColor();
881 //===== XAccessibleContext ==================================================
883 sal_Int32 SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleChildCount( void ) throw( RuntimeException
)
888 Reference
< XAccessible
> SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleChild( sal_Int32
/*nIndex*/ ) throw ( RuntimeException
, lang::IndexOutOfBoundsException
)
890 throw lang::IndexOutOfBoundsException();
893 Reference
< XAccessible
> SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleParent( void ) throw( RuntimeException
)
898 sal_Int32 SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleIndexInParent( void ) throw( RuntimeException
)
900 return mnIndexInParent
;
903 sal_Int16 SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleRole( void ) throw( RuntimeException
)
905 return AccessibleRole::RADIO_BUTTON
;
908 OUString SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleDescription( void ) throw( RuntimeException
)
910 ::osl::MutexGuard
aGuard( maMutex
);
911 return msDescription
;
914 OUString SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleName( void ) throw( RuntimeException
)
916 ::osl::MutexGuard
aGuard( maMutex
);
920 /** Return empty reference to indicate that the relation set is not
923 Reference
<XAccessibleRelationSet
> SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleRelationSet( void ) throw( RuntimeException
)
925 return Reference
< XAccessibleRelationSet
>();
928 Reference
< XAccessibleStateSet
> SAL_CALL
SvxRectCtlChildAccessibleContext::getAccessibleStateSet( void ) throw( RuntimeException
)
930 ::osl::MutexGuard
aGuard( maMutex
);
931 utl::AccessibleStateSetHelper
* pStateSetHelper
= new utl::AccessibleStateSetHelper
;
937 pStateSetHelper
->AddState( AccessibleStateType::CHECKED
);
938 // pStateSetHelper->AddState( AccessibleStateType::SELECTED );
941 pStateSetHelper
->AddState( AccessibleStateType::ENABLED
);
942 pStateSetHelper
->AddState( AccessibleStateType::SENSITIVE
);
943 pStateSetHelper
->AddState( AccessibleStateType::OPAQUE
);
944 pStateSetHelper
->AddState( AccessibleStateType::SELECTABLE
);
945 pStateSetHelper
->AddState( AccessibleStateType::SHOWING
);
946 pStateSetHelper
->AddState( AccessibleStateType::VISIBLE
);
949 pStateSetHelper
->AddState( AccessibleStateType::DEFUNC
);
951 return pStateSetHelper
;
954 lang::Locale SAL_CALL
SvxRectCtlChildAccessibleContext::getLocale( void ) throw( IllegalAccessibleComponentStateException
, RuntimeException
)
956 ::osl::MutexGuard
aGuard( maMutex
);
959 Reference
< XAccessibleContext
> xParentContext( mxParent
->getAccessibleContext() );
960 if( xParentContext
.is() )
961 return xParentContext
->getLocale();
964 // No locale and no parent. Therefore throw exception to indicate this
966 throw IllegalAccessibleComponentStateException();
969 void SAL_CALL
SvxRectCtlChildAccessibleContext::addAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
970 throw( RuntimeException
)
974 ::osl::MutexGuard
aGuard( maMutex
);
976 mnClientId
= comphelper::AccessibleEventNotifier::registerClient( );
977 comphelper::AccessibleEventNotifier::addEventListener( mnClientId
, xListener
);
984 void SAL_CALL
SvxRectCtlChildAccessibleContext::removeAccessibleEventListener( const Reference
< XAccessibleEventListener
>& xListener
)
985 throw( RuntimeException
)
989 ::osl::MutexGuard
aGuard( maMutex
);
991 sal_Int32 nListenerCount
= comphelper::AccessibleEventNotifier::removeEventListener( mnClientId
, xListener
);
992 if ( !nListenerCount
)
994 // no listeners anymore
995 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
996 // and at least to us not firing any events anymore, in case somebody calls
997 // NotifyAccessibleEvent, again
998 comphelper::AccessibleEventNotifier::revokeClient( mnClientId
);
1004 //===== XAccessibleValue ================================================
1006 Any SAL_CALL
SvxRectCtlChildAccessibleContext::getCurrentValue() throw( RuntimeException
)
1008 ThrowExceptionIfNotAlive();
1011 aRet
<<= ( mbIsChecked
? 1.0 : 0.0 );
1015 sal_Bool SAL_CALL
SvxRectCtlChildAccessibleContext::setCurrentValue( const Any
& /*aNumber*/ ) throw( RuntimeException
)
1020 Any SAL_CALL
SvxRectCtlChildAccessibleContext::getMaximumValue() throw( RuntimeException
)
1027 Any SAL_CALL
SvxRectCtlChildAccessibleContext::getMinimumValue() throw( RuntimeException
)
1034 //===== XServiceInfo ========================================================
1036 OUString SAL_CALL
SvxRectCtlChildAccessibleContext::getImplementationName( void ) throw( RuntimeException
)
1038 return OUString( "com.sun.star.comp.ui.SvxRectCtlChildAccessibleContext" );
1041 sal_Bool SAL_CALL
SvxRectCtlChildAccessibleContext::supportsService( const OUString
& sServiceName
) throw( RuntimeException
)
1043 // Iterate over all supported service names and return true if on of them
1044 // matches the given name.
1045 ::osl::MutexGuard
aGuard( maMutex
);
1046 Sequence
< OUString
> aSupportedServices ( getSupportedServiceNames() );
1047 int nLength
= aSupportedServices
.getLength();
1048 for( int i
= 0 ; i
< nLength
; ++i
)
1050 if( sServiceName
== aSupportedServices
[ i
] )
1057 Sequence
< OUString
> SAL_CALL
SvxRectCtlChildAccessibleContext::getSupportedServiceNames( void ) throw( RuntimeException
)
1059 const OUString
sServiceName ("com.sun.star.accessibility.AccessibleContext");
1060 return Sequence
< OUString
>( &sServiceName
, 1 );
1063 //===== XTypeProvider =======================================================
1065 Sequence
< sal_Int8
> SAL_CALL
SvxRectCtlChildAccessibleContext::getImplementationId( void ) throw( RuntimeException
)
1067 static OImplementationId
* pId
= 0;
1070 MutexGuard
aGuard( Mutex::getGlobalMutex() );
1073 static OImplementationId aId
;
1077 return pId
->getImplementationId();
1080 //===== internal ============================================================
1082 void SvxRectCtlChildAccessibleContext::CommitChange( const AccessibleEventObject
& rEvent
)
1085 comphelper::AccessibleEventNotifier::addEvent( mnClientId
, rEvent
);
1088 void SAL_CALL
SvxRectCtlChildAccessibleContext::disposing()
1090 if( !rBHelper
.bDisposed
)
1092 ::osl::MutexGuard
aGuard( maMutex
);
1094 // Send a disposing to all listeners.
1097 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId
, *this );
1101 mxParent
= Reference
< XAccessible
>();
1103 delete mpBoundingBox
;
1107 void SvxRectCtlChildAccessibleContext::ThrowExceptionIfNotAlive( void ) throw( lang::DisposedException
)
1110 throw lang::DisposedException();
1113 Rectangle
SvxRectCtlChildAccessibleContext::GetBoundingBoxOnScreen( void ) throw( RuntimeException
)
1115 ::osl::MutexGuard
aGuard( maMutex
);
1117 // no ThrowExceptionIfNotAlive() because its done in GetBoundingBox()
1118 Rectangle
aRect( GetBoundingBox() );
1120 return Rectangle( mrParentWindow
.OutputToScreenPixel( aRect
.TopLeft() ), aRect
.GetSize() );
1123 Rectangle
SvxRectCtlChildAccessibleContext::GetBoundingBox( void ) throw( RuntimeException
)
1125 // no guard necessary, because no one changes mpBoundingBox after creating it
1126 ThrowExceptionIfNotAlive();
1128 return *mpBoundingBox
;
1131 void SvxRectCtlChildAccessibleContext::setStateChecked( bool bChecked
)
1133 if( mbIsChecked
!= bChecked
)
1135 mbIsChecked
= bChecked
;
1137 const Reference
< XInterface
> xSource( *this );
1141 Any
& rMod
= bChecked
? aNew
: aOld
;
1143 rMod
<<= AccessibleStateType::CHECKED
;
1145 CommitChange( AccessibleEventObject( xSource
, AccessibleEventId::STATE_CHANGED
, aNew
, aOld
) );
1149 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */