summaryrefslogtreecommitdiff
path: root/sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx')
-rw-r--r--sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx999
1 files changed, 999 insertions, 0 deletions
diff --git a/sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx b/sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx
new file mode 100644
index 000000000000..f85fb22531aa
--- /dev/null
+++ b/sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx
@@ -0,0 +1,999 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sc.hxx"
+
+
+#include "AccessibleSpreadsheet.hxx"
+#include "AccessibilityHints.hxx"
+#include "AccessibleCell.hxx"
+#include "AccessibleDocument.hxx"
+#include "tabvwsh.hxx"
+#include "document.hxx"
+#include "unoguard.hxx"
+#include "hints.hxx"
+#include "scmod.hxx"
+
+#ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
+#include <unotools/accessiblestatesethelper.hxx>
+#endif
+#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#endif
+#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#endif
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
+#include <rtl/uuid.h>
+#include <tools/debug.hxx>
+#include <tools/gen.hxx>
+#include <svtools/colorcfg.hxx>
+
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::accessibility;
+
+//===== internal ============================================================
+
+ScAccessibleSpreadsheet::ScAccessibleSpreadsheet(
+ ScAccessibleDocument* pAccDoc,
+ ScTabViewShell* pViewShell,
+ SCTAB nTab,
+ ScSplitPos eSplitPos)
+ :
+ ScAccessibleTableBase (pAccDoc, GetDocument(pViewShell),
+ ScRange(ScAddress(0, 0, nTab),ScAddress(MAXCOL, MAXROW, nTab))),
+ mbIsSpreadsheet( sal_True )
+{
+ ConstructScAccessibleSpreadsheet( pAccDoc, pViewShell, nTab, eSplitPos );
+}
+
+ScAccessibleSpreadsheet::ScAccessibleSpreadsheet(
+ ScAccessibleSpreadsheet& rParent, const ScRange& rRange ) :
+ ScAccessibleTableBase( rParent.mpAccDoc, rParent.mpDoc, rRange),
+ mbIsSpreadsheet( sal_False )
+{
+ ConstructScAccessibleSpreadsheet( rParent.mpAccDoc, rParent.mpViewShell, rParent.mnTab, rParent.meSplitPos );
+}
+
+ScAccessibleSpreadsheet::~ScAccessibleSpreadsheet()
+{
+ if (mpMarkedRanges)
+ delete mpMarkedRanges;
+ if (mpSortedMarkedCells)
+ delete mpSortedMarkedCells;
+ if (mpViewShell)
+ mpViewShell->RemoveAccessibilityObject(*this);
+}
+
+void ScAccessibleSpreadsheet::ConstructScAccessibleSpreadsheet(
+ ScAccessibleDocument* pAccDoc,
+ ScTabViewShell* pViewShell,
+ SCTAB nTab,
+ ScSplitPos eSplitPos)
+{
+ mpViewShell = pViewShell;
+ mpMarkedRanges = 0;
+ mpSortedMarkedCells = 0;
+ mpAccDoc = pAccDoc;
+ mpAccCell = 0;
+ meSplitPos = eSplitPos;
+ mnTab = nTab;
+ mbHasSelection = sal_False;
+ mbDelIns = sal_False;
+ mbIsFocusSend = sal_False;
+ maVisCells = GetVisCells(GetVisArea(mpViewShell, meSplitPos));
+ if (mpViewShell)
+ {
+ mpViewShell->AddAccessibilityObject(*this);
+
+ const ScViewData& rViewData = *mpViewShell->GetViewData();
+ const ScMarkData& rMarkData = rViewData.GetMarkData();
+ maActiveCell = rViewData.GetCurPos();
+ mbHasSelection = rMarkData.GetTableSelect(maActiveCell.Tab()) &&
+ (rMarkData.IsMarked() || rMarkData.IsMultiMarked());
+ mpAccCell = GetAccessibleCellAt(maActiveCell.Row(), maActiveCell.Col());
+ mpAccCell->acquire();
+ mpAccCell->Init();
+ }
+}
+
+void SAL_CALL ScAccessibleSpreadsheet::disposing()
+{
+ ScUnoGuard aGuard;
+ if (mpViewShell)
+ {
+ mpViewShell->RemoveAccessibilityObject(*this);
+ mpViewShell = NULL;
+ }
+ if (mpAccCell)
+ {
+ mpAccCell->release();
+ mpAccCell = NULL;
+ }
+
+ ScAccessibleTableBase::disposing();
+}
+
+void ScAccessibleSpreadsheet::CompleteSelectionChanged(sal_Bool bNewState)
+{
+ if (mpMarkedRanges)
+ DELETEZ(mpMarkedRanges);
+ if (mpSortedMarkedCells)
+ DELETEZ(mpSortedMarkedCells);
+
+ mbHasSelection = bNewState;
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::STATE_CHANGED;
+ if (bNewState)
+ aEvent.NewValue = uno::makeAny(AccessibleStateType::SELECTED);
+ else
+ aEvent.OldValue = uno::makeAny(AccessibleStateType::SELECTED);
+ aEvent.Source = uno::Reference< XAccessibleContext >(this);
+
+ CommitChange(aEvent);
+}
+
+void ScAccessibleSpreadsheet::LostFocus()
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
+ aEvent.Source = uno::Reference< XAccessibleContext >(this);
+ uno::Reference< XAccessible > xOld = mpAccCell;
+ aEvent.OldValue <<= xOld;
+
+ CommitChange(aEvent);
+
+ CommitFocusLost();
+}
+
+void ScAccessibleSpreadsheet::GotFocus()
+{
+ CommitFocusGained();
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
+ aEvent.Source = uno::Reference< XAccessibleContext >(this);
+ uno::Reference< XAccessible > xNew = mpAccCell;
+ aEvent.NewValue <<= xNew;
+
+ CommitChange(aEvent);
+}
+
+void ScAccessibleSpreadsheet::BoundingBoxChanged()
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
+ aEvent.Source = uno::Reference< XAccessibleContext >(this);
+
+ CommitChange(aEvent);
+}
+
+void ScAccessibleSpreadsheet::VisAreaChanged()
+{
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
+ aEvent.Source = uno::Reference< XAccessibleContext >(this);
+
+ CommitChange(aEvent);
+}
+
+ //===== SfxListener =====================================================
+
+void ScAccessibleSpreadsheet::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
+{
+ if (rHint.ISA( SfxSimpleHint ) )
+ {
+ const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
+ // only notify if child exist, otherwise it is not necessary
+ if ((rRef.GetId() == SC_HINT_ACC_CURSORCHANGED))
+ {
+ if (mpViewShell)
+ {
+ ScAddress aNewCell = mpViewShell->GetViewData()->GetCurPos();
+ sal_Bool bNewMarked(mpViewShell->GetViewData()->GetMarkData().GetTableSelect(aNewCell.Tab()) &&
+ (mpViewShell->GetViewData()->GetMarkData().IsMarked() ||
+ mpViewShell->GetViewData()->GetMarkData().IsMultiMarked()));
+ sal_Bool bNewCellSelected(isAccessibleSelected(aNewCell.Row(), aNewCell.Col()));
+ if ((bNewMarked != mbHasSelection) ||
+ (!bNewCellSelected && bNewMarked) ||
+ (bNewCellSelected && mbHasSelection))
+ {
+ if (mpMarkedRanges)
+ DELETEZ(mpMarkedRanges);
+ if (mpSortedMarkedCells)
+ DELETEZ(mpSortedMarkedCells);
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
+ aEvent.Source = uno::Reference< XAccessibleContext >(this);
+
+ mbHasSelection = bNewMarked;
+
+ CommitChange(aEvent);
+ }
+
+ // active descendant changed event (new cell selected)
+ bool bFireActiveDescChanged = (aNewCell != maActiveCell) &&
+ (aNewCell.Tab() == maActiveCell.Tab()) && IsFocused();
+
+ /* Remember old active cell and set new active cell.
+ #i82409# always update the class members mpAccCell and
+ maActiveCell, even if the sheet is not focused, e.g. when
+ using the name box in the toolbar. */
+ uno::Reference< XAccessible > xOld = mpAccCell;
+ mpAccCell->release();
+ mpAccCell = GetAccessibleCellAt(aNewCell.Row(), aNewCell.Col());
+ mpAccCell->acquire();
+ mpAccCell->Init();
+ uno::Reference< XAccessible > xNew = mpAccCell;
+ maActiveCell = aNewCell;
+
+ // #i14108# fire event only if sheet is focused
+ if( bFireActiveDescChanged )
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
+ aEvent.Source = uno::Reference< XAccessibleContext >(this);
+ aEvent.OldValue <<= xOld;
+ aEvent.NewValue <<= xNew;
+ CommitChange(aEvent);
+ }
+ }
+ }
+ else if ((rRef.GetId() == SC_HINT_DATACHANGED))
+ {
+ if (!mbDelIns)
+ CommitTableModelChange(maRange.aStart.Row(), maRange.aStart.Col(), maRange.aEnd.Row(), maRange.aEnd.Col(), AccessibleTableModelChangeType::UPDATE);
+ else
+ mbDelIns = sal_False;
+ }
+ // no longer needed, because the document calls the VisAreaChanged method
+/* else if (rRef.GetId() == SC_HINT_ACC_VISAREACHANGED)
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
+ aEvent.Source = uno::Reference< XAccessibleContext >(this);
+
+ CommitChange(aEvent);*/
+ // commented out, because to use a ModelChangeEvent is not the right way
+ // at the moment there is no way, but the Java/Gnome Api should be extended sometime
+/* if (mpViewShell)
+ {
+ Rectangle aNewVisCells(GetVisCells(GetVisArea(mpViewShell, meSplitPos)));
+
+ Rectangle aNewPos(aNewVisCells);
+
+ if (aNewVisCells.IsOver(maVisCells))
+ aNewPos.Union(maVisCells);
+ else
+ CommitTableModelChange(maVisCells.Top(), maVisCells.Left(), maVisCells.Bottom(), maVisCells.Right(), AccessibleTableModelChangeType::UPDATE);
+
+ maVisCells = aNewVisCells;
+
+ CommitTableModelChange(aNewPos.Top(), aNewPos.Left(), aNewPos.Bottom(), aNewPos.Right(), AccessibleTableModelChangeType::UPDATE);
+ }
+ }*/
+ // no longer needed, because the document calls the BoundingBoxChanged method
+/* else if (rRef.GetId() == SC_HINT_ACC_WINDOWRESIZED)
+ {
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
+ aEvent.Source = uno::Reference< XAccessibleContext >(this);
+
+ CommitChange(aEvent);
+ }*/
+ }
+ else if (rHint.ISA( ScUpdateRefHint ))
+ {
+ const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint;
+ if (rRef.GetMode() == URM_INSDEL && rRef.GetDz() == 0) //#107250# test whether table is inserted or deleted
+ {
+ if (((rRef.GetRange().aStart.Col() == maRange.aStart.Col()) &&
+ (rRef.GetRange().aEnd.Col() == maRange.aEnd.Col())) ||
+ ((rRef.GetRange().aStart.Row() == maRange.aStart.Row()) &&
+ (rRef.GetRange().aEnd.Row() == maRange.aEnd.Row())))
+ {
+ // ignore next SC_HINT_DATACHANGED notification
+ mbDelIns = sal_True;
+
+ sal_Int16 nId(0);
+ SCsCOL nX(rRef.GetDx());
+ SCsROW nY(rRef.GetDy());
+ ScRange aRange(rRef.GetRange());
+ if ((nX < 0) || (nY < 0))
+ {
+ DBG_ASSERT(!((nX < 0) && (nY < 0)), "should not be possible to remove row and column at the same time");
+ nId = AccessibleTableModelChangeType::DELETE;
+ if (nX < 0)
+ {
+ nX = -nX;
+ nY = aRange.aEnd.Row() - aRange.aStart.Row();
+ }
+ else
+ {
+ nY = -nY;
+ nX = aRange.aEnd.Col() - aRange.aStart.Col();
+ }
+ }
+ else if ((nX > 0) || (nY > 0))
+ {
+ DBG_ASSERT(!((nX > 0) && (nY > 0)), "should not be possible to add row and column at the same time");
+ nId = AccessibleTableModelChangeType::INSERT;
+ if (nX < 0)
+ nY = aRange.aEnd.Row() - aRange.aStart.Row();
+ else
+ nX = aRange.aEnd.Col() - aRange.aStart.Col();
+ }
+ else
+ {
+ DBG_ERROR("is it a deletion or a insertion?");
+ }
+
+ CommitTableModelChange(rRef.GetRange().aStart.Row(),
+ rRef.GetRange().aStart.Col(),
+ rRef.GetRange().aStart.Row() + nY,
+ rRef.GetRange().aStart.Col() + nX, nId);
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
+ aEvent.Source = uno::Reference< XAccessibleContext >(this);
+ uno::Reference< XAccessible > xNew = mpAccCell;
+ aEvent.NewValue <<= xNew;
+
+ CommitChange(aEvent);
+ }
+ }
+ }
+
+ ScAccessibleTableBase::Notify(rBC, rHint);
+}
+
+ //===== XAccessibleTable ================================================
+
+uno::Reference< XAccessibleTable > SAL_CALL ScAccessibleSpreadsheet::getAccessibleRowHeaders( )
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ uno::Reference< XAccessibleTable > xAccessibleTable;
+ if( mpDoc && mbIsSpreadsheet )
+ {
+ if( const ScRange* pRowRange = mpDoc->GetRepeatRowRange( mnTab ) )
+ {
+ SCROW nStart = pRowRange->aStart.Row();
+ SCROW nEnd = pRowRange->aEnd.Row();
+ if( (0 <= nStart) && (nStart <= nEnd) && (nEnd <= MAXROW) )
+ xAccessibleTable.set( new ScAccessibleSpreadsheet( *this, ScRange( 0, nStart, mnTab, MAXCOL, nEnd, mnTab ) ) );
+ }
+ }
+ return xAccessibleTable;
+}
+
+uno::Reference< XAccessibleTable > SAL_CALL ScAccessibleSpreadsheet::getAccessibleColumnHeaders( )
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ uno::Reference< XAccessibleTable > xAccessibleTable;
+ if( mpDoc && mbIsSpreadsheet )
+ {
+ if( const ScRange* pColRange = mpDoc->GetRepeatColRange( mnTab ) )
+ {
+ SCCOL nStart = pColRange->aStart.Col();
+ SCCOL nEnd = pColRange->aEnd.Col();
+ if( (0 <= nStart) && (nStart <= nEnd) && (nEnd <= MAXCOL) )
+ xAccessibleTable.set( new ScAccessibleSpreadsheet( *this, ScRange( nStart, 0, mnTab, nEnd, MAXROW, mnTab ) ) );
+ }
+ }
+ return xAccessibleTable;
+}
+
+uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleSpreadsheet::getSelectedAccessibleRows( )
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ uno::Sequence<sal_Int32> aSequence;
+ if (mpViewShell && mpViewShell->GetViewData())
+ {
+ aSequence.realloc(maRange.aEnd.Row() - maRange.aStart.Row() + 1);
+ const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
+ sal_Int32* pSequence = aSequence.getArray();
+ sal_Int32 nCount(0);
+ for (SCROW i = maRange.aStart.Row(); i <= maRange.aEnd.Row(); ++i)
+ {
+ if (rMarkdata.IsRowMarked(i))
+ {
+ pSequence[nCount] = i;
+ ++nCount;
+ }
+ }
+ aSequence.realloc(nCount);
+ }
+ else
+ aSequence.realloc(0);
+ return aSequence;
+}
+
+uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleSpreadsheet::getSelectedAccessibleColumns( )
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ uno::Sequence<sal_Int32> aSequence;
+ if (mpViewShell && mpViewShell->GetViewData())
+ {
+ aSequence.realloc(maRange.aEnd.Col() - maRange.aStart.Col() + 1);
+ const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
+ sal_Int32* pSequence = aSequence.getArray();
+ sal_Int32 nCount(0);
+ for (SCCOL i = maRange.aStart.Col(); i <= maRange.aEnd.Col(); ++i)
+ {
+ if (rMarkdata.IsColumnMarked(i))
+ {
+ pSequence[nCount] = i;
+ ++nCount;
+ }
+ }
+ aSequence.realloc(nCount);
+ }
+ else
+ aSequence.realloc(0);
+ return aSequence;
+}
+
+sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleRowSelected( sal_Int32 nRow )
+ throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+
+ if ((nRow > (maRange.aEnd.Row() - maRange.aStart.Row())) || (nRow < 0))
+ throw lang::IndexOutOfBoundsException();
+
+ sal_Bool bResult(sal_False);
+ if (mpViewShell && mpViewShell->GetViewData())
+ {
+ const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
+ bResult = rMarkdata.IsRowMarked((SCROW)nRow);
+ }
+ return bResult;
+}
+
+sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleColumnSelected( sal_Int32 nColumn )
+ throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+
+ if ((nColumn > (maRange.aEnd.Col() - maRange.aStart.Col())) || (nColumn < 0))
+ throw lang::IndexOutOfBoundsException();
+
+ sal_Bool bResult(sal_False);
+ if (mpViewShell && mpViewShell->GetViewData())
+ {
+ const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
+ bResult = rMarkdata.IsColumnMarked((SCCOL)nColumn);
+ }
+ return bResult;
+}
+
+ScAccessibleCell* ScAccessibleSpreadsheet::GetAccessibleCellAt(sal_Int32 nRow, sal_Int32 nColumn)
+{
+ ScAccessibleCell* pAccessibleCell = NULL;
+ ScAddress aCellAddress(static_cast<SCCOL>(maRange.aStart.Col() + nColumn),
+ static_cast<SCROW>(maRange.aStart.Row() + nRow), maRange.aStart.Tab());
+ if ((aCellAddress == maActiveCell) && mpAccCell)
+ {
+ pAccessibleCell = mpAccCell;
+ }
+ else
+ pAccessibleCell = new ScAccessibleCell(this, mpViewShell, aCellAddress, getAccessibleIndex(nRow, nColumn), meSplitPos, mpAccDoc);
+
+ return pAccessibleCell;
+}
+
+uno::Reference< XAccessible > SAL_CALL ScAccessibleSpreadsheet::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn )
+ throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ if (nRow > (maRange.aEnd.Row() - maRange.aStart.Row()) ||
+ nRow < 0 ||
+ nColumn > (maRange.aEnd.Col() - maRange.aStart.Col()) ||
+ nColumn < 0)
+ throw lang::IndexOutOfBoundsException();
+
+ uno::Reference<XAccessible> xAccessible;
+ ScAccessibleCell* pAccessibleCell = GetAccessibleCellAt(nRow, nColumn);
+ xAccessible = pAccessibleCell;
+ pAccessibleCell->Init();
+ return xAccessible;
+}
+
+sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn )
+ throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+
+ if ((nColumn > (maRange.aEnd.Col() - maRange.aStart.Col())) || (nColumn < 0) ||
+ (nRow > (maRange.aEnd.Row() - maRange.aStart.Row())) || (nRow < 0))
+ throw lang::IndexOutOfBoundsException();
+
+ sal_Bool bResult(sal_False);
+ if (mpViewShell)
+ {
+ const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData();
+ bResult = rMarkdata.IsCellMarked(static_cast<SCCOL>(nColumn), static_cast<SCROW>(nRow));
+ }
+ return bResult;
+}
+
+ //===== XAccessibleComponent ============================================
+
+uno::Reference< XAccessible > SAL_CALL ScAccessibleSpreadsheet::getAccessibleAtPoint(
+ const awt::Point& rPoint )
+ throw (uno::RuntimeException)
+{
+ uno::Reference< XAccessible > xAccessible;
+ if (containsPoint(rPoint))
+ {
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ if (mpViewShell)
+ {
+ SCsCOL nX;
+ SCsROW nY;
+ mpViewShell->GetViewData()->GetPosFromPixel( rPoint.X, rPoint.Y, meSplitPos, nX, nY);
+ xAccessible = getAccessibleCellAt(nY, nX);
+ }
+ }
+ return xAccessible;
+}
+
+void SAL_CALL ScAccessibleSpreadsheet::grabFocus( )
+ throw (uno::RuntimeException)
+{
+ if (getAccessibleParent().is())
+ {
+ uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
+ if (xAccessibleComponent.is())
+ xAccessibleComponent->grabFocus();
+ }
+}
+
+sal_Int32 SAL_CALL ScAccessibleSpreadsheet::getForeground( )
+ throw (uno::RuntimeException)
+{
+ return COL_BLACK;
+}
+
+sal_Int32 SAL_CALL ScAccessibleSpreadsheet::getBackground( )
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor;
+}
+
+ //===== XAccessibleContext ==============================================
+
+uno::Reference<XAccessibleRelationSet> SAL_CALL ScAccessibleSpreadsheet::getAccessibleRelationSet(void)
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ utl::AccessibleRelationSetHelper* pRelationSet = NULL;
+ if(mpAccDoc)
+ pRelationSet = mpAccDoc->GetRelationSet(NULL);
+ if (!pRelationSet)
+ pRelationSet = new utl::AccessibleRelationSetHelper();
+ return pRelationSet;
+}
+
+uno::Reference<XAccessibleStateSet> SAL_CALL
+ ScAccessibleSpreadsheet::getAccessibleStateSet(void)
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ uno::Reference<XAccessibleStateSet> xParentStates;
+ if (getAccessibleParent().is())
+ {
+ uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
+ xParentStates = xParentContext->getAccessibleStateSet();
+ }
+ utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
+ if (IsDefunc(xParentStates))
+ pStateSet->AddState(AccessibleStateType::DEFUNC);
+ else
+ {
+ pStateSet->AddState(AccessibleStateType::MANAGES_DESCENDANTS);
+ if (IsEditable(xParentStates))
+ pStateSet->AddState(AccessibleStateType::EDITABLE);
+ pStateSet->AddState(AccessibleStateType::ENABLED);
+ pStateSet->AddState(AccessibleStateType::FOCUSABLE);
+ if (IsFocused())
+ pStateSet->AddState(AccessibleStateType::FOCUSED);
+ pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
+ pStateSet->AddState(AccessibleStateType::OPAQUE);
+ pStateSet->AddState(AccessibleStateType::SELECTABLE);
+ if (IsCompleteSheetSelected())
+ pStateSet->AddState(AccessibleStateType::SELECTED);
+ if (isShowing())
+ pStateSet->AddState(AccessibleStateType::SHOWING);
+ if (isVisible())
+ pStateSet->AddState(AccessibleStateType::VISIBLE);
+ }
+ return pStateSet;
+}
+
+ ///===== XAccessibleSelection ===========================================
+
+void SAL_CALL
+ ScAccessibleSpreadsheet::selectAccessibleChild( sal_Int32 nChildIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
+ throw lang::IndexOutOfBoundsException();
+
+ if (mpViewShell)
+ {
+ sal_Int32 nCol(getAccessibleColumn(nChildIndex));
+ sal_Int32 nRow(getAccessibleRow(nChildIndex));
+
+ SelectCell(nRow, nCol, sal_False);
+ }
+}
+
+void SAL_CALL
+ ScAccessibleSpreadsheet::clearAccessibleSelection( )
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ if (mpViewShell)
+ {
+ mpViewShell->Unmark();
+ }
+}
+
+void SAL_CALL
+ ScAccessibleSpreadsheet::selectAllAccessibleChildren( )
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ if (mpViewShell)
+ {
+ mpViewShell->SelectAll();
+ }
+}
+
+sal_Int32 SAL_CALL
+ ScAccessibleSpreadsheet::getSelectedAccessibleChildCount( )
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ sal_Int32 nResult(0);
+ if (mpViewShell)
+ {
+ if (!mpMarkedRanges)
+ {
+ mpMarkedRanges = new ScRangeList();
+ ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData());
+ aMarkData.MarkToMulti();
+ aMarkData.FillRangeListWithMarks(mpMarkedRanges, sal_False);
+ }
+ // is possible, because there shouldn't be overlapped ranges in it
+ if (mpMarkedRanges)
+ nResult = mpMarkedRanges->GetCellCount();
+ }
+ return nResult;
+}
+
+uno::Reference<XAccessible > SAL_CALL
+ ScAccessibleSpreadsheet::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ uno::Reference < XAccessible > xAccessible;
+ if (mpViewShell)
+ {
+ if (!mpMarkedRanges)
+ {
+ mpMarkedRanges = new ScRangeList();
+ mpViewShell->GetViewData()->GetMarkData().FillRangeListWithMarks(mpMarkedRanges, sal_False);
+ }
+ if (mpMarkedRanges)
+ {
+ if (!mpSortedMarkedCells)
+ CreateSortedMarkedCells();
+ if (mpSortedMarkedCells)
+ {
+ if ((nSelectedChildIndex < 0) ||
+ (mpSortedMarkedCells->size() <= static_cast<sal_uInt32>(nSelectedChildIndex)))
+ throw lang::IndexOutOfBoundsException();
+ else
+ xAccessible = getAccessibleCellAt((*mpSortedMarkedCells)[nSelectedChildIndex].Row(), (*mpSortedMarkedCells)[nSelectedChildIndex].Col());
+ }
+ }
+ }
+ return xAccessible;
+}
+
+void SAL_CALL
+ ScAccessibleSpreadsheet::deselectAccessibleChild( sal_Int32 nChildIndex )
+ throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+
+ if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount())
+ throw lang::IndexOutOfBoundsException();
+
+ if (mpViewShell)
+ {
+ sal_Int32 nCol(getAccessibleColumn(nChildIndex));
+ sal_Int32 nRow(getAccessibleRow(nChildIndex));
+
+ if (mpViewShell->GetViewData()->GetMarkData().IsCellMarked(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow)))
+ SelectCell(nRow, nCol, sal_True);
+ }
+}
+
+void ScAccessibleSpreadsheet::SelectCell(sal_Int32 nRow, sal_Int32 nCol, sal_Bool bDeselect)
+{
+ mpViewShell->SetTabNo( maRange.aStart.Tab() );
+
+ mpViewShell->DoneBlockMode( sal_True ); // continue selecting
+ mpViewShell->InitBlockMode( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), maRange.aStart.Tab(), bDeselect, sal_False, sal_False );
+
+ mpViewShell->SelectionChanged();
+}
+
+void ScAccessibleSpreadsheet::CreateSortedMarkedCells()
+{
+ mpSortedMarkedCells = new std::vector<ScMyAddress>();
+ mpSortedMarkedCells->reserve(mpMarkedRanges->GetCellCount());
+ ScRange* pRange = mpMarkedRanges->First();
+ while (pRange)
+ {
+ if (pRange->aStart.Tab() != pRange->aEnd.Tab())
+ {
+ if ((maActiveCell.Tab() >= pRange->aStart.Tab()) ||
+ maActiveCell.Tab() <= pRange->aEnd.Tab())
+ {
+ ScRange aRange(*pRange);
+ aRange.aStart.SetTab(maActiveCell.Tab());
+ aRange.aEnd.SetTab(maActiveCell.Tab());
+ AddMarkedRange(aRange);
+ }
+ else
+ {
+ DBG_ERROR("Range of wrong table");
+ }
+ }
+ else if(pRange->aStart.Tab() == maActiveCell.Tab())
+ AddMarkedRange(*pRange);
+ else
+ {
+ DBG_ERROR("Range of wrong table");
+ }
+ pRange = mpMarkedRanges->Next();
+ }
+ std::sort(mpSortedMarkedCells->begin(), mpSortedMarkedCells->end());
+}
+
+void ScAccessibleSpreadsheet::AddMarkedRange(const ScRange& rRange)
+{
+ for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
+ {
+ for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
+ {
+ ScMyAddress aCell(nCol, nRow, maActiveCell.Tab());
+ mpSortedMarkedCells->push_back(aCell);
+ }
+ }
+}
+
+ //===== XServiceInfo ====================================================
+
+::rtl::OUString SAL_CALL ScAccessibleSpreadsheet::getImplementationName(void)
+ throw (uno::RuntimeException)
+{
+ return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleSpreadsheet"));
+}
+
+uno::Sequence< ::rtl::OUString> SAL_CALL
+ ScAccessibleSpreadsheet::getSupportedServiceNames (void)
+ throw (uno::RuntimeException)
+{
+ uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleTableBase::getSupportedServiceNames();
+ sal_Int32 nOldSize(aSequence.getLength());
+ aSequence.realloc(nOldSize + 1);
+ ::rtl::OUString* pNames = aSequence.getArray();
+
+ pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.AccessibleSpreadsheet"));
+
+ return aSequence;
+}
+
+//===== XTypeProvider =======================================================
+
+uno::Sequence<sal_Int8> SAL_CALL
+ ScAccessibleSpreadsheet::getImplementationId(void)
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ static uno::Sequence<sal_Int8> aId;
+ if (aId.getLength() == 0)
+ {
+ aId.realloc (16);
+ rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
+ }
+ return aId;
+}
+
+///===== XAccessibleEventBroadcaster =====================================
+
+void SAL_CALL ScAccessibleSpreadsheet::addEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
+ throw (uno::RuntimeException)
+{
+ ScUnoGuard aGuard;
+ IsObjectValid();
+ ScAccessibleTableBase::addEventListener(xListener);
+
+ if (!mbIsFocusSend)
+ {
+ mbIsFocusSend = sal_True;
+ CommitFocusGained();
+
+ AccessibleEventObject aEvent;
+ aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED;
+ aEvent.Source = uno::Reference< XAccessibleContext >(this);
+ aEvent.NewValue <<= getAccessibleCellAt(maActiveCell.Row(), maActiveCell.Col());
+
+ CommitChange(aEvent);
+ }
+}
+
+ //==== internal =========================================================
+
+Rectangle ScAccessibleSpreadsheet::GetBoundingBoxOnScreen() const
+ throw (uno::RuntimeException)
+{
+ Rectangle aRect;
+ if (mpViewShell)
+ {
+ Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
+ if (pWindow)
+ aRect = pWindow->GetWindowExtentsRelative(NULL);
+ }
+ return aRect;
+}
+
+Rectangle ScAccessibleSpreadsheet::GetBoundingBox() const
+ throw (uno::RuntimeException)
+{
+ Rectangle aRect;
+ if (mpViewShell)
+ {
+ Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
+ if (pWindow)
+ //#101986#; extends to the same window, because the parent is the document and it has the same window
+ aRect = pWindow->GetWindowExtentsRelative(pWindow);
+ }
+ return aRect;
+}
+
+sal_Bool ScAccessibleSpreadsheet::IsDefunc(
+ const uno::Reference<XAccessibleStateSet>& rxParentStates)
+{
+ return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() ||
+ (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
+}
+
+sal_Bool ScAccessibleSpreadsheet::IsEditable(
+ const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
+{
+ sal_Bool bProtected(sal_False);
+ if (mpDoc && mpDoc->IsTabProtected(maRange.aStart.Tab()))
+ bProtected = sal_True;
+ return !bProtected;
+}
+
+sal_Bool ScAccessibleSpreadsheet::IsFocused()
+{
+ sal_Bool bFocused(sal_False);
+ if (mpViewShell)
+ {
+ if (mpViewShell->GetViewData()->GetActivePart() == meSplitPos)
+ bFocused = mpViewShell->GetActiveWin()->HasFocus();
+ }
+ return bFocused;
+}
+
+sal_Bool ScAccessibleSpreadsheet::IsCompleteSheetSelected()
+{
+ sal_Bool bResult(sal_False);
+ if(mpViewShell)
+ {
+ //#103800#; use a copy of MarkData
+ ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData());
+ aMarkData.MarkToMulti();
+ if (aMarkData.IsAllMarked(maRange))
+ bResult = sal_True;
+ }
+ return bResult;
+}
+
+ScDocument* ScAccessibleSpreadsheet::GetDocument(ScTabViewShell* pViewShell)
+{
+ ScDocument* pDoc = NULL;
+ if (pViewShell)
+ pDoc = pViewShell->GetViewData()->GetDocument();
+ return pDoc;
+}
+
+Rectangle ScAccessibleSpreadsheet::GetVisArea(ScTabViewShell* pViewShell, ScSplitPos eSplitPos)
+{
+ Rectangle aVisArea;
+ if (pViewShell)
+ {
+ Window* pWindow = pViewShell->GetWindowByPos(eSplitPos);
+ if (pWindow)
+ {
+ aVisArea.SetPos(pViewShell->GetViewData()->GetPixPos(eSplitPos));
+ aVisArea.SetSize(pWindow->GetSizePixel());
+ }
+ }
+ return aVisArea;
+}
+
+Rectangle ScAccessibleSpreadsheet::GetVisCells(const Rectangle& rVisArea)
+{
+ if (mpViewShell)
+ {
+ SCsCOL nStartX, nEndX;
+ SCsROW nStartY, nEndY;
+
+ mpViewShell->GetViewData()->GetPosFromPixel( 1, 1, meSplitPos, nStartX, nStartY);
+ mpViewShell->GetViewData()->GetPosFromPixel( rVisArea.GetWidth(), rVisArea.GetHeight(), meSplitPos, nEndX, nEndY);
+
+ return Rectangle(nStartX, nStartY, nEndX, nEndY);
+ }
+ else
+ return Rectangle();
+}