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/AccessibleGridControl.hxx" 31 #include "accessibility/extended/AccessibleGridControlTable.hxx" 32 #include "accessibility/extended/AccessibleGridControlHeader.hxx" 33 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 34 #include <com/sun/star/accessibility/AccessibleTableModelChange.hpp> 35 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp> 36 #include <svtools/accessibletable.hxx> 37 #include <comphelper/types.hxx> 38 #include <toolkit/helper/vclunohelper.hxx> 39 40 // ============================================================================ 41 42 namespace accessibility 43 { 44 45 // ============================================================================ 46 47 using ::rtl::OUString; 48 49 using namespace ::com::sun::star::uno; 50 using namespace ::com::sun::star; 51 using namespace ::com::sun::star::lang; 52 using namespace ::com::sun::star::accessibility; 53 using namespace ::svt; 54 using namespace ::svt::table; 55 56 // ============================================================================ 57 class AccessibleGridControl_Impl 58 { 59 public: 60 /// the XAccessible which created the AccessibleGridControl 61 WeakReference< XAccessible > m_aCreator; 62 63 /** The data table child. */ 64 Reference< 65 ::com::sun::star::accessibility::XAccessible > m_xTable; 66 AccessibleGridControlTable* m_pTable; 67 68 /** The header bar for rows. */ 69 Reference< 70 ::com::sun::star::accessibility::XAccessible > m_xRowHeaderBar; 71 AccessibleGridControlHeader* m_pRowHeaderBar; 72 73 /** The header bar for columns (first row of the table). */ 74 Reference< 75 ::com::sun::star::accessibility::XAccessible > m_xColumnHeaderBar; 76 AccessibleGridControlHeader* m_pColumnHeaderBar; 77 78 /** The table cell child. */ 79 Reference< 80 ::com::sun::star::accessibility::XAccessible > m_xCell; 81 AccessibleGridControlTableCell* m_pCell; 82 }; 83 84 DBG_NAME( AccessibleGridControl ) 85 86 AccessibleGridControl::AccessibleGridControl( 87 const Reference< XAccessible >& _rxParent, const Reference< XAccessible >& _rxCreator, 88 IAccessibleTable& _rTable ) 89 : AccessibleGridControlBase( _rxParent, _rTable, TCTYPE_GRIDCONTROL ) 90 { 91 m_pImpl.reset( new AccessibleGridControl_Impl() ); 92 m_pImpl->m_aCreator = _rxCreator; 93 } 94 95 // ----------------------------------------------------------------------------- 96 AccessibleGridControl::~AccessibleGridControl() 97 { 98 } 99 // ----------------------------------------------------------------------------- 100 101 void SAL_CALL AccessibleGridControl::disposing() 102 { 103 ::osl::MutexGuard aGuard( getOslMutex() ); 104 105 m_pImpl->m_pTable = NULL; 106 m_pImpl->m_pColumnHeaderBar = NULL; 107 m_pImpl->m_pRowHeaderBar = NULL; 108 m_pImpl->m_pCell = NULL; 109 m_pImpl->m_aCreator = Reference< XAccessible >(); 110 111 Reference< XAccessible > xTable = m_pImpl->m_xTable; 112 113 Reference< XComponent > xComp( m_pImpl->m_xTable, UNO_QUERY ); 114 if ( xComp.is() ) 115 { 116 xComp->dispose(); 117 } 118 Reference< XAccessible > xCell = m_pImpl->m_xCell; 119 120 Reference< XComponent > xCellComp( m_pImpl->m_xCell, UNO_QUERY ); 121 if ( xCellComp.is() ) 122 { 123 xCellComp->dispose(); 124 } 125 126 ::comphelper::disposeComponent(m_pImpl->m_xRowHeaderBar); 127 ::comphelper::disposeComponent(m_pImpl->m_xColumnHeaderBar); 128 AccessibleGridControlBase::disposing(); 129 } 130 // ----------------------------------------------------------------------------- 131 132 // XAccessibleContext --------------------------------------------------------- 133 134 sal_Int32 SAL_CALL AccessibleGridControl::getAccessibleChildCount() 135 throw ( uno::RuntimeException ) 136 { 137 TCSolarGuard aSolarGuard; 138 ::osl::MutexGuard aGuard( getOslMutex() ); 139 ensureIsAlive(); 140 return m_aTable.GetAccessibleControlCount(); 141 } 142 // ----------------------------------------------------------------------------- 143 144 Reference< XAccessible > SAL_CALL 145 AccessibleGridControl::getAccessibleChild( sal_Int32 nChildIndex ) 146 throw ( lang::IndexOutOfBoundsException, uno::RuntimeException ) 147 { 148 TCSolarGuard aSolarGuard; 149 ::osl::MutexGuard aGuard( getOslMutex() ); 150 151 if (nChildIndex<0 || nChildIndex>=getAccessibleChildCount()) 152 throw IndexOutOfBoundsException(); 153 154 Reference< XAccessible > xChild; 155 if (isAlive()) 156 { 157 if(nChildIndex == 0 && m_aTable.HasColHeader()) 158 { 159 if(!m_pImpl->m_xColumnHeaderBar.is()) 160 { 161 AccessibleGridControlHeader* pColHeaderBar = new AccessibleGridControlHeader(m_pImpl->m_aCreator, m_aTable, svt::table::TCTYPE_COLUMNHEADERBAR); 162 m_pImpl->m_xColumnHeaderBar = pColHeaderBar; 163 } 164 xChild = m_pImpl->m_xColumnHeaderBar; 165 } 166 else if(m_aTable.HasRowHeader() && (nChildIndex == 1 || nChildIndex == 0)) 167 { 168 if(!m_pImpl->m_xRowHeaderBar.is()) 169 { 170 AccessibleGridControlHeader* pRowHeaderBar = new AccessibleGridControlHeader(m_pImpl->m_aCreator, m_aTable, svt::table::TCTYPE_ROWHEADERBAR); 171 m_pImpl->m_xRowHeaderBar = pRowHeaderBar; 172 } 173 xChild = m_pImpl->m_xRowHeaderBar; 174 } 175 else 176 { 177 if(!m_pImpl->m_xTable.is()) 178 { 179 AccessibleGridControlTable* pTable = new AccessibleGridControlTable(m_pImpl->m_aCreator, m_aTable, svt::table::TCTYPE_TABLE); 180 m_pImpl->m_xTable = pTable; 181 m_pImpl->m_pTable = pTable; 182 } 183 xChild = m_pImpl->m_xTable; 184 } 185 } 186 return xChild; 187 } 188 // ----------------------------------------------------------------------------- 189 190 sal_Int16 SAL_CALL AccessibleGridControl::getAccessibleRole() 191 throw ( uno::RuntimeException ) 192 { 193 ensureIsAlive(); 194 return AccessibleRole::PANEL; 195 } 196 // ----------------------------------------------------------------------------- 197 198 // XAccessibleComponent ------------------------------------------------------- 199 200 Reference< XAccessible > SAL_CALL 201 AccessibleGridControl::getAccessibleAtPoint( const awt::Point& rPoint ) 202 throw ( uno::RuntimeException ) 203 { 204 TCSolarGuard aSolarGuard; 205 ::osl::MutexGuard aGuard( getOslMutex() ); 206 ensureIsAlive(); 207 208 Reference< XAccessible > xChild; 209 sal_Int32 nIndex = 0; 210 if( m_aTable.ConvertPointToControlIndex( nIndex, VCLPoint( rPoint ) ) ) 211 xChild = m_aTable.CreateAccessibleControl( nIndex ); 212 else 213 { 214 // try whether point is in one of the fixed children 215 // (table, header bars, corner control) 216 Point aPoint( VCLPoint( rPoint ) ); 217 for( nIndex = 0; (nIndex < 3) && !xChild.is(); ++nIndex ) 218 { 219 Reference< XAccessible > xCurrChild( implGetFixedChild( nIndex ) ); 220 Reference< XAccessibleComponent > 221 xCurrChildComp( xCurrChild, uno::UNO_QUERY ); 222 223 if( xCurrChildComp.is() && 224 VCLRectangle( xCurrChildComp->getBounds() ).IsInside( aPoint ) ) 225 xChild = xCurrChild; 226 } 227 } 228 return xChild; 229 } 230 // ----------------------------------------------------------------------------- 231 232 void SAL_CALL AccessibleGridControl::grabFocus() 233 throw ( uno::RuntimeException ) 234 { 235 TCSolarGuard aSolarGuard; 236 ::osl::MutexGuard aGuard( getOslMutex() ); 237 ensureIsAlive(); 238 m_aTable.GrabFocus(); 239 } 240 // ----------------------------------------------------------------------------- 241 242 Any SAL_CALL AccessibleGridControl::getAccessibleKeyBinding() 243 throw ( uno::RuntimeException ) 244 { 245 ensureIsAlive(); 246 return Any(); 247 } 248 // ----------------------------------------------------------------------------- 249 250 // XServiceInfo --------------------------------------------------------------- 251 252 OUString SAL_CALL AccessibleGridControl::getImplementationName() 253 throw ( uno::RuntimeException ) 254 { 255 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.AccessibleGridControl" ) ); 256 } 257 // ----------------------------------------------------------------------------- 258 259 // internal virtual methods --------------------------------------------------- 260 261 Rectangle AccessibleGridControl::implGetBoundingBox() 262 { 263 Window* pParent = m_aTable.GetAccessibleParentWindow(); 264 DBG_ASSERT( pParent, "implGetBoundingBox - missing parent window" ); 265 return m_aTable.GetWindowExtentsRelative( pParent ); 266 } 267 // ----------------------------------------------------------------------------- 268 269 Rectangle AccessibleGridControl::implGetBoundingBoxOnScreen() 270 { 271 return m_aTable.GetWindowExtentsRelative( NULL ); 272 } 273 // internal helper methods ---------------------------------------------------- 274 275 Reference< XAccessible > AccessibleGridControl::implGetTable() 276 { 277 if( !m_pImpl->m_xTable.is() ) 278 { 279 m_pImpl->m_pTable = createAccessibleTable(); 280 m_pImpl->m_xTable = m_pImpl->m_pTable; 281 } 282 return m_pImpl->m_xTable; 283 } 284 // ----------------------------------------------------------------------------- 285 286 Reference< XAccessible > 287 AccessibleGridControl::implGetHeaderBar( AccessibleTableControlObjType eObjType ) 288 { 289 Reference< XAccessible > xRet; 290 Reference< XAccessible >* pxMember = NULL; 291 292 if( eObjType == TCTYPE_ROWHEADERBAR ) 293 pxMember = &m_pImpl->m_xRowHeaderBar; 294 else if( eObjType == TCTYPE_COLUMNHEADERBAR ) 295 pxMember = &m_pImpl->m_xColumnHeaderBar; 296 297 if( pxMember ) 298 { 299 if( !pxMember->is() ) 300 { 301 AccessibleGridControlHeader* pHeaderBar = new AccessibleGridControlHeader( 302 (Reference< XAccessible >)m_pImpl->m_aCreator, m_aTable, eObjType ); 303 304 if ( TCTYPE_COLUMNHEADERBAR == eObjType) 305 m_pImpl->m_pColumnHeaderBar = pHeaderBar; 306 else 307 m_pImpl->m_pRowHeaderBar = pHeaderBar; 308 309 *pxMember = pHeaderBar; 310 } 311 xRet = *pxMember; 312 } 313 return xRet; 314 } 315 // ----------------------------------------------------------------------------- 316 Reference< XAccessible > 317 AccessibleGridControl::implGetFixedChild( sal_Int32 nChildIndex ) 318 { 319 Reference< XAccessible > xRet; 320 switch( nChildIndex ) 321 { 322 case TCINDEX_COLUMNHEADERBAR: 323 xRet = implGetHeaderBar( TCTYPE_COLUMNHEADERBAR ); 324 break; 325 case TCINDEX_ROWHEADERBAR: 326 xRet = implGetHeaderBar( TCTYPE_ROWHEADERBAR ); 327 break; 328 case TCINDEX_TABLE: 329 xRet = implGetTable(); 330 break; 331 } 332 return xRet; 333 } 334 // ----------------------------------------------------------------------------- 335 AccessibleGridControlTable* AccessibleGridControl::createAccessibleTable() 336 { 337 Reference< XAccessible > xCreator = (Reference< XAccessible >)m_pImpl->m_aCreator; 338 DBG_ASSERT( xCreator.is(), "accessibility/extended/AccessibleGirdControl::createAccessibleTable: my creator died - how this?" ); 339 return new AccessibleGridControlTable( xCreator, m_aTable, TCTYPE_TABLE ); 340 } 341 // ----------------------------------------------------------------------------- 342 void AccessibleGridControl::commitCellEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue) 343 { 344 sal_Int32 nChildCount = getAccessibleChildCount(); 345 if(nChildCount != 0) 346 { 347 for(sal_Int32 i=0;i<nChildCount;i++) 348 { 349 Reference< XAccessible > xAccessible = getAccessibleChild(i); 350 com::sun::star::uno::Reference< com::sun::star::accessibility::XAccessibleContext > xAccessibleChild = xAccessible->getAccessibleContext(); 351 if(m_pImpl->m_xTable == xAccessible) 352 { 353 std::vector< AccessibleGridControlTableCell* > xCellCont = m_pImpl->m_pTable->getCellVector(); 354 int nIndex = m_aTable.GetCurrentRow()*m_aTable.GetColumnCount()+m_aTable.GetCurrentColumn(); 355 if(!xCellCont.empty() && xCellCont[nIndex]) 356 { 357 m_pImpl->m_pCell = xCellCont[nIndex]; 358 m_pImpl->m_pCell->commitEvent( _nEventId, _rNewValue, _rOldValue ); 359 } 360 } 361 } 362 } 363 else 364 { 365 if ( m_pImpl->m_xTable.is() ) 366 m_pImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue); 367 } 368 } 369 void AccessibleGridControl::commitTableEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue) 370 { 371 if ( m_pImpl->m_xTable.is() ) 372 { 373 if(_nEventId == AccessibleEventId::ACTIVE_DESCENDANT_CHANGED) 374 { 375 Reference< XAccessible > xChild = m_pImpl->m_pTable->getAccessibleChild(m_aTable.GetCurrentRow()*m_aTable.GetColumnCount()+m_aTable.GetCurrentColumn()); 376 m_pImpl->m_pTable->commitEvent(_nEventId, makeAny(xChild),_rOldValue); 377 } 378 else if(_nEventId == AccessibleEventId::TABLE_MODEL_CHANGED) 379 { 380 AccessibleTableModelChange aChange; 381 if(_rNewValue >>= aChange) 382 { 383 if(aChange.Type == AccessibleTableModelChangeType::DELETE) 384 { 385 std::vector< AccessibleGridControlTableCell* >::iterator m_pCell = m_pImpl->m_pTable->getCellVector().begin(); 386 std::vector< Reference< XAccessible > >::iterator m_xAccessibleVector = m_pImpl->m_pTable->getAccessibleCellVector().begin(); 387 int nColCount = m_aTable.GetColumnCount(); 388 m_pImpl->m_pTable->getCellVector().erase(m_pCell+nColCount*aChange.FirstRow, m_pCell+nColCount*aChange.LastRow ); 389 m_pImpl->m_pTable->getAccessibleCellVector().erase(m_xAccessibleVector+nColCount*aChange.FirstRow, m_xAccessibleVector+nColCount*aChange.LastRow); 390 m_pImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue); 391 } 392 else 393 m_pImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue); 394 } 395 } 396 else 397 m_pImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue); 398 } 399 } 400 // ============================================================================ 401 // = AccessibleGridControlAccess 402 // ============================================================================ 403 DBG_NAME( AccessibleGridControlAccess ) 404 // ----------------------------------------------------------------------------- 405 AccessibleGridControlAccess::AccessibleGridControlAccess( const Reference< XAccessible >& _rxParent, IAccessibleTable& _rTable ) 406 :m_xParent( _rxParent ) 407 ,m_rTable( _rTable ) 408 ,m_pContext( NULL ) 409 { 410 } 411 412 // ----------------------------------------------------------------------------- 413 AccessibleGridControlAccess::~AccessibleGridControlAccess() 414 { 415 } 416 417 // ----------------------------------------------------------------------------- 418 void AccessibleGridControlAccess::dispose() 419 { 420 ::osl::MutexGuard aGuard( m_aMutex ); 421 422 m_pContext = NULL; 423 ::comphelper::disposeComponent( m_xContext ); 424 } 425 426 // ----------------------------------------------------------------------------- 427 Reference< XAccessibleContext > SAL_CALL AccessibleGridControlAccess::getAccessibleContext() throw ( RuntimeException ) 428 { 429 ::osl::MutexGuard aGuard( m_aMutex ); 430 431 DBG_ASSERT( ( m_pContext && m_xContext.is() ) || ( !m_pContext && !m_xContext.is() ), 432 "accessibility/extended/AccessibleGridControlAccess::getAccessibleContext: inconsistency!" ); 433 434 // if the context died meanwhile (we're no listener, so it won't tell us explicitily when this happens), 435 // then reset an re-create. 436 if ( m_pContext && !m_pContext->isAlive() ) 437 m_xContext = m_pContext = NULL; 438 439 if ( !m_xContext.is() ) 440 m_xContext = m_pContext = new AccessibleGridControl( m_xParent, this, m_rTable ); 441 442 return m_xContext; 443 } 444 445 // ----------------------------------------------------------------------------- 446 bool AccessibleGridControlAccess::isContextAlive() const 447 { 448 return ( NULL != m_pContext ) && m_pContext->isAlive(); 449 } 450 451 // ============================================================================ 452 453 } // namespace accessibility 454