Line data Source code
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 :
25 : #include <comphelper/accessiblewrapper.hxx>
26 : #include <osl/mutex.hxx>
27 : #include <vcl/svapp.hxx>
28 :
29 : #include <svx/AccessibleTableShape.hxx>
30 : #include <svx/sdr/table/tablecontroller.hxx>
31 : #include "accessiblecell.hxx"
32 :
33 : #include <algorithm>
34 :
35 : #include <cppuhelper/implbase1.hxx>
36 :
37 :
38 : using namespace ::accessibility;
39 : using namespace ::sdr::table;
40 : using namespace ::com::sun::star::accessibility;
41 : using namespace ::com::sun::star::uno;
42 : using namespace ::com::sun::star::beans;
43 : using namespace ::com::sun::star::util;
44 : using namespace ::com::sun::star::lang;
45 : using namespace ::com::sun::star::drawing;
46 : using namespace ::com::sun::star::table;
47 : using namespace ::com::sun::star::container;
48 :
49 : namespace accessibility
50 : {
51 :
52 : struct hash
53 : {
54 0 : std::size_t operator()( const Reference< XCell >& xCell ) const
55 : {
56 0 : return std::size_t( xCell.get() );
57 : }
58 : };
59 :
60 : typedef boost::unordered_map< Reference< XCell >, rtl::Reference< AccessibleCell >, hash > AccessibleCellMap;
61 :
62 : //-----------------------------------------------------------------------------
63 : // AccessibleTableShapeImpl
64 : //-----------------------------------------------------------------------------
65 :
66 0 : class AccessibleTableShapeImpl : public cppu::WeakImplHelper1< XModifyListener >
67 : {
68 : public:
69 : AccessibleTableShapeImpl( AccessibleShapeTreeInfo& rShapeTreeInfo );
70 :
71 : void init( const Reference< XAccessible>& xAccessible, const Reference< XTable >& xTable );
72 : void dispose();
73 :
74 : Reference< XAccessible > getAccessibleChild( sal_Int32 i ) throw(IndexOutOfBoundsException);
75 : void getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow ) throw (IndexOutOfBoundsException );
76 :
77 : // XModifyListener
78 : virtual void SAL_CALL modified( const EventObject& aEvent ) throw (RuntimeException);
79 :
80 : // XEventListener
81 : virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException);
82 :
83 : AccessibleShapeTreeInfo& mrShapeTreeInfo;
84 : Reference< XTable > mxTable;
85 : AccessibleCellMap maChildMap;
86 : Reference< XAccessible> mxAccessible;
87 : };
88 :
89 : //-----------------------------------------------------------------------------
90 :
91 0 : AccessibleTableShapeImpl::AccessibleTableShapeImpl( AccessibleShapeTreeInfo& rShapeTreeInfo )
92 0 : : mrShapeTreeInfo( rShapeTreeInfo )
93 : {
94 0 : }
95 :
96 : //-----------------------------------------------------------------------------
97 :
98 0 : void AccessibleTableShapeImpl::init( const Reference< XAccessible>& xAccessible, const Reference< XTable >& xTable )
99 : {
100 0 : mxAccessible = xAccessible;
101 0 : mxTable = xTable;
102 :
103 0 : if( mxTable.is() )
104 : {
105 0 : Reference< XModifyListener > xListener( this );
106 0 : mxTable->addModifyListener( xListener );
107 : }
108 0 : }
109 :
110 : //-----------------------------------------------------------------------------
111 :
112 0 : void AccessibleTableShapeImpl::dispose()
113 : {
114 0 : if( mxTable.is() )
115 : {
116 0 : Reference< XModifyListener > xListener( this );
117 0 : mxTable->removeModifyListener( xListener );
118 0 : mxTable.clear();
119 : }
120 0 : mxAccessible.clear();
121 0 : }
122 :
123 : //-----------------------------------------------------------------------------
124 :
125 0 : Reference< XAccessible > AccessibleTableShapeImpl::getAccessibleChild( sal_Int32 nChildIndex ) throw(IndexOutOfBoundsException)
126 : {
127 0 : sal_Int32 nColumn = 0, nRow = 0;
128 0 : getColumnAndRow( nChildIndex, nColumn, nRow );
129 :
130 0 : Reference< XCell > xCell( mxTable->getCellByPosition( nColumn, nRow ) );
131 0 : AccessibleCellMap::iterator iter( maChildMap.find( xCell ) );
132 :
133 0 : if( iter != maChildMap.end() )
134 : {
135 0 : Reference< XAccessible > xChild( (*iter).second.get() );
136 0 : return xChild;
137 : }
138 : else
139 : {
140 0 : CellRef xCellRef( dynamic_cast< Cell* >( xCell.get() ) );
141 :
142 0 : rtl::Reference< AccessibleCell > xAccessibleCell( new AccessibleCell( mxAccessible, xCellRef, nChildIndex, mrShapeTreeInfo ) );
143 :
144 0 : maChildMap[xCell] = xAccessibleCell;
145 :
146 0 : xAccessibleCell->Init();
147 :
148 0 : Reference< XAccessible > xChild( xAccessibleCell.get() );
149 0 : return xChild;
150 0 : }
151 : }
152 :
153 : //-----------------------------------------------------------------------------
154 :
155 0 : void AccessibleTableShapeImpl::getColumnAndRow( sal_Int32 nChildIndex, sal_Int32& rnColumn, sal_Int32& rnRow ) throw (IndexOutOfBoundsException )
156 : {
157 0 : rnRow = 0;
158 0 : rnColumn = nChildIndex;
159 :
160 0 : if( mxTable.is() )
161 : {
162 0 : const sal_Int32 nColumnCount = mxTable->getColumnCount();
163 0 : while( rnColumn >= nColumnCount )
164 : {
165 0 : rnRow++;
166 0 : rnColumn -= nColumnCount;
167 : }
168 :
169 0 : if( rnRow < mxTable->getRowCount() )
170 0 : return;
171 : }
172 :
173 0 : throw IndexOutOfBoundsException();
174 : }
175 :
176 : // XModifyListener
177 0 : void SAL_CALL AccessibleTableShapeImpl::modified( const EventObject& /*aEvent*/ ) throw (RuntimeException)
178 : {
179 0 : if( mxTable.is() ) try
180 : {
181 : // structural changes may have happened to the table, validate all accessible cell instances
182 0 : AccessibleCellMap aTempChildMap;
183 0 : aTempChildMap.swap( maChildMap );
184 :
185 : // first move all still existing cells to maChildMap again and update their index
186 :
187 0 : const sal_Int32 nRowCount = mxTable->getRowCount();
188 0 : const sal_Int32 nColCount = mxTable->getColumnCount();
189 :
190 0 : sal_Int32 nChildIndex = 0;
191 :
192 0 : for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
193 : {
194 0 : for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
195 : {
196 0 : Reference< XCell > xCell( mxTable->getCellByPosition( nCol, nRow ) );
197 0 : AccessibleCellMap::iterator iter( aTempChildMap.find( xCell ) );
198 :
199 0 : if( iter != aTempChildMap.end() )
200 : {
201 0 : rtl::Reference< AccessibleCell > xAccessibleCell( (*iter).second );
202 0 : xAccessibleCell->setIndexInParent( nChildIndex );
203 0 : xAccessibleCell->CommitChange(AccessibleEventId::VISIBLE_DATA_CHANGED, Any(), Any());
204 :
205 : // move still existing cell from temporary child map to our child map
206 0 : maChildMap[xCell] = xAccessibleCell;
207 0 : aTempChildMap.erase( iter );
208 : }
209 :
210 0 : ++nChildIndex;
211 0 : }
212 : }
213 :
214 : // all accessible cell instances still left in aTempChildMap must be disposed
215 : // as they are no longer part of the table
216 :
217 0 : for( AccessibleCellMap::iterator iter( aTempChildMap.begin() ); iter != aTempChildMap.end(); ++iter )
218 : {
219 0 : (*iter).second->dispose();
220 0 : }
221 : }
222 0 : catch( Exception& )
223 : {
224 : OSL_FAIL("svx::AccessibleTableShape::modified(), exception caught!");
225 : }
226 0 : }
227 :
228 : // XEventListener
229 0 : void SAL_CALL AccessibleTableShapeImpl::disposing( const EventObject& /*Source*/ ) throw (RuntimeException)
230 : {
231 0 : }
232 :
233 : //-----------------------------------------------------------------------------
234 : // AccessibleTableShape
235 : //-----------------------------------------------------------------------------
236 :
237 : //-----------------------------------------------------------------------------
238 :
239 0 : AccessibleTableShape::AccessibleTableShape( const AccessibleShapeInfo& rShapeInfo, const AccessibleShapeTreeInfo& rShapeTreeInfo)
240 : : AccessibleTableShape_Base(rShapeInfo, rShapeTreeInfo)
241 0 : , mxImpl( new AccessibleTableShapeImpl( maShapeTreeInfo ) )
242 : {
243 0 : }
244 :
245 : //-----------------------------------------------------------------------------
246 :
247 0 : AccessibleTableShape::~AccessibleTableShape (void)
248 : {
249 0 : }
250 :
251 : //-----------------------------------------------------------------------------
252 :
253 0 : void AccessibleTableShape::Init()
254 : {
255 : try
256 : {
257 :
258 0 : Reference< XPropertySet > xSet( mxShape, UNO_QUERY_THROW );
259 0 : Reference< XTable > xTable( xSet->getPropertyValue("Model"), UNO_QUERY_THROW );
260 :
261 0 : mxImpl->init( this, xTable );
262 : }
263 0 : catch( Exception& )
264 : {
265 : OSL_FAIL("AccessibleTableShape::init(), exception caught?");
266 : }
267 :
268 0 : AccessibleTableShape_Base::Init();
269 0 : }
270 :
271 : //-----------------------------------------------------------------------------
272 :
273 0 : SvxTableController* AccessibleTableShape::getTableController()
274 : {
275 0 : SdrView* pView = maShapeTreeInfo.GetSdrView ();
276 0 : if( pView )
277 0 : return dynamic_cast< SvxTableController* >( pView->getSelectionController().get() );
278 : else
279 0 : return 0;
280 : }
281 :
282 : //-----------------------------------------------------------------------------
283 : // XInterface
284 : //-----------------------------------------------------------------------------
285 :
286 0 : Any SAL_CALL AccessibleTableShape::queryInterface( const Type& aType ) throw (RuntimeException)
287 : {
288 0 : return AccessibleTableShape_Base::queryInterface( aType );
289 : }
290 :
291 : //-----------------------------------------------------------------------------
292 :
293 0 : void SAL_CALL AccessibleTableShape::acquire( ) throw ()
294 : {
295 0 : AccessibleTableShape_Base::acquire();
296 0 : }
297 :
298 : //-----------------------------------------------------------------------------
299 :
300 0 : void SAL_CALL AccessibleTableShape::release( ) throw ()
301 : {
302 0 : AccessibleTableShape_Base::release();
303 0 : }
304 :
305 : //-----------------------------------------------------------------------------
306 : // XAccessible
307 : //-----------------------------------------------------------------------------
308 :
309 0 : Reference< XAccessibleContext > SAL_CALL AccessibleTableShape::getAccessibleContext(void) throw (RuntimeException)
310 : {
311 0 : return AccessibleShape::getAccessibleContext ();
312 : }
313 :
314 : //-----------------------------------------------------------------------------
315 0 : OUString SAL_CALL AccessibleTableShape::getImplementationName(void) throw (RuntimeException)
316 : {
317 0 : return OUString( "com.sun.star.comp.accessibility.AccessibleTableShape" );
318 : }
319 :
320 : //-----------------------------------------------------------------------------
321 :
322 0 : OUString AccessibleTableShape::CreateAccessibleBaseName(void) throw (RuntimeException)
323 : {
324 0 : return OUString("TableShape");
325 : }
326 :
327 : //--------------------------------------------------------------------
328 :
329 0 : sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleChildCount( ) throw(RuntimeException)
330 : {
331 0 : SolarMutexGuard aSolarGuard;
332 0 : return mxImpl->mxTable.is() ? mxImpl->mxTable->getRowCount() * mxImpl->mxTable->getColumnCount() : 0;
333 : }
334 :
335 : //--------------------------------------------------------------------
336 0 : Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleChild( sal_Int32 i ) throw(IndexOutOfBoundsException, RuntimeException)
337 : {
338 0 : SolarMutexGuard aSolarGuard;
339 0 : ThrowIfDisposed();
340 :
341 0 : return mxImpl->getAccessibleChild( i );
342 : }
343 :
344 : //--------------------------------------------------------------------
345 0 : Reference< XAccessibleRelationSet > SAL_CALL AccessibleTableShape::getAccessibleRelationSet( ) throw (RuntimeException)
346 : {
347 0 : return AccessibleShape::getAccessibleRelationSet( );
348 : }
349 :
350 : //--------------------------------------------------------------------
351 :
352 0 : sal_Int16 SAL_CALL AccessibleTableShape::getAccessibleRole (void) throw (RuntimeException)
353 : {
354 0 : return AccessibleRole::TABLE;
355 : }
356 :
357 : //--------------------------------------------------------------------
358 :
359 0 : void SAL_CALL AccessibleTableShape::disposing (void)
360 : {
361 0 : mxImpl->dispose();
362 :
363 : // let the base do it's stuff
364 0 : AccessibleShape::disposing();
365 0 : }
366 :
367 : //--------------------------------------------------------------------
368 : // XAccessibleTable
369 : //--------------------------------------------------------------------
370 :
371 0 : sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRowCount() throw (RuntimeException)
372 : {
373 0 : SolarMutexGuard aSolarGuard;
374 0 : return mxImpl->mxTable.is() ? mxImpl->mxTable->getRowCount() : 0;
375 : }
376 :
377 : //--------------------------------------------------------------------
378 :
379 0 : sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumnCount( ) throw (RuntimeException)
380 : {
381 0 : SolarMutexGuard aSolarGuard;
382 0 : return mxImpl->mxTable.is() ? mxImpl->mxTable->getColumnCount() : 0;
383 : }
384 :
385 : //--------------------------------------------------------------------
386 :
387 0 : OUString SAL_CALL AccessibleTableShape::getAccessibleRowDescription( sal_Int32 nRow ) throw (IndexOutOfBoundsException, RuntimeException)
388 : {
389 0 : checkCellPosition( 0, nRow );
390 0 : return OUString();
391 : }
392 :
393 : //--------------------------------------------------------------------
394 :
395 0 : OUString SAL_CALL AccessibleTableShape::getAccessibleColumnDescription( sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException)
396 : {
397 0 : SolarMutexGuard aSolarGuard;
398 0 : checkCellPosition( nColumn, 0 );
399 0 : return OUString();
400 : }
401 :
402 : //--------------------------------------------------------------------
403 :
404 0 : sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException)
405 : {
406 0 : SolarMutexGuard aSolarGuard;
407 0 : checkCellPosition( nColumn, nRow );
408 0 : if( mxImpl->mxTable.is() )
409 : {
410 0 : Reference< XMergeableCell > xCell( mxImpl->mxTable->getCellByPosition( nColumn, nRow ), UNO_QUERY );
411 0 : if( xCell.is() )
412 0 : return xCell->getRowSpan();
413 : }
414 0 : return 1;
415 : }
416 :
417 : //--------------------------------------------------------------------
418 :
419 0 : sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException)
420 : {
421 0 : SolarMutexGuard aSolarGuard;
422 0 : checkCellPosition( nColumn, nRow );
423 0 : if( mxImpl->mxTable.is() )
424 : {
425 0 : Reference< XMergeableCell > xCell( mxImpl->mxTable->getCellByPosition( nColumn, nRow ), UNO_QUERY );
426 0 : if( xCell.is() )
427 0 : return xCell->getColumnSpan();
428 : }
429 0 : return 1;
430 : }
431 :
432 : //--------------------------------------------------------------------
433 :
434 0 : Reference< XAccessibleTable > SAL_CALL AccessibleTableShape::getAccessibleRowHeaders( ) throw (RuntimeException)
435 : {
436 0 : Reference< XAccessibleTable > xRet( this ); // todo
437 0 : return xRet;
438 : }
439 :
440 : //--------------------------------------------------------------------
441 :
442 0 : Reference< XAccessibleTable > SAL_CALL AccessibleTableShape::getAccessibleColumnHeaders( ) throw (RuntimeException)
443 : {
444 0 : Reference< XAccessibleTable > xRet( this ); // todo
445 0 : return xRet;
446 : }
447 :
448 : //--------------------------------------------------------------------
449 :
450 0 : Sequence< sal_Int32 > SAL_CALL AccessibleTableShape::getSelectedAccessibleRows( ) throw (RuntimeException)
451 : {
452 0 : Sequence< sal_Int32 > aRet;
453 0 : return aRet;
454 : }
455 :
456 : //--------------------------------------------------------------------
457 :
458 0 : Sequence< sal_Int32 > SAL_CALL AccessibleTableShape::getSelectedAccessibleColumns( ) throw (RuntimeException)
459 : {
460 0 : Sequence< sal_Int32 > aRet;
461 0 : return aRet;
462 : }
463 :
464 : //--------------------------------------------------------------------
465 :
466 0 : sal_Bool SAL_CALL AccessibleTableShape::isAccessibleRowSelected( sal_Int32 nRow ) throw (IndexOutOfBoundsException, RuntimeException)
467 : {
468 0 : SolarMutexGuard aSolarGuard;
469 0 : checkCellPosition( 0, nRow );
470 0 : return sal_False;
471 : }
472 :
473 : //--------------------------------------------------------------------
474 :
475 0 : sal_Bool SAL_CALL AccessibleTableShape::isAccessibleColumnSelected( sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException)
476 : {
477 0 : SolarMutexGuard aSolarGuard;
478 0 : checkCellPosition( nColumn, 0 );
479 0 : return sal_False;
480 : }
481 :
482 : //--------------------------------------------------------------------
483 :
484 0 : Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException)
485 : {
486 0 : SolarMutexGuard aSolarGuard;
487 0 : checkCellPosition( nColumn, nRow );
488 :
489 0 : sal_Int32 nChildIndex = 0;
490 0 : if( mxImpl->mxTable.is() )
491 0 : nChildIndex = mxImpl->mxTable->getColumnCount() * nRow + nColumn;
492 :
493 0 : return getAccessibleChild( nChildIndex );
494 : }
495 :
496 : //--------------------------------------------------------------------
497 :
498 0 : Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleCaption( ) throw (RuntimeException)
499 : {
500 0 : Reference< XAccessible > xRet;
501 0 : return xRet;
502 : }
503 :
504 : //--------------------------------------------------------------------
505 :
506 0 : Reference< XAccessible > SAL_CALL AccessibleTableShape::getAccessibleSummary( ) throw (RuntimeException)
507 : {
508 0 : Reference< XAccessible > xRet;
509 0 : return xRet;
510 : }
511 :
512 : //--------------------------------------------------------------------
513 :
514 0 : sal_Bool SAL_CALL AccessibleTableShape::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException)
515 : {
516 0 : SolarMutexGuard aSolarGuard;
517 0 : checkCellPosition( nColumn, nRow );
518 :
519 0 : SvxTableController* pController = getTableController();
520 0 : if( pController && pController->hasSelectedCells() )
521 : {
522 0 : CellPos aFirstPos, aLastPos;
523 0 : pController->getSelectedCells( aFirstPos, aLastPos );
524 0 : if( (aFirstPos.mnRow <= nRow) && (aFirstPos.mnCol <= nColumn) && (nRow <= aLastPos.mnRow) && (nColumn <= aLastPos.mnCol) )
525 0 : return sal_True;
526 : }
527 :
528 0 : return sal_False;
529 : }
530 :
531 : //--------------------------------------------------------------------
532 :
533 0 : sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn ) throw (IndexOutOfBoundsException, RuntimeException)
534 : {
535 0 : SolarMutexGuard aSolarGuard;
536 0 : checkCellPosition( nColumn, nRow );
537 0 : return mxImpl->mxTable.is() ? (nRow * mxImpl->mxTable->getColumnCount() + nColumn) : 0;
538 : }
539 :
540 : //--------------------------------------------------------------------
541 :
542 0 : sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleRow( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
543 : {
544 0 : SolarMutexGuard aSolarGuard;
545 0 : sal_Int32 nColumn = 0, nRow = 0;
546 0 : mxImpl->getColumnAndRow( nChildIndex, nColumn, nRow );
547 0 : return nRow;
548 : }
549 :
550 : //--------------------------------------------------------------------
551 :
552 0 : sal_Int32 SAL_CALL AccessibleTableShape::getAccessibleColumn( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
553 : {
554 0 : SolarMutexGuard aSolarGuard;
555 0 : sal_Int32 nColumn = 0, nRow = 0;
556 0 : mxImpl->getColumnAndRow( nChildIndex, nColumn, nRow );
557 0 : return nChildIndex;
558 : }
559 :
560 : //--------------------------------------------------------------------
561 : // XAccessibleSelection
562 : //--------------------------------------------------------------------
563 :
564 0 : void SAL_CALL AccessibleTableShape::selectAccessibleChild( sal_Int32 nChildIndex ) throw ( IndexOutOfBoundsException, RuntimeException )
565 : {
566 0 : SolarMutexGuard aSolarGuard;
567 0 : CellPos aPos;
568 0 : mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
569 :
570 : // todo, select table shape?!?
571 0 : SvxTableController* pController = getTableController();
572 0 : if( pController )
573 : {
574 0 : CellPos aFirstPos( aPos ), aLastPos( aPos );
575 0 : if( pController->hasSelectedCells() )
576 : {
577 0 : pController->getSelectedCells( aFirstPos, aLastPos );
578 :
579 0 : aFirstPos.mnRow = std::min( aFirstPos.mnRow, aPos.mnRow );
580 0 : aFirstPos.mnCol = std::min( aFirstPos.mnCol, aPos.mnCol );
581 0 : aLastPos.mnRow = std::max( aLastPos.mnRow, aPos.mnRow );
582 0 : aLastPos.mnCol = std::max( aLastPos.mnCol, aPos.mnCol );
583 : }
584 0 : pController->setSelectedCells( aFirstPos, aLastPos );
585 0 : }
586 0 : }
587 :
588 : //--------------------------------------------------------------------
589 :
590 0 : sal_Bool SAL_CALL AccessibleTableShape::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw ( IndexOutOfBoundsException, RuntimeException )
591 : {
592 0 : SolarMutexGuard aSolarGuard;
593 0 : CellPos aPos;
594 0 : mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
595 :
596 0 : return isAccessibleSelected(aPos.mnCol, aPos.mnRow);
597 : }
598 :
599 : //--------------------------------------------------------------------
600 :
601 0 : void SAL_CALL AccessibleTableShape::clearAccessibleSelection() throw ( RuntimeException )
602 : {
603 0 : SolarMutexGuard aSolarGuard;
604 :
605 0 : SvxTableController* pController = getTableController();
606 0 : if( pController )
607 0 : pController->clearSelection();
608 0 : }
609 : //--------------------------------------------------------------------
610 :
611 0 : void SAL_CALL AccessibleTableShape::selectAllAccessibleChildren() throw ( RuntimeException )
612 : {
613 0 : SolarMutexGuard aSolarGuard;
614 :
615 : // todo: force selection of shape?
616 0 : SvxTableController* pController = getTableController();
617 0 : if( pController )
618 0 : pController->selectAll();
619 0 : }
620 :
621 : //--------------------------------------------------------------------
622 :
623 0 : sal_Int32 SAL_CALL AccessibleTableShape::getSelectedAccessibleChildCount() throw ( RuntimeException )
624 : {
625 0 : SolarMutexGuard aSolarGuard;
626 :
627 0 : SvxTableController* pController = getTableController();
628 0 : if( pController && pController->hasSelectedCells() )
629 : {
630 0 : CellPos aFirstPos, aLastPos;
631 0 : pController->getSelectedCells( aFirstPos, aLastPos );
632 :
633 0 : const sal_Int32 nSelectedColumns = std::max( (sal_Int32)0, aLastPos.mnCol - aFirstPos.mnCol ) + 1;
634 0 : const sal_Int32 nSelectedRows = std::max( (sal_Int32)0, aLastPos.mnRow - aFirstPos.mnRow ) + 1;
635 0 : return nSelectedRows * nSelectedColumns;
636 : }
637 :
638 0 : return 0;
639 : }
640 :
641 : //--------------------------------------------------------------------
642 :
643 0 : Reference< XAccessible > SAL_CALL AccessibleTableShape::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw ( IndexOutOfBoundsException, RuntimeException)
644 : {
645 0 : SolarMutexGuard aSolarGuard;
646 :
647 0 : SvxTableController* pController = getTableController();
648 0 : if( pController && pController->hasSelectedCells() )
649 : {
650 0 : CellPos aFirstPos, aLastPos;
651 0 : pController->getSelectedCells( aFirstPos, aLastPos );
652 :
653 0 : const sal_Int32 nSelectedColumns = std::max( (sal_Int32)0, aLastPos.mnCol - aFirstPos.mnCol ) + 1;
654 0 : const sal_Int32 nSelectedRows = std::max( (sal_Int32)0, aLastPos.mnRow - aFirstPos.mnRow ) + 1;
655 :
656 0 : if( nSelectedChildIndex < (nSelectedRows * nSelectedColumns) )
657 : {
658 0 : while( nSelectedChildIndex >= nSelectedColumns )
659 : {
660 0 : aFirstPos.mnRow++;
661 0 : nSelectedChildIndex -= nSelectedColumns;
662 : }
663 0 : return getAccessibleCellAt( nSelectedColumns, aFirstPos.mnRow );
664 : }
665 : }
666 :
667 0 : throw IndexOutOfBoundsException();
668 : }
669 :
670 : //--------------------------------------------------------------------
671 :
672 0 : void SAL_CALL AccessibleTableShape::deselectAccessibleChild( sal_Int32 nChildIndex ) throw ( IndexOutOfBoundsException, RuntimeException )
673 : {
674 0 : SolarMutexGuard aSolarGuard;
675 0 : CellPos aPos;
676 0 : mxImpl->getColumnAndRow( nChildIndex, aPos.mnCol, aPos.mnRow );
677 :
678 : // todo, select table shape?!?
679 0 : SvxTableController* pController = getTableController();
680 0 : if( pController && pController->hasSelectedCells() )
681 : {
682 0 : CellPos aFirstPos, aLastPos;
683 0 : pController->getSelectedCells( aFirstPos, aLastPos );
684 :
685 : // create a selection where aPos is not part of anymore
686 0 : aFirstPos.mnRow = std::min( aFirstPos.mnRow, aPos.mnRow+1 );
687 0 : aFirstPos.mnCol = std::min( aFirstPos.mnCol, aPos.mnCol+1 );
688 0 : aLastPos.mnRow = std::max( aLastPos.mnRow, aPos.mnRow-1 );
689 0 : aLastPos.mnCol = std::max( aLastPos.mnCol, aPos.mnCol-1 );
690 :
691 : // new selection may be invalid (child to deselect is not at a border of the selection but in between)
692 0 : if( (aFirstPos.mnRow > aLastPos.mnRow) || (aFirstPos.mnCol > aLastPos.mnCol) )
693 0 : pController->clearSelection(); // if selection is invalid, clear all
694 : else
695 0 : pController->setSelectedCells( aFirstPos, aLastPos );
696 0 : }
697 0 : }
698 :
699 : //--------------------------------------------------------------------
700 :
701 0 : void AccessibleTableShape::checkCellPosition( sal_Int32 nCol, sal_Int32 nRow ) throw ( IndexOutOfBoundsException )
702 : {
703 0 : if( (nCol >= 0) && (nRow >= 0) && mxImpl->mxTable.is() && (nCol < mxImpl->mxTable->getColumnCount()) && (nRow < mxImpl->mxTable->getRowCount()) )
704 0 : return;
705 :
706 0 : throw IndexOutOfBoundsException();
707 : }
708 :
709 216 : }
710 :
711 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|