diff options
Diffstat (limited to 'sc/source/ui/Accessibility/AccessibleDocument.cxx')
-rw-r--r-- | sc/source/ui/Accessibility/AccessibleDocument.cxx | 2120 |
1 files changed, 2120 insertions, 0 deletions
diff --git a/sc/source/ui/Accessibility/AccessibleDocument.cxx b/sc/source/ui/Accessibility/AccessibleDocument.cxx new file mode 100644 index 000000000000..4c65632fb45e --- /dev/null +++ b/sc/source/ui/Accessibility/AccessibleDocument.cxx @@ -0,0 +1,2120 @@ +/************************************************************************* + * + * 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 "AccessibleDocument.hxx" +#include "AccessibleSpreadsheet.hxx" +#include "tabvwsh.hxx" +#include "AccessibilityHints.hxx" +#include "document.hxx" +#include "drwlayer.hxx" +#include "unoguard.hxx" +#include "shapeuno.hxx" +#include "DrawModelBroadcaster.hxx" +#include "drawview.hxx" +#include "gridwin.hxx" +#include "AccessibleEditObject.hxx" +#include "scresid.hxx" +#ifndef SC_SC_HRC +#include "sc.hrc" +#endif +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_ +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#endif +#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLERELATIONTYPE_HPP_ +#include <com/sun/star/accessibility/AccessibleRelationType.hpp> +#endif +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/drawing/XShapes.hpp> + +#ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX +#include <unotools/accessiblestatesethelper.hxx> +#endif +#include <tools/debug.hxx> +#include <tools/gen.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdobj.hxx> +#include <svx/ShapeTypeHandler.hxx> +#include <svx/AccessibleShape.hxx> +#include <svx/AccessibleShapeTreeInfo.hxx> +#include <svx/AccessibleShapeInfo.hxx> +#include <comphelper/sequence.hxx> +#include <sfx2/viewfrm.hxx> +#include <svx/unoshcol.hxx> +#include <svx/unoshape.hxx> +#include <unotools/accessiblerelationsethelper.hxx> +#include <toolkit/helper/convert.hxx> + +#include <list> +#include <algorithm> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; +using ::std::for_each; + + //===== internal ======================================================== + +struct ScAccessibleShapeData +{ + ScAccessibleShapeData() : pAccShape(NULL), pRelationCell(NULL), bSelected(sal_False), bSelectable(sal_True) {} + ~ScAccessibleShapeData(); + mutable ::accessibility::AccessibleShape* pAccShape; + mutable ScAddress* pRelationCell; // if it is NULL this shape is anchored on the table +// SdrObject* pShape; + com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape; + mutable sal_Bool bSelected; + sal_Bool bSelectable; +}; + +ScAccessibleShapeData::~ScAccessibleShapeData() +{ + if (pAccShape) + { + pAccShape->dispose(); + pAccShape->release(); + } +} + +struct ScShapeDataLess +{ + rtl::OUString msLayerId; + rtl::OUString msZOrder; + ScShapeDataLess() + : msLayerId(RTL_CONSTASCII_USTRINGPARAM( "LayerID" )), + msZOrder(RTL_CONSTASCII_USTRINGPARAM( "ZOrder" )) + { + } + void ConvertLayerId(sal_Int16& rLayerID) const // changes the number of the LayerId so it the accessibility order + { + switch (rLayerID) + { + case SC_LAYER_FRONT: + rLayerID = 1; + break; + case SC_LAYER_BACK: + rLayerID = 0; + break; + case SC_LAYER_INTERN: + rLayerID = 2; + break; + case SC_LAYER_CONTROLS: + rLayerID = 3; + break; + } + } + sal_Bool LessThanSheet(const ScAccessibleShapeData* pData) const + { + sal_Bool bResult(sal_False); + uno::Reference< beans::XPropertySet> xProps(pData->xShape, uno::UNO_QUERY); + if (xProps.is()) + { + uno::Any aPropAny = xProps->getPropertyValue(msLayerId); + sal_Int16 nLayerID = 0; + if( (aPropAny >>= nLayerID) ) + { + if (nLayerID == SC_LAYER_BACK) + bResult = sal_True; + } + } + return bResult; + } + sal_Bool operator()(const ScAccessibleShapeData* pData1, const ScAccessibleShapeData* pData2) const + { + sal_Bool bResult(sal_False); + if (pData1 && pData2) + { + uno::Reference< beans::XPropertySet> xProps1(pData1->xShape, uno::UNO_QUERY); + uno::Reference< beans::XPropertySet> xProps2(pData2->xShape, uno::UNO_QUERY); + if (xProps1.is() && xProps2.is()) + { + uno::Any aPropAny1 = xProps1->getPropertyValue(msLayerId); + uno::Any aPropAny2 = xProps2->getPropertyValue(msLayerId); + sal_Int16 nLayerID1(0); + sal_Int16 nLayerID2(0); + if( (aPropAny1 >>= nLayerID1) && (aPropAny2 >>= nLayerID2) ) + { + if (nLayerID1 == nLayerID2) + { + uno::Any aAny1 = xProps1->getPropertyValue(msZOrder); + sal_Int32 nZOrder1 = 0; + uno::Any aAny2 = xProps2->getPropertyValue(msZOrder); + sal_Int32 nZOrder2 = 0; + if ( (aAny1 >>= nZOrder1) && (aAny2 >>= nZOrder2) ) + bResult = (nZOrder1 < nZOrder2); + } + else + { + ConvertLayerId(nLayerID1); + ConvertLayerId(nLayerID2); + bResult = (nLayerID1 < nLayerID2); + } + } + } + } + else if (pData1 && !pData2) + bResult = LessThanSheet(pData1); + else if (!pData1 && pData2) + bResult = !LessThanSheet(pData2); + else + bResult = sal_False; + return bResult; + } +}; + +struct DeselectShape +{ + void operator() (const ScAccessibleShapeData* pAccShapeData) const + { + if (pAccShapeData) + { + pAccShapeData->bSelected = sal_False; + if (pAccShapeData->pAccShape) + pAccShapeData->pAccShape->ResetState(AccessibleStateType::SELECTED); + } + } +}; + +struct SelectShape +{ + uno::Reference < drawing::XShapes > xShapes; + SelectShape(uno::Reference<drawing::XShapes>& xTemp) : xShapes(xTemp) {} + void operator() (const ScAccessibleShapeData* pAccShapeData) const + { + if (pAccShapeData && pAccShapeData->bSelectable) + { + pAccShapeData->bSelected = sal_True; + if (pAccShapeData->pAccShape) + pAccShapeData->pAccShape->SetState(AccessibleStateType::SELECTED); + if (xShapes.is()) + xShapes->add(pAccShapeData->xShape); + } + } +}; + +struct Destroy +{ + void operator() (ScAccessibleShapeData* pData) + { + if (pData) + DELETEZ(pData); + } +}; + +class ScChildrenShapes : public SfxListener, + public ::accessibility::IAccessibleParent +{ +public: + ScChildrenShapes(ScAccessibleDocument* pAccessibleDocument, ScTabViewShell* pViewShell, ScSplitPos eSplitPos); + ~ScChildrenShapes(); + + ///===== SfxListener ===================================================== + + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); + + ///===== IAccessibleParent =============================================== + + virtual sal_Bool ReplaceChild ( + ::accessibility::AccessibleShape* pCurrentChild, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape, + const long _nIndex, + const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo + ) throw (::com::sun::star::uno::RuntimeException); + + ///===== Internal ======================================================== + void SetDrawBroadcaster(); + + sal_Int32 GetCount() const; + uno::Reference< XAccessible > Get(const ScAccessibleShapeData* pData) const; + uno::Reference< XAccessible > Get(sal_Int32 nIndex) const; + uno::Reference< XAccessible > GetAt(const awt::Point& rPoint) const; + + // gets the index of the shape starting on 0 (without the index of the table) + // returns the selected shape + sal_Bool IsSelected(sal_Int32 nIndex, + com::sun::star::uno::Reference<com::sun::star::drawing::XShape>& rShape) const; + + sal_Bool SelectionChanged(); + + void Select(sal_Int32 nIndex); + void DeselectAll(); // deselect also the table + void SelectAll(); + sal_Int32 GetSelectedCount() const; + uno::Reference< XAccessible > GetSelected(sal_Int32 nSelectedChildIndex, sal_Bool bTabSelected) const; + void Deselect(sal_Int32 nChildIndex); + + SdrPage* GetDrawPage() const; + + utl::AccessibleRelationSetHelper* GetRelationSet(const ScAddress* pAddress) const; + + void VisAreaChanged() const; +private: + typedef std::vector<ScAccessibleShapeData*> SortedShapes; + + mutable SortedShapes maZOrderedShapes; // a null pointer represents the sheet in the correct order + + mutable ::accessibility::AccessibleShapeTreeInfo maShapeTreeInfo; + mutable com::sun::star::uno::Reference<com::sun::star::view::XSelectionSupplier> xSelectionSupplier; + mutable sal_uInt32 mnSdrObjCount; + mutable sal_uInt32 mnShapesSelected; + ScTabViewShell* mpViewShell; + ScAccessibleDocument* mpAccessibleDocument; + ScSplitPos meSplitPos; + + void FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const; + sal_Bool FindSelectedShapesChanges(const com::sun::star::uno::Reference<com::sun::star::drawing::XShapes>& xShapes, sal_Bool bCommitChange) const; + void FillSelectionSupplier() const; + + ScAddress* GetAnchor(const uno::Reference<drawing::XShape>& xShape) const; + uno::Reference<XAccessibleRelationSet> GetRelationSet(const ScAccessibleShapeData* pData) const; + void CheckWhetherAnchorChanged(const uno::Reference<drawing::XShape>& xShape) const; + void SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const; + void AddShape(const uno::Reference<drawing::XShape>& xShape, sal_Bool bCommitChange) const; + void RemoveShape(const uno::Reference<drawing::XShape>& xShape) const; + + sal_Bool FindShape(const uno::Reference<drawing::XShape>& xShape, SortedShapes::iterator& rItr) const; + + sal_Int8 Compare(const ScAccessibleShapeData* pData1, + const ScAccessibleShapeData* pData2) const; +}; + +ScChildrenShapes::ScChildrenShapes(ScAccessibleDocument* pAccessibleDocument, ScTabViewShell* pViewShell, ScSplitPos eSplitPos) + : + mnShapesSelected(0), + mpViewShell(pViewShell), + mpAccessibleDocument(pAccessibleDocument), + meSplitPos(eSplitPos) +{ + FillSelectionSupplier(); + maZOrderedShapes.push_back(NULL); // add an element which represents the table + + GetCount(); // fill list with filtered shapes (no internal shapes) + + if (mnShapesSelected) + { + //set flag on every selected shape + if (!xSelectionSupplier.is()) + throw uno::RuntimeException(); + + uno::Reference<drawing::XShapes> xShapes(xSelectionSupplier->getSelection(), uno::UNO_QUERY); + if (xShapes.is()) + FindSelectedShapesChanges(xShapes, sal_False); + } + if (pViewShell) + { + SfxBroadcaster* pDrawBC = pViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster(); + if (pDrawBC) + { + StartListening(*pDrawBC); + + maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(pViewShell->GetViewData()->GetDocument()->GetDrawLayer()) ); + maShapeTreeInfo.SetSdrView(pViewShell->GetViewData()->GetScDrawView()); + maShapeTreeInfo.SetController(NULL); + maShapeTreeInfo.SetWindow(pViewShell->GetWindowByPos(meSplitPos)); + maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument); + } + } +} + +ScChildrenShapes::~ScChildrenShapes() +{ + std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), Destroy()); + if (mpViewShell) + { + SfxBroadcaster* pDrawBC = mpViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster(); + if (pDrawBC) + EndListening(*pDrawBC); + } +} + +void ScChildrenShapes::SetDrawBroadcaster() +{ + if (mpViewShell) + { + SfxBroadcaster* pDrawBC = mpViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster(); + if (pDrawBC) + { + StartListening(*pDrawBC, TRUE); + + maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(mpViewShell->GetViewData()->GetDocument()->GetDrawLayer()) ); + maShapeTreeInfo.SetSdrView(mpViewShell->GetViewData()->GetScDrawView()); + maShapeTreeInfo.SetController(NULL); + maShapeTreeInfo.SetWindow(mpViewShell->GetWindowByPos(meSplitPos)); + maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument); + } + } +} + +void ScChildrenShapes::Notify(SfxBroadcaster&, const SfxHint& rHint) +{ + if ( rHint.ISA( SdrHint ) ) + { + const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint ); + if (pSdrHint) + { + SdrObject* pObj = const_cast<SdrObject*>(pSdrHint->GetObject()); + if (pObj && /*(pObj->GetLayer() != SC_LAYER_INTERN) && */(pObj->GetPage() == GetDrawPage()) && + (pObj->GetPage() == pObj->GetObjList()) ) //#108480# only do something if the object lies direct on the page + { + switch (pSdrHint->GetKind()) + { + case HINT_OBJCHG : // Objekt geaendert + { + uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY); + if (xShape.is()) + { + ScShapeDataLess aLess; + std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), aLess); // sort, because the z index or layer could be changed + CheckWhetherAnchorChanged(xShape); + } + } + break; + case HINT_OBJINSERTED : // Neues Zeichenobjekt eingefuegt + { + uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY); + if (xShape.is()) + AddShape(xShape, sal_True); + } + break; + case HINT_OBJREMOVED : // Zeichenobjekt aus Liste entfernt + { + uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY); + if (xShape.is()) + RemoveShape(xShape); + } + break; + default : + { + // other events are not interesting + } + break; + } + } + } + } +} + +sal_Bool ScChildrenShapes::ReplaceChild (::accessibility::AccessibleShape* pCurrentChild, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape, + const long _nIndex, const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo) + throw (uno::RuntimeException) +{ + // create the new child + ::accessibility::AccessibleShape* pReplacement = ::accessibility::ShapeTypeHandler::Instance().CreateAccessibleObject ( + ::accessibility::AccessibleShapeInfo ( _rxShape, pCurrentChild->getAccessibleParent(), this, _nIndex ), + _rShapeTreeInfo + ); + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xNewChild( pReplacement ); // keep this alive (do this before calling Init!) + if ( pReplacement ) + pReplacement->Init(); + + sal_Bool bResult(sal_False); + if (pCurrentChild && pReplacement) + { + DBG_ASSERT(pCurrentChild->GetXShape().get() == pReplacement->GetXShape().get(), "XShape changes and should be inserted sorted"); + SortedShapes::iterator aItr; + FindShape(pCurrentChild->GetXShape(), aItr); + if (aItr != maZOrderedShapes.end() && (*aItr)) + { + if ((*aItr)->pAccShape) + { + DBG_ASSERT((*aItr)->pAccShape == pCurrentChild, "wrong child found"); + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::CHILD; + aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument); + aEvent.OldValue <<= uno::makeAny(uno::Reference<XAccessible>(pCurrentChild)); + + mpAccessibleDocument->CommitChange(aEvent); // child is gone - event + + pCurrentChild->dispose(); + } + (*aItr)->pAccShape = pReplacement; + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::CHILD; + aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument); + aEvent.NewValue <<= uno::makeAny(uno::Reference<XAccessible>(pReplacement)); + + mpAccessibleDocument->CommitChange(aEvent); // child is new - event + bResult = sal_True; + } + } + return bResult; +} + +sal_Int32 ScChildrenShapes::GetCount() const +{ + SdrPage* pDrawPage = GetDrawPage(); + if (pDrawPage && (maZOrderedShapes.size() == 1)) // the table is always in + { + mnSdrObjCount = pDrawPage->GetObjCount(); + maZOrderedShapes.reserve(mnSdrObjCount + 1); // the table is always in + for (sal_uInt32 i = 0; i < mnSdrObjCount; ++i) + { + SdrObject* pObj = pDrawPage->GetObj(i); + if (pObj/* && (pObj->GetLayer() != SC_LAYER_INTERN)*/) + { + uno::Reference< drawing::XShape > xShape (pObj->getUnoShape(), uno::UNO_QUERY); + AddShape(xShape, sal_False); //inserts in the correct order + } + } + } + return maZOrderedShapes.size(); +} + +uno::Reference< XAccessible > ScChildrenShapes::Get(const ScAccessibleShapeData* pData) const +{ + if (!pData) + return NULL; + + if (!pData->pAccShape) + { + ::accessibility::ShapeTypeHandler& rShapeHandler = ::accessibility::ShapeTypeHandler::Instance(); + ::accessibility::AccessibleShapeInfo aShapeInfo(pData->xShape, mpAccessibleDocument, const_cast<ScChildrenShapes*>(this)); + pData->pAccShape = rShapeHandler.CreateAccessibleObject( + aShapeInfo, maShapeTreeInfo); + if (pData->pAccShape) + { + pData->pAccShape->acquire(); + pData->pAccShape->Init(); + if (pData->bSelected) + pData->pAccShape->SetState(AccessibleStateType::SELECTED); + if (!pData->bSelectable) + pData->pAccShape->ResetState(AccessibleStateType::SELECTABLE); + pData->pAccShape->SetRelationSet(GetRelationSet(pData)); + } + } + return pData->pAccShape; + } + +uno::Reference< XAccessible > ScChildrenShapes::Get(sal_Int32 nIndex) const +{ + if (maZOrderedShapes.size() <= 1) + GetCount(); // fill list with filtered shapes (no internal shapes) + + if (static_cast<sal_uInt32>(nIndex) >= maZOrderedShapes.size()) + return NULL; + + return Get(maZOrderedShapes[nIndex]); +} + +uno::Reference< XAccessible > ScChildrenShapes::GetAt(const awt::Point& rPoint) const +{ + uno::Reference<XAccessible> xAccessible; + if(mpViewShell) + { + sal_Int32 i(maZOrderedShapes.size() - 1); + sal_Bool bFound(sal_False); + while (!bFound && i >= 0) + { + ScAccessibleShapeData* pShape = maZOrderedShapes[i]; + if (pShape) + { + if (!pShape->pAccShape) + Get(pShape); + + if (pShape->pAccShape) + { + Point aPoint(VCLPoint(rPoint)); + aPoint -= VCLRectangle(pShape->pAccShape->getBounds()).TopLeft(); + if (pShape->pAccShape->containsPoint(AWTPoint(aPoint))) + { + xAccessible = pShape->pAccShape; + bFound = sal_True; + } + } + else + { + DBG_ERRORFILE("I should have an accessible shape now!"); + } + } + else + bFound = sal_True; // this is the sheet and it lies before the rest of the shapes which are background shapes + + --i; + } + } + return xAccessible; +} + +sal_Bool ScChildrenShapes::IsSelected(sal_Int32 nIndex, + uno::Reference<drawing::XShape>& rShape) const +{ + sal_Bool bResult (sal_False); + if (maZOrderedShapes.size() <= 1) + GetCount(); // fill list with filtered shapes (no internal shapes) + + if (!xSelectionSupplier.is()) + throw uno::RuntimeException(); + + if (!maZOrderedShapes[nIndex]) + return sal_False; + + bResult = maZOrderedShapes[nIndex]->bSelected; + rShape = maZOrderedShapes[nIndex]->xShape; + +#ifdef DBG_UTIL // test whether it is truly selected by a slower method + uno::Reference< drawing::XShape > xReturnShape; + sal_Bool bDebugResult(sal_False); + uno::Reference<container::XIndexAccess> xIndexAccess; + xSelectionSupplier->getSelection() >>= xIndexAccess; + + if (xIndexAccess.is()) + { + sal_Int32 nCount(xIndexAccess->getCount()); + if (nCount) + { + uno::Reference< drawing::XShape > xShape; + uno::Reference< drawing::XShape > xIndexShape = maZOrderedShapes[nIndex]->xShape; + sal_Int32 i(0); + while (!bDebugResult && (i < nCount)) + { + xIndexAccess->getByIndex(i) >>= xShape; + if (xShape.is() && (xIndexShape.get() == xShape.get())) + { + bDebugResult = sal_True; + xReturnShape = xShape; + } + else + ++i; + } + } + } + DBG_ASSERT((bResult == bDebugResult) && ((bResult && (rShape.get() == xReturnShape.get())) || !bResult), "found the wrong shape or result"); +#endif + + return bResult; +} + +sal_Bool ScChildrenShapes::SelectionChanged() +{ + sal_Bool bResult(sal_False); + if (!xSelectionSupplier.is()) + throw uno::RuntimeException(); + + uno::Reference<drawing::XShapes> xShapes(xSelectionSupplier->getSelection(), uno::UNO_QUERY); + + bResult = FindSelectedShapesChanges(xShapes, sal_True); + + return bResult; +} + +void ScChildrenShapes::Select(sal_Int32 nIndex) +{ + if (maZOrderedShapes.size() <= 1) + GetCount(); // fill list with filtered shapes (no internal shapes) + + if (!xSelectionSupplier.is()) + throw uno::RuntimeException(); + + if (!maZOrderedShapes[nIndex]) + return; + + uno::Reference<drawing::XShape> xShape; + if (!IsSelected(nIndex, xShape) && maZOrderedShapes[nIndex]->bSelectable) + { + uno::Reference<drawing::XShapes> xShapes; + xSelectionSupplier->getSelection() >>= xShapes; + + if (!xShapes.is()) + xShapes = new SvxShapeCollection(); + + xShapes->add(maZOrderedShapes[nIndex]->xShape); + + try + { + xSelectionSupplier->select(uno::makeAny(xShapes)); + maZOrderedShapes[nIndex]->bSelected = sal_True; + if (maZOrderedShapes[nIndex]->pAccShape) + maZOrderedShapes[nIndex]->pAccShape->SetState(AccessibleStateType::SELECTED); + } + catch (lang::IllegalArgumentException&) + { + } + } +} + +void ScChildrenShapes::DeselectAll() +{ + if (!xSelectionSupplier.is()) + throw uno::RuntimeException(); + + sal_Bool bSomethingSelected(sal_True); + try + { + xSelectionSupplier->select(uno::Any()); //deselects all + } + catch (lang::IllegalArgumentException&) + { + DBG_ERRORFILE("nothing selected before"); + bSomethingSelected = sal_False; + } + + if (bSomethingSelected) + std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), DeselectShape()); +} + +void ScChildrenShapes::SelectAll() +{ + if (!xSelectionSupplier.is()) + throw uno::RuntimeException(); + + if (maZOrderedShapes.size() <= 1) + GetCount(); // fill list with filtered shapes (no internal shapes) + + if (maZOrderedShapes.size() > 1) + { + uno::Reference<drawing::XShapes> xShapes; + xShapes = new SvxShapeCollection(); + + try + { + std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), SelectShape(xShapes)); + xSelectionSupplier->select(uno::makeAny(xShapes)); + } + catch (lang::IllegalArgumentException&) + { + SelectionChanged(); // find all selected shapes and set the flags + } + } +} + +void ScChildrenShapes::FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const +{ + uno::Reference<container::XIndexAccess> xIndexAccess; + xSelectionSupplier->getSelection() >>= xIndexAccess; + + if (xIndexAccess.is()) + { + sal_uInt32 nCount(xIndexAccess->getCount()); + for (sal_uInt32 i = 0; i < nCount; ++i) + { + uno::Reference<drawing::XShape> xShape; + xIndexAccess->getByIndex(i) >>= xShape; + if (xShape.is()) + rShapes.push_back(xShape); + } + } +} + +sal_Int32 ScChildrenShapes::GetSelectedCount() const +{ + if (!xSelectionSupplier.is()) + throw uno::RuntimeException(); + + std::vector < uno::Reference < drawing::XShape > > aShapes; + FillShapes(aShapes); + + return aShapes.size(); +} + +uno::Reference< XAccessible > ScChildrenShapes::GetSelected(sal_Int32 nSelectedChildIndex, sal_Bool bTabSelected) const +{ + uno::Reference< XAccessible > xAccessible; + + if (maZOrderedShapes.size() <= 1) + GetCount(); // fill list with shapes + + if (!bTabSelected) + { + std::vector < uno::Reference < drawing::XShape > > aShapes; + FillShapes(aShapes); + + SortedShapes::iterator aItr; + if (FindShape(aShapes[nSelectedChildIndex], aItr)) + xAccessible = Get(aItr - maZOrderedShapes.begin()); + } + else + { + SortedShapes::iterator aItr = maZOrderedShapes.begin(); + SortedShapes::iterator aEndItr = maZOrderedShapes.end(); + sal_Bool bFound(sal_False); + while(!bFound && aItr != aEndItr) + { + if (*aItr) + { + if ((*aItr)->bSelected) + { + if (nSelectedChildIndex == 0) + bFound = sal_True; + else + --nSelectedChildIndex; + } + } + else + { + if (nSelectedChildIndex == 0) + bFound = sal_True; + else + --nSelectedChildIndex; + } + if (!bFound) + ++aItr; + } + if (bFound && *aItr) + xAccessible = (*aItr)->pAccShape; + } + + return xAccessible; +} + +void ScChildrenShapes::Deselect(sal_Int32 nChildIndex) +{ + uno::Reference<drawing::XShape> xShape; + if (IsSelected(nChildIndex, xShape)) // returns false if it is the sheet + { + if (xShape.is()) + { + uno::Reference<drawing::XShapes> xShapes; + xSelectionSupplier->getSelection() >>= xShapes; + if (xShapes.is()) + xShapes->remove(xShape); + + try + { + xSelectionSupplier->select(uno::makeAny(xShapes)); + } + catch (lang::IllegalArgumentException&) + { + DBG_ERRORFILE("something not selectable"); + } + + maZOrderedShapes[nChildIndex]->bSelected = sal_False; + if (maZOrderedShapes[nChildIndex]->pAccShape) + maZOrderedShapes[nChildIndex]->pAccShape->ResetState(AccessibleStateType::SELECTED); + } + } +} + + +SdrPage* ScChildrenShapes::GetDrawPage() const +{ + SCTAB nTab(mpAccessibleDocument->getVisibleTable()); + SdrPage* pDrawPage = NULL; + if (mpViewShell) + { + ScDocument* pDoc = mpViewShell->GetViewData()->GetDocument(); + if (pDoc && pDoc->GetDrawLayer()) + { + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab)) + pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(static_cast<sal_Int16>(nTab))); + } + } + return pDrawPage; +} + +struct SetRelation +{ + const ScChildrenShapes* mpChildrenShapes; + mutable utl::AccessibleRelationSetHelper* mpRelationSet; + const ScAddress* mpAddress; + SetRelation(const ScChildrenShapes* pChildrenShapes, const ScAddress* pAddress) + : + mpChildrenShapes(pChildrenShapes), + mpRelationSet(NULL), + mpAddress(pAddress) + { + } + void operator() (const ScAccessibleShapeData* pAccShapeData) const + { + if (pAccShapeData && + ((!pAccShapeData->pRelationCell && !mpAddress) || + (pAccShapeData->pRelationCell && mpAddress && (*(pAccShapeData->pRelationCell) == *mpAddress)))) + { + if (!mpRelationSet) + mpRelationSet = new utl::AccessibleRelationSetHelper(); + + AccessibleRelation aRelation; + aRelation.TargetSet.realloc(1); + aRelation.TargetSet[0] = mpChildrenShapes->Get(pAccShapeData); + aRelation.RelationType = AccessibleRelationType::CONTROLLER_FOR; + + mpRelationSet->AddRelation(aRelation); + } + } +}; + +utl::AccessibleRelationSetHelper* ScChildrenShapes::GetRelationSet(const ScAddress* pAddress) const +{ + SetRelation aSetRelation(this, pAddress); + ::std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), aSetRelation); + return aSetRelation.mpRelationSet; +} + +sal_Bool ScChildrenShapes::FindSelectedShapesChanges(const uno::Reference<drawing::XShapes>& xShapes, sal_Bool /* bCommitChange */) const +{ + sal_Bool bResult(sal_False); + SortedShapes aShapesList; + uno::Reference<container::XIndexAccess> xIndexAcc(xShapes, uno::UNO_QUERY); + if (xIndexAcc.is()) + { + mnShapesSelected = xIndexAcc->getCount(); + for (sal_uInt32 i = 0; i < mnShapesSelected; ++i) + { + uno::Reference< drawing::XShape > xShape; + xIndexAcc->getByIndex(i) >>= xShape; + if (xShape.is()) + { + ScAccessibleShapeData* pShapeData = new ScAccessibleShapeData(); + pShapeData->xShape = xShape; + aShapesList.push_back(pShapeData); + } + } + } + else + mnShapesSelected = 0; + ScShapeDataLess aLess; + std::sort(aShapesList.begin(), aShapesList.end(), aLess); + + SortedShapes::iterator aXShapesItr(aShapesList.begin()); + SortedShapes::const_iterator aXShapesEndItr(aShapesList.end()); + SortedShapes::iterator aDataItr(maZOrderedShapes.begin()); + SortedShapes::const_iterator aDataEndItr(maZOrderedShapes.end()); + SortedShapes::const_iterator aFocusedItr = aDataEndItr; + while((aDataItr != aDataEndItr)) + { + if (*aDataItr) // is it realy a shape or only the sheet + { + sal_Int8 nComp(0); + if (aXShapesItr == aXShapesEndItr) + nComp = -1; // simulate that the Shape is lower, so the selction state will be removed + else + nComp = Compare(*aDataItr, *aXShapesItr); + if (nComp == 0) + { + if (!(*aDataItr)->bSelected) + { + (*aDataItr)->bSelected = sal_True; + if ((*aDataItr)->pAccShape) + { + (*aDataItr)->pAccShape->SetState(AccessibleStateType::SELECTED); + (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED); + bResult = sal_True; + } + aFocusedItr = aDataItr; + } + ++aDataItr; + ++aXShapesItr; + } + else if (nComp < 0) + { + if ((*aDataItr)->bSelected) + { + (*aDataItr)->bSelected = sal_False; + if ((*aDataItr)->pAccShape) + { + (*aDataItr)->pAccShape->ResetState(AccessibleStateType::SELECTED); + (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED); + bResult = sal_True; + } + } + ++aDataItr; + } + else + { + DBG_ERRORFILE("here is a selected shape which is not in the childlist"); + ++aXShapesItr; + --mnShapesSelected; + } + } + else + ++aDataItr; + } + if ((aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape && (mnShapesSelected == 1)) + (*aFocusedItr)->pAccShape->SetState(AccessibleStateType::FOCUSED); + + std::for_each(aShapesList.begin(), aShapesList.end(), Destroy()); + + return bResult; +} + +void ScChildrenShapes::FillSelectionSupplier() const +{ + if (!xSelectionSupplier.is() && mpViewShell) + { + SfxViewFrame* pViewFrame = mpViewShell->GetViewFrame(); + if (pViewFrame) + { + xSelectionSupplier = uno::Reference<view::XSelectionSupplier>(pViewFrame->GetFrame().GetController(), uno::UNO_QUERY); + if (xSelectionSupplier.is()) + { + if (mpAccessibleDocument) + xSelectionSupplier->addSelectionChangeListener(mpAccessibleDocument); + uno::Reference<drawing::XShapes> xShapes (xSelectionSupplier->getSelection(), uno::UNO_QUERY); + if (xShapes.is()) + mnShapesSelected = xShapes->getCount(); + } + } + } +} + +ScAddress* ScChildrenShapes::GetAnchor(const uno::Reference<drawing::XShape>& xShape) const +{ + ScAddress* pAddress = NULL; + if (mpViewShell) + { + SvxShape* pShapeImp = SvxShape::getImplementation(xShape); + uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY); + if (pShapeImp && xShapeProp.is()) + { + SdrObject *pSdrObj = pShapeImp->GetSdrObject(); + if (pSdrObj) + { + if (ScDrawLayer::GetAnchor(pSdrObj) == SCA_CELL) + { + ScDocument* pDoc = mpViewShell->GetViewData()->GetDocument(); + if (pDoc) + { + rtl::OUString sCaptionShape(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CaptionShape")); + awt::Point aPoint(xShape->getPosition()); + awt::Size aSize(xShape->getSize()); + rtl::OUString sType(xShape->getShapeType()); + Rectangle aRectangle(aPoint.X, aPoint.Y, aPoint.X + aSize.Width, aPoint.Y + aSize.Height); + if ( sType.equals(sCaptionShape) ) + { + awt::Point aRelativeCaptionPoint; + rtl::OUString sCaptionPoint( RTL_CONSTASCII_USTRINGPARAM( "CaptionPoint" )); + xShapeProp->getPropertyValue( sCaptionPoint ) >>= aRelativeCaptionPoint; + Point aCoreRelativeCaptionPoint(aRelativeCaptionPoint.X, aRelativeCaptionPoint.Y); + Point aCoreAbsoluteCaptionPoint(aPoint.X, aPoint.Y); + aCoreAbsoluteCaptionPoint += aCoreRelativeCaptionPoint; + aRectangle.Union(Rectangle(aCoreAbsoluteCaptionPoint, aCoreAbsoluteCaptionPoint)); + } + ScRange aRange = pDoc->GetRange(mpAccessibleDocument->getVisibleTable(), aRectangle); + pAddress = new ScAddress(aRange.aStart); + } + } +// else +// do nothing, because it is always a NULL Pointer + } + } + } + + return pAddress; +} + +uno::Reference<XAccessibleRelationSet> ScChildrenShapes::GetRelationSet(const ScAccessibleShapeData* pData) const +{ + utl::AccessibleRelationSetHelper* pRelationSet = new utl::AccessibleRelationSetHelper(); + + if(pData && pRelationSet && mpAccessibleDocument) + { + uno::Reference<XAccessible> xAccessible = mpAccessibleDocument->GetAccessibleSpreadsheet(); // should be the current table + if (pData->pRelationCell && xAccessible.is()) + { + uno::Reference<XAccessibleTable> xAccTable (xAccessible->getAccessibleContext(), uno::UNO_QUERY); + if (xAccTable.is()) + xAccessible = xAccTable->getAccessibleCellAt(pData->pRelationCell->Row(), pData->pRelationCell->Col()); + } + AccessibleRelation aRelation; + aRelation.TargetSet.realloc(1); + aRelation.TargetSet[0] = xAccessible; + aRelation.RelationType = AccessibleRelationType::CONTROLLED_BY; + pRelationSet->AddRelation(aRelation); + } + + return pRelationSet; +} + +void ScChildrenShapes::CheckWhetherAnchorChanged(const uno::Reference<drawing::XShape>& xShape) const +{ + SortedShapes::iterator aItr; + if (FindShape(xShape, aItr)) + SetAnchor(xShape, *aItr); +} + +void ScChildrenShapes::SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const +{ + if (pData) + { + ScAddress* pAddress = GetAnchor(xShape); + if ((pAddress && pData->pRelationCell && (*pAddress != *(pData->pRelationCell))) || + (!pAddress && pData->pRelationCell) || (pAddress && !pData->pRelationCell)) + { + if (pData->pRelationCell) + delete pData->pRelationCell; + pData->pRelationCell = pAddress; + if (pData->pAccShape) + pData->pAccShape->SetRelationSet(GetRelationSet(pData)); + } + } +} + +void ScChildrenShapes::AddShape(const uno::Reference<drawing::XShape>& xShape, sal_Bool bCommitChange) const +{ + SortedShapes::iterator aFindItr; + if (!FindShape(xShape, aFindItr)) + { + ScAccessibleShapeData* pShape = new ScAccessibleShapeData(); + pShape->xShape = xShape; + SortedShapes::iterator aNewItr = maZOrderedShapes.insert(aFindItr, pShape); + SetAnchor(xShape, pShape); + + uno::Reference< beans::XPropertySet > xShapeProp(xShape, uno::UNO_QUERY); + if (xShapeProp.is()) + { + uno::Any aPropAny = xShapeProp->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "LayerID" ))); + sal_Int16 nLayerID = 0; + if( aPropAny >>= nLayerID ) + { + if( (nLayerID == SC_LAYER_INTERN) || (nLayerID == SC_LAYER_HIDDEN) ) + pShape->bSelectable = sal_False; + else + pShape->bSelectable = sal_True; + } + } + + + if (!xSelectionSupplier.is()) + throw uno::RuntimeException(); + + uno::Reference<container::XEnumerationAccess> xEnumAcc(xSelectionSupplier->getSelection(), uno::UNO_QUERY); + if (xEnumAcc.is()) + { + uno::Reference<container::XEnumeration> xEnum = xEnumAcc->createEnumeration(); + if (xEnum.is()) + { + uno::Reference<drawing::XShape> xSelectedShape; + sal_Bool bFound(sal_False); + while (!bFound && xEnum->hasMoreElements()) + { + xEnum->nextElement() >>= xSelectedShape; + if (xShape.is() && (xShape.get() == xSelectedShape.get())) + { + pShape->bSelected = sal_True; + bFound = sal_True; + } + } + } + } + if (mpAccessibleDocument && bCommitChange) + { + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::CHILD; + aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument); + aEvent.NewValue <<= Get(aNewItr - maZOrderedShapes.begin()); + + mpAccessibleDocument->CommitChange(aEvent); // new child - event + } + } + else + { + DBG_ERRORFILE("shape is always in the list"); + } +} + +void ScChildrenShapes::RemoveShape(const uno::Reference<drawing::XShape>& xShape) const +{ + SortedShapes::iterator aItr; + if (FindShape(xShape, aItr)) + { + if (mpAccessibleDocument) + { + uno::Reference<XAccessible> xOldAccessible (Get(aItr - maZOrderedShapes.begin())); + + delete *aItr; + maZOrderedShapes.erase(aItr); + + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::CHILD; + aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument); + aEvent.OldValue <<= uno::makeAny(xOldAccessible); + + mpAccessibleDocument->CommitChange(aEvent); // child is gone - event + } + else + { + delete *aItr; + maZOrderedShapes.erase(aItr); + } + } + else + { + DBG_ERRORFILE("shape was not in internal list"); + } +} + +sal_Bool ScChildrenShapes::FindShape(const uno::Reference<drawing::XShape>& xShape, ScChildrenShapes::SortedShapes::iterator& rItr) const +{ + sal_Bool bResult(sal_False); + ScAccessibleShapeData aShape; + aShape.xShape = xShape; + ScShapeDataLess aLess; + rItr = std::lower_bound(maZOrderedShapes.begin(), maZOrderedShapes.end(), &aShape, aLess); + if ((rItr != maZOrderedShapes.end()) && (*rItr != NULL) && ((*rItr)->xShape.get() == xShape.get())) + bResult = sal_True; // if the shape is found + +#ifdef DBG_UTIL // test whether it finds truly the correct shape (perhaps it is not really sorted) + SortedShapes::iterator aDebugItr = maZOrderedShapes.begin(); + SortedShapes::iterator aEndItr = maZOrderedShapes.end(); + sal_Bool bFound(sal_False); + while (!bFound && aDebugItr != aEndItr) + { + if (*aDebugItr && ((*aDebugItr)->xShape.get() == xShape.get())) + bFound = sal_True; + else + ++aDebugItr; + } + sal_Bool bResult2 = (aDebugItr != maZOrderedShapes.end()); + DBG_ASSERT((bResult == bResult2) && ((bResult && (rItr == aDebugItr)) || !bResult), "wrong Shape found"); +#endif + return bResult; +} + +sal_Int8 ScChildrenShapes::Compare(const ScAccessibleShapeData* pData1, + const ScAccessibleShapeData* pData2) const +{ + ScShapeDataLess aLess; + + sal_Bool bResult1(aLess(pData1, pData2)); + sal_Bool bResult2(aLess(pData2, pData1)); + + sal_Int8 nResult(0); + if (!bResult1 && bResult2) + nResult = 1; + else if (bResult1 && !bResult2) + nResult = -1; + + return nResult; +} + +struct ScVisAreaChanged +{ + ScAccessibleDocument* mpAccDoc; + ScVisAreaChanged(ScAccessibleDocument* pAccDoc) : mpAccDoc(pAccDoc) {} + void operator() (const ScAccessibleShapeData* pAccShapeData) const + { + if (pAccShapeData && pAccShapeData->pAccShape) + { + pAccShapeData->pAccShape->ViewForwarderChanged(::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA, mpAccDoc); + } + } +}; + +void ScChildrenShapes::VisAreaChanged() const +{ + ScVisAreaChanged aVisAreaChanged(mpAccessibleDocument); + std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), aVisAreaChanged); +} + +// ============================================================================ + +ScAccessibleDocument::ScAccessibleDocument( + const uno::Reference<XAccessible>& rxParent, + ScTabViewShell* pViewShell, + ScSplitPos eSplitPos) + : ScAccessibleDocumentBase(rxParent), + mpViewShell(pViewShell), + meSplitPos(eSplitPos), + mpAccessibleSpreadsheet(NULL), + mpChildrenShapes(NULL), + mpTempAccEdit(NULL), + mbCompleteSheetSelected(sal_False) +{ + if (pViewShell) + { + pViewShell->AddAccessibilityObject(*this); + Window *pWin = pViewShell->GetWindowByPos(eSplitPos); + if( pWin ) + { + pWin->AddChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener )); + USHORT nCount = pWin->GetChildCount(); + for( sal_uInt16 i=0; i < nCount; ++i ) + { + Window *pChildWin = pWin->GetChild( i ); + if( pChildWin && + AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() ) + AddChild( pChildWin->GetAccessible(), sal_False ); + } + } + if (pViewShell->GetViewData()->HasEditView( eSplitPos )) + { + uno::Reference<XAccessible> xAcc = new ScAccessibleEditObject(this, pViewShell->GetViewData()->GetEditView(eSplitPos), + pViewShell->GetWindowByPos(eSplitPos), GetCurrentCellName(), GetCurrentCellDescription(), + CellInEditMode); + AddChild(xAcc, sal_False); + } + } + maVisArea = GetVisibleArea_Impl(); +} + +void ScAccessibleDocument::Init() +{ + if(!mpChildrenShapes) + mpChildrenShapes = new ScChildrenShapes(this, mpViewShell, meSplitPos); +} + +ScAccessibleDocument::~ScAccessibleDocument(void) +{ + if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose) + { + // increment refcount to prevent double call off dtor + osl_incrementInterlockedCount( &m_refCount ); + dispose(); + } +} + +void SAL_CALL ScAccessibleDocument::disposing() +{ + ScUnoGuard aGuard; + FreeAccessibleSpreadsheet(); + if (mpViewShell) + { + Window *pWin = mpViewShell->GetWindowByPos(meSplitPos); + if( pWin ) + pWin->RemoveChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener )); + + mpViewShell->RemoveAccessibilityObject(*this); + mpViewShell = NULL; + } + if (mpChildrenShapes) + DELETEZ(mpChildrenShapes); + + ScAccessibleDocumentBase::disposing(); +} + +void SAL_CALL ScAccessibleDocument::disposing( const lang::EventObject& /* Source */ ) + throw (uno::RuntimeException) +{ + disposing(); +} + + //===== SfxListener ===================================================== + +IMPL_LINK( ScAccessibleDocument, WindowChildEventListener, VclSimpleEvent*, pEvent ) +{ + DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" ); + if ( pEvent && pEvent->ISA( VclWindowEvent ) ) + { + VclWindowEvent *pVclEvent = static_cast< VclWindowEvent * >( pEvent ); + DBG_ASSERT( pVclEvent->GetWindow(), "Window???" ); + switch ( pVclEvent->GetId() ) + { + case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children + { + Window* pChildWin = static_cast < Window * >( pVclEvent->GetData() ); + if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() ) + { + AddChild( pChildWin->GetAccessible(), sal_True ); + } + } + break; + case VCLEVENT_WINDOW_HIDE: // send destroy on hide for direct accessible children + { + Window* pChildWin = static_cast < Window * >( pVclEvent->GetData() ); + if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() ) + { + RemoveChild( pChildWin->GetAccessible(), sal_True ); + } + } + break; + } + } + return 0; +} + +void ScAccessibleDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + if (rHint.ISA( ScAccGridWinFocusLostHint ) ) + { + const ScAccGridWinFocusLostHint& rRef = (const ScAccGridWinFocusLostHint&)rHint; + if (rRef.GetOldGridWin() == meSplitPos) + { + if (mxTempAcc.is() && mpTempAccEdit) + mpTempAccEdit->LostFocus(); + else if (mpAccessibleSpreadsheet) + mpAccessibleSpreadsheet->LostFocus(); + else + CommitFocusLost(); + } + } + else if (rHint.ISA( ScAccGridWinFocusGotHint ) ) + { + const ScAccGridWinFocusGotHint& rRef = (const ScAccGridWinFocusGotHint&)rHint; + if (rRef.GetNewGridWin() == meSplitPos) + { + if (mxTempAcc.is() && mpTempAccEdit) + mpTempAccEdit->GotFocus(); + else if (mpAccessibleSpreadsheet) + mpAccessibleSpreadsheet->GotFocus(); + else + CommitFocusGained(); + } + } + else 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_TABLECHANGED) && + mpAccessibleSpreadsheet) + { + FreeAccessibleSpreadsheet(); + if (mpChildrenShapes) + DELETEZ(mpChildrenShapes); + + // #124567# Accessibility: Shapes / form controls after reload not accessible + if ( !mpChildrenShapes ) + { + mpChildrenShapes = new ScChildrenShapes( this, mpViewShell, meSplitPos ); + } + + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::INVALIDATE_ALL_CHILDREN; + aEvent.Source = uno::Reference< XAccessibleContext >(this); + CommitChange(aEvent); // all childs changed + } + else if (rRef.GetId() == SC_HINT_ACC_MAKEDRAWLAYER) + { + if (mpChildrenShapes) + mpChildrenShapes->SetDrawBroadcaster(); + } + else if ((rRef.GetId() == SC_HINT_ACC_ENTEREDITMODE)) // this event comes only on creating edit field of a cell + { + if (mpViewShell && mpViewShell->GetViewData()->HasEditView(meSplitPos)) + { + mpTempAccEdit = new ScAccessibleEditObject(this, mpViewShell->GetViewData()->GetEditView(meSplitPos), + mpViewShell->GetWindowByPos(meSplitPos), GetCurrentCellName(), + rtl::OUString(String(ScResId(STR_ACC_EDITLINE_DESCR))), CellInEditMode); + uno::Reference<XAccessible> xAcc = mpTempAccEdit; + + AddChild(xAcc, sal_True); + + if (mpAccessibleSpreadsheet) + mpAccessibleSpreadsheet->LostFocus(); + else + CommitFocusLost(); + + mpTempAccEdit->GotFocus(); + } + } + else if (rRef.GetId() == SC_HINT_ACC_LEAVEEDITMODE) + { + if (mxTempAcc.is()) + { + if (mpTempAccEdit) + mpTempAccEdit->LostFocus(); + + mpTempAccEdit = NULL; + RemoveChild(mxTempAcc, sal_True); + + if (mpAccessibleSpreadsheet) + mpAccessibleSpreadsheet->GotFocus(); + else + CommitFocusGained(); + } + } + else if ((rRef.GetId() == SC_HINT_ACC_VISAREACHANGED) || (rRef.GetId() == SC_HINT_ACC_WINDOWRESIZED)) + { + Rectangle aOldVisArea(maVisArea); + maVisArea = GetVisibleArea_Impl(); + + if (maVisArea != aOldVisArea) + { + if (maVisArea.GetSize() != aOldVisArea.GetSize()) + { + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED; + aEvent.Source = uno::Reference< XAccessibleContext >(this); + + CommitChange(aEvent); + + if (mpAccessibleSpreadsheet) + mpAccessibleSpreadsheet->BoundingBoxChanged(); + } + else if (mpAccessibleSpreadsheet) + { + mpAccessibleSpreadsheet->VisAreaChanged(); + } + if (mpChildrenShapes) + mpChildrenShapes->VisAreaChanged(); + } + } + } + + ScAccessibleDocumentBase::Notify(rBC, rHint); +} + +void SAL_CALL ScAccessibleDocument::selectionChanged( const lang::EventObject& /* aEvent */ ) + throw (uno::RuntimeException) +{ + sal_Bool bSelectionChanged(sal_False); + if (mpAccessibleSpreadsheet) + { + sal_Bool bOldSelected(mbCompleteSheetSelected); + mbCompleteSheetSelected = IsTableSelected(); + if (bOldSelected != mbCompleteSheetSelected) + { + mpAccessibleSpreadsheet->CompleteSelectionChanged(mbCompleteSheetSelected); + bSelectionChanged = sal_True; + } + } + + if (mpChildrenShapes && mpChildrenShapes->SelectionChanged()) + bSelectionChanged = sal_True; + + if (bSelectionChanged) + { + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::SELECTION_CHANGED; + aEvent.Source = uno::Reference< XAccessibleContext >(this); + + CommitChange(aEvent); + } +} + + //===== XInterface ===================================================== + +uno::Any SAL_CALL ScAccessibleDocument::queryInterface( uno::Type const & rType ) + throw (uno::RuntimeException) +{ + uno::Any aAny (ScAccessibleDocumentImpl::queryInterface(rType)); + return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType); +} + +void SAL_CALL ScAccessibleDocument::acquire() + throw () +{ + ScAccessibleContextBase::acquire(); +} + +void SAL_CALL ScAccessibleDocument::release() + throw () +{ + ScAccessibleContextBase::release(); +} + + //===== XAccessibleComponent ============================================ + +uno::Reference< XAccessible > SAL_CALL ScAccessibleDocument::getAccessibleAtPoint( + const awt::Point& rPoint ) + throw (uno::RuntimeException) +{ + uno::Reference<XAccessible> xAccessible = NULL; + if (containsPoint(rPoint)) + { + ScUnoGuard aGuard; + IsObjectValid(); + if (mpChildrenShapes) + xAccessible = mpChildrenShapes->GetAt(rPoint); + if(!xAccessible.is()) + { + if (mxTempAcc.is()) + { + uno::Reference< XAccessibleContext > xCont(mxTempAcc->getAccessibleContext()); + uno::Reference< XAccessibleComponent > xComp(xCont, uno::UNO_QUERY); + if (xComp.is()) + { + Rectangle aBound(VCLRectangle(xComp->getBounds())); + if (aBound.IsInside(VCLPoint(rPoint))) + xAccessible = mxTempAcc; + } + } + if (!xAccessible.is()) + xAccessible = GetAccessibleSpreadsheet(); + } + } + return xAccessible; +} + +void SAL_CALL ScAccessibleDocument::grabFocus( ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + IsObjectValid(); + if (getAccessibleParent().is()) + { + uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY); + if (xAccessibleComponent.is()) + { + xAccessibleComponent->grabFocus(); + // grab only focus if it does not have the focus and it is not hidden + if (mpViewShell && mpViewShell->GetViewData() && + (mpViewShell->GetViewData()->GetActivePart() != meSplitPos) && + mpViewShell->GetWindowByPos(meSplitPos)->IsVisible()) + { + mpViewShell->ActivatePart(meSplitPos); + } + } + } +} + + //===== XAccessibleContext ============================================== + + /// Return the number of currently visible children. +sal_Int32 SAL_CALL + ScAccessibleDocument::getAccessibleChildCount(void) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + IsObjectValid(); + sal_Int32 nCount(1); + if (mpChildrenShapes) + nCount = mpChildrenShapes->GetCount(); // returns the count of the shapes inclusive the table + + if (mxTempAcc.is()) + ++nCount; + + return nCount; +} + + /// Return the specified child or NULL if index is invalid. +uno::Reference<XAccessible> SAL_CALL + ScAccessibleDocument::getAccessibleChild(sal_Int32 nIndex) + throw (uno::RuntimeException, + lang::IndexOutOfBoundsException) +{ + ScUnoGuard aGuard; + IsObjectValid(); + uno::Reference<XAccessible> xAccessible; + if (nIndex >= 0) + { + sal_Int32 nCount(1); + if (mpChildrenShapes) + { + xAccessible = mpChildrenShapes->Get(nIndex); // returns NULL if it is the table or out of range + nCount = mpChildrenShapes->GetCount(); //there is always a table + } + if (!xAccessible.is()) + { + if (nIndex < nCount) + xAccessible = GetAccessibleSpreadsheet(); + else if (nIndex == nCount && mxTempAcc.is()) + xAccessible = mxTempAcc; + } + } + + if (!xAccessible.is()) + throw lang::IndexOutOfBoundsException(); + + return xAccessible; +} + + /// Return the set of current states. +uno::Reference<XAccessibleStateSet> SAL_CALL + ScAccessibleDocument::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 + { + if (IsEditable(xParentStates)) + pStateSet->AddState(AccessibleStateType::EDITABLE); + pStateSet->AddState(AccessibleStateType::ENABLED); + pStateSet->AddState(AccessibleStateType::OPAQUE); + if (isShowing()) + pStateSet->AddState(AccessibleStateType::SHOWING); + if (isVisible()) + pStateSet->AddState(AccessibleStateType::VISIBLE); + } + return pStateSet; +} + + ///===== XAccessibleSelection =========================================== + +void SAL_CALL + ScAccessibleDocument::selectAccessibleChild( sal_Int32 nChildIndex ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + IsObjectValid(); + + if (mpChildrenShapes) + { + sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table + if (mxTempAcc.is()) + ++nCount; + if (nChildIndex < 0 || nChildIndex >= nCount) + throw lang::IndexOutOfBoundsException(); + + uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex); + if (xAccessible.is()) + { + sal_Bool bWasTableSelected(IsTableSelected()); + + if (mpChildrenShapes) + mpChildrenShapes->Select(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is to high + + if (bWasTableSelected) + mpViewShell->SelectAll(); + } + else + { + if (mpViewShell) + mpViewShell->SelectAll(); + } + } +} + +sal_Bool SAL_CALL + ScAccessibleDocument::isAccessibleChildSelected( sal_Int32 nChildIndex ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + IsObjectValid(); + sal_Bool bResult(sal_False); + + if (mpChildrenShapes) + { + sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table + if (mxTempAcc.is()) + ++nCount; + if (nChildIndex < 0 || nChildIndex >= nCount) + throw lang::IndexOutOfBoundsException(); + + uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex); + if (xAccessible.is()) + { + uno::Reference<drawing::XShape> xShape; + bResult = mpChildrenShapes->IsSelected(nChildIndex, xShape); // throws no lang::IndexOutOfBoundsException if Index is to high + } + else + { + if (mxTempAcc.is() && nChildIndex == nCount) + bResult = sal_True; + else + bResult = IsTableSelected(); + } + } + return bResult; +} + +void SAL_CALL + ScAccessibleDocument::clearAccessibleSelection( ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + IsObjectValid(); + + if (mpChildrenShapes) + mpChildrenShapes->DeselectAll(); //deselects all (also the table) +} + +void SAL_CALL + ScAccessibleDocument::selectAllAccessibleChildren( ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + IsObjectValid(); + + if (mpChildrenShapes) + mpChildrenShapes->SelectAll(); + + // select table after shapes, because while selecting shapes the table will be deselected + if (mpViewShell) + { + mpViewShell->SelectAll(); + } +} + +sal_Int32 SAL_CALL + ScAccessibleDocument::getSelectedAccessibleChildCount( ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + IsObjectValid(); + sal_Int32 nCount(0); + + if (mpChildrenShapes) + nCount = mpChildrenShapes->GetSelectedCount(); + + if (IsTableSelected()) + ++nCount; + + if (mxTempAcc.is()) + ++nCount; + + return nCount; +} + +uno::Reference<XAccessible > SAL_CALL + ScAccessibleDocument::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + IsObjectValid(); + uno::Reference<XAccessible> xAccessible; + if (mpChildrenShapes) + { + sal_Int32 nCount(getSelectedAccessibleChildCount()); //all shapes and the table + if (nSelectedChildIndex < 0 || nSelectedChildIndex >= nCount) + throw lang::IndexOutOfBoundsException(); + + sal_Bool bTabMarked(IsTableSelected()); + + if (mpChildrenShapes) + xAccessible = mpChildrenShapes->GetSelected(nSelectedChildIndex, bTabMarked); // throws no lang::IndexOutOfBoundsException if Index is to high + if (mxTempAcc.is() && nSelectedChildIndex == nCount - 1) + xAccessible = mxTempAcc; + else if (bTabMarked) + xAccessible = GetAccessibleSpreadsheet(); + } + + DBG_ASSERT(xAccessible.is(), "here should always be an accessible object or a exception throwed"); + + return xAccessible; +} + +void SAL_CALL + ScAccessibleDocument::deselectAccessibleChild( sal_Int32 nChildIndex ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + IsObjectValid(); + + if (mpChildrenShapes) + { + sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table + if (mxTempAcc.is()) + ++nCount; + if (nChildIndex < 0 || nChildIndex >= nCount) + throw lang::IndexOutOfBoundsException(); + + sal_Bool bTabMarked(IsTableSelected()); + + uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex); + if (xAccessible.is()) + { + if (mpChildrenShapes) + mpChildrenShapes->Deselect(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is to high + + if (bTabMarked) + mpViewShell->SelectAll(); // select the table again + } + else if (bTabMarked) + mpViewShell->Unmark(); + } +} + + //===== XServiceInfo ==================================================== + +::rtl::OUString SAL_CALL + ScAccessibleDocument::getImplementationName(void) + throw (uno::RuntimeException) +{ + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleDocument")); +} + +uno::Sequence< ::rtl::OUString> SAL_CALL + ScAccessibleDocument::getSupportedServiceNames(void) + throw (uno::RuntimeException) +{ + uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::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.AccessibleSpreadsheetDocumentView")); + + return aSequence; +} + +//===== XTypeProvider ======================================================= + +uno::Sequence< uno::Type > SAL_CALL ScAccessibleDocument::getTypes() + throw (uno::RuntimeException) +{ + return comphelper::concatSequences(ScAccessibleDocumentImpl::getTypes(), ScAccessibleContextBase::getTypes()); +} + +uno::Sequence<sal_Int8> SAL_CALL + ScAccessibleDocument::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; +} + +///===== IAccessibleViewForwarder ======================================== + +sal_Bool ScAccessibleDocument::IsValid (void) const +{ + ScUnoGuard aGuard; + IsObjectValid(); + return (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose); +} + +Rectangle ScAccessibleDocument::GetVisibleArea_Impl() const +{ + Rectangle aVisRect(GetBoundingBox()); + + Point aPoint(mpViewShell->GetViewData()->GetPixPos(meSplitPos)); // returns a negative Point + aPoint.setX(-aPoint.getX()); + aPoint.setY(-aPoint.getY()); + aVisRect.SetPos(aPoint); + + ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos)); + if (pWin) + aVisRect = pWin->PixelToLogic(aVisRect, pWin->GetDrawMapMode()); + + return aVisRect; +} + +Rectangle ScAccessibleDocument::GetVisibleArea() const +{ + ScUnoGuard aGuard; + IsObjectValid(); + return maVisArea; +} + +Point ScAccessibleDocument::LogicToPixel (const Point& rPoint) const +{ + ScUnoGuard aGuard; + IsObjectValid(); + Point aPoint; + ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos)); + if (pWin) + { + aPoint = pWin->LogicToPixel(rPoint, pWin->GetDrawMapMode()); + aPoint += pWin->GetWindowExtentsRelative(NULL).TopLeft(); + } + return aPoint; +} + +Size ScAccessibleDocument::LogicToPixel (const Size& rSize) const +{ + ScUnoGuard aGuard; + IsObjectValid(); + Size aSize; + ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos)); + if (pWin) + aSize = pWin->LogicToPixel(rSize, pWin->GetDrawMapMode()); + return aSize; +} + +Point ScAccessibleDocument::PixelToLogic (const Point& rPoint) const +{ + ScUnoGuard aGuard; + IsObjectValid(); + Point aPoint; + ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos)); + if (pWin) + { + aPoint -= pWin->GetWindowExtentsRelative(NULL).TopLeft(); + aPoint = pWin->PixelToLogic(rPoint, pWin->GetDrawMapMode()); + } + return aPoint; +} + +Size ScAccessibleDocument::PixelToLogic (const Size& rSize) const +{ + ScUnoGuard aGuard; + IsObjectValid(); + Size aSize; + ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos)); + if (pWin) + aSize = pWin->PixelToLogic(rSize, pWin->GetDrawMapMode()); + return aSize; +} + + //===== internal ======================================================== + +utl::AccessibleRelationSetHelper* ScAccessibleDocument::GetRelationSet(const ScAddress* pAddress) const +{ + utl::AccessibleRelationSetHelper* pRelationSet = NULL; + if (mpChildrenShapes) + pRelationSet = mpChildrenShapes->GetRelationSet(pAddress); + return pRelationSet; +} + +::rtl::OUString SAL_CALL + ScAccessibleDocument::createAccessibleDescription(void) + throw (uno::RuntimeException) +{ + rtl::OUString sDescription = String(ScResId(STR_ACC_DOC_DESCR)); + return sDescription; +} + +::rtl::OUString SAL_CALL + ScAccessibleDocument::createAccessibleName(void) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + IsObjectValid(); + rtl::OUString sName = String(ScResId(STR_ACC_DOC_NAME)); + sal_Int32 nNumber(sal_Int32(meSplitPos) + 1); + sName += rtl::OUString::valueOf(nNumber); + return sName; +} + +Rectangle ScAccessibleDocument::GetBoundingBoxOnScreen() const + throw (uno::RuntimeException) +{ + Rectangle aRect; + if (mpViewShell) + { + Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos); + if (pWindow) + aRect = pWindow->GetWindowExtentsRelative(NULL); + } + return aRect; +} + +Rectangle ScAccessibleDocument::GetBoundingBox() const + throw (uno::RuntimeException) +{ + Rectangle aRect; + if (mpViewShell) + { + Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos); + if (pWindow) + aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow()); + } + return aRect; +} + +SCTAB ScAccessibleDocument::getVisibleTable() const +{ + SCTAB nVisibleTable(0); + if (mpViewShell && mpViewShell->GetViewData()) + nVisibleTable = mpViewShell->GetViewData()->GetTabNo(); + return nVisibleTable; +} + +uno::Reference < XAccessible > + ScAccessibleDocument::GetAccessibleSpreadsheet() +{ + if (!mpAccessibleSpreadsheet && mpViewShell) + { + mpAccessibleSpreadsheet = new ScAccessibleSpreadsheet(this, mpViewShell, getVisibleTable(), meSplitPos); + mpAccessibleSpreadsheet->acquire(); + mpAccessibleSpreadsheet->Init(); + mbCompleteSheetSelected = IsTableSelected(); + } + return mpAccessibleSpreadsheet; +} + +void ScAccessibleDocument::FreeAccessibleSpreadsheet() +{ + if (mpAccessibleSpreadsheet) + { + mpAccessibleSpreadsheet->dispose(); + mpAccessibleSpreadsheet->release(); + mpAccessibleSpreadsheet = NULL; + } +} + +sal_Bool ScAccessibleDocument::IsTableSelected() const +{ + sal_Bool bResult (sal_False); + if(mpViewShell) + { + SCTAB nTab(getVisibleTable()); + //#103800#; use a copy of MarkData + ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData()); + aMarkData.MarkToMulti(); + if (aMarkData.IsAllMarked(ScRange(ScAddress(0, 0, nTab),ScAddress(MAXCOL, MAXROW, nTab)))) + bResult = sal_True; + } + return bResult; +} + +sal_Bool ScAccessibleDocument::IsDefunc( + const uno::Reference<XAccessibleStateSet>& rxParentStates) +{ + return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() || + (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC)); +} + +sal_Bool ScAccessibleDocument::IsEditable( + const uno::Reference<XAccessibleStateSet>& /* rxParentStates */) +{ + // what is with document protection or readonly documents? + return sal_True; +} + +void ScAccessibleDocument::AddChild(const uno::Reference<XAccessible>& xAcc, sal_Bool bFireEvent) +{ + DBG_ASSERT(!mxTempAcc.is(), "this object should be removed before"); + if (xAcc.is()) + { + mxTempAcc = xAcc; + if( bFireEvent ) + { + AccessibleEventObject aEvent; + aEvent.Source = uno::Reference<XAccessibleContext>(this); + aEvent.EventId = AccessibleEventId::CHILD; + aEvent.NewValue <<= mxTempAcc; + CommitChange( aEvent ); + } + } +} + +void ScAccessibleDocument::RemoveChild(const uno::Reference<XAccessible>& xAcc, sal_Bool bFireEvent) +{ + DBG_ASSERT(mxTempAcc.is(), "this object should be added before"); + if (xAcc.is()) + { + DBG_ASSERT(xAcc.get() == mxTempAcc.get(), "only the same object should be removed"); + if( bFireEvent ) + { + AccessibleEventObject aEvent; + aEvent.Source = uno::Reference<XAccessibleContext>(this); + aEvent.EventId = AccessibleEventId::CHILD; + aEvent.OldValue <<= mxTempAcc; + CommitChange( aEvent ); + } + mxTempAcc = NULL; + } +} + +rtl::OUString ScAccessibleDocument::GetCurrentCellName() const +{ + String sName( ScResId(STR_ACC_CELL_NAME) ); + if (mpViewShell) + { + String sAddress; + // Document not needed, because only the cell address, but not the tablename is needed + mpViewShell->GetViewData()->GetCurPos().Format( sAddress, SCA_VALID, NULL ); + sName.SearchAndReplaceAscii("%1", sAddress); + } + return rtl::OUString(sName); +} + +rtl::OUString ScAccessibleDocument::GetCurrentCellDescription() const +{ + return rtl::OUString(); +} |