1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "AccessibleSpreadsheet.hxx"
21 #include "AccessibilityHints.hxx"
22 #include "AccessibleCell.hxx"
23 #include "AccessibleDocument.hxx"
24 #include "tabvwsh.hxx"
25 #include "document.hxx"
28 #include "markdata.hxx"
30 #include <unotools/accessiblestatesethelper.hxx>
31 #include <com/sun/star/accessibility/AccessibleRole.hpp>
32 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
33 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
34 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
35 #include <comphelper/servicehelper.hxx>
36 #include <tools/gen.hxx>
37 #include <svtools/colorcfg.hxx>
38 #include <vcl/svapp.hxx>
42 using namespace ::com::sun::star
;
43 using namespace ::com::sun::star::accessibility
;
45 //===== internal ============================================================
47 // FIXME: really unclear why we have an ScAccessibleTableBase with
48 // only this single sub-class
49 ScAccessibleSpreadsheet::ScAccessibleSpreadsheet(
50 ScAccessibleDocument
* pAccDoc
,
51 ScTabViewShell
* pViewShell
,
55 ScAccessibleTableBase (pAccDoc
, GetDocument(pViewShell
),
56 ScRange(ScAddress(0, 0, nTab
),ScAddress(MAXCOL
, MAXROW
, nTab
))),
57 mbIsSpreadsheet( sal_True
)
59 ConstructScAccessibleSpreadsheet( pAccDoc
, pViewShell
, nTab
, eSplitPos
);
62 ScAccessibleSpreadsheet::ScAccessibleSpreadsheet(
63 ScAccessibleSpreadsheet
& rParent
, const ScRange
& rRange
) :
64 ScAccessibleTableBase( rParent
.mpAccDoc
, rParent
.mpDoc
, rRange
),
65 mbIsSpreadsheet( false )
67 ConstructScAccessibleSpreadsheet( rParent
.mpAccDoc
, rParent
.mpViewShell
, rParent
.mnTab
, rParent
.meSplitPos
);
70 ScAccessibleSpreadsheet::~ScAccessibleSpreadsheet()
73 delete mpMarkedRanges
;
74 if (mpSortedMarkedCells
)
75 delete mpSortedMarkedCells
;
77 mpViewShell
->RemoveAccessibilityObject(*this);
80 void ScAccessibleSpreadsheet::ConstructScAccessibleSpreadsheet(
81 ScAccessibleDocument
* pAccDoc
,
82 ScTabViewShell
* pViewShell
,
86 mpViewShell
= pViewShell
;
88 mpSortedMarkedCells
= 0;
91 meSplitPos
= eSplitPos
;
93 mbHasSelection
= false;
95 mbIsFocusSend
= false;
96 maVisCells
= GetVisCells(GetVisArea(mpViewShell
, meSplitPos
));
99 mpViewShell
->AddAccessibilityObject(*this);
101 const ScViewData
& rViewData
= *mpViewShell
->GetViewData();
102 const ScMarkData
& rMarkData
= rViewData
.GetMarkData();
103 maActiveCell
= rViewData
.GetCurPos();
104 mbHasSelection
= rMarkData
.GetTableSelect(maActiveCell
.Tab()) &&
105 (rMarkData
.IsMarked() || rMarkData
.IsMultiMarked());
106 mpAccCell
= GetAccessibleCellAt(maActiveCell
.Row(), maActiveCell
.Col());
107 mpAccCell
->acquire();
112 void SAL_CALL
ScAccessibleSpreadsheet::disposing()
114 SolarMutexGuard aGuard
;
117 mpViewShell
->RemoveAccessibilityObject(*this);
122 mpAccCell
->release();
126 ScAccessibleTableBase::disposing();
129 void ScAccessibleSpreadsheet::CompleteSelectionChanged(sal_Bool bNewState
)
132 DELETEZ(mpMarkedRanges
);
133 if (mpSortedMarkedCells
)
134 DELETEZ(mpSortedMarkedCells
);
136 mbHasSelection
= bNewState
;
138 AccessibleEventObject aEvent
;
139 aEvent
.EventId
= AccessibleEventId::STATE_CHANGED
;
141 aEvent
.NewValue
= uno::makeAny(AccessibleStateType::SELECTED
);
143 aEvent
.OldValue
= uno::makeAny(AccessibleStateType::SELECTED
);
144 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
146 CommitChange(aEvent
);
149 void ScAccessibleSpreadsheet::LostFocus()
151 AccessibleEventObject aEvent
;
152 aEvent
.EventId
= AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
;
153 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
154 uno::Reference
< XAccessible
> xOld
= mpAccCell
;
155 aEvent
.OldValue
<<= xOld
;
157 CommitChange(aEvent
);
162 void ScAccessibleSpreadsheet::GotFocus()
166 AccessibleEventObject aEvent
;
167 aEvent
.EventId
= AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
;
168 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
169 uno::Reference
< XAccessible
> xNew
= mpAccCell
;
170 aEvent
.NewValue
<<= xNew
;
172 CommitChange(aEvent
);
175 void ScAccessibleSpreadsheet::BoundingBoxChanged()
177 AccessibleEventObject aEvent
;
178 aEvent
.EventId
= AccessibleEventId::BOUNDRECT_CHANGED
;
179 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
181 CommitChange(aEvent
);
184 void ScAccessibleSpreadsheet::VisAreaChanged()
186 AccessibleEventObject aEvent
;
187 aEvent
.EventId
= AccessibleEventId::VISIBLE_DATA_CHANGED
;
188 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
190 CommitChange(aEvent
);
193 //===== SfxListener =====================================================
195 void ScAccessibleSpreadsheet::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
197 if (rHint
.ISA( SfxSimpleHint
) )
199 const SfxSimpleHint
& rRef
= (const SfxSimpleHint
&)rHint
;
200 // only notify if child exist, otherwise it is not necessary
201 if ((rRef
.GetId() == SC_HINT_ACC_CURSORCHANGED
))
205 ScAddress aNewCell
= mpViewShell
->GetViewData()->GetCurPos();
206 sal_Bool
bNewMarked(mpViewShell
->GetViewData()->GetMarkData().GetTableSelect(aNewCell
.Tab()) &&
207 (mpViewShell
->GetViewData()->GetMarkData().IsMarked() ||
208 mpViewShell
->GetViewData()->GetMarkData().IsMultiMarked()));
209 sal_Bool
bNewCellSelected(isAccessibleSelected(aNewCell
.Row(), aNewCell
.Col()));
210 if ((bNewMarked
!= mbHasSelection
) ||
211 (!bNewCellSelected
&& bNewMarked
) ||
212 (bNewCellSelected
&& mbHasSelection
))
215 DELETEZ(mpMarkedRanges
);
216 if (mpSortedMarkedCells
)
217 DELETEZ(mpSortedMarkedCells
);
218 AccessibleEventObject aEvent
;
219 aEvent
.EventId
= AccessibleEventId::SELECTION_CHANGED
;
220 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
222 mbHasSelection
= bNewMarked
;
224 CommitChange(aEvent
);
227 // active descendant changed event (new cell selected)
228 bool bFireActiveDescChanged
= (aNewCell
!= maActiveCell
) &&
229 (aNewCell
.Tab() == maActiveCell
.Tab()) && IsFocused();
231 /* Remember old active cell and set new active cell.
232 #i82409# always update the class members mpAccCell and
233 maActiveCell, even if the sheet is not focused, e.g. when
234 using the name box in the toolbar. */
235 uno::Reference
< XAccessible
> xOld
= mpAccCell
;
236 mpAccCell
->release();
237 mpAccCell
= GetAccessibleCellAt(aNewCell
.Row(), aNewCell
.Col());
238 mpAccCell
->acquire();
240 uno::Reference
< XAccessible
> xNew
= mpAccCell
;
241 maActiveCell
= aNewCell
;
243 // #i14108# fire event only if sheet is focused
244 if( bFireActiveDescChanged
)
246 AccessibleEventObject aEvent
;
247 aEvent
.EventId
= AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
;
248 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
249 aEvent
.OldValue
<<= xOld
;
250 aEvent
.NewValue
<<= xNew
;
251 CommitChange(aEvent
);
255 else if ((rRef
.GetId() == SC_HINT_DATACHANGED
))
258 CommitTableModelChange(maRange
.aStart
.Row(), maRange
.aStart
.Col(), maRange
.aEnd
.Row(), maRange
.aEnd
.Col(), AccessibleTableModelChangeType::UPDATE
);
262 // commented out, because to use a ModelChangeEvent is not the right way
263 // at the moment there is no way, but the Java/Gnome Api should be extended sometime
266 Rectangle aNewVisCells(GetVisCells(GetVisArea(mpViewShell, meSplitPos)));
268 Rectangle aNewPos(aNewVisCells);
270 if (aNewVisCells.IsOver(maVisCells))
271 aNewPos.Union(maVisCells);
273 CommitTableModelChange(maVisCells.Top(), maVisCells.Left(), maVisCells.Bottom(), maVisCells.Right(), AccessibleTableModelChangeType::UPDATE);
275 maVisCells = aNewVisCells;
277 CommitTableModelChange(aNewPos.Top(), aNewPos.Left(), aNewPos.Bottom(), aNewPos.Right(), AccessibleTableModelChangeType::UPDATE);
281 else if (rHint
.ISA( ScUpdateRefHint
))
283 const ScUpdateRefHint
& rRef
= (const ScUpdateRefHint
&)rHint
;
284 if (rRef
.GetMode() == URM_INSDEL
&& rRef
.GetDz() == 0) //test whether table is inserted or deleted
286 if (((rRef
.GetRange().aStart
.Col() == maRange
.aStart
.Col()) &&
287 (rRef
.GetRange().aEnd
.Col() == maRange
.aEnd
.Col())) ||
288 ((rRef
.GetRange().aStart
.Row() == maRange
.aStart
.Row()) &&
289 (rRef
.GetRange().aEnd
.Row() == maRange
.aEnd
.Row())))
291 // ignore next SC_HINT_DATACHANGED notification
295 SCsCOL
nX(rRef
.GetDx());
296 SCsROW
nY(rRef
.GetDy());
297 ScRange
aRange(rRef
.GetRange());
298 if ((nX
< 0) || (nY
< 0))
300 OSL_ENSURE(!((nX
< 0) && (nY
< 0)), "should not be possible to remove row and column at the same time");
301 nId
= AccessibleTableModelChangeType::DELETE
;
305 nY
= aRange
.aEnd
.Row() - aRange
.aStart
.Row();
310 nX
= aRange
.aEnd
.Col() - aRange
.aStart
.Col();
313 else if ((nX
> 0) || (nY
> 0))
315 OSL_ENSURE(!((nX
> 0) && (nY
> 0)), "should not be possible to add row and column at the same time");
316 nId
= AccessibleTableModelChangeType::INSERT
;
318 nY
= aRange
.aEnd
.Row() - aRange
.aStart
.Row();
320 nX
= aRange
.aEnd
.Col() - aRange
.aStart
.Col();
324 OSL_FAIL("is it a deletion or a insertion?");
327 CommitTableModelChange(rRef
.GetRange().aStart
.Row(),
328 rRef
.GetRange().aStart
.Col(),
329 rRef
.GetRange().aStart
.Row() + nY
,
330 rRef
.GetRange().aStart
.Col() + nX
, nId
);
332 AccessibleEventObject aEvent
;
333 aEvent
.EventId
= AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
;
334 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
335 uno::Reference
< XAccessible
> xNew
= mpAccCell
;
336 aEvent
.NewValue
<<= xNew
;
338 CommitChange(aEvent
);
343 ScAccessibleTableBase::Notify(rBC
, rHint
);
346 //===== XAccessibleTable ================================================
348 uno::Reference
< XAccessibleTable
> SAL_CALL
ScAccessibleSpreadsheet::getAccessibleRowHeaders( )
349 throw (uno::RuntimeException
)
351 SolarMutexGuard aGuard
;
353 uno::Reference
< XAccessibleTable
> xAccessibleTable
;
354 if( mpDoc
&& mbIsSpreadsheet
)
356 if( const ScRange
* pRowRange
= mpDoc
->GetRepeatRowRange( mnTab
) )
358 SCROW nStart
= pRowRange
->aStart
.Row();
359 SCROW nEnd
= pRowRange
->aEnd
.Row();
360 if( (0 <= nStart
) && (nStart
<= nEnd
) && (nEnd
<= MAXROW
) )
361 xAccessibleTable
.set( new ScAccessibleSpreadsheet( *this, ScRange( 0, nStart
, mnTab
, MAXCOL
, nEnd
, mnTab
) ) );
364 return xAccessibleTable
;
367 uno::Reference
< XAccessibleTable
> SAL_CALL
ScAccessibleSpreadsheet::getAccessibleColumnHeaders( )
368 throw (uno::RuntimeException
)
370 SolarMutexGuard aGuard
;
372 uno::Reference
< XAccessibleTable
> xAccessibleTable
;
373 if( mpDoc
&& mbIsSpreadsheet
)
375 if( const ScRange
* pColRange
= mpDoc
->GetRepeatColRange( mnTab
) )
377 SCCOL nStart
= pColRange
->aStart
.Col();
378 SCCOL nEnd
= pColRange
->aEnd
.Col();
379 if( (0 <= nStart
) && (nStart
<= nEnd
) && (nEnd
<= MAXCOL
) )
380 xAccessibleTable
.set( new ScAccessibleSpreadsheet( *this, ScRange( nStart
, 0, mnTab
, nEnd
, MAXROW
, mnTab
) ) );
383 return xAccessibleTable
;
386 uno::Sequence
< sal_Int32
> SAL_CALL
ScAccessibleSpreadsheet::getSelectedAccessibleRows( )
387 throw (uno::RuntimeException
)
389 SolarMutexGuard aGuard
;
391 uno::Sequence
<sal_Int32
> aSequence
;
392 if (mpViewShell
&& mpViewShell
->GetViewData())
394 aSequence
.realloc(maRange
.aEnd
.Row() - maRange
.aStart
.Row() + 1);
395 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData()->GetMarkData();
396 sal_Int32
* pSequence
= aSequence
.getArray();
398 for (SCROW i
= maRange
.aStart
.Row(); i
<= maRange
.aEnd
.Row(); ++i
)
400 if (rMarkdata
.IsRowMarked(i
))
402 pSequence
[nCount
] = i
;
406 aSequence
.realloc(nCount
);
409 aSequence
.realloc(0);
413 uno::Sequence
< sal_Int32
> SAL_CALL
ScAccessibleSpreadsheet::getSelectedAccessibleColumns( )
414 throw (uno::RuntimeException
)
416 SolarMutexGuard aGuard
;
418 uno::Sequence
<sal_Int32
> aSequence
;
419 if (mpViewShell
&& mpViewShell
->GetViewData())
421 aSequence
.realloc(maRange
.aEnd
.Col() - maRange
.aStart
.Col() + 1);
422 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData()->GetMarkData();
423 sal_Int32
* pSequence
= aSequence
.getArray();
425 for (SCCOL i
= maRange
.aStart
.Col(); i
<= maRange
.aEnd
.Col(); ++i
)
427 if (rMarkdata
.IsColumnMarked(i
))
429 pSequence
[nCount
] = i
;
433 aSequence
.realloc(nCount
);
436 aSequence
.realloc(0);
440 sal_Bool SAL_CALL
ScAccessibleSpreadsheet::isAccessibleRowSelected( sal_Int32 nRow
)
441 throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
)
443 SolarMutexGuard aGuard
;
446 if ((nRow
> (maRange
.aEnd
.Row() - maRange
.aStart
.Row())) || (nRow
< 0))
447 throw lang::IndexOutOfBoundsException();
449 sal_Bool
bResult(false);
450 if (mpViewShell
&& mpViewShell
->GetViewData())
452 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData()->GetMarkData();
453 bResult
= rMarkdata
.IsRowMarked((SCROW
)nRow
);
458 sal_Bool SAL_CALL
ScAccessibleSpreadsheet::isAccessibleColumnSelected( sal_Int32 nColumn
)
459 throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
)
461 SolarMutexGuard aGuard
;
464 if ((nColumn
> (maRange
.aEnd
.Col() - maRange
.aStart
.Col())) || (nColumn
< 0))
465 throw lang::IndexOutOfBoundsException();
467 sal_Bool
bResult(false);
468 if (mpViewShell
&& mpViewShell
->GetViewData())
470 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData()->GetMarkData();
471 bResult
= rMarkdata
.IsColumnMarked((SCCOL
)nColumn
);
476 ScAccessibleCell
* ScAccessibleSpreadsheet::GetAccessibleCellAt(sal_Int32 nRow
, sal_Int32 nColumn
)
478 ScAccessibleCell
* pAccessibleCell
= NULL
;
479 ScAddress
aCellAddress(static_cast<SCCOL
>(maRange
.aStart
.Col() + nColumn
),
480 static_cast<SCROW
>(maRange
.aStart
.Row() + nRow
), maRange
.aStart
.Tab());
481 if ((aCellAddress
== maActiveCell
) && mpAccCell
)
483 pAccessibleCell
= mpAccCell
;
486 pAccessibleCell
= new ScAccessibleCell(this, mpViewShell
, aCellAddress
, getAccessibleIndex(nRow
, nColumn
), meSplitPos
, mpAccDoc
);
488 return pAccessibleCell
;
491 uno::Reference
< XAccessible
> SAL_CALL
ScAccessibleSpreadsheet::getAccessibleCellAt( sal_Int32 nRow
, sal_Int32 nColumn
)
492 throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
)
494 SolarMutexGuard aGuard
;
496 if (nRow
> (maRange
.aEnd
.Row() - maRange
.aStart
.Row()) ||
498 nColumn
> (maRange
.aEnd
.Col() - maRange
.aStart
.Col()) ||
500 throw lang::IndexOutOfBoundsException();
502 uno::Reference
<XAccessible
> xAccessible
;
503 ScAccessibleCell
* pAccessibleCell
= GetAccessibleCellAt(nRow
, nColumn
);
504 xAccessible
= pAccessibleCell
;
505 pAccessibleCell
->Init();
509 sal_Bool SAL_CALL
ScAccessibleSpreadsheet::isAccessibleSelected( sal_Int32 nRow
, sal_Int32 nColumn
)
510 throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
)
512 SolarMutexGuard aGuard
;
515 if ((nColumn
> (maRange
.aEnd
.Col() - maRange
.aStart
.Col())) || (nColumn
< 0) ||
516 (nRow
> (maRange
.aEnd
.Row() - maRange
.aStart
.Row())) || (nRow
< 0))
517 throw lang::IndexOutOfBoundsException();
519 sal_Bool
bResult(false);
522 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData()->GetMarkData();
523 bResult
= rMarkdata
.IsCellMarked(static_cast<SCCOL
>(nColumn
), static_cast<SCROW
>(nRow
));
528 //===== XAccessibleComponent ============================================
530 uno::Reference
< XAccessible
> SAL_CALL
ScAccessibleSpreadsheet::getAccessibleAtPoint(
531 const awt::Point
& rPoint
)
532 throw (uno::RuntimeException
)
534 uno::Reference
< XAccessible
> xAccessible
;
535 if (containsPoint(rPoint
))
537 SolarMutexGuard aGuard
;
543 mpViewShell
->GetViewData()->GetPosFromPixel( rPoint
.X
, rPoint
.Y
, meSplitPos
, nX
, nY
);
544 xAccessible
= getAccessibleCellAt(nY
, nX
);
550 void SAL_CALL
ScAccessibleSpreadsheet::grabFocus( )
551 throw (uno::RuntimeException
)
553 if (getAccessibleParent().is())
555 uno::Reference
<XAccessibleComponent
> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY
);
556 if (xAccessibleComponent
.is())
557 xAccessibleComponent
->grabFocus();
561 sal_Int32 SAL_CALL
ScAccessibleSpreadsheet::getForeground( )
562 throw (uno::RuntimeException
)
567 sal_Int32 SAL_CALL
ScAccessibleSpreadsheet::getBackground( )
568 throw (uno::RuntimeException
)
570 SolarMutexGuard aGuard
;
572 return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR
).nColor
;
575 //===== XAccessibleContext ==============================================
577 uno::Reference
<XAccessibleRelationSet
> SAL_CALL
ScAccessibleSpreadsheet::getAccessibleRelationSet(void)
578 throw (::com::sun::star::uno::RuntimeException
)
580 utl::AccessibleRelationSetHelper
* pRelationSet
= NULL
;
582 pRelationSet
= mpAccDoc
->GetRelationSet(NULL
);
584 pRelationSet
= new utl::AccessibleRelationSetHelper();
588 uno::Reference
<XAccessibleStateSet
> SAL_CALL
589 ScAccessibleSpreadsheet::getAccessibleStateSet(void)
590 throw (uno::RuntimeException
)
592 SolarMutexGuard aGuard
;
593 uno::Reference
<XAccessibleStateSet
> xParentStates
;
594 if (getAccessibleParent().is())
596 uno::Reference
<XAccessibleContext
> xParentContext
= getAccessibleParent()->getAccessibleContext();
597 xParentStates
= xParentContext
->getAccessibleStateSet();
599 utl::AccessibleStateSetHelper
* pStateSet
= new utl::AccessibleStateSetHelper();
600 if (IsDefunc(xParentStates
))
601 pStateSet
->AddState(AccessibleStateType::DEFUNC
);
604 pStateSet
->AddState(AccessibleStateType::MANAGES_DESCENDANTS
);
605 if (IsEditable(xParentStates
))
606 pStateSet
->AddState(AccessibleStateType::EDITABLE
);
607 pStateSet
->AddState(AccessibleStateType::ENABLED
);
608 pStateSet
->AddState(AccessibleStateType::FOCUSABLE
);
610 pStateSet
->AddState(AccessibleStateType::FOCUSED
);
611 pStateSet
->AddState(AccessibleStateType::MULTI_SELECTABLE
);
612 pStateSet
->AddState(AccessibleStateType::OPAQUE
);
613 pStateSet
->AddState(AccessibleStateType::SELECTABLE
);
614 if (IsCompleteSheetSelected())
615 pStateSet
->AddState(AccessibleStateType::SELECTED
);
617 pStateSet
->AddState(AccessibleStateType::SHOWING
);
619 pStateSet
->AddState(AccessibleStateType::VISIBLE
);
624 ///===== XAccessibleSelection ===========================================
627 ScAccessibleSpreadsheet::selectAccessibleChild( sal_Int32 nChildIndex
)
628 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
630 SolarMutexGuard aGuard
;
632 if (nChildIndex
< 0 || nChildIndex
>= getAccessibleChildCount())
633 throw lang::IndexOutOfBoundsException();
637 sal_Int32
nCol(getAccessibleColumn(nChildIndex
));
638 sal_Int32
nRow(getAccessibleRow(nChildIndex
));
640 SelectCell(nRow
, nCol
, false);
645 ScAccessibleSpreadsheet::clearAccessibleSelection( )
646 throw (uno::RuntimeException
)
648 SolarMutexGuard aGuard
;
652 mpViewShell
->Unmark();
657 ScAccessibleSpreadsheet::selectAllAccessibleChildren( )
658 throw (uno::RuntimeException
)
660 SolarMutexGuard aGuard
;
664 mpViewShell
->SelectAll();
669 ScAccessibleSpreadsheet::getSelectedAccessibleChildCount( )
670 throw (uno::RuntimeException
)
672 SolarMutexGuard aGuard
;
674 sal_Int32
nResult(0);
679 mpMarkedRanges
= new ScRangeList();
680 ScMarkData
aMarkData(mpViewShell
->GetViewData()->GetMarkData());
681 aMarkData
.MarkToMulti();
682 aMarkData
.FillRangeListWithMarks(mpMarkedRanges
, false);
684 // is possible, because there shouldn't be overlapped ranges in it
686 nResult
= mpMarkedRanges
->GetCellCount();
691 uno::Reference
<XAccessible
> SAL_CALL
692 ScAccessibleSpreadsheet::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex
)
693 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
695 SolarMutexGuard aGuard
;
697 uno::Reference
< XAccessible
> xAccessible
;
702 mpMarkedRanges
= new ScRangeList();
703 mpViewShell
->GetViewData()->GetMarkData().FillRangeListWithMarks(mpMarkedRanges
, false);
707 if (!mpSortedMarkedCells
)
708 CreateSortedMarkedCells();
709 if (mpSortedMarkedCells
)
711 if ((nSelectedChildIndex
< 0) ||
712 (mpSortedMarkedCells
->size() <= static_cast<sal_uInt32
>(nSelectedChildIndex
)))
713 throw lang::IndexOutOfBoundsException();
715 xAccessible
= getAccessibleCellAt((*mpSortedMarkedCells
)[nSelectedChildIndex
].Row(), (*mpSortedMarkedCells
)[nSelectedChildIndex
].Col());
723 ScAccessibleSpreadsheet::deselectAccessibleChild( sal_Int32 nChildIndex
)
724 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
726 SolarMutexGuard aGuard
;
729 if (nChildIndex
< 0 || nChildIndex
>= getAccessibleChildCount())
730 throw lang::IndexOutOfBoundsException();
734 sal_Int32
nCol(getAccessibleColumn(nChildIndex
));
735 sal_Int32
nRow(getAccessibleRow(nChildIndex
));
737 if (mpViewShell
->GetViewData()->GetMarkData().IsCellMarked(static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
)))
738 SelectCell(nRow
, nCol
, sal_True
);
742 void ScAccessibleSpreadsheet::SelectCell(sal_Int32 nRow
, sal_Int32 nCol
, sal_Bool bDeselect
)
744 mpViewShell
->SetTabNo( maRange
.aStart
.Tab() );
746 mpViewShell
->DoneBlockMode( sal_True
); // continue selecting
747 mpViewShell
->InitBlockMode( static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
), maRange
.aStart
.Tab(), bDeselect
, false, false );
749 mpViewShell
->SelectionChanged();
752 void ScAccessibleSpreadsheet::CreateSortedMarkedCells()
754 mpSortedMarkedCells
= new std::vector
<ScMyAddress
>();
755 mpSortedMarkedCells
->reserve(mpMarkedRanges
->GetCellCount());
756 for ( size_t i
= 0, ListSize
= mpMarkedRanges
->size(); i
< ListSize
; ++i
)
758 ScRange
* pRange
= (*mpMarkedRanges
)[i
];
759 if (pRange
->aStart
.Tab() != pRange
->aEnd
.Tab())
761 if ((maActiveCell
.Tab() >= pRange
->aStart
.Tab()) ||
762 maActiveCell
.Tab() <= pRange
->aEnd
.Tab())
764 ScRange
aRange(*pRange
);
765 aRange
.aStart
.SetTab(maActiveCell
.Tab());
766 aRange
.aEnd
.SetTab(maActiveCell
.Tab());
767 AddMarkedRange(aRange
);
771 OSL_FAIL("Range of wrong table");
774 else if(pRange
->aStart
.Tab() == maActiveCell
.Tab())
775 AddMarkedRange(*pRange
);
778 OSL_FAIL("Range of wrong table");
781 std::sort(mpSortedMarkedCells
->begin(), mpSortedMarkedCells
->end());
784 void ScAccessibleSpreadsheet::AddMarkedRange(const ScRange
& rRange
)
786 for (SCROW nRow
= rRange
.aStart
.Row(); nRow
<= rRange
.aEnd
.Row(); ++nRow
)
788 for (SCCOL nCol
= rRange
.aStart
.Col(); nCol
<= rRange
.aEnd
.Col(); ++nCol
)
790 ScMyAddress
aCell(nCol
, nRow
, maActiveCell
.Tab());
791 mpSortedMarkedCells
->push_back(aCell
);
796 //===== XServiceInfo ====================================================
798 OUString SAL_CALL
ScAccessibleSpreadsheet::getImplementationName(void)
799 throw (uno::RuntimeException
)
801 return OUString("ScAccessibleSpreadsheet");
804 uno::Sequence
< OUString
> SAL_CALL
805 ScAccessibleSpreadsheet::getSupportedServiceNames (void)
806 throw (uno::RuntimeException
)
808 uno::Sequence
< OUString
> aSequence
= ScAccessibleTableBase::getSupportedServiceNames();
809 sal_Int32
nOldSize(aSequence
.getLength());
810 aSequence
.realloc(nOldSize
+ 1);
811 OUString
* pNames
= aSequence
.getArray();
813 pNames
[nOldSize
] = OUString("com.sun.star.AccessibleSpreadsheet");
818 //===== XTypeProvider =======================================================
822 class theScAccessibleSpreadsheetImplementationId
: public rtl::Static
< UnoTunnelIdInit
, theScAccessibleSpreadsheetImplementationId
> {};
825 uno::Sequence
<sal_Int8
> SAL_CALL
826 ScAccessibleSpreadsheet::getImplementationId(void)
827 throw (uno::RuntimeException
)
829 return theScAccessibleSpreadsheetImplementationId::get().getSeq();
832 ///===== XAccessibleEventBroadcaster =====================================
834 void SAL_CALL
ScAccessibleSpreadsheet::addAccessibleEventListener(const uno::Reference
<XAccessibleEventListener
>& xListener
)
835 throw (uno::RuntimeException
)
837 SolarMutexGuard aGuard
;
839 ScAccessibleTableBase::addAccessibleEventListener(xListener
);
843 mbIsFocusSend
= sal_True
;
846 AccessibleEventObject aEvent
;
847 aEvent
.EventId
= AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
;
848 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
849 aEvent
.NewValue
<<= getAccessibleCellAt(maActiveCell
.Row(), maActiveCell
.Col());
851 CommitChange(aEvent
);
855 //==== internal =========================================================
857 Rectangle
ScAccessibleSpreadsheet::GetBoundingBoxOnScreen() const
858 throw (uno::RuntimeException
)
863 Window
* pWindow
= mpViewShell
->GetWindowByPos(meSplitPos
);
865 aRect
= pWindow
->GetWindowExtentsRelative(NULL
);
870 Rectangle
ScAccessibleSpreadsheet::GetBoundingBox() const
871 throw (uno::RuntimeException
)
876 Window
* pWindow
= mpViewShell
->GetWindowByPos(meSplitPos
);
878 //#101986#; extends to the same window, because the parent is the document and it has the same window
879 aRect
= pWindow
->GetWindowExtentsRelative(pWindow
);
884 sal_Bool
ScAccessibleSpreadsheet::IsDefunc(
885 const uno::Reference
<XAccessibleStateSet
>& rxParentStates
)
887 return ScAccessibleContextBase::IsDefunc() || (mpViewShell
== NULL
) || !getAccessibleParent().is() ||
888 (rxParentStates
.is() && rxParentStates
->contains(AccessibleStateType::DEFUNC
));
891 sal_Bool
ScAccessibleSpreadsheet::IsEditable(
892 const uno::Reference
<XAccessibleStateSet
>& /* rxParentStates */)
894 sal_Bool
bProtected(false);
895 if (mpDoc
&& mpDoc
->IsTabProtected(maRange
.aStart
.Tab()))
896 bProtected
= sal_True
;
900 sal_Bool
ScAccessibleSpreadsheet::IsFocused()
902 sal_Bool
bFocused(false);
905 if (mpViewShell
->GetViewData()->GetActivePart() == meSplitPos
)
906 bFocused
= mpViewShell
->GetActiveWin()->HasFocus();
911 sal_Bool
ScAccessibleSpreadsheet::IsCompleteSheetSelected()
913 sal_Bool
bResult(false);
916 //#103800#; use a copy of MarkData
917 ScMarkData
aMarkData(mpViewShell
->GetViewData()->GetMarkData());
918 aMarkData
.MarkToMulti();
919 if (aMarkData
.IsAllMarked(maRange
))
925 ScDocument
* ScAccessibleSpreadsheet::GetDocument(ScTabViewShell
* pViewShell
)
927 ScDocument
* pDoc
= NULL
;
929 pDoc
= pViewShell
->GetViewData()->GetDocument();
933 Rectangle
ScAccessibleSpreadsheet::GetVisArea(ScTabViewShell
* pViewShell
, ScSplitPos eSplitPos
)
938 Window
* pWindow
= pViewShell
->GetWindowByPos(eSplitPos
);
941 aVisArea
.SetPos(pViewShell
->GetViewData()->GetPixPos(eSplitPos
));
942 aVisArea
.SetSize(pWindow
->GetSizePixel());
948 Rectangle
ScAccessibleSpreadsheet::GetVisCells(const Rectangle
& rVisArea
)
952 SCsCOL nStartX
, nEndX
;
953 SCsROW nStartY
, nEndY
;
955 mpViewShell
->GetViewData()->GetPosFromPixel( 1, 1, meSplitPos
, nStartX
, nStartY
);
956 mpViewShell
->GetViewData()->GetPosFromPixel( rVisArea
.GetWidth(), rVisArea
.GetHeight(), meSplitPos
, nEndX
, nEndY
);
958 return Rectangle(nStartX
, nStartY
, nEndX
, nEndY
);
964 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */