1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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
>
61 explicit AccessibleTableShapeImpl( AccessibleShapeTreeInfo
& rShapeTreeInfo
);
63 void init( const rtl::Reference
< AccessibleTableShape
>& xAccessible
, const rtl::Reference
< TableModel
>& xTable
);
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
);
73 virtual void SAL_CALL
modified( const EventObject
& aEvent
) override
;
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
)
99 void AccessibleTableShapeImpl::init( const rtl::Reference
<AccessibleTableShape
>& xAccessible
, const rtl::Reference
< TableModel
>& xTable
)
101 mxAccessible
= xAccessible
;
106 Reference
< XModifyListener
> xListener( this );
107 mxTable
->addModifyListener( xListener
);
108 mRowCount
= mxTable
->getRowCount();
109 mColCount
= mxTable
->getColumnCount();
114 void AccessibleTableShapeImpl::dispose()
118 //remove all the cell's acc object in table's dispose.
119 for( auto& rEntry
: maChildMap
)
121 rEntry
.second
->dispose();
124 Reference
< XModifyListener
> xListener( this );
125 mxTable
->removeModifyListener( xListener
);
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
);
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
);
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
);
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
)
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() )
205 throw IndexOutOfBoundsException();
209 void SAL_CALL
AccessibleTableShapeImpl::modified( const EventObject
& /*aEvent*/ )
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
);
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
);
276 rtl::Reference
< AccessibleCell
> xAccessibleCell( new AccessibleCell( mxAccessible
, xCell
, nChildIndex
, mrShapeTreeInfo
) );
278 xAccessibleCell
->Init();
279 maChildMap
[xCell
] = std::move(xAccessibleCell
);
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.
295 mxAccessible
->CommitChange(AccessibleEventId::INVALIDATE_ALL_CHILDREN
, Any(), Any(), -1);
297 catch( const Exception
& )
299 TOOLS_WARN_EXCEPTION("svx.table", "");
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());
330 mxImpl
->init( this, pModel
);
334 TOOLS_WARN_EXCEPTION("svx.table", "");
337 AccessibleTableShape_Base::Init();
341 SvxTableController
* AccessibleTableShape::getTableController()
343 SdrView
* pView
= maShapeTreeInfo
.GetSdrView ();
345 return dynamic_cast< SvxTableController
* >( pView
->getSelectionController().get() );
354 Any SAL_CALL
AccessibleTableShape::queryInterface( const Type
& aType
)
356 if ( aType
== cppu::UnoType
<XAccessibleTableSelection
>::get())
358 Reference
<XAccessibleTableSelection
> xThis( this );
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();
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
;
407 return mxImpl
->getAccessibleChild( i
);
411 sal_Int16 SAL_CALL
AccessibleTableShape::getAccessibleRole()
413 return AccessibleRole::TABLE
;
417 void SAL_CALL
AccessibleTableShape::disposing()
421 // let the base do its stuff
422 AccessibleShape::disposing();
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
);
450 OUString SAL_CALL
AccessibleTableShape::getAccessibleColumnDescription( sal_Int32 nColumn
)
452 SolarMutexGuard aSolarGuard
;
453 checkCellPosition( nColumn
, 0 );
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
) );
466 return xCell
->getRowSpan();
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
) );
480 return xCell
->getColumnSpan();
486 Reference
< XAccessibleTable
> SAL_CALL
AccessibleTableShape::getAccessibleRowHeaders( )
488 Reference
< XAccessibleTable
> xRet
;
489 SvxTableController
* pController
= getTableController();
492 if( pController
->isRowHeader() )
494 xRet
= new AccessibleTableHeaderShape( this, true );
501 Reference
< XAccessibleTable
> SAL_CALL
AccessibleTableShape::getAccessibleColumnHeaders( )
503 Reference
< XAccessibleTable
> xRet
;
504 SvxTableController
* pController
= getTableController();
507 if( pController
->isColumnHeader() )
509 xRet
= new AccessibleTableHeaderShape( this, false );
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
);
529 return Sequence
< sal_Int32
>();
535 Sequence
< sal_Int32
> aRet( nCount
);
536 sal_Int32
*pRet
= aRet
.getArray();
538 size_t nSize
= aSelected
.size();
539 for( size_t i
=0; i
< nSize
&& nPos
< nCount
; i
++ )
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
);
565 return Sequence
< sal_Int32
>();
571 Sequence
< sal_Int32
> aRet( nCount
);
572 sal_Int32
*pRet
= aRet
.getArray();
574 size_t nSize
= aSelected
.size();
575 for( size_t i
=0; i
< nSize
&& nPos
< nCount
; i
++ )
588 sal_Bool SAL_CALL
AccessibleTableShape::isAccessibleRowSelected( sal_Int32 nRow
)
590 SolarMutexGuard aSolarGuard
;
591 checkCellPosition( 0, nRow
);
592 SvxTableController
* pController
= getTableController();
595 return pController
->isRowSelected( nRow
);
601 sal_Bool SAL_CALL
AccessibleTableShape::isAccessibleColumnSelected( sal_Int32 nColumn
)
603 SolarMutexGuard aSolarGuard
;
604 checkCellPosition( nColumn
, 0 );
605 SvxTableController
* pController
= getTableController();
608 return pController
->isColumnSelected( nColumn
);
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
;
634 Reference
< XAccessible
> SAL_CALL
AccessibleTableShape::getAccessibleSummary( )
636 Reference
< XAccessible
> 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
) )
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
);
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
);
685 // XAccessibleSelection
688 void SAL_CALL
AccessibleTableShape::selectAccessibleChild( sal_Int64 nChildIndex
)
690 SolarMutexGuard aSolarGuard
;
692 mxImpl
->getColumnAndRow( nChildIndex
, aPos
.mnCol
, aPos
.mnRow
);
694 // todo, select table shape?!?
695 SvxTableController
* pController
= getTableController();
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();
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();
733 pController
->clearSelection();
737 void SAL_CALL
AccessibleTableShape::selectAllAccessibleChildren()
739 SolarMutexGuard aSolarGuard
;
741 // todo: force selection of shape?
742 SvxTableController
* pController
= getTableController();
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
);
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
;
792 mxImpl
->getColumnAndRow( nChildIndex
, aPos
.mnCol
, aPos
.mnRow
);
794 // todo, select table shape?!?
795 SvxTableController
* pController
= getTableController();
796 if( !(pController
&& pController
->hasSelectedCells()) )
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
812 pController
->setSelectedCells( aFirstPos
, aLastPos
);
815 // XAccessibleTableSelection
816 sal_Bool SAL_CALL
AccessibleTableShape::selectRow( sal_Int32 row
)
818 SolarMutexGuard aSolarGuard
;
819 SvxTableController
* pController
= getTableController();
822 return pController
->selectRow( row
);
825 sal_Bool SAL_CALL
AccessibleTableShape::selectColumn( sal_Int32 column
)
827 SolarMutexGuard aSolarGuard
;
828 SvxTableController
* pController
= getTableController();
831 return pController
->selectColumn( column
);
834 sal_Bool SAL_CALL
AccessibleTableShape::unselectRow( sal_Int32 row
)
836 SolarMutexGuard aSolarGuard
;
837 SvxTableController
* pController
= getTableController();
840 return pController
->deselectRow( row
);
843 sal_Bool SAL_CALL
AccessibleTableShape::unselectColumn( sal_Int32 column
)
845 SolarMutexGuard aSolarGuard
;
846 SvxTableController
* pController
= getTableController();
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
)
861 while( n
< nChildren
)
863 if( const_cast<AccessibleTableShape
*>(this)->isAccessibleChildSelected( n
) )
865 if( 0 == nSelectedChildIndex
)
868 --nSelectedChildIndex
;
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
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());
893 rtl::Reference
< AccessibleCell
> xAccCell
= mxImpl
->getAccessibleCell( xCell
);
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);
907 xAccCell
->SetState(AccessibleStateType::SELECTED
);
908 xAccCell
->CommitChange(AccessibleEventId::SELECTION_CHANGED_ADD
, Any(), Any(), -1);
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();
925 sdr::table::SdrTableObj
* pTableObj
= pController
->GetTableObj();
928 const sdr::table::CellRef
& xCellRef (pTableObj
->getActiveCell());
934 pTableObj
->getActiveCellPos( rPos
);
935 xAccCell
= mxImpl
->getAccessibleCell( rPos
.mnRow
, rPos
.mnCol
);
937 pAccCell
= xAccCell
.get();
939 catch ( IndexOutOfBoundsException
& ) {}
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()) )
987 throw IndexOutOfBoundsException();
990 AccessibleTableHeaderShape::AccessibleTableHeaderShape( AccessibleTableShape
* pTable
, bool bRow
)
996 AccessibleTableHeaderShape::~AccessibleTableHeaderShape()
1002 Reference
< XAccessibleContext
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleContext()
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
;
1024 sal_Int64 SAL_CALL
AccessibleTableHeaderShape::getAccessibleIndexInParent()
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();
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
;
1141 Reference
< XAccessibleTable
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleColumnHeaders( )
1143 Reference
< XAccessibleTable
> 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
);
1160 return Sequence
< sal_Int32
>();
1166 Sequence
< sal_Int32
> aRet( nCount
);
1167 sal_Int32
*pRet
= aRet
.getArray();
1169 size_t nSize
= aSelected
.size();
1170 for( size_t i
=0; i
< nSize
&& nPos
< nCount
; i
++ )
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
);
1195 return Sequence
< sal_Int32
>();
1201 Sequence
< sal_Int32
> aRet( nCount
);
1202 sal_Int32
*pRet
= aRet
.getArray();
1204 size_t nSize
= aSelected
.size();
1205 for( size_t i
=0; i
< nSize
&& nPos
< nCount
; i
++ )
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
)
1266 return mpTable
->selectRow( row
);
1269 mpTable
->clearAccessibleSelection();
1270 sal_Int64 nIndex
= mpTable
->getAccessibleIndex( row
, 0 );
1271 mpTable
->selectAccessibleChild( nIndex
);
1276 sal_Bool SAL_CALL
AccessibleTableHeaderShape::selectColumn( sal_Int32 column
)
1279 return mpTable
->selectColumn( column
);
1282 mpTable
->clearAccessibleSelection();
1283 sal_Int64 nIndex
= mpTable
->getAccessibleIndex( 0, column
);
1284 mpTable
->selectAccessibleChild( nIndex
);
1289 sal_Bool SAL_CALL
AccessibleTableHeaderShape::unselectRow( sal_Int32 row
)
1292 return mpTable
->unselectRow( row
);
1295 sal_Int64 nIndex
= mpTable
->getAccessibleIndex( row
, 0 );
1296 mpTable
->deselectAccessibleChild( nIndex
);
1301 sal_Bool SAL_CALL
AccessibleTableHeaderShape::unselectColumn( sal_Int32 column
)
1304 return mpTable
->unselectColumn( column
);
1307 sal_Int64 nIndex
= mpTable
->getAccessibleIndex( 0, column
);
1308 mpTable
->deselectAccessibleChild( nIndex
);
1314 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */