tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / svx / source / table / accessibletableshape.cxx
bloba2ea65e4f056d2568f2b425fd235d4d0c5c891f6
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/accessibility/AccessibleRole.hpp>
25 #include <com/sun/star/drawing/XShape.hpp>
26 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
28 #include <comphelper/diagnose_ex.hxx>
29 #include <vcl/svapp.hxx>
31 #include <AccessibleTableShape.hxx>
32 #include <svx/sdr/table/tablecontroller.hxx>
33 #include "accessiblecell.hxx"
34 #include <cell.hxx>
36 #include <algorithm>
37 #include <unordered_map>
39 #include <cppuhelper/implbase.hxx>
40 #include <svx/svdotable.hxx>
41 #include <com/sun/star/view/XSelectionSupplier.hpp>
44 using namespace ::accessibility;
45 using namespace sdr::table;
46 using namespace ::com::sun::star::accessibility;
47 using namespace ::com::sun::star::uno;
48 using namespace ::com::sun::star::beans;
49 using namespace ::com::sun::star::util;
50 using namespace ::com::sun::star::lang;
51 using namespace ::com::sun::star::table;
53 namespace accessibility
56 typedef std::unordered_map< rtl::Reference< Cell >, rtl::Reference< AccessibleCell > > AccessibleCellMap;
58 class AccessibleTableShapeImpl : public cppu::WeakImplHelper< XModifyListener >
60 public:
61 explicit AccessibleTableShapeImpl( AccessibleShapeTreeInfo& rShapeTreeInfo );
63 void init( const rtl::Reference< AccessibleTableShape>& xAccessible, const rtl::Reference< TableModel >& xTable );
64 void dispose();
66 /// @throws IndexOutOfBoundsException
67 /// @throws RuntimeException
68 Reference< XAccessible > getAccessibleChild(sal_Int64 i);
69 /// @throws IndexOutOfBoundsException
70 void getColumnAndRow( sal_Int64 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow );
72 // XModifyListener
73 virtual void SAL_CALL modified( const EventObject& aEvent ) override;
75 // XEventListener
76 virtual void SAL_CALL disposing( const EventObject& Source ) override;
78 AccessibleShapeTreeInfo& mrShapeTreeInfo;
79 rtl::Reference< TableModel > mxTable;
80 AccessibleCellMap maChildMap;
81 rtl::Reference< AccessibleTableShape> mxAccessible;
82 sal_Int32 mRowCount, mColCount;
83 //get the cached AccessibleCell from XCell
84 rtl::Reference< AccessibleCell > getAccessibleCell (const rtl::Reference< Cell >& xCell);
85 /// @throws IndexOutOfBoundsException
86 /// @throws RuntimeException
87 rtl::Reference< AccessibleCell > getAccessibleCell (sal_Int32 nRow, sal_Int32 nColumn);
91 AccessibleTableShapeImpl::AccessibleTableShapeImpl( AccessibleShapeTreeInfo& rShapeTreeInfo )
92 : mrShapeTreeInfo( rShapeTreeInfo )
93 , mRowCount(0)
94 , mColCount(0)
99 void AccessibleTableShapeImpl::init( const rtl::Reference<AccessibleTableShape>& xAccessible, const rtl::Reference< TableModel >& xTable )
101 mxAccessible = xAccessible;
102 mxTable = xTable;
104 if( mxTable.is() )
106 Reference< XModifyListener > xListener( this );
107 mxTable->addModifyListener( xListener );
108 mRowCount = mxTable->getRowCount();
109 mColCount = mxTable->getColumnCount();
114 void AccessibleTableShapeImpl::dispose()
116 if( mxTable.is() )
118 //remove all the cell's acc object in table's dispose.
119 for( auto& rEntry : maChildMap )
121 rEntry.second->dispose();
123 maChildMap.clear();
124 Reference< XModifyListener > xListener( this );
125 mxTable->removeModifyListener( xListener );
126 mxTable.clear();
128 mxAccessible.clear();
132 //get the cached AccessibleCell from XCell
133 rtl::Reference< AccessibleCell > AccessibleTableShapeImpl::getAccessibleCell (const rtl::Reference< Cell >& xCell)
135 AccessibleCellMap::iterator iter( maChildMap.find( xCell ) );
137 if( iter != maChildMap.end() )
139 rtl::Reference< AccessibleCell > xChild( (*iter).second );
140 return xChild;
142 return rtl::Reference< AccessibleCell >();
145 rtl::Reference< AccessibleCell > AccessibleTableShapeImpl::getAccessibleCell (sal_Int32 nRow, sal_Int32 nColumn)
147 rtl::Reference< Cell > xCell( mxTable->getCell( nColumn, nRow ) );
148 rtl::Reference< AccessibleCell > xChild = getAccessibleCell( xCell );
150 if( !xChild.is() && mxTable.is() )
152 sal_Int32 nChildIndex = mxTable->getColumnCount() * nRow + nColumn;
154 rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCell, nChildIndex, mrShapeTreeInfo ) );
156 xAccessibleCell->Init();
157 maChildMap[xCell] = xAccessibleCell;
159 xChild = std::move(xAccessibleCell);
161 return xChild;
165 Reference< XAccessible > AccessibleTableShapeImpl::getAccessibleChild(sal_Int64 nChildIndex)
167 sal_Int32 nColumn = 0, nRow = 0;
168 getColumnAndRow( nChildIndex, nColumn, nRow );
170 rtl::Reference< Cell > xCell( mxTable->getCell( nColumn, nRow ) );
171 AccessibleCellMap::iterator iter( maChildMap.find( xCell ) );
173 if( iter != maChildMap.end() )
175 Reference< XAccessible > xChild( (*iter).second );
176 return xChild;
178 else
180 rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCell, nChildIndex, mrShapeTreeInfo ) );
182 xAccessibleCell->Init();
183 maChildMap[xCell] = xAccessibleCell;
185 return xAccessibleCell;
190 void AccessibleTableShapeImpl::getColumnAndRow( sal_Int64 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow )
192 if( mxTable.is() )
194 const sal_Int32 nColumnCount = mxTable->getColumnCount();
195 if (nColumnCount == 0)
196 throw IndexOutOfBoundsException();
198 rnColumn = nChildIndex % nColumnCount;
199 rnRow = nChildIndex / nColumnCount;
201 if( rnRow < mxTable->getRowCount() )
202 return;
205 throw IndexOutOfBoundsException();
208 // XModifyListener
209 void SAL_CALL AccessibleTableShapeImpl::modified( const EventObject& /*aEvent*/ )
211 if( !mxTable.is() )
212 return;
216 // structural changes may have happened to the table, validate all accessible cell instances
217 AccessibleCellMap aTempChildMap;
218 aTempChildMap.swap( maChildMap );
220 // first move all still existing cells to maChildMap again and update their index
222 const sal_Int32 nRowCount = mxTable->getRowCount();
223 const sal_Int32 nColCount = mxTable->getColumnCount();
225 bool bRowOrColumnChanged = false;
226 if (mRowCount != nRowCount || mColCount != nColCount )
228 bRowOrColumnChanged = true;
229 mRowCount = nRowCount;
230 mColCount = nColCount;
232 sal_Int32 nChildIndex = 0;
234 for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
236 for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
238 rtl::Reference< Cell > xCell( mxTable->getCell( nCol, nRow ) );
239 AccessibleCellMap::iterator iter( aTempChildMap.find( xCell ) );
241 if( iter != aTempChildMap.end() )
243 rtl::Reference< AccessibleCell > xAccessibleCell( (*iter).second );
244 xAccessibleCell->setIndexInParent( nChildIndex );
245 xAccessibleCell->UpdateChildren();
246 // If row or column count is changed, there is split or merge, so all cell's acc name should be updated
247 if (bRowOrColumnChanged)
249 xAccessibleCell->SetAccessibleName(xAccessibleCell->getAccessibleName(), AccessibleContextBase::ManuallySet);
251 // For merged cell, add invisible & disabled state.
252 rtl::Reference< Cell > xMergedCell( mxTable->getCell( nCol, nRow ) );
253 if (xMergedCell.is() && xMergedCell->isMerged())
255 xAccessibleCell->ResetState(AccessibleStateType::VISIBLE);
256 xAccessibleCell->ResetState(AccessibleStateType::ENABLED);
257 // IA2 CWS. MT: OFFSCREEN == !SHOWING, should stay consistent
258 // xAccessibleCell->SetState(AccessibleStateType::OFFSCREEN);
259 xAccessibleCell->ResetState(AccessibleStateType::SHOWING);
261 else
263 xAccessibleCell->SetState(AccessibleStateType::VISIBLE);
264 xAccessibleCell->SetState(AccessibleStateType::ENABLED);
265 // IA2 CWS. MT: OFFSCREEN == !SHOWING, should stay consistent
266 // xAccessibleCell->ResetState(AccessibleStateType::OFFSCREEN);
267 xAccessibleCell->SetState(AccessibleStateType::SHOWING);
270 // move still existing cell from temporary child map to our child map
271 maChildMap[xCell] = std::move(xAccessibleCell);
272 aTempChildMap.erase( iter );
274 else
276 rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCell, nChildIndex, mrShapeTreeInfo ) );
278 xAccessibleCell->Init();
279 maChildMap[xCell] = std::move(xAccessibleCell);
282 ++nChildIndex;
286 // all accessible cell instances still left in aTempChildMap must be disposed
287 // as they are no longer part of the table
289 for( auto& rEntry : aTempChildMap )
291 rEntry.second->dispose();
293 //notify bridge to update the acc cache.
294 if (mxAccessible)
295 mxAccessible->CommitChange(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any(), -1);
297 catch( const Exception& )
299 TOOLS_WARN_EXCEPTION("svx.table", "");
303 // XEventListener
304 void SAL_CALL AccessibleTableShapeImpl::disposing( const EventObject& /*Source*/ )
308 AccessibleTableShape::AccessibleTableShape( const AccessibleShapeInfo& rShapeInfo, const AccessibleShapeTreeInfo& rShapeTreeInfo)
309 : AccessibleTableShape_Base(rShapeInfo, rShapeTreeInfo)
310 , mnPreviousSelectionCount(0)
311 , mxImpl( new AccessibleTableShapeImpl( maShapeTreeInfo ) )
316 AccessibleTableShape::~AccessibleTableShape()
321 void AccessibleTableShape::Init()
325 Reference< XPropertySet > xSet( mxShape, UNO_QUERY_THROW );
326 Reference< XTable > xTable( xSet->getPropertyValue(u"Model"_ustr), UNO_QUERY_THROW );
328 TableModel* pModel = dynamic_cast<TableModel*>(xTable.get());
329 assert(pModel);
330 mxImpl->init( this, pModel );
332 catch( Exception& )
334 TOOLS_WARN_EXCEPTION("svx.table", "");
337 AccessibleTableShape_Base::Init();
341 SvxTableController* AccessibleTableShape::getTableController()
343 SdrView* pView = maShapeTreeInfo.GetSdrView ();
344 if( pView )
345 return dynamic_cast< SvxTableController* >( pView->getSelectionController().get() );
346 else
347 return nullptr;
351 // XInterface
354 Any SAL_CALL AccessibleTableShape::queryInterface( const Type& aType )
356 if ( aType == cppu::UnoType<XAccessibleTableSelection>::get())
358 Reference<XAccessibleTableSelection> xThis( this );
359 Any aRet;
360 aRet <<= xThis;
361 return aRet;
363 else
364 return AccessibleTableShape_Base::queryInterface( aType );
368 void SAL_CALL AccessibleTableShape::acquire( ) noexcept
370 AccessibleTableShape_Base::acquire();
374 void SAL_CALL AccessibleTableShape::release( ) noexcept
376 AccessibleTableShape_Base::release();
380 // XAccessible
383 OUString SAL_CALL AccessibleTableShape::getImplementationName()
385 return u"com.sun.star.comp.accessibility.AccessibleTableShape"_ustr;
389 OUString AccessibleTableShape::CreateAccessibleBaseName()
391 return u"TableShape"_ustr;
395 sal_Int64 SAL_CALL AccessibleTableShape::getAccessibleChildCount( )
397 SolarMutexGuard aSolarGuard;
398 return mxImpl->mxTable.is() ? static_cast<sal_Int64>(mxImpl->mxTable->getRowCount()) * static_cast<sal_Int64>(mxImpl->mxTable->getColumnCount()) : 0;
402 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleChild( sal_Int64 i )
404 SolarMutexGuard aSolarGuard;
405 ThrowIfDisposed();
407 return mxImpl->getAccessibleChild( i );
411 sal_Int16 SAL_CALL AccessibleTableShape::getAccessibleRole()
413 return AccessibleRole::TABLE;
417 void SAL_CALL AccessibleTableShape::disposing()
419 mxImpl->dispose();
421 // let the base do its stuff
422 AccessibleShape::disposing();
426 // XAccessibleTable
429 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRowCount()
431 SolarMutexGuard aSolarGuard;
432 return mxImpl->mxTable.is() ? mxImpl->mxTable->getRowCount() : 0;
436 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumnCount( )
438 SolarMutexGuard aSolarGuard;
439 return mxImpl->mxTable.is() ? mxImpl->mxTable->getColumnCount() : 0;
443 OUString SAL_CALL AccessibleTableShape::getAccessibleRowDescription( sal_Int32 nRow )
445 checkCellPosition( 0, nRow );
446 return OUString();
450 OUString SAL_CALL AccessibleTableShape::getAccessibleColumnDescription( sal_Int32 nColumn )
452 SolarMutexGuard aSolarGuard;
453 checkCellPosition( nColumn, 0 );
454 return OUString();
458 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
460 SolarMutexGuard aSolarGuard;
461 checkCellPosition( nColumn, nRow );
462 if( mxImpl->mxTable.is() )
464 rtl::Reference< Cell > xCell( mxImpl->mxTable->getCell( nColumn, nRow ) );
465 if( xCell.is() )
466 return xCell->getRowSpan();
468 return 1;
472 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
474 SolarMutexGuard aSolarGuard;
475 checkCellPosition( nColumn, nRow );
476 if( mxImpl->mxTable.is() )
478 rtl::Reference< Cell > xCell( mxImpl->mxTable->getCell( nColumn, nRow ) );
479 if( xCell.is() )
480 return xCell->getColumnSpan();
482 return 1;
486 Reference< XAccessibleTable > SAL_CALL AccessibleTableShape::getAccessibleRowHeaders( )
488 Reference< XAccessibleTable > xRet;
489 SvxTableController* pController = getTableController();
490 if( pController )
492 if( pController->isRowHeader() )
494 xRet = new AccessibleTableHeaderShape( this, true );
497 return xRet;
501 Reference< XAccessibleTable > SAL_CALL AccessibleTableShape::getAccessibleColumnHeaders( )
503 Reference< XAccessibleTable > xRet;
504 SvxTableController* pController = getTableController();
505 if( pController )
507 if( pController->isColumnHeader() )
509 xRet = new AccessibleTableHeaderShape( this, false );
512 return xRet;
516 Sequence< sal_Int32 > SAL_CALL AccessibleTableShape::getSelectedAccessibleRows( )
518 sal_Int32 nRow = getAccessibleRowCount();
519 ::std::vector<bool> aSelected( nRow, true );
520 sal_Int32 nCount = nRow;
521 for( sal_Int32 i = 0; i < nRow; i++ )
525 aSelected[i] = isAccessibleRowSelected( i );
527 catch( ... )
529 return Sequence< sal_Int32 >();
532 if( !aSelected[i] )
533 nCount--;
535 Sequence < sal_Int32 > aRet( nCount );
536 sal_Int32 *pRet = aRet.getArray();
537 sal_Int32 nPos = 0;
538 size_t nSize = aSelected.size();
539 for( size_t i=0; i < nSize && nPos < nCount; i++ )
541 if( aSelected[i] )
543 *pRet++ = i;
544 nPos++;
548 return aRet;
552 Sequence< sal_Int32 > SAL_CALL AccessibleTableShape::getSelectedAccessibleColumns( )
554 sal_Int32 nColumn = getAccessibleColumnCount();
555 ::std::vector<bool> aSelected( nColumn, true );
556 sal_Int32 nCount = nColumn;
557 for( sal_Int32 i = 0; i < nColumn; i++ )
561 aSelected[i] = isAccessibleColumnSelected( i );
563 catch( ... )
565 return Sequence< sal_Int32 >();
568 if( !aSelected[i] )
569 nCount--;
571 Sequence < sal_Int32 > aRet( nCount );
572 sal_Int32 *pRet = aRet.getArray();
573 sal_Int32 nPos = 0;
574 size_t nSize = aSelected.size();
575 for( size_t i=0; i < nSize && nPos < nCount; i++ )
577 if( aSelected[i] )
579 *pRet++ = i;
580 nPos++;
584 return aRet;
588 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleRowSelected( sal_Int32 nRow )
590 SolarMutexGuard aSolarGuard;
591 checkCellPosition( 0, nRow );
592 SvxTableController* pController = getTableController();
593 if( pController )
595 return pController->isRowSelected( nRow );
597 return false;
601 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleColumnSelected( sal_Int32 nColumn )
603 SolarMutexGuard aSolarGuard;
604 checkCellPosition( nColumn, 0 );
605 SvxTableController* pController = getTableController();
606 if( pController )
608 return pController->isColumnSelected( nColumn );
610 return false;
614 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
616 SolarMutexGuard aSolarGuard;
617 checkCellPosition( nColumn, nRow );
619 sal_Int32 nChildIndex = 0;
620 if( mxImpl->mxTable.is() )
621 nChildIndex = mxImpl->mxTable->getColumnCount() * nRow + nColumn;
623 return getAccessibleChild( nChildIndex );
627 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleCaption( )
629 Reference< XAccessible > xRet;
630 return xRet;
634 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleSummary( )
636 Reference< XAccessible > xRet;
637 return xRet;
641 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn )
643 SolarMutexGuard aSolarGuard;
644 checkCellPosition( nColumn, nRow );
646 SvxTableController* pController = getTableController();
647 if( pController && pController->hasSelectedCells() )
649 CellPos aFirstPos, aLastPos;
650 pController->getSelectedCells( aFirstPos, aLastPos );
651 if( (aFirstPos.mnRow <= nRow) && (aFirstPos.mnCol <= nColumn) && (nRow <= aLastPos.mnRow) && (nColumn <= aLastPos.mnCol) )
652 return true;
655 return false;
659 sal_Int64 SAL_CALL AccessibleTableShape::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn )
661 SolarMutexGuard aSolarGuard;
662 checkCellPosition( nColumn, nRow );
663 return mxImpl->mxTable.is() ? (static_cast<sal_Int64>(nRow) * static_cast<sal_Int64>(mxImpl->mxTable->getColumnCount()) + nColumn) : 0;
667 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRow( sal_Int64 nChildIndex )
669 SolarMutexGuard aSolarGuard;
670 sal_Int32 nColumn = 0, nRow = 0;
671 mxImpl->getColumnAndRow( nChildIndex, nColumn, nRow );
672 return nRow;
676 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumn( sal_Int64 nChildIndex )
678 SolarMutexGuard aSolarGuard;
679 sal_Int32 nColumn = 0, nRow = 0;
680 mxImpl->getColumnAndRow( nChildIndex, nColumn, nRow );
681 return nColumn;
685 // XAccessibleSelection
688 void SAL_CALL AccessibleTableShape::selectAccessibleChild( sal_Int64 nChildIndex )
690 SolarMutexGuard aSolarGuard;
691 CellPos aPos;
692 mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
694 // todo, select table shape?!?
695 SvxTableController* pController = getTableController();
696 if( !pController )
697 return;
699 CellPos aFirstPos( aPos ), aLastPos( aPos );
700 if( pController->hasSelectedCells() )
702 pController->getSelectedCells( aFirstPos, aLastPos );
704 aFirstPos.mnRow = std::min( aFirstPos.mnRow, aPos.mnRow );
705 aFirstPos.mnCol = std::min( aFirstPos.mnCol, aPos.mnCol );
706 aLastPos.mnRow = std::max( aLastPos.mnRow, aPos.mnRow );
707 aLastPos.mnCol = std::max( aLastPos.mnCol, aPos.mnCol );
709 pController->setSelectedCells( aFirstPos, aLastPos );
713 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleChildSelected( sal_Int64 nChildIndex )
715 SolarMutexGuard aSolarGuard;
717 if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
718 throw IndexOutOfBoundsException();
720 CellPos aPos;
721 mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
723 return isAccessibleSelected(aPos.mnRow, aPos.mnCol);
727 void SAL_CALL AccessibleTableShape::clearAccessibleSelection()
729 SolarMutexGuard aSolarGuard;
731 SvxTableController* pController = getTableController();
732 if( pController )
733 pController->clearSelection();
737 void SAL_CALL AccessibleTableShape::selectAllAccessibleChildren()
739 SolarMutexGuard aSolarGuard;
741 // todo: force selection of shape?
742 SvxTableController* pController = getTableController();
743 if( pController )
744 pController->selectAll();
748 sal_Int64 SAL_CALL AccessibleTableShape::getSelectedAccessibleChildCount()
750 SolarMutexGuard aSolarGuard;
752 SvxTableController* pController = getTableController();
753 if( pController && pController->hasSelectedCells() )
755 CellPos aFirstPos, aLastPos;
756 pController->getSelectedCells( aFirstPos, aLastPos );
758 const sal_Int32 nSelectedColumns = std::max( sal_Int32(0), aLastPos.mnCol - aFirstPos.mnCol ) + 1;
759 const sal_Int32 nSelectedRows = std::max( sal_Int32(0), aLastPos.mnRow - aFirstPos.mnRow ) + 1;
760 return static_cast<sal_Int64>(nSelectedRows) * static_cast<sal_Int64>(nSelectedColumns);
763 return 0;
767 Reference< XAccessible > SAL_CALL AccessibleTableShape::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex )
769 SolarMutexGuard aSolarGuard;
771 if( nSelectedChildIndex < 0 )
772 throw IndexOutOfBoundsException();
774 sal_Int64 nChildIndex = GetIndexOfSelectedChild( nSelectedChildIndex );
776 if( nChildIndex < 0 )
777 throw IndexOutOfBoundsException();
779 if ( nChildIndex >= getAccessibleChildCount() )
781 throw IndexOutOfBoundsException();
784 return getAccessibleChild( nChildIndex );
788 void SAL_CALL AccessibleTableShape::deselectAccessibleChild( sal_Int64 nChildIndex )
790 SolarMutexGuard aSolarGuard;
791 CellPos aPos;
792 mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
794 // todo, select table shape?!?
795 SvxTableController* pController = getTableController();
796 if( !(pController && pController->hasSelectedCells()) )
797 return;
799 CellPos aFirstPos, aLastPos;
800 pController->getSelectedCells( aFirstPos, aLastPos );
802 // create a selection where aPos is not part of anymore
803 aFirstPos.mnRow = std::min( aFirstPos.mnRow, aPos.mnRow+1 );
804 aFirstPos.mnCol = std::min( aFirstPos.mnCol, aPos.mnCol+1 );
805 aLastPos.mnRow = std::max( aLastPos.mnRow, aPos.mnRow-1 );
806 aLastPos.mnCol = std::max( aLastPos.mnCol, aPos.mnCol-1 );
808 // new selection may be invalid (child to deselect is not at a border of the selection but in between)
809 if( (aFirstPos.mnRow > aLastPos.mnRow) || (aFirstPos.mnCol > aLastPos.mnCol) )
810 pController->clearSelection(); // if selection is invalid, clear all
811 else
812 pController->setSelectedCells( aFirstPos, aLastPos );
815 // XAccessibleTableSelection
816 sal_Bool SAL_CALL AccessibleTableShape::selectRow( sal_Int32 row )
818 SolarMutexGuard aSolarGuard;
819 SvxTableController* pController = getTableController();
820 if( !pController )
821 return false;
822 return pController->selectRow( row );
825 sal_Bool SAL_CALL AccessibleTableShape::selectColumn( sal_Int32 column )
827 SolarMutexGuard aSolarGuard;
828 SvxTableController* pController = getTableController();
829 if( !pController )
830 return false;
831 return pController->selectColumn( column );
834 sal_Bool SAL_CALL AccessibleTableShape::unselectRow( sal_Int32 row )
836 SolarMutexGuard aSolarGuard;
837 SvxTableController* pController = getTableController();
838 if( !pController )
839 return false;
840 return pController->deselectRow( row );
843 sal_Bool SAL_CALL AccessibleTableShape::unselectColumn( sal_Int32 column )
845 SolarMutexGuard aSolarGuard;
846 SvxTableController* pController = getTableController();
847 if( !pController )
848 return false;
849 return pController->deselectColumn( column );
852 sal_Int64 AccessibleTableShape::GetIndexOfSelectedChild(
853 sal_Int64 nSelectedChildIndex ) const
855 sal_Int64 nChildren = const_cast<AccessibleTableShape*>(this)->getAccessibleChildCount();
857 if( nSelectedChildIndex >= nChildren )
858 return -1;
860 sal_Int64 n = 0;
861 while( n < nChildren )
863 if( const_cast<AccessibleTableShape*>(this)->isAccessibleChildSelected( n ) )
865 if( 0 == nSelectedChildIndex )
866 break;
867 else
868 --nSelectedChildIndex;
870 ++n;
873 return n < nChildren ? n : -1;
875 void AccessibleTableShape::getColumnAndRow( sal_Int64 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow )
877 mxImpl->getColumnAndRow(nChildIndex, rnColumn, rnRow);
880 // XSelectionChangeListener
881 void SAL_CALL
882 AccessibleTableShape::disposing (const EventObject& aEvent)
884 AccessibleShape::disposing(aEvent);
886 void SAL_CALL AccessibleTableShape::selectionChanged (const EventObject& rEvent)
888 //sdr::table::CellRef xCellRef = static_cast< sdr::table::CellRef > (rEvent.Source);
889 rtl::Reference< Cell > xCell = dynamic_cast<Cell*>(rEvent.Source.get());
890 if (!xCell.is())
891 return;
893 rtl::Reference< AccessibleCell > xAccCell = mxImpl->getAccessibleCell( xCell );
894 if (!xAccCell.is())
895 return;
897 sal_Int64 nIndex = xAccCell->getAccessibleIndexInParent(),
898 nCount = getSelectedAccessibleChildCount();
899 bool bSelected = isAccessibleChildSelected(nIndex);
900 if (mnPreviousSelectionCount == 0 && nCount > 0 && bSelected)
902 xAccCell->SetState(AccessibleStateType::SELECTED);
903 xAccCell->CommitChange(AccessibleEventId::SELECTION_CHANGED, Any(), Any(), -1);
905 else if (bSelected)
907 xAccCell->SetState(AccessibleStateType::SELECTED);
908 xAccCell->CommitChange(AccessibleEventId::SELECTION_CHANGED_ADD, Any(), Any(), -1);
910 else
912 xAccCell->ResetState(AccessibleStateType::SELECTED);
913 xAccCell->CommitChange(AccessibleEventId::SELECTION_CHANGED_REMOVE, Any(), Any(), -1);
915 mnPreviousSelectionCount = nCount;
917 // Get the currently active cell which is text editing
918 AccessibleCell* AccessibleTableShape::GetActiveAccessibleCell()
920 rtl::Reference< AccessibleCell > xAccCell;
921 AccessibleCell* pAccCell = nullptr;
922 SvxTableController* pController = getTableController();
923 if (pController)
925 sdr::table::SdrTableObj* pTableObj = pController->GetTableObj();
926 if ( pTableObj )
928 const sdr::table::CellRef& xCellRef (pTableObj->getActiveCell());
929 if ( xCellRef.is() )
933 CellPos rPos;
934 pTableObj->getActiveCellPos( rPos );
935 xAccCell = mxImpl->getAccessibleCell( rPos.mnRow, rPos.mnCol );
936 if ( xAccCell.is() )
937 pAccCell = xAccCell.get();
939 catch ( IndexOutOfBoundsException& ) {}
943 return pAccCell;
946 //If current active cell is in editing, the focus state should be set to internal text
947 bool AccessibleTableShape::SetState (sal_Int64 aState)
949 if( aState == AccessibleStateType::FOCUSED )
951 AccessibleCell* pActiveAccessibleCell = GetActiveAccessibleCell();
952 if( pActiveAccessibleCell != nullptr )
953 return pActiveAccessibleCell->SetState(aState);
956 return AccessibleShape::SetState (aState);
959 //If current active cell is in editing, the focus state should be reset to internal text
960 bool AccessibleTableShape::ResetState (sal_Int64 aState)
962 if( aState == AccessibleStateType::FOCUSED )
964 AccessibleCell* pActiveAccessibleCell = GetActiveAccessibleCell();
965 if( pActiveAccessibleCell != nullptr )
966 return pActiveAccessibleCell->ResetState(aState);
969 return AccessibleShape::ResetState (aState);
972 bool AccessibleTableShape::SetStateDirectly (sal_Int64 aState)
974 return AccessibleContextBase::SetState (aState);
977 bool AccessibleTableShape::ResetStateDirectly (sal_Int64 aState)
979 return AccessibleContextBase::ResetState (aState);
982 void AccessibleTableShape::checkCellPosition( sal_Int32 nCol, sal_Int32 nRow )
984 if( (nCol >= 0) && (nRow >= 0) && mxImpl->mxTable.is() && (nCol < mxImpl->mxTable->getColumnCount()) && (nRow < mxImpl->mxTable->getRowCount()) )
985 return;
987 throw IndexOutOfBoundsException();
990 AccessibleTableHeaderShape::AccessibleTableHeaderShape( AccessibleTableShape* pTable, bool bRow )
992 mpTable = pTable;
993 mbRow = bRow;
996 AccessibleTableHeaderShape::~AccessibleTableHeaderShape()
998 mpTable = nullptr;
1001 // XAccessible
1002 Reference< XAccessibleContext > SAL_CALL AccessibleTableHeaderShape::getAccessibleContext()
1004 return this;
1007 // XAccessibleContext
1008 sal_Int64 SAL_CALL AccessibleTableHeaderShape::getAccessibleChildCount( )
1010 return static_cast<sal_Int64>(getAccessibleRowCount()) * static_cast<sal_Int64>(getAccessibleColumnCount());
1013 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleChild( sal_Int64 i )
1015 return mpTable->getAccessibleChild( i );
1018 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleParent()
1020 Reference< XAccessible > XParent;
1021 return XParent;
1024 sal_Int64 SAL_CALL AccessibleTableHeaderShape::getAccessibleIndexInParent()
1026 return -1;
1029 sal_Int16 SAL_CALL AccessibleTableHeaderShape::getAccessibleRole()
1031 return mpTable->getAccessibleRole();
1034 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleDescription()
1036 return mpTable->getAccessibleDescription();
1039 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleName()
1041 return mpTable->getAccessibleName();
1044 sal_Int64 SAL_CALL AccessibleTableHeaderShape::getAccessibleStateSet()
1046 return mpTable->getAccessibleStateSet();
1049 Reference< XAccessibleRelationSet > SAL_CALL AccessibleTableHeaderShape::getAccessibleRelationSet()
1051 return mpTable->getAccessibleRelationSet();
1054 Locale SAL_CALL AccessibleTableHeaderShape::getLocale()
1056 return mpTable->getLocale();
1059 //XAccessibleComponent
1060 sal_Bool SAL_CALL AccessibleTableHeaderShape::containsPoint ( const css::awt::Point& aPoint )
1062 return mpTable->containsPoint( aPoint );
1065 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleAtPoint ( const css::awt::Point& aPoint)
1067 return mpTable->getAccessibleAtPoint( aPoint );
1070 css::awt::Rectangle SAL_CALL AccessibleTableHeaderShape::getBounds()
1072 return mpTable->getBounds();
1075 css::awt::Point SAL_CALL AccessibleTableHeaderShape::getLocation()
1077 return mpTable->getLocation();
1080 css::awt::Point SAL_CALL AccessibleTableHeaderShape::getLocationOnScreen()
1082 return mpTable->getLocationOnScreen();
1085 css::awt::Size SAL_CALL AccessibleTableHeaderShape::getSize()
1087 return mpTable->getSize();
1090 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getForeground()
1092 return mpTable->getForeground();
1095 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getBackground()
1097 return mpTable->getBackground();
1100 void SAL_CALL AccessibleTableHeaderShape::grabFocus()
1102 mpTable->grabFocus();
1104 // XAccessibleTable
1105 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleRowCount()
1107 return mbRow ? 1 : mpTable->getAccessibleRowCount();
1110 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnCount()
1112 return !mbRow ? 1 : mpTable->getAccessibleColumnCount();
1115 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleRowDescription( sal_Int32 nRow )
1117 return mpTable->getAccessibleRowDescription( nRow );
1120 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnDescription( sal_Int32 nColumn )
1122 return mpTable->getAccessibleColumnDescription( nColumn );
1125 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
1127 return mpTable->getAccessibleRowExtentAt( nRow, nColumn );
1130 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
1132 return mpTable->getAccessibleColumnExtentAt( nRow, nColumn );
1135 Reference< XAccessibleTable > SAL_CALL AccessibleTableHeaderShape::getAccessibleRowHeaders( )
1137 Reference< XAccessibleTable > xRet;
1138 return xRet;
1141 Reference< XAccessibleTable > SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnHeaders( )
1143 Reference< XAccessibleTable > xRet;
1144 return xRet;
1147 Sequence< sal_Int32 > SAL_CALL AccessibleTableHeaderShape::getSelectedAccessibleRows( )
1149 sal_Int32 nRow = getAccessibleRowCount();
1150 ::std::vector<bool> aSelected( nRow, true );
1151 sal_Int32 nCount = nRow;
1152 for( sal_Int32 i = 0; i < nRow; i++ )
1156 aSelected[i] = isAccessibleRowSelected( i );
1158 catch( ... )
1160 return Sequence< sal_Int32 >();
1163 if( !aSelected[i] )
1164 nCount--;
1166 Sequence < sal_Int32 > aRet( nCount );
1167 sal_Int32 *pRet = aRet.getArray();
1168 sal_Int32 nPos = 0;
1169 size_t nSize = aSelected.size();
1170 for( size_t i=0; i < nSize && nPos < nCount; i++ )
1172 if( aSelected[i] )
1174 *pRet++ = i;
1175 nPos++;
1179 return aRet;
1182 Sequence< sal_Int32 > SAL_CALL AccessibleTableHeaderShape::getSelectedAccessibleColumns( )
1184 sal_Int32 nColumn = getAccessibleColumnCount();
1185 ::std::vector<bool> aSelected( nColumn, true );
1186 sal_Int32 nCount = nColumn;
1187 for( sal_Int32 i = 0; i < nColumn; i++ )
1191 aSelected[i] = isAccessibleColumnSelected( i );
1193 catch( ... )
1195 return Sequence< sal_Int32 >();
1198 if( !aSelected[i] )
1199 nCount--;
1201 Sequence < sal_Int32 > aRet( nCount );
1202 sal_Int32 *pRet = aRet.getArray();
1203 sal_Int32 nPos = 0;
1204 size_t nSize = aSelected.size();
1205 for( size_t i=0; i < nSize && nPos < nCount; i++ )
1207 if( aSelected[i] )
1209 *pRet++ = i;
1210 nPos++;
1214 return aRet;
1217 sal_Bool SAL_CALL AccessibleTableHeaderShape::isAccessibleRowSelected( sal_Int32 nRow )
1219 return mpTable->isAccessibleRowSelected( nRow );
1222 sal_Bool SAL_CALL AccessibleTableHeaderShape::isAccessibleColumnSelected( sal_Int32 nColumn )
1224 return mpTable->isAccessibleColumnSelected( nColumn );
1227 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
1229 return mpTable->getAccessibleCellAt( nRow, nColumn );
1232 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleCaption( )
1234 return mpTable->getAccessibleCaption();
1237 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleSummary( )
1239 return mpTable->getAccessibleSummary();
1242 sal_Bool SAL_CALL AccessibleTableHeaderShape::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn )
1244 return mpTable->isAccessibleSelected( nRow, nColumn );
1247 sal_Int64 SAL_CALL AccessibleTableHeaderShape::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn )
1249 return mpTable->getAccessibleIndex( nRow, nColumn );
1252 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleRow( sal_Int64 nChildIndex )
1254 return mpTable->getAccessibleRow( nChildIndex );
1257 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleColumn( sal_Int64 nChildIndex )
1259 return mpTable->getAccessibleColumn( nChildIndex );
1262 // XAccessibleTableSelection
1263 sal_Bool SAL_CALL AccessibleTableHeaderShape::selectRow( sal_Int32 row )
1265 if( mbRow )
1266 return mpTable->selectRow( row );
1267 else
1269 mpTable->clearAccessibleSelection();
1270 sal_Int64 nIndex = mpTable->getAccessibleIndex( row, 0 );
1271 mpTable->selectAccessibleChild( nIndex );
1272 return true;
1276 sal_Bool SAL_CALL AccessibleTableHeaderShape::selectColumn( sal_Int32 column )
1278 if( !mbRow )
1279 return mpTable->selectColumn( column );
1280 else
1282 mpTable->clearAccessibleSelection();
1283 sal_Int64 nIndex = mpTable->getAccessibleIndex( 0, column );
1284 mpTable->selectAccessibleChild( nIndex );
1285 return true;
1289 sal_Bool SAL_CALL AccessibleTableHeaderShape::unselectRow( sal_Int32 row )
1291 if( mbRow )
1292 return mpTable->unselectRow( row );
1293 else
1295 sal_Int64 nIndex = mpTable->getAccessibleIndex( row, 0 );
1296 mpTable->deselectAccessibleChild( nIndex );
1297 return true;
1301 sal_Bool SAL_CALL AccessibleTableHeaderShape::unselectColumn( sal_Int32 column )
1303 if( !mbRow )
1304 return mpTable->unselectColumn( column );
1305 else
1307 sal_Int64 nIndex = mpTable->getAccessibleIndex( 0, column );
1308 mpTable->deselectAccessibleChild( nIndex );
1309 return true;
1314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */