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