Bump version to 6.4-15
[LibreOffice.git] / svx / source / table / accessibletableshape.cxx
blobbab37ae9ffc5fad910a53ccb3ab5184959deb2d9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <com/sun/star/table/XMergeableCell.hpp>
22 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
23 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
24 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
26 #include <comphelper/accessiblewrapper.hxx>
27 #include <vcl/svapp.hxx>
29 #include <AccessibleTableShape.hxx>
30 #include <svx/sdr/table/tablecontroller.hxx>
31 #include "accessiblecell.hxx"
33 #include <algorithm>
34 #include <unordered_map>
36 #include <cppuhelper/implbase.hxx>
37 #include <svx/svdotable.hxx>
38 #include <com/sun/star/view/XSelectionSupplier.hpp>
41 using namespace ::accessibility;
42 using namespace sdr::table;
43 using namespace ::com::sun::star::accessibility;
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::beans;
46 using namespace ::com::sun::star::util;
47 using namespace ::com::sun::star::lang;
48 using namespace ::com::sun::star::drawing;
49 using namespace ::com::sun::star::table;
50 using namespace ::com::sun::star::container;
52 namespace accessibility
55 typedef std::unordered_map< Reference< XCell >, rtl::Reference< AccessibleCell > > AccessibleCellMap;
57 class AccessibleTableShapeImpl : public cppu::WeakImplHelper< XModifyListener >
59 public:
60 explicit AccessibleTableShapeImpl( AccessibleShapeTreeInfo& rShapeTreeInfo );
62 void init( const Reference< XAccessible>& xAccessible, const Reference< XTable >& xTable );
63 void dispose();
65 /// @throws IndexOutOfBoundsException
66 /// @throws RuntimeException
67 Reference< XAccessible > getAccessibleChild(sal_Int32 i);
68 /// @throws IndexOutOfBoundsException
69 void getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow );
71 // XModifyListener
72 virtual void SAL_CALL modified( const EventObject& aEvent ) override;
74 // XEventListener
75 virtual void SAL_CALL disposing( const EventObject& Source ) override;
77 AccessibleShapeTreeInfo& mrShapeTreeInfo;
78 Reference< XTable > mxTable;
79 AccessibleCellMap maChildMap;
80 Reference< XAccessible> mxAccessible;
81 sal_Int32 mRowCount, mColCount;
82 //get the cached AccessibleCell from XCell
83 rtl::Reference< AccessibleCell > getAccessibleCell (const Reference< XCell >& xCell);
84 /// @throws IndexOutOfBoundsException
85 /// @throws RuntimeException
86 rtl::Reference< AccessibleCell > getAccessibleCell (sal_Int32 nRow, sal_Int32 nColumn);
90 AccessibleTableShapeImpl::AccessibleTableShapeImpl( AccessibleShapeTreeInfo& rShapeTreeInfo )
91 : mrShapeTreeInfo( rShapeTreeInfo )
92 , mRowCount(0)
93 , mColCount(0)
98 void AccessibleTableShapeImpl::init( const Reference< XAccessible>& xAccessible, const Reference< XTable >& xTable )
100 mxAccessible = xAccessible;
101 mxTable = xTable;
103 if( mxTable.is() )
105 Reference< XModifyListener > xListener( this );
106 mxTable->addModifyListener( xListener );
107 //register the listener with table model
108 Reference< css::view::XSelectionSupplier > xSelSupplier(xTable, UNO_QUERY);
109 Reference< css::view::XSelectionChangeListener > xSelListener( xAccessible, UNO_QUERY );
110 if (xSelSupplier.is())
111 xSelSupplier->addSelectionChangeListener(xSelListener);
112 mRowCount = mxTable->getRowCount();
113 mColCount = mxTable->getColumnCount();
118 void AccessibleTableShapeImpl::dispose()
120 if( mxTable.is() )
122 //remove all the cell's acc object in table's dispose.
123 for( auto& rEntry : maChildMap )
125 rEntry.second->dispose();
127 maChildMap.clear();
128 Reference< XModifyListener > xListener( this );
129 mxTable->removeModifyListener( xListener );
130 mxTable.clear();
132 mxAccessible.clear();
136 //get the cached AccessibleCell from XCell
137 rtl::Reference< AccessibleCell > AccessibleTableShapeImpl::getAccessibleCell (const Reference< XCell >& xCell)
139 AccessibleCellMap::iterator iter( maChildMap.find( xCell ) );
141 if( iter != maChildMap.end() )
143 rtl::Reference< AccessibleCell > xChild( (*iter).second.get() );
144 return xChild;
146 return rtl::Reference< AccessibleCell >();
149 rtl::Reference< AccessibleCell > AccessibleTableShapeImpl::getAccessibleCell (sal_Int32 nRow, sal_Int32 nColumn)
151 Reference< XCell > xCell( mxTable->getCellByPosition( nColumn, nRow ) );
152 rtl::Reference< AccessibleCell > xChild = getAccessibleCell( xCell );
154 if( !xChild.is() && mxTable.is() )
156 sal_Int32 nChildIndex = mxTable->getColumnCount() * nRow + nColumn;
157 CellRef xCellRef( dynamic_cast< Cell* >( xCell.get() ) );
159 rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCellRef, nChildIndex, mrShapeTreeInfo ) );
161 xAccessibleCell->Init();
162 maChildMap[xCell] = xAccessibleCell;
164 xChild = rtl::Reference< AccessibleCell >( xAccessibleCell.get() );
166 return xChild;
170 Reference< XAccessible > AccessibleTableShapeImpl::getAccessibleChild(sal_Int32 nChildIndex)
172 sal_Int32 nColumn = 0, nRow = 0;
173 getColumnAndRow( nChildIndex, nColumn, nRow );
175 Reference< XCell > xCell( mxTable->getCellByPosition( nColumn, nRow ) );
176 AccessibleCellMap::iterator iter( maChildMap.find( xCell ) );
178 if( iter != maChildMap.end() )
180 Reference< XAccessible > xChild( (*iter).second.get() );
181 return xChild;
183 else
185 CellRef xCellRef( dynamic_cast< Cell* >( xCell.get() ) );
187 rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCellRef, nChildIndex, mrShapeTreeInfo ) );
189 xAccessibleCell->Init();
190 maChildMap[xCell] = xAccessibleCell;
192 Reference< XAccessible > xChild( xAccessibleCell.get() );
193 return xChild;
198 void AccessibleTableShapeImpl::getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow )
200 rnRow = 0;
201 rnColumn = nChildIndex;
203 if( mxTable.is() )
205 const sal_Int32 nColumnCount = mxTable->getColumnCount();
206 while( rnColumn >= nColumnCount )
208 rnRow++;
209 rnColumn -= nColumnCount;
212 if( rnRow < mxTable->getRowCount() )
213 return;
216 throw IndexOutOfBoundsException();
219 // XModifyListener
220 void SAL_CALL AccessibleTableShapeImpl::modified( const EventObject& /*aEvent*/ )
222 if( mxTable.is() ) try
224 // structural changes may have happened to the table, validate all accessible cell instances
225 AccessibleCellMap aTempChildMap;
226 aTempChildMap.swap( maChildMap );
228 // first move all still existing cells to maChildMap again and update their index
230 const sal_Int32 nRowCount = mxTable->getRowCount();
231 const sal_Int32 nColCount = mxTable->getColumnCount();
233 bool bRowOrColumnChanged = false;
234 if (mRowCount != nRowCount || mColCount != nColCount )
236 bRowOrColumnChanged = true;
237 mRowCount = nRowCount;
238 mColCount = nColCount;
240 sal_Int32 nChildIndex = 0;
242 for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
244 for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
246 Reference< XCell > xCell( mxTable->getCellByPosition( nCol, nRow ) );
247 AccessibleCellMap::iterator iter( aTempChildMap.find( xCell ) );
249 if( iter != aTempChildMap.end() )
251 rtl::Reference< AccessibleCell > xAccessibleCell( (*iter).second );
252 xAccessibleCell->setIndexInParent( nChildIndex );
253 xAccessibleCell->UpdateChildren();
254 // If row or column count is changed, there is split or merge, so all cell's acc name should be updated
255 if (bRowOrColumnChanged)
257 xAccessibleCell->SetAccessibleName(xAccessibleCell->getAccessibleName(), AccessibleContextBase::ManuallySet);
259 // For merged cell, add invisible & disabled state.
260 Reference< XMergeableCell > xMergedCell( mxTable->getCellByPosition( nCol, nRow ), UNO_QUERY );
261 if (xMergedCell.is() && xMergedCell->isMerged())
263 xAccessibleCell->ResetState(AccessibleStateType::VISIBLE);
264 xAccessibleCell->ResetState(AccessibleStateType::ENABLED);
265 // IA2 CWS. MT: OFFSCREEN == !SHOWING, should stay consistent
266 // xAccessibleCell->SetState(AccessibleStateType::OFFSCREEN);
267 xAccessibleCell->ResetState(AccessibleStateType::SHOWING);
269 else
271 xAccessibleCell->SetState(AccessibleStateType::VISIBLE);
272 xAccessibleCell->SetState(AccessibleStateType::ENABLED);
273 // IA2 CWS. MT: OFFSCREEN == !SHOWING, should stay consistent
274 // xAccessibleCell->ResetState(AccessibleStateType::OFFSCREEN);
275 xAccessibleCell->SetState(AccessibleStateType::SHOWING);
278 // move still existing cell from temporary child map to our child map
279 maChildMap[xCell] = xAccessibleCell;
280 aTempChildMap.erase( iter );
282 else
284 CellRef xCellRef( dynamic_cast< Cell* >( xCell.get() ) );
286 rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCellRef, nChildIndex, mrShapeTreeInfo ) );
288 xAccessibleCell->Init();
289 maChildMap[xCell] = xAccessibleCell;
292 ++nChildIndex;
296 // all accessible cell instances still left in aTempChildMap must be disposed
297 // as they are no longer part of the table
299 for( auto& rEntry : aTempChildMap )
301 rEntry.second->dispose();
303 //notify bridge to update the acc cache.
304 AccessibleTableShape *pAccTable = dynamic_cast <AccessibleTableShape *> (mxAccessible.get());
305 if (pAccTable)
306 pAccTable->CommitChange(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
308 catch( const Exception& )
310 OSL_FAIL("svx::AccessibleTableShape::modified(), exception caught!");
314 // XEventListener
315 void SAL_CALL AccessibleTableShapeImpl::disposing( const EventObject& /*Source*/ )
319 AccessibleTableShape::AccessibleTableShape( const AccessibleShapeInfo& rShapeInfo, const AccessibleShapeTreeInfo& rShapeTreeInfo)
320 : AccessibleTableShape_Base(rShapeInfo, rShapeTreeInfo)
321 , mnPreviousSelectionCount(0)
322 , mxImpl( new AccessibleTableShapeImpl( maShapeTreeInfo ) )
327 AccessibleTableShape::~AccessibleTableShape()
332 void AccessibleTableShape::Init()
336 Reference< XPropertySet > xSet( mxShape, UNO_QUERY_THROW );
337 Reference< XTable > xTable( xSet->getPropertyValue("Model"), UNO_QUERY_THROW );
339 mxImpl->init( this, xTable );
341 catch( Exception& )
343 OSL_FAIL("AccessibleTableShape::init(), exception caught?");
346 AccessibleTableShape_Base::Init();
350 SvxTableController* AccessibleTableShape::getTableController()
352 SdrView* pView = maShapeTreeInfo.GetSdrView ();
353 if( pView )
354 return dynamic_cast< SvxTableController* >( pView->getSelectionController().get() );
355 else
356 return nullptr;
360 // XInterface
363 Any SAL_CALL AccessibleTableShape::queryInterface( const Type& aType )
365 if ( aType == cppu::UnoType<XAccessibleTableSelection>::get())
367 Reference<XAccessibleTableSelection> xThis( this );
368 Any aRet;
369 aRet <<= xThis;
370 return aRet;
372 else
373 return AccessibleTableShape_Base::queryInterface( aType );
377 void SAL_CALL AccessibleTableShape::acquire( ) throw ()
379 AccessibleTableShape_Base::acquire();
383 void SAL_CALL AccessibleTableShape::release( ) throw ()
385 AccessibleTableShape_Base::release();
389 // XAccessible
392 OUString SAL_CALL AccessibleTableShape::getImplementationName()
394 return "com.sun.star.comp.accessibility.AccessibleTableShape";
398 OUString AccessibleTableShape::CreateAccessibleBaseName()
400 return "TableShape";
404 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleChildCount( )
406 SolarMutexGuard aSolarGuard;
407 return mxImpl->mxTable.is() ? mxImpl->mxTable->getRowCount() * mxImpl->mxTable->getColumnCount() : 0;
411 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleChild( sal_Int32 i )
413 SolarMutexGuard aSolarGuard;
414 ThrowIfDisposed();
416 return mxImpl->getAccessibleChild( i );
420 sal_Int16 SAL_CALL AccessibleTableShape::getAccessibleRole()
422 return AccessibleRole::TABLE;
426 void SAL_CALL AccessibleTableShape::disposing()
428 mxImpl->dispose();
430 // let the base do its stuff
431 AccessibleShape::disposing();
435 // XAccessibleTable
438 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRowCount()
440 SolarMutexGuard aSolarGuard;
441 return mxImpl->mxTable.is() ? mxImpl->mxTable->getRowCount() : 0;
445 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumnCount( )
447 SolarMutexGuard aSolarGuard;
448 return mxImpl->mxTable.is() ? mxImpl->mxTable->getColumnCount() : 0;
452 OUString SAL_CALL AccessibleTableShape::getAccessibleRowDescription( sal_Int32 nRow )
454 checkCellPosition( 0, nRow );
455 return OUString();
459 OUString SAL_CALL AccessibleTableShape::getAccessibleColumnDescription( sal_Int32 nColumn )
461 SolarMutexGuard aSolarGuard;
462 checkCellPosition( nColumn, 0 );
463 return OUString();
467 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
469 SolarMutexGuard aSolarGuard;
470 checkCellPosition( nColumn, nRow );
471 if( mxImpl->mxTable.is() )
473 Reference< XMergeableCell > xCell( mxImpl->mxTable->getCellByPosition( nColumn, nRow ), UNO_QUERY );
474 if( xCell.is() )
475 return xCell->getRowSpan();
477 return 1;
481 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
483 SolarMutexGuard aSolarGuard;
484 checkCellPosition( nColumn, nRow );
485 if( mxImpl->mxTable.is() )
487 Reference< XMergeableCell > xCell( mxImpl->mxTable->getCellByPosition( nColumn, nRow ), UNO_QUERY );
488 if( xCell.is() )
489 return xCell->getColumnSpan();
491 return 1;
495 Reference< XAccessibleTable > SAL_CALL AccessibleTableShape::getAccessibleRowHeaders( )
497 Reference< XAccessibleTable > xRet;
498 SvxTableController* pController = getTableController();
499 if( pController )
501 if( pController->isRowHeader() )
503 AccessibleTableHeaderShape* pTableHeader = new AccessibleTableHeaderShape( this, true );
504 xRet.set( pTableHeader );
507 return xRet;
511 Reference< XAccessibleTable > SAL_CALL AccessibleTableShape::getAccessibleColumnHeaders( )
513 Reference< XAccessibleTable > xRet;
514 SvxTableController* pController = getTableController();
515 if( pController )
517 if( pController->isColumnHeader() )
519 AccessibleTableHeaderShape* pTableHeader = new AccessibleTableHeaderShape( this, false );
520 xRet.set( pTableHeader );
523 return xRet;
527 Sequence< sal_Int32 > SAL_CALL AccessibleTableShape::getSelectedAccessibleRows( )
529 sal_Int32 nRow = getAccessibleRowCount();
530 ::std::vector<bool> aSelected( nRow, true );
531 sal_Int32 nCount = nRow;
532 for( sal_Int32 i = 0; i < nRow; i++ )
536 aSelected[i] = isAccessibleRowSelected( i );
538 catch( ... )
540 return Sequence< sal_Int32 >();
543 if( !aSelected[i] )
544 nCount--;
546 Sequence < sal_Int32 > aRet( nCount );
547 sal_Int32 *pRet = aRet.getArray();
548 sal_Int32 nPos = 0;
549 size_t nSize = aSelected.size();
550 for( size_t i=0; i < nSize && nPos < nCount; i++ )
552 if( aSelected[i] )
554 *pRet++ = i;
555 nPos++;
559 return aRet;
563 Sequence< sal_Int32 > SAL_CALL AccessibleTableShape::getSelectedAccessibleColumns( )
565 sal_Int32 nColumn = getAccessibleColumnCount();
566 ::std::vector<bool> aSelected( nColumn, true );
567 sal_Int32 nCount = nColumn;
568 for( sal_Int32 i = 0; i < nColumn; i++ )
572 aSelected[i] = isAccessibleColumnSelected( i );
574 catch( ... )
576 return Sequence< sal_Int32 >();
579 if( !aSelected[i] )
580 nCount--;
582 Sequence < sal_Int32 > aRet( nCount );
583 sal_Int32 *pRet = aRet.getArray();
584 sal_Int32 nPos = 0;
585 size_t nSize = aSelected.size();
586 for( size_t i=0; i < nSize && nPos < nCount; i++ )
588 if( aSelected[i] )
590 *pRet++ = i;
591 nPos++;
595 return aRet;
599 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleRowSelected( sal_Int32 nRow )
601 SolarMutexGuard aSolarGuard;
602 checkCellPosition( 0, nRow );
603 SvxTableController* pController = getTableController();
604 if( pController )
606 return pController->isRowSelected( nRow );
608 return false;
612 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleColumnSelected( sal_Int32 nColumn )
614 SolarMutexGuard aSolarGuard;
615 checkCellPosition( nColumn, 0 );
616 SvxTableController* pController = getTableController();
617 if( pController )
619 return pController->isColumnSelected( nColumn );
621 return false;
625 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
627 SolarMutexGuard aSolarGuard;
628 checkCellPosition( nColumn, nRow );
630 sal_Int32 nChildIndex = 0;
631 if( mxImpl->mxTable.is() )
632 nChildIndex = mxImpl->mxTable->getColumnCount() * nRow + nColumn;
634 return getAccessibleChild( nChildIndex );
638 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleCaption( )
640 Reference< XAccessible > xRet;
641 return xRet;
645 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleSummary( )
647 Reference< XAccessible > xRet;
648 return xRet;
652 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn )
654 SolarMutexGuard aSolarGuard;
655 checkCellPosition( nColumn, nRow );
657 SvxTableController* pController = getTableController();
658 if( pController && pController->hasSelectedCells() )
660 CellPos aFirstPos, aLastPos;
661 pController->getSelectedCells( aFirstPos, aLastPos );
662 if( (aFirstPos.mnRow <= nRow) && (aFirstPos.mnCol <= nColumn) && (nRow <= aLastPos.mnRow) && (nColumn <= aLastPos.mnCol) )
663 return true;
666 return false;
670 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn )
672 SolarMutexGuard aSolarGuard;
673 checkCellPosition( nColumn, nRow );
674 return mxImpl->mxTable.is() ? (nRow * mxImpl->mxTable->getColumnCount() + nColumn) : 0;
678 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRow( sal_Int32 nChildIndex )
680 SolarMutexGuard aSolarGuard;
681 sal_Int32 nColumn = 0, nRow = 0;
682 mxImpl->getColumnAndRow( nChildIndex, nColumn, nRow );
683 return nRow;
687 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumn( sal_Int32 nChildIndex )
689 SolarMutexGuard aSolarGuard;
690 sal_Int32 nColumn = 0, nRow = 0;
691 mxImpl->getColumnAndRow( nChildIndex, nColumn, nRow );
692 return nColumn;
696 // XAccessibleSelection
699 void SAL_CALL AccessibleTableShape::selectAccessibleChild( sal_Int32 nChildIndex )
701 SolarMutexGuard aSolarGuard;
702 CellPos aPos;
703 mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
705 // todo, select table shape?!?
706 SvxTableController* pController = getTableController();
707 if( pController )
709 CellPos aFirstPos( aPos ), aLastPos( aPos );
710 if( pController->hasSelectedCells() )
712 pController->getSelectedCells( aFirstPos, aLastPos );
714 aFirstPos.mnRow = std::min( aFirstPos.mnRow, aPos.mnRow );
715 aFirstPos.mnCol = std::min( aFirstPos.mnCol, aPos.mnCol );
716 aLastPos.mnRow = std::max( aLastPos.mnRow, aPos.mnRow );
717 aLastPos.mnCol = std::max( aLastPos.mnCol, aPos.mnCol );
719 pController->setSelectedCells( aFirstPos, aLastPos );
724 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleChildSelected( sal_Int32 nChildIndex )
726 SolarMutexGuard aSolarGuard;
727 CellPos aPos;
728 mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
730 return isAccessibleSelected(aPos.mnRow, aPos.mnCol);
734 void SAL_CALL AccessibleTableShape::clearAccessibleSelection()
736 SolarMutexGuard aSolarGuard;
738 SvxTableController* pController = getTableController();
739 if( pController )
740 pController->clearSelection();
744 void SAL_CALL AccessibleTableShape::selectAllAccessibleChildren()
746 SolarMutexGuard aSolarGuard;
748 // todo: force selection of shape?
749 SvxTableController* pController = getTableController();
750 if( pController )
751 pController->selectAll();
755 sal_Int32 SAL_CALL AccessibleTableShape::getSelectedAccessibleChildCount()
757 SolarMutexGuard aSolarGuard;
759 SvxTableController* pController = getTableController();
760 if( pController && pController->hasSelectedCells() )
762 CellPos aFirstPos, aLastPos;
763 pController->getSelectedCells( aFirstPos, aLastPos );
765 const sal_Int32 nSelectedColumns = std::max( sal_Int32(0), aLastPos.mnCol - aFirstPos.mnCol ) + 1;
766 const sal_Int32 nSelectedRows = std::max( sal_Int32(0), aLastPos.mnRow - aFirstPos.mnRow ) + 1;
767 return nSelectedRows * nSelectedColumns;
770 return 0;
774 Reference< XAccessible > SAL_CALL AccessibleTableShape::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
776 SolarMutexGuard aSolarGuard;
778 if( nSelectedChildIndex < 0 )
779 throw IndexOutOfBoundsException();
781 sal_Int32 nChildIndex = GetIndexOfSelectedChild( nSelectedChildIndex );
783 if( nChildIndex < 0 )
784 throw IndexOutOfBoundsException();
786 if ( nChildIndex >= getAccessibleChildCount() )
788 throw IndexOutOfBoundsException();
791 return getAccessibleChild( nChildIndex );
795 void SAL_CALL AccessibleTableShape::deselectAccessibleChild( sal_Int32 nChildIndex )
797 SolarMutexGuard aSolarGuard;
798 CellPos aPos;
799 mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
801 // todo, select table shape?!?
802 SvxTableController* pController = getTableController();
803 if( pController && pController->hasSelectedCells() )
805 CellPos aFirstPos, aLastPos;
806 pController->getSelectedCells( aFirstPos, aLastPos );
808 // create a selection where aPos is not part of anymore
809 aFirstPos.mnRow = std::min( aFirstPos.mnRow, aPos.mnRow+1 );
810 aFirstPos.mnCol = std::min( aFirstPos.mnCol, aPos.mnCol+1 );
811 aLastPos.mnRow = std::max( aLastPos.mnRow, aPos.mnRow-1 );
812 aLastPos.mnCol = std::max( aLastPos.mnCol, aPos.mnCol-1 );
814 // new selection may be invalid (child to deselect is not at a border of the selection but in between)
815 if( (aFirstPos.mnRow > aLastPos.mnRow) || (aFirstPos.mnCol > aLastPos.mnCol) )
816 pController->clearSelection(); // if selection is invalid, clear all
817 else
818 pController->setSelectedCells( aFirstPos, aLastPos );
822 // XAccessibleTableSelection
823 sal_Bool SAL_CALL AccessibleTableShape::selectRow( sal_Int32 row )
825 SolarMutexGuard aSolarGuard;
826 SvxTableController* pController = getTableController();
827 if( !pController )
828 return false;
829 return pController->selectRow( row );
832 sal_Bool SAL_CALL AccessibleTableShape::selectColumn( sal_Int32 column )
834 SolarMutexGuard aSolarGuard;
835 SvxTableController* pController = getTableController();
836 if( !pController )
837 return false;
838 return pController->selectColumn( column );
841 sal_Bool SAL_CALL AccessibleTableShape::unselectRow( sal_Int32 row )
843 SolarMutexGuard aSolarGuard;
844 SvxTableController* pController = getTableController();
845 if( !pController )
846 return false;
847 return pController->deselectRow( row );
850 sal_Bool SAL_CALL AccessibleTableShape::unselectColumn( sal_Int32 column )
852 SolarMutexGuard aSolarGuard;
853 SvxTableController* pController = getTableController();
854 if( !pController )
855 return false;
856 return pController->deselectColumn( column );
859 sal_Int32 AccessibleTableShape::GetIndexOfSelectedChild(
860 sal_Int32 nSelectedChildIndex ) const
862 sal_Int32 nChildren = const_cast<AccessibleTableShape*>(this)->getAccessibleChildCount();
864 if( nSelectedChildIndex >= nChildren )
865 return -1;
867 sal_Int32 n = 0;
868 while( n < nChildren )
870 if( const_cast<AccessibleTableShape*>(this)->isAccessibleChildSelected( n ) )
872 if( 0 == nSelectedChildIndex )
873 break;
874 else
875 --nSelectedChildIndex;
877 ++n;
880 return n < nChildren ? n : -1;
882 void AccessibleTableShape::getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow )
884 mxImpl->getColumnAndRow(nChildIndex, rnColumn, rnRow);
887 // XSelectionChangeListener
888 void SAL_CALL
889 AccessibleTableShape::disposing (const EventObject& aEvent)
891 AccessibleShape::disposing(aEvent);
893 void SAL_CALL AccessibleTableShape::selectionChanged (const EventObject& rEvent)
895 //sdr::table::CellRef xCellRef = static_cast< sdr::table::CellRef > (rEvent.Source);
896 Reference< XCell > xCell(rEvent.Source, UNO_QUERY);
897 if (xCell.is())
899 rtl::Reference< AccessibleCell > xAccCell = mxImpl->getAccessibleCell( xCell );
900 if (xAccCell.is())
902 sal_Int32 nIndex = xAccCell->getAccessibleIndexInParent(),
903 nCount = getSelectedAccessibleChildCount();
904 bool bSelected = isAccessibleChildSelected(nIndex);
905 if (mnPreviousSelectionCount == 0 && nCount > 0 && bSelected)
907 xAccCell->SetState(AccessibleStateType::SELECTED);
908 xAccCell->CommitChange(AccessibleEventId::SELECTION_CHANGED, Any(), Any());
910 else if (bSelected)
912 xAccCell->SetState(AccessibleStateType::SELECTED);
913 xAccCell->CommitChange(AccessibleEventId::SELECTION_CHANGED_ADD, Any(), Any());
915 else
917 xAccCell->ResetState(AccessibleStateType::SELECTED);
918 xAccCell->CommitChange(AccessibleEventId::SELECTION_CHANGED_REMOVE, Any(), Any());
920 mnPreviousSelectionCount = nCount;
924 // Get the currently active cell which is text editing
925 AccessibleCell* AccessibleTableShape::GetActiveAccessibleCell()
927 rtl::Reference< AccessibleCell > xAccCell;
928 AccessibleCell* pAccCell = nullptr;
929 SvxTableController* pController = getTableController();
930 if (pController)
932 sdr::table::SdrTableObj* pTableObj = pController->GetTableObj();
933 if ( pTableObj )
935 const sdr::table::CellRef& xCellRef (pTableObj->getActiveCell());
936 if ( xCellRef.is() )
940 CellPos rPos;
941 pTableObj->getActiveCellPos( rPos );
942 xAccCell = mxImpl->getAccessibleCell( rPos.mnRow, rPos.mnCol );
943 if ( xAccCell.is() )
944 pAccCell = xAccCell.get();
946 catch ( IndexOutOfBoundsException& ) {}
950 return pAccCell;
953 //If current active cell is in editing, the focus state should be set to internal text
954 bool AccessibleTableShape::SetState (sal_Int16 aState)
956 if( aState == AccessibleStateType::FOCUSED )
958 AccessibleCell* pActiveAccessibleCell = GetActiveAccessibleCell();
959 if( pActiveAccessibleCell != nullptr )
960 return pActiveAccessibleCell->SetState(aState);
963 return AccessibleShape::SetState (aState);
966 //If current active cell is in editing, the focus state should be reset to internal text
967 bool AccessibleTableShape::ResetState (sal_Int16 aState)
969 if( aState == AccessibleStateType::FOCUSED )
971 AccessibleCell* pActiveAccessibleCell = GetActiveAccessibleCell();
972 if( pActiveAccessibleCell != nullptr )
973 return pActiveAccessibleCell->ResetState(aState);
976 return AccessibleShape::ResetState (aState);
979 bool AccessibleTableShape::SetStateDirectly (sal_Int16 aState)
981 return AccessibleContextBase::SetState (aState);
984 bool AccessibleTableShape::ResetStateDirectly (sal_Int16 aState)
986 return AccessibleContextBase::ResetState (aState);
989 void AccessibleTableShape::checkCellPosition( sal_Int32 nCol, sal_Int32 nRow )
991 if( (nCol >= 0) && (nRow >= 0) && mxImpl->mxTable.is() && (nCol < mxImpl->mxTable->getColumnCount()) && (nRow < mxImpl->mxTable->getRowCount()) )
992 return;
994 throw IndexOutOfBoundsException();
997 AccessibleTableHeaderShape::AccessibleTableHeaderShape( AccessibleTableShape* pTable, bool bRow )
999 mpTable = pTable;
1000 mbRow = bRow;
1003 AccessibleTableHeaderShape::~AccessibleTableHeaderShape()
1005 mpTable = nullptr;
1008 // XAccessible
1009 Reference< XAccessibleContext > SAL_CALL AccessibleTableHeaderShape::getAccessibleContext()
1011 return this;
1014 // XAccessibleContext
1015 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleChildCount( )
1017 return getAccessibleRowCount() * getAccessibleColumnCount();
1020 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleChild( sal_Int32 i )
1022 return mpTable->getAccessibleChild( i );
1025 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleParent()
1027 Reference< XAccessible > XParent;
1028 return XParent;
1031 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleIndexInParent()
1033 return -1;
1036 sal_Int16 SAL_CALL AccessibleTableHeaderShape::getAccessibleRole()
1038 return mpTable->getAccessibleRole();
1041 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleDescription()
1043 return mpTable->getAccessibleDescription();
1046 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleName()
1048 return mpTable->getAccessibleName();
1051 Reference< XAccessibleStateSet > SAL_CALL AccessibleTableHeaderShape::getAccessibleStateSet()
1053 return mpTable->getAccessibleStateSet();
1056 Reference< XAccessibleRelationSet > SAL_CALL AccessibleTableHeaderShape::getAccessibleRelationSet()
1058 return mpTable->getAccessibleRelationSet();
1061 Locale SAL_CALL AccessibleTableHeaderShape::getLocale()
1063 return mpTable->getLocale();
1066 //XAccessibleComponent
1067 sal_Bool SAL_CALL AccessibleTableHeaderShape::containsPoint ( const css::awt::Point& aPoint )
1069 return mpTable->containsPoint( aPoint );
1072 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleAtPoint ( const css::awt::Point& aPoint)
1074 return mpTable->getAccessibleAtPoint( aPoint );
1077 css::awt::Rectangle SAL_CALL AccessibleTableHeaderShape::getBounds()
1079 return mpTable->getBounds();
1082 css::awt::Point SAL_CALL AccessibleTableHeaderShape::getLocation()
1084 return mpTable->getLocation();
1087 css::awt::Point SAL_CALL AccessibleTableHeaderShape::getLocationOnScreen()
1089 return mpTable->getLocationOnScreen();
1092 css::awt::Size SAL_CALL AccessibleTableHeaderShape::getSize()
1094 return mpTable->getSize();
1097 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getForeground()
1099 return mpTable->getForeground();
1102 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getBackground()
1104 return mpTable->getBackground();
1107 void SAL_CALL AccessibleTableHeaderShape::grabFocus()
1109 mpTable->grabFocus();
1111 // XAccessibleTable
1112 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleRowCount()
1114 return mbRow ? 1 : mpTable->getAccessibleRowCount();
1117 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnCount()
1119 return !mbRow ? 1 : mpTable->getAccessibleColumnCount();
1122 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleRowDescription( sal_Int32 nRow )
1124 return mpTable->getAccessibleRowDescription( nRow );
1127 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnDescription( sal_Int32 nColumn )
1129 return mpTable->getAccessibleColumnDescription( nColumn );
1132 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
1134 return mpTable->getAccessibleRowExtentAt( nRow, nColumn );
1137 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
1139 return mpTable->getAccessibleColumnExtentAt( nRow, nColumn );
1142 Reference< XAccessibleTable > SAL_CALL AccessibleTableHeaderShape::getAccessibleRowHeaders( )
1144 Reference< XAccessibleTable > xRet;
1145 return xRet;
1148 Reference< XAccessibleTable > SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnHeaders( )
1150 Reference< XAccessibleTable > xRet;
1151 return xRet;
1154 Sequence< sal_Int32 > SAL_CALL AccessibleTableHeaderShape::getSelectedAccessibleRows( )
1156 sal_Int32 nRow = getAccessibleRowCount();
1157 ::std::vector<bool> aSelected( nRow, true );
1158 sal_Int32 nCount = nRow;
1159 for( sal_Int32 i = 0; i < nRow; i++ )
1163 aSelected[i] = isAccessibleRowSelected( i );
1165 catch( ... )
1167 return Sequence< sal_Int32 >();
1170 if( !aSelected[i] )
1171 nCount--;
1173 Sequence < sal_Int32 > aRet( nCount );
1174 sal_Int32 *pRet = aRet.getArray();
1175 sal_Int32 nPos = 0;
1176 size_t nSize = aSelected.size();
1177 for( size_t i=0; i < nSize && nPos < nCount; i++ )
1179 if( aSelected[i] )
1181 *pRet++ = i;
1182 nPos++;
1186 return aRet;
1189 Sequence< sal_Int32 > SAL_CALL AccessibleTableHeaderShape::getSelectedAccessibleColumns( )
1191 sal_Int32 nColumn = getAccessibleColumnCount();
1192 ::std::vector<bool> aSelected( nColumn, true );
1193 sal_Int32 nCount = nColumn;
1194 for( sal_Int32 i = 0; i < nColumn; i++ )
1198 aSelected[i] = isAccessibleColumnSelected( i );
1200 catch( ... )
1202 return Sequence< sal_Int32 >();
1205 if( !aSelected[i] )
1206 nCount--;
1208 Sequence < sal_Int32 > aRet( nCount );
1209 sal_Int32 *pRet = aRet.getArray();
1210 sal_Int32 nPos = 0;
1211 size_t nSize = aSelected.size();
1212 for( size_t i=0; i < nSize && nPos < nCount; i++ )
1214 if( aSelected[i] )
1216 *pRet++ = i;
1217 nPos++;
1221 return aRet;
1224 sal_Bool SAL_CALL AccessibleTableHeaderShape::isAccessibleRowSelected( sal_Int32 nRow )
1226 return mpTable->isAccessibleRowSelected( nRow );
1229 sal_Bool SAL_CALL AccessibleTableHeaderShape::isAccessibleColumnSelected( sal_Int32 nColumn )
1231 return mpTable->isAccessibleColumnSelected( nColumn );
1234 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
1236 return mpTable->getAccessibleCellAt( nRow, nColumn );
1239 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleCaption( )
1241 return mpTable->getAccessibleCaption();
1244 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleSummary( )
1246 return mpTable->getAccessibleSummary();
1249 sal_Bool SAL_CALL AccessibleTableHeaderShape::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn )
1251 return mpTable->isAccessibleSelected( nRow, nColumn );
1254 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn )
1256 return mpTable->getAccessibleIndex( nRow, nColumn );
1259 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleRow( sal_Int32 nChildIndex )
1261 return mpTable->getAccessibleRow( nChildIndex );
1264 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleColumn( sal_Int32 nChildIndex )
1266 return mpTable->getAccessibleColumn( nChildIndex );
1269 // XAccessibleTableSelection
1270 sal_Bool SAL_CALL AccessibleTableHeaderShape::selectRow( sal_Int32 row )
1272 if( mbRow )
1273 return mpTable->selectRow( row );
1274 else
1276 mpTable->clearAccessibleSelection();
1277 sal_Int32 nIndex = mpTable->getAccessibleIndex( row, 0 );
1278 mpTable->selectAccessibleChild( nIndex );
1279 return true;
1283 sal_Bool SAL_CALL AccessibleTableHeaderShape::selectColumn( sal_Int32 column )
1285 if( !mbRow )
1286 return mpTable->selectColumn( column );
1287 else
1289 mpTable->clearAccessibleSelection();
1290 sal_Int32 nIndex = mpTable->getAccessibleIndex( 0, column );
1291 mpTable->selectAccessibleChild( nIndex );
1292 return true;
1296 sal_Bool SAL_CALL AccessibleTableHeaderShape::unselectRow( sal_Int32 row )
1298 if( mbRow )
1299 return mpTable->unselectRow( row );
1300 else
1302 sal_Int32 nIndex = mpTable->getAccessibleIndex( row, 0 );
1303 mpTable->deselectAccessibleChild( nIndex );
1304 return true;
1308 sal_Bool SAL_CALL AccessibleTableHeaderShape::unselectColumn( sal_Int32 column )
1310 if( !mbRow )
1311 return mpTable->unselectColumn( column );
1312 else
1314 sal_Int32 nIndex = mpTable->getAccessibleIndex( 0, column );
1315 mpTable->deselectAccessibleChild( nIndex );
1316 return true;
1321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */