fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / sc / source / ui / Accessibility / AccessibleSpreadsheet.cxx
blob2dddb0627fddd726183711c771782fe1b11275ef
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
26 #include "hints.hxx"
27 #include "scmod.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>
40 #include <algorithm>
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,
52 SCTAB nTab,
53 ScSplitPos eSplitPos)
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()
72 if (mpMarkedRanges)
73 delete mpMarkedRanges;
74 if (mpSortedMarkedCells)
75 delete mpSortedMarkedCells;
76 if (mpViewShell)
77 mpViewShell->RemoveAccessibilityObject(*this);
80 void ScAccessibleSpreadsheet::ConstructScAccessibleSpreadsheet(
81 ScAccessibleDocument* pAccDoc,
82 ScTabViewShell* pViewShell,
83 SCTAB nTab,
84 ScSplitPos eSplitPos)
86 mpViewShell = pViewShell;
87 mpMarkedRanges = 0;
88 mpSortedMarkedCells = 0;
89 mpAccDoc = pAccDoc;
90 mpAccCell = 0;
91 meSplitPos = eSplitPos;
92 mnTab = nTab;
93 mbHasSelection = false;
94 mbDelIns = false;
95 mbIsFocusSend = false;
96 maVisCells = GetVisCells(GetVisArea(mpViewShell, meSplitPos));
97 if (mpViewShell)
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();
108 mpAccCell->Init();
112 void SAL_CALL ScAccessibleSpreadsheet::disposing()
114 SolarMutexGuard aGuard;
115 if (mpViewShell)
117 mpViewShell->RemoveAccessibilityObject(*this);
118 mpViewShell = NULL;
120 if (mpAccCell)
122 mpAccCell->release();
123 mpAccCell = NULL;
126 ScAccessibleTableBase::disposing();
129 void ScAccessibleSpreadsheet::CompleteSelectionChanged(sal_Bool bNewState)
131 if (mpMarkedRanges)
132 DELETEZ(mpMarkedRanges);
133 if (mpSortedMarkedCells)
134 DELETEZ(mpSortedMarkedCells);
136 mbHasSelection = bNewState;
138 AccessibleEventObject aEvent;
139 aEvent.EventId = AccessibleEventId::STATE_CHANGED;
140 if (bNewState)
141 aEvent.NewValue = uno::makeAny(AccessibleStateType::SELECTED);
142 else
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);
159 CommitFocusLost();
162 void ScAccessibleSpreadsheet::GotFocus()
164 CommitFocusGained();
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))
203 if (mpViewShell)
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))
214 if (mpMarkedRanges)
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();
239 mpAccCell->Init();
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))
257 if (!mbDelIns)
258 CommitTableModelChange(maRange.aStart.Row(), maRange.aStart.Col(), maRange.aEnd.Row(), maRange.aEnd.Col(), AccessibleTableModelChangeType::UPDATE);
259 else
260 mbDelIns = false;
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
264 /* if (mpViewShell)
266 Rectangle aNewVisCells(GetVisCells(GetVisArea(mpViewShell, meSplitPos)));
268 Rectangle aNewPos(aNewVisCells);
270 if (aNewVisCells.IsOver(maVisCells))
271 aNewPos.Union(maVisCells);
272 else
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
292 mbDelIns = sal_True;
294 sal_Int16 nId(0);
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;
302 if (nX < 0)
304 nX = -nX;
305 nY = aRange.aEnd.Row() - aRange.aStart.Row();
307 else
309 nY = -nY;
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;
317 if (nX < 0)
318 nY = aRange.aEnd.Row() - aRange.aStart.Row();
319 else
320 nX = aRange.aEnd.Col() - aRange.aStart.Col();
322 else
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;
352 IsObjectValid();
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;
371 IsObjectValid();
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;
390 IsObjectValid();
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();
397 sal_Int32 nCount(0);
398 for (SCROW i = maRange.aStart.Row(); i <= maRange.aEnd.Row(); ++i)
400 if (rMarkdata.IsRowMarked(i))
402 pSequence[nCount] = i;
403 ++nCount;
406 aSequence.realloc(nCount);
408 else
409 aSequence.realloc(0);
410 return aSequence;
413 uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleSpreadsheet::getSelectedAccessibleColumns( )
414 throw (uno::RuntimeException)
416 SolarMutexGuard aGuard;
417 IsObjectValid();
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();
424 sal_Int32 nCount(0);
425 for (SCCOL i = maRange.aStart.Col(); i <= maRange.aEnd.Col(); ++i)
427 if (rMarkdata.IsColumnMarked(i))
429 pSequence[nCount] = i;
430 ++nCount;
433 aSequence.realloc(nCount);
435 else
436 aSequence.realloc(0);
437 return aSequence;
440 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleRowSelected( sal_Int32 nRow )
441 throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
443 SolarMutexGuard aGuard;
444 IsObjectValid();
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);
455 return bResult;
458 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleColumnSelected( sal_Int32 nColumn )
459 throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
461 SolarMutexGuard aGuard;
462 IsObjectValid();
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);
473 return bResult;
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;
485 else
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;
495 IsObjectValid();
496 if (nRow > (maRange.aEnd.Row() - maRange.aStart.Row()) ||
497 nRow < 0 ||
498 nColumn > (maRange.aEnd.Col() - maRange.aStart.Col()) ||
499 nColumn < 0)
500 throw lang::IndexOutOfBoundsException();
502 uno::Reference<XAccessible> xAccessible;
503 ScAccessibleCell* pAccessibleCell = GetAccessibleCellAt(nRow, nColumn);
504 xAccessible = pAccessibleCell;
505 pAccessibleCell->Init();
506 return xAccessible;
509 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn )
510 throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
512 SolarMutexGuard aGuard;
513 IsObjectValid();
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);
520 if (mpViewShell)
522 const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
523 bResult = rMarkdata.IsCellMarked(static_cast<SCCOL>(nColumn), static_cast<SCROW>(nRow));
525 return bResult;
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;
538 IsObjectValid();
539 if (mpViewShell)
541 SCsCOL nX;
542 SCsROW nY;
543 mpViewShell->GetViewData()->GetPosFromPixel( rPoint.X, rPoint.Y, meSplitPos, nX, nY);
544 xAccessible = getAccessibleCellAt(nY, nX);
547 return xAccessible;
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)
564 return COL_BLACK;
567 sal_Int32 SAL_CALL ScAccessibleSpreadsheet::getBackground( )
568 throw (uno::RuntimeException)
570 SolarMutexGuard aGuard;
571 IsObjectValid();
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;
581 if(mpAccDoc)
582 pRelationSet = mpAccDoc->GetRelationSet(NULL);
583 if (!pRelationSet)
584 pRelationSet = new utl::AccessibleRelationSetHelper();
585 return pRelationSet;
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);
602 else
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);
609 if (IsFocused())
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);
616 if (isShowing())
617 pStateSet->AddState(AccessibleStateType::SHOWING);
618 if (isVisible())
619 pStateSet->AddState(AccessibleStateType::VISIBLE);
621 return pStateSet;
624 ///===== XAccessibleSelection ===========================================
626 void SAL_CALL
627 ScAccessibleSpreadsheet::selectAccessibleChild( sal_Int32 nChildIndex )
628 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
630 SolarMutexGuard aGuard;
631 IsObjectValid();
632 if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
633 throw lang::IndexOutOfBoundsException();
635 if (mpViewShell)
637 sal_Int32 nCol(getAccessibleColumn(nChildIndex));
638 sal_Int32 nRow(getAccessibleRow(nChildIndex));
640 SelectCell(nRow, nCol, false);
644 void SAL_CALL
645 ScAccessibleSpreadsheet::clearAccessibleSelection( )
646 throw (uno::RuntimeException)
648 SolarMutexGuard aGuard;
649 IsObjectValid();
650 if (mpViewShell)
652 mpViewShell->Unmark();
656 void SAL_CALL
657 ScAccessibleSpreadsheet::selectAllAccessibleChildren( )
658 throw (uno::RuntimeException)
660 SolarMutexGuard aGuard;
661 IsObjectValid();
662 if (mpViewShell)
664 mpViewShell->SelectAll();
668 sal_Int32 SAL_CALL
669 ScAccessibleSpreadsheet::getSelectedAccessibleChildCount( )
670 throw (uno::RuntimeException)
672 SolarMutexGuard aGuard;
673 IsObjectValid();
674 sal_Int32 nResult(0);
675 if (mpViewShell)
677 if (!mpMarkedRanges)
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
685 if (mpMarkedRanges)
686 nResult = mpMarkedRanges->GetCellCount();
688 return nResult;
691 uno::Reference<XAccessible > SAL_CALL
692 ScAccessibleSpreadsheet::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
693 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
695 SolarMutexGuard aGuard;
696 IsObjectValid();
697 uno::Reference < XAccessible > xAccessible;
698 if (mpViewShell)
700 if (!mpMarkedRanges)
702 mpMarkedRanges = new ScRangeList();
703 mpViewShell->GetViewData()->GetMarkData().FillRangeListWithMarks(mpMarkedRanges, false);
705 if (mpMarkedRanges)
707 if (!mpSortedMarkedCells)
708 CreateSortedMarkedCells();
709 if (mpSortedMarkedCells)
711 if ((nSelectedChildIndex < 0) ||
712 (mpSortedMarkedCells->size() <= static_cast<sal_uInt32>(nSelectedChildIndex)))
713 throw lang::IndexOutOfBoundsException();
714 else
715 xAccessible = getAccessibleCellAt((*mpSortedMarkedCells)[nSelectedChildIndex].Row(), (*mpSortedMarkedCells)[nSelectedChildIndex].Col());
719 return xAccessible;
722 void SAL_CALL
723 ScAccessibleSpreadsheet::deselectAccessibleChild( sal_Int32 nChildIndex )
724 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
726 SolarMutexGuard aGuard;
727 IsObjectValid();
729 if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
730 throw lang::IndexOutOfBoundsException();
732 if (mpViewShell)
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);
769 else
771 OSL_FAIL("Range of wrong table");
774 else if(pRange->aStart.Tab() == maActiveCell.Tab())
775 AddMarkedRange(*pRange);
776 else
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");
815 return aSequence;
818 //===== XTypeProvider =======================================================
820 namespace
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;
838 IsObjectValid();
839 ScAccessibleTableBase::addAccessibleEventListener(xListener);
841 if (!mbIsFocusSend)
843 mbIsFocusSend = sal_True;
844 CommitFocusGained();
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)
860 Rectangle aRect;
861 if (mpViewShell)
863 Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
864 if (pWindow)
865 aRect = pWindow->GetWindowExtentsRelative(NULL);
867 return aRect;
870 Rectangle ScAccessibleSpreadsheet::GetBoundingBox() const
871 throw (uno::RuntimeException)
873 Rectangle aRect;
874 if (mpViewShell)
876 Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
877 if (pWindow)
878 //#101986#; extends to the same window, because the parent is the document and it has the same window
879 aRect = pWindow->GetWindowExtentsRelative(pWindow);
881 return aRect;
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;
897 return !bProtected;
900 sal_Bool ScAccessibleSpreadsheet::IsFocused()
902 sal_Bool bFocused(false);
903 if (mpViewShell)
905 if (mpViewShell->GetViewData()->GetActivePart() == meSplitPos)
906 bFocused = mpViewShell->GetActiveWin()->HasFocus();
908 return bFocused;
911 sal_Bool ScAccessibleSpreadsheet::IsCompleteSheetSelected()
913 sal_Bool bResult(false);
914 if(mpViewShell)
916 //#103800#; use a copy of MarkData
917 ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData());
918 aMarkData.MarkToMulti();
919 if (aMarkData.IsAllMarked(maRange))
920 bResult = sal_True;
922 return bResult;
925 ScDocument* ScAccessibleSpreadsheet::GetDocument(ScTabViewShell* pViewShell)
927 ScDocument* pDoc = NULL;
928 if (pViewShell)
929 pDoc = pViewShell->GetViewData()->GetDocument();
930 return pDoc;
933 Rectangle ScAccessibleSpreadsheet::GetVisArea(ScTabViewShell* pViewShell, ScSplitPos eSplitPos)
935 Rectangle aVisArea;
936 if (pViewShell)
938 Window* pWindow = pViewShell->GetWindowByPos(eSplitPos);
939 if (pWindow)
941 aVisArea.SetPos(pViewShell->GetViewData()->GetPixPos(eSplitPos));
942 aVisArea.SetSize(pWindow->GetSizePixel());
945 return aVisArea;
948 Rectangle ScAccessibleSpreadsheet::GetVisCells(const Rectangle& rVisArea)
950 if (mpViewShell)
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);
960 else
961 return Rectangle();
964 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */