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/lang/IndexOutOfBoundsException.hpp>
26 #include <comphelper/accessiblewrapper.hxx>
27 #include <vcl/svapp.hxx>
29 #include <AccessibleTableShape.hxx>
30 #include <svx/sdr/table/tablecontroller.hxx>
31 #include "accessiblecell.hxx"
34 #include <unordered_map>
36 #include <cppuhelper/implbase.hxx>
37 #include <svx/svdotable.hxx>
38 #include <com/sun/star/view/XSelectionSupplier.hpp>
41 using namespace ::accessibility
;
42 using namespace sdr::table
;
43 using namespace ::com::sun::star::accessibility
;
44 using namespace ::com::sun::star::uno
;
45 using namespace ::com::sun::star::beans
;
46 using namespace ::com::sun::star::util
;
47 using namespace ::com::sun::star::lang
;
48 using namespace ::com::sun::star::drawing
;
49 using namespace ::com::sun::star::table
;
50 using namespace ::com::sun::star::container
;
52 namespace accessibility
55 typedef std::unordered_map
< Reference
< XCell
>, rtl::Reference
< AccessibleCell
> > AccessibleCellMap
;
57 class AccessibleTableShapeImpl
: public cppu::WeakImplHelper
< XModifyListener
>
60 explicit AccessibleTableShapeImpl( AccessibleShapeTreeInfo
& rShapeTreeInfo
);
62 void init( const Reference
< XAccessible
>& xAccessible
, const Reference
< XTable
>& xTable
);
65 /// @throws IndexOutOfBoundsException
66 /// @throws RuntimeException
67 Reference
< XAccessible
> getAccessibleChild(sal_Int32 i
);
68 /// @throws IndexOutOfBoundsException
69 void getColumnAndRow( sal_Int32 nChildIndex
, sal_Int32
& rnColumn
, sal_Int32
& rnRow
);
72 virtual void SAL_CALL
modified( const EventObject
& aEvent
) override
;
75 virtual void SAL_CALL
disposing( const EventObject
& Source
) override
;
77 AccessibleShapeTreeInfo
& mrShapeTreeInfo
;
78 Reference
< XTable
> mxTable
;
79 AccessibleCellMap maChildMap
;
80 Reference
< XAccessible
> mxAccessible
;
81 sal_Int32 mRowCount
, mColCount
;
82 //get the cached AccessibleCell from XCell
83 rtl::Reference
< AccessibleCell
> getAccessibleCell (const Reference
< XCell
>& xCell
);
84 /// @throws IndexOutOfBoundsException
85 /// @throws RuntimeException
86 rtl::Reference
< AccessibleCell
> getAccessibleCell (sal_Int32 nRow
, sal_Int32 nColumn
);
90 AccessibleTableShapeImpl::AccessibleTableShapeImpl( AccessibleShapeTreeInfo
& rShapeTreeInfo
)
91 : mrShapeTreeInfo( rShapeTreeInfo
)
98 void AccessibleTableShapeImpl::init( const Reference
< XAccessible
>& xAccessible
, const Reference
< XTable
>& xTable
)
100 mxAccessible
= xAccessible
;
105 Reference
< XModifyListener
> xListener( this );
106 mxTable
->addModifyListener( xListener
);
107 //register the listener with table model
108 Reference
< css::view::XSelectionSupplier
> xSelSupplier(xTable
, UNO_QUERY
);
109 Reference
< css::view::XSelectionChangeListener
> xSelListener( xAccessible
, UNO_QUERY
);
110 if (xSelSupplier
.is())
111 xSelSupplier
->addSelectionChangeListener(xSelListener
);
112 mRowCount
= mxTable
->getRowCount();
113 mColCount
= mxTable
->getColumnCount();
118 void AccessibleTableShapeImpl::dispose()
122 //remove all the cell's acc object in table's dispose.
123 for( auto& rEntry
: maChildMap
)
125 rEntry
.second
->dispose();
128 Reference
< XModifyListener
> xListener( this );
129 mxTable
->removeModifyListener( xListener
);
132 mxAccessible
.clear();
136 //get the cached AccessibleCell from XCell
137 rtl::Reference
< AccessibleCell
> AccessibleTableShapeImpl::getAccessibleCell (const Reference
< XCell
>& xCell
)
139 AccessibleCellMap::iterator
iter( maChildMap
.find( xCell
) );
141 if( iter
!= maChildMap
.end() )
143 rtl::Reference
< AccessibleCell
> xChild( (*iter
).second
.get() );
146 return rtl::Reference
< AccessibleCell
>();
149 rtl::Reference
< AccessibleCell
> AccessibleTableShapeImpl::getAccessibleCell (sal_Int32 nRow
, sal_Int32 nColumn
)
151 Reference
< XCell
> xCell( mxTable
->getCellByPosition( nColumn
, nRow
) );
152 rtl::Reference
< AccessibleCell
> xChild
= getAccessibleCell( xCell
);
154 if( !xChild
.is() && mxTable
.is() )
156 sal_Int32 nChildIndex
= mxTable
->getColumnCount() * nRow
+ nColumn
;
157 CellRef
xCellRef( dynamic_cast< Cell
* >( xCell
.get() ) );
159 rtl::Reference
< AccessibleCell
> xAccessibleCell( new AccessibleCell( mxAccessible
, xCellRef
, nChildIndex
, mrShapeTreeInfo
) );
161 xAccessibleCell
->Init();
162 maChildMap
[xCell
] = xAccessibleCell
;
164 xChild
= rtl::Reference
< AccessibleCell
>( xAccessibleCell
.get() );
170 Reference
< XAccessible
> AccessibleTableShapeImpl::getAccessibleChild(sal_Int32 nChildIndex
)
172 sal_Int32 nColumn
= 0, nRow
= 0;
173 getColumnAndRow( nChildIndex
, nColumn
, nRow
);
175 Reference
< XCell
> xCell( mxTable
->getCellByPosition( nColumn
, nRow
) );
176 AccessibleCellMap::iterator
iter( maChildMap
.find( xCell
) );
178 if( iter
!= maChildMap
.end() )
180 Reference
< XAccessible
> xChild( (*iter
).second
.get() );
185 CellRef
xCellRef( dynamic_cast< Cell
* >( xCell
.get() ) );
187 rtl::Reference
< AccessibleCell
> xAccessibleCell( new AccessibleCell( mxAccessible
, xCellRef
, nChildIndex
, mrShapeTreeInfo
) );
189 xAccessibleCell
->Init();
190 maChildMap
[xCell
] = xAccessibleCell
;
192 Reference
< XAccessible
> xChild( xAccessibleCell
.get() );
198 void AccessibleTableShapeImpl::getColumnAndRow( sal_Int32 nChildIndex
, sal_Int32
& rnColumn
, sal_Int32
& rnRow
)
201 rnColumn
= nChildIndex
;
205 const sal_Int32 nColumnCount
= mxTable
->getColumnCount();
206 while( rnColumn
>= nColumnCount
)
209 rnColumn
-= nColumnCount
;
212 if( rnRow
< mxTable
->getRowCount() )
216 throw IndexOutOfBoundsException();
220 void SAL_CALL
AccessibleTableShapeImpl::modified( const EventObject
& /*aEvent*/ )
222 if( mxTable
.is() ) try
224 // structural changes may have happened to the table, validate all accessible cell instances
225 AccessibleCellMap aTempChildMap
;
226 aTempChildMap
.swap( maChildMap
);
228 // first move all still existing cells to maChildMap again and update their index
230 const sal_Int32 nRowCount
= mxTable
->getRowCount();
231 const sal_Int32 nColCount
= mxTable
->getColumnCount();
233 bool bRowOrColumnChanged
= false;
234 if (mRowCount
!= nRowCount
|| mColCount
!= nColCount
)
236 bRowOrColumnChanged
= true;
237 mRowCount
= nRowCount
;
238 mColCount
= nColCount
;
240 sal_Int32 nChildIndex
= 0;
242 for( sal_Int32 nRow
= 0; nRow
< nRowCount
; ++nRow
)
244 for( sal_Int32 nCol
= 0; nCol
< nColCount
; ++nCol
)
246 Reference
< XCell
> xCell( mxTable
->getCellByPosition( nCol
, nRow
) );
247 AccessibleCellMap::iterator
iter( aTempChildMap
.find( xCell
) );
249 if( iter
!= aTempChildMap
.end() )
251 rtl::Reference
< AccessibleCell
> xAccessibleCell( (*iter
).second
);
252 xAccessibleCell
->setIndexInParent( nChildIndex
);
253 xAccessibleCell
->UpdateChildren();
254 // If row or column count is changed, there is split or merge, so all cell's acc name should be updated
255 if (bRowOrColumnChanged
)
257 xAccessibleCell
->SetAccessibleName(xAccessibleCell
->getAccessibleName(), AccessibleContextBase::ManuallySet
);
259 // For merged cell, add invisible & disabled state.
260 Reference
< XMergeableCell
> xMergedCell( mxTable
->getCellByPosition( nCol
, nRow
), UNO_QUERY
);
261 if (xMergedCell
.is() && xMergedCell
->isMerged())
263 xAccessibleCell
->ResetState(AccessibleStateType::VISIBLE
);
264 xAccessibleCell
->ResetState(AccessibleStateType::ENABLED
);
265 // IA2 CWS. MT: OFFSCREEN == !SHOWING, should stay consistent
266 // xAccessibleCell->SetState(AccessibleStateType::OFFSCREEN);
267 xAccessibleCell
->ResetState(AccessibleStateType::SHOWING
);
271 xAccessibleCell
->SetState(AccessibleStateType::VISIBLE
);
272 xAccessibleCell
->SetState(AccessibleStateType::ENABLED
);
273 // IA2 CWS. MT: OFFSCREEN == !SHOWING, should stay consistent
274 // xAccessibleCell->ResetState(AccessibleStateType::OFFSCREEN);
275 xAccessibleCell
->SetState(AccessibleStateType::SHOWING
);
278 // move still existing cell from temporary child map to our child map
279 maChildMap
[xCell
] = xAccessibleCell
;
280 aTempChildMap
.erase( iter
);
284 CellRef
xCellRef( dynamic_cast< Cell
* >( xCell
.get() ) );
286 rtl::Reference
< AccessibleCell
> xAccessibleCell( new AccessibleCell( mxAccessible
, xCellRef
, nChildIndex
, mrShapeTreeInfo
) );
288 xAccessibleCell
->Init();
289 maChildMap
[xCell
] = xAccessibleCell
;
296 // all accessible cell instances still left in aTempChildMap must be disposed
297 // as they are no longer part of the table
299 for( auto& rEntry
: aTempChildMap
)
301 rEntry
.second
->dispose();
303 //notify bridge to update the acc cache.
304 AccessibleTableShape
*pAccTable
= dynamic_cast <AccessibleTableShape
*> (mxAccessible
.get());
306 pAccTable
->CommitChange(AccessibleEventId::INVALIDATE_ALL_CHILDREN
, Any(), Any());
308 catch( const Exception
& )
310 OSL_FAIL("svx::AccessibleTableShape::modified(), exception caught!");
315 void SAL_CALL
AccessibleTableShapeImpl::disposing( const EventObject
& /*Source*/ )
319 AccessibleTableShape::AccessibleTableShape( const AccessibleShapeInfo
& rShapeInfo
, const AccessibleShapeTreeInfo
& rShapeTreeInfo
)
320 : AccessibleTableShape_Base(rShapeInfo
, rShapeTreeInfo
)
321 , mnPreviousSelectionCount(0)
322 , mxImpl( new AccessibleTableShapeImpl( maShapeTreeInfo
) )
327 AccessibleTableShape::~AccessibleTableShape()
332 void AccessibleTableShape::Init()
336 Reference
< XPropertySet
> xSet( mxShape
, UNO_QUERY_THROW
);
337 Reference
< XTable
> xTable( xSet
->getPropertyValue("Model"), UNO_QUERY_THROW
);
339 mxImpl
->init( this, xTable
);
343 OSL_FAIL("AccessibleTableShape::init(), exception caught?");
346 AccessibleTableShape_Base::Init();
350 SvxTableController
* AccessibleTableShape::getTableController()
352 SdrView
* pView
= maShapeTreeInfo
.GetSdrView ();
354 return dynamic_cast< SvxTableController
* >( pView
->getSelectionController().get() );
363 Any SAL_CALL
AccessibleTableShape::queryInterface( const Type
& aType
)
365 if ( aType
== cppu::UnoType
<XAccessibleTableSelection
>::get())
367 Reference
<XAccessibleTableSelection
> xThis( this );
373 return AccessibleTableShape_Base::queryInterface( aType
);
377 void SAL_CALL
AccessibleTableShape::acquire( ) throw ()
379 AccessibleTableShape_Base::acquire();
383 void SAL_CALL
AccessibleTableShape::release( ) throw ()
385 AccessibleTableShape_Base::release();
392 OUString SAL_CALL
AccessibleTableShape::getImplementationName()
394 return "com.sun.star.comp.accessibility.AccessibleTableShape";
398 OUString
AccessibleTableShape::CreateAccessibleBaseName()
404 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleChildCount( )
406 SolarMutexGuard aSolarGuard
;
407 return mxImpl
->mxTable
.is() ? mxImpl
->mxTable
->getRowCount() * mxImpl
->mxTable
->getColumnCount() : 0;
411 Reference
< XAccessible
> SAL_CALL
AccessibleTableShape::getAccessibleChild( sal_Int32 i
)
413 SolarMutexGuard aSolarGuard
;
416 return mxImpl
->getAccessibleChild( i
);
420 sal_Int16 SAL_CALL
AccessibleTableShape::getAccessibleRole()
422 return AccessibleRole::TABLE
;
426 void SAL_CALL
AccessibleTableShape::disposing()
430 // let the base do its stuff
431 AccessibleShape::disposing();
438 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleRowCount()
440 SolarMutexGuard aSolarGuard
;
441 return mxImpl
->mxTable
.is() ? mxImpl
->mxTable
->getRowCount() : 0;
445 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleColumnCount( )
447 SolarMutexGuard aSolarGuard
;
448 return mxImpl
->mxTable
.is() ? mxImpl
->mxTable
->getColumnCount() : 0;
452 OUString SAL_CALL
AccessibleTableShape::getAccessibleRowDescription( sal_Int32 nRow
)
454 checkCellPosition( 0, nRow
);
459 OUString SAL_CALL
AccessibleTableShape::getAccessibleColumnDescription( sal_Int32 nColumn
)
461 SolarMutexGuard aSolarGuard
;
462 checkCellPosition( nColumn
, 0 );
467 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleRowExtentAt( sal_Int32 nRow
, sal_Int32 nColumn
)
469 SolarMutexGuard aSolarGuard
;
470 checkCellPosition( nColumn
, nRow
);
471 if( mxImpl
->mxTable
.is() )
473 Reference
< XMergeableCell
> xCell( mxImpl
->mxTable
->getCellByPosition( nColumn
, nRow
), UNO_QUERY
);
475 return xCell
->getRowSpan();
481 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleColumnExtentAt( sal_Int32 nRow
, sal_Int32 nColumn
)
483 SolarMutexGuard aSolarGuard
;
484 checkCellPosition( nColumn
, nRow
);
485 if( mxImpl
->mxTable
.is() )
487 Reference
< XMergeableCell
> xCell( mxImpl
->mxTable
->getCellByPosition( nColumn
, nRow
), UNO_QUERY
);
489 return xCell
->getColumnSpan();
495 Reference
< XAccessibleTable
> SAL_CALL
AccessibleTableShape::getAccessibleRowHeaders( )
497 Reference
< XAccessibleTable
> xRet
;
498 SvxTableController
* pController
= getTableController();
501 if( pController
->isRowHeader() )
503 AccessibleTableHeaderShape
* pTableHeader
= new AccessibleTableHeaderShape( this, true );
504 xRet
.set( pTableHeader
);
511 Reference
< XAccessibleTable
> SAL_CALL
AccessibleTableShape::getAccessibleColumnHeaders( )
513 Reference
< XAccessibleTable
> xRet
;
514 SvxTableController
* pController
= getTableController();
517 if( pController
->isColumnHeader() )
519 AccessibleTableHeaderShape
* pTableHeader
= new AccessibleTableHeaderShape( this, false );
520 xRet
.set( pTableHeader
);
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_Int32 SAL_CALL
AccessibleTableShape::getAccessibleIndex( sal_Int32 nRow
, sal_Int32 nColumn
)
672 SolarMutexGuard aSolarGuard
;
673 checkCellPosition( nColumn
, nRow
);
674 return mxImpl
->mxTable
.is() ? (nRow
* mxImpl
->mxTable
->getColumnCount() + nColumn
) : 0;
678 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleRow( sal_Int32 nChildIndex
)
680 SolarMutexGuard aSolarGuard
;
681 sal_Int32 nColumn
= 0, nRow
= 0;
682 mxImpl
->getColumnAndRow( nChildIndex
, nColumn
, nRow
);
687 sal_Int32 SAL_CALL
AccessibleTableShape::getAccessibleColumn( sal_Int32 nChildIndex
)
689 SolarMutexGuard aSolarGuard
;
690 sal_Int32 nColumn
= 0, nRow
= 0;
691 mxImpl
->getColumnAndRow( nChildIndex
, nColumn
, nRow
);
696 // XAccessibleSelection
699 void SAL_CALL
AccessibleTableShape::selectAccessibleChild( sal_Int32 nChildIndex
)
701 SolarMutexGuard aSolarGuard
;
703 mxImpl
->getColumnAndRow( nChildIndex
, aPos
.mnCol
, aPos
.mnRow
);
705 // todo, select table shape?!?
706 SvxTableController
* pController
= getTableController();
709 CellPos
aFirstPos( aPos
), aLastPos( aPos
);
710 if( pController
->hasSelectedCells() )
712 pController
->getSelectedCells( aFirstPos
, aLastPos
);
714 aFirstPos
.mnRow
= std::min( aFirstPos
.mnRow
, aPos
.mnRow
);
715 aFirstPos
.mnCol
= std::min( aFirstPos
.mnCol
, aPos
.mnCol
);
716 aLastPos
.mnRow
= std::max( aLastPos
.mnRow
, aPos
.mnRow
);
717 aLastPos
.mnCol
= std::max( aLastPos
.mnCol
, aPos
.mnCol
);
719 pController
->setSelectedCells( aFirstPos
, aLastPos
);
724 sal_Bool SAL_CALL
AccessibleTableShape::isAccessibleChildSelected( sal_Int32 nChildIndex
)
726 SolarMutexGuard aSolarGuard
;
728 mxImpl
->getColumnAndRow( nChildIndex
, aPos
.mnCol
, aPos
.mnRow
);
730 return isAccessibleSelected(aPos
.mnRow
, aPos
.mnCol
);
734 void SAL_CALL
AccessibleTableShape::clearAccessibleSelection()
736 SolarMutexGuard aSolarGuard
;
738 SvxTableController
* pController
= getTableController();
740 pController
->clearSelection();
744 void SAL_CALL
AccessibleTableShape::selectAllAccessibleChildren()
746 SolarMutexGuard aSolarGuard
;
748 // todo: force selection of shape?
749 SvxTableController
* pController
= getTableController();
751 pController
->selectAll();
755 sal_Int32 SAL_CALL
AccessibleTableShape::getSelectedAccessibleChildCount()
757 SolarMutexGuard aSolarGuard
;
759 SvxTableController
* pController
= getTableController();
760 if( pController
&& pController
->hasSelectedCells() )
762 CellPos aFirstPos
, aLastPos
;
763 pController
->getSelectedCells( aFirstPos
, aLastPos
);
765 const sal_Int32 nSelectedColumns
= std::max( sal_Int32(0), aLastPos
.mnCol
- aFirstPos
.mnCol
) + 1;
766 const sal_Int32 nSelectedRows
= std::max( sal_Int32(0), aLastPos
.mnRow
- aFirstPos
.mnRow
) + 1;
767 return nSelectedRows
* nSelectedColumns
;
774 Reference
< XAccessible
> SAL_CALL
AccessibleTableShape::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex
)
776 SolarMutexGuard aSolarGuard
;
778 if( nSelectedChildIndex
< 0 )
779 throw IndexOutOfBoundsException();
781 sal_Int32 nChildIndex
= GetIndexOfSelectedChild( nSelectedChildIndex
);
783 if( nChildIndex
< 0 )
784 throw IndexOutOfBoundsException();
786 if ( nChildIndex
>= getAccessibleChildCount() )
788 throw IndexOutOfBoundsException();
791 return getAccessibleChild( nChildIndex
);
795 void SAL_CALL
AccessibleTableShape::deselectAccessibleChild( sal_Int32 nChildIndex
)
797 SolarMutexGuard aSolarGuard
;
799 mxImpl
->getColumnAndRow( nChildIndex
, aPos
.mnCol
, aPos
.mnRow
);
801 // todo, select table shape?!?
802 SvxTableController
* pController
= getTableController();
803 if( pController
&& pController
->hasSelectedCells() )
805 CellPos aFirstPos
, aLastPos
;
806 pController
->getSelectedCells( aFirstPos
, aLastPos
);
808 // create a selection where aPos is not part of anymore
809 aFirstPos
.mnRow
= std::min( aFirstPos
.mnRow
, aPos
.mnRow
+1 );
810 aFirstPos
.mnCol
= std::min( aFirstPos
.mnCol
, aPos
.mnCol
+1 );
811 aLastPos
.mnRow
= std::max( aLastPos
.mnRow
, aPos
.mnRow
-1 );
812 aLastPos
.mnCol
= std::max( aLastPos
.mnCol
, aPos
.mnCol
-1 );
814 // new selection may be invalid (child to deselect is not at a border of the selection but in between)
815 if( (aFirstPos
.mnRow
> aLastPos
.mnRow
) || (aFirstPos
.mnCol
> aLastPos
.mnCol
) )
816 pController
->clearSelection(); // if selection is invalid, clear all
818 pController
->setSelectedCells( aFirstPos
, aLastPos
);
822 // XAccessibleTableSelection
823 sal_Bool SAL_CALL
AccessibleTableShape::selectRow( sal_Int32 row
)
825 SolarMutexGuard aSolarGuard
;
826 SvxTableController
* pController
= getTableController();
829 return pController
->selectRow( row
);
832 sal_Bool SAL_CALL
AccessibleTableShape::selectColumn( sal_Int32 column
)
834 SolarMutexGuard aSolarGuard
;
835 SvxTableController
* pController
= getTableController();
838 return pController
->selectColumn( column
);
841 sal_Bool SAL_CALL
AccessibleTableShape::unselectRow( sal_Int32 row
)
843 SolarMutexGuard aSolarGuard
;
844 SvxTableController
* pController
= getTableController();
847 return pController
->deselectRow( row
);
850 sal_Bool SAL_CALL
AccessibleTableShape::unselectColumn( sal_Int32 column
)
852 SolarMutexGuard aSolarGuard
;
853 SvxTableController
* pController
= getTableController();
856 return pController
->deselectColumn( column
);
859 sal_Int32
AccessibleTableShape::GetIndexOfSelectedChild(
860 sal_Int32 nSelectedChildIndex
) const
862 sal_Int32 nChildren
= const_cast<AccessibleTableShape
*>(this)->getAccessibleChildCount();
864 if( nSelectedChildIndex
>= nChildren
)
868 while( n
< nChildren
)
870 if( const_cast<AccessibleTableShape
*>(this)->isAccessibleChildSelected( n
) )
872 if( 0 == nSelectedChildIndex
)
875 --nSelectedChildIndex
;
880 return n
< nChildren
? n
: -1;
882 void AccessibleTableShape::getColumnAndRow( sal_Int32 nChildIndex
, sal_Int32
& rnColumn
, sal_Int32
& rnRow
)
884 mxImpl
->getColumnAndRow(nChildIndex
, rnColumn
, rnRow
);
887 // XSelectionChangeListener
889 AccessibleTableShape::disposing (const EventObject
& aEvent
)
891 AccessibleShape::disposing(aEvent
);
893 void SAL_CALL
AccessibleTableShape::selectionChanged (const EventObject
& rEvent
)
895 //sdr::table::CellRef xCellRef = static_cast< sdr::table::CellRef > (rEvent.Source);
896 Reference
< XCell
> xCell(rEvent
.Source
, UNO_QUERY
);
899 rtl::Reference
< AccessibleCell
> xAccCell
= mxImpl
->getAccessibleCell( xCell
);
902 sal_Int32 nIndex
= xAccCell
->getAccessibleIndexInParent(),
903 nCount
= getSelectedAccessibleChildCount();
904 bool bSelected
= isAccessibleChildSelected(nIndex
);
905 if (mnPreviousSelectionCount
== 0 && nCount
> 0 && bSelected
)
907 xAccCell
->SetState(AccessibleStateType::SELECTED
);
908 xAccCell
->CommitChange(AccessibleEventId::SELECTION_CHANGED
, Any(), Any());
912 xAccCell
->SetState(AccessibleStateType::SELECTED
);
913 xAccCell
->CommitChange(AccessibleEventId::SELECTION_CHANGED_ADD
, Any(), Any());
917 xAccCell
->ResetState(AccessibleStateType::SELECTED
);
918 xAccCell
->CommitChange(AccessibleEventId::SELECTION_CHANGED_REMOVE
, Any(), Any());
920 mnPreviousSelectionCount
= nCount
;
924 // Get the currently active cell which is text editing
925 AccessibleCell
* AccessibleTableShape::GetActiveAccessibleCell()
927 rtl::Reference
< AccessibleCell
> xAccCell
;
928 AccessibleCell
* pAccCell
= nullptr;
929 SvxTableController
* pController
= getTableController();
932 sdr::table::SdrTableObj
* pTableObj
= pController
->GetTableObj();
935 const sdr::table::CellRef
& xCellRef (pTableObj
->getActiveCell());
941 pTableObj
->getActiveCellPos( rPos
);
942 xAccCell
= mxImpl
->getAccessibleCell( rPos
.mnRow
, rPos
.mnCol
);
944 pAccCell
= xAccCell
.get();
946 catch ( IndexOutOfBoundsException
& ) {}
953 //If current active cell is in editing, the focus state should be set to internal text
954 bool AccessibleTableShape::SetState (sal_Int16 aState
)
956 if( aState
== AccessibleStateType::FOCUSED
)
958 AccessibleCell
* pActiveAccessibleCell
= GetActiveAccessibleCell();
959 if( pActiveAccessibleCell
!= nullptr )
960 return pActiveAccessibleCell
->SetState(aState
);
963 return AccessibleShape::SetState (aState
);
966 //If current active cell is in editing, the focus state should be reset to internal text
967 bool AccessibleTableShape::ResetState (sal_Int16 aState
)
969 if( aState
== AccessibleStateType::FOCUSED
)
971 AccessibleCell
* pActiveAccessibleCell
= GetActiveAccessibleCell();
972 if( pActiveAccessibleCell
!= nullptr )
973 return pActiveAccessibleCell
->ResetState(aState
);
976 return AccessibleShape::ResetState (aState
);
979 bool AccessibleTableShape::SetStateDirectly (sal_Int16 aState
)
981 return AccessibleContextBase::SetState (aState
);
984 bool AccessibleTableShape::ResetStateDirectly (sal_Int16 aState
)
986 return AccessibleContextBase::ResetState (aState
);
989 void AccessibleTableShape::checkCellPosition( sal_Int32 nCol
, sal_Int32 nRow
)
991 if( (nCol
>= 0) && (nRow
>= 0) && mxImpl
->mxTable
.is() && (nCol
< mxImpl
->mxTable
->getColumnCount()) && (nRow
< mxImpl
->mxTable
->getRowCount()) )
994 throw IndexOutOfBoundsException();
997 AccessibleTableHeaderShape::AccessibleTableHeaderShape( AccessibleTableShape
* pTable
, bool bRow
)
1003 AccessibleTableHeaderShape::~AccessibleTableHeaderShape()
1009 Reference
< XAccessibleContext
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleContext()
1014 // XAccessibleContext
1015 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleChildCount( )
1017 return getAccessibleRowCount() * getAccessibleColumnCount();
1020 Reference
< XAccessible
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleChild( sal_Int32 i
)
1022 return mpTable
->getAccessibleChild( i
);
1025 Reference
< XAccessible
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleParent()
1027 Reference
< XAccessible
> XParent
;
1031 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleIndexInParent()
1036 sal_Int16 SAL_CALL
AccessibleTableHeaderShape::getAccessibleRole()
1038 return mpTable
->getAccessibleRole();
1041 OUString SAL_CALL
AccessibleTableHeaderShape::getAccessibleDescription()
1043 return mpTable
->getAccessibleDescription();
1046 OUString SAL_CALL
AccessibleTableHeaderShape::getAccessibleName()
1048 return mpTable
->getAccessibleName();
1051 Reference
< XAccessibleStateSet
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleStateSet()
1053 return mpTable
->getAccessibleStateSet();
1056 Reference
< XAccessibleRelationSet
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleRelationSet()
1058 return mpTable
->getAccessibleRelationSet();
1061 Locale SAL_CALL
AccessibleTableHeaderShape::getLocale()
1063 return mpTable
->getLocale();
1066 //XAccessibleComponent
1067 sal_Bool SAL_CALL
AccessibleTableHeaderShape::containsPoint ( const css::awt::Point
& aPoint
)
1069 return mpTable
->containsPoint( aPoint
);
1072 Reference
< XAccessible
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleAtPoint ( const css::awt::Point
& aPoint
)
1074 return mpTable
->getAccessibleAtPoint( aPoint
);
1077 css::awt::Rectangle SAL_CALL
AccessibleTableHeaderShape::getBounds()
1079 return mpTable
->getBounds();
1082 css::awt::Point SAL_CALL
AccessibleTableHeaderShape::getLocation()
1084 return mpTable
->getLocation();
1087 css::awt::Point SAL_CALL
AccessibleTableHeaderShape::getLocationOnScreen()
1089 return mpTable
->getLocationOnScreen();
1092 css::awt::Size SAL_CALL
AccessibleTableHeaderShape::getSize()
1094 return mpTable
->getSize();
1097 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getForeground()
1099 return mpTable
->getForeground();
1102 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getBackground()
1104 return mpTable
->getBackground();
1107 void SAL_CALL
AccessibleTableHeaderShape::grabFocus()
1109 mpTable
->grabFocus();
1112 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleRowCount()
1114 return mbRow
? 1 : mpTable
->getAccessibleRowCount();
1117 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleColumnCount()
1119 return !mbRow
? 1 : mpTable
->getAccessibleColumnCount();
1122 OUString SAL_CALL
AccessibleTableHeaderShape::getAccessibleRowDescription( sal_Int32 nRow
)
1124 return mpTable
->getAccessibleRowDescription( nRow
);
1127 OUString SAL_CALL
AccessibleTableHeaderShape::getAccessibleColumnDescription( sal_Int32 nColumn
)
1129 return mpTable
->getAccessibleColumnDescription( nColumn
);
1132 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleRowExtentAt( sal_Int32 nRow
, sal_Int32 nColumn
)
1134 return mpTable
->getAccessibleRowExtentAt( nRow
, nColumn
);
1137 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleColumnExtentAt( sal_Int32 nRow
, sal_Int32 nColumn
)
1139 return mpTable
->getAccessibleColumnExtentAt( nRow
, nColumn
);
1142 Reference
< XAccessibleTable
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleRowHeaders( )
1144 Reference
< XAccessibleTable
> xRet
;
1148 Reference
< XAccessibleTable
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleColumnHeaders( )
1150 Reference
< XAccessibleTable
> xRet
;
1154 Sequence
< sal_Int32
> SAL_CALL
AccessibleTableHeaderShape::getSelectedAccessibleRows( )
1156 sal_Int32 nRow
= getAccessibleRowCount();
1157 ::std::vector
<bool> aSelected( nRow
, true );
1158 sal_Int32 nCount
= nRow
;
1159 for( sal_Int32 i
= 0; i
< nRow
; i
++ )
1163 aSelected
[i
] = isAccessibleRowSelected( i
);
1167 return Sequence
< sal_Int32
>();
1173 Sequence
< sal_Int32
> aRet( nCount
);
1174 sal_Int32
*pRet
= aRet
.getArray();
1176 size_t nSize
= aSelected
.size();
1177 for( size_t i
=0; i
< nSize
&& nPos
< nCount
; i
++ )
1189 Sequence
< sal_Int32
> SAL_CALL
AccessibleTableHeaderShape::getSelectedAccessibleColumns( )
1191 sal_Int32 nColumn
= getAccessibleColumnCount();
1192 ::std::vector
<bool> aSelected( nColumn
, true );
1193 sal_Int32 nCount
= nColumn
;
1194 for( sal_Int32 i
= 0; i
< nColumn
; i
++ )
1198 aSelected
[i
] = isAccessibleColumnSelected( i
);
1202 return Sequence
< sal_Int32
>();
1208 Sequence
< sal_Int32
> aRet( nCount
);
1209 sal_Int32
*pRet
= aRet
.getArray();
1211 size_t nSize
= aSelected
.size();
1212 for( size_t i
=0; i
< nSize
&& nPos
< nCount
; i
++ )
1224 sal_Bool SAL_CALL
AccessibleTableHeaderShape::isAccessibleRowSelected( sal_Int32 nRow
)
1226 return mpTable
->isAccessibleRowSelected( nRow
);
1229 sal_Bool SAL_CALL
AccessibleTableHeaderShape::isAccessibleColumnSelected( sal_Int32 nColumn
)
1231 return mpTable
->isAccessibleColumnSelected( nColumn
);
1234 Reference
< XAccessible
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleCellAt( sal_Int32 nRow
, sal_Int32 nColumn
)
1236 return mpTable
->getAccessibleCellAt( nRow
, nColumn
);
1239 Reference
< XAccessible
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleCaption( )
1241 return mpTable
->getAccessibleCaption();
1244 Reference
< XAccessible
> SAL_CALL
AccessibleTableHeaderShape::getAccessibleSummary( )
1246 return mpTable
->getAccessibleSummary();
1249 sal_Bool SAL_CALL
AccessibleTableHeaderShape::isAccessibleSelected( sal_Int32 nRow
, sal_Int32 nColumn
)
1251 return mpTable
->isAccessibleSelected( nRow
, nColumn
);
1254 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleIndex( sal_Int32 nRow
, sal_Int32 nColumn
)
1256 return mpTable
->getAccessibleIndex( nRow
, nColumn
);
1259 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleRow( sal_Int32 nChildIndex
)
1261 return mpTable
->getAccessibleRow( nChildIndex
);
1264 sal_Int32 SAL_CALL
AccessibleTableHeaderShape::getAccessibleColumn( sal_Int32 nChildIndex
)
1266 return mpTable
->getAccessibleColumn( nChildIndex
);
1269 // XAccessibleTableSelection
1270 sal_Bool SAL_CALL
AccessibleTableHeaderShape::selectRow( sal_Int32 row
)
1273 return mpTable
->selectRow( row
);
1276 mpTable
->clearAccessibleSelection();
1277 sal_Int32 nIndex
= mpTable
->getAccessibleIndex( row
, 0 );
1278 mpTable
->selectAccessibleChild( nIndex
);
1283 sal_Bool SAL_CALL
AccessibleTableHeaderShape::selectColumn( sal_Int32 column
)
1286 return mpTable
->selectColumn( column
);
1289 mpTable
->clearAccessibleSelection();
1290 sal_Int32 nIndex
= mpTable
->getAccessibleIndex( 0, column
);
1291 mpTable
->selectAccessibleChild( nIndex
);
1296 sal_Bool SAL_CALL
AccessibleTableHeaderShape::unselectRow( sal_Int32 row
)
1299 return mpTable
->unselectRow( row
);
1302 sal_Int32 nIndex
= mpTable
->getAccessibleIndex( row
, 0 );
1303 mpTable
->deselectAccessibleChild( nIndex
);
1308 sal_Bool SAL_CALL
AccessibleTableHeaderShape::unselectColumn( sal_Int32 column
)
1311 return mpTable
->unselectColumn( column
);
1314 sal_Int32 nIndex
= mpTable
->getAccessibleIndex( 0, column
);
1315 mpTable
->deselectAccessibleChild( nIndex
);
1321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */