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_svx.hxx" 30 31 #include <com/sun/star/table/XMergeableCell.hpp> 32 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 33 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 34 35 #include <comphelper/accessiblewrapper.hxx> 36 #include <vos/mutex.hxx> 37 #include <tools/debug.hxx> 38 #include <vcl/svapp.hxx> 39 40 #include <svx/AccessibleTableShape.hxx> 41 #include "tablecontroller.hxx" 42 #include "accessiblecell.hxx" 43 44 #include <algorithm> 45 46 #include <cppuhelper/implbase1.hxx> 47 48 using ::rtl::OUString; 49 50 using namespace ::accessibility; 51 using namespace ::sdr::table; 52 using namespace ::com::sun::star::accessibility; 53 using namespace ::com::sun::star::uno; 54 using namespace ::com::sun::star::beans; 55 using namespace ::com::sun::star::util; 56 using namespace ::com::sun::star::lang; 57 using namespace ::com::sun::star::drawing; 58 using namespace ::com::sun::star::table; 59 using namespace ::com::sun::star::container; 60 61 #define C2U(x) OUString(RTL_CONSTASCII_USTRINGPARAM(x)) 62 63 namespace accessibility 64 { 65 66 struct hash 67 { 68 std::size_t operator()( const Reference< XCell >& xCell ) const 69 { 70 return std::size_t( xCell.get() ); 71 } 72 }; 73 74 typedef std::hash_map< Reference< XCell >, rtl::Reference< AccessibleCell >, hash > AccessibleCellMap; 75 76 //----------------------------------------------------------------------------- 77 // AccessibleTableShapeImpl 78 //----------------------------------------------------------------------------- 79 80 class AccessibleTableShapeImpl : public cppu::WeakImplHelper1< XModifyListener > 81 { 82 public: 83 AccessibleTableShapeImpl( AccessibleShapeTreeInfo& rShapeTreeInfo ); 84 85 void init( const Reference< XAccessible>& xAccessible, const Reference< XTable >& xTable ); 86 void dispose(); 87 88 Reference< XAccessible > getAccessibleChild( sal_Int32 i ) throw(IndexOutOfBoundsException); 89 void getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow ) throw (IndexOutOfBoundsException ); 90 91 // XModifyListener 92 virtual void SAL_CALL modified( const EventObject& aEvent ) throw (RuntimeException); 93 94 // XEventListener 95 virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException); 96 97 AccessibleShapeTreeInfo& mrShapeTreeInfo; 98 Reference< XTable > mxTable; 99 AccessibleCellMap maChildMap; 100 Reference< XAccessible> mxAccessible; 101 }; 102 103 //----------------------------------------------------------------------------- 104 105 AccessibleTableShapeImpl::AccessibleTableShapeImpl( AccessibleShapeTreeInfo& rShapeTreeInfo ) 106 : mrShapeTreeInfo( rShapeTreeInfo ) 107 { 108 } 109 110 //----------------------------------------------------------------------------- 111 112 void AccessibleTableShapeImpl::init( const Reference< XAccessible>& xAccessible, const Reference< XTable >& xTable ) 113 { 114 mxAccessible = xAccessible; 115 mxTable = xTable; 116 117 if( mxTable.is() ) 118 { 119 Reference< XModifyListener > xListener( this ); 120 mxTable->addModifyListener( xListener ); 121 } 122 } 123 124 //----------------------------------------------------------------------------- 125 126 void AccessibleTableShapeImpl::dispose() 127 { 128 if( mxTable.is() ) 129 { 130 Reference< XModifyListener > xListener( this ); 131 mxTable->removeModifyListener( xListener ); 132 mxTable.clear(); 133 } 134 mxAccessible.clear(); 135 } 136 137 //----------------------------------------------------------------------------- 138 139 Reference< XAccessible > AccessibleTableShapeImpl::getAccessibleChild( sal_Int32 nChildIndex ) throw(IndexOutOfBoundsException) 140 { 141 sal_Int32 nColumn = 0, nRow = 0; 142 getColumnAndRow( nChildIndex, nColumn, nRow ); 143 144 Reference< XCell > xCell( mxTable->getCellByPosition( nColumn, nRow ) ); 145 AccessibleCellMap::iterator iter( maChildMap.find( xCell ) ); 146 147 if( iter != maChildMap.end() ) 148 { 149 Reference< XAccessible > xChild( (*iter).second.get() ); 150 return xChild; 151 } 152 else 153 { 154 CellRef xCellRef( dynamic_cast< Cell* >( xCell.get() ) ); 155 156 rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCellRef, nChildIndex, mrShapeTreeInfo ) ); 157 158 maChildMap[xCell] = xAccessibleCell; 159 160 xAccessibleCell->Init(); 161 162 Reference< XAccessible > xChild( xAccessibleCell.get() ); 163 return xChild; 164 } 165 } 166 167 //----------------------------------------------------------------------------- 168 169 void AccessibleTableShapeImpl::getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow ) throw (IndexOutOfBoundsException ) 170 { 171 rnRow = 0; 172 rnColumn = nChildIndex; 173 174 if( mxTable.is() ) 175 { 176 const sal_Int32 nColumnCount = mxTable->getColumnCount(); 177 while( rnColumn >= nColumnCount ) 178 { 179 rnRow++; 180 rnColumn -= nColumnCount; 181 } 182 183 if( rnRow < mxTable->getRowCount() ) 184 return; 185 } 186 187 throw IndexOutOfBoundsException(); 188 } 189 190 // XModifyListener 191 void SAL_CALL AccessibleTableShapeImpl::modified( const EventObject& /*aEvent*/ ) throw (RuntimeException) 192 { 193 if( mxTable.is() ) try 194 { 195 // structural changes may have happened to the table, validate all accessible cell instances 196 AccessibleCellMap aTempChildMap; 197 aTempChildMap.swap( maChildMap ); 198 199 // first move all still existing cells to maChildMap again and update their index 200 201 const sal_Int32 nRowCount = mxTable->getRowCount(); 202 const sal_Int32 nColCount = mxTable->getColumnCount(); 203 204 sal_Int32 nChildIndex = 0; 205 206 for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow ) 207 { 208 for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol ) 209 { 210 Reference< XCell > xCell( mxTable->getCellByPosition( nCol, nRow ) ); 211 AccessibleCellMap::iterator iter( aTempChildMap.find( xCell ) ); 212 213 if( iter != aTempChildMap.end() ) 214 { 215 rtl::Reference< AccessibleCell > xAccessibleCell( (*iter).second ); 216 xAccessibleCell->setIndexInParent( nChildIndex ); 217 xAccessibleCell->CommitChange(AccessibleEventId::VISIBLE_DATA_CHANGED, Any(), Any()); 218 219 // move still existing cell from temporary child map to our child map 220 maChildMap[xCell] = xAccessibleCell; 221 aTempChildMap.erase( iter ); 222 } 223 224 ++nChildIndex; 225 } 226 } 227 228 // all accessible cell instances still left in aTempChildMap must be disposed 229 // as they are no longer part of the table 230 231 for( AccessibleCellMap::iterator iter( aTempChildMap.begin() ); iter != aTempChildMap.end(); iter++ ) 232 { 233 (*iter).second->dispose(); 234 } 235 } 236 catch( Exception& ) 237 { 238 DBG_ERROR("svx::AccessibleTableShape::modified(), exception caught!"); 239 } 240 } 241 242 // XEventListener 243 void SAL_CALL AccessibleTableShapeImpl::disposing( const EventObject& /*Source*/ ) throw (RuntimeException) 244 { 245 } 246 247 //----------------------------------------------------------------------------- 248 // AccessibleTableShape 249 //----------------------------------------------------------------------------- 250 251 //----------------------------------------------------------------------------- 252 253 AccessibleTableShape::AccessibleTableShape( const AccessibleShapeInfo& rShapeInfo, const AccessibleShapeTreeInfo& rShapeTreeInfo) 254 : AccessibleTableShape_Base(rShapeInfo, rShapeTreeInfo) 255 , mxImpl( new AccessibleTableShapeImpl( maShapeTreeInfo ) ) 256 { 257 } 258 259 //----------------------------------------------------------------------------- 260 261 AccessibleTableShape::~AccessibleTableShape (void) 262 { 263 } 264 265 //----------------------------------------------------------------------------- 266 267 void AccessibleTableShape::Init() 268 { 269 try 270 { 271 272 Reference< XPropertySet > xSet( mxShape, UNO_QUERY_THROW ); 273 Reference< XTable > xTable( xSet->getPropertyValue(C2U("Model")), UNO_QUERY_THROW ); 274 275 mxImpl->init( this, xTable ); 276 } 277 catch( Exception& ) 278 { 279 DBG_ERROR("AccessibleTableShape::init(), exception caught?"); 280 } 281 282 AccessibleTableShape_Base::Init(); 283 } 284 285 //----------------------------------------------------------------------------- 286 287 SvxTableController* AccessibleTableShape::getTableController() 288 { 289 SdrView* pView = maShapeTreeInfo.GetSdrView (); 290 if( pView ) 291 return dynamic_cast< SvxTableController* >( pView->getSelectionController().get() ); 292 else 293 return 0; 294 } 295 296 //----------------------------------------------------------------------------- 297 // XInterface 298 //----------------------------------------------------------------------------- 299 300 Any SAL_CALL AccessibleTableShape::queryInterface( const Type& aType ) throw (RuntimeException) 301 { 302 return AccessibleTableShape_Base::queryInterface( aType ); 303 } 304 305 //----------------------------------------------------------------------------- 306 307 void SAL_CALL AccessibleTableShape::acquire( ) throw () 308 { 309 AccessibleTableShape_Base::acquire(); 310 } 311 312 //----------------------------------------------------------------------------- 313 314 void SAL_CALL AccessibleTableShape::release( ) throw () 315 { 316 AccessibleTableShape_Base::release(); 317 } 318 319 //----------------------------------------------------------------------------- 320 // XAccessible 321 //----------------------------------------------------------------------------- 322 323 Reference< XAccessibleContext > SAL_CALL AccessibleTableShape::getAccessibleContext(void) throw (RuntimeException) 324 { 325 return AccessibleShape::getAccessibleContext (); 326 } 327 328 //----------------------------------------------------------------------------- 329 OUString SAL_CALL AccessibleTableShape::getImplementationName(void) throw (RuntimeException) 330 { 331 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.accessibility.AccessibleTableShape" ) ); 332 } 333 334 //----------------------------------------------------------------------------- 335 336 OUString AccessibleTableShape::CreateAccessibleBaseName(void) throw (RuntimeException) 337 { 338 return OUString (RTL_CONSTASCII_USTRINGPARAM("TableShape"));; 339 } 340 341 //-------------------------------------------------------------------- 342 343 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleChildCount( ) throw(RuntimeException) 344 { 345 ::vos::OGuard aSolarGuard(::Application::GetSolarMutex()); 346 return mxImpl->mxTable.is() ? mxImpl->mxTable->getRowCount() * mxImpl->mxTable->getColumnCount() : 0; 347 } 348 349 //-------------------------------------------------------------------- 350 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleChild( sal_Int32 i ) throw(IndexOutOfBoundsException, RuntimeException) 351 { 352 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 353 ThrowIfDisposed(); 354 355 return mxImpl->getAccessibleChild( i ); 356 } 357 358 //-------------------------------------------------------------------- 359 Reference< XAccessibleRelationSet > SAL_CALL AccessibleTableShape::getAccessibleRelationSet( ) throw (RuntimeException) 360 { 361 return AccessibleShape::getAccessibleRelationSet( ); 362 } 363 364 //-------------------------------------------------------------------- 365 366 sal_Int16 SAL_CALL AccessibleTableShape::getAccessibleRole (void) throw (RuntimeException) 367 { 368 return AccessibleRole::TABLE; 369 } 370 371 //-------------------------------------------------------------------- 372 373 void SAL_CALL AccessibleTableShape::disposing (void) 374 { 375 mxImpl->dispose(); 376 377 // let the base do it's stuff 378 AccessibleShape::disposing(); 379 } 380 381 //-------------------------------------------------------------------- 382 // XAccessibleTable 383 //-------------------------------------------------------------------- 384 385 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRowCount() throw (RuntimeException) 386 { 387 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 388 return mxImpl->mxTable.is() ? mxImpl->mxTable->getRowCount() : 0; 389 } 390 391 //-------------------------------------------------------------------- 392 393 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumnCount( ) throw (RuntimeException) 394 { 395 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 396 return mxImpl->mxTable.is() ? mxImpl->mxTable->getColumnCount() : 0; 397 } 398 399 //-------------------------------------------------------------------- 400 401 OUString SAL_CALL AccessibleTableShape::getAccessibleRowDescription( sal_Int32 nRow ) throw (IndexOutOfBoundsException, RuntimeException) 402 { 403 checkCellPosition( 0, nRow ); 404 return OUString(); 405 } 406 407 //-------------------------------------------------------------------- 408 409 OUString SAL_CALL AccessibleTableShape::getAccessibleColumnDescription( sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException) 410 { 411 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 412 checkCellPosition( nColumn, 0 ); 413 return OUString(); 414 } 415 416 //-------------------------------------------------------------------- 417 418 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException) 419 { 420 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 421 checkCellPosition( nColumn, nRow ); 422 if( mxImpl->mxTable.is() ) 423 { 424 Reference< XMergeableCell > xCell( mxImpl->mxTable->getCellByPosition( nColumn, nRow ), UNO_QUERY ); 425 if( xCell.is() ) 426 return xCell->getRowSpan(); 427 } 428 return 1; 429 } 430 431 //-------------------------------------------------------------------- 432 433 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException) 434 { 435 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 436 checkCellPosition( nColumn, nRow ); 437 if( mxImpl->mxTable.is() ) 438 { 439 Reference< XMergeableCell > xCell( mxImpl->mxTable->getCellByPosition( nColumn, nRow ), UNO_QUERY ); 440 if( xCell.is() ) 441 return xCell->getColumnSpan(); 442 } 443 return 1; 444 } 445 446 //-------------------------------------------------------------------- 447 448 Reference< XAccessibleTable > SAL_CALL AccessibleTableShape::getAccessibleRowHeaders( ) throw (RuntimeException) 449 { 450 Reference< XAccessibleTable > xRet( this ); // todo 451 return xRet; 452 } 453 454 //-------------------------------------------------------------------- 455 456 Reference< XAccessibleTable > SAL_CALL AccessibleTableShape::getAccessibleColumnHeaders( ) throw (RuntimeException) 457 { 458 Reference< XAccessibleTable > xRet( this ); // todo 459 return xRet; 460 } 461 462 //-------------------------------------------------------------------- 463 464 Sequence< sal_Int32 > SAL_CALL AccessibleTableShape::getSelectedAccessibleRows( ) throw (RuntimeException) 465 { 466 Sequence< sal_Int32 > aRet; 467 return aRet; 468 } 469 470 //-------------------------------------------------------------------- 471 472 Sequence< sal_Int32 > SAL_CALL AccessibleTableShape::getSelectedAccessibleColumns( ) throw (RuntimeException) 473 { 474 Sequence< sal_Int32 > aRet; 475 return aRet; 476 } 477 478 //-------------------------------------------------------------------- 479 480 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleRowSelected( sal_Int32 nRow ) throw (IndexOutOfBoundsException, RuntimeException) 481 { 482 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 483 checkCellPosition( 0, nRow ); 484 return sal_False; 485 } 486 487 //-------------------------------------------------------------------- 488 489 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleColumnSelected( sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException) 490 { 491 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 492 checkCellPosition( nColumn, 0 ); 493 return sal_False; 494 } 495 496 //-------------------------------------------------------------------- 497 498 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException) 499 { 500 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 501 checkCellPosition( nColumn, nRow ); 502 503 sal_Int32 nChildIndex = 0; 504 if( mxImpl->mxTable.is() ) 505 nChildIndex = mxImpl->mxTable->getColumnCount() * nRow + nColumn; 506 507 return getAccessibleChild( nChildIndex ); 508 } 509 510 //-------------------------------------------------------------------- 511 512 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleCaption( ) throw (RuntimeException) 513 { 514 Reference< XAccessible > xRet; 515 return xRet; 516 } 517 518 //-------------------------------------------------------------------- 519 520 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleSummary( ) throw (RuntimeException) 521 { 522 Reference< XAccessible > xRet; 523 return xRet; 524 } 525 526 //-------------------------------------------------------------------- 527 528 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException) 529 { 530 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 531 checkCellPosition( nColumn, nRow ); 532 533 SvxTableController* pController = getTableController(); 534 if( pController && pController->hasSelectedCells() ) 535 { 536 CellPos aFirstPos, aLastPos; 537 pController->getSelectedCells( aFirstPos, aLastPos ); 538 if( (aFirstPos.mnRow <= nRow) && (aFirstPos.mnCol <= nColumn) && (nRow <= aLastPos.mnRow) && (nColumn <= aLastPos.mnCol) ) 539 return sal_True; 540 } 541 542 return sal_False; 543 } 544 545 //-------------------------------------------------------------------- 546 547 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException) 548 { 549 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 550 checkCellPosition( nColumn, nRow ); 551 return mxImpl->mxTable.is() ? (nRow * mxImpl->mxTable->getColumnCount() + nColumn) : 0; 552 } 553 554 //-------------------------------------------------------------------- 555 556 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRow( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 557 { 558 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 559 sal_Int32 nColumn = 0, nRow = 0; 560 mxImpl->getColumnAndRow( nChildIndex, nColumn, nRow ); 561 return nRow; 562 } 563 564 //-------------------------------------------------------------------- 565 566 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumn( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 567 { 568 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 569 sal_Int32 nColumn = 0, nRow = 0; 570 mxImpl->getColumnAndRow( nChildIndex, nColumn, nRow ); 571 return nChildIndex; 572 } 573 574 //-------------------------------------------------------------------- 575 // XAccessibleSelection 576 //-------------------------------------------------------------------- 577 578 void SAL_CALL AccessibleTableShape::selectAccessibleChild( sal_Int32 nChildIndex ) throw ( IndexOutOfBoundsException, RuntimeException ) 579 { 580 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 581 CellPos aPos; 582 mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow ); 583 584 // todo, select table shape?!? 585 SvxTableController* pController = getTableController(); 586 if( pController ) 587 { 588 CellPos aFirstPos( aPos ), aLastPos( aPos ); 589 if( pController->hasSelectedCells() ) 590 { 591 pController->getSelectedCells( aFirstPos, aLastPos ); 592 593 aFirstPos.mnRow = std::min( aFirstPos.mnRow, aPos.mnRow ); 594 aFirstPos.mnCol = std::min( aFirstPos.mnCol, aPos.mnCol ); 595 aLastPos.mnRow = std::max( aLastPos.mnRow, aPos.mnRow ); 596 aLastPos.mnCol = std::max( aLastPos.mnCol, aPos.mnCol ); 597 } 598 pController->setSelectedCells( aFirstPos, aLastPos ); 599 } 600 } 601 602 //-------------------------------------------------------------------- 603 604 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw ( IndexOutOfBoundsException, RuntimeException ) 605 { 606 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 607 CellPos aPos; 608 mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow ); 609 610 return isAccessibleSelected(aPos.mnCol, aPos.mnRow); 611 } 612 613 //-------------------------------------------------------------------- 614 615 void SAL_CALL AccessibleTableShape::clearAccessibleSelection() throw ( RuntimeException ) 616 { 617 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 618 619 SvxTableController* pController = getTableController(); 620 if( pController ) 621 pController->clearSelection(); 622 } 623 //-------------------------------------------------------------------- 624 625 void SAL_CALL AccessibleTableShape::selectAllAccessibleChildren() throw ( RuntimeException ) 626 { 627 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 628 629 // todo: force selection of shape? 630 SvxTableController* pController = getTableController(); 631 if( pController ) 632 pController->selectAll(); 633 } 634 635 //-------------------------------------------------------------------- 636 637 sal_Int32 SAL_CALL AccessibleTableShape::getSelectedAccessibleChildCount() throw ( RuntimeException ) 638 { 639 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 640 641 SvxTableController* pController = getTableController(); 642 if( pController && pController->hasSelectedCells() ) 643 { 644 CellPos aFirstPos, aLastPos; 645 pController->getSelectedCells( aFirstPos, aLastPos ); 646 647 const sal_Int32 nSelectedColumns = std::max( (sal_Int32)0, aLastPos.mnCol - aFirstPos.mnCol ) + 1; 648 const sal_Int32 nSelectedRows = std::max( (sal_Int32)0, aLastPos.mnRow - aFirstPos.mnRow ) + 1; 649 return nSelectedRows * nSelectedColumns; 650 } 651 652 return 0; 653 } 654 655 //-------------------------------------------------------------------- 656 657 Reference< XAccessible > SAL_CALL AccessibleTableShape::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw ( IndexOutOfBoundsException, RuntimeException) 658 { 659 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 660 661 SvxTableController* pController = getTableController(); 662 if( pController && pController->hasSelectedCells() ) 663 { 664 CellPos aFirstPos, aLastPos; 665 pController->getSelectedCells( aFirstPos, aLastPos ); 666 667 const sal_Int32 nSelectedColumns = std::max( (sal_Int32)0, aLastPos.mnCol - aFirstPos.mnCol ) + 1; 668 const sal_Int32 nSelectedRows = std::max( (sal_Int32)0, aLastPos.mnRow - aFirstPos.mnRow ) + 1; 669 670 if( nSelectedChildIndex < (nSelectedRows * nSelectedColumns) ) 671 { 672 while( nSelectedChildIndex >= nSelectedColumns ) 673 { 674 aFirstPos.mnRow++; 675 nSelectedChildIndex -= nSelectedColumns; 676 } 677 return getAccessibleCellAt( nSelectedColumns, aFirstPos.mnRow ); 678 } 679 } 680 681 throw IndexOutOfBoundsException(); 682 } 683 684 //-------------------------------------------------------------------- 685 686 void SAL_CALL AccessibleTableShape::deselectAccessibleChild( sal_Int32 nChildIndex ) throw ( IndexOutOfBoundsException, RuntimeException ) 687 { 688 ::vos::OGuard aSolarGuard (::Application::GetSolarMutex()); 689 CellPos aPos; 690 mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow ); 691 692 // todo, select table shape?!? 693 SvxTableController* pController = getTableController(); 694 if( pController && pController->hasSelectedCells() ) 695 { 696 CellPos aFirstPos, aLastPos; 697 pController->getSelectedCells( aFirstPos, aLastPos ); 698 699 // create a selection where aPos is not part of anymore 700 aFirstPos.mnRow = std::min( aFirstPos.mnRow, aPos.mnRow+1 ); 701 aFirstPos.mnCol = std::min( aFirstPos.mnCol, aPos.mnCol+1 ); 702 aLastPos.mnRow = std::max( aLastPos.mnRow, aPos.mnRow-1 ); 703 aLastPos.mnCol = std::max( aLastPos.mnCol, aPos.mnCol-1 ); 704 705 // new selection may be invalid (child to deselect is not at a border of the selection but in between) 706 if( (aFirstPos.mnRow > aLastPos.mnRow) || (aFirstPos.mnCol > aLastPos.mnCol) ) 707 pController->clearSelection(); // if selection is invalid, clear all 708 else 709 pController->setSelectedCells( aFirstPos, aLastPos ); 710 } 711 } 712 713 //-------------------------------------------------------------------- 714 715 void AccessibleTableShape::checkCellPosition( sal_Int32 nCol, sal_Int32 nRow ) throw ( IndexOutOfBoundsException ) 716 { 717 if( (nCol >= 0) && (nRow >= 0) && mxImpl->mxTable.is() && (nCol < mxImpl->mxTable->getColumnCount()) && (nRow < mxImpl->mxTable->getRowCount()) ) 718 return; 719 720 throw IndexOutOfBoundsException(); 721 } 722 723 } 724