1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: AccessibleSpreadsheet.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
35 #include "AccessibleSpreadsheet.hxx"
36 #include "AccessibilityHints.hxx"
37 #include "AccessibleCell.hxx"
38 #include "AccessibleDocument.hxx"
39 #include "tabvwsh.hxx"
40 #include "document.hxx"
41 #include "unoguard.hxx"
45 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
46 #include <unotools/accessiblestatesethelper.hxx>
48 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
49 #include <com/sun/star/accessibility/AccessibleRole.hpp>
51 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
52 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
54 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
55 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
57 #include <tools/debug.hxx>
58 #include <tools/gen.hxx>
59 #include <svtools/colorcfg.hxx>
63 using namespace ::com::sun::star
;
64 using namespace ::com::sun::star::accessibility
;
66 //===== internal ============================================================
68 ScAccessibleSpreadsheet::ScAccessibleSpreadsheet(
69 ScAccessibleDocument
* pAccDoc
,
70 ScTabViewShell
* pViewShell
,
74 ScAccessibleTableBase (pAccDoc
, GetDocument(pViewShell
),
75 ScRange(ScAddress(0, 0, nTab
),ScAddress(MAXCOL
, MAXROW
, nTab
))),
76 mbIsSpreadsheet( sal_True
)
78 ConstructScAccessibleSpreadsheet( pAccDoc
, pViewShell
, nTab
, eSplitPos
);
81 ScAccessibleSpreadsheet::ScAccessibleSpreadsheet(
82 ScAccessibleSpreadsheet
& rParent
, const ScRange
& rRange
) :
83 ScAccessibleTableBase( rParent
.mpAccDoc
, rParent
.mpDoc
, rRange
),
84 mbIsSpreadsheet( sal_False
)
86 ConstructScAccessibleSpreadsheet( rParent
.mpAccDoc
, rParent
.mpViewShell
, rParent
.mnTab
, rParent
.meSplitPos
);
89 ScAccessibleSpreadsheet::~ScAccessibleSpreadsheet()
92 delete mpMarkedRanges
;
93 if (mpSortedMarkedCells
)
94 delete mpSortedMarkedCells
;
96 mpViewShell
->RemoveAccessibilityObject(*this);
99 void ScAccessibleSpreadsheet::ConstructScAccessibleSpreadsheet(
100 ScAccessibleDocument
* pAccDoc
,
101 ScTabViewShell
* pViewShell
,
103 ScSplitPos eSplitPos
)
105 mpViewShell
= pViewShell
;
107 mpSortedMarkedCells
= 0;
110 meSplitPos
= eSplitPos
;
112 mbHasSelection
= sal_False
;
113 mbDelIns
= sal_False
;
114 mbIsFocusSend
= sal_False
;
115 maVisCells
= GetVisCells(GetVisArea(mpViewShell
, meSplitPos
));
118 mpViewShell
->AddAccessibilityObject(*this);
120 const ScViewData
& rViewData
= *mpViewShell
->GetViewData();
121 const ScMarkData
& rMarkData
= rViewData
.GetMarkData();
122 maActiveCell
= rViewData
.GetCurPos();
123 mbHasSelection
= rMarkData
.GetTableSelect(maActiveCell
.Tab()) &&
124 (rMarkData
.IsMarked() || rMarkData
.IsMultiMarked());
125 mpAccCell
= GetAccessibleCellAt(maActiveCell
.Row(), maActiveCell
.Col());
126 mpAccCell
->acquire();
131 void SAL_CALL
ScAccessibleSpreadsheet::disposing()
136 mpViewShell
->RemoveAccessibilityObject(*this);
141 mpAccCell
->release();
145 ScAccessibleTableBase::disposing();
148 void ScAccessibleSpreadsheet::CompleteSelectionChanged(sal_Bool bNewState
)
151 DELETEZ(mpMarkedRanges
);
152 if (mpSortedMarkedCells
)
153 DELETEZ(mpSortedMarkedCells
);
155 mbHasSelection
= bNewState
;
157 AccessibleEventObject aEvent
;
158 aEvent
.EventId
= AccessibleEventId::STATE_CHANGED
;
160 aEvent
.NewValue
= uno::makeAny(AccessibleStateType::SELECTED
);
162 aEvent
.OldValue
= uno::makeAny(AccessibleStateType::SELECTED
);
163 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
165 CommitChange(aEvent
);
168 void ScAccessibleSpreadsheet::LostFocus()
170 AccessibleEventObject aEvent
;
171 aEvent
.EventId
= AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
;
172 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
173 uno::Reference
< XAccessible
> xOld
= mpAccCell
;
174 aEvent
.OldValue
<<= xOld
;
176 CommitChange(aEvent
);
181 void ScAccessibleSpreadsheet::GotFocus()
185 AccessibleEventObject aEvent
;
186 aEvent
.EventId
= AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
;
187 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
188 uno::Reference
< XAccessible
> xNew
= mpAccCell
;
189 aEvent
.NewValue
<<= xNew
;
191 CommitChange(aEvent
);
194 void ScAccessibleSpreadsheet::BoundingBoxChanged()
196 AccessibleEventObject aEvent
;
197 aEvent
.EventId
= AccessibleEventId::BOUNDRECT_CHANGED
;
198 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
200 CommitChange(aEvent
);
203 void ScAccessibleSpreadsheet::VisAreaChanged()
205 AccessibleEventObject aEvent
;
206 aEvent
.EventId
= AccessibleEventId::VISIBLE_DATA_CHANGED
;
207 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
209 CommitChange(aEvent
);
212 //===== SfxListener =====================================================
214 void ScAccessibleSpreadsheet::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
216 if (rHint
.ISA( SfxSimpleHint
) )
218 const SfxSimpleHint
& rRef
= (const SfxSimpleHint
&)rHint
;
219 // only notify if child exist, otherwise it is not necessary
220 if ((rRef
.GetId() == SC_HINT_ACC_CURSORCHANGED
))
224 ScAddress aNewCell
= mpViewShell
->GetViewData()->GetCurPos();
225 sal_Bool
bNewMarked(mpViewShell
->GetViewData()->GetMarkData().GetTableSelect(aNewCell
.Tab()) &&
226 (mpViewShell
->GetViewData()->GetMarkData().IsMarked() ||
227 mpViewShell
->GetViewData()->GetMarkData().IsMultiMarked()));
228 sal_Bool
bNewCellSelected(isAccessibleSelected(aNewCell
.Row(), aNewCell
.Col()));
229 if ((bNewMarked
!= mbHasSelection
) ||
230 (!bNewCellSelected
&& bNewMarked
) ||
231 (bNewCellSelected
&& mbHasSelection
))
234 DELETEZ(mpMarkedRanges
);
235 if (mpSortedMarkedCells
)
236 DELETEZ(mpSortedMarkedCells
);
237 AccessibleEventObject aEvent
;
238 aEvent
.EventId
= AccessibleEventId::SELECTION_CHANGED
;
239 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
241 mbHasSelection
= bNewMarked
;
243 CommitChange(aEvent
);
246 // active descendant changed event (new cell selected)
247 bool bFireActiveDescChanged
= (aNewCell
!= maActiveCell
) &&
248 (aNewCell
.Tab() == maActiveCell
.Tab()) && IsFocused();
250 /* Remember old active cell and set new active cell.
251 #i82409# always update the class members mpAccCell and
252 maActiveCell, even if the sheet is not focused, e.g. when
253 using the name box in the toolbar. */
254 uno::Reference
< XAccessible
> xOld
= mpAccCell
;
255 mpAccCell
->release();
256 mpAccCell
= GetAccessibleCellAt(aNewCell
.Row(), aNewCell
.Col());
257 mpAccCell
->acquire();
259 uno::Reference
< XAccessible
> xNew
= mpAccCell
;
260 maActiveCell
= aNewCell
;
262 // #i14108# fire event only if sheet is focused
263 if( bFireActiveDescChanged
)
265 AccessibleEventObject aEvent
;
266 aEvent
.EventId
= AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
;
267 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
268 aEvent
.OldValue
<<= xOld
;
269 aEvent
.NewValue
<<= xNew
;
270 CommitChange(aEvent
);
274 else if ((rRef
.GetId() == SC_HINT_DATACHANGED
))
277 CommitTableModelChange(maRange
.aStart
.Row(), maRange
.aStart
.Col(), maRange
.aEnd
.Row(), maRange
.aEnd
.Col(), AccessibleTableModelChangeType::UPDATE
);
279 mbDelIns
= sal_False
;
281 // no longer needed, because the document calls the VisAreaChanged method
282 /* else if (rRef.GetId() == SC_HINT_ACC_VISAREACHANGED)
284 AccessibleEventObject aEvent;
285 aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
286 aEvent.Source = uno::Reference< XAccessibleContext >(this);
288 CommitChange(aEvent);*/
289 // commented out, because to use a ModelChangeEvent is not the right way
290 // at the moment there is no way, but the Java/Gnome Api should be extended sometime
293 Rectangle aNewVisCells(GetVisCells(GetVisArea(mpViewShell, meSplitPos)));
295 Rectangle aNewPos(aNewVisCells);
297 if (aNewVisCells.IsOver(maVisCells))
298 aNewPos.Union(maVisCells);
300 CommitTableModelChange(maVisCells.Top(), maVisCells.Left(), maVisCells.Bottom(), maVisCells.Right(), AccessibleTableModelChangeType::UPDATE);
302 maVisCells = aNewVisCells;
304 CommitTableModelChange(aNewPos.Top(), aNewPos.Left(), aNewPos.Bottom(), aNewPos.Right(), AccessibleTableModelChangeType::UPDATE);
307 // no longer needed, because the document calls the BoundingBoxChanged method
308 /* else if (rRef.GetId() == SC_HINT_ACC_WINDOWRESIZED)
310 AccessibleEventObject aEvent;
311 aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
312 aEvent.Source = uno::Reference< XAccessibleContext >(this);
314 CommitChange(aEvent);
317 else if (rHint
.ISA( ScUpdateRefHint
))
319 const ScUpdateRefHint
& rRef
= (const ScUpdateRefHint
&)rHint
;
320 if (rRef
.GetMode() == URM_INSDEL
&& rRef
.GetDz() == 0) //#107250# test whether table is inserted or deleted
322 if (((rRef
.GetRange().aStart
.Col() == maRange
.aStart
.Col()) &&
323 (rRef
.GetRange().aEnd
.Col() == maRange
.aEnd
.Col())) ||
324 ((rRef
.GetRange().aStart
.Row() == maRange
.aStart
.Row()) &&
325 (rRef
.GetRange().aEnd
.Row() == maRange
.aEnd
.Row())))
327 // ignore next SC_HINT_DATACHANGED notification
331 SCsCOL
nX(rRef
.GetDx());
332 SCsROW
nY(rRef
.GetDy());
333 ScRange
aRange(rRef
.GetRange());
334 if ((nX
< 0) || (nY
< 0))
336 DBG_ASSERT(!((nX
< 0) && (nY
< 0)), "should not be possible to remove row and column at the same time");
337 nId
= AccessibleTableModelChangeType::DELETE
;
341 nY
= aRange
.aEnd
.Row() - aRange
.aStart
.Row();
346 nX
= aRange
.aEnd
.Col() - aRange
.aStart
.Col();
349 else if ((nX
> 0) || (nY
> 0))
351 DBG_ASSERT(!((nX
> 0) && (nY
> 0)), "should not be possible to add row and column at the same time");
352 nId
= AccessibleTableModelChangeType::INSERT
;
354 nY
= aRange
.aEnd
.Row() - aRange
.aStart
.Row();
356 nX
= aRange
.aEnd
.Col() - aRange
.aStart
.Col();
360 DBG_ERROR("is it a deletion or a insertion?");
363 CommitTableModelChange(rRef
.GetRange().aStart
.Row(),
364 rRef
.GetRange().aStart
.Col(),
365 rRef
.GetRange().aStart
.Row() + nY
,
366 rRef
.GetRange().aStart
.Col() + nX
, nId
);
368 AccessibleEventObject aEvent
;
369 aEvent
.EventId
= AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
;
370 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
371 uno::Reference
< XAccessible
> xNew
= mpAccCell
;
372 aEvent
.NewValue
<<= xNew
;
374 CommitChange(aEvent
);
379 ScAccessibleTableBase::Notify(rBC
, rHint
);
382 //===== XAccessibleTable ================================================
384 uno::Reference
< XAccessibleTable
> SAL_CALL
ScAccessibleSpreadsheet::getAccessibleRowHeaders( )
385 throw (uno::RuntimeException
)
389 uno::Reference
< XAccessibleTable
> xAccessibleTable
;
390 if( mpDoc
&& mbIsSpreadsheet
)
392 if( const ScRange
* pRowRange
= mpDoc
->GetRepeatRowRange( mnTab
) )
394 SCROW nStart
= pRowRange
->aStart
.Row();
395 SCROW nEnd
= pRowRange
->aEnd
.Row();
396 if( (0 <= nStart
) && (nStart
<= nEnd
) && (nEnd
<= MAXROW
) )
397 xAccessibleTable
.set( new ScAccessibleSpreadsheet( *this, ScRange( 0, nStart
, mnTab
, MAXCOL
, nEnd
, mnTab
) ) );
400 return xAccessibleTable
;
403 uno::Reference
< XAccessibleTable
> SAL_CALL
ScAccessibleSpreadsheet::getAccessibleColumnHeaders( )
404 throw (uno::RuntimeException
)
408 uno::Reference
< XAccessibleTable
> xAccessibleTable
;
409 if( mpDoc
&& mbIsSpreadsheet
)
411 if( const ScRange
* pColRange
= mpDoc
->GetRepeatColRange( mnTab
) )
413 SCCOL nStart
= pColRange
->aStart
.Col();
414 SCCOL nEnd
= pColRange
->aEnd
.Col();
415 if( (0 <= nStart
) && (nStart
<= nEnd
) && (nEnd
<= MAXCOL
) )
416 xAccessibleTable
.set( new ScAccessibleSpreadsheet( *this, ScRange( nStart
, 0, mnTab
, nEnd
, MAXROW
, mnTab
) ) );
419 return xAccessibleTable
;
422 uno::Sequence
< sal_Int32
> SAL_CALL
ScAccessibleSpreadsheet::getSelectedAccessibleRows( )
423 throw (uno::RuntimeException
)
427 uno::Sequence
<sal_Int32
> aSequence
;
428 if (mpViewShell
&& mpViewShell
->GetViewData())
430 aSequence
.realloc(maRange
.aEnd
.Row() - maRange
.aStart
.Row() + 1);
431 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData()->GetMarkData();
432 sal_Int32
* pSequence
= aSequence
.getArray();
434 for (SCROW i
= maRange
.aStart
.Row(); i
<= maRange
.aEnd
.Row(); ++i
)
436 if (rMarkdata
.IsRowMarked(i
))
438 pSequence
[nCount
] = i
;
442 aSequence
.realloc(nCount
);
445 aSequence
.realloc(0);
449 uno::Sequence
< sal_Int32
> SAL_CALL
ScAccessibleSpreadsheet::getSelectedAccessibleColumns( )
450 throw (uno::RuntimeException
)
454 uno::Sequence
<sal_Int32
> aSequence
;
455 if (mpViewShell
&& mpViewShell
->GetViewData())
457 aSequence
.realloc(maRange
.aEnd
.Col() - maRange
.aStart
.Col() + 1);
458 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData()->GetMarkData();
459 sal_Int32
* pSequence
= aSequence
.getArray();
461 for (SCCOL i
= maRange
.aStart
.Col(); i
<= maRange
.aEnd
.Col(); ++i
)
463 if (rMarkdata
.IsColumnMarked(i
))
465 pSequence
[nCount
] = i
;
469 aSequence
.realloc(nCount
);
472 aSequence
.realloc(0);
476 sal_Bool SAL_CALL
ScAccessibleSpreadsheet::isAccessibleRowSelected( sal_Int32 nRow
)
477 throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
)
482 if ((nRow
> (maRange
.aEnd
.Row() - maRange
.aStart
.Row())) || (nRow
< 0))
483 throw lang::IndexOutOfBoundsException();
485 sal_Bool
bResult(sal_False
);
486 if (mpViewShell
&& mpViewShell
->GetViewData())
488 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData()->GetMarkData();
489 bResult
= rMarkdata
.IsRowMarked((SCROW
)nRow
);
494 sal_Bool SAL_CALL
ScAccessibleSpreadsheet::isAccessibleColumnSelected( sal_Int32 nColumn
)
495 throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
)
500 if ((nColumn
> (maRange
.aEnd
.Col() - maRange
.aStart
.Col())) || (nColumn
< 0))
501 throw lang::IndexOutOfBoundsException();
503 sal_Bool
bResult(sal_False
);
504 if (mpViewShell
&& mpViewShell
->GetViewData())
506 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData()->GetMarkData();
507 bResult
= rMarkdata
.IsColumnMarked((SCCOL
)nColumn
);
512 ScAccessibleCell
* ScAccessibleSpreadsheet::GetAccessibleCellAt(sal_Int32 nRow
, sal_Int32 nColumn
)
514 ScAccessibleCell
* pAccessibleCell
= NULL
;
515 ScAddress
aCellAddress(static_cast<SCCOL
>(maRange
.aStart
.Col() + nColumn
),
516 static_cast<SCROW
>(maRange
.aStart
.Row() + nRow
), maRange
.aStart
.Tab());
517 if ((aCellAddress
== maActiveCell
) && mpAccCell
)
519 pAccessibleCell
= mpAccCell
;
522 pAccessibleCell
= new ScAccessibleCell(this, mpViewShell
, aCellAddress
, getAccessibleIndex(nRow
, nColumn
), meSplitPos
, mpAccDoc
);
524 return pAccessibleCell
;
527 uno::Reference
< XAccessible
> SAL_CALL
ScAccessibleSpreadsheet::getAccessibleCellAt( sal_Int32 nRow
, sal_Int32 nColumn
)
528 throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
)
532 if (nRow
> (maRange
.aEnd
.Row() - maRange
.aStart
.Row()) ||
534 nColumn
> (maRange
.aEnd
.Col() - maRange
.aStart
.Col()) ||
536 throw lang::IndexOutOfBoundsException();
538 uno::Reference
<XAccessible
> xAccessible
;
539 ScAccessibleCell
* pAccessibleCell
= GetAccessibleCellAt(nRow
, nColumn
);
540 xAccessible
= pAccessibleCell
;
541 pAccessibleCell
->Init();
545 sal_Bool SAL_CALL
ScAccessibleSpreadsheet::isAccessibleSelected( sal_Int32 nRow
, sal_Int32 nColumn
)
546 throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
)
551 if ((nColumn
> (maRange
.aEnd
.Col() - maRange
.aStart
.Col())) || (nColumn
< 0) ||
552 (nRow
> (maRange
.aEnd
.Row() - maRange
.aStart
.Row())) || (nRow
< 0))
553 throw lang::IndexOutOfBoundsException();
555 sal_Bool
bResult(sal_False
);
558 const ScMarkData
& rMarkdata
= mpViewShell
->GetViewData()->GetMarkData();
559 bResult
= rMarkdata
.IsCellMarked(static_cast<SCCOL
>(nColumn
), static_cast<SCROW
>(nRow
));
564 //===== XAccessibleComponent ============================================
566 uno::Reference
< XAccessible
> SAL_CALL
ScAccessibleSpreadsheet::getAccessibleAtPoint(
567 const awt::Point
& rPoint
)
568 throw (uno::RuntimeException
)
570 uno::Reference
< XAccessible
> xAccessible
;
571 if (containsPoint(rPoint
))
579 mpViewShell
->GetViewData()->GetPosFromPixel( rPoint
.X
, rPoint
.Y
, meSplitPos
, nX
, nY
);
580 xAccessible
= getAccessibleCellAt(nY
, nX
);
586 void SAL_CALL
ScAccessibleSpreadsheet::grabFocus( )
587 throw (uno::RuntimeException
)
589 if (getAccessibleParent().is())
591 uno::Reference
<XAccessibleComponent
> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY
);
592 if (xAccessibleComponent
.is())
593 xAccessibleComponent
->grabFocus();
597 sal_Int32 SAL_CALL
ScAccessibleSpreadsheet::getForeground( )
598 throw (uno::RuntimeException
)
603 sal_Int32 SAL_CALL
ScAccessibleSpreadsheet::getBackground( )
604 throw (uno::RuntimeException
)
608 return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR
).nColor
;
611 //===== XAccessibleContext ==============================================
613 uno::Reference
<XAccessibleRelationSet
> SAL_CALL
ScAccessibleSpreadsheet::getAccessibleRelationSet(void)
614 throw (::com::sun::star::uno::RuntimeException
)
616 utl::AccessibleRelationSetHelper
* pRelationSet
= NULL
;
618 pRelationSet
= mpAccDoc
->GetRelationSet(NULL
);
620 pRelationSet
= new utl::AccessibleRelationSetHelper();
624 uno::Reference
<XAccessibleStateSet
> SAL_CALL
625 ScAccessibleSpreadsheet::getAccessibleStateSet(void)
626 throw (uno::RuntimeException
)
629 uno::Reference
<XAccessibleStateSet
> xParentStates
;
630 if (getAccessibleParent().is())
632 uno::Reference
<XAccessibleContext
> xParentContext
= getAccessibleParent()->getAccessibleContext();
633 xParentStates
= xParentContext
->getAccessibleStateSet();
635 utl::AccessibleStateSetHelper
* pStateSet
= new utl::AccessibleStateSetHelper();
636 if (IsDefunc(xParentStates
))
637 pStateSet
->AddState(AccessibleStateType::DEFUNC
);
640 pStateSet
->AddState(AccessibleStateType::MANAGES_DESCENDANTS
);
641 if (IsEditable(xParentStates
))
642 pStateSet
->AddState(AccessibleStateType::EDITABLE
);
643 pStateSet
->AddState(AccessibleStateType::ENABLED
);
644 pStateSet
->AddState(AccessibleStateType::FOCUSABLE
);
646 pStateSet
->AddState(AccessibleStateType::FOCUSED
);
647 pStateSet
->AddState(AccessibleStateType::MULTI_SELECTABLE
);
648 pStateSet
->AddState(AccessibleStateType::OPAQUE
);
649 pStateSet
->AddState(AccessibleStateType::SELECTABLE
);
650 if (IsCompleteSheetSelected())
651 pStateSet
->AddState(AccessibleStateType::SELECTED
);
653 pStateSet
->AddState(AccessibleStateType::SHOWING
);
655 pStateSet
->AddState(AccessibleStateType::VISIBLE
);
660 ///===== XAccessibleSelection ===========================================
663 ScAccessibleSpreadsheet::selectAccessibleChild( sal_Int32 nChildIndex
)
664 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
668 if (nChildIndex
< 0 || nChildIndex
>= getAccessibleChildCount())
669 throw lang::IndexOutOfBoundsException();
673 sal_Int32
nCol(getAccessibleColumn(nChildIndex
));
674 sal_Int32
nRow(getAccessibleRow(nChildIndex
));
676 SelectCell(nRow
, nCol
, sal_False
);
681 ScAccessibleSpreadsheet::clearAccessibleSelection( )
682 throw (uno::RuntimeException
)
688 mpViewShell
->Unmark();
693 ScAccessibleSpreadsheet::selectAllAccessibleChildren( )
694 throw (uno::RuntimeException
)
700 mpViewShell
->SelectAll();
705 ScAccessibleSpreadsheet::getSelectedAccessibleChildCount( )
706 throw (uno::RuntimeException
)
710 sal_Int32
nResult(0);
715 mpMarkedRanges
= new ScRangeList();
716 ScMarkData
aMarkData(mpViewShell
->GetViewData()->GetMarkData());
717 aMarkData
.MarkToMulti();
718 aMarkData
.FillRangeListWithMarks(mpMarkedRanges
, sal_False
);
720 // is possible, because there shouldn't be overlapped ranges in it
722 nResult
= mpMarkedRanges
->GetCellCount();
727 uno::Reference
<XAccessible
> SAL_CALL
728 ScAccessibleSpreadsheet::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex
)
729 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
733 uno::Reference
< XAccessible
> xAccessible
;
738 mpMarkedRanges
= new ScRangeList();
739 mpViewShell
->GetViewData()->GetMarkData().FillRangeListWithMarks(mpMarkedRanges
, sal_False
);
743 if (!mpSortedMarkedCells
)
744 CreateSortedMarkedCells();
745 if (mpSortedMarkedCells
)
747 if ((nSelectedChildIndex
< 0) ||
748 (mpSortedMarkedCells
->size() <= static_cast<sal_uInt32
>(nSelectedChildIndex
)))
749 throw lang::IndexOutOfBoundsException();
751 xAccessible
= getAccessibleCellAt((*mpSortedMarkedCells
)[nSelectedChildIndex
].Row(), (*mpSortedMarkedCells
)[nSelectedChildIndex
].Col());
759 ScAccessibleSpreadsheet::deselectAccessibleChild( sal_Int32 nChildIndex
)
760 throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
765 if (nChildIndex
< 0 || nChildIndex
>= getAccessibleChildCount())
766 throw lang::IndexOutOfBoundsException();
770 sal_Int32
nCol(getAccessibleColumn(nChildIndex
));
771 sal_Int32
nRow(getAccessibleRow(nChildIndex
));
773 if (mpViewShell
->GetViewData()->GetMarkData().IsCellMarked(static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
)))
774 SelectCell(nRow
, nCol
, sal_True
);
778 void ScAccessibleSpreadsheet::SelectCell(sal_Int32 nRow
, sal_Int32 nCol
, sal_Bool bDeselect
)
780 mpViewShell
->SetTabNo( maRange
.aStart
.Tab() );
782 mpViewShell
->DoneBlockMode( sal_True
); // continue selecting
783 mpViewShell
->InitBlockMode( static_cast<SCCOL
>(nCol
), static_cast<SCROW
>(nRow
), maRange
.aStart
.Tab(), bDeselect
, sal_False
, sal_False
);
785 mpViewShell
->SelectionChanged();
788 void ScAccessibleSpreadsheet::CreateSortedMarkedCells()
790 mpSortedMarkedCells
= new std::vector
<ScMyAddress
>();
791 mpSortedMarkedCells
->reserve(mpMarkedRanges
->GetCellCount());
792 ScRange
* pRange
= mpMarkedRanges
->First();
795 if (pRange
->aStart
.Tab() != pRange
->aEnd
.Tab())
797 if ((maActiveCell
.Tab() >= pRange
->aStart
.Tab()) ||
798 maActiveCell
.Tab() <= pRange
->aEnd
.Tab())
800 ScRange
aRange(*pRange
);
801 aRange
.aStart
.SetTab(maActiveCell
.Tab());
802 aRange
.aEnd
.SetTab(maActiveCell
.Tab());
803 AddMarkedRange(aRange
);
807 DBG_ERROR("Range of wrong table");
810 else if(pRange
->aStart
.Tab() == maActiveCell
.Tab())
811 AddMarkedRange(*pRange
);
814 DBG_ERROR("Range of wrong table");
816 pRange
= mpMarkedRanges
->Next();
818 std::sort(mpSortedMarkedCells
->begin(), mpSortedMarkedCells
->end());
821 void ScAccessibleSpreadsheet::AddMarkedRange(const ScRange
& rRange
)
823 for (SCROW nRow
= rRange
.aStart
.Row(); nRow
<= rRange
.aEnd
.Row(); ++nRow
)
825 for (SCCOL nCol
= rRange
.aStart
.Col(); nCol
<= rRange
.aEnd
.Col(); ++nCol
)
827 ScMyAddress
aCell(nCol
, nRow
, maActiveCell
.Tab());
828 mpSortedMarkedCells
->push_back(aCell
);
833 //===== XServiceInfo ====================================================
835 ::rtl::OUString SAL_CALL
ScAccessibleSpreadsheet::getImplementationName(void)
836 throw (uno::RuntimeException
)
838 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleSpreadsheet"));
841 uno::Sequence
< ::rtl::OUString
> SAL_CALL
842 ScAccessibleSpreadsheet::getSupportedServiceNames (void)
843 throw (uno::RuntimeException
)
845 uno::Sequence
< ::rtl::OUString
> aSequence
= ScAccessibleTableBase::getSupportedServiceNames();
846 sal_Int32
nOldSize(aSequence
.getLength());
847 aSequence
.realloc(nOldSize
+ 1);
848 ::rtl::OUString
* pNames
= aSequence
.getArray();
850 pNames
[nOldSize
] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.AccessibleSpreadsheet"));
855 //===== XTypeProvider =======================================================
857 uno::Sequence
<sal_Int8
> SAL_CALL
858 ScAccessibleSpreadsheet::getImplementationId(void)
859 throw (uno::RuntimeException
)
863 static uno::Sequence
<sal_Int8
> aId
;
864 if (aId
.getLength() == 0)
867 rtl_createUuid (reinterpret_cast<sal_uInt8
*>(aId
.getArray()), 0, sal_True
);
872 ///===== XAccessibleEventBroadcaster =====================================
874 void SAL_CALL
ScAccessibleSpreadsheet::addEventListener(const uno::Reference
<XAccessibleEventListener
>& xListener
)
875 throw (uno::RuntimeException
)
879 ScAccessibleTableBase::addEventListener(xListener
);
883 mbIsFocusSend
= sal_True
;
886 AccessibleEventObject aEvent
;
887 aEvent
.EventId
= AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
;
888 aEvent
.Source
= uno::Reference
< XAccessibleContext
>(this);
889 aEvent
.NewValue
<<= getAccessibleCellAt(maActiveCell
.Row(), maActiveCell
.Col());
891 CommitChange(aEvent
);
895 //==== internal =========================================================
897 Rectangle
ScAccessibleSpreadsheet::GetBoundingBoxOnScreen() const
898 throw (uno::RuntimeException
)
903 Window
* pWindow
= mpViewShell
->GetWindowByPos(meSplitPos
);
905 aRect
= pWindow
->GetWindowExtentsRelative(NULL
);
910 Rectangle
ScAccessibleSpreadsheet::GetBoundingBox() const
911 throw (uno::RuntimeException
)
916 Window
* pWindow
= mpViewShell
->GetWindowByPos(meSplitPos
);
918 //#101986#; extends to the same window, because the parent is the document and it has the same window
919 aRect
= pWindow
->GetWindowExtentsRelative(pWindow
);
924 sal_Bool
ScAccessibleSpreadsheet::IsDefunc(
925 const uno::Reference
<XAccessibleStateSet
>& rxParentStates
)
927 return ScAccessibleContextBase::IsDefunc() || (mpViewShell
== NULL
) || !getAccessibleParent().is() ||
928 (rxParentStates
.is() && rxParentStates
->contains(AccessibleStateType::DEFUNC
));
931 sal_Bool
ScAccessibleSpreadsheet::IsEditable(
932 const uno::Reference
<XAccessibleStateSet
>& /* rxParentStates */)
934 sal_Bool
bProtected(sal_False
);
935 if (mpDoc
&& mpDoc
->IsTabProtected(maRange
.aStart
.Tab()))
936 bProtected
= sal_True
;
940 sal_Bool
ScAccessibleSpreadsheet::IsFocused()
942 sal_Bool
bFocused(sal_False
);
945 if (mpViewShell
->GetViewData()->GetActivePart() == meSplitPos
)
946 bFocused
= mpViewShell
->GetActiveWin()->HasFocus();
951 sal_Bool
ScAccessibleSpreadsheet::IsCompleteSheetSelected()
953 sal_Bool
bResult(sal_False
);
956 //#103800#; use a copy of MarkData
957 ScMarkData
aMarkData(mpViewShell
->GetViewData()->GetMarkData());
958 aMarkData
.MarkToMulti();
959 if (aMarkData
.IsAllMarked(maRange
))
965 ScDocument
* ScAccessibleSpreadsheet::GetDocument(ScTabViewShell
* pViewShell
)
967 ScDocument
* pDoc
= NULL
;
969 pDoc
= pViewShell
->GetViewData()->GetDocument();
973 Rectangle
ScAccessibleSpreadsheet::GetVisArea(ScTabViewShell
* pViewShell
, ScSplitPos eSplitPos
)
978 Window
* pWindow
= pViewShell
->GetWindowByPos(eSplitPos
);
981 aVisArea
.SetPos(pViewShell
->GetViewData()->GetPixPos(eSplitPos
));
982 aVisArea
.SetSize(pWindow
->GetSizePixel());
988 Rectangle
ScAccessibleSpreadsheet::GetVisCells(const Rectangle
& rVisArea
)
992 SCsCOL nStartX
, nEndX
;
993 SCsROW nStartY
, nEndY
;
995 mpViewShell
->GetViewData()->GetPosFromPixel( 1, 1, meSplitPos
, nStartX
, nStartY
);
996 mpViewShell
->GetViewData()->GetPosFromPixel( rVisArea
.GetWidth(), rVisArea
.GetHeight(), meSplitPos
, nEndX
, nEndY
);
998 return Rectangle(nStartX
, nStartY
, nEndX
, nEndY
);