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