bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / table / accessibletableshape.cxx
bloba0841f0b4ce1feb02d66223fb8735fd816161b21
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <com/sun/star/table/XMergeableCell.hpp>
22 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
23 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
25 #include <comphelper/accessiblewrapper.hxx>
26 #include <osl/mutex.hxx>
27 #include <vcl/svapp.hxx>
29 #include <AccessibleTableShape.hxx>
30 #include <svx/sdr/table/tablecontroller.hxx>
31 #include "accessiblecell.hxx"
33 #include <algorithm>
35 #include <cppuhelper/implbase1.hxx>
36 #include <svx/svdotable.hxx>
37 #include <com/sun/star/view/XSelectionSupplier.hpp>
40 using namespace ::accessibility;
41 using namespace sdr::table;
42 using namespace ::com::sun::star::accessibility;
43 using namespace ::com::sun::star::uno;
44 using namespace ::com::sun::star::beans;
45 using namespace ::com::sun::star::util;
46 using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star::drawing;
48 using namespace ::com::sun::star::table;
49 using namespace ::com::sun::star::container;
51 namespace accessibility
54 struct hash
56 std::size_t operator()( const Reference< XCell >& xCell ) const
58 return std::size_t( xCell.get() );
62 typedef std::unordered_map< Reference< XCell >, rtl::Reference< AccessibleCell >, hash > AccessibleCellMap;
64 class AccessibleTableShapeImpl : public cppu::WeakImplHelper1< XModifyListener >
66 public:
67 AccessibleTableShapeImpl( AccessibleShapeTreeInfo& rShapeTreeInfo );
69 void init( const Reference< XAccessible>& xAccessible, const Reference< XTable >& xTable );
70 void dispose();
72 Reference< XAccessible > getAccessibleChild(sal_Int32 i) throw (IndexOutOfBoundsException, RuntimeException);
73 void getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow ) throw (IndexOutOfBoundsException );
75 // XModifyListener
76 virtual void SAL_CALL modified( const EventObject& aEvent ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
78 // XEventListener
79 virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
81 AccessibleShapeTreeInfo& mrShapeTreeInfo;
82 Reference< XTable > mxTable;
83 AccessibleCellMap maChildMap;
84 Reference< XAccessible> mxAccessible;
85 sal_Int32 mRowCount, mColCount;
86 //get the cached AccessibleCell from XCell
87 Reference< AccessibleCell > getAccessibleCell (Reference< XCell > xCell);
92 AccessibleTableShapeImpl::AccessibleTableShapeImpl( AccessibleShapeTreeInfo& rShapeTreeInfo )
93 : mrShapeTreeInfo( rShapeTreeInfo )
94 , mRowCount(0)
95 , mColCount(0)
101 void AccessibleTableShapeImpl::init( const Reference< XAccessible>& xAccessible, const Reference< XTable >& xTable )
103 mxAccessible = xAccessible;
104 mxTable = xTable;
106 if( mxTable.is() )
108 Reference< XModifyListener > xListener( this );
109 mxTable->addModifyListener( xListener );
110 //register the listener with table model
111 Reference< ::com::sun::star::view::XSelectionSupplier > xSelSupplier(xTable, UNO_QUERY);
112 Reference< ::com::sun::star::view::XSelectionChangeListener > xSelListener( xAccessible, UNO_QUERY );
113 if (xSelSupplier.is())
114 xSelSupplier->addSelectionChangeListener(xSelListener);
115 mRowCount = mxTable->getRowCount();
116 mColCount = mxTable->getColumnCount();
122 void AccessibleTableShapeImpl::dispose()
124 if( mxTable.is() )
126 //remove all the cell's acc object in table's dispose.
127 for( AccessibleCellMap::iterator iter( maChildMap.begin() ); iter != maChildMap.end(); ++iter )
129 (*iter).second->dispose();
131 maChildMap.clear();
132 Reference< XModifyListener > xListener( this );
133 mxTable->removeModifyListener( xListener );
134 mxTable.clear();
136 mxAccessible.clear();
140 //get the cached AccessibleCell from XCell
141 Reference< AccessibleCell > AccessibleTableShapeImpl::getAccessibleCell (Reference< XCell > xCell)
143 AccessibleCellMap::iterator iter( maChildMap.find( xCell ) );
145 if( iter != maChildMap.end() )
147 Reference< AccessibleCell > xChild( (*iter).second.get() );
148 return xChild;
150 return Reference< AccessibleCell >();
154 Reference< XAccessible > AccessibleTableShapeImpl::getAccessibleChild(sal_Int32 nChildIndex)
155 throw (IndexOutOfBoundsException, RuntimeException)
157 sal_Int32 nColumn = 0, nRow = 0;
158 getColumnAndRow( nChildIndex, nColumn, nRow );
160 Reference< XCell > xCell( mxTable->getCellByPosition( nColumn, nRow ) );
161 AccessibleCellMap::iterator iter( maChildMap.find( xCell ) );
163 if( iter != maChildMap.end() )
165 Reference< XAccessible > xChild( (*iter).second.get() );
166 return xChild;
168 else
170 CellRef xCellRef( dynamic_cast< Cell* >( xCell.get() ) );
172 rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCellRef, nChildIndex, mrShapeTreeInfo ) );
174 xAccessibleCell->Init();
175 maChildMap[xCell] = xAccessibleCell;
177 Reference< XAccessible > xChild( xAccessibleCell.get() );
178 return xChild;
184 void AccessibleTableShapeImpl::getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow ) throw (IndexOutOfBoundsException )
186 rnRow = 0;
187 rnColumn = nChildIndex;
189 if( mxTable.is() )
191 const sal_Int32 nColumnCount = mxTable->getColumnCount();
192 while( rnColumn >= nColumnCount )
194 rnRow++;
195 rnColumn -= nColumnCount;
198 if( rnRow < mxTable->getRowCount() )
199 return;
202 throw IndexOutOfBoundsException();
205 // XModifyListener
206 void SAL_CALL AccessibleTableShapeImpl::modified( const EventObject& /*aEvent*/ ) throw (RuntimeException, std::exception)
208 if( mxTable.is() ) try
210 // structural changes may have happened to the table, validate all accessible cell instances
211 AccessibleCellMap aTempChildMap;
212 aTempChildMap.swap( maChildMap );
214 // first move all still existing cells to maChildMap again and update their index
216 const sal_Int32 nRowCount = mxTable->getRowCount();
217 const sal_Int32 nColCount = mxTable->getColumnCount();
219 bool bRowOrColumnChanged = false;
220 if (mRowCount != nRowCount || mColCount != nColCount )
222 bRowOrColumnChanged = true;
223 mRowCount = nRowCount;
224 mColCount = nColCount;
226 sal_Int32 nChildIndex = 0;
228 for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
230 for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
232 Reference< XCell > xCell( mxTable->getCellByPosition( nCol, nRow ) );
233 AccessibleCellMap::iterator iter( aTempChildMap.find( xCell ) );
235 if( iter != aTempChildMap.end() )
237 rtl::Reference< AccessibleCell > xAccessibleCell( (*iter).second );
238 xAccessibleCell->setIndexInParent( nChildIndex );
239 xAccessibleCell->UpdateChildren();
240 // If row or column count is changed, there is split or merge, so all cell's acc name should be updated
241 if (bRowOrColumnChanged)
243 xAccessibleCell->SetAccessibleName(xAccessibleCell->getAccessibleName(), AccessibleContextBase::ManuallySet);
245 // For merged cell, add invisible & disabled state.
246 Reference< XMergeableCell > xMergedCell( mxTable->getCellByPosition( nCol, nRow ), UNO_QUERY );
247 if (xMergedCell.is() && xMergedCell->isMerged())
249 xAccessibleCell->ResetState(AccessibleStateType::VISIBLE);
250 xAccessibleCell->ResetState(AccessibleStateType::ENABLED);
251 // IA2 CWS. MT: OFFSCREEN == !SHOWING, should stay consistent
252 // xAccessibleCell->SetState(AccessibleStateType::OFFSCREEN);
253 xAccessibleCell->ResetState(AccessibleStateType::SHOWING);
255 else
257 xAccessibleCell->SetState(AccessibleStateType::VISIBLE);
258 xAccessibleCell->SetState(AccessibleStateType::ENABLED);
259 // IA2 CWS. MT: OFFSCREEN == !SHOWING, should stay consistent
260 // xAccessibleCell->ResetState(AccessibleStateType::OFFSCREEN);
261 xAccessibleCell->SetState(AccessibleStateType::SHOWING);
264 // move still existing cell from temporary child map to our child map
265 maChildMap[xCell] = xAccessibleCell;
266 aTempChildMap.erase( iter );
268 else
270 CellRef xCellRef( dynamic_cast< Cell* >( xCell.get() ) );
272 rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCellRef, nChildIndex, mrShapeTreeInfo ) );
274 xAccessibleCell->Init();
275 maChildMap[xCell] = xAccessibleCell;
278 ++nChildIndex;
282 // all accessible cell instances still left in aTempChildMap must be disposed
283 // as they are no longer part of the table
285 for( AccessibleCellMap::iterator iter( aTempChildMap.begin() ); iter != aTempChildMap.end(); ++iter )
287 (*iter).second->dispose();
289 //notify bridge to update the acc cache.
290 AccessibleTableShape *pAccTable = dynamic_cast <AccessibleTableShape *> (mxAccessible.get());
291 if (pAccTable)
292 pAccTable->CommitChange(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
294 catch( const Exception& )
296 OSL_FAIL("svx::AccessibleTableShape::modified(), exception caught!");
300 // XEventListener
301 void SAL_CALL AccessibleTableShapeImpl::disposing( const EventObject& /*Source*/ ) throw (RuntimeException, std::exception)
305 AccessibleTableShape::AccessibleTableShape( const AccessibleShapeInfo& rShapeInfo, const AccessibleShapeTreeInfo& rShapeTreeInfo)
306 : AccessibleTableShape_Base(rShapeInfo, rShapeTreeInfo)
307 , mnPreviousSelectionCount(0)
308 , mxImpl( new AccessibleTableShapeImpl( maShapeTreeInfo ) )
314 AccessibleTableShape::~AccessibleTableShape()
320 void AccessibleTableShape::Init()
324 Reference< XPropertySet > xSet( mxShape, UNO_QUERY_THROW );
325 Reference< XTable > xTable( xSet->getPropertyValue("Model"), UNO_QUERY_THROW );
327 mxImpl->init( this, xTable );
329 catch( Exception& )
331 OSL_FAIL("AccessibleTableShape::init(), exception caught?");
334 AccessibleTableShape_Base::Init();
339 SvxTableController* AccessibleTableShape::getTableController()
341 SdrView* pView = maShapeTreeInfo.GetSdrView ();
342 if( pView )
343 return dynamic_cast< SvxTableController* >( pView->getSelectionController().get() );
344 else
345 return 0;
349 // XInterface
352 Any SAL_CALL AccessibleTableShape::queryInterface( const Type& aType ) throw (RuntimeException, std::exception)
354 if ( aType == cppu::UnoType<XAccessibleTableSelection>::get())
356 Reference<XAccessibleTableSelection> xThis( this );
357 Any aRet;
358 aRet <<= xThis;
359 return aRet;
361 else
362 return AccessibleTableShape_Base::queryInterface( aType );
367 void SAL_CALL AccessibleTableShape::acquire( ) throw ()
369 AccessibleTableShape_Base::acquire();
374 void SAL_CALL AccessibleTableShape::release( ) throw ()
376 AccessibleTableShape_Base::release();
380 // XAccessible
383 Reference< XAccessibleContext > SAL_CALL AccessibleTableShape::getAccessibleContext() throw (RuntimeException, std::exception)
385 return AccessibleShape::getAccessibleContext ();
389 OUString SAL_CALL AccessibleTableShape::getImplementationName() throw (RuntimeException, std::exception)
391 return OUString( "com.sun.star.comp.accessibility.AccessibleTableShape" );
396 OUString AccessibleTableShape::CreateAccessibleBaseName() throw (RuntimeException)
398 return OUString("TableShape");
403 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleChildCount( ) throw(RuntimeException, std::exception)
405 SolarMutexGuard aSolarGuard;
406 return mxImpl->mxTable.is() ? mxImpl->mxTable->getRowCount() * mxImpl->mxTable->getColumnCount() : 0;
410 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleChild( sal_Int32 i ) throw(IndexOutOfBoundsException, RuntimeException, std::exception)
412 SolarMutexGuard aSolarGuard;
413 ThrowIfDisposed();
415 return mxImpl->getAccessibleChild( i );
419 Reference< XAccessibleRelationSet > SAL_CALL AccessibleTableShape::getAccessibleRelationSet( ) throw (RuntimeException, std::exception)
421 return AccessibleShape::getAccessibleRelationSet( );
426 sal_Int16 SAL_CALL AccessibleTableShape::getAccessibleRole() throw (RuntimeException, std::exception)
428 return AccessibleRole::TABLE;
433 void SAL_CALL AccessibleTableShape::disposing()
435 mxImpl->dispose();
437 // let the base do it's stuff
438 AccessibleShape::disposing();
442 // XAccessibleTable
445 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRowCount() throw (RuntimeException, std::exception)
447 SolarMutexGuard aSolarGuard;
448 return mxImpl->mxTable.is() ? mxImpl->mxTable->getRowCount() : 0;
453 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumnCount( ) throw (RuntimeException, std::exception)
455 SolarMutexGuard aSolarGuard;
456 return mxImpl->mxTable.is() ? mxImpl->mxTable->getColumnCount() : 0;
461 OUString SAL_CALL AccessibleTableShape::getAccessibleRowDescription( sal_Int32 nRow ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
463 checkCellPosition( 0, nRow );
464 return OUString();
469 OUString SAL_CALL AccessibleTableShape::getAccessibleColumnDescription( sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
471 SolarMutexGuard aSolarGuard;
472 checkCellPosition( nColumn, 0 );
473 return OUString();
478 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
480 SolarMutexGuard aSolarGuard;
481 checkCellPosition( nColumn, nRow );
482 if( mxImpl->mxTable.is() )
484 Reference< XMergeableCell > xCell( mxImpl->mxTable->getCellByPosition( nColumn, nRow ), UNO_QUERY );
485 if( xCell.is() )
486 return xCell->getRowSpan();
488 return 1;
493 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
495 SolarMutexGuard aSolarGuard;
496 checkCellPosition( nColumn, nRow );
497 if( mxImpl->mxTable.is() )
499 Reference< XMergeableCell > xCell( mxImpl->mxTable->getCellByPosition( nColumn, nRow ), UNO_QUERY );
500 if( xCell.is() )
501 return xCell->getColumnSpan();
503 return 1;
508 Reference< XAccessibleTable > SAL_CALL AccessibleTableShape::getAccessibleRowHeaders( ) throw (RuntimeException, std::exception)
510 Reference< XAccessibleTable > xRet;
511 SvxTableController* pController = getTableController();
512 if( pController )
514 if( pController->isRowHeader() )
516 AccessibleTableHeaderShape* pTableHeader = new AccessibleTableHeaderShape( this, true );
517 xRet.set( pTableHeader );
520 return xRet;
525 Reference< XAccessibleTable > SAL_CALL AccessibleTableShape::getAccessibleColumnHeaders( ) throw (RuntimeException, std::exception)
527 Reference< XAccessibleTable > xRet;
528 SvxTableController* pController = getTableController();
529 if( pController )
531 if( pController->isColumnHeader() )
533 AccessibleTableHeaderShape* pTableHeader = new AccessibleTableHeaderShape( this, false );
534 xRet.set( pTableHeader );
537 return xRet;
542 Sequence< sal_Int32 > SAL_CALL AccessibleTableShape::getSelectedAccessibleRows( ) throw (RuntimeException, std::exception)
544 sal_Int32 nRow = getAccessibleRowCount();
545 ::std::vector< sal_Bool > aSelected( nRow, sal_True );
546 sal_Int32 nCount = nRow;
547 for( sal_Int32 i = 0; i < nRow; i++ )
551 aSelected[i] = isAccessibleRowSelected( i );
553 catch( ... )
555 return Sequence< sal_Int32 >();
558 if( !aSelected[i] )
559 nCount--;
561 Sequence < sal_Int32 > aRet( nCount );
562 sal_Int32 *pRet = aRet.getArray();
563 sal_Int32 nPos = 0;
564 size_t nSize = aSelected.size();
565 for( size_t i=0; i < nSize && nPos < nCount; i++ )
567 if( aSelected[i] )
569 *pRet++ = i;
570 nPos++;
574 return aRet;
579 Sequence< sal_Int32 > SAL_CALL AccessibleTableShape::getSelectedAccessibleColumns( ) throw (RuntimeException, std::exception)
581 sal_Int32 nColumn = getAccessibleColumnCount();
582 ::std::vector< sal_Bool > aSelected( nColumn, sal_True );
583 sal_Int32 nCount = nColumn;
584 for( sal_Int32 i = 0; i < nColumn; i++ )
588 aSelected[i] = isAccessibleColumnSelected( i );
590 catch( ... )
592 return Sequence< sal_Int32 >();
595 if( !aSelected[i] )
596 nCount--;
598 Sequence < sal_Int32 > aRet( nCount );
599 sal_Int32 *pRet = aRet.getArray();
600 sal_Int32 nPos = 0;
601 size_t nSize = aSelected.size();
602 for( size_t i=0; i < nSize && nPos < nCount; i++ )
604 if( aSelected[i] )
606 *pRet++ = i;
607 nPos++;
611 return aRet;
616 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleRowSelected( sal_Int32 nRow ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
618 SolarMutexGuard aSolarGuard;
619 checkCellPosition( 0, nRow );
620 SvxTableController* pController = getTableController();
621 if( pController )
623 return pController->isRowSelected( nRow );
625 return sal_False;
630 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleColumnSelected( sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
632 SolarMutexGuard aSolarGuard;
633 checkCellPosition( nColumn, 0 );
634 SvxTableController* pController = getTableController();
635 if( pController )
637 return pController->isColumnSelected( nColumn );
639 return sal_False;
644 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
646 SolarMutexGuard aSolarGuard;
647 checkCellPosition( nColumn, nRow );
649 sal_Int32 nChildIndex = 0;
650 if( mxImpl->mxTable.is() )
651 nChildIndex = mxImpl->mxTable->getColumnCount() * nRow + nColumn;
653 return getAccessibleChild( nChildIndex );
658 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleCaption( ) throw (RuntimeException, std::exception)
660 Reference< XAccessible > xRet;
661 return xRet;
666 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleSummary( ) throw (RuntimeException, std::exception)
668 Reference< XAccessible > xRet;
669 return xRet;
674 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
676 SolarMutexGuard aSolarGuard;
677 checkCellPosition( nColumn, nRow );
679 SvxTableController* pController = getTableController();
680 if( pController && pController->hasSelectedCells() )
682 CellPos aFirstPos, aLastPos;
683 pController->getSelectedCells( aFirstPos, aLastPos );
684 if( (aFirstPos.mnRow <= nRow) && (aFirstPos.mnCol <= nColumn) && (nRow <= aLastPos.mnRow) && (nColumn <= aLastPos.mnCol) )
685 return sal_True;
688 return sal_False;
693 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
695 SolarMutexGuard aSolarGuard;
696 checkCellPosition( nColumn, nRow );
697 return mxImpl->mxTable.is() ? (nRow * mxImpl->mxTable->getColumnCount() + nColumn) : 0;
702 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRow( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
704 SolarMutexGuard aSolarGuard;
705 sal_Int32 nColumn = 0, nRow = 0;
706 mxImpl->getColumnAndRow( nChildIndex, nColumn, nRow );
707 return nRow;
712 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumn( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
714 SolarMutexGuard aSolarGuard;
715 sal_Int32 nColumn = 0, nRow = 0;
716 mxImpl->getColumnAndRow( nChildIndex, nColumn, nRow );
717 return nColumn;
721 // XAccessibleSelection
724 void SAL_CALL AccessibleTableShape::selectAccessibleChild( sal_Int32 nChildIndex ) throw ( IndexOutOfBoundsException, RuntimeException, std::exception )
726 SolarMutexGuard aSolarGuard;
727 CellPos aPos;
728 mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
730 // todo, select table shape?!?
731 SvxTableController* pController = getTableController();
732 if( pController )
734 CellPos aFirstPos( aPos ), aLastPos( aPos );
735 if( pController->hasSelectedCells() )
737 pController->getSelectedCells( aFirstPos, aLastPos );
739 aFirstPos.mnRow = std::min( aFirstPos.mnRow, aPos.mnRow );
740 aFirstPos.mnCol = std::min( aFirstPos.mnCol, aPos.mnCol );
741 aLastPos.mnRow = std::max( aLastPos.mnRow, aPos.mnRow );
742 aLastPos.mnCol = std::max( aLastPos.mnCol, aPos.mnCol );
744 pController->setSelectedCells( aFirstPos, aLastPos );
750 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw ( IndexOutOfBoundsException, RuntimeException, std::exception )
752 SolarMutexGuard aSolarGuard;
753 CellPos aPos;
754 mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
756 return isAccessibleSelected(aPos.mnRow, aPos.mnCol);
761 void SAL_CALL AccessibleTableShape::clearAccessibleSelection() throw ( RuntimeException, std::exception )
763 SolarMutexGuard aSolarGuard;
765 SvxTableController* pController = getTableController();
766 if( pController )
767 pController->clearSelection();
771 void SAL_CALL AccessibleTableShape::selectAllAccessibleChildren() throw ( RuntimeException, std::exception )
773 SolarMutexGuard aSolarGuard;
775 // todo: force selection of shape?
776 SvxTableController* pController = getTableController();
777 if( pController )
778 pController->selectAll();
783 sal_Int32 SAL_CALL AccessibleTableShape::getSelectedAccessibleChildCount() throw ( RuntimeException, std::exception )
785 SolarMutexGuard aSolarGuard;
787 SvxTableController* pController = getTableController();
788 if( pController && pController->hasSelectedCells() )
790 CellPos aFirstPos, aLastPos;
791 pController->getSelectedCells( aFirstPos, aLastPos );
793 const sal_Int32 nSelectedColumns = std::max( (sal_Int32)0, aLastPos.mnCol - aFirstPos.mnCol ) + 1;
794 const sal_Int32 nSelectedRows = std::max( (sal_Int32)0, aLastPos.mnRow - aFirstPos.mnRow ) + 1;
795 return nSelectedRows * nSelectedColumns;
798 return 0;
803 Reference< XAccessible > SAL_CALL AccessibleTableShape::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw ( IndexOutOfBoundsException, RuntimeException, std::exception)
805 SolarMutexGuard aSolarGuard;
807 if( nSelectedChildIndex < 0 )
808 throw IndexOutOfBoundsException();
810 sal_Int32 nChildIndex = GetIndexOfSelectedChild( nSelectedChildIndex );
812 if( nChildIndex < 0 )
813 throw IndexOutOfBoundsException();
815 if ( nChildIndex >= getAccessibleChildCount() )
817 throw IndexOutOfBoundsException();
820 return getAccessibleChild( nChildIndex );
825 void SAL_CALL AccessibleTableShape::deselectAccessibleChild( sal_Int32 nChildIndex ) throw ( IndexOutOfBoundsException, RuntimeException, std::exception )
827 SolarMutexGuard aSolarGuard;
828 CellPos aPos;
829 mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
831 // todo, select table shape?!?
832 SvxTableController* pController = getTableController();
833 if( pController && pController->hasSelectedCells() )
835 CellPos aFirstPos, aLastPos;
836 pController->getSelectedCells( aFirstPos, aLastPos );
838 // create a selection where aPos is not part of anymore
839 aFirstPos.mnRow = std::min( aFirstPos.mnRow, aPos.mnRow+1 );
840 aFirstPos.mnCol = std::min( aFirstPos.mnCol, aPos.mnCol+1 );
841 aLastPos.mnRow = std::max( aLastPos.mnRow, aPos.mnRow-1 );
842 aLastPos.mnCol = std::max( aLastPos.mnCol, aPos.mnCol-1 );
844 // new selection may be invalid (child to deselect is not at a border of the selection but in between)
845 if( (aFirstPos.mnRow > aLastPos.mnRow) || (aFirstPos.mnCol > aLastPos.mnCol) )
846 pController->clearSelection(); // if selection is invalid, clear all
847 else
848 pController->setSelectedCells( aFirstPos, aLastPos );
852 // XAccessibleTableSelection
853 sal_Bool SAL_CALL AccessibleTableShape::selectRow( sal_Int32 row )
854 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
856 SolarMutexGuard aSolarGuard;
857 SvxTableController* pController = getTableController();
858 if( !pController )
859 return sal_False;
860 return pController->selectRow( row );
863 sal_Bool SAL_CALL AccessibleTableShape::selectColumn( sal_Int32 column )
864 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
866 SolarMutexGuard aSolarGuard;
867 SvxTableController* pController = getTableController();
868 if( !pController )
869 return sal_False;
870 return pController->selectColumn( column );
873 sal_Bool SAL_CALL AccessibleTableShape::unselectRow( sal_Int32 row )
874 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
876 SolarMutexGuard aSolarGuard;
877 SvxTableController* pController = getTableController();
878 if( !pController )
879 return sal_False;
880 return pController->deselectRow( row );
883 sal_Bool SAL_CALL AccessibleTableShape::unselectColumn( sal_Int32 column )
884 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
886 SolarMutexGuard aSolarGuard;
887 SvxTableController* pController = getTableController();
888 if( !pController )
889 return sal_False;
890 return pController->deselectColumn( column );
893 sal_Int32 AccessibleTableShape::GetIndexOfSelectedChild(
894 sal_Int32 nSelectedChildIndex ) const
896 sal_Int32 nChildren = const_cast<AccessibleTableShape*>(this)->getAccessibleChildCount();
898 if( nSelectedChildIndex >= nChildren )
899 return -1L;
901 sal_Int32 n = 0;
902 while( n < nChildren )
904 if( const_cast<AccessibleTableShape*>(this)->isAccessibleChildSelected( n ) )
906 if( 0 == nSelectedChildIndex )
907 break;
908 else
909 --nSelectedChildIndex;
911 ++n;
914 return n < nChildren ? n : -1L;
916 void AccessibleTableShape::getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow ) throw (IndexOutOfBoundsException )
918 mxImpl->getColumnAndRow(nChildIndex, rnColumn, rnRow);
921 // XSelectionChangeListener
922 void SAL_CALL
923 AccessibleTableShape::disposing (const EventObject& aEvent)
924 throw (RuntimeException, std::exception)
926 AccessibleShape::disposing(aEvent);
928 void SAL_CALL AccessibleTableShape::selectionChanged (const EventObject& rEvent)
929 throw (RuntimeException, std::exception)
931 //sdr::table::CellRef xCellRef = static_cast< sdr::table::CellRef > (rEvent.Source);
932 Reference< XCell > xCell(rEvent.Source, UNO_QUERY);
933 if (xCell.is())
935 Reference< AccessibleCell > xAccCell = mxImpl->getAccessibleCell( xCell );
936 if (xAccCell.is())
938 sal_Int32 nIndex = xAccCell->getAccessibleIndexInParent(),
939 nCount = getSelectedAccessibleChildCount();
940 bool bSelected = isAccessibleChildSelected(nIndex);
941 if (mnPreviousSelectionCount == 0 && nCount > 0 && bSelected)
943 xAccCell->SetState(AccessibleStateType::SELECTED);
944 xAccCell->CommitChange(AccessibleEventId::SELECTION_CHANGED, Any(), Any());
946 else if (bSelected)
948 xAccCell->SetState(AccessibleStateType::SELECTED);
949 xAccCell->CommitChange(AccessibleEventId::SELECTION_CHANGED_ADD, Any(), Any());
951 else
953 xAccCell->ResetState(AccessibleStateType::SELECTED);
954 xAccCell->CommitChange(AccessibleEventId::SELECTION_CHANGED_REMOVE, Any(), Any());
956 mnPreviousSelectionCount = nCount;
960 // Get the currently active cell which is text editing
961 AccessibleCell* AccessibleTableShape::GetActiveAccessibleCell()
963 Reference< AccessibleCell > xAccCell;
964 AccessibleCell* pAccCell = NULL;
965 SvxTableController* pController = getTableController();
966 if (pController)
968 sdr::table::SdrTableObj* pTableObj = pController->GetTableObj();
969 if ( pTableObj )
971 sdr::table::CellRef xCellRef (pTableObj->getActiveCell());
972 if ( xCellRef.is() )
974 const bool bCellEditing = xCellRef->IsTextEditActive();
975 if (bCellEditing)
977 //Reference< XCell > xCell(xCellRef.get(), UNO_QUERY);
978 xAccCell = mxImpl->getAccessibleCell(Reference< XCell >( xCellRef.get() ));
979 if (xAccCell.is())
980 pAccCell = xAccCell.get();
985 return pAccCell;
988 //If current active cell is in editing, the focus state should be set to internal text
989 bool AccessibleTableShape::SetState (sal_Int16 aState)
991 AccessibleCell* pActiveAccessibleCell = GetActiveAccessibleCell();
992 bool bStateHasChanged = false;
993 if (aState == AccessibleStateType::FOCUSED && pActiveAccessibleCell != NULL)
995 return pActiveAccessibleCell->SetState(aState);
997 else
998 bStateHasChanged = AccessibleShape::SetState (aState);
999 return bStateHasChanged;
1002 //If current active cell is in editing, the focus state should be reset to internal text
1003 bool AccessibleTableShape::ResetState (sal_Int16 aState)
1005 AccessibleCell* pActiveAccessibleCell = GetActiveAccessibleCell();
1006 bool bStateHasChanged = false;
1007 if (aState == AccessibleStateType::FOCUSED && pActiveAccessibleCell != NULL)
1009 return pActiveAccessibleCell->ResetState(aState);
1011 else
1012 bStateHasChanged = AccessibleShape::ResetState (aState);
1013 return bStateHasChanged;
1016 bool AccessibleTableShape::SetStateDirectly (sal_Int16 aState)
1018 return AccessibleContextBase::SetState (aState);
1021 bool AccessibleTableShape::ResetStateDirectly (sal_Int16 aState)
1023 return AccessibleContextBase::ResetState (aState);
1026 void AccessibleTableShape::checkCellPosition( sal_Int32 nCol, sal_Int32 nRow ) throw ( IndexOutOfBoundsException )
1028 if( (nCol >= 0) && (nRow >= 0) && mxImpl->mxTable.is() && (nCol < mxImpl->mxTable->getColumnCount()) && (nRow < mxImpl->mxTable->getRowCount()) )
1029 return;
1031 throw IndexOutOfBoundsException();
1034 AccessibleTableHeaderShape::AccessibleTableHeaderShape( AccessibleTableShape* pTable, bool bRow )
1036 mpTable = pTable;
1037 mbRow = bRow;
1040 AccessibleTableHeaderShape::~AccessibleTableHeaderShape()
1042 mpTable = NULL;
1045 // XAccessible
1046 Reference< XAccessibleContext > SAL_CALL AccessibleTableHeaderShape::getAccessibleContext() throw (RuntimeException, std::exception)
1048 return this;
1051 // XAccessibleContext
1052 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleChildCount( ) throw(RuntimeException, std::exception)
1054 return getAccessibleRowCount() * getAccessibleColumnCount();
1057 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleChild( sal_Int32 i ) throw(IndexOutOfBoundsException, RuntimeException, std::exception)
1059 return mpTable->getAccessibleChild( i );
1062 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleParent() throw (RuntimeException, std::exception)
1064 Reference< XAccessible > XParent;
1065 return XParent;
1068 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleIndexInParent() throw (RuntimeException, std::exception)
1070 return -1;
1073 sal_Int16 SAL_CALL AccessibleTableHeaderShape::getAccessibleRole() throw (RuntimeException, std::exception)
1075 return mpTable->getAccessibleRole();
1078 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleDescription() throw (RuntimeException, std::exception)
1080 return mpTable->getAccessibleDescription();
1083 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleName() throw (RuntimeException, std::exception)
1085 return mpTable->getAccessibleName();
1088 Reference< XAccessibleStateSet > SAL_CALL AccessibleTableHeaderShape::getAccessibleStateSet() throw (RuntimeException, std::exception)
1090 return mpTable->getAccessibleStateSet();
1093 Reference< XAccessibleRelationSet > SAL_CALL AccessibleTableHeaderShape::getAccessibleRelationSet() throw (RuntimeException, std::exception)
1095 return mpTable->getAccessibleRelationSet();
1098 Locale SAL_CALL AccessibleTableHeaderShape::getLocale() throw (IllegalAccessibleComponentStateException, RuntimeException, std::exception)
1100 return mpTable->getLocale();
1103 //XAccessibleComponent
1104 sal_Bool SAL_CALL AccessibleTableHeaderShape::containsPoint ( const ::com::sun::star::awt::Point& aPoint ) throw (RuntimeException, std::exception)
1106 return mpTable->containsPoint( aPoint );
1109 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleAtPoint ( const ::com::sun::star::awt::Point& aPoint) throw (RuntimeException, std::exception)
1111 return mpTable->getAccessibleAtPoint( aPoint );
1114 ::com::sun::star::awt::Rectangle SAL_CALL AccessibleTableHeaderShape::getBounds() throw (RuntimeException, std::exception)
1116 return mpTable->getBounds();
1119 ::com::sun::star::awt::Point SAL_CALL AccessibleTableHeaderShape::getLocation() throw (RuntimeException, std::exception)
1121 return mpTable->getLocation();
1124 ::com::sun::star::awt::Point SAL_CALL AccessibleTableHeaderShape::getLocationOnScreen() throw (RuntimeException, std::exception)
1126 return mpTable->getLocationOnScreen();
1129 ::com::sun::star::awt::Size SAL_CALL AccessibleTableHeaderShape::getSize() throw (RuntimeException, std::exception)
1131 return mpTable->getSize();
1134 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getForeground() throw (RuntimeException, std::exception)
1136 return mpTable->getForeground();
1139 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getBackground() throw (RuntimeException, std::exception)
1141 return mpTable->getBackground();
1144 void SAL_CALL AccessibleTableHeaderShape::grabFocus() throw (RuntimeException, std::exception)
1146 mpTable->grabFocus();
1148 // XAccessibleTable
1149 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleRowCount() throw (RuntimeException, std::exception)
1151 return mbRow ? 1 : mpTable->getAccessibleRowCount();
1154 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnCount() throw (RuntimeException, std::exception)
1156 return !mbRow ? 1 : mpTable->getAccessibleColumnCount();
1159 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleRowDescription( sal_Int32 nRow ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1161 return mpTable->getAccessibleRowDescription( nRow );
1164 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnDescription( sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1166 return mpTable->getAccessibleColumnDescription( nColumn );
1169 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1171 return mpTable->getAccessibleRowExtentAt( nRow, nColumn );
1174 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1176 return mpTable->getAccessibleColumnExtentAt( nRow, nColumn );
1179 Reference< XAccessibleTable > SAL_CALL AccessibleTableHeaderShape::getAccessibleRowHeaders( ) throw (RuntimeException, std::exception)
1181 Reference< XAccessibleTable > xRet;
1182 return xRet;
1185 Reference< XAccessibleTable > SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnHeaders( ) throw (RuntimeException, std::exception)
1187 Reference< XAccessibleTable > xRet;
1188 return xRet;
1191 Sequence< sal_Int32 > SAL_CALL AccessibleTableHeaderShape::getSelectedAccessibleRows( ) throw (RuntimeException, std::exception)
1193 sal_Int32 nRow = getAccessibleRowCount();
1194 ::std::vector< sal_Bool > aSelected( nRow, sal_True );
1195 sal_Int32 nCount = nRow;
1196 for( sal_Int32 i = 0; i < nRow; i++ )
1200 aSelected[i] = isAccessibleRowSelected( i );
1202 catch( ... )
1204 return Sequence< sal_Int32 >();
1207 if( !aSelected[i] )
1208 nCount--;
1210 Sequence < sal_Int32 > aRet( nCount );
1211 sal_Int32 *pRet = aRet.getArray();
1212 sal_Int32 nPos = 0;
1213 size_t nSize = aSelected.size();
1214 for( size_t i=0; i < nSize && nPos < nCount; i++ )
1216 if( aSelected[i] )
1218 *pRet++ = i;
1219 nPos++;
1223 return aRet;
1226 Sequence< sal_Int32 > SAL_CALL AccessibleTableHeaderShape::getSelectedAccessibleColumns( ) throw (RuntimeException, std::exception)
1228 sal_Int32 nColumn = getAccessibleColumnCount();
1229 ::std::vector< sal_Bool > aSelected( nColumn, sal_True );
1230 sal_Int32 nCount = nColumn;
1231 for( sal_Int32 i = 0; i < nColumn; i++ )
1235 aSelected[i] = isAccessibleColumnSelected( i );
1237 catch( ... )
1239 return Sequence< sal_Int32 >();
1242 if( !aSelected[i] )
1243 nCount--;
1245 Sequence < sal_Int32 > aRet( nCount );
1246 sal_Int32 *pRet = aRet.getArray();
1247 sal_Int32 nPos = 0;
1248 size_t nSize = aSelected.size();
1249 for( size_t i=0; i < nSize && nPos < nCount; i++ )
1251 if( aSelected[i] )
1253 *pRet++ = i;
1254 nPos++;
1258 return aRet;
1261 sal_Bool SAL_CALL AccessibleTableHeaderShape::isAccessibleRowSelected( sal_Int32 nRow ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1263 return mpTable->isAccessibleRowSelected( nRow );
1266 sal_Bool SAL_CALL AccessibleTableHeaderShape::isAccessibleColumnSelected( sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1268 return mpTable->isAccessibleColumnSelected( nColumn );
1271 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1273 return mpTable->getAccessibleCellAt( nRow, nColumn );
1276 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleCaption( ) throw (RuntimeException, std::exception)
1278 return mpTable->getAccessibleCaption();
1281 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleSummary( ) throw (RuntimeException, std::exception)
1283 return mpTable->getAccessibleSummary();
1286 sal_Bool SAL_CALL AccessibleTableHeaderShape::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1288 return mpTable->isAccessibleSelected( nRow, nColumn );
1291 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1293 return mpTable->getAccessibleIndex( nRow, nColumn );
1296 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleRow( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1298 return mpTable->getAccessibleRow( nChildIndex );
1301 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleColumn( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1303 return mpTable->getAccessibleColumn( nChildIndex );
1306 // XAccessibleTableSelection
1307 sal_Bool SAL_CALL AccessibleTableHeaderShape::selectRow( sal_Int32 row )
1308 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1310 if( mbRow )
1311 return mpTable->selectRow( row );
1312 else
1314 mpTable->clearAccessibleSelection();
1315 sal_Int32 nIndex = mpTable->getAccessibleIndex( row, 0 );
1316 mpTable->selectAccessibleChild( nIndex );
1317 return sal_True;
1321 sal_Bool SAL_CALL AccessibleTableHeaderShape::selectColumn( sal_Int32 column )
1322 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1324 if( !mbRow )
1325 return mpTable->selectColumn( column );
1326 else
1328 mpTable->clearAccessibleSelection();
1329 sal_Int32 nIndex = mpTable->getAccessibleIndex( 0, column );
1330 mpTable->selectAccessibleChild( nIndex );
1331 return sal_True;
1335 sal_Bool SAL_CALL AccessibleTableHeaderShape::unselectRow( sal_Int32 row )
1336 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1338 if( mbRow )
1339 return mpTable->unselectRow( row );
1340 else
1342 sal_Int32 nIndex = mpTable->getAccessibleIndex( row, 0 );
1343 mpTable->deselectAccessibleChild( nIndex );
1344 return sal_True;
1348 sal_Bool SAL_CALL AccessibleTableHeaderShape::unselectColumn( sal_Int32 column )
1349 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1351 if( !mbRow )
1352 return mpTable->unselectColumn( column );
1353 else
1355 sal_Int32 nIndex = mpTable->getAccessibleIndex( 0, column );
1356 mpTable->deselectAccessibleChild( nIndex );
1357 return sal_True;
1362 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */