bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / accessibility / svxrectctaccessiblecontext.cxx
blob2c87389ff5e29457cef4c71023843825a107c35c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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
55 // internal
56 namespace
58 struct ChildIndexToPointData
60 short nResIdName;
61 short nResIdDescr;
62 RECT_POINT ePoint;
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[] =
73 { // index
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[] =
86 { // index
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 );
105 if( bAngleControl )
106 { // angle control
107 // angles are counted reverse counter clock wise
108 switch( ePoint )
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;
121 else
122 { // corner control
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;
130 return nRet;
134 SvxRectCtlAccessibleContext::SvxRectCtlAccessibleContext(
135 const Reference< XAccessible >& rxParent,
136 SvxRectCtl& rRepr,
137 const OUString* pName,
138 const OUString* pDesc ) :
140 SvxRectCtlAccessibleContext_Base( m_aMutex ),
141 mxParent( rxParent ),
142 mpRepr( &rRepr ),
143 mpChildren( NULL ),
144 mnClientId( 0 ),
145 mnSelectedChild( NOCHILDSELECTED ),
146 mbAngleMode( rRepr.GetNumOfChildren() == 8 )
149 if( pName )
150 msName = *pName;
151 else
153 ::SolarMutexGuard aSolarGuard;
154 msName = SVX_RESSTR( mbAngleMode? RID_SVXSTR_RECTCTL_ACC_ANGL_NAME : RID_SVXSTR_RECTCTL_ACC_CORN_NAME );
157 if( pDesc )
158 msDescription = *pDesc;
159 else
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 )
169 *p = NULL;
173 SvxRectCtlAccessibleContext::~SvxRectCtlAccessibleContext()
176 if( IsAlive() )
178 osl_atomic_increment( &m_refCount );
179 dispose(); // set mpRepr = NULL & release all children
183 // XAccessible
184 Reference< XAccessibleContext > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleContext() throw( RuntimeException, std::exception )
186 return this;
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 );
210 return xRet;
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 ];
262 if( !xChild.is() )
264 ::SolarMutexGuard aSolarGuard;
266 ::osl::MutexGuard aGuard( m_aMutex );
268 ThrowExceptionIfNotAlive();
270 xChild = mpChildren[ nIndex ];
272 if( !xChild.is() )
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;
283 pChild->acquire();
285 // set actual state
286 if( mnSelectedChild == nIndex )
287 pChild->setStateChecked( true );
291 return xChild;
294 Reference< XAccessible > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleParent() throw( RuntimeException, std::exception )
296 return mxParent;
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.
305 if( mxParent.is() )
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 )
315 return i;
320 // Return -1 to indicate that this object's parent does not know about the
321 // object.
322 return -1;
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 );
339 return msName;
342 /** Return empty reference to indicate that the relation set is not
343 supported.
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;
351 if ( pWindow )
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 ) );
369 return xSet;
372 Reference< XAccessibleStateSet > SAL_CALL SvxRectCtlAccessibleContext::getAccessibleStateSet() throw( RuntimeException, std::exception )
374 ::osl::MutexGuard aGuard( m_aMutex );
375 utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
377 if( IsAlive() )
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 );
387 if( isVisible() )
388 pStateSetHelper->AddState( AccessibleStateType::VISIBLE );
390 else
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 );
399 if( mxParent.is() )
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 )
413 if (xListener.is())
415 ::osl::MutexGuard aGuard( m_aMutex );
416 if (!mnClientId)
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 )
425 if (xListener.is())
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 );
437 mnClientId = 0;
442 void SAL_CALL SvxRectCtlAccessibleContext::grabFocus() throw( RuntimeException, std::exception )
444 ::SolarMutexGuard aSolarGuard;
445 ::osl::MutexGuard aGuard( m_aMutex );
447 ThrowExceptionIfNotAlive();
449 mpRepr->GrabFocus();
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();
471 // XServiceInfo
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 );
488 // XTypeProvider
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 );
507 DBG_ASSERT( pData,
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
561 // internals
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 )
582 // select new child
583 mnSelectedChild = nNew;
584 if( nNew != NOCHILDSELECTED )
586 SvxRectCtlChildAccessibleContext* pChild = mpChildren[ nNew ];
587 if( pChild )
589 pChild->FireFocusEvent();
592 else
594 const Reference< XInterface > xSource( *this );
595 Any aOld;
596 Any aNew;
597 aNew <<= AccessibleStateType::FOCUSED;
598 CommitChange( AccessibleEventObject( xSource, AccessibleEventId::STATE_CHANGED, aNew, aOld ) );
601 else
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 )
611 { // valid index
612 SvxRectCtlChildAccessibleContext* pChild;
613 if( mnSelectedChild != NOCHILDSELECTED )
614 { // deselect old selected child if one is selected
615 pChild = mpChildren[ mnSelectedChild ];
616 if( pChild )
617 pChild->setStateChecked( false, bFireFocus );
620 // select new child
621 mnSelectedChild = nNew;
623 if( nNew != NOCHILDSELECTED )
625 pChild = mpChildren[ nNew ];
626 if( pChild )
627 pChild->setStateChecked( true, bFireFocus );
630 else
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 )
643 if (mnClientId)
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;
659 if( pChild )
661 pChild->dispose();
662 pChild->release();
663 *p = NULL;
667 delete[] mpChildren;
668 mpChildren = NULL;
672 ::osl::MutexGuard aGuard( m_aMutex );
674 // Send a disposing to all listeners.
675 if ( mnClientId )
677 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
678 mnClientId = 0;
681 mxParent.clear();
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 )
708 if( IsNotAlive() )
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 ),
727 msName( rName ),
728 mxParent(rxParent),
729 mpBoundingBox( new Rectangle( rBoundingBox ) ),
730 mrParentWindow( rParentWindow ),
731 mnClientId( 0 ),
732 mnIndexInParent( nIndexInParent ),
733 mbIsChecked( false )
738 SvxRectCtlChildAccessibleContext::~SvxRectCtlChildAccessibleContext()
741 if( IsAlive() )
743 osl_atomic_increment( &m_refCount );
744 dispose(); // set mpRepr = NULL & release all children
748 // XAccessible
749 Reference< XAccessibleContext> SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleContext() throw( RuntimeException, std::exception )
751 return this;
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 )
815 return 0;
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 )
825 return mxParent;
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 );
847 return msName;
850 /** Return empty reference to indicate that the relation set is not
851 supported.
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;
857 if( mxParent.is() )
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 ) );
865 return xSet;
868 Reference< XAccessibleStateSet > SAL_CALL SvxRectCtlChildAccessibleContext::getAccessibleStateSet() throw( RuntimeException, std::exception )
870 ::osl::MutexGuard aGuard( maMutex );
871 utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
873 if( IsAlive() )
875 if( mbIsChecked )
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 );
888 else
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 );
897 if( mxParent.is() )
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
905 // cluelessness.
906 throw IllegalAccessibleComponentStateException();
909 void SAL_CALL SvxRectCtlChildAccessibleContext::addAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener )
910 throw( RuntimeException, std::exception )
912 if (xListener.is())
914 ::osl::MutexGuard aGuard( maMutex );
915 if (!mnClientId)
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 )
927 if (xListener.is())
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 );
939 mnClientId = 0;
944 // XAccessibleValue
945 Any SAL_CALL SvxRectCtlChildAccessibleContext::getCurrentValue() throw( RuntimeException, std::exception )
947 ThrowExceptionIfNotAlive();
949 Any aRet;
950 aRet <<= ( mbIsChecked? 1.0 : 0.0 );
951 return aRet;
954 sal_Bool SAL_CALL SvxRectCtlChildAccessibleContext::setCurrentValue( const Any& /*aNumber*/ ) throw( RuntimeException, std::exception )
956 return sal_False;
959 Any SAL_CALL SvxRectCtlChildAccessibleContext::getMaximumValue() throw( RuntimeException, std::exception )
961 Any aRet;
962 aRet <<= 1.0;
963 return aRet;
966 Any SAL_CALL SvxRectCtlChildAccessibleContext::getMinimumValue() throw( RuntimeException, std::exception )
968 Any aRet;
969 aRet <<= 0.0;
970 return aRet;
974 // XAccessibleAction
977 sal_Int32 SvxRectCtlChildAccessibleContext::getAccessibleActionCount( ) throw (RuntimeException, std::exception)
979 ::osl::MutexGuard aGuard( maMutex );
981 return 1;
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);
997 return sal_True;
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 >();
1024 // XServiceInfo
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 );
1041 // XTypeProvider
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 )
1049 if (mnClientId)
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.
1060 if ( mnClientId )
1062 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
1063 mnClientId = 0;
1066 mxParent.clear();
1068 delete mpBoundingBox;
1072 void SvxRectCtlChildAccessibleContext::ThrowExceptionIfNotAlive() throw( lang::DisposedException )
1074 if( IsNotAlive() )
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 );
1104 Any aOld;
1105 Any aNew;
1106 Any& rMod = bChecked? aNew : aOld;
1108 if( bFireFocus )
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 );
1123 Any aOld;
1124 Any aNew;
1125 aNew <<= AccessibleStateType::FOCUSED;
1126 CommitChange( AccessibleEventObject( xSource, AccessibleEventId::STATE_CHANGED, aNew, aOld ) );
1129 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */