1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_accessibility.hxx" 26 #include "accessibility/extended/AccessibleGridControlBase.hxx" 27 #include <svtools/accessibletable.hxx> 28 #include <rtl/uuid.h> 29 // 30 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 31 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 32 #include <unotools/accessiblerelationsethelper.hxx> 33 34 // ============================================================================ 35 36 using ::rtl::OUString; 37 38 using ::com::sun::star::uno::Reference; 39 using ::com::sun::star::uno::Sequence; 40 using ::com::sun::star::uno::Any; 41 42 using namespace ::com::sun::star; 43 using namespace ::com::sun::star::accessibility; 44 using namespace ::comphelper; 45 using namespace ::svt; 46 using namespace ::svt::table; 47 48 49 // ============================================================================ 50 51 namespace accessibility { 52 53 using namespace com::sun::star::accessibility::AccessibleStateType; 54 // ============================================================================ 55 56 DBG_NAME( AccessibleGridControlBase ) 57 58 AccessibleGridControlBase::AccessibleGridControlBase( 59 const Reference< XAccessible >& rxParent, 60 svt::table::IAccessibleTable& rTable, 61 AccessibleTableControlObjType eObjType ) : 62 AccessibleGridControlImplHelper( m_aMutex ), 63 m_xParent( rxParent ), 64 m_aTable( rTable), 65 m_eObjType( eObjType ), 66 m_aName( rTable.GetAccessibleObjectName( eObjType, 0, 0 ) ), 67 m_aDescription( rTable.GetAccessibleObjectDescription( eObjType ) ), 68 m_aClientId(0) 69 { 70 } 71 72 AccessibleGridControlBase::~AccessibleGridControlBase() 73 { 74 if( isAlive() ) 75 { 76 // increment ref count to prevent double call of Dtor 77 osl_incrementInterlockedCount( &m_refCount ); 78 dispose(); 79 } 80 } 81 82 void SAL_CALL AccessibleGridControlBase::disposing() 83 { 84 ::osl::MutexGuard aGuard( getOslMutex() ); 85 86 if ( getClientId( ) ) 87 { 88 AccessibleEventNotifier::TClientId nId( getClientId( ) ); 89 setClientId( 0 ); 90 AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this ); 91 } 92 93 m_xParent = NULL; 94 //m_aTable = NULL; 95 } 96 97 // XAccessibleContext --------------------------------------------------------- 98 99 Reference< XAccessible > SAL_CALL AccessibleGridControlBase::getAccessibleParent() 100 throw ( uno::RuntimeException ) 101 { 102 ::osl::MutexGuard aGuard( getOslMutex() ); 103 ensureIsAlive(); 104 return m_xParent; 105 } 106 107 sal_Int32 SAL_CALL AccessibleGridControlBase::getAccessibleIndexInParent() 108 throw ( uno::RuntimeException ) 109 { 110 ::osl::MutexGuard aGuard( getOslMutex() ); 111 ensureIsAlive(); 112 113 // -1 for child not found/no parent (according to specification) 114 sal_Int32 nRet = -1; 115 116 Reference< uno::XInterface > xMeMyselfAndI( static_cast< XAccessibleContext* >( this ), uno::UNO_QUERY ); 117 118 // iterate over parent's children and search for this object 119 if( m_xParent.is() ) 120 { 121 Reference< XAccessibleContext > 122 xParentContext( m_xParent->getAccessibleContext() ); 123 if( xParentContext.is() ) 124 { 125 Reference< uno::XInterface > xChild; 126 127 sal_Int32 nChildCount = xParentContext->getAccessibleChildCount(); 128 for( sal_Int32 nChild = 0; nChild < nChildCount; ++nChild ) 129 { 130 xChild = xChild.query( xParentContext->getAccessibleChild( nChild ) ); 131 if ( xMeMyselfAndI.get() == xChild.get() ) 132 { 133 nRet = nChild; 134 break; 135 } 136 } 137 } 138 } 139 return nRet; 140 } 141 142 OUString SAL_CALL AccessibleGridControlBase::getAccessibleDescription() 143 throw ( uno::RuntimeException ) 144 { 145 ::osl::MutexGuard aGuard( getOslMutex() ); 146 ensureIsAlive(); 147 return m_aDescription; 148 } 149 150 OUString SAL_CALL AccessibleGridControlBase::getAccessibleName() 151 throw ( uno::RuntimeException ) 152 { 153 ::osl::MutexGuard aGuard( getOslMutex() ); 154 ensureIsAlive(); 155 return m_aName; 156 } 157 158 Reference< XAccessibleRelationSet > SAL_CALL 159 AccessibleGridControlBase::getAccessibleRelationSet() 160 throw ( uno::RuntimeException ) 161 { 162 ensureIsAlive(); 163 // GridControl does not have relations. 164 return new utl::AccessibleRelationSetHelper; 165 } 166 167 Reference< XAccessibleStateSet > SAL_CALL 168 AccessibleGridControlBase::getAccessibleStateSet() 169 throw ( uno::RuntimeException ) 170 { 171 TCSolarGuard aSolarGuard; 172 ::osl::MutexGuard aGuard( getOslMutex() ); 173 // don't check whether alive -> StateSet may contain DEFUNC 174 return implCreateStateSetHelper(); 175 } 176 177 lang::Locale SAL_CALL AccessibleGridControlBase::getLocale() 178 throw ( IllegalAccessibleComponentStateException, uno::RuntimeException ) 179 { 180 ::osl::MutexGuard aGuard( getOslMutex() ); 181 ensureIsAlive(); 182 if( m_xParent.is() ) 183 { 184 Reference< XAccessibleContext > 185 xParentContext( m_xParent->getAccessibleContext() ); 186 if( xParentContext.is() ) 187 return xParentContext->getLocale(); 188 } 189 throw IllegalAccessibleComponentStateException(); 190 } 191 192 // XAccessibleComponent ------------------------------------------------------- 193 194 sal_Bool SAL_CALL AccessibleGridControlBase::containsPoint( const awt::Point& rPoint ) 195 throw ( uno::RuntimeException ) 196 { 197 return Rectangle( Point(), getBoundingBox().GetSize() ).IsInside( VCLPoint( rPoint ) ); 198 } 199 200 awt::Rectangle SAL_CALL AccessibleGridControlBase::getBounds() 201 throw ( uno::RuntimeException ) 202 { 203 return AWTRectangle( getBoundingBox() ); 204 } 205 206 awt::Point SAL_CALL AccessibleGridControlBase::getLocation() 207 throw ( uno::RuntimeException ) 208 { 209 return AWTPoint( getBoundingBox().TopLeft() ); 210 } 211 212 awt::Point SAL_CALL AccessibleGridControlBase::getLocationOnScreen() 213 throw ( uno::RuntimeException ) 214 { 215 return AWTPoint( getBoundingBoxOnScreen().TopLeft() ); 216 } 217 218 awt::Size SAL_CALL AccessibleGridControlBase::getSize() 219 throw ( uno::RuntimeException ) 220 { 221 return AWTSize( getBoundingBox().GetSize() ); 222 } 223 224 sal_Bool SAL_CALL AccessibleGridControlBase::isShowing() 225 throw ( uno::RuntimeException ) 226 { 227 TCSolarGuard aSolarGuard; 228 ::osl::MutexGuard aGuard( getOslMutex() ); 229 ensureIsAlive(); 230 return implIsShowing(); 231 } 232 233 sal_Bool SAL_CALL AccessibleGridControlBase::isVisible() 234 throw ( uno::RuntimeException ) 235 { 236 Reference< XAccessibleStateSet > xStateSet = getAccessibleStateSet(); 237 return xStateSet.is() ? 238 xStateSet->contains( AccessibleStateType::VISIBLE ) : sal_False; 239 } 240 241 sal_Bool SAL_CALL AccessibleGridControlBase::isFocusTraversable() 242 throw ( uno::RuntimeException ) 243 { 244 Reference< XAccessibleStateSet > xStateSet = getAccessibleStateSet(); 245 return xStateSet.is() ? 246 xStateSet->contains( AccessibleStateType::FOCUSABLE ) : sal_False; 247 } 248 // XAccessibleEventBroadcaster ------------------------------------------------ 249 250 void SAL_CALL AccessibleGridControlBase::addEventListener( 251 const Reference< XAccessibleEventListener>& _rxListener ) 252 throw ( uno::RuntimeException ) 253 { 254 if ( _rxListener.is() ) 255 { 256 ::osl::MutexGuard aGuard( getOslMutex() ); 257 if ( !getClientId( ) ) 258 setClientId( AccessibleEventNotifier::registerClient( ) ); 259 260 AccessibleEventNotifier::addEventListener( getClientId( ), _rxListener ); 261 } 262 } 263 264 void SAL_CALL AccessibleGridControlBase::removeEventListener( 265 const Reference< XAccessibleEventListener>& _rxListener ) 266 throw ( uno::RuntimeException ) 267 { 268 if( _rxListener.is() && getClientId( ) ) 269 { 270 ::osl::MutexGuard aGuard( getOslMutex() ); 271 sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( getClientId( ), _rxListener ); 272 if ( !nListenerCount ) 273 { 274 // no listeners anymore 275 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), 276 // and at least to us not firing any events anymore, in case somebody calls 277 // NotifyAccessibleEvent, again 278 AccessibleEventNotifier::TClientId nId( getClientId( ) ); 279 setClientId( 0 ); 280 AccessibleEventNotifier::revokeClient( nId ); 281 } 282 } 283 } 284 285 // XTypeProvider -------------------------------------------------------------- 286 287 Sequence< sal_Int8 > SAL_CALL AccessibleGridControlBase::getImplementationId() 288 throw ( uno::RuntimeException ) 289 { 290 ::osl::MutexGuard aGuard( getOslGlobalMutex() ); 291 static Sequence< sal_Int8 > aId; 292 implCreateUuid( aId ); 293 return aId; 294 } 295 296 // XServiceInfo --------------------------------------------------------------- 297 298 sal_Bool SAL_CALL AccessibleGridControlBase::supportsService( 299 const OUString& rServiceName ) 300 throw ( uno::RuntimeException ) 301 { 302 ::osl::MutexGuard aGuard( getOslMutex() ); 303 304 Sequence< OUString > aSupportedServices( getSupportedServiceNames() ); 305 const OUString* pArrBegin = aSupportedServices.getConstArray(); 306 const OUString* pArrEnd = pArrBegin + aSupportedServices.getLength(); 307 const OUString* pString = pArrBegin; 308 309 for( ; ( pString != pArrEnd ) && ( rServiceName != *pString ); ++pString ) 310 ; 311 return pString != pArrEnd; 312 } 313 314 Sequence< OUString > SAL_CALL AccessibleGridControlBase::getSupportedServiceNames() 315 throw ( uno::RuntimeException ) 316 { 317 const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.AccessibleContext" ) ); 318 return Sequence< OUString >( &aServiceName, 1 ); 319 } 320 // internal virtual methods --------------------------------------------------- 321 322 sal_Bool AccessibleGridControlBase::implIsShowing() 323 { 324 sal_Bool bShowing = sal_False; 325 if( m_xParent.is() ) 326 { 327 Reference< XAccessibleComponent > 328 xParentComp( m_xParent->getAccessibleContext(), uno::UNO_QUERY ); 329 if( xParentComp.is() ) 330 bShowing = implGetBoundingBox().IsOver( 331 VCLRectangle( xParentComp->getBounds() ) ); 332 } 333 return bShowing; 334 } 335 336 ::utl::AccessibleStateSetHelper* AccessibleGridControlBase::implCreateStateSetHelper() 337 { 338 ::utl::AccessibleStateSetHelper* 339 pStateSetHelper = new ::utl::AccessibleStateSetHelper; 340 341 if( isAlive() ) 342 { 343 // SHOWING done with m_xParent 344 if( implIsShowing() ) 345 pStateSetHelper->AddState( AccessibleStateType::SHOWING ); 346 // GridControl fills StateSet with states depending on object type 347 m_aTable.FillAccessibleStateSet( *pStateSetHelper, getType() ); 348 } 349 else 350 pStateSetHelper->AddState( AccessibleStateType::DEFUNC ); 351 return pStateSetHelper; 352 } 353 354 // internal helper methods ---------------------------------------------------- 355 356 sal_Bool AccessibleGridControlBase::isAlive() const 357 { 358 return !rBHelper.bDisposed && !rBHelper.bInDispose && &m_aTable; 359 } 360 361 void AccessibleGridControlBase::ensureIsAlive() const 362 throw ( lang::DisposedException ) 363 { 364 if( !isAlive() ) 365 throw lang::DisposedException(); 366 } 367 368 Rectangle AccessibleGridControlBase::getBoundingBox() 369 throw ( lang::DisposedException ) 370 { 371 TCSolarGuard aSolarGuard; 372 ::osl::MutexGuard aGuard( getOslMutex() ); 373 ensureIsAlive(); 374 Rectangle aRect = implGetBoundingBox(); 375 if ( 0 == aRect.Left() && 0 == aRect.Top() && 0 == aRect.Right() && 0 == aRect.Bottom() ) 376 { 377 DBG_ERRORFILE( "rectangle doesn't exist" ); 378 } 379 return aRect; 380 } 381 382 Rectangle AccessibleGridControlBase::getBoundingBoxOnScreen() 383 throw ( lang::DisposedException ) 384 { 385 TCSolarGuard aSolarGuard; 386 ::osl::MutexGuard aGuard( getOslMutex() ); 387 ensureIsAlive(); 388 Rectangle aRect = implGetBoundingBoxOnScreen(); 389 if ( 0 == aRect.Left() && 0 == aRect.Top() && 0 == aRect.Right() && 0 == aRect.Bottom() ) 390 { 391 DBG_ERRORFILE( "rectangle doesn't exist" ); 392 } 393 return aRect; 394 } 395 396 void AccessibleGridControlBase::commitEvent( 397 sal_Int16 _nEventId, const Any& _rNewValue, const Any& _rOldValue ) 398 { 399 ::osl::ClearableMutexGuard aGuard( getOslMutex() ); 400 if ( !getClientId( ) ) 401 // if we don't have a client id for the notifier, then we don't have listeners, then 402 // we don't need to notify anything 403 return; 404 405 // build an event object 406 AccessibleEventObject aEvent; 407 aEvent.Source = *this; 408 aEvent.EventId = _nEventId; 409 aEvent.OldValue = _rOldValue; 410 aEvent.NewValue = _rNewValue; 411 412 // let the notifier handle this event 413 414 AccessibleEventNotifier::addEvent( getClientId( ), aEvent ); 415 } 416 // ----------------------------------------------------------------------------- 417 418 void AccessibleGridControlBase::implCreateUuid( Sequence< sal_Int8 >& rId ) 419 { 420 if( !rId.hasElements() ) 421 { 422 rId.realloc( 16 ); 423 rtl_createUuid( reinterpret_cast< sal_uInt8* >( rId.getArray() ), 0, sal_True ); 424 } 425 } 426 // ----------------------------------------------------------------------------- 427 sal_Int16 SAL_CALL AccessibleGridControlBase::getAccessibleRole() 428 throw ( uno::RuntimeException ) 429 { 430 ensureIsAlive(); 431 sal_Int16 nRole = AccessibleRole::UNKNOWN; 432 switch ( m_eObjType ) 433 { 434 case TCTYPE_ROWHEADERCELL: 435 nRole = AccessibleRole::ROW_HEADER; 436 break; 437 case TCTYPE_COLUMNHEADERCELL: 438 nRole = AccessibleRole::COLUMN_HEADER; 439 break; 440 case TCTYPE_COLUMNHEADERBAR: 441 case TCTYPE_ROWHEADERBAR: 442 case TCTYPE_TABLE: 443 nRole = AccessibleRole::TABLE; 444 break; 445 case TCTYPE_TABLECELL: 446 nRole = AccessibleRole::TABLE_CELL; 447 break; 448 case TCTYPE_GRIDCONTROL: 449 nRole = AccessibleRole::PANEL; 450 break; 451 } 452 return nRole; 453 } 454 // ----------------------------------------------------------------------------- 455 Any SAL_CALL AccessibleGridControlBase::getAccessibleKeyBinding() 456 throw ( uno::RuntimeException ) 457 { 458 return Any(); 459 } 460 // ----------------------------------------------------------------------------- 461 Reference<XAccessible > SAL_CALL AccessibleGridControlBase::getAccessibleAtPoint( const ::com::sun::star::awt::Point& ) 462 throw ( uno::RuntimeException ) 463 { 464 return NULL; 465 } 466 //// ----------------------------------------------------------------------------- 467 sal_Int32 SAL_CALL AccessibleGridControlBase::getForeground( ) throw (::com::sun::star::uno::RuntimeException) 468 { 469 TCSolarGuard aSolarGuard; 470 ::osl::MutexGuard aGuard( getOslMutex() ); 471 ensureIsAlive(); 472 473 sal_Int32 nColor = 0; 474 Window* pInst = m_aTable.GetWindowInstance(); 475 if ( pInst ) 476 { 477 if ( pInst->IsControlForeground() ) 478 nColor = pInst->GetControlForeground().GetColor(); 479 else 480 { 481 Font aFont; 482 if ( pInst->IsControlFont() ) 483 aFont = pInst->GetControlFont(); 484 else 485 aFont = pInst->GetFont(); 486 nColor = aFont.GetColor().GetColor(); 487 } 488 } 489 return nColor; 490 } 491 // ----------------------------------------------------------------------------- 492 sal_Int32 SAL_CALL AccessibleGridControlBase::getBackground( ) throw (::com::sun::star::uno::RuntimeException) 493 { 494 TCSolarGuard aSolarGuard; 495 ::osl::MutexGuard aGuard( getOslMutex() ); 496 ensureIsAlive(); 497 sal_Int32 nColor = 0; 498 Window* pInst = m_aTable.GetWindowInstance(); 499 if ( pInst ) 500 { 501 if ( pInst->IsControlBackground() ) 502 nColor = pInst->GetControlBackground().GetColor(); 503 else 504 nColor = pInst->GetBackground().GetColor().GetColor(); 505 } 506 return nColor; 507 } 508 509 //// ============================================================================ 510 GridControlAccessibleElement::GridControlAccessibleElement( const Reference< XAccessible >& rxParent, 511 IAccessibleTable& rTable, 512 AccessibleTableControlObjType eObjType ) 513 :AccessibleGridControlBase( rxParent, rTable, eObjType ) 514 { 515 } 516 517 // XInterface ----------------------------------------------------------------- 518 IMPLEMENT_FORWARD_XINTERFACE2( GridControlAccessibleElement, AccessibleGridControlBase, GridControlAccessibleElement_Base) 519 520 // XTypeProvider -------------------------------------------------------------- 521 IMPLEMENT_FORWARD_XTYPEPROVIDER2( GridControlAccessibleElement, AccessibleGridControlBase, GridControlAccessibleElement_Base ) 522 523 // XAccessible ---------------------------------------------------------------- 524 525 Reference< XAccessibleContext > SAL_CALL GridControlAccessibleElement::getAccessibleContext() throw ( uno::RuntimeException ) 526 { 527 ensureIsAlive(); 528 return this; 529 } 530 // ---------------------------------------------------------------------------- 531 GridControlAccessibleElement::~GridControlAccessibleElement( ) 532 { 533 } 534 535 // ============================================================================ 536 537 } // namespace accessibility 538 539 // ============================================================================ 540 541