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::drawing
;
52 using namespace ::com::sun::star::table
;
53 using namespace ::com::sun::star::container
;
55 namespace accessibility
58 typedef std::unordered_map
< Reference
< XCell
>, rtl::Reference
< AccessibleCell
> > AccessibleCellMap
;
60 class AccessibleTableShapeImpl
: public cppu::WeakImplHelper
< XModifyListener
>
63 explicit AccessibleTableShapeImpl( AccessibleShapeTreeInfo
& rShapeTreeInfo
);
65 void init( const Reference
< XAccessible
>& xAccessible
, const Reference
< XTable
>& xTable
);
68 /// @throws IndexOutOfBoundsException
69 /// @throws RuntimeException
70 Reference
< XAccessible
> getAccessibleChild(sal_Int64 i
);
71 /// @throws IndexOutOfBoundsException
72 void getColumnAndRow( sal_Int64 nChildIndex
, sal_Int32
& rnColumn
, sal_Int32
& rnRow
);
75 virtual void SAL_CALL
modified( const EventObject
& aEvent
) override
;
78 virtual void SAL_CALL
disposing( const EventObject
& Source
) override
;
80 AccessibleShapeTreeInfo
& mrShapeTreeInfo
;
81 Reference
< XTable
> mxTable
;
82 AccessibleCellMap maChildMap
;
83 Reference
< XAccessible
> mxAccessible
;
84 sal_Int32 mRowCount
, mColCount
;
85 //get the cached AccessibleCell from XCell
86 rtl::Reference
< AccessibleCell
> getAccessibleCell (const Reference
< XCell
>& xCell
);
87 /// @throws IndexOutOfBoundsException
88 /// @throws RuntimeException
89 rtl::Reference
< AccessibleCell
> getAccessibleCell (sal_Int32 nRow
, sal_Int32 nColumn
);
93 AccessibleTableShapeImpl::AccessibleTableShapeImpl( AccessibleShapeTreeInfo
& rShapeTreeInfo
)
94 : mrShapeTreeInfo( rShapeTreeInfo
)
101 void AccessibleTableShapeImpl::init( const Reference
< XAccessible
>& xAccessible
, const Reference
< XTable
>& xTable
)
103 mxAccessible
= xAccessible
;
108 Reference
< XModifyListener
> xListener( this );
109 mxTable
->addModifyListener( xListener
);
110 //register the listener with table model
111 Reference
< css::view::XSelectionSupplier
> xSelSupplier(xTable
, UNO_QUERY
);
112 Reference
< css::view::XSelectionChangeListener
> xSelListener( xAccessible
, UNO_QUERY
);
113 if (xSelSupplier
.is())
114 xSelSupplier
->addSelectionChangeListener(xSelListener
);
115 mRowCount
= mxTable
->getRowCount();
116 mColCount
= mxTable
->getColumnCount();
121 void AccessibleTableShapeImpl::dispose()
125 //remove all the cell's acc object in table's dispose.
126 for( auto& rEntry
: maChildMap
)
128 rEntry
.second
->dispose();
131 Reference
< XModifyListener
> xListener( this );
132 mxTable
->removeModifyListener( xListener
);
135 mxAccessible
.clear();
139 //get the cached AccessibleCell from XCell
140 rtl::Reference
< AccessibleCell
> AccessibleTableShapeImpl::getAccessibleCell (const Reference
< XCell
>& xCell
)
142 AccessibleCellMap::iterator
iter( maChildMap
.find( xCell
) );
144 if( iter
!= maChildMap
.end() )
146 rtl::Reference
< AccessibleCell
> xChild( (*iter
).second
);
149 return rtl::Reference
< AccessibleCell
>();
152 rtl::Reference
< AccessibleCell
> AccessibleTableShapeImpl::getAccessibleCell (sal_Int32 nRow
, sal_Int32 nColumn
)
154 Reference
< XCell
> xCell( mxTable
->getCellByPosition( nColumn
, nRow
) );
155 rtl::Reference
< AccessibleCell
> xChild
= getAccessibleCell( xCell
);
157 if( !xChild
.is() && mxTable
.is() )
159 sal_Int32 nChildIndex
= mxTable
->getColumnCount() * nRow
+ nColumn
;
160 CellRef
xCellRef( dynamic_cast< Cell
* >( xCell
.get() ) );
162 rtl::Reference
< AccessibleCell
> xAccessibleCell( new AccessibleCell( mxAccessible
, xCellRef
, nChildIndex
, mrShapeTreeInfo
) );
164 xAccessibleCell
->Init();
165 maChildMap
[xCell
] = xAccessibleCell
;
167 xChild
= xAccessibleCell
;
173 Reference
< XAccessible
> AccessibleTableShapeImpl::getAccessibleChild(sal_Int64 nChildIndex
)
175 sal_Int32 nColumn
= 0, nRow
= 0;
176 getColumnAndRow( nChildIndex
, nColumn
, nRow
);
178 Reference
< XCell
> xCell( mxTable
->getCellByPosition( nColumn
, nRow
) );
179 AccessibleCellMap::iterator
iter( maChildMap
.find( xCell
) );
181 if( iter
!= maChildMap
.end() )
183 Reference
< XAccessible
> xChild( (*iter
).second
);
188 CellRef
xCellRef( dynamic_cast< Cell
* >( xCell
.get() ) );
190 rtl::Reference
< AccessibleCell
> xAccessibleCell( new AccessibleCell( mxAccessible
, xCellRef
, nChildIndex
, mrShapeTreeInfo
) );
192 xAccessibleCell
->Init();
193 maChildMap
[xCell
] = xAccessibleCell
;
195 return xAccessibleCell
;
200 void AccessibleTableShapeImpl::getColumnAndRow( sal_Int64 nChildIndex
, sal_Int32
& rnColumn
, sal_Int32
& rnRow
)
204 const sal_Int32 nColumnCount
= mxTable
->getColumnCount();
205 if (nColumnCount
== 0)
206 throw IndexOutOfBoundsException();
208 rnColumn
= nChildIndex
% nColumnCount
;
209 rnRow
= nChildIndex
/ nColumnCount
;
211 if( rnRow
< mxTable
->getRowCount() )
215 throw IndexOutOfBoundsException();
219 void SAL_CALL
AccessibleTableShapeImpl::modified( const EventObject
& /*aEvent*/ )
226 // structural changes may have happened to the table, validate all accessible cell instances
227 AccessibleCellMap aTempChildMap
;
228 aTempChildMap
.swap( maChildMap
);
230 // first move all still existing cells to maChildMap again and update their index
232 const sal_Int32 nRowCount
= mxTable
->getRowCount();
233 const sal_Int32 nColCount
= mxTable
->getColumnCount();
235 bool bRowOrColumnChanged
= false;
236 if (mRowCount
!= nRowCount
|| mColCount
!= nColCount
)
238 bRowOrColumnChanged
= true;
239 mRowCount
= nRowCount
;
240 mColCount
= nColCount
;
242 sal_Int32 nChildIndex
= 0;
244 for( sal_Int32 nRow
= 0; nRow
< nRowCount
; ++nRow
)
246 for( sal_Int32 nCol
= 0; nCol
< nColCount
; ++nCol
)
248 Reference
< XCell
> xCell( mxTable
->getCellByPosition( nCol
, nRow
) );
249 AccessibleCellMap::iterator
iter( aTempChildMap
.find( xCell
) );
251 if( iter
!= aTempChildMap
.end() )
253 rtl::Reference
< AccessibleCell
> xAccessibleCell( (*iter
).second
);
254 xAccessibleCell
->setIndexInParent( nChildIndex
);
255 xAccessibleCell
->UpdateChildren();
256 // If row or column count is changed, there is split or merge, so all cell's acc name should be updated
257 if (bRowOrColumnChanged
)
259 xAccessibleCell
->SetAccessibleName(xAccessibleCell
->getAccessibleName(), AccessibleContextBase::ManuallySet
);
261 // For merged cell, add invisible & disabled state.
262 Reference
< XMergeableCell
> xMergedCell( mxTable
->getCellByPosition( nCol
, nRow
), UNO_QUERY
);
263 if (xMergedCell
.is() && xMergedCell
->isMerged())
265 xAccessibleCell
->ResetState(AccessibleStateType::VISIBLE
);
266 xAccessibleCell
->ResetState(AccessibleStateType::ENABLED
);
267 // IA2 CWS. MT: OFFSCREEN == !SHOWING, should stay consistent
268 // xAccessibleCell->SetState(AccessibleStateType::OFFSCREEN);
269 xAccessibleCell
->ResetState(AccessibleStateType::SHOWING
);
273 xAccessibleCell
->SetState(AccessibleStateType::VISIBLE
);
274 xAccessibleCell
->SetState(AccessibleStateType::ENABLED
);
275 // IA2 CWS. MT: OFFSCREEN == !SHOWING, should stay consistent
276 // xAccessibleCell->ResetState(AccessibleStateType::OFFSCREEN);
277 xAccessibleCell
->SetState(AccessibleStateType::SHOWING
);
280 // move still existing cell from temporary child map to our child map
281 maChildMap
[xCell
] = xAccessibleCell
;
282 aTempChildMap
.erase( iter
);
286 CellRef
xCellRef( dynamic_cast< Cell
* >( xCell
.get() ) );
288 rtl::Reference
< AccessibleCell
> xAccessibleCell( new AccessibleCell( mxAccessible
, xCellRef
, nChildIndex
, mrShapeTreeInfo
) );
290 xAccessibleCell
->Init();
291 maChildMap
[xCell
] = xAccessibleCell
;
298 // all accessible cell instances still left in aTempChildMap must be disposed
299 // as they are no longer part of the table
301 for( auto& rEntry
: aTempChildMap
)
303 rEntry
.second
->dispose();
305 //notify bridge to update the acc cache.
306 AccessibleTableShape
*pAccTable
= dynamic_cast <AccessibleTableShape
*> (mxAccessible
.get());
308 pAccTable
->CommitChange(AccessibleEventId::INVALIDATE_ALL_CHILDREN
, Any(), Any(), -1);
310 catch( const Exception
& )
312 TOOLS_WARN_EXCEPTION("svx.table", "");
317 void SAL_CALL
AccessibleTableShapeImpl::disposing( const EventObject
& /*Source*/ )
321 AccessibleTableShape::AccessibleTableShape( const AccessibleShapeInfo
& rShapeInfo
, const AccessibleShapeTreeInfo
& rShapeTreeInfo
)
322 : AccessibleTableShape_Base(rShapeInfo
, rShapeTreeInfo
)
323 , mnPreviousSelectionCount(0)
324 , mxImpl( new AccessibleTableShapeImpl( maShapeTreeInfo
) )
329 AccessibleTableShape::~AccessibleTableShape()
334 void AccessibleTableShape::Init()
338 Reference
< XPropertySet
> xSet( mxShape
, UNO_QUERY_THROW
);
339 Reference
< XTable
> xTable( xSet
->getPropertyValue("Model"), UNO_QUERY_THROW
);
341 mxImpl
->init( this, xTable
);
345 TOOLS_WARN_EXCEPTION("svx.table", "");
348 AccessibleTableShape_Base::Init();
352 SvxTableController
* AccessibleTableShape::getTableController()
354 SdrView
* pView
= maShapeTreeInfo
.GetSdrView ();
356 return dynamic_cast< SvxTableController
* >( pView
->getSelectionController().get() );
365 Any SAL_CALL
AccessibleTableShape::queryInterface( const Type
& aType
)
367 if ( aType
== cppu::UnoType
<XAccessibleTableSelection
>::get())
369 Reference
<XAccessibleTableSelection
> xThis( this );
375 return AccessibleTableShape_Base::queryInterface( aType
);
379 void SAL_CALL
AccessibleTableShape::acquire( ) noexcept
381 AccessibleTableShape_Base::acquire();
385 void SAL_CALL
AccessibleTableShape::release( ) noexcept
387 AccessibleTableShape_Base::release();
394 OUString SAL_CALL
AccessibleTableShape::getImplementationName()
396 return "com.sun.star.comp.accessibility.AccessibleTableShape";
400 OUString
AccessibleTableShape::CreateAccessibleBaseName()
406 sal_Int64 SAL_CALL
AccessibleTableShape::getAccessibleChildCount( )
408 SolarMutexGuard aSolarGuard
;
409 return mxImpl
->mxTable
.is() ? static_cast<sal_Int64
>(mxImpl
->mxTable
->getRowCount()) * static_cast<sal_Int64
>(mxImpl
->mxTable
->getColumnCount()) : 0;
413 Reference
< XAccessible
> SAL_CALL
AccessibleTableShape::getAccessibleChild( sal_Int64 i
)
415 SolarMutexGuard aSolarGuard
;
418 return mxImpl
->getAccessibleChild( i
);
422 sal_Int16 SAL_CALL
AccessibleTableShape::getAccessibleRole()
424 return AccessibleRole::TABLE
;
428 void SAL_CALL
AccessibleTableShape::disposing()
432 // let the base do its stuff
433 AccessibleShape::disposing();
440 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleRowCount()
442 SolarMutexGuard aSolarGuard
;
443 return mxImpl
->mxTable
.is() ? mxImpl
->mxTable
->getRowCount() : 0;
447 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleColumnCount( )
449 SolarMutexGuard aSolarGuard
;
450 return mxImpl
->mxTable
.is() ? mxImpl
->mxTable
->getColumnCount() : 0;
454 OUString SAL_CALL
AccessibleTableShape::getAccessibleRowDescription( sal_Int32 nRow
)
456 checkCellPosition( 0, nRow
);
461 OUString SAL_CALL
AccessibleTableShape::getAccessibleColumnDescription( sal_Int32 nColumn
)
463 SolarMutexGuard aSolarGuard
;
464 checkCellPosition( nColumn
, 0 );
469 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleRowExtentAt( sal_Int32 nRow
, sal_Int32 nColumn
)
471 SolarMutexGuard aSolarGuard
;
472 checkCellPosition( nColumn
, nRow
);
473 if( mxImpl
->mxTable
.is() )
475 Reference
< XMergeableCell
> xCell( mxImpl
->mxTable
->getCellByPosition( nColumn
, nRow
), UNO_QUERY
);
477 return xCell
->getRowSpan();
483 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleColumnExtentAt( sal_Int32 nRow
, sal_Int32 nColumn
)
485 SolarMutexGuard aSolarGuard
;
486 checkCellPosition( nColumn
, nRow
);
487 if( mxImpl
->mxTable
.is() )
489 Reference
< XMergeableCell
> xCell( mxImpl
->mxTable
->getCellByPosition( nColumn
, nRow
), UNO_QUERY
);
491 return xCell
->getColumnSpan();
497 Reference
< XAccessibleTable
> SAL_CALL
AccessibleTableShape::getAccessibleRowHeaders( )
499 Reference
< XAccessibleTable
> xRet
;
500 SvxTableController
* pController
= getTableController();
503 if( pController
->isRowHeader() )
505 xRet
= new AccessibleTableHeaderShape( this, true );
512 Reference
< XAccessibleTable
> SAL_CALL
AccessibleTableShape::getAccessibleColumnHeaders( )
514 Reference
< XAccessibleTable
> xRet
;
515 SvxTableController
* pController
= getTableController();
518 if( pController
->isColumnHeader() )
520 xRet
= new AccessibleTableHeaderShape( this, false );
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
);
540 return Sequence
< sal_Int32
>();
546 Sequence
< sal_Int32
> aRet( nCount
);
547 sal_Int32
*pRet
= aRet
.getArray();
549 size_t nSize
= aSelected
.size();
550 for( size_t i
=0; i
< nSize
&& nPos
< nCount
; i
++ )
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
);
576 return Sequence
< sal_Int32
>();
582 Sequence
< sal_Int32
> aRet( nCount
);
583 sal_Int32
*pRet
= aRet
.getArray();
585 size_t nSize
= aSelected
.size();
586 for( size_t i
=0; i
< nSize
&& nPos
< nCount
; i
++ )
599 sal_Bool SAL_CALL
AccessibleTableShape::isAccessibleRowSelected( sal_Int32 nRow
)
601 SolarMutexGuard aSolarGuard
;
602 checkCellPosition( 0, nRow
);
603 SvxTableController
* pController
= getTableController();
606 return pController
->isRowSelected( nRow
);
612 sal_Bool SAL_CALL
AccessibleTableShape::isAccessibleColumnSelected( sal_Int32 nColumn
)
614 SolarMutexGuard aSolarGuard
;
615 checkCellPosition( nColumn
, 0 );
616 SvxTableController
* pController
= getTableController();
619 return pController
->isColumnSelected( nColumn
);
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
;
645 Reference
< XAccessible
> SAL_CALL
AccessibleTableShape::getAccessibleSummary( )
647 Reference
< XAccessible
> 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
) )
670 sal_Int64 SAL_CALL
AccessibleTableShape::getAccessibleIndex( sal_Int32 nRow
, sal_Int32 nColumn
)
672 SolarMutexGuard aSolarGuard
;
673 checkCellPosition( nColumn
, nRow
);
674 return mxImpl
->mxTable
.is() ? (static_cast<sal_Int64
>(nRow
) * static_cast<sal_Int64
>(mxImpl
->mxTable
->getColumnCount()) + nColumn
) : 0;
678 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleRow( sal_Int64 nChildIndex
)
680 SolarMutexGuard aSolarGuard
;
681 sal_Int32 nColumn
= 0, nRow
= 0;
682 mxImpl
->getColumnAndRow( nChildIndex
, nColumn
, nRow
);
687 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleColumn( sal_Int64 nChildIndex
)
689 SolarMutexGuard aSolarGuard
;
690 sal_Int32 nColumn
= 0, nRow
= 0;
691 mxImpl
->getColumnAndRow( nChildIndex
, nColumn
, nRow
);
696 // XAccessibleSelection
699 void SAL_CALL
AccessibleTableShape::selectAccessibleChild( sal_Int64 nChildIndex
)
701 SolarMutexGuard aSolarGuard
;
703 mxImpl
->getColumnAndRow( nChildIndex
, aPos
.mnCol
, aPos
.mnRow
);
705 // todo, select table shape?!?
706 SvxTableController
* pController
= getTableController();
710 CellPos
aFirstPos( aPos
), aLastPos( aPos
);
711 if( pController
->hasSelectedCells() )
713 pController
->getSelectedCells( aFirstPos
, aLastPos
);
715 aFirstPos
.mnRow
= std::min( aFirstPos
.mnRow
, aPos
.mnRow
);
716 aFirstPos
.mnCol
= std::min( aFirstPos
.mnCol
, aPos
.mnCol
);
717 aLastPos
.mnRow
= std::max( aLastPos
.mnRow
, aPos
.mnRow
);
718 aLastPos
.mnCol
= std::max( aLastPos
.mnCol
, aPos
.mnCol
);
720 pController
->setSelectedCells( aFirstPos
, aLastPos
);
724 sal_Bool SAL_CALL
AccessibleTableShape::isAccessibleChildSelected( sal_Int64 nChildIndex
)
726 SolarMutexGuard aSolarGuard
;
728 if (nChildIndex
< 0 || nChildIndex
>= getAccessibleChildCount())
729 throw IndexOutOfBoundsException();
732 mxImpl
->getColumnAndRow( nChildIndex
, aPos
.mnCol
, aPos
.mnRow
);
734 return isAccessibleSelected(aPos
.mnRow
, aPos
.mnCol
);
738 void SAL_CALL
AccessibleTableShape::clearAccessibleSelection()
740 SolarMutexGuard aSolarGuard
;
742 SvxTableController
* pController
= getTableController();
744 pController
->clearSelection();
748 void SAL_CALL
AccessibleTableShape::selectAllAccessibleChildren()
750 SolarMutexGuard aSolarGuard
;
752 // todo: force selection of shape?
753 SvxTableController
* pController
= getTableController();
755 pController
->selectAll();
759 sal_Int64 SAL_CALL
AccessibleTableShape::getSelectedAccessibleChildCount()
761 SolarMutexGuard aSolarGuard
;
763 SvxTableController
* pController
= getTableController();
764 if( pController
&& pController
->hasSelectedCells() )
766 CellPos aFirstPos
, aLastPos
;
767 pController
->getSelectedCells( aFirstPos
, aLastPos
);
769 const sal_Int32 nSelectedColumns
= std::max( sal_Int32(0), aLastPos
.mnCol
- aFirstPos
.mnCol
) + 1;
770 const sal_Int32 nSelectedRows
= std::max( sal_Int32(0), aLastPos
.mnRow
- aFirstPos
.mnRow
) + 1;
771 return static_cast<sal_Int64
>(nSelectedRows
) * static_cast<sal_Int64
>(nSelectedColumns
);
778 Reference
< XAccessible
> SAL_CALL
AccessibleTableShape::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex
)
780 SolarMutexGuard aSolarGuard
;
782 if( nSelectedChildIndex
< 0 )
783 throw IndexOutOfBoundsException();
785 sal_Int64 nChildIndex
= GetIndexOfSelectedChild( nSelectedChildIndex
);
787 if( nChildIndex
< 0 )
788 throw IndexOutOfBoundsException();
790 if ( nChildIndex
>= getAccessibleChildCount() )
792 throw IndexOutOfBoundsException();
795 return getAccessibleChild( nChildIndex
);
799 void SAL_CALL
AccessibleTableShape::deselectAccessibleChild( sal_Int64 nChildIndex
)
801 SolarMutexGuard aSolarGuard
;
803 mxImpl
->getColumnAndRow( nChildIndex
, aPos
.mnCol
, aPos
.mnRow
);
805 // todo, select table shape?!?
806 SvxTableController
* pController
= getTableController();
807 if( !(pController
&& pController
->hasSelectedCells()) )
810 CellPos aFirstPos
, aLastPos
;
811 pController
->getSelectedCells( aFirstPos
, aLastPos
);
813 // create a selection where aPos is not part of anymore
814 aFirstPos
.mnRow
= std::min( aFirstPos
.mnRow
, aPos
.mnRow
+1 );
815 aFirstPos
.mnCol
= std::min( aFirstPos
.mnCol
, aPos
.mnCol
+1 );
816 aLastPos
.mnRow
= std::max( aLastPos
.mnRow
, aPos
.mnRow
-1 );
817 aLastPos
.mnCol
= std::max( aLastPos
.mnCol
, aPos
.mnCol
-1 );
819 // new selection may be invalid (child to deselect is not at a border of the selection but in between)
820 if( (aFirstPos
.mnRow
> aLastPos
.mnRow
) || (aFirstPos
.mnCol
> aLastPos
.mnCol
) )
821 pController
->clearSelection(); // if selection is invalid, clear all
823 pController
->setSelectedCells( aFirstPos
, aLastPos
);
826 // XAccessibleTableSelection
827 sal_Bool SAL_CALL
AccessibleTableShape::selectRow( sal_Int32 row
)
829 SolarMutexGuard aSolarGuard
;
830 SvxTableController
* pController
= getTableController();
833 return pController
->selectRow( row
);
836 sal_Bool SAL_CALL
AccessibleTableShape::selectColumn( sal_Int32 column
)
838 SolarMutexGuard aSolarGuard
;
839 SvxTableController
* pController
= getTableController();
842 return pController
->selectColumn( column
);
845 sal_Bool SAL_CALL
AccessibleTableShape::unselectRow( sal_Int32 row
)
847 SolarMutexGuard aSolarGuard
;
848 SvxTableController
* pController
= getTableController();
851 return pController
->deselectRow( row
);
854 sal_Bool SAL_CALL
AccessibleTableShape::unselectColumn( sal_Int32 column
)
856 SolarMutexGuard aSolarGuard
;
857 SvxTableController
* pController
= getTableController();
860 return pController
->deselectColumn( column
);
863 sal_Int64
AccessibleTableShape::GetIndexOfSelectedChild(
864 sal_Int64 nSelectedChildIndex
) const
866 sal_Int64 nChildren
= const_cast<AccessibleTableShape
*>(this)->getAccessibleChildCount();
868 if( nSelectedChildIndex
>= nChildren
)
872 while( n
< nChildren
)
874 if( const_cast<AccessibleTableShape
*>(this)->isAccessibleChildSelected( n
) )
876 if( 0 == nSelectedChildIndex
)
879 --nSelectedChildIndex
;
884 return n
< nChildren
? n
: -1;
886 void AccessibleTableShape::getColumnAndRow( sal_Int64 nChildIndex
, sal_Int32
& rnColumn
, sal_Int32
& rnRow
)
888 mxImpl
->getColumnAndRow(nChildIndex
, rnColumn
, rnRow
);
891 // XSelectionChangeListener
893 AccessibleTableShape::disposing (const EventObject
& aEvent
)
895 AccessibleShape::disposing(aEvent
);
897 void SAL_CALL
AccessibleTableShape::selectionChanged (const EventObject
& rEvent
)
899 //sdr::table::CellRef xCellRef = static_cast< sdr::table::CellRef > (rEvent.Source);
900 Reference
< XCell
> xCell(rEvent
.Source
, UNO_QUERY
);
904 rtl::Reference
< AccessibleCell
> xAccCell
= mxImpl
->getAccessibleCell( xCell
);
908 sal_Int64 nIndex
= xAccCell
->getAccessibleIndexInParent(),
909 nCount
= getSelectedAccessibleChildCount();
910 bool bSelected
= isAccessibleChildSelected(nIndex
);
911 if (mnPreviousSelectionCount
== 0 && nCount
> 0 && bSelected
)
913 xAccCell
->SetState(AccessibleStateType::SELECTED
);
914 xAccCell
->CommitChange(AccessibleEventId::SELECTION_CHANGED
, Any(), Any(), -1);
918 xAccCell
->SetState(AccessibleStateType::SELECTED
);
919 xAccCell
->CommitChange(AccessibleEventId::SELECTION_CHANGED_ADD
, Any(), Any(), -1);
923 xAccCell
->ResetState(AccessibleStateType::SELECTED
);
924 xAccCell
->CommitChange(AccessibleEventId::SELECTION_CHANGED_REMOVE
, Any(), Any(), -1);
926 mnPreviousSelectionCount
= nCount
;
928 // Get the currently active cell which is text editing
929 AccessibleCell
* AccessibleTableShape::GetActiveAccessibleCell()
931 rtl::Reference
< AccessibleCell
> xAccCell
;
932 AccessibleCell
* pAccCell
= nullptr;
933 SvxTableController
* pController
= getTableController();
936 sdr::table::SdrTableObj
* pTableObj
= pController
->GetTableObj();
939 const sdr::table::CellRef
& xCellRef (pTableObj
->getActiveCell());
945 pTableObj
->getActiveCellPos( rPos
);
946 xAccCell
= mxImpl
->getAccessibleCell( rPos
.mnRow
, rPos
.mnCol
);
948 pAccCell
= xAccCell
.get();
950 catch ( IndexOutOfBoundsException
& ) {}
957 //If current active cell is in editing, the focus state should be set to internal text
958 bool AccessibleTableShape::SetState (sal_Int64 aState
)
960 if( aState
== AccessibleStateType::FOCUSED
)
962 AccessibleCell
* pActiveAccessibleCell
= GetActiveAccessibleCell();
963 if( pActiveAccessibleCell
!= nullptr )
964 return pActiveAccessibleCell
->SetState(aState
);
967 return AccessibleShape::SetState (aState
);
970 //If current active cell is in editing, the focus state should be reset to internal text
971 bool AccessibleTableShape::ResetState (sal_Int64 aState
)
973 if( aState
== AccessibleStateType::FOCUSED
)
975 AccessibleCell
* pActiveAccessibleCell
= GetActiveAccessibleCell();
976 if( pActiveAccessibleCell
!= nullptr )
977 return pActiveAccessibleCell
->ResetState(aState
);
980 return AccessibleShape::ResetState (aState
);
983 bool AccessibleTableShape::SetStateDirectly (sal_Int64 aState
)
985 return AccessibleContextBase::SetState (aState
);
988 bool AccessibleTableShape::ResetStateDirectly (sal_Int64 aState
)
990 return AccessibleContextBase::ResetState (aState
);
993 void AccessibleTableShape::checkCellPosition( sal_Int32 nCol
, sal_Int32 nRow
)
995 if( (nCol
>= 0) && (nRow
>= 0) && mxImpl
->mxTable
.is() && (nCol
< mxImpl
->mxTable
->getColumnCount()) && (nRow
< mxImpl
->mxTable
->getRowCount()) )
998 throw IndexOutOfBoundsException();
1001 AccessibleTableHeaderShape::AccessibleTableHeaderShape( AccessibleTableShape
* pTable
, bool bRow
)
1007 AccessibleTableHeaderShape::~AccessibleTableHeaderShape()
1013 Reference
< XAccessibleContext
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleContext()
1018 // XAccessibleContext
1019 sal_Int64 SAL_CALL
AccessibleTableHeaderShape::getAccessibleChildCount( )
1021 return static_cast<sal_Int64
>(getAccessibleRowCount()) * static_cast<sal_Int64
>(getAccessibleColumnCount());
1024 Reference
< XAccessible
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleChild( sal_Int64 i
)
1026 return mpTable
->getAccessibleChild( i
);
1029 Reference
< XAccessible
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleParent()
1031 Reference
< XAccessible
> XParent
;
1035 sal_Int64 SAL_CALL
AccessibleTableHeaderShape::getAccessibleIndexInParent()
1040 sal_Int16 SAL_CALL
AccessibleTableHeaderShape::getAccessibleRole()
1042 return mpTable
->getAccessibleRole();
1045 OUString SAL_CALL
AccessibleTableHeaderShape::getAccessibleDescription()
1047 return mpTable
->getAccessibleDescription();
1050 OUString SAL_CALL
AccessibleTableHeaderShape::getAccessibleName()
1052 return mpTable
->getAccessibleName();
1055 sal_Int64 SAL_CALL
AccessibleTableHeaderShape::getAccessibleStateSet()
1057 return mpTable
->getAccessibleStateSet();
1060 Reference
< XAccessibleRelationSet
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleRelationSet()
1062 return mpTable
->getAccessibleRelationSet();
1065 Locale SAL_CALL
AccessibleTableHeaderShape::getLocale()
1067 return mpTable
->getLocale();
1070 //XAccessibleComponent
1071 sal_Bool SAL_CALL
AccessibleTableHeaderShape::containsPoint ( const css::awt::Point
& aPoint
)
1073 return mpTable
->containsPoint( aPoint
);
1076 Reference
< XAccessible
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleAtPoint ( const css::awt::Point
& aPoint
)
1078 return mpTable
->getAccessibleAtPoint( aPoint
);
1081 css::awt::Rectangle SAL_CALL
AccessibleTableHeaderShape::getBounds()
1083 return mpTable
->getBounds();
1086 css::awt::Point SAL_CALL
AccessibleTableHeaderShape::getLocation()
1088 return mpTable
->getLocation();
1091 css::awt::Point SAL_CALL
AccessibleTableHeaderShape::getLocationOnScreen()
1093 return mpTable
->getLocationOnScreen();
1096 css::awt::Size SAL_CALL
AccessibleTableHeaderShape::getSize()
1098 return mpTable
->getSize();
1101 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getForeground()
1103 return mpTable
->getForeground();
1106 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getBackground()
1108 return mpTable
->getBackground();
1111 void SAL_CALL
AccessibleTableHeaderShape::grabFocus()
1113 mpTable
->grabFocus();
1116 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleRowCount()
1118 return mbRow
? 1 : mpTable
->getAccessibleRowCount();
1121 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleColumnCount()
1123 return !mbRow
? 1 : mpTable
->getAccessibleColumnCount();
1126 OUString SAL_CALL
AccessibleTableHeaderShape::getAccessibleRowDescription( sal_Int32 nRow
)
1128 return mpTable
->getAccessibleRowDescription( nRow
);
1131 OUString SAL_CALL
AccessibleTableHeaderShape::getAccessibleColumnDescription( sal_Int32 nColumn
)
1133 return mpTable
->getAccessibleColumnDescription( nColumn
);
1136 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleRowExtentAt( sal_Int32 nRow
, sal_Int32 nColumn
)
1138 return mpTable
->getAccessibleRowExtentAt( nRow
, nColumn
);
1141 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleColumnExtentAt( sal_Int32 nRow
, sal_Int32 nColumn
)
1143 return mpTable
->getAccessibleColumnExtentAt( nRow
, nColumn
);
1146 Reference
< XAccessibleTable
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleRowHeaders( )
1148 Reference
< XAccessibleTable
> xRet
;
1152 Reference
< XAccessibleTable
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleColumnHeaders( )
1154 Reference
< XAccessibleTable
> xRet
;
1158 Sequence
< sal_Int32
> SAL_CALL
AccessibleTableHeaderShape::getSelectedAccessibleRows( )
1160 sal_Int32 nRow
= getAccessibleRowCount();
1161 ::std::vector
<bool> aSelected( nRow
, true );
1162 sal_Int32 nCount
= nRow
;
1163 for( sal_Int32 i
= 0; i
< nRow
; i
++ )
1167 aSelected
[i
] = isAccessibleRowSelected( i
);
1171 return Sequence
< sal_Int32
>();
1177 Sequence
< sal_Int32
> aRet( nCount
);
1178 sal_Int32
*pRet
= aRet
.getArray();
1180 size_t nSize
= aSelected
.size();
1181 for( size_t i
=0; i
< nSize
&& nPos
< nCount
; i
++ )
1193 Sequence
< sal_Int32
> SAL_CALL
AccessibleTableHeaderShape::getSelectedAccessibleColumns( )
1195 sal_Int32 nColumn
= getAccessibleColumnCount();
1196 ::std::vector
<bool> aSelected( nColumn
, true );
1197 sal_Int32 nCount
= nColumn
;
1198 for( sal_Int32 i
= 0; i
< nColumn
; i
++ )
1202 aSelected
[i
] = isAccessibleColumnSelected( i
);
1206 return Sequence
< sal_Int32
>();
1212 Sequence
< sal_Int32
> aRet( nCount
);
1213 sal_Int32
*pRet
= aRet
.getArray();
1215 size_t nSize
= aSelected
.size();
1216 for( size_t i
=0; i
< nSize
&& nPos
< nCount
; i
++ )
1228 sal_Bool SAL_CALL
AccessibleTableHeaderShape::isAccessibleRowSelected( sal_Int32 nRow
)
1230 return mpTable
->isAccessibleRowSelected( nRow
);
1233 sal_Bool SAL_CALL
AccessibleTableHeaderShape::isAccessibleColumnSelected( sal_Int32 nColumn
)
1235 return mpTable
->isAccessibleColumnSelected( nColumn
);
1238 Reference
< XAccessible
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleCellAt( sal_Int32 nRow
, sal_Int32 nColumn
)
1240 return mpTable
->getAccessibleCellAt( nRow
, nColumn
);
1243 Reference
< XAccessible
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleCaption( )
1245 return mpTable
->getAccessibleCaption();
1248 Reference
< XAccessible
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleSummary( )
1250 return mpTable
->getAccessibleSummary();
1253 sal_Bool SAL_CALL
AccessibleTableHeaderShape::isAccessibleSelected( sal_Int32 nRow
, sal_Int32 nColumn
)
1255 return mpTable
->isAccessibleSelected( nRow
, nColumn
);
1258 sal_Int64 SAL_CALL
AccessibleTableHeaderShape::getAccessibleIndex( sal_Int32 nRow
, sal_Int32 nColumn
)
1260 return mpTable
->getAccessibleIndex( nRow
, nColumn
);
1263 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleRow( sal_Int64 nChildIndex
)
1265 return mpTable
->getAccessibleRow( nChildIndex
);
1268 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleColumn( sal_Int64 nChildIndex
)
1270 return mpTable
->getAccessibleColumn( nChildIndex
);
1273 // XAccessibleTableSelection
1274 sal_Bool SAL_CALL
AccessibleTableHeaderShape::selectRow( sal_Int32 row
)
1277 return mpTable
->selectRow( row
);
1280 mpTable
->clearAccessibleSelection();
1281 sal_Int64 nIndex
= mpTable
->getAccessibleIndex( row
, 0 );
1282 mpTable
->selectAccessibleChild( nIndex
);
1287 sal_Bool SAL_CALL
AccessibleTableHeaderShape::selectColumn( sal_Int32 column
)
1290 return mpTable
->selectColumn( column
);
1293 mpTable
->clearAccessibleSelection();
1294 sal_Int64 nIndex
= mpTable
->getAccessibleIndex( 0, column
);
1295 mpTable
->selectAccessibleChild( nIndex
);
1300 sal_Bool SAL_CALL
AccessibleTableHeaderShape::unselectRow( sal_Int32 row
)
1303 return mpTable
->unselectRow( row
);
1306 sal_Int64 nIndex
= mpTable
->getAccessibleIndex( row
, 0 );
1307 mpTable
->deselectAccessibleChild( nIndex
);
1312 sal_Bool SAL_CALL
AccessibleTableHeaderShape::unselectColumn( sal_Int32 column
)
1315 return mpTable
->unselectColumn( column
);
1318 sal_Int64 nIndex
= mpTable
->getAccessibleIndex( 0, column
);
1319 mpTable
->deselectAccessibleChild( nIndex
);
1325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */