merge the formfield patch from ooo-build
[ooovba.git] / sc / source / ui / Accessibility / AccessibleSpreadsheet.cxx
blob8036e35e1f43f4b2d30897d606296e7bf8b9f4cf
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: AccessibleSpreadsheet.cxx,v $
10 * $Revision: 1.51 $
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"
42 #include "hints.hxx"
43 #include "scmod.hxx"
45 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
46 #include <unotools/accessiblestatesethelper.hxx>
47 #endif
48 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
49 #include <com/sun/star/accessibility/AccessibleRole.hpp>
50 #endif
51 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
52 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
53 #endif
54 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
55 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
56 #include <rtl/uuid.h>
57 #include <tools/debug.hxx>
58 #include <tools/gen.hxx>
59 #include <svtools/colorcfg.hxx>
61 #include <algorithm>
63 using namespace ::com::sun::star;
64 using namespace ::com::sun::star::accessibility;
66 //===== internal ============================================================
68 ScAccessibleSpreadsheet::ScAccessibleSpreadsheet(
69 ScAccessibleDocument* pAccDoc,
70 ScTabViewShell* pViewShell,
71 SCTAB nTab,
72 ScSplitPos eSplitPos)
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()
91 if (mpMarkedRanges)
92 delete mpMarkedRanges;
93 if (mpSortedMarkedCells)
94 delete mpSortedMarkedCells;
95 if (mpViewShell)
96 mpViewShell->RemoveAccessibilityObject(*this);
99 void ScAccessibleSpreadsheet::ConstructScAccessibleSpreadsheet(
100 ScAccessibleDocument* pAccDoc,
101 ScTabViewShell* pViewShell,
102 SCTAB nTab,
103 ScSplitPos eSplitPos)
105 mpViewShell = pViewShell;
106 mpMarkedRanges = 0;
107 mpSortedMarkedCells = 0;
108 mpAccDoc = pAccDoc;
109 mpAccCell = 0;
110 meSplitPos = eSplitPos;
111 mnTab = nTab;
112 mbHasSelection = sal_False;
113 mbDelIns = sal_False;
114 mbIsFocusSend = sal_False;
115 maVisCells = GetVisCells(GetVisArea(mpViewShell, meSplitPos));
116 if (mpViewShell)
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();
127 mpAccCell->Init();
131 void SAL_CALL ScAccessibleSpreadsheet::disposing()
133 ScUnoGuard aGuard;
134 if (mpViewShell)
136 mpViewShell->RemoveAccessibilityObject(*this);
137 mpViewShell = NULL;
139 if (mpAccCell)
141 mpAccCell->release();
142 mpAccCell = NULL;
145 ScAccessibleTableBase::disposing();
148 void ScAccessibleSpreadsheet::CompleteSelectionChanged(sal_Bool bNewState)
150 if (mpMarkedRanges)
151 DELETEZ(mpMarkedRanges);
152 if (mpSortedMarkedCells)
153 DELETEZ(mpSortedMarkedCells);
155 mbHasSelection = bNewState;
157 AccessibleEventObject aEvent;
158 aEvent.EventId = AccessibleEventId::STATE_CHANGED;
159 if (bNewState)
160 aEvent.NewValue = uno::makeAny(AccessibleStateType::SELECTED);
161 else
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);
178 CommitFocusLost();
181 void ScAccessibleSpreadsheet::GotFocus()
183 CommitFocusGained();
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))
222 if (mpViewShell)
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))
233 if (mpMarkedRanges)
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();
258 mpAccCell->Init();
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))
276 if (!mbDelIns)
277 CommitTableModelChange(maRange.aStart.Row(), maRange.aStart.Col(), maRange.aEnd.Row(), maRange.aEnd.Col(), AccessibleTableModelChangeType::UPDATE);
278 else
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
291 /* if (mpViewShell)
293 Rectangle aNewVisCells(GetVisCells(GetVisArea(mpViewShell, meSplitPos)));
295 Rectangle aNewPos(aNewVisCells);
297 if (aNewVisCells.IsOver(maVisCells))
298 aNewPos.Union(maVisCells);
299 else
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
328 mbDelIns = sal_True;
330 sal_Int16 nId(0);
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;
338 if (nX < 0)
340 nX = -nX;
341 nY = aRange.aEnd.Row() - aRange.aStart.Row();
343 else
345 nY = -nY;
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;
353 if (nX < 0)
354 nY = aRange.aEnd.Row() - aRange.aStart.Row();
355 else
356 nX = aRange.aEnd.Col() - aRange.aStart.Col();
358 else
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)
387 ScUnoGuard aGuard;
388 IsObjectValid();
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)
406 ScUnoGuard aGuard;
407 IsObjectValid();
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)
425 ScUnoGuard aGuard;
426 IsObjectValid();
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();
433 sal_Int32 nCount(0);
434 for (SCROW i = maRange.aStart.Row(); i <= maRange.aEnd.Row(); ++i)
436 if (rMarkdata.IsRowMarked(i))
438 pSequence[nCount] = i;
439 ++nCount;
442 aSequence.realloc(nCount);
444 else
445 aSequence.realloc(0);
446 return aSequence;
449 uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleSpreadsheet::getSelectedAccessibleColumns( )
450 throw (uno::RuntimeException)
452 ScUnoGuard aGuard;
453 IsObjectValid();
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();
460 sal_Int32 nCount(0);
461 for (SCCOL i = maRange.aStart.Col(); i <= maRange.aEnd.Col(); ++i)
463 if (rMarkdata.IsColumnMarked(i))
465 pSequence[nCount] = i;
466 ++nCount;
469 aSequence.realloc(nCount);
471 else
472 aSequence.realloc(0);
473 return aSequence;
476 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleRowSelected( sal_Int32 nRow )
477 throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
479 ScUnoGuard aGuard;
480 IsObjectValid();
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);
491 return bResult;
494 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleColumnSelected( sal_Int32 nColumn )
495 throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
497 ScUnoGuard aGuard;
498 IsObjectValid();
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);
509 return bResult;
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;
521 else
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)
530 ScUnoGuard aGuard;
531 IsObjectValid();
532 if (nRow > (maRange.aEnd.Row() - maRange.aStart.Row()) ||
533 nRow < 0 ||
534 nColumn > (maRange.aEnd.Col() - maRange.aStart.Col()) ||
535 nColumn < 0)
536 throw lang::IndexOutOfBoundsException();
538 uno::Reference<XAccessible> xAccessible;
539 ScAccessibleCell* pAccessibleCell = GetAccessibleCellAt(nRow, nColumn);
540 xAccessible = pAccessibleCell;
541 pAccessibleCell->Init();
542 return xAccessible;
545 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn )
546 throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
548 ScUnoGuard aGuard;
549 IsObjectValid();
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);
556 if (mpViewShell)
558 const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
559 bResult = rMarkdata.IsCellMarked(static_cast<SCCOL>(nColumn), static_cast<SCROW>(nRow));
561 return bResult;
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))
573 ScUnoGuard aGuard;
574 IsObjectValid();
575 if (mpViewShell)
577 SCsCOL nX;
578 SCsROW nY;
579 mpViewShell->GetViewData()->GetPosFromPixel( rPoint.X, rPoint.Y, meSplitPos, nX, nY);
580 xAccessible = getAccessibleCellAt(nY, nX);
583 return xAccessible;
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)
600 return COL_BLACK;
603 sal_Int32 SAL_CALL ScAccessibleSpreadsheet::getBackground( )
604 throw (uno::RuntimeException)
606 ScUnoGuard aGuard;
607 IsObjectValid();
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;
617 if(mpAccDoc)
618 pRelationSet = mpAccDoc->GetRelationSet(NULL);
619 if (!pRelationSet)
620 pRelationSet = new utl::AccessibleRelationSetHelper();
621 return pRelationSet;
624 uno::Reference<XAccessibleStateSet> SAL_CALL
625 ScAccessibleSpreadsheet::getAccessibleStateSet(void)
626 throw (uno::RuntimeException)
628 ScUnoGuard aGuard;
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);
638 else
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);
645 if (IsFocused())
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);
652 if (isShowing())
653 pStateSet->AddState(AccessibleStateType::SHOWING);
654 if (isVisible())
655 pStateSet->AddState(AccessibleStateType::VISIBLE);
657 return pStateSet;
660 ///===== XAccessibleSelection ===========================================
662 void SAL_CALL
663 ScAccessibleSpreadsheet::selectAccessibleChild( sal_Int32 nChildIndex )
664 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
666 ScUnoGuard aGuard;
667 IsObjectValid();
668 if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
669 throw lang::IndexOutOfBoundsException();
671 if (mpViewShell)
673 sal_Int32 nCol(getAccessibleColumn(nChildIndex));
674 sal_Int32 nRow(getAccessibleRow(nChildIndex));
676 SelectCell(nRow, nCol, sal_False);
680 void SAL_CALL
681 ScAccessibleSpreadsheet::clearAccessibleSelection( )
682 throw (uno::RuntimeException)
684 ScUnoGuard aGuard;
685 IsObjectValid();
686 if (mpViewShell)
688 mpViewShell->Unmark();
692 void SAL_CALL
693 ScAccessibleSpreadsheet::selectAllAccessibleChildren( )
694 throw (uno::RuntimeException)
696 ScUnoGuard aGuard;
697 IsObjectValid();
698 if (mpViewShell)
700 mpViewShell->SelectAll();
704 sal_Int32 SAL_CALL
705 ScAccessibleSpreadsheet::getSelectedAccessibleChildCount( )
706 throw (uno::RuntimeException)
708 ScUnoGuard aGuard;
709 IsObjectValid();
710 sal_Int32 nResult(0);
711 if (mpViewShell)
713 if (!mpMarkedRanges)
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
721 if (mpMarkedRanges)
722 nResult = mpMarkedRanges->GetCellCount();
724 return nResult;
727 uno::Reference<XAccessible > SAL_CALL
728 ScAccessibleSpreadsheet::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
729 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
731 ScUnoGuard aGuard;
732 IsObjectValid();
733 uno::Reference < XAccessible > xAccessible;
734 if (mpViewShell)
736 if (!mpMarkedRanges)
738 mpMarkedRanges = new ScRangeList();
739 mpViewShell->GetViewData()->GetMarkData().FillRangeListWithMarks(mpMarkedRanges, sal_False);
741 if (mpMarkedRanges)
743 if (!mpSortedMarkedCells)
744 CreateSortedMarkedCells();
745 if (mpSortedMarkedCells)
747 if ((nSelectedChildIndex < 0) ||
748 (mpSortedMarkedCells->size() <= static_cast<sal_uInt32>(nSelectedChildIndex)))
749 throw lang::IndexOutOfBoundsException();
750 else
751 xAccessible = getAccessibleCellAt((*mpSortedMarkedCells)[nSelectedChildIndex].Row(), (*mpSortedMarkedCells)[nSelectedChildIndex].Col());
755 return xAccessible;
758 void SAL_CALL
759 ScAccessibleSpreadsheet::deselectAccessibleChild( sal_Int32 nChildIndex )
760 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
762 ScUnoGuard aGuard;
763 IsObjectValid();
765 if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
766 throw lang::IndexOutOfBoundsException();
768 if (mpViewShell)
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();
793 while (pRange)
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);
805 else
807 DBG_ERROR("Range of wrong table");
810 else if(pRange->aStart.Tab() == maActiveCell.Tab())
811 AddMarkedRange(*pRange);
812 else
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"));
852 return aSequence;
855 //===== XTypeProvider =======================================================
857 uno::Sequence<sal_Int8> SAL_CALL
858 ScAccessibleSpreadsheet::getImplementationId(void)
859 throw (uno::RuntimeException)
861 ScUnoGuard aGuard;
862 IsObjectValid();
863 static uno::Sequence<sal_Int8> aId;
864 if (aId.getLength() == 0)
866 aId.realloc (16);
867 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
869 return aId;
872 ///===== XAccessibleEventBroadcaster =====================================
874 void SAL_CALL ScAccessibleSpreadsheet::addEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
875 throw (uno::RuntimeException)
877 ScUnoGuard aGuard;
878 IsObjectValid();
879 ScAccessibleTableBase::addEventListener(xListener);
881 if (!mbIsFocusSend)
883 mbIsFocusSend = sal_True;
884 CommitFocusGained();
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)
900 Rectangle aRect;
901 if (mpViewShell)
903 Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
904 if (pWindow)
905 aRect = pWindow->GetWindowExtentsRelative(NULL);
907 return aRect;
910 Rectangle ScAccessibleSpreadsheet::GetBoundingBox() const
911 throw (uno::RuntimeException)
913 Rectangle aRect;
914 if (mpViewShell)
916 Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
917 if (pWindow)
918 //#101986#; extends to the same window, because the parent is the document and it has the same window
919 aRect = pWindow->GetWindowExtentsRelative(pWindow);
921 return aRect;
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;
937 return !bProtected;
940 sal_Bool ScAccessibleSpreadsheet::IsFocused()
942 sal_Bool bFocused(sal_False);
943 if (mpViewShell)
945 if (mpViewShell->GetViewData()->GetActivePart() == meSplitPos)
946 bFocused = mpViewShell->GetActiveWin()->HasFocus();
948 return bFocused;
951 sal_Bool ScAccessibleSpreadsheet::IsCompleteSheetSelected()
953 sal_Bool bResult(sal_False);
954 if(mpViewShell)
956 //#103800#; use a copy of MarkData
957 ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData());
958 aMarkData.MarkToMulti();
959 if (aMarkData.IsAllMarked(maRange))
960 bResult = sal_True;
962 return bResult;
965 ScDocument* ScAccessibleSpreadsheet::GetDocument(ScTabViewShell* pViewShell)
967 ScDocument* pDoc = NULL;
968 if (pViewShell)
969 pDoc = pViewShell->GetViewData()->GetDocument();
970 return pDoc;
973 Rectangle ScAccessibleSpreadsheet::GetVisArea(ScTabViewShell* pViewShell, ScSplitPos eSplitPos)
975 Rectangle aVisArea;
976 if (pViewShell)
978 Window* pWindow = pViewShell->GetWindowByPos(eSplitPos);
979 if (pWindow)
981 aVisArea.SetPos(pViewShell->GetViewData()->GetPixPos(eSplitPos));
982 aVisArea.SetSize(pWindow->GetSizePixel());
985 return aVisArea;
988 Rectangle ScAccessibleSpreadsheet::GetVisCells(const Rectangle& rVisArea)
990 if (mpViewShell)
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);
1000 else
1001 return Rectangle();