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