/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include "AccessibleDocumentPagePreview.hxx" #include "AccessiblePreviewTable.hxx" #include "AccessiblePageHeader.hxx" #include "AccessibilityHints.hxx" #include "AccessibleText.hxx" #include "document.hxx" #include "prevwsh.hxx" #include "prevloc.hxx" #include "drwlayer.hxx" #include "editsrc.hxx" #include "scresid.hxx" #include "sc.hrc" #include "DrawModelBroadcaster.hxx" #include "docsh.hxx" #include "drawview.hxx" #include "preview.hxx" #include "postit.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; typedef std::list< uno::Reference< XAccessible > > ScXAccList; struct ScAccNote { OUString maNoteText; Rectangle maRect; ScAddress maNoteCell; ::accessibility::AccessibleTextHelper* mpTextHelper; sal_Int32 mnParaCount; bool mbMarkNote; ScAccNote() : mpTextHelper(NULL) , mnParaCount(0) , mbMarkNote(false) { } }; class ScNotesChildren { public: ScNotesChildren(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc); ~ScNotesChildren(); void Init(const Rectangle& rVisRect, sal_Int32 nOffset); sal_Int32 GetChildrenCount() const { return mnParagraphs;} uno::Reference GetChild(sal_Int32 nIndex) const; uno::Reference GetAt(const awt::Point& rPoint) const; void DataChanged(const Rectangle& rVisRect); private: ScPreviewShell* mpViewShell; ScAccessibleDocumentPagePreview* mpAccDoc; typedef std::vector ScAccNotes; mutable ScAccNotes maNotes; mutable ScAccNotes maMarks; sal_Int32 mnParagraphs; sal_Int32 mnOffset; ::accessibility::AccessibleTextHelper* CreateTextHelper(const OUString& rString, const Rectangle& rVisRect, const ScAddress& aCellPos, bool bMarkNote, sal_Int32 nChildOffset) const; sal_Int32 AddNotes(const ScPreviewLocationData& rData, const Rectangle& rVisRect, bool bMark, ScAccNotes& rNotes); sal_Int8 CompareCell(const ScAddress& aCell1, const ScAddress& aCell2); void CollectChildren(const ScAccNote& rNote, ScXAccList& rList); sal_Int32 CheckChanges(const ScPreviewLocationData& rData, const Rectangle& rVisRect, bool bMark, ScAccNotes& rOldNotes, ScAccNotes& rNewNotes, ScXAccList& rOldParas, ScXAccList& rNewParas); inline ScDocument* GetDocument() const; }; ScNotesChildren::ScNotesChildren(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc) : mpViewShell(pViewShell), mpAccDoc(pAccDoc), mnParagraphs(0), mnOffset(0) { } struct DeleteAccNote { void operator()(ScAccNote& rNote) { if (rNote.mpTextHelper) DELETEZ( rNote.mpTextHelper); } }; ScNotesChildren::~ScNotesChildren() { std::for_each(maNotes.begin(), maNotes.end(), DeleteAccNote()); std::for_each(maMarks.begin(), maMarks.end(), DeleteAccNote()); } ::accessibility::AccessibleTextHelper* ScNotesChildren::CreateTextHelper(const OUString& rString, const Rectangle& rVisRect, const ScAddress& aCellPos, bool bMarkNote, sal_Int32 nChildOffset) const { ::accessibility::AccessibleTextHelper* pTextHelper = NULL; ::std::unique_ptr < ScAccessibleTextData > pAccessiblePreviewHeaderCellTextData (new ScAccessibleNoteTextData(mpViewShell, rString, aCellPos, bMarkNote)); ::std::unique_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(std::move(pAccessiblePreviewHeaderCellTextData))); pTextHelper = new ::accessibility::AccessibleTextHelper(std::move(pEditSource)); if (pTextHelper) { pTextHelper->SetEventSource(mpAccDoc); pTextHelper->SetStartIndex(nChildOffset); pTextHelper->SetOffset(rVisRect.TopLeft()); } return pTextHelper; } sal_Int32 ScNotesChildren::AddNotes(const ScPreviewLocationData& rData, const Rectangle& rVisRect, bool bMark, ScAccNotes& rNotes) { sal_Int32 nCount = rData.GetNoteCountInRange(rVisRect, bMark); rNotes.reserve(nCount); sal_Int32 nParagraphs(0); ScDocument* pDoc = GetDocument(); if (pDoc) { ScAccNote aNote; aNote.mbMarkNote = bMark; if (bMark) aNote.mnParaCount = 1; for (sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex) { if (rData.GetNoteInRange(rVisRect, nIndex, bMark, aNote.maNoteCell, aNote.maRect)) { if (bMark) { // Document not needed, because only the cell address, but not the tablename is needed aNote.maNoteText = aNote.maNoteCell.Format(SCA_VALID, NULL); } else { if( ScPostIt* pNote = pDoc->GetNote( aNote.maNoteCell ) ) aNote.maNoteText = pNote->GetText(); aNote.mpTextHelper = CreateTextHelper(aNote.maNoteText, aNote.maRect, aNote.maNoteCell, aNote.mbMarkNote, nParagraphs + mnOffset); if (aNote.mpTextHelper) aNote.mnParaCount = aNote.mpTextHelper->GetChildCount(); } nParagraphs += aNote.mnParaCount; rNotes.push_back(aNote); } } } return nParagraphs; } void ScNotesChildren::Init(const Rectangle& rVisRect, sal_Int32 nOffset) { if (mpViewShell && !mnParagraphs) { mnOffset = nOffset; const ScPreviewLocationData& rData = mpViewShell->GetLocationData(); mnParagraphs = AddNotes(rData, rVisRect, false, maMarks); mnParagraphs += AddNotes(rData, rVisRect, true, maNotes); } } struct ScParaFound { sal_Int32 mnIndex; ScParaFound(sal_Int32 nIndex) : mnIndex(nIndex) {} bool operator() (const ScAccNote& rNote) { bool bResult(false); if (rNote.mnParaCount > mnIndex) bResult = true; else mnIndex -= rNote.mnParaCount; return bResult; } }; uno::Reference ScNotesChildren::GetChild(sal_Int32 nIndex) const { uno::Reference xAccessible; if (nIndex < mnParagraphs) { if (nIndex < static_cast(maMarks.size())) { ScAccNotes::iterator aEndItr = maMarks.end(); ScParaFound aParaFound(nIndex); ScAccNotes::iterator aItr = std::find_if(maMarks.begin(), aEndItr, aParaFound); if (aItr != aEndItr) { OSL_ENSURE((aItr->maNoteCell == maMarks[nIndex].maNoteCell) && (aItr->mbMarkNote == maMarks[nIndex].mbMarkNote), "wrong note found"); if (!aItr->mpTextHelper) aItr->mpTextHelper = CreateTextHelper(maMarks[nIndex].maNoteText, maMarks[nIndex].maRect, maMarks[nIndex].maNoteCell, maMarks[nIndex].mbMarkNote, nIndex + mnOffset); // the marks are the first and every mark has only one paragraph xAccessible = aItr->mpTextHelper->GetChild(aParaFound.mnIndex + aItr->mpTextHelper->GetStartIndex()); } else { OSL_FAIL("wrong note found"); } } else { nIndex -= maMarks.size(); ScAccNotes::iterator aEndItr = maNotes.end(); ScParaFound aParaFound(nIndex); ScAccNotes::iterator aItr = std::find_if(maNotes.begin(), aEndItr, aParaFound); if (aEndItr != aItr) { if (!aItr->mpTextHelper) aItr->mpTextHelper = CreateTextHelper(aItr->maNoteText, aItr->maRect, aItr->maNoteCell, aItr->mbMarkNote, (nIndex - aParaFound.mnIndex) + mnOffset + maMarks.size()); xAccessible = aItr->mpTextHelper->GetChild(aParaFound.mnIndex + aItr->mpTextHelper->GetStartIndex()); } } } return xAccessible; } struct ScPointFound { Rectangle maPoint; sal_Int32 mnParagraphs; ScPointFound(const Point& rPoint) : maPoint(rPoint, Size(0, 0)), mnParagraphs(0) {} bool operator() (const ScAccNote& rNote) { bool bResult(false); if (maPoint.IsInside(rNote.maRect)) bResult = true; else mnParagraphs += rNote.mnParaCount; return bResult; } }; uno::Reference ScNotesChildren::GetAt(const awt::Point& rPoint) const { uno::Reference xAccessible; ScPointFound aPointFound(Point(rPoint.X, rPoint.Y)); ScAccNotes::iterator aEndItr = maMarks.end(); ScAccNotes::iterator aItr = std::find_if(maMarks.begin(), aEndItr, aPointFound); if (aEndItr == aItr) { aEndItr = maNotes.end(); aItr = std::find_if(maNotes.begin(), aEndItr, aPointFound); } if (aEndItr != aItr) { if (!aItr->mpTextHelper) aItr->mpTextHelper = CreateTextHelper(aItr->maNoteText, aItr->maRect, aItr->maNoteCell, aItr->mbMarkNote, aPointFound.mnParagraphs + mnOffset); xAccessible = aItr->mpTextHelper->GetAt(rPoint); } return xAccessible; } sal_Int8 ScNotesChildren::CompareCell(const ScAddress& aCell1, const ScAddress& aCell2) { OSL_ENSURE(aCell1.Tab() == aCell2.Tab(), "the notes should be on the same table"); sal_Int8 nResult(0); if (aCell1 != aCell2) { if (aCell1.Row() == aCell2.Row()) nResult = (aCell1.Col() < aCell2.Col()) ? -1 : 1; else nResult = (aCell1.Row() < aCell2.Row()) ? -1 : 1; } return nResult; } void ScNotesChildren::CollectChildren(const ScAccNote& rNote, ScXAccList& rList) { if (rNote.mpTextHelper) for (sal_Int32 i = 0; i < rNote.mnParaCount; ++i) rList.push_back(rNote.mpTextHelper->GetChild(i + rNote.mpTextHelper->GetStartIndex())); } sal_Int32 ScNotesChildren::CheckChanges(const ScPreviewLocationData& rData, const Rectangle& rVisRect, bool bMark, ScAccNotes& rOldNotes, ScAccNotes& rNewNotes, ScXAccList& rOldParas, ScXAccList& rNewParas) { sal_Int32 nCount = rData.GetNoteCountInRange(rVisRect, bMark); rNewNotes.reserve(nCount); sal_Int32 nParagraphs(0); ScDocument* pDoc = GetDocument(); if (pDoc) { ScAccNote aNote; aNote.mbMarkNote = bMark; if (bMark) aNote.mnParaCount = 1; ScAccNotes::iterator aItr = rOldNotes.begin(); ScAccNotes::iterator aEndItr = rOldNotes.end(); bool bAddNote(false); for (sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex) { if (rData.GetNoteInRange(rVisRect, nIndex, bMark, aNote.maNoteCell, aNote.maRect)) { if (bMark) { // Document not needed, because only the cell address, but not the tablename is needed aNote.maNoteText = aNote.maNoteCell.Format(SCA_VALID, NULL); } else { if( ScPostIt* pNote = pDoc->GetNote( aNote.maNoteCell ) ) aNote.maNoteText = pNote->GetText(); } sal_Int8 nCompare(-1); // if there are no more old children it is always a new one if (aItr != aEndItr) nCompare = CompareCell(aNote.maNoteCell, aItr->maNoteCell); if (nCompare == 0) { if (aNote.maNoteText == aItr->maNoteText) { aNote.mpTextHelper = aItr->mpTextHelper; if (aNote.maRect != aItr->maRect) //neue VisArea setzen { aNote.mpTextHelper->SetOffset(aNote.maRect.TopLeft()); aNote.mpTextHelper->UpdateChildren(); //OSL_ENSURE(aItr->maRect.GetSize() == aNote.maRect.GetSize(), "size should be the same, because the text is not changed"); // could be changed, because only a part of the note is visible } } else { aNote.mpTextHelper = CreateTextHelper(aNote.maNoteText, aNote.maRect, aNote.maNoteCell, aNote.mbMarkNote, nParagraphs + mnOffset); if (aNote.mpTextHelper) aNote.mnParaCount = aNote.mpTextHelper->GetChildCount(); // collect removed children CollectChildren(*aItr, rOldParas); DELETEZ(aItr->mpTextHelper); // collect new children CollectChildren(aNote, rNewParas); } bAddNote = true; // not necessary, because this branch should not be reached if it is the end //if (aItr != aEndItr) ++aItr; } else if (nCompare < 0) { aNote.mpTextHelper = CreateTextHelper(aNote.maNoteText, aNote.maRect, aNote.maNoteCell, aNote.mbMarkNote, nParagraphs + mnOffset); if (aNote.mpTextHelper) aNote.mnParaCount = aNote.mpTextHelper->GetChildCount(); // collect new children CollectChildren(aNote, rNewParas); bAddNote = true; } else { // collect removed children CollectChildren(*aItr, rOldParas); DELETEZ(aItr->mpTextHelper); // no note to add // not necessary, because this branch should not be reached if it is the end //if (aItr != aEndItr) ++aItr; } if (bAddNote) { nParagraphs += aNote.mnParaCount; rNewNotes.push_back(aNote); bAddNote = false; } } } } return nParagraphs; } struct ScChildGone { ScAccessibleDocumentPagePreview* mpAccDoc; ScChildGone(ScAccessibleDocumentPagePreview* pAccDoc) : mpAccDoc(pAccDoc) {} void operator() (const uno::Reference& xAccessible) const { if (mpAccDoc) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::CHILD; aEvent.Source = uno::Reference< XAccessibleContext >(mpAccDoc); aEvent.OldValue <<= xAccessible; mpAccDoc->CommitChange(aEvent); // gone child - event } } }; struct ScChildNew { ScAccessibleDocumentPagePreview* mpAccDoc; ScChildNew(ScAccessibleDocumentPagePreview* pAccDoc) : mpAccDoc(pAccDoc) {} void operator() (const uno::Reference& xAccessible) const { if (mpAccDoc) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::CHILD; aEvent.Source = uno::Reference< XAccessibleContext >(mpAccDoc); aEvent.NewValue <<= xAccessible; mpAccDoc->CommitChange(aEvent); // new child - event } } }; void ScNotesChildren::DataChanged(const Rectangle& rVisRect) { if (mpViewShell && mpAccDoc) { ScXAccList aNewParas; ScXAccList aOldParas; ScAccNotes aNewMarks; mnParagraphs = CheckChanges(mpViewShell->GetLocationData(), rVisRect, true, maMarks, aNewMarks, aOldParas, aNewParas); maMarks = aNewMarks; ScAccNotes aNewNotes; mnParagraphs += CheckChanges(mpViewShell->GetLocationData(), rVisRect, false, maNotes, aNewNotes, aOldParas, aNewParas); maNotes = aNewNotes; std::for_each(aOldParas.begin(), aOldParas.end(), ScChildGone(mpAccDoc)); std::for_each(aNewParas.begin(), aNewParas.end(), ScChildNew(mpAccDoc)); } } inline ScDocument* ScNotesChildren::GetDocument() const { ScDocument* pDoc = NULL; if (mpViewShell) pDoc = &mpViewShell->GetDocument(); return pDoc; } class ScIAccessibleViewForwarder : public ::accessibility::IAccessibleViewForwarder { public: ScIAccessibleViewForwarder(); ScIAccessibleViewForwarder(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc, const MapMode& aMapMode); virtual ~ScIAccessibleViewForwarder(); ///===== IAccessibleViewForwarder ======================================== virtual bool IsValid (void) const SAL_OVERRIDE; virtual Rectangle GetVisibleArea() const SAL_OVERRIDE; virtual Point LogicToPixel (const Point& rPoint) const SAL_OVERRIDE; virtual Size LogicToPixel (const Size& rSize) const SAL_OVERRIDE; virtual Point PixelToLogic (const Point& rPoint) const SAL_OVERRIDE; virtual Size PixelToLogic (const Size& rSize) const SAL_OVERRIDE; private: ScPreviewShell* mpViewShell; ScAccessibleDocumentPagePreview* mpAccDoc; MapMode maMapMode; bool mbValid; }; ScIAccessibleViewForwarder::ScIAccessibleViewForwarder() : mpViewShell(NULL), mpAccDoc(NULL), mbValid(false) { } ScIAccessibleViewForwarder::ScIAccessibleViewForwarder(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc, const MapMode& aMapMode) : mpViewShell(pViewShell), mpAccDoc(pAccDoc), maMapMode(aMapMode), mbValid(true) { } ScIAccessibleViewForwarder::~ScIAccessibleViewForwarder() { } ///===== IAccessibleViewForwarder ======================================== bool ScIAccessibleViewForwarder::IsValid (void) const { SolarMutexGuard aGuard; return mbValid; } Rectangle ScIAccessibleViewForwarder::GetVisibleArea() const { SolarMutexGuard aGuard; Rectangle aVisRect; vcl::Window* pWin = mpViewShell->GetWindow(); if (pWin) { aVisRect.SetSize(pWin->GetOutputSizePixel()); aVisRect.SetPos(Point(0, 0)); aVisRect = pWin->PixelToLogic(aVisRect, maMapMode); } return aVisRect; } Point ScIAccessibleViewForwarder::LogicToPixel (const Point& rPoint) const { SolarMutexGuard aGuard; Point aPoint; vcl::Window* pWin = mpViewShell->GetWindow(); if (pWin && mpAccDoc) { Rectangle aRect(mpAccDoc->GetBoundingBoxOnScreen()); aPoint = pWin->LogicToPixel(rPoint, maMapMode) + aRect.TopLeft(); } return aPoint; } Size ScIAccessibleViewForwarder::LogicToPixel (const Size& rSize) const { SolarMutexGuard aGuard; Size aSize; vcl::Window* pWin = mpViewShell->GetWindow(); if (pWin) aSize = pWin->LogicToPixel(rSize, maMapMode); return aSize; } Point ScIAccessibleViewForwarder::PixelToLogic (const Point& rPoint) const { SolarMutexGuard aGuard; Point aPoint; vcl::Window* pWin = mpViewShell->GetWindow(); if (pWin && mpAccDoc) { Rectangle aRect(mpAccDoc->GetBoundingBoxOnScreen()); aPoint = pWin->PixelToLogic(rPoint - aRect.TopLeft(), maMapMode); } return aPoint; } Size ScIAccessibleViewForwarder::PixelToLogic (const Size& rSize) const { SolarMutexGuard aGuard; Size aSize; vcl::Window* pWin = mpViewShell->GetWindow(); if (pWin) aSize = pWin->PixelToLogic(rSize, maMapMode); return aSize; } struct ScShapeChild { ScShapeChild() : mpAccShape(NULL) , mnRangeId(0) { } ScShapeChild(const ScShapeChild& rOld); ~ScShapeChild(); mutable ::accessibility::AccessibleShape* mpAccShape; com::sun::star::uno::Reference< com::sun::star::drawing::XShape > mxShape; sal_Int32 mnRangeId; }; ScShapeChild::ScShapeChild(const ScShapeChild& rOld) : mpAccShape(rOld.mpAccShape), mxShape(rOld.mxShape), mnRangeId(rOld.mnRangeId) { if (mpAccShape) mpAccShape->acquire(); } ScShapeChild::~ScShapeChild() { if (mpAccShape) { mpAccShape->dispose(); mpAccShape->release(); } } struct ScShapeChildLess { bool operator()(const ScShapeChild& rChild1, const ScShapeChild& rChild2) const { bool bResult(false); if (rChild1.mxShape.is() && rChild2.mxShape.is()) bResult = (rChild1.mxShape.get() < rChild2.mxShape.get()); return bResult; } }; typedef std::vector ScShapeChildVec; struct ScShapeRange { ScShapeChildVec maBackShapes; ScShapeChildVec maForeShapes; // inclusive internal shapes ScShapeChildVec maControls; Rectangle maPixelRect; MapMode maMapMode; ScIAccessibleViewForwarder maViewForwarder; }; typedef std::vector ScShapeRangeVec; class ScShapeChildren : public SfxListener, public ::accessibility::IAccessibleParent { public: ScShapeChildren(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc); virtual ~ScShapeChildren(); ///===== SfxListener ===================================================== virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) SAL_OVERRIDE; ///===== IAccessibleParent ============================================== virtual 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) SAL_OVERRIDE; ///===== Internal ======================================================== void Init(); sal_Int32 GetBackShapeCount() const; uno::Reference GetBackShape(sal_Int32 nIndex) const; sal_Int32 GetForeShapeCount() const; uno::Reference GetForeShape(sal_Int32 nIndex) const; sal_Int32 GetControlCount() const; uno::Reference GetControl(sal_Int32 nIndex) const; uno::Reference GetForegroundShapeAt(const awt::Point& rPoint) const; // inclusive controls uno::Reference GetBackgroundShapeAt(const awt::Point& rPoint) const; void DataChanged(); void VisAreaChanged() const; void SetDrawBroadcaster(); private: ScAccessibleDocumentPagePreview* mpAccDoc; ScPreviewShell* mpViewShell; ScShapeRangeVec maShapeRanges; void FindChanged(ScShapeChildVec& aOld, ScShapeChildVec& aNew) const; void FindChanged(ScShapeRange& aOld, ScShapeRange& aNew) const; ::accessibility::AccessibleShape* GetAccShape(const ScShapeChild& rShape) const; ::accessibility::AccessibleShape* GetAccShape(const ScShapeChildVec& rShapes, sal_Int32 nIndex) const; void FillShapes(const Rectangle& aPixelPaintRect, const MapMode& aMapMode, sal_uInt8 nRangeId); // void AddShape(const uno::Reference& xShape, SdrLayerID aLayerID); // void RemoveShape(const uno::Reference& xShape, SdrLayerID aLayerID); SdrPage* GetDrawPage() const; }; ScShapeChildren::ScShapeChildren(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc) : mpAccDoc(pAccDoc), mpViewShell(pViewShell), maShapeRanges(SC_PREVIEW_MAXRANGES) { if (pViewShell) { SfxBroadcaster* pDrawBC = pViewShell->GetDocument().GetDrawBroadcaster(); if (pDrawBC) StartListening(*pDrawBC); } } ScShapeChildren::~ScShapeChildren() { if (mpViewShell) { SfxBroadcaster* pDrawBC = mpViewShell->GetDocument().GetDrawBroadcaster(); if (pDrawBC) EndListening(*pDrawBC); } } void ScShapeChildren::SetDrawBroadcaster() { if (mpViewShell) { SfxBroadcaster* pDrawBC = mpViewShell->GetDocument().GetDrawBroadcaster(); if (pDrawBC) StartListening(*pDrawBC, true); } } void ScShapeChildren::Notify(SfxBroadcaster&, const SfxHint& rHint) { const SdrHint* pSdrHint = dynamic_cast( &rHint ); if (pSdrHint) { SdrObject* pObj = const_cast(pSdrHint->GetObject()); if (pObj && (pObj->GetPage() == GetDrawPage())) { switch (pSdrHint->GetKind()) { case HINT_OBJCHG : // Objekt geaendert { } break; default : { // other events are not interesting } break; } } } } void ScShapeChildren::FindChanged(ScShapeChildVec& rOld, ScShapeChildVec& rNew) const { ScShapeChildVec::iterator aOldItr = rOld.begin(); ScShapeChildVec::iterator aOldEnd = rOld.end(); ScShapeChildVec::const_iterator aNewItr = rNew.begin(); ScShapeChildVec::const_iterator aNewEnd = rNew.begin(); uno::Reference xAcc; while ((aNewItr != aNewEnd) && (aOldItr != aOldEnd)) { if (aNewItr->mxShape.get() == aOldItr->mxShape.get()) { ++aOldItr; ++aNewItr; } else if (aNewItr->mxShape.get() < aOldItr->mxShape.get()) { xAcc = GetAccShape(*aNewItr); AccessibleEventObject aEvent; aEvent.Source = uno::Reference (mpAccDoc); aEvent.EventId = AccessibleEventId::CHILD; aEvent.NewValue <<= xAcc; mpAccDoc->CommitChange(aEvent); ++aNewItr; } else { xAcc = GetAccShape(*aOldItr); AccessibleEventObject aEvent; aEvent.Source = uno::Reference (mpAccDoc); aEvent.EventId = AccessibleEventId::CHILD; aEvent.OldValue <<= xAcc; mpAccDoc->CommitChange(aEvent); ++aOldItr; } } while (aOldItr != aOldEnd) { xAcc = GetAccShape(*aOldItr); AccessibleEventObject aEvent; aEvent.Source = uno::Reference (mpAccDoc); aEvent.EventId = AccessibleEventId::CHILD; aEvent.OldValue <<= xAcc; mpAccDoc->CommitChange(aEvent); ++aOldItr; } while (aNewItr != aNewEnd) { xAcc = GetAccShape(*aNewItr); AccessibleEventObject aEvent; aEvent.Source = uno::Reference (mpAccDoc); aEvent.EventId = AccessibleEventId::CHILD; aEvent.NewValue <<= xAcc; mpAccDoc->CommitChange(aEvent); ++aNewItr; } } void ScShapeChildren::FindChanged(ScShapeRange& rOld, ScShapeRange& rNew) const { FindChanged(rOld.maBackShapes, rNew.maBackShapes); FindChanged(rOld.maForeShapes, rNew.maForeShapes); FindChanged(rOld.maControls, rNew.maControls); } void ScShapeChildren::DataChanged() { ScShapeRangeVec aOldShapeRanges(maShapeRanges); maShapeRanges.clear(); maShapeRanges.resize(SC_PREVIEW_MAXRANGES); Init(); for (sal_Int32 i = 0; i < SC_PREVIEW_MAXRANGES; ++i) { FindChanged(aOldShapeRanges[i], maShapeRanges[i]); } } namespace { struct ScVisAreaChanged { const ScIAccessibleViewForwarder* mpViewForwarder; ScVisAreaChanged(const ScIAccessibleViewForwarder* pViewForwarder) : mpViewForwarder(pViewForwarder) {} void operator() (const ScShapeChild& rAccShapeData) const { if (rAccShapeData.mpAccShape) { rAccShapeData.mpAccShape->ViewForwarderChanged(::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA, mpViewForwarder); } } }; } void ScShapeChildren::VisAreaChanged() const { ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end(); ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin(); while (aItr != aEndItr) { ScVisAreaChanged aVisAreaChanged(&(aItr->maViewForwarder)); std::for_each(aItr->maBackShapes.begin(), aItr->maBackShapes.end(), aVisAreaChanged); std::for_each(aItr->maControls.begin(), aItr->maControls.end(), aVisAreaChanged); std::for_each(aItr->maForeShapes.begin(), aItr->maForeShapes.end(), aVisAreaChanged); ++aItr; } } ///===== IAccessibleParent ============================================== bool ScShapeChildren::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) { OSL_FAIL("should not be called in the page preview"); return false; } ///===== Internal ======================================================== void ScShapeChildren::Init() { if(mpViewShell) { const ScPreviewLocationData& rData = mpViewShell->GetLocationData(); MapMode aMapMode; Rectangle aPixelPaintRect; sal_uInt8 nRangeId; sal_uInt16 nCount(rData.GetDrawRanges()); for (sal_uInt16 i = 0; i < nCount; ++i) { rData.GetDrawRange(i, aPixelPaintRect, aMapMode, nRangeId); FillShapes(aPixelPaintRect, aMapMode, nRangeId); } } } sal_Int32 ScShapeChildren::GetBackShapeCount() const { sal_Int32 nCount(0); ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end(); for ( ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin(); aItr != aEndItr; ++aItr ) nCount += aItr->maBackShapes.size(); return nCount; } uno::Reference ScShapeChildren::GetBackShape(sal_Int32 nIndex) const { uno::Reference xAccessible; ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end(); ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin(); while ((aItr != aEndItr) && !xAccessible.is()) { sal_Int32 nCount(aItr->maBackShapes.size()); if(nIndex < nCount) xAccessible = GetAccShape(aItr->maBackShapes, nIndex); else ++aItr; nIndex -= nCount; } if (nIndex >= 0) throw lang::IndexOutOfBoundsException(); return xAccessible; } sal_Int32 ScShapeChildren::GetForeShapeCount() const { sal_Int32 nCount(0); ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end(); for ( ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin(); aItr != aEndItr; ++aItr ) nCount += aItr->maForeShapes.size(); return nCount; } uno::Reference ScShapeChildren::GetForeShape(sal_Int32 nIndex) const { uno::Reference xAccessible; ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end(); ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin(); while ((aItr != aEndItr) && !xAccessible.is()) { sal_Int32 nCount(aItr->maForeShapes.size()); if(nIndex < nCount) xAccessible = GetAccShape(aItr->maForeShapes, nIndex); else ++aItr; nIndex -= nCount; } if (nIndex >= 0) throw lang::IndexOutOfBoundsException(); return xAccessible; } sal_Int32 ScShapeChildren::GetControlCount() const { sal_Int32 nCount(0); ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end(); for ( ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin(); aItr != aEndItr; ++aItr ) nCount += aItr->maControls.size(); return nCount; } uno::Reference ScShapeChildren::GetControl(sal_Int32 nIndex) const { uno::Reference xAccessible; ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end(); ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin(); while ((aItr != aEndItr) && !xAccessible.is()) { sal_Int32 nCount(aItr->maControls.size()); if(nIndex < nCount) xAccessible = GetAccShape(aItr->maControls, nIndex); else ++aItr; nIndex -= nCount; } if (nIndex >= 0) throw lang::IndexOutOfBoundsException(); return xAccessible; } struct ScShapePointFound { Point maPoint; ScShapePointFound(const awt::Point& rPoint) : maPoint(VCLPoint(rPoint)) {} bool operator() (const ScShapeChild& rShape) { bool bResult(false); if ((VCLRectangle(rShape.mpAccShape->getBounds())).IsInside(maPoint)) bResult = true; return bResult; } }; uno::Reference ScShapeChildren::GetForegroundShapeAt(const awt::Point& rPoint) const //inclusive Controls { uno::Reference xAcc; ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin(); ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end(); while((aItr != aEndItr) && !xAcc.is()) { ScShapeChildVec::const_iterator aFindItr = std::find_if(aItr->maForeShapes.begin(), aItr->maForeShapes.end(), ScShapePointFound(rPoint)); if (aFindItr != aItr->maForeShapes.end()) xAcc = GetAccShape(*aFindItr); else { ScShapeChildVec::const_iterator aCtrlItr = std::find_if(aItr->maControls.begin(), aItr->maControls.end(), ScShapePointFound(rPoint)); if (aCtrlItr != aItr->maControls.end()) xAcc = GetAccShape(*aCtrlItr); else ++aItr; } } return xAcc; } uno::Reference ScShapeChildren::GetBackgroundShapeAt(const awt::Point& rPoint) const { uno::Reference xAcc; ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin(); ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end(); while((aItr != aEndItr) && !xAcc.is()) { ScShapeChildVec::const_iterator aFindItr = std::find_if(aItr->maBackShapes.begin(), aItr->maBackShapes.end(), ScShapePointFound(rPoint)); if (aFindItr != aItr->maBackShapes.end()) xAcc = GetAccShape(*aFindItr); else ++aItr; } return xAcc; } ::accessibility::AccessibleShape* ScShapeChildren::GetAccShape(const ScShapeChild& rShape) const { if (!rShape.mpAccShape) { ::accessibility::ShapeTypeHandler& rShapeHandler = ::accessibility::ShapeTypeHandler::Instance(); ::accessibility::AccessibleShapeInfo aShapeInfo(rShape.mxShape, mpAccDoc, const_cast(this)); if (mpViewShell) { ::accessibility::AccessibleShapeTreeInfo aShapeTreeInfo; aShapeTreeInfo.SetSdrView(mpViewShell->GetPreview()->GetDrawView()); aShapeTreeInfo.SetController(NULL); aShapeTreeInfo.SetWindow(mpViewShell->GetWindow()); aShapeTreeInfo.SetViewForwarder(&(maShapeRanges[rShape.mnRangeId].maViewForwarder)); rShape.mpAccShape = rShapeHandler.CreateAccessibleObject(aShapeInfo, aShapeTreeInfo); if (rShape.mpAccShape) { rShape.mpAccShape->acquire(); rShape.mpAccShape->Init(); } } } return rShape.mpAccShape; } ::accessibility::AccessibleShape* ScShapeChildren::GetAccShape(const ScShapeChildVec& rShapes, sal_Int32 nIndex) const { return (GetAccShape(rShapes[nIndex])); } void ScShapeChildren::FillShapes(const Rectangle& aPixelPaintRect, const MapMode& aMapMode, sal_uInt8 nRangeId) { OSL_ENSURE(nRangeId < maShapeRanges.size(), "this is not a valid range for draw objects"); SdrPage* pPage = GetDrawPage(); vcl::Window* pWin = mpViewShell->GetWindow(); if (pPage && pWin) { bool bForeAdded(false); bool bBackAdded(false); bool bControlAdded(false); Rectangle aClippedPixelPaintRect(aPixelPaintRect); if (mpAccDoc) { Rectangle aRect2(Point(0,0), mpAccDoc->GetBoundingBoxOnScreen().GetSize()); aClippedPixelPaintRect = aPixelPaintRect.GetIntersection(aRect2); } maShapeRanges[nRangeId].maPixelRect = aClippedPixelPaintRect; maShapeRanges[nRangeId].maMapMode = aMapMode; ScIAccessibleViewForwarder aViewForwarder(mpViewShell, mpAccDoc, aMapMode); maShapeRanges[nRangeId].maViewForwarder = aViewForwarder; const size_t nCount(pPage->GetObjCount()); for (size_t i = 0; i < nCount; ++i) { SdrObject* pObj = pPage->GetObj(i); if (pObj) { uno::Reference< drawing::XShape > xShape(pObj->getUnoShape(), uno::UNO_QUERY); if (xShape.is()) { Rectangle aRect(pWin->LogicToPixel(VCLPoint(xShape->getPosition()), aMapMode), pWin->LogicToPixel(VCLSize(xShape->getSize()), aMapMode)); if(!aClippedPixelPaintRect.GetIntersection(aRect).IsEmpty()) { ScShapeChild aShape; aShape.mxShape = xShape; aShape.mnRangeId = nRangeId; switch (pObj->GetLayer()) { case SC_LAYER_INTERN: case SC_LAYER_FRONT: { maShapeRanges[nRangeId].maForeShapes.push_back(aShape); bForeAdded = true; } break; case SC_LAYER_BACK: { maShapeRanges[nRangeId].maBackShapes.push_back(aShape); bBackAdded = true; } break; case SC_LAYER_CONTROLS: { maShapeRanges[nRangeId].maControls.push_back(aShape); bControlAdded = true; } break; default: { OSL_FAIL("I don't know this layer."); } break; } } } } } if (bForeAdded) std::sort(maShapeRanges[nRangeId].maForeShapes.begin(), maShapeRanges[nRangeId].maForeShapes.end(),ScShapeChildLess()); if (bBackAdded) std::sort(maShapeRanges[nRangeId].maBackShapes.begin(), maShapeRanges[nRangeId].maBackShapes.end(),ScShapeChildLess()); if (bControlAdded) std::sort(maShapeRanges[nRangeId].maControls.begin(), maShapeRanges[nRangeId].maControls.end(),ScShapeChildLess()); } } SdrPage* ScShapeChildren::GetDrawPage() const { SCTAB nTab( mpViewShell->GetLocationData().GetPrintTab() ); SdrPage* pDrawPage = NULL; ScDocument& rDoc = mpViewShell->GetDocument(); if (rDoc.GetDrawLayer()) { ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer(); if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab)) pDrawPage = pDrawLayer->GetPage(static_cast(static_cast(nTab))); } return pDrawPage; } struct ScPagePreviewCountData { // order is background shapes, header, table or notes, footer, foreground shapes, controls Rectangle aVisRect; long nBackShapes; long nHeaders; long nTables; long nNoteParagraphs; long nFooters; long nForeShapes; long nControls; ScPagePreviewCountData( const ScPreviewLocationData& rData, vcl::Window* pSizeWindow, ScNotesChildren* pNotesChildren, ScShapeChildren* pShapeChildren ); long GetTotal() const { return nBackShapes + nHeaders + nTables + nNoteParagraphs + nFooters + nForeShapes + nControls; } }; ScPagePreviewCountData::ScPagePreviewCountData( const ScPreviewLocationData& rData, vcl::Window* pSizeWindow, ScNotesChildren* pNotesChildren, ScShapeChildren* pShapeChildren) : nBackShapes( 0 ), nHeaders( 0 ), nTables( 0 ), nNoteParagraphs( 0 ), nFooters( 0 ), nForeShapes( 0 ), nControls( 0 ) { Size aOutputSize; if ( pSizeWindow ) aOutputSize = pSizeWindow->GetOutputSizePixel(); Point aPoint; aVisRect = Rectangle( aPoint, aOutputSize ); Rectangle aObjRect; if ( rData.GetHeaderPosition( aObjRect ) && aObjRect.IsOver( aVisRect ) ) nHeaders = 1; if ( rData.GetFooterPosition( aObjRect ) && aObjRect.IsOver( aVisRect ) ) nFooters = 1; if ( rData.HasCellsInRange( aVisRect ) ) nTables = 1; //! shapes... nBackShapes = pShapeChildren->GetBackShapeCount(); nForeShapes = pShapeChildren->GetForeShapeCount(); nControls = pShapeChildren->GetControlCount(); // there are only notes if there is no table if (nTables == 0) nNoteParagraphs = pNotesChildren->GetChildrenCount(); } //===== internal ======================================================== ScAccessibleDocumentPagePreview::ScAccessibleDocumentPagePreview( const uno::Reference& rxParent, ScPreviewShell* pViewShell ) : ScAccessibleDocumentBase(rxParent), mpViewShell(pViewShell), mpNotesChildren(NULL), mpShapeChildren(NULL), mpTable(NULL), mpHeader(NULL), mpFooter(NULL) { if (pViewShell) pViewShell->AddAccessibilityObject(*this); } ScAccessibleDocumentPagePreview::~ScAccessibleDocumentPagePreview(void) { if (!ScAccessibleDocumentBase::IsDefunc() && !rBHelper.bInDispose) { // increment refcount to prevent double call off dtor osl_atomic_increment( &m_refCount ); // call dispose to inform object which have a weak reference to this object dispose(); } } void SAL_CALL ScAccessibleDocumentPagePreview::disposing() { SolarMutexGuard aGuard; if (mpTable) { mpTable->release(); mpTable = NULL; } if (mpHeader) { mpHeader->release(); mpHeader = NULL; } if (mpFooter) { mpFooter->release(); mpFooter = NULL; } if (mpViewShell) { mpViewShell->RemoveAccessibilityObject(*this); mpViewShell = NULL; } // no need to Dispose the AccessibleTextHelper, // as long as mpNotesChildren are destructed here if (mpNotesChildren) DELETEZ(mpNotesChildren); if (mpShapeChildren) DELETEZ(mpShapeChildren); ScAccessibleDocumentBase::disposing(); } //===== SfxListener ===================================================== void ScAccessibleDocumentPagePreview::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) { const SfxSimpleHint* pSimpleHint = dynamic_cast(&rHint); if (pSimpleHint) { // only notify if child exist, otherwise it is not necessary if (pSimpleHint->GetId() == SC_HINT_DATACHANGED) { if (mpTable) // if there is no table there is nothing to notify, because no one recongnizes the change { { uno::Reference xAcc = mpTable; AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::CHILD; aEvent.Source = uno::Reference< XAccessibleContext >(this); aEvent.OldValue <<= xAcc; CommitChange(aEvent); } mpTable->dispose(); mpTable->release(); mpTable = NULL; } Size aOutputSize; vcl::Window* pSizeWindow = mpViewShell->GetWindow(); if ( pSizeWindow ) aOutputSize = pSizeWindow->GetOutputSizePixel(); Point aPoint; Rectangle aVisRect( aPoint, aOutputSize ); GetNotesChildren()->DataChanged(aVisRect); GetShapeChildren()->DataChanged(); const ScPreviewLocationData& rData = mpViewShell->GetLocationData(); ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() ); if (aCount.nTables > 0) { //! order is background shapes, header, table or notes, footer, foreground shapes, controls sal_Int32 nIndex (aCount.nBackShapes + aCount.nHeaders); mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex ); mpTable->acquire(); mpTable->Init(); { uno::Reference xAcc = mpTable; AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::CHILD; aEvent.Source = uno::Reference< XAccessibleContext >(this); aEvent.NewValue <<= xAcc; CommitChange(aEvent); } } } else if (pSimpleHint->GetId() == SC_HINT_ACC_MAKEDRAWLAYER) { GetShapeChildren()->SetDrawBroadcaster(); } else if (pSimpleHint->GetId() == SC_HINT_ACC_VISAREACHANGED) { Size aOutputSize; vcl::Window* pSizeWindow = mpViewShell->GetWindow(); if ( pSizeWindow ) aOutputSize = pSizeWindow->GetOutputSizePixel(); Point aPoint; Rectangle aVisRect( aPoint, aOutputSize ); GetNotesChildren()->DataChanged(aVisRect); GetShapeChildren()->VisAreaChanged(); AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED; aEvent.Source = uno::Reference< XAccessibleContext >(this); CommitChange(aEvent); } } else if ( dynamic_cast(&rHint) ) { CommitFocusLost(); } else if ( dynamic_cast(&rHint) ) { CommitFocusGained(); } ScAccessibleDocumentBase::Notify(rBC, rHint); } //===== XAccessibleComponent ============================================ uno::Reference< XAccessible > SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException, std::exception) { uno::Reference xAccessible; if (containsPoint(rPoint)) { SolarMutexGuard aGuard; IsObjectValid(); if ( mpViewShell ) { xAccessible = GetShapeChildren()->GetForegroundShapeAt(rPoint); if (!xAccessible.is()) { const ScPreviewLocationData& rData = mpViewShell->GetLocationData(); ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() ); if ( !mpTable && (aCount.nTables > 0) ) { //! order is background shapes, header, table or notes, footer, foreground shapes, controls sal_Int32 nIndex (aCount.nBackShapes + aCount.nHeaders); mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex ); mpTable->acquire(); mpTable->Init(); } if (mpTable && VCLRectangle(mpTable->getBounds()).IsInside(VCLPoint(rPoint))) xAccessible = mpTable; } if (!xAccessible.is()) xAccessible = GetNotesChildren()->GetAt(rPoint); if (!xAccessible.is()) { if (!mpHeader || !mpFooter) { const ScPreviewLocationData& rData = mpViewShell->GetLocationData(); ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() ); if (!mpHeader) { mpHeader = new ScAccessiblePageHeader( this, mpViewShell, true, aCount.nBackShapes + aCount.nHeaders - 1); mpHeader->acquire(); } if (!mpFooter) { mpFooter = new ScAccessiblePageHeader( this, mpViewShell, false, aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters - 1 ); mpFooter->acquire(); } } Point aPoint(VCLPoint(rPoint)); if (VCLRectangle(mpHeader->getBounds()).IsInside(aPoint)) xAccessible = mpHeader; else if (VCLRectangle(mpFooter->getBounds()).IsInside(aPoint)) xAccessible = mpFooter; } if (!xAccessible.is()) xAccessible = GetShapeChildren()->GetBackgroundShapeAt(rPoint); } } return xAccessible; } void SAL_CALL ScAccessibleDocumentPagePreview::grabFocus() throw (uno::RuntimeException, std::exception) { SolarMutexGuard aGuard; IsObjectValid(); if (getAccessibleParent().is()) { uno::Reference xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY); if (xAccessibleComponent.is()) { // just grab the focus for the window xAccessibleComponent->grabFocus(); } } } //===== XAccessibleContext ============================================== sal_Int32 SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleChildCount() throw (uno::RuntimeException, std::exception) { SolarMutexGuard aGuard; IsObjectValid(); long nRet = 0; if ( mpViewShell ) { ScPagePreviewCountData aCount( mpViewShell->GetLocationData(), mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() ); nRet = aCount.GetTotal(); } return nRet; } uno::Reference SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleChild(sal_Int32 nIndex) throw (uno::RuntimeException, lang::IndexOutOfBoundsException, std::exception) { SolarMutexGuard aGuard; IsObjectValid(); uno::Reference xAccessible; if ( mpViewShell ) { const ScPreviewLocationData& rData = mpViewShell->GetLocationData(); ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() ); if ( nIndex < aCount.nBackShapes ) { xAccessible = GetShapeChildren()->GetBackShape(nIndex); } else if ( nIndex < aCount.nBackShapes + aCount.nHeaders ) { if ( !mpHeader ) { mpHeader = new ScAccessiblePageHeader( this, mpViewShell, true, nIndex ); mpHeader->acquire(); } xAccessible = mpHeader; } else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nTables ) { if ( !mpTable ) { mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex ); mpTable->acquire(); mpTable->Init(); } xAccessible = mpTable; } else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nNoteParagraphs ) { xAccessible = GetNotesChildren()->GetChild(nIndex - aCount.nBackShapes - aCount.nHeaders); } else if ( (nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters) ) { if ( !mpFooter ) { mpFooter = new ScAccessiblePageHeader( this, mpViewShell, false, nIndex ); mpFooter->acquire(); } xAccessible = mpFooter; } else { sal_Int32 nIdx(nIndex - (aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters)); if (nIdx < aCount.nForeShapes) xAccessible = GetShapeChildren()->GetForeShape(nIdx); else xAccessible = GetShapeChildren()->GetControl(nIdx - aCount.nForeShapes); } } if ( !xAccessible.is() ) throw lang::IndexOutOfBoundsException(); return xAccessible; } /// Return the set of current states. uno::Reference SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleStateSet(void) throw (uno::RuntimeException, std::exception) { SolarMutexGuard aGuard; uno::Reference xParentStates; if (getAccessibleParent().is()) { uno::Reference xParentContext = getAccessibleParent()->getAccessibleContext(); xParentStates = xParentContext->getAccessibleStateSet(); } utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper(); if (IsDefunc(xParentStates)) pStateSet->AddState(AccessibleStateType::DEFUNC); else { // never editable pStateSet->AddState(AccessibleStateType::ENABLED); pStateSet->AddState(AccessibleStateType::OPAQUE); if (isShowing()) pStateSet->AddState(AccessibleStateType::SHOWING); if (isVisible()) pStateSet->AddState(AccessibleStateType::VISIBLE); } return pStateSet; } //===== XServiceInfo ==================================================== OUString SAL_CALL ScAccessibleDocumentPagePreview::getImplementationName(void) throw (uno::RuntimeException, std::exception) { return OUString("ScAccessibleDocumentPagePreview"); } uno::Sequence< OUString> SAL_CALL ScAccessibleDocumentPagePreview::getSupportedServiceNames(void) throw (uno::RuntimeException, std::exception) { uno::Sequence< OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames(); sal_Int32 nOldSize(aSequence.getLength()); aSequence.realloc(nOldSize + 1); aSequence[nOldSize] = "com.sun.star.AccessibleSpreadsheetPageView"; return aSequence; } //===== XTypeProvider ======================================================= uno::Sequence SAL_CALL ScAccessibleDocumentPagePreview::getImplementationId(void) throw (uno::RuntimeException, std::exception) { return css::uno::Sequence(); } //===== internal ======================================================== OUString SAL_CALL ScAccessibleDocumentPagePreview::createAccessibleDescription(void) throw (uno::RuntimeException) { OUString sDescription = OUString(ScResId(STR_ACC_PREVIEWDOC_DESCR)); return sDescription; } OUString SAL_CALL ScAccessibleDocumentPagePreview::createAccessibleName(void) throw (uno::RuntimeException, std::exception) { OUString sName = OUString(ScResId(STR_ACC_PREVIEWDOC_NAME)); return sName; } Rectangle ScAccessibleDocumentPagePreview::GetBoundingBoxOnScreen() const throw (uno::RuntimeException, std::exception) { Rectangle aRect; if (mpViewShell) { vcl::Window* pWindow = mpViewShell->GetWindow(); if (pWindow) aRect = pWindow->GetWindowExtentsRelative(NULL); } return aRect; } Rectangle ScAccessibleDocumentPagePreview::GetBoundingBox() const throw (uno::RuntimeException, std::exception) { Rectangle aRect; if (mpViewShell) { vcl::Window* pWindow = mpViewShell->GetWindow(); if (pWindow) aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow()); } return aRect; } bool ScAccessibleDocumentPagePreview::IsDefunc( const uno::Reference& rxParentStates) { return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() || (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC)); } ScNotesChildren* ScAccessibleDocumentPagePreview::GetNotesChildren() { if (!mpNotesChildren && mpViewShell) { mpNotesChildren = new ScNotesChildren(mpViewShell, this); const ScPreviewLocationData& rData = mpViewShell->GetLocationData(); ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() ); //! order is background shapes, header, table or notes, footer, foreground shapes, controls mpNotesChildren->Init(aCount.aVisRect, aCount.nBackShapes + aCount.nHeaders); } return mpNotesChildren; } ScShapeChildren* ScAccessibleDocumentPagePreview::GetShapeChildren() { if (!mpShapeChildren && mpViewShell) { mpShapeChildren = new ScShapeChildren(mpViewShell, this); mpShapeChildren->Init(); } return mpShapeChildren; } OUString ScAccessibleDocumentPagePreview::getAccessibleName(void) throw (::com::sun::star::uno::RuntimeException, std::exception) { SolarMutexGuard g; OUString aName = ScResId(STR_ACC_DOC_SPREADSHEET); ScDocument& rScDoc = mpViewShell->GetDocument(); SfxObjectShell* pObjSh = rScDoc.GetDocumentShell(); if (!pObjSh) return aName; OUString aFileName; SfxMedium* pMed = pObjSh->GetMedium(); if (pMed) aFileName = pMed->GetName(); if (aFileName.isEmpty()) aFileName = pObjSh->GetTitle(SFX_TITLE_APINAME); if (!aFileName.isEmpty()) { aName = aFileName + " - " + aName; aName += ScResId(STR_ACC_DOC_PREVIEW_SUFFIX); } return aName; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */