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 { 101 ::osl::MutexGuard aGuard( getOslMutex() ); 102 ensureIsAlive(); 103 return m_xParent; 104 } 105 106 sal_Int32 SAL_CALL AccessibleGridControlBase::getAccessibleIndexInParent() 107 { 108 ::osl::MutexGuard aGuard( getOslMutex() ); 109 ensureIsAlive(); 110 111 // -1 for child not found/no parent (according to specification) 112 sal_Int32 nRet = -1; 113 114 Reference< uno::XInterface > xMeMyselfAndI( static_cast< XAccessibleContext* >( this ), uno::UNO_QUERY ); 115 116 // iterate over parent's children and search for this object 117 if( m_xParent.is() ) 118 { 119 Reference< XAccessibleContext > 120 xParentContext( m_xParent->getAccessibleContext() ); 121 if( xParentContext.is() ) 122 { 123 Reference< uno::XInterface > xChild; 124 125 sal_Int32 nChildCount = xParentContext->getAccessibleChildCount(); 126 for( sal_Int32 nChild = 0; nChild < nChildCount; ++nChild ) 127 { 128 xChild = xChild.query( xParentContext->getAccessibleChild( nChild ) ); 129 if ( xMeMyselfAndI.get() == xChild.get() ) 130 { 131 nRet = nChild; 132 break; 133 } 134 } 135 } 136 } 137 return nRet; 138 } 139 140 OUString SAL_CALL AccessibleGridControlBase::getAccessibleDescription() 141 { 142 ::osl::MutexGuard aGuard( getOslMutex() ); 143 ensureIsAlive(); 144 return m_aDescription; 145 } 146 147 OUString SAL_CALL AccessibleGridControlBase::getAccessibleName() 148 { 149 ::osl::MutexGuard aGuard( getOslMutex() ); 150 ensureIsAlive(); 151 return m_aName; 152 } 153 154 Reference< XAccessibleRelationSet > SAL_CALL 155 AccessibleGridControlBase::getAccessibleRelationSet() 156 { 157 ensureIsAlive(); 158 // GridControl does not have relations. 159 return new utl::AccessibleRelationSetHelper; 160 } 161 162 Reference< XAccessibleStateSet > SAL_CALL 163 AccessibleGridControlBase::getAccessibleStateSet() 164 { 165 TCSolarGuard aSolarGuard; 166 ::osl::MutexGuard aGuard( getOslMutex() ); 167 // don't check whether alive -> StateSet may contain DEFUNC 168 return implCreateStateSetHelper(); 169 } 170 171 lang::Locale SAL_CALL AccessibleGridControlBase::getLocale() 172 { 173 ::osl::MutexGuard aGuard( getOslMutex() ); 174 ensureIsAlive(); 175 if( m_xParent.is() ) 176 { 177 Reference< XAccessibleContext > 178 xParentContext( m_xParent->getAccessibleContext() ); 179 if( xParentContext.is() ) 180 return xParentContext->getLocale(); 181 } 182 throw IllegalAccessibleComponentStateException(); 183 } 184 185 // XAccessibleComponent ------------------------------------------------------- 186 187 sal_Bool SAL_CALL AccessibleGridControlBase::containsPoint( const awt::Point& rPoint ) 188 { 189 return Rectangle( Point(), getBoundingBox().GetSize() ).IsInside( VCLPoint( rPoint ) ); 190 } 191 192 awt::Rectangle SAL_CALL AccessibleGridControlBase::getBounds() 193 { 194 return AWTRectangle( getBoundingBox() ); 195 } 196 197 awt::Point SAL_CALL AccessibleGridControlBase::getLocation() 198 { 199 return AWTPoint( getBoundingBox().TopLeft() ); 200 } 201 202 awt::Point SAL_CALL AccessibleGridControlBase::getLocationOnScreen() 203 { 204 return AWTPoint( getBoundingBoxOnScreen().TopLeft() ); 205 } 206 207 awt::Size SAL_CALL AccessibleGridControlBase::getSize() 208 { 209 return AWTSize( getBoundingBox().GetSize() ); 210 } 211 212 sal_Bool SAL_CALL AccessibleGridControlBase::isShowing() 213 { 214 TCSolarGuard aSolarGuard; 215 ::osl::MutexGuard aGuard( getOslMutex() ); 216 ensureIsAlive(); 217 return implIsShowing(); 218 } 219 220 sal_Bool SAL_CALL AccessibleGridControlBase::isVisible() 221 { 222 Reference< XAccessibleStateSet > xStateSet = getAccessibleStateSet(); 223 return xStateSet.is() ? 224 xStateSet->contains( AccessibleStateType::VISIBLE ) : sal_False; 225 } 226 227 sal_Bool SAL_CALL AccessibleGridControlBase::isFocusTraversable() 228 { 229 Reference< XAccessibleStateSet > xStateSet = getAccessibleStateSet(); 230 return xStateSet.is() ? 231 xStateSet->contains( AccessibleStateType::FOCUSABLE ) : sal_False; 232 } 233 // XAccessibleEventBroadcaster ------------------------------------------------ 234 235 void SAL_CALL AccessibleGridControlBase::addEventListener( 236 const Reference< XAccessibleEventListener>& _rxListener ) 237 { 238 if ( _rxListener.is() ) 239 { 240 ::osl::MutexGuard aGuard( getOslMutex() ); 241 if ( !getClientId( ) ) 242 setClientId( AccessibleEventNotifier::registerClient( ) ); 243 244 AccessibleEventNotifier::addEventListener( getClientId( ), _rxListener ); 245 } 246 } 247 248 void SAL_CALL AccessibleGridControlBase::removeEventListener( 249 const Reference< XAccessibleEventListener>& _rxListener ) 250 { 251 if( _rxListener.is() && getClientId( ) ) 252 { 253 ::osl::MutexGuard aGuard( getOslMutex() ); 254 sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( getClientId( ), _rxListener ); 255 if ( !nListenerCount ) 256 { 257 // no listeners anymore 258 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), 259 // and at least to us not firing any events anymore, in case somebody calls 260 // NotifyAccessibleEvent, again 261 AccessibleEventNotifier::TClientId nId( getClientId( ) ); 262 setClientId( 0 ); 263 AccessibleEventNotifier::revokeClient( nId ); 264 } 265 } 266 } 267 268 // XTypeProvider -------------------------------------------------------------- 269 270 Sequence< sal_Int8 > SAL_CALL AccessibleGridControlBase::getImplementationId() 271 { 272 ::osl::MutexGuard aGuard( getOslGlobalMutex() ); 273 static Sequence< sal_Int8 > aId; 274 implCreateUuid( aId ); 275 return aId; 276 } 277 278 // XServiceInfo --------------------------------------------------------------- 279 280 sal_Bool SAL_CALL AccessibleGridControlBase::supportsService( 281 const OUString& rServiceName ) 282 { 283 ::osl::MutexGuard aGuard( getOslMutex() ); 284 285 Sequence< OUString > aSupportedServices( getSupportedServiceNames() ); 286 const OUString* pArrBegin = aSupportedServices.getConstArray(); 287 const OUString* pArrEnd = pArrBegin + aSupportedServices.getLength(); 288 const OUString* pString = pArrBegin; 289 290 for( ; ( pString != pArrEnd ) && ( rServiceName != *pString ); ++pString ) 291 ; 292 return pString != pArrEnd; 293 } 294 295 Sequence< OUString > SAL_CALL AccessibleGridControlBase::getSupportedServiceNames() 296 { 297 const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.AccessibleContext" ) ); 298 return Sequence< OUString >( &aServiceName, 1 ); 299 } 300 // internal virtual methods --------------------------------------------------- 301 302 sal_Bool AccessibleGridControlBase::implIsShowing() 303 { 304 sal_Bool bShowing = sal_False; 305 if( m_xParent.is() ) 306 { 307 Reference< XAccessibleComponent > 308 xParentComp( m_xParent->getAccessibleContext(), uno::UNO_QUERY ); 309 if( xParentComp.is() ) 310 bShowing = implGetBoundingBox().IsOver( 311 VCLRectangle( xParentComp->getBounds() ) ); 312 } 313 return bShowing; 314 } 315 316 ::utl::AccessibleStateSetHelper* AccessibleGridControlBase::implCreateStateSetHelper() 317 { 318 ::utl::AccessibleStateSetHelper* 319 pStateSetHelper = new ::utl::AccessibleStateSetHelper; 320 321 if( isAlive() ) 322 { 323 // SHOWING done with m_xParent 324 if( implIsShowing() ) 325 pStateSetHelper->AddState( AccessibleStateType::SHOWING ); 326 // GridControl fills StateSet with states depending on object type 327 m_aTable.FillAccessibleStateSet( *pStateSetHelper, getType() ); 328 } 329 else 330 pStateSetHelper->AddState( AccessibleStateType::DEFUNC ); 331 return pStateSetHelper; 332 } 333 334 // internal helper methods ---------------------------------------------------- 335 336 sal_Bool AccessibleGridControlBase::isAlive() const 337 { 338 return !rBHelper.bDisposed && !rBHelper.bInDispose && &m_aTable; 339 } 340 341 void AccessibleGridControlBase::ensureIsAlive() const 342 { 343 if( !isAlive() ) 344 throw lang::DisposedException(); 345 } 346 347 Rectangle AccessibleGridControlBase::getBoundingBox() 348 { 349 TCSolarGuard aSolarGuard; 350 ::osl::MutexGuard aGuard( getOslMutex() ); 351 ensureIsAlive(); 352 Rectangle aRect = implGetBoundingBox(); 353 if ( 0 == aRect.Left() && 0 == aRect.Top() && 0 == aRect.Right() && 0 == aRect.Bottom() ) 354 { 355 DBG_ERRORFILE( "rectangle doesn't exist" ); 356 } 357 return aRect; 358 } 359 360 Rectangle AccessibleGridControlBase::getBoundingBoxOnScreen() 361 { 362 TCSolarGuard aSolarGuard; 363 ::osl::MutexGuard aGuard( getOslMutex() ); 364 ensureIsAlive(); 365 Rectangle aRect = implGetBoundingBoxOnScreen(); 366 if ( 0 == aRect.Left() && 0 == aRect.Top() && 0 == aRect.Right() && 0 == aRect.Bottom() ) 367 { 368 DBG_ERRORFILE( "rectangle doesn't exist" ); 369 } 370 return aRect; 371 } 372 373 void AccessibleGridControlBase::commitEvent( 374 sal_Int16 _nEventId, const Any& _rNewValue, const Any& _rOldValue ) 375 { 376 ::osl::ClearableMutexGuard aGuard( getOslMutex() ); 377 if ( !getClientId( ) ) 378 // if we don't have a client id for the notifier, then we don't have listeners, then 379 // we don't need to notify anything 380 return; 381 382 // build an event object 383 AccessibleEventObject aEvent; 384 aEvent.Source = *this; 385 aEvent.EventId = _nEventId; 386 aEvent.OldValue = _rOldValue; 387 aEvent.NewValue = _rNewValue; 388 389 // let the notifier handle this event 390 391 AccessibleEventNotifier::addEvent( getClientId( ), aEvent ); 392 } 393 // ----------------------------------------------------------------------------- 394 395 void AccessibleGridControlBase::implCreateUuid( Sequence< sal_Int8 >& rId ) 396 { 397 if( !rId.hasElements() ) 398 { 399 rId.realloc( 16 ); 400 rtl_createUuid( reinterpret_cast< sal_uInt8* >( rId.getArray() ), 0, sal_True ); 401 } 402 } 403 // ----------------------------------------------------------------------------- 404 sal_Int16 SAL_CALL AccessibleGridControlBase::getAccessibleRole() 405 { 406 ensureIsAlive(); 407 sal_Int16 nRole = AccessibleRole::UNKNOWN; 408 switch ( m_eObjType ) 409 { 410 case TCTYPE_ROWHEADERCELL: 411 nRole = AccessibleRole::ROW_HEADER; 412 break; 413 case TCTYPE_COLUMNHEADERCELL: 414 nRole = AccessibleRole::COLUMN_HEADER; 415 break; 416 case TCTYPE_COLUMNHEADERBAR: 417 case TCTYPE_ROWHEADERBAR: 418 case TCTYPE_TABLE: 419 nRole = AccessibleRole::TABLE; 420 break; 421 case TCTYPE_TABLECELL: 422 nRole = AccessibleRole::TABLE_CELL; 423 break; 424 case TCTYPE_GRIDCONTROL: 425 nRole = AccessibleRole::PANEL; 426 break; 427 } 428 return nRole; 429 } 430 // ----------------------------------------------------------------------------- 431 Any SAL_CALL AccessibleGridControlBase::getAccessibleKeyBinding() 432 { 433 return Any(); 434 } 435 // ----------------------------------------------------------------------------- 436 Reference<XAccessible > SAL_CALL AccessibleGridControlBase::getAccessibleAtPoint( const ::com::sun::star::awt::Point& ) 437 { 438 return NULL; 439 } 440 //// ----------------------------------------------------------------------------- 441 sal_Int32 SAL_CALL AccessibleGridControlBase::getForeground( ) 442 { 443 TCSolarGuard aSolarGuard; 444 ::osl::MutexGuard aGuard( getOslMutex() ); 445 ensureIsAlive(); 446 447 sal_Int32 nColor = 0; 448 Window* pInst = m_aTable.GetWindowInstance(); 449 if ( pInst ) 450 { 451 if ( pInst->IsControlForeground() ) 452 nColor = pInst->GetControlForeground().GetColor(); 453 else 454 { 455 Font aFont; 456 if ( pInst->IsControlFont() ) 457 aFont = pInst->GetControlFont(); 458 else 459 aFont = pInst->GetFont(); 460 nColor = aFont.GetColor().GetColor(); 461 } 462 } 463 return nColor; 464 } 465 // ----------------------------------------------------------------------------- 466 sal_Int32 SAL_CALL AccessibleGridControlBase::getBackground( ) 467 { 468 TCSolarGuard aSolarGuard; 469 ::osl::MutexGuard aGuard( getOslMutex() ); 470 ensureIsAlive(); 471 sal_Int32 nColor = 0; 472 Window* pInst = m_aTable.GetWindowInstance(); 473 if ( pInst ) 474 { 475 if ( pInst->IsControlBackground() ) 476 nColor = pInst->GetControlBackground().GetColor(); 477 else 478 nColor = pInst->GetBackground().GetColor().GetColor(); 479 } 480 return nColor; 481 } 482 483 //// ============================================================================ 484 GridControlAccessibleElement::GridControlAccessibleElement( const Reference< XAccessible >& rxParent, 485 IAccessibleTable& rTable, 486 AccessibleTableControlObjType eObjType ) 487 :AccessibleGridControlBase( rxParent, rTable, eObjType ) 488 { 489 } 490 491 // XInterface ----------------------------------------------------------------- 492 IMPLEMENT_FORWARD_XINTERFACE2( GridControlAccessibleElement, AccessibleGridControlBase, GridControlAccessibleElement_Base) 493 494 // XTypeProvider -------------------------------------------------------------- 495 IMPLEMENT_FORWARD_XTYPEPROVIDER2( GridControlAccessibleElement, AccessibleGridControlBase, GridControlAccessibleElement_Base ) 496 497 // XAccessible ---------------------------------------------------------------- 498 499 Reference< XAccessibleContext > SAL_CALL GridControlAccessibleElement::getAccessibleContext() 500 { 501 ensureIsAlive(); 502 return this; 503 } 504 // ---------------------------------------------------------------------------- 505 GridControlAccessibleElement::~GridControlAccessibleElement( ) 506 { 507 } 508 509 // ============================================================================ 510 511 } // namespace accessibility 512 513 // ============================================================================ 514