1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 
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>
27 
28 #include <tools/diagnose_ex.h>
29 #include <vcl/svapp.hxx>
30 
31 #include <AccessibleTableShape.hxx>
32 #include <svx/sdr/table/tablecontroller.hxx>
33 #include "accessiblecell.hxx"
34 #include <cell.hxx>
35 
36 #include <algorithm>
37 #include <unordered_map>
38 
39 #include <cppuhelper/implbase.hxx>
40 #include <svx/svdotable.hxx>
41 #include <com/sun/star/view/XSelectionSupplier.hpp>
42 
43 
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;
54 
55 namespace accessibility
56 {
57 
58 typedef std::unordered_map< Reference< XCell >, rtl::Reference< AccessibleCell > > AccessibleCellMap;
59 
60 class AccessibleTableShapeImpl : public cppu::WeakImplHelper< XModifyListener >
61 {
62 public:
63     explicit AccessibleTableShapeImpl( AccessibleShapeTreeInfo& rShapeTreeInfo );
64 
65     void init( const Reference< XAccessible>& xAccessible, const Reference< XTable >& xTable );
66     void dispose();
67 
68     /// @throws IndexOutOfBoundsException
69     /// @throws RuntimeException
70     Reference< XAccessible > getAccessibleChild(sal_Int32 i);
71     /// @throws IndexOutOfBoundsException
72     void getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow );
73 
74     // XModifyListener
75     virtual void SAL_CALL modified( const EventObject& aEvent ) override;
76 
77     // XEventListener
78     virtual void SAL_CALL disposing( const EventObject& Source ) override;
79 
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);
90 };
91 
92 
AccessibleTableShapeImpl(AccessibleShapeTreeInfo & rShapeTreeInfo)93 AccessibleTableShapeImpl::AccessibleTableShapeImpl( AccessibleShapeTreeInfo& rShapeTreeInfo )
94 : mrShapeTreeInfo( rShapeTreeInfo )
95 , mRowCount(0)
96 , mColCount(0)
97 {
98 }
99 
100 
init(const Reference<XAccessible> & xAccessible,const Reference<XTable> & xTable)101 void AccessibleTableShapeImpl::init( const Reference< XAccessible>& xAccessible, const Reference< XTable >& xTable )
102 {
103     mxAccessible = xAccessible;
104     mxTable = xTable;
105 
106     if( mxTable.is() )
107     {
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();
117     }
118 }
119 
120 
dispose()121 void AccessibleTableShapeImpl::dispose()
122 {
123     if( mxTable.is() )
124     {
125         //remove all the cell's acc object in table's dispose.
126         for( auto& rEntry : maChildMap )
127         {
128             rEntry.second->dispose();
129         }
130         maChildMap.clear();
131         Reference< XModifyListener > xListener( this );
132         mxTable->removeModifyListener( xListener );
133         mxTable.clear();
134     }
135     mxAccessible.clear();
136 }
137 
138 
139 //get the cached AccessibleCell from XCell
getAccessibleCell(const Reference<XCell> & xCell)140 rtl::Reference< AccessibleCell > AccessibleTableShapeImpl::getAccessibleCell (const Reference< XCell >& xCell)
141 {
142     AccessibleCellMap::iterator iter( maChildMap.find( xCell ) );
143 
144     if( iter != maChildMap.end() )
145     {
146         rtl::Reference< AccessibleCell > xChild( (*iter).second );
147         return xChild;
148     }
149     return rtl::Reference< AccessibleCell >();
150 }
151 
getAccessibleCell(sal_Int32 nRow,sal_Int32 nColumn)152 rtl::Reference< AccessibleCell > AccessibleTableShapeImpl::getAccessibleCell (sal_Int32 nRow, sal_Int32 nColumn)
153 {
154     Reference< XCell > xCell( mxTable->getCellByPosition( nColumn, nRow ) );
155     rtl::Reference< AccessibleCell > xChild = getAccessibleCell( xCell );
156 
157     if( !xChild.is() && mxTable.is() )
158     {
159         sal_Int32 nChildIndex = mxTable->getColumnCount() * nRow + nColumn;
160         CellRef xCellRef( dynamic_cast< Cell* >( xCell.get() ) );
161 
162         rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCellRef, nChildIndex, mrShapeTreeInfo ) );
163 
164         xAccessibleCell->Init();
165         maChildMap[xCell] = xAccessibleCell;
166 
167         xChild = xAccessibleCell;
168     }
169     return xChild;
170 }
171 
172 
getAccessibleChild(sal_Int32 nChildIndex)173 Reference< XAccessible > AccessibleTableShapeImpl::getAccessibleChild(sal_Int32 nChildIndex)
174 {
175     sal_Int32 nColumn = 0, nRow = 0;
176     getColumnAndRow( nChildIndex, nColumn, nRow );
177 
178     Reference< XCell > xCell( mxTable->getCellByPosition( nColumn, nRow ) );
179     AccessibleCellMap::iterator iter( maChildMap.find( xCell ) );
180 
181     if( iter != maChildMap.end() )
182     {
183         Reference< XAccessible > xChild( (*iter).second );
184         return xChild;
185     }
186     else
187     {
188         CellRef xCellRef( dynamic_cast< Cell* >( xCell.get() ) );
189 
190         rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCellRef, nChildIndex, mrShapeTreeInfo ) );
191 
192         xAccessibleCell->Init();
193         maChildMap[xCell] = xAccessibleCell;
194 
195         return xAccessibleCell;
196     }
197 }
198 
199 
getColumnAndRow(sal_Int32 nChildIndex,sal_Int32 & rnColumn,sal_Int32 & rnRow)200 void AccessibleTableShapeImpl::getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow )
201 {
202     rnRow = 0;
203     rnColumn = nChildIndex;
204 
205     if( mxTable.is() )
206     {
207         const sal_Int32 nColumnCount = mxTable->getColumnCount();
208         while( rnColumn >= nColumnCount )
209         {
210             rnRow++;
211             rnColumn -= nColumnCount;
212         }
213 
214         if( rnRow < mxTable->getRowCount() )
215             return;
216     }
217 
218     throw IndexOutOfBoundsException();
219 }
220 
221 // XModifyListener
modified(const EventObject &)222 void SAL_CALL AccessibleTableShapeImpl::modified( const EventObject& /*aEvent*/ )
223 {
224     if( !mxTable.is() )
225         return;
226 
227     try
228     {
229         // structural changes may have happened to the table, validate all accessible cell instances
230         AccessibleCellMap aTempChildMap;
231         aTempChildMap.swap( maChildMap );
232 
233         // first move all still existing cells to maChildMap again and update their index
234 
235         const sal_Int32 nRowCount = mxTable->getRowCount();
236         const sal_Int32 nColCount = mxTable->getColumnCount();
237 
238         bool bRowOrColumnChanged = false;
239         if (mRowCount != nRowCount || mColCount != nColCount )
240         {
241             bRowOrColumnChanged = true;
242             mRowCount = nRowCount;
243             mColCount = nColCount;
244         }
245         sal_Int32 nChildIndex = 0;
246 
247         for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
248         {
249             for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
250             {
251                 Reference< XCell > xCell( mxTable->getCellByPosition( nCol, nRow ) );
252                 AccessibleCellMap::iterator iter( aTempChildMap.find( xCell ) );
253 
254                 if( iter != aTempChildMap.end() )
255                 {
256                     rtl::Reference< AccessibleCell > xAccessibleCell( (*iter).second );
257                     xAccessibleCell->setIndexInParent( nChildIndex );
258                     xAccessibleCell->UpdateChildren();
259                     // If row or column count is changed, there is split or merge, so all cell's acc name should be updated
260                     if (bRowOrColumnChanged)
261                     {
262                         xAccessibleCell->SetAccessibleName(xAccessibleCell->getAccessibleName(), AccessibleContextBase::ManuallySet);
263                     }
264                     // For merged cell, add invisible & disabled state.
265                     Reference< XMergeableCell > xMergedCell( mxTable->getCellByPosition( nCol, nRow ),  UNO_QUERY );
266                     if (xMergedCell.is() && xMergedCell->isMerged())
267                     {
268                         xAccessibleCell->ResetState(AccessibleStateType::VISIBLE);
269                         xAccessibleCell->ResetState(AccessibleStateType::ENABLED);
270                         // IA2 CWS. MT: OFFSCREEN == !SHOWING, should stay consistent
271                         // xAccessibleCell->SetState(AccessibleStateType::OFFSCREEN);
272                         xAccessibleCell->ResetState(AccessibleStateType::SHOWING);
273                     }
274                     else
275                     {
276                         xAccessibleCell->SetState(AccessibleStateType::VISIBLE);
277                         xAccessibleCell->SetState(AccessibleStateType::ENABLED);
278                         // IA2 CWS. MT: OFFSCREEN == !SHOWING, should stay consistent
279                         // xAccessibleCell->ResetState(AccessibleStateType::OFFSCREEN);
280                         xAccessibleCell->SetState(AccessibleStateType::SHOWING);
281                     }
282 
283                     // move still existing cell from temporary child map to our child map
284                     maChildMap[xCell] = xAccessibleCell;
285                     aTempChildMap.erase( iter );
286                 }
287                 else
288                 {
289                     CellRef xCellRef( dynamic_cast< Cell* >( xCell.get() ) );
290 
291                     rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCellRef, nChildIndex, mrShapeTreeInfo ) );
292 
293                     xAccessibleCell->Init();
294                     maChildMap[xCell] = xAccessibleCell;
295                 }
296 
297                 ++nChildIndex;
298             }
299         }
300 
301         // all accessible cell instances still left in aTempChildMap must be disposed
302         // as they are no longer part of the table
303 
304         for( auto& rEntry : aTempChildMap )
305         {
306             rEntry.second->dispose();
307         }
308         //notify bridge to update the acc cache.
309         AccessibleTableShape *pAccTable = dynamic_cast <AccessibleTableShape *> (mxAccessible.get());
310         if (pAccTable)
311             pAccTable->CommitChange(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
312     }
313     catch( const Exception& )
314     {
315         TOOLS_WARN_EXCEPTION("svx.table", "");
316     }
317 }
318 
319 // XEventListener
disposing(const EventObject &)320 void SAL_CALL AccessibleTableShapeImpl::disposing( const EventObject& /*Source*/ )
321 {
322 }
323 
AccessibleTableShape(const AccessibleShapeInfo & rShapeInfo,const AccessibleShapeTreeInfo & rShapeTreeInfo)324 AccessibleTableShape::AccessibleTableShape( const AccessibleShapeInfo& rShapeInfo, const AccessibleShapeTreeInfo& rShapeTreeInfo)
325 : AccessibleTableShape_Base(rShapeInfo, rShapeTreeInfo)
326 , mnPreviousSelectionCount(0)
327 , mxImpl( new AccessibleTableShapeImpl( maShapeTreeInfo ) )
328 {
329 }
330 
331 
~AccessibleTableShape()332 AccessibleTableShape::~AccessibleTableShape()
333 {
334 }
335 
336 
Init()337 void AccessibleTableShape::Init()
338 {
339     try
340     {
341         Reference< XPropertySet > xSet( mxShape, UNO_QUERY_THROW );
342         Reference< XTable > xTable( xSet->getPropertyValue("Model"), UNO_QUERY_THROW );
343 
344         mxImpl->init( this, xTable );
345     }
346     catch( Exception& )
347     {
348         TOOLS_WARN_EXCEPTION("svx.table", "");
349     }
350 
351     AccessibleTableShape_Base::Init();
352 }
353 
354 
getTableController()355 SvxTableController* AccessibleTableShape::getTableController()
356 {
357     SdrView* pView = maShapeTreeInfo.GetSdrView ();
358     if( pView )
359         return dynamic_cast< SvxTableController* >( pView->getSelectionController().get() );
360     else
361         return nullptr;
362 }
363 
364 
365 // XInterface
366 
367 
queryInterface(const Type & aType)368 Any SAL_CALL AccessibleTableShape::queryInterface( const Type& aType )
369 {
370     if ( aType == cppu::UnoType<XAccessibleTableSelection>::get())
371     {
372         Reference<XAccessibleTableSelection> xThis( this );
373         Any aRet;
374         aRet <<= xThis;
375         return aRet;
376     }
377     else
378         return AccessibleTableShape_Base::queryInterface( aType );
379 }
380 
381 
acquire()382 void SAL_CALL AccessibleTableShape::acquire(  ) noexcept
383 {
384     AccessibleTableShape_Base::acquire();
385 }
386 
387 
release()388 void SAL_CALL AccessibleTableShape::release(  ) noexcept
389 {
390     AccessibleTableShape_Base::release();
391 }
392 
393 
394 // XAccessible
395 
396 
getImplementationName()397 OUString SAL_CALL AccessibleTableShape::getImplementationName()
398 {
399     return "com.sun.star.comp.accessibility.AccessibleTableShape";
400 }
401 
402 
CreateAccessibleBaseName()403 OUString AccessibleTableShape::CreateAccessibleBaseName()
404 {
405     return "TableShape";
406 }
407 
408 
getAccessibleChildCount()409 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleChildCount( )
410 {
411     SolarMutexGuard aSolarGuard;
412     return mxImpl->mxTable.is() ? mxImpl->mxTable->getRowCount() * mxImpl->mxTable->getColumnCount() : 0;
413 }
414 
415 
getAccessibleChild(sal_Int32 i)416 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleChild( sal_Int32 i )
417 {
418     SolarMutexGuard aSolarGuard;
419     ThrowIfDisposed();
420 
421     return mxImpl->getAccessibleChild( i );
422 }
423 
424 
getAccessibleRole()425 sal_Int16 SAL_CALL AccessibleTableShape::getAccessibleRole()
426 {
427     return AccessibleRole::TABLE;
428 }
429 
430 
disposing()431 void SAL_CALL AccessibleTableShape::disposing()
432 {
433     mxImpl->dispose();
434 
435     // let the base do its stuff
436     AccessibleShape::disposing();
437 }
438 
439 
440 // XAccessibleTable
441 
442 
getAccessibleRowCount()443 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRowCount()
444 {
445     SolarMutexGuard aSolarGuard;
446     return mxImpl->mxTable.is() ? mxImpl->mxTable->getRowCount() : 0;
447 }
448 
449 
getAccessibleColumnCount()450 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumnCount(  )
451 {
452     SolarMutexGuard aSolarGuard;
453     return mxImpl->mxTable.is() ? mxImpl->mxTable->getColumnCount() : 0;
454 }
455 
456 
getAccessibleRowDescription(sal_Int32 nRow)457 OUString SAL_CALL AccessibleTableShape::getAccessibleRowDescription( sal_Int32 nRow )
458 {
459     checkCellPosition( 0, nRow );
460     return OUString();
461 }
462 
463 
getAccessibleColumnDescription(sal_Int32 nColumn)464 OUString SAL_CALL AccessibleTableShape::getAccessibleColumnDescription( sal_Int32 nColumn )
465 {
466     SolarMutexGuard aSolarGuard;
467     checkCellPosition( nColumn, 0 );
468     return OUString();
469 }
470 
471 
getAccessibleRowExtentAt(sal_Int32 nRow,sal_Int32 nColumn)472 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
473 {
474     SolarMutexGuard aSolarGuard;
475     checkCellPosition( nColumn, nRow );
476     if( mxImpl->mxTable.is() )
477     {
478         Reference< XMergeableCell > xCell( mxImpl->mxTable->getCellByPosition( nColumn, nRow ), UNO_QUERY );
479         if( xCell.is() )
480             return xCell->getRowSpan();
481     }
482     return 1;
483 }
484 
485 
getAccessibleColumnExtentAt(sal_Int32 nRow,sal_Int32 nColumn)486 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
487 {
488     SolarMutexGuard aSolarGuard;
489     checkCellPosition( nColumn, nRow );
490     if( mxImpl->mxTable.is() )
491     {
492         Reference< XMergeableCell > xCell( mxImpl->mxTable->getCellByPosition( nColumn, nRow ), UNO_QUERY );
493         if( xCell.is() )
494             return xCell->getColumnSpan();
495     }
496     return 1;
497 }
498 
499 
getAccessibleRowHeaders()500 Reference< XAccessibleTable > SAL_CALL AccessibleTableShape::getAccessibleRowHeaders(  )
501 {
502     Reference< XAccessibleTable > xRet;
503     SvxTableController* pController = getTableController();
504     if( pController )
505     {
506         if( pController->isRowHeader() )
507         {
508             xRet = new AccessibleTableHeaderShape( this, true );
509         }
510     }
511     return xRet;
512 }
513 
514 
getAccessibleColumnHeaders()515 Reference< XAccessibleTable > SAL_CALL AccessibleTableShape::getAccessibleColumnHeaders(  )
516 {
517     Reference< XAccessibleTable > xRet;
518     SvxTableController* pController = getTableController();
519     if( pController )
520     {
521         if( pController->isColumnHeader() )
522         {
523             xRet = new AccessibleTableHeaderShape( this, false );
524         }
525     }
526     return xRet;
527 }
528 
529 
getSelectedAccessibleRows()530 Sequence< sal_Int32 > SAL_CALL AccessibleTableShape::getSelectedAccessibleRows(  )
531 {
532     sal_Int32 nRow = getAccessibleRowCount();
533     ::std::vector<bool> aSelected( nRow, true );
534     sal_Int32 nCount = nRow;
535     for( sal_Int32 i = 0; i < nRow; i++ )
536     {
537         try
538         {
539             aSelected[i] = isAccessibleRowSelected( i );
540         }
541         catch( ... )
542         {
543             return Sequence< sal_Int32 >();
544         }
545 
546         if( !aSelected[i] )
547             nCount--;
548     }
549     Sequence < sal_Int32 > aRet( nCount );
550     sal_Int32 *pRet = aRet.getArray();
551     sal_Int32 nPos = 0;
552     size_t nSize = aSelected.size();
553     for( size_t i=0; i < nSize && nPos < nCount; i++ )
554     {
555         if( aSelected[i] )
556         {
557             *pRet++ = i;
558             nPos++;
559         }
560     }
561 
562     return aRet;
563 }
564 
565 
getSelectedAccessibleColumns()566 Sequence< sal_Int32 > SAL_CALL AccessibleTableShape::getSelectedAccessibleColumns(  )
567 {
568     sal_Int32 nColumn = getAccessibleColumnCount();
569     ::std::vector<bool> aSelected( nColumn, true );
570     sal_Int32 nCount = nColumn;
571     for( sal_Int32 i = 0; i < nColumn; i++ )
572     {
573         try
574         {
575             aSelected[i] = isAccessibleColumnSelected( i );
576         }
577         catch( ... )
578         {
579             return Sequence< sal_Int32 >();
580         }
581 
582         if( !aSelected[i] )
583             nCount--;
584     }
585     Sequence < sal_Int32 > aRet( nCount );
586     sal_Int32 *pRet = aRet.getArray();
587     sal_Int32 nPos = 0;
588     size_t nSize = aSelected.size();
589     for( size_t i=0; i < nSize && nPos < nCount; i++ )
590     {
591         if( aSelected[i] )
592         {
593             *pRet++ = i;
594             nPos++;
595         }
596     }
597 
598     return aRet;
599 }
600 
601 
isAccessibleRowSelected(sal_Int32 nRow)602 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleRowSelected( sal_Int32 nRow )
603 {
604     SolarMutexGuard aSolarGuard;
605     checkCellPosition( 0, nRow );
606     SvxTableController* pController = getTableController();
607     if( pController )
608     {
609         return pController->isRowSelected( nRow );
610     }
611     return false;
612 }
613 
614 
isAccessibleColumnSelected(sal_Int32 nColumn)615 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleColumnSelected( sal_Int32 nColumn )
616 {
617     SolarMutexGuard aSolarGuard;
618     checkCellPosition( nColumn, 0 );
619     SvxTableController* pController = getTableController();
620     if( pController )
621     {
622         return pController->isColumnSelected( nColumn );
623     }
624     return false;
625 }
626 
627 
getAccessibleCellAt(sal_Int32 nRow,sal_Int32 nColumn)628 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
629 {
630     SolarMutexGuard aSolarGuard;
631     checkCellPosition( nColumn, nRow );
632 
633     sal_Int32 nChildIndex = 0;
634     if( mxImpl->mxTable.is() )
635         nChildIndex = mxImpl->mxTable->getColumnCount() * nRow + nColumn;
636 
637     return getAccessibleChild( nChildIndex );
638 }
639 
640 
getAccessibleCaption()641 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleCaption(  )
642 {
643     Reference< XAccessible > xRet;
644     return xRet;
645 }
646 
647 
getAccessibleSummary()648 Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleSummary(  )
649 {
650     Reference< XAccessible > xRet;
651     return xRet;
652 }
653 
654 
isAccessibleSelected(sal_Int32 nRow,sal_Int32 nColumn)655 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn )
656 {
657     SolarMutexGuard aSolarGuard;
658     checkCellPosition( nColumn, nRow );
659 
660     SvxTableController* pController = getTableController();
661     if( pController && pController->hasSelectedCells() )
662     {
663         CellPos aFirstPos, aLastPos;
664         pController->getSelectedCells( aFirstPos, aLastPos );
665         if( (aFirstPos.mnRow <= nRow) && (aFirstPos.mnCol <= nColumn) && (nRow <= aLastPos.mnRow) && (nColumn <= aLastPos.mnCol) )
666             return true;
667     }
668 
669     return false;
670 }
671 
672 
getAccessibleIndex(sal_Int32 nRow,sal_Int32 nColumn)673 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn )
674 {
675     SolarMutexGuard aSolarGuard;
676     checkCellPosition( nColumn, nRow );
677     return  mxImpl->mxTable.is() ? (nRow * mxImpl->mxTable->getColumnCount() + nColumn) : 0;
678 }
679 
680 
getAccessibleRow(sal_Int32 nChildIndex)681 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRow( sal_Int32 nChildIndex )
682 {
683     SolarMutexGuard aSolarGuard;
684     sal_Int32 nColumn = 0, nRow = 0;
685     mxImpl->getColumnAndRow( nChildIndex, nColumn, nRow );
686     return nRow;
687 }
688 
689 
getAccessibleColumn(sal_Int32 nChildIndex)690 sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumn( sal_Int32 nChildIndex )
691 {
692     SolarMutexGuard aSolarGuard;
693     sal_Int32 nColumn = 0, nRow = 0;
694     mxImpl->getColumnAndRow( nChildIndex, nColumn, nRow );
695     return nColumn;
696 }
697 
698 
699 // XAccessibleSelection
700 
701 
selectAccessibleChild(sal_Int32 nChildIndex)702 void SAL_CALL AccessibleTableShape::selectAccessibleChild( sal_Int32 nChildIndex )
703 {
704     SolarMutexGuard aSolarGuard;
705     CellPos aPos;
706     mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
707 
708     // todo, select table shape?!?
709     SvxTableController* pController = getTableController();
710     if( !pController )
711         return;
712 
713     CellPos aFirstPos( aPos ), aLastPos( aPos );
714     if( pController->hasSelectedCells() )
715     {
716         pController->getSelectedCells( aFirstPos, aLastPos );
717 
718         aFirstPos.mnRow = std::min( aFirstPos.mnRow, aPos.mnRow );
719         aFirstPos.mnCol = std::min( aFirstPos.mnCol, aPos.mnCol );
720         aLastPos.mnRow = std::max( aLastPos.mnRow, aPos.mnRow );
721         aLastPos.mnCol = std::max( aLastPos.mnCol, aPos.mnCol );
722     }
723     pController->setSelectedCells( aFirstPos, aLastPos );
724 }
725 
726 
isAccessibleChildSelected(sal_Int32 nChildIndex)727 sal_Bool SAL_CALL AccessibleTableShape::isAccessibleChildSelected( sal_Int32 nChildIndex )
728 {
729     SolarMutexGuard aSolarGuard;
730     CellPos aPos;
731     mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
732 
733     return isAccessibleSelected(aPos.mnRow, aPos.mnCol);
734 }
735 
736 
clearAccessibleSelection()737 void SAL_CALL AccessibleTableShape::clearAccessibleSelection()
738 {
739     SolarMutexGuard aSolarGuard;
740 
741     SvxTableController* pController = getTableController();
742     if( pController )
743         pController->clearSelection();
744 }
745 
746 
selectAllAccessibleChildren()747 void SAL_CALL AccessibleTableShape::selectAllAccessibleChildren()
748 {
749     SolarMutexGuard aSolarGuard;
750 
751    // todo: force selection of shape?
752     SvxTableController* pController = getTableController();
753     if( pController )
754         pController->selectAll();
755 }
756 
757 
getSelectedAccessibleChildCount()758 sal_Int32 SAL_CALL AccessibleTableShape::getSelectedAccessibleChildCount()
759 {
760     SolarMutexGuard aSolarGuard;
761 
762     SvxTableController* pController = getTableController();
763     if( pController && pController->hasSelectedCells() )
764     {
765         CellPos aFirstPos, aLastPos;
766         pController->getSelectedCells( aFirstPos, aLastPos );
767 
768         const sal_Int32 nSelectedColumns = std::max( sal_Int32(0), aLastPos.mnCol - aFirstPos.mnCol ) + 1;
769         const sal_Int32 nSelectedRows = std::max( sal_Int32(0), aLastPos.mnRow - aFirstPos.mnRow ) + 1;
770         return nSelectedRows * nSelectedColumns;
771     }
772 
773     return 0;
774 }
775 
776 
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)777 Reference< XAccessible > SAL_CALL AccessibleTableShape::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
778 {
779     SolarMutexGuard aSolarGuard;
780 
781     if( nSelectedChildIndex < 0 )
782         throw IndexOutOfBoundsException();
783 
784     sal_Int32 nChildIndex = GetIndexOfSelectedChild( nSelectedChildIndex );
785 
786     if( nChildIndex < 0 )
787         throw IndexOutOfBoundsException();
788 
789     if ( nChildIndex >= getAccessibleChildCount() )
790     {
791         throw IndexOutOfBoundsException();
792     }
793 
794     return getAccessibleChild( nChildIndex );
795 }
796 
797 
deselectAccessibleChild(sal_Int32 nChildIndex)798 void SAL_CALL AccessibleTableShape::deselectAccessibleChild( sal_Int32 nChildIndex )
799 {
800     SolarMutexGuard aSolarGuard;
801     CellPos aPos;
802     mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
803 
804     // todo, select table shape?!?
805     SvxTableController* pController = getTableController();
806     if( !(pController && pController->hasSelectedCells()) )
807         return;
808 
809     CellPos aFirstPos, aLastPos;
810     pController->getSelectedCells( aFirstPos, aLastPos );
811 
812     // create a selection where aPos is not part of anymore
813     aFirstPos.mnRow = std::min( aFirstPos.mnRow, aPos.mnRow+1 );
814     aFirstPos.mnCol = std::min( aFirstPos.mnCol, aPos.mnCol+1 );
815     aLastPos.mnRow = std::max( aLastPos.mnRow, aPos.mnRow-1 );
816     aLastPos.mnCol = std::max( aLastPos.mnCol, aPos.mnCol-1 );
817 
818     // new selection may be invalid (child to deselect is not at a border of the selection but in between)
819     if( (aFirstPos.mnRow > aLastPos.mnRow) || (aFirstPos.mnCol > aLastPos.mnCol) )
820         pController->clearSelection(); // if selection is invalid, clear all
821     else
822         pController->setSelectedCells( aFirstPos, aLastPos );
823 }
824 
825 // XAccessibleTableSelection
selectRow(sal_Int32 row)826 sal_Bool SAL_CALL AccessibleTableShape::selectRow( sal_Int32 row )
827 {
828     SolarMutexGuard aSolarGuard;
829     SvxTableController* pController = getTableController();
830     if( !pController )
831         return false;
832     return pController->selectRow( row );
833 }
834 
selectColumn(sal_Int32 column)835 sal_Bool SAL_CALL AccessibleTableShape::selectColumn( sal_Int32 column )
836 {
837     SolarMutexGuard aSolarGuard;
838     SvxTableController* pController = getTableController();
839     if( !pController )
840         return false;
841     return pController->selectColumn( column );
842 }
843 
unselectRow(sal_Int32 row)844 sal_Bool SAL_CALL AccessibleTableShape::unselectRow( sal_Int32 row )
845 {
846     SolarMutexGuard aSolarGuard;
847     SvxTableController* pController = getTableController();
848     if( !pController )
849         return false;
850     return pController->deselectRow( row );
851 }
852 
unselectColumn(sal_Int32 column)853 sal_Bool SAL_CALL AccessibleTableShape::unselectColumn( sal_Int32 column )
854 {
855     SolarMutexGuard aSolarGuard;
856     SvxTableController* pController = getTableController();
857     if( !pController )
858         return false;
859     return pController->deselectColumn( column );
860 }
861 
GetIndexOfSelectedChild(sal_Int32 nSelectedChildIndex) const862 sal_Int32 AccessibleTableShape::GetIndexOfSelectedChild(
863                 sal_Int32 nSelectedChildIndex ) const
864 {
865     sal_Int32 nChildren = const_cast<AccessibleTableShape*>(this)->getAccessibleChildCount();
866 
867     if( nSelectedChildIndex >= nChildren )
868         return -1;
869 
870     sal_Int32 n = 0;
871     while( n < nChildren )
872     {
873         if( const_cast<AccessibleTableShape*>(this)->isAccessibleChildSelected( n ) )
874         {
875             if( 0 == nSelectedChildIndex )
876                 break;
877             else
878                 --nSelectedChildIndex;
879         }
880         ++n;
881     }
882 
883     return n < nChildren ? n : -1;
884 }
getColumnAndRow(sal_Int32 nChildIndex,sal_Int32 & rnColumn,sal_Int32 & rnRow)885 void AccessibleTableShape::getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow )
886 {
887     mxImpl->getColumnAndRow(nChildIndex, rnColumn, rnRow);
888 }
889 
890 // XSelectionChangeListener
891 void SAL_CALL
disposing(const EventObject & aEvent)892     AccessibleTableShape::disposing (const EventObject& aEvent)
893 {
894     AccessibleShape::disposing(aEvent);
895 }
selectionChanged(const EventObject & rEvent)896 void  SAL_CALL AccessibleTableShape::selectionChanged (const EventObject& rEvent)
897 {
898     //sdr::table::CellRef xCellRef = static_cast< sdr::table::CellRef > (rEvent.Source);
899     Reference< XCell > xCell(rEvent.Source, UNO_QUERY);
900     if (!xCell.is())
901         return;
902 
903     rtl::Reference< AccessibleCell > xAccCell = mxImpl->getAccessibleCell( xCell );
904     if (!xAccCell.is())
905         return;
906 
907     sal_Int32 nIndex = xAccCell->getAccessibleIndexInParent(),
908         nCount = getSelectedAccessibleChildCount();
909     bool bSelected = isAccessibleChildSelected(nIndex);
910     if (mnPreviousSelectionCount == 0 && nCount > 0 && bSelected)
911     {
912         xAccCell->SetState(AccessibleStateType::SELECTED);
913         xAccCell->CommitChange(AccessibleEventId::SELECTION_CHANGED, Any(), Any());
914     }
915     else if (bSelected)
916     {
917         xAccCell->SetState(AccessibleStateType::SELECTED);
918         xAccCell->CommitChange(AccessibleEventId::SELECTION_CHANGED_ADD, Any(), Any());
919     }
920     else
921     {
922         xAccCell->ResetState(AccessibleStateType::SELECTED);
923         xAccCell->CommitChange(AccessibleEventId::SELECTION_CHANGED_REMOVE, Any(), Any());
924     }
925     mnPreviousSelectionCount = nCount;
926 }
927 // Get the currently active cell which is text editing
GetActiveAccessibleCell()928 AccessibleCell* AccessibleTableShape::GetActiveAccessibleCell()
929 {
930     rtl::Reference< AccessibleCell > xAccCell;
931     AccessibleCell* pAccCell = nullptr;
932     SvxTableController* pController = getTableController();
933     if (pController)
934     {
935         sdr::table::SdrTableObj* pTableObj = pController->GetTableObj();
936         if ( pTableObj )
937         {
938             const sdr::table::CellRef& xCellRef (pTableObj->getActiveCell());
939             if ( xCellRef.is() )
940             {
941                 try
942                 {
943                     CellPos rPos;
944                     pTableObj->getActiveCellPos( rPos );
945                     xAccCell = mxImpl->getAccessibleCell( rPos.mnRow, rPos.mnCol );
946                     if ( xAccCell.is() )
947                         pAccCell = xAccCell.get();
948                 }
949                 catch ( IndexOutOfBoundsException& ) {}
950             }
951         }
952     }
953     return pAccCell;
954 }
955 
956 //If current active cell is in editing, the focus state should be set to internal text
SetState(sal_Int16 aState)957 bool AccessibleTableShape::SetState (sal_Int16 aState)
958 {
959     if( aState == AccessibleStateType::FOCUSED )
960     {
961         AccessibleCell* pActiveAccessibleCell = GetActiveAccessibleCell();
962         if( pActiveAccessibleCell != nullptr )
963             return pActiveAccessibleCell->SetState(aState);
964     }
965 
966     return AccessibleShape::SetState (aState);
967 }
968 
969 //If current active cell is in editing, the focus state should be reset to internal text
ResetState(sal_Int16 aState)970 bool AccessibleTableShape::ResetState (sal_Int16 aState)
971 {
972     if( aState == AccessibleStateType::FOCUSED )
973     {
974         AccessibleCell* pActiveAccessibleCell = GetActiveAccessibleCell();
975         if( pActiveAccessibleCell != nullptr )
976             return pActiveAccessibleCell->ResetState(aState);
977     }
978 
979     return AccessibleShape::ResetState (aState);
980 }
981 
SetStateDirectly(sal_Int16 aState)982 bool AccessibleTableShape::SetStateDirectly (sal_Int16 aState)
983 {
984     return AccessibleContextBase::SetState (aState);
985 }
986 
ResetStateDirectly(sal_Int16 aState)987 bool AccessibleTableShape::ResetStateDirectly (sal_Int16 aState)
988 {
989     return AccessibleContextBase::ResetState (aState);
990 }
991 
checkCellPosition(sal_Int32 nCol,sal_Int32 nRow)992 void AccessibleTableShape::checkCellPosition( sal_Int32 nCol, sal_Int32 nRow )
993 {
994     if( (nCol >= 0) && (nRow >= 0) && mxImpl->mxTable.is() && (nCol < mxImpl->mxTable->getColumnCount()) && (nRow < mxImpl->mxTable->getRowCount()) )
995         return;
996 
997     throw IndexOutOfBoundsException();
998 }
999 
AccessibleTableHeaderShape(AccessibleTableShape * pTable,bool bRow)1000 AccessibleTableHeaderShape::AccessibleTableHeaderShape( AccessibleTableShape* pTable, bool bRow )
1001 {
1002     mpTable = pTable;
1003     mbRow = bRow;
1004 }
1005 
~AccessibleTableHeaderShape()1006 AccessibleTableHeaderShape::~AccessibleTableHeaderShape()
1007 {
1008     mpTable = nullptr;
1009 }
1010 
1011 // XAccessible
getAccessibleContext()1012 Reference< XAccessibleContext > SAL_CALL AccessibleTableHeaderShape::getAccessibleContext()
1013 {
1014     return this;
1015 }
1016 
1017 // XAccessibleContext
getAccessibleChildCount()1018 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleChildCount( )
1019 {
1020     return getAccessibleRowCount() * getAccessibleColumnCount();
1021 }
1022 
getAccessibleChild(sal_Int32 i)1023 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleChild( sal_Int32 i )
1024 {
1025     return mpTable->getAccessibleChild( i );
1026 }
1027 
getAccessibleParent()1028 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleParent()
1029 {
1030     Reference< XAccessible > XParent;
1031     return XParent;
1032 }
1033 
getAccessibleIndexInParent()1034 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleIndexInParent()
1035 {
1036     return -1;
1037 }
1038 
getAccessibleRole()1039 sal_Int16 SAL_CALL AccessibleTableHeaderShape::getAccessibleRole()
1040 {
1041     return mpTable->getAccessibleRole();
1042 }
1043 
getAccessibleDescription()1044 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleDescription()
1045 {
1046     return mpTable->getAccessibleDescription();
1047 }
1048 
getAccessibleName()1049 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleName()
1050 {
1051     return mpTable->getAccessibleName();
1052 }
1053 
getAccessibleStateSet()1054 Reference< XAccessibleStateSet > SAL_CALL AccessibleTableHeaderShape::getAccessibleStateSet()
1055 {
1056     return mpTable->getAccessibleStateSet();
1057 }
1058 
getAccessibleRelationSet()1059 Reference< XAccessibleRelationSet > SAL_CALL AccessibleTableHeaderShape::getAccessibleRelationSet()
1060 {
1061     return mpTable->getAccessibleRelationSet();
1062 }
1063 
getLocale()1064 Locale SAL_CALL AccessibleTableHeaderShape::getLocale()
1065 {
1066     return mpTable->getLocale();
1067 }
1068 
1069 //XAccessibleComponent
containsPoint(const css::awt::Point & aPoint)1070 sal_Bool SAL_CALL AccessibleTableHeaderShape::containsPoint ( const css::awt::Point& aPoint )
1071 {
1072     return mpTable->containsPoint( aPoint );
1073 }
1074 
getAccessibleAtPoint(const css::awt::Point & aPoint)1075 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleAtPoint ( const css::awt::Point& aPoint)
1076 {
1077     return mpTable->getAccessibleAtPoint( aPoint );
1078 }
1079 
getBounds()1080 css::awt::Rectangle SAL_CALL AccessibleTableHeaderShape::getBounds()
1081 {
1082     return mpTable->getBounds();
1083 }
1084 
getLocation()1085 css::awt::Point SAL_CALL AccessibleTableHeaderShape::getLocation()
1086 {
1087     return mpTable->getLocation();
1088 }
1089 
getLocationOnScreen()1090 css::awt::Point SAL_CALL AccessibleTableHeaderShape::getLocationOnScreen()
1091 {
1092     return mpTable->getLocationOnScreen();
1093 }
1094 
getSize()1095 css::awt::Size SAL_CALL AccessibleTableHeaderShape::getSize()
1096 {
1097     return mpTable->getSize();
1098 }
1099 
getForeground()1100 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getForeground()
1101 {
1102     return mpTable->getForeground();
1103 }
1104 
getBackground()1105 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getBackground()
1106 {
1107     return mpTable->getBackground();
1108 }
1109 
grabFocus()1110 void SAL_CALL AccessibleTableHeaderShape::grabFocus()
1111 {
1112     mpTable->grabFocus();
1113 }
1114 // XAccessibleTable
getAccessibleRowCount()1115 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleRowCount()
1116 {
1117     return mbRow ? 1 : mpTable->getAccessibleRowCount();
1118 }
1119 
getAccessibleColumnCount()1120 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnCount()
1121 {
1122     return !mbRow ? 1 : mpTable->getAccessibleColumnCount();
1123 }
1124 
getAccessibleRowDescription(sal_Int32 nRow)1125 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleRowDescription( sal_Int32 nRow )
1126 {
1127     return mpTable->getAccessibleRowDescription( nRow );
1128 }
1129 
getAccessibleColumnDescription(sal_Int32 nColumn)1130 OUString SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnDescription( sal_Int32 nColumn )
1131 {
1132     return mpTable->getAccessibleColumnDescription( nColumn );
1133 }
1134 
getAccessibleRowExtentAt(sal_Int32 nRow,sal_Int32 nColumn)1135 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
1136 {
1137     return mpTable->getAccessibleRowExtentAt( nRow, nColumn );
1138 }
1139 
getAccessibleColumnExtentAt(sal_Int32 nRow,sal_Int32 nColumn)1140 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn )
1141 {
1142     return mpTable->getAccessibleColumnExtentAt( nRow, nColumn );
1143 }
1144 
getAccessibleRowHeaders()1145 Reference< XAccessibleTable > SAL_CALL AccessibleTableHeaderShape::getAccessibleRowHeaders(  )
1146 {
1147     Reference< XAccessibleTable > xRet;
1148     return xRet;
1149 }
1150 
getAccessibleColumnHeaders()1151 Reference< XAccessibleTable > SAL_CALL AccessibleTableHeaderShape::getAccessibleColumnHeaders(  )
1152 {
1153     Reference< XAccessibleTable > xRet;
1154     return xRet;
1155 }
1156 
getSelectedAccessibleRows()1157 Sequence< sal_Int32 > SAL_CALL AccessibleTableHeaderShape::getSelectedAccessibleRows(  )
1158 {
1159     sal_Int32 nRow = getAccessibleRowCount();
1160     ::std::vector<bool> aSelected( nRow, true );
1161     sal_Int32 nCount = nRow;
1162     for( sal_Int32 i = 0; i < nRow; i++ )
1163     {
1164         try
1165         {
1166             aSelected[i] = isAccessibleRowSelected( i );
1167         }
1168         catch( ... )
1169         {
1170             return Sequence< sal_Int32 >();
1171         }
1172 
1173         if( !aSelected[i] )
1174             nCount--;
1175     }
1176     Sequence < sal_Int32 > aRet( nCount );
1177     sal_Int32 *pRet = aRet.getArray();
1178     sal_Int32 nPos = 0;
1179     size_t nSize = aSelected.size();
1180     for( size_t i=0; i < nSize && nPos < nCount; i++ )
1181     {
1182         if( aSelected[i] )
1183         {
1184             *pRet++ = i;
1185             nPos++;
1186         }
1187     }
1188 
1189     return aRet;
1190 }
1191 
getSelectedAccessibleColumns()1192 Sequence< sal_Int32 > SAL_CALL AccessibleTableHeaderShape::getSelectedAccessibleColumns(  )
1193 {
1194     sal_Int32 nColumn = getAccessibleColumnCount();
1195     ::std::vector<bool> aSelected( nColumn, true );
1196     sal_Int32 nCount = nColumn;
1197     for( sal_Int32 i = 0; i < nColumn; i++ )
1198     {
1199         try
1200         {
1201             aSelected[i] = isAccessibleColumnSelected( i );
1202         }
1203         catch( ... )
1204         {
1205             return Sequence< sal_Int32 >();
1206         }
1207 
1208         if( !aSelected[i] )
1209             nCount--;
1210     }
1211     Sequence < sal_Int32 > aRet( nCount );
1212     sal_Int32 *pRet = aRet.getArray();
1213     sal_Int32 nPos = 0;
1214     size_t nSize = aSelected.size();
1215     for( size_t i=0; i < nSize && nPos < nCount; i++ )
1216     {
1217         if( aSelected[i] )
1218         {
1219             *pRet++ = i;
1220             nPos++;
1221         }
1222     }
1223 
1224     return aRet;
1225 }
1226 
isAccessibleRowSelected(sal_Int32 nRow)1227 sal_Bool SAL_CALL AccessibleTableHeaderShape::isAccessibleRowSelected( sal_Int32 nRow )
1228 {
1229     return mpTable->isAccessibleRowSelected( nRow );
1230 }
1231 
isAccessibleColumnSelected(sal_Int32 nColumn)1232 sal_Bool SAL_CALL AccessibleTableHeaderShape::isAccessibleColumnSelected( sal_Int32 nColumn )
1233 {
1234     return mpTable->isAccessibleColumnSelected( nColumn );
1235 }
1236 
getAccessibleCellAt(sal_Int32 nRow,sal_Int32 nColumn)1237 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
1238 {
1239     return mpTable->getAccessibleCellAt( nRow, nColumn );
1240 }
1241 
getAccessibleCaption()1242 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleCaption(  )
1243 {
1244     return mpTable->getAccessibleCaption();
1245 }
1246 
getAccessibleSummary()1247 Reference< XAccessible > SAL_CALL AccessibleTableHeaderShape::getAccessibleSummary(  )
1248 {
1249     return mpTable->getAccessibleSummary();
1250 }
1251 
isAccessibleSelected(sal_Int32 nRow,sal_Int32 nColumn)1252 sal_Bool SAL_CALL AccessibleTableHeaderShape::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn )
1253 {
1254     return mpTable->isAccessibleSelected( nRow, nColumn );
1255 }
1256 
getAccessibleIndex(sal_Int32 nRow,sal_Int32 nColumn)1257 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn )
1258 {
1259     return mpTable->getAccessibleIndex( nRow, nColumn );
1260 }
1261 
getAccessibleRow(sal_Int32 nChildIndex)1262 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleRow( sal_Int32 nChildIndex )
1263 {
1264     return mpTable->getAccessibleRow( nChildIndex );
1265 }
1266 
getAccessibleColumn(sal_Int32 nChildIndex)1267 sal_Int32 SAL_CALL AccessibleTableHeaderShape::getAccessibleColumn( sal_Int32 nChildIndex )
1268 {
1269     return mpTable->getAccessibleColumn( nChildIndex );
1270 }
1271 
1272 // XAccessibleTableSelection
selectRow(sal_Int32 row)1273 sal_Bool SAL_CALL AccessibleTableHeaderShape::selectRow( sal_Int32 row )
1274 {
1275     if( mbRow )
1276         return mpTable->selectRow( row );
1277     else
1278     {
1279         mpTable->clearAccessibleSelection();
1280         sal_Int32 nIndex = mpTable->getAccessibleIndex( row, 0 );
1281         mpTable->selectAccessibleChild( nIndex );
1282         return true;
1283     }
1284 }
1285 
selectColumn(sal_Int32 column)1286 sal_Bool SAL_CALL AccessibleTableHeaderShape::selectColumn( sal_Int32 column )
1287 {
1288     if( !mbRow )
1289         return mpTable->selectColumn( column );
1290     else
1291     {
1292         mpTable->clearAccessibleSelection();
1293         sal_Int32 nIndex = mpTable->getAccessibleIndex( 0, column );
1294         mpTable->selectAccessibleChild( nIndex );
1295         return true;
1296     }
1297 }
1298 
unselectRow(sal_Int32 row)1299 sal_Bool SAL_CALL AccessibleTableHeaderShape::unselectRow( sal_Int32 row )
1300 {
1301     if( mbRow )
1302         return mpTable->unselectRow( row );
1303     else
1304     {
1305         sal_Int32 nIndex = mpTable->getAccessibleIndex( row, 0 );
1306         mpTable->deselectAccessibleChild( nIndex );
1307         return true;
1308     }
1309 }
1310 
unselectColumn(sal_Int32 column)1311 sal_Bool SAL_CALL AccessibleTableHeaderShape::unselectColumn( sal_Int32 column )
1312 {
1313     if( !mbRow )
1314         return mpTable->unselectColumn( column );
1315     else
1316     {
1317         sal_Int32 nIndex = mpTable->getAccessibleIndex( 0, column );
1318         mpTable->deselectAccessibleChild( nIndex );
1319         return true;
1320     }
1321 }
1322 }
1323 
1324 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1325