nss: upgrade to release 3.73
[LibreOffice.git] / sc / source / ui / Accessibility / AccessibleDocumentPagePreview.cxx
blob568b4a2c59ee03410d3322b1dd4a91d943f40921
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <AccessibleDocumentPagePreview.hxx>
21 #include <AccessiblePreviewTable.hxx>
22 #include <AccessiblePageHeader.hxx>
23 #include <AccessibilityHints.hxx>
24 #include <AccessibleText.hxx>
25 #include <document.hxx>
26 #include <prevwsh.hxx>
27 #include <prevloc.hxx>
28 #include <drwlayer.hxx>
29 #include <editsrc.hxx>
30 #include <scresid.hxx>
31 #include <strings.hrc>
32 #include <strings.hxx>
33 #include <preview.hxx>
34 #include <postit.hxx>
36 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
37 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
38 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
40 #include <unotools/accessiblestatesethelper.hxx>
41 #include <tools/gen.hxx>
42 #include <svx/fmview.hxx>
43 #include <svx/svdpage.hxx>
44 #include <svx/svdobj.hxx>
45 #include <svx/AccessibleTextHelper.hxx>
46 #include <svx/AccessibleShape.hxx>
47 #include <svx/AccessibleShapeInfo.hxx>
48 #include <svx/IAccessibleParent.hxx>
49 #include <svx/IAccessibleViewForwarder.hxx>
50 #include <svx/ShapeTypeHandler.hxx>
51 #include <toolkit/helper/convert.hxx>
52 #include <vcl/svapp.hxx>
53 #include <sfx2/docfile.hxx>
55 #include <vector>
56 #include <algorithm>
57 #include <memory>
58 #include <utility>
60 using namespace ::com::sun::star;
61 using namespace ::com::sun::star::accessibility;
63 typedef std::vector< uno::Reference< XAccessible > > ScXAccVector;
65 namespace {
67 struct ScAccNote
69 OUString maNoteText;
70 tools::Rectangle maRect;
71 ScAddress maNoteCell;
72 ::accessibility::AccessibleTextHelper* mpTextHelper;
73 sal_Int32 mnParaCount;
74 bool mbMarkNote;
76 ScAccNote()
77 : mpTextHelper(nullptr)
78 , mnParaCount(0)
79 , mbMarkNote(false)
86 class ScNotesChildren
88 public:
89 ScNotesChildren(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc);
90 ~ScNotesChildren();
91 void Init(const tools::Rectangle& rVisRect, sal_Int32 nOffset);
93 sal_Int32 GetChildrenCount() const { return mnParagraphs;}
94 uno::Reference<XAccessible> GetChild(sal_Int32 nIndex) const;
95 uno::Reference<XAccessible> GetAt(const awt::Point& rPoint) const;
97 void DataChanged(const tools::Rectangle& rVisRect);
99 private:
100 ScPreviewShell* mpViewShell;
101 ScAccessibleDocumentPagePreview* mpAccDoc;
102 typedef std::vector<ScAccNote> ScAccNotes;
103 mutable ScAccNotes maNotes;
104 mutable ScAccNotes maMarks;
105 sal_Int32 mnParagraphs;
106 sal_Int32 mnOffset;
108 ::accessibility::AccessibleTextHelper* CreateTextHelper(const OUString& rString, const tools::Rectangle& rVisRect, const ScAddress& aCellPos, bool bMarkNote, sal_Int32 nChildOffset) const;
109 sal_Int32 AddNotes(const ScPreviewLocationData& rData, const tools::Rectangle& rVisRect, bool bMark, ScAccNotes& rNotes);
111 static sal_Int8 CompareCell(const ScAddress& aCell1, const ScAddress& aCell2);
112 static void CollectChildren(const ScAccNote& rNote, ScXAccVector& rVector);
113 sal_Int32 CheckChanges(const ScPreviewLocationData& rData, const tools::Rectangle& rVisRect,
114 bool bMark, ScAccNotes& rOldNotes, ScAccNotes& rNewNotes,
115 ScXAccVector& rOldParas, ScXAccVector& rNewParas);
117 inline ScDocument* GetDocument() const;
120 ScNotesChildren::ScNotesChildren(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc)
121 : mpViewShell(pViewShell),
122 mpAccDoc(pAccDoc),
123 mnParagraphs(0),
124 mnOffset(0)
128 ScNotesChildren::~ScNotesChildren()
130 for (auto & i : maNotes)
131 if (i.mpTextHelper)
133 delete i.mpTextHelper;
134 i.mpTextHelper = nullptr;
136 for (auto & i : maMarks)
137 if (i.mpTextHelper)
139 delete i.mpTextHelper;
140 i.mpTextHelper = nullptr;
144 ::accessibility::AccessibleTextHelper* ScNotesChildren::CreateTextHelper(const OUString& rString, const tools::Rectangle& rVisRect, const ScAddress& aCellPos, bool bMarkNote, sal_Int32 nChildOffset) const
146 ::accessibility::AccessibleTextHelper* pTextHelper = new ::accessibility::AccessibleTextHelper(std::make_unique<ScAccessibilityEditSource>(std::make_unique<ScAccessibleNoteTextData>(mpViewShell, rString, aCellPos, bMarkNote)));
147 pTextHelper->SetEventSource(mpAccDoc);
148 pTextHelper->SetStartIndex(nChildOffset);
149 pTextHelper->SetOffset(rVisRect.TopLeft());
151 return pTextHelper;
154 sal_Int32 ScNotesChildren::AddNotes(const ScPreviewLocationData& rData, const tools::Rectangle& rVisRect, bool bMark, ScAccNotes& rNotes)
156 sal_Int32 nCount = rData.GetNoteCountInRange(rVisRect, bMark);
158 rNotes.reserve(nCount);
160 sal_Int32 nParagraphs(0);
161 ScDocument* pDoc = GetDocument();
162 if (pDoc)
164 ScAccNote aNote;
165 aNote.mbMarkNote = bMark;
166 if (bMark)
167 aNote.mnParaCount = 1;
168 for (sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex)
170 if (rData.GetNoteInRange(rVisRect, nIndex, bMark, aNote.maNoteCell, aNote.maRect))
172 if (bMark)
174 // Document not needed, because only the cell address, but not the tablename is needed
175 aNote.maNoteText = aNote.maNoteCell.Format(ScRefFlags::VALID);
177 else
179 if( ScPostIt* pNote = pDoc->GetNote( aNote.maNoteCell ) )
180 aNote.maNoteText = pNote->GetText();
181 aNote.mpTextHelper = CreateTextHelper(aNote.maNoteText, aNote.maRect, aNote.maNoteCell, aNote.mbMarkNote, nParagraphs + mnOffset);
182 if (aNote.mpTextHelper)
183 aNote.mnParaCount = aNote.mpTextHelper->GetChildCount();
185 nParagraphs += aNote.mnParaCount;
186 rNotes.push_back(aNote);
190 return nParagraphs;
193 void ScNotesChildren::Init(const tools::Rectangle& rVisRect, sal_Int32 nOffset)
195 if (mpViewShell && !mnParagraphs)
197 mnOffset = nOffset;
198 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
200 mnParagraphs = AddNotes(rData, rVisRect, false, maMarks);
201 mnParagraphs += AddNotes(rData, rVisRect, true, maNotes);
205 namespace {
207 struct ScParaFound
209 sal_Int32 mnIndex;
210 explicit ScParaFound(sal_Int32 nIndex) : mnIndex(nIndex) {}
211 bool operator() (const ScAccNote& rNote)
213 bool bResult(false);
214 if (rNote.mnParaCount > mnIndex)
215 bResult = true;
216 else
217 mnIndex -= rNote.mnParaCount;
218 return bResult;
224 uno::Reference<XAccessible> ScNotesChildren::GetChild(sal_Int32 nIndex) const
226 uno::Reference<XAccessible> xAccessible;
228 if (nIndex < mnParagraphs)
230 if (nIndex < static_cast<sal_Int32>(maMarks.size()))
232 ScAccNotes::iterator aEndItr = maMarks.end();
233 ScParaFound aParaFound(nIndex);
234 ScAccNotes::iterator aItr = std::find_if(maMarks.begin(), aEndItr, aParaFound);
235 if (aItr != aEndItr)
237 OSL_ENSURE((aItr->maNoteCell == maMarks[nIndex].maNoteCell) && (aItr->mbMarkNote == maMarks[nIndex].mbMarkNote), "wrong note found");
238 if (!aItr->mpTextHelper)
239 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
240 xAccessible = aItr->mpTextHelper->GetChild(aParaFound.mnIndex + aItr->mpTextHelper->GetStartIndex());
242 else
244 OSL_FAIL("wrong note found");
247 else
249 nIndex -= maMarks.size();
250 ScAccNotes::iterator aEndItr = maNotes.end();
251 ScParaFound aParaFound(nIndex);
252 ScAccNotes::iterator aItr = std::find_if(maNotes.begin(), aEndItr, aParaFound);
253 if (aEndItr != aItr)
255 if (!aItr->mpTextHelper)
256 aItr->mpTextHelper = CreateTextHelper(aItr->maNoteText, aItr->maRect, aItr->maNoteCell, aItr->mbMarkNote, (nIndex - aParaFound.mnIndex) + mnOffset + maMarks.size());
257 xAccessible = aItr->mpTextHelper->GetChild(aParaFound.mnIndex + aItr->mpTextHelper->GetStartIndex());
262 return xAccessible;
265 namespace {
267 struct ScPointFound
269 tools::Rectangle maPoint;
270 sal_Int32 mnParagraphs;
271 explicit ScPointFound(const Point& rPoint) : maPoint(rPoint, Size(0, 0)), mnParagraphs(0) {}
272 bool operator() (const ScAccNote& rNote)
274 bool bResult(false);
275 if (maPoint.IsInside(rNote.maRect))
276 bResult = true;
277 else
278 mnParagraphs += rNote.mnParaCount;
279 return bResult;
285 uno::Reference<XAccessible> ScNotesChildren::GetAt(const awt::Point& rPoint) const
287 uno::Reference<XAccessible> xAccessible;
289 ScPointFound aPointFound(Point(rPoint.X, rPoint.Y));
291 ScAccNotes::iterator aEndItr = maMarks.end();
292 ScAccNotes::iterator aItr = std::find_if(maMarks.begin(), aEndItr, aPointFound);
293 if (aEndItr == aItr)
295 aEndItr = maNotes.end();
296 aItr = std::find_if(maNotes.begin(), aEndItr, aPointFound);
298 if (aEndItr != aItr)
300 if (!aItr->mpTextHelper)
301 aItr->mpTextHelper = CreateTextHelper(aItr->maNoteText, aItr->maRect, aItr->maNoteCell, aItr->mbMarkNote, aPointFound.mnParagraphs + mnOffset);
302 xAccessible = aItr->mpTextHelper->GetAt(rPoint);
305 return xAccessible;
308 sal_Int8 ScNotesChildren::CompareCell(const ScAddress& aCell1, const ScAddress& aCell2)
310 OSL_ENSURE(aCell1.Tab() == aCell2.Tab(), "the notes should be on the same table");
311 sal_Int8 nResult(0);
312 if (aCell1 != aCell2)
314 if (aCell1.Row() == aCell2.Row())
315 nResult = (aCell1.Col() < aCell2.Col()) ? -1 : 1;
316 else
317 nResult = (aCell1.Row() < aCell2.Row()) ? -1 : 1;
319 return nResult;
322 void ScNotesChildren::CollectChildren(const ScAccNote& rNote, ScXAccVector& rVector)
324 if (rNote.mpTextHelper)
325 for (sal_Int32 i = 0; i < rNote.mnParaCount; ++i)
326 rVector.push_back(rNote.mpTextHelper->GetChild(i + rNote.mpTextHelper->GetStartIndex()));
329 sal_Int32 ScNotesChildren::CheckChanges(const ScPreviewLocationData& rData,
330 const tools::Rectangle& rVisRect, bool bMark, ScAccNotes& rOldNotes,
331 ScAccNotes& rNewNotes, ScXAccVector& rOldParas, ScXAccVector& rNewParas)
333 sal_Int32 nCount = rData.GetNoteCountInRange(rVisRect, bMark);
335 rNewNotes.reserve(nCount);
337 sal_Int32 nParagraphs(0);
338 ScDocument* pDoc = GetDocument();
339 if (pDoc)
341 ScAccNote aNote;
342 aNote.mbMarkNote = bMark;
343 if (bMark)
344 aNote.mnParaCount = 1;
345 ScAccNotes::iterator aItr = rOldNotes.begin();
346 ScAccNotes::iterator aEndItr = rOldNotes.end();
347 bool bAddNote(false);
348 for (sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex)
350 if (rData.GetNoteInRange(rVisRect, nIndex, bMark, aNote.maNoteCell, aNote.maRect))
352 if (bMark)
354 // Document not needed, because only the cell address, but not the tablename is needed
355 aNote.maNoteText = aNote.maNoteCell.Format(ScRefFlags::VALID);
357 else
359 if( ScPostIt* pNote = pDoc->GetNote( aNote.maNoteCell ) )
360 aNote.maNoteText = pNote->GetText();
363 sal_Int8 nCompare(-1); // if there are no more old children it is always a new one
364 if (aItr != aEndItr)
365 nCompare = CompareCell(aNote.maNoteCell, aItr->maNoteCell);
366 if (nCompare == 0)
368 if (aNote.maNoteText == aItr->maNoteText)
370 aNote.mpTextHelper = aItr->mpTextHelper;
371 if (aNote.maRect != aItr->maRect) // set new VisArea
373 aNote.mpTextHelper->SetOffset(aNote.maRect.TopLeft());
374 aNote.mpTextHelper->UpdateChildren();
375 //OSL_ENSURE(aItr->maRect.GetSize() == aNote.maRect.GetSize(), "size should be the same, because the text is not changed");
376 // could be changed, because only a part of the note is visible
379 else
381 aNote.mpTextHelper = CreateTextHelper(aNote.maNoteText, aNote.maRect, aNote.maNoteCell, aNote.mbMarkNote, nParagraphs + mnOffset);
382 if (aNote.mpTextHelper)
383 aNote.mnParaCount = aNote.mpTextHelper->GetChildCount();
384 // collect removed children
385 CollectChildren(*aItr, rOldParas);
386 delete aItr->mpTextHelper;
387 aItr->mpTextHelper = nullptr;;
388 // collect new children
389 CollectChildren(aNote, rNewParas);
391 bAddNote = true;
392 // not necessary, because this branch should not be reached if it is the end
393 //if (aItr != aEndItr)
394 ++aItr;
396 else if (nCompare < 0)
398 aNote.mpTextHelper = CreateTextHelper(aNote.maNoteText, aNote.maRect, aNote.maNoteCell, aNote.mbMarkNote, nParagraphs + mnOffset);
399 if (aNote.mpTextHelper)
400 aNote.mnParaCount = aNote.mpTextHelper->GetChildCount();
401 // collect new children
402 CollectChildren(aNote, rNewParas);
403 bAddNote = true;
405 else
407 // collect removed children
408 CollectChildren(*aItr, rOldParas);
409 delete aItr->mpTextHelper;
410 aItr->mpTextHelper = nullptr;
412 // no note to add
413 // not necessary, because this branch should not be reached if it is the end
414 //if (aItr != aEndItr)
415 ++aItr;
417 if (bAddNote)
419 nParagraphs += aNote.mnParaCount;
420 rNewNotes.push_back(aNote);
421 bAddNote = false;
426 return nParagraphs;
429 namespace {
431 struct ScChildGone
433 ScAccessibleDocumentPagePreview* mpAccDoc;
434 explicit ScChildGone(ScAccessibleDocumentPagePreview* pAccDoc) : mpAccDoc(pAccDoc) {}
435 void operator() (const uno::Reference<XAccessible>& xAccessible) const
437 if (mpAccDoc)
439 AccessibleEventObject aEvent;
440 aEvent.EventId = AccessibleEventId::CHILD;
441 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccDoc);
442 aEvent.OldValue <<= xAccessible;
444 mpAccDoc->CommitChange(aEvent); // gone child - event
449 struct ScChildNew
451 ScAccessibleDocumentPagePreview* mpAccDoc;
452 explicit ScChildNew(ScAccessibleDocumentPagePreview* pAccDoc) : mpAccDoc(pAccDoc) {}
453 void operator() (const uno::Reference<XAccessible>& xAccessible) const
455 if (mpAccDoc)
457 AccessibleEventObject aEvent;
458 aEvent.EventId = AccessibleEventId::CHILD;
459 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccDoc);
460 aEvent.NewValue <<= xAccessible;
462 mpAccDoc->CommitChange(aEvent); // new child - event
469 void ScNotesChildren::DataChanged(const tools::Rectangle& rVisRect)
471 if (!(mpViewShell && mpAccDoc))
472 return;
474 ScXAccVector aNewParas;
475 ScXAccVector aOldParas;
476 ScAccNotes aNewMarks;
477 mnParagraphs = CheckChanges(mpViewShell->GetLocationData(), rVisRect, true, maMarks, aNewMarks, aOldParas, aNewParas);
478 maMarks = aNewMarks;
479 ScAccNotes aNewNotes;
480 mnParagraphs += CheckChanges(mpViewShell->GetLocationData(), rVisRect, false, maNotes, aNewNotes, aOldParas, aNewParas);
481 maNotes = aNewNotes;
483 std::for_each(aOldParas.begin(), aOldParas.end(), ScChildGone(mpAccDoc));
484 std::for_each(aNewParas.begin(), aNewParas.end(), ScChildNew(mpAccDoc));
487 inline ScDocument* ScNotesChildren::GetDocument() const
489 ScDocument* pDoc = nullptr;
490 if (mpViewShell)
491 pDoc = &mpViewShell->GetDocument();
492 return pDoc;
495 namespace {
497 class ScIAccessibleViewForwarder : public ::accessibility::IAccessibleViewForwarder
499 public:
500 ScIAccessibleViewForwarder();
501 ScIAccessibleViewForwarder(ScPreviewShell* pViewShell,
502 ScAccessibleDocumentPagePreview* pAccDoc,
503 const MapMode& aMapMode);
505 ///===== IAccessibleViewForwarder ========================================
507 virtual tools::Rectangle GetVisibleArea() const override;
508 virtual Point LogicToPixel (const Point& rPoint) const override;
509 virtual Size LogicToPixel (const Size& rSize) const override;
511 private:
512 ScPreviewShell* mpViewShell;
513 ScAccessibleDocumentPagePreview* mpAccDoc;
514 MapMode maMapMode;
519 ScIAccessibleViewForwarder::ScIAccessibleViewForwarder()
520 : mpViewShell(nullptr), mpAccDoc(nullptr)
524 ScIAccessibleViewForwarder::ScIAccessibleViewForwarder(ScPreviewShell* pViewShell,
525 ScAccessibleDocumentPagePreview* pAccDoc,
526 const MapMode& aMapMode)
527 : mpViewShell(pViewShell),
528 mpAccDoc(pAccDoc),
529 maMapMode(aMapMode)
533 ///===== IAccessibleViewForwarder ========================================
535 tools::Rectangle ScIAccessibleViewForwarder::GetVisibleArea() const
537 SolarMutexGuard aGuard;
538 tools::Rectangle aVisRect;
539 vcl::Window* pWin = mpViewShell->GetWindow();
540 if (pWin)
542 aVisRect.SetSize(pWin->GetOutputSizePixel());
543 aVisRect.SetPos(Point(0, 0));
545 aVisRect = pWin->PixelToLogic(aVisRect, maMapMode);
548 return aVisRect;
551 Point ScIAccessibleViewForwarder::LogicToPixel (const Point& rPoint) const
553 SolarMutexGuard aGuard;
554 Point aPoint;
555 vcl::Window* pWin = mpViewShell->GetWindow();
556 if (pWin && mpAccDoc)
558 tools::Rectangle aRect(mpAccDoc->GetBoundingBoxOnScreen());
559 aPoint = pWin->LogicToPixel(rPoint, maMapMode) + aRect.TopLeft();
562 return aPoint;
565 Size ScIAccessibleViewForwarder::LogicToPixel (const Size& rSize) const
567 SolarMutexGuard aGuard;
568 Size aSize;
569 vcl::Window* pWin = mpViewShell->GetWindow();
570 if (pWin)
571 aSize = pWin->LogicToPixel(rSize, maMapMode);
572 return aSize;
575 namespace {
577 struct ScShapeChild
579 ScShapeChild()
580 : mnRangeId(0)
583 ScShapeChild(ScShapeChild const &) = delete;
584 ScShapeChild(ScShapeChild &&) = default;
585 ~ScShapeChild();
586 ScShapeChild & operator =(ScShapeChild const &) = delete;
587 ScShapeChild & operator =(ScShapeChild && other) {
588 std::swap(mpAccShape, other.mpAccShape);
589 mxShape = std::move(other.mxShape);
590 mnRangeId = other.mnRangeId;
591 return *this;
594 mutable rtl::Reference< ::accessibility::AccessibleShape > mpAccShape;
595 css::uno::Reference< css::drawing::XShape > mxShape;
596 sal_Int32 mnRangeId;
601 ScShapeChild::~ScShapeChild()
603 if (mpAccShape.is())
605 mpAccShape->dispose();
609 namespace {
611 struct ScShapeChildLess
613 bool operator()(const ScShapeChild& rChild1, const ScShapeChild& rChild2) const
615 bool bResult(false);
616 if (rChild1.mxShape.is() && rChild2.mxShape.is())
617 bResult = (rChild1.mxShape.get() < rChild2.mxShape.get());
618 return bResult;
624 typedef std::vector<ScShapeChild> ScShapeChildVec;
626 namespace {
628 struct ScShapeRange
630 ScShapeRange() = default;
631 ScShapeRange(ScShapeRange const &) = delete;
632 ScShapeRange(ScShapeRange &&) = default;
633 ScShapeRange & operator =(ScShapeRange const &) = delete;
634 ScShapeRange & operator =(ScShapeRange &&) = default;
636 ScShapeChildVec maBackShapes;
637 ScShapeChildVec maForeShapes; // inclusive internal shapes
638 ScShapeChildVec maControls;
639 ScIAccessibleViewForwarder maViewForwarder;
644 typedef std::vector<ScShapeRange> ScShapeRangeVec;
646 class ScShapeChildren : public ::accessibility::IAccessibleParent
648 public:
649 ScShapeChildren(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc);
651 ///===== IAccessibleParent ==============================================
653 virtual bool ReplaceChild (
654 ::accessibility::AccessibleShape* pCurrentChild,
655 const css::uno::Reference< css::drawing::XShape >& _rxShape,
656 const tools::Long _nIndex,
657 const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo
658 ) override;
660 ///===== Internal ========================================================
662 void Init();
664 sal_Int32 GetBackShapeCount() const;
665 uno::Reference<XAccessible> GetBackShape(sal_Int32 nIndex) const;
666 sal_Int32 GetForeShapeCount() const;
667 uno::Reference<XAccessible> GetForeShape(sal_Int32 nIndex) const;
668 sal_Int32 GetControlCount() const;
669 uno::Reference<XAccessible> GetControl(sal_Int32 nIndex) const;
670 uno::Reference<XAccessible> GetForegroundShapeAt(const awt::Point& rPoint) const; // inclusive controls
671 uno::Reference<XAccessible> GetBackgroundShapeAt(const awt::Point& rPoint) const;
673 void DataChanged();
674 void VisAreaChanged() const;
676 private:
677 ScAccessibleDocumentPagePreview* mpAccDoc;
678 ScPreviewShell* mpViewShell;
679 ScShapeRangeVec maShapeRanges;
681 void FindChanged(ScShapeChildVec& aOld, ScShapeChildVec& aNew) const;
682 void FindChanged(ScShapeRange& aOld, ScShapeRange& aNew) const;
683 ::accessibility::AccessibleShape* GetAccShape(const ScShapeChild& rShape) const;
684 ::accessibility::AccessibleShape* GetAccShape(const ScShapeChildVec& rShapes, sal_Int32 nIndex) const;
685 void FillShapes(const tools::Rectangle& aPixelPaintRect, const MapMode& aMapMode, sal_uInt8 nRangeId);
687 // void AddShape(const uno::Reference<drawing::XShape>& xShape, SdrLayerID aLayerID);
688 // void RemoveShape(const uno::Reference<drawing::XShape>& xShape, SdrLayerID aLayerID);
689 SdrPage* GetDrawPage() const;
692 ScShapeChildren::ScShapeChildren(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc)
694 mpAccDoc(pAccDoc),
695 mpViewShell(pViewShell),
696 maShapeRanges(SC_PREVIEW_MAXRANGES)
700 void ScShapeChildren::FindChanged(ScShapeChildVec& rOld, ScShapeChildVec& rNew) const
702 ScShapeChildVec::iterator aOldItr = rOld.begin();
703 ScShapeChildVec::iterator aOldEnd = rOld.end();
704 ScShapeChildVec::const_iterator aNewItr = rNew.begin();
705 ScShapeChildVec::const_iterator aNewEnd = rNew.end();
706 uno::Reference<XAccessible> xAcc;
707 while ((aNewItr != aNewEnd) && (aOldItr != aOldEnd))
709 if (aNewItr->mxShape.get() == aOldItr->mxShape.get())
711 ++aOldItr;
712 ++aNewItr;
714 else if (aNewItr->mxShape.get() < aOldItr->mxShape.get())
716 xAcc = GetAccShape(*aNewItr);
717 AccessibleEventObject aEvent;
718 aEvent.Source = uno::Reference<XAccessibleContext> (mpAccDoc);
719 aEvent.EventId = AccessibleEventId::CHILD;
720 aEvent.NewValue <<= xAcc;
721 mpAccDoc->CommitChange(aEvent);
722 ++aNewItr;
724 else
726 xAcc = GetAccShape(*aOldItr);
727 AccessibleEventObject aEvent;
728 aEvent.Source = uno::Reference<XAccessibleContext> (mpAccDoc);
729 aEvent.EventId = AccessibleEventId::CHILD;
730 aEvent.OldValue <<= xAcc;
731 mpAccDoc->CommitChange(aEvent);
732 ++aOldItr;
735 while (aOldItr != aOldEnd)
737 xAcc = GetAccShape(*aOldItr);
738 AccessibleEventObject aEvent;
739 aEvent.Source = uno::Reference<XAccessibleContext> (mpAccDoc);
740 aEvent.EventId = AccessibleEventId::CHILD;
741 aEvent.OldValue <<= xAcc;
742 mpAccDoc->CommitChange(aEvent);
743 ++aOldItr;
745 while (aNewItr != aNewEnd)
747 xAcc = GetAccShape(*aNewItr);
748 AccessibleEventObject aEvent;
749 aEvent.Source = uno::Reference<XAccessibleContext> (mpAccDoc);
750 aEvent.EventId = AccessibleEventId::CHILD;
751 aEvent.NewValue <<= xAcc;
752 mpAccDoc->CommitChange(aEvent);
753 ++aNewItr;
757 void ScShapeChildren::FindChanged(ScShapeRange& rOld, ScShapeRange& rNew) const
759 FindChanged(rOld.maBackShapes, rNew.maBackShapes);
760 FindChanged(rOld.maForeShapes, rNew.maForeShapes);
761 FindChanged(rOld.maControls, rNew.maControls);
764 void ScShapeChildren::DataChanged()
766 ScShapeRangeVec aOldShapeRanges(std::move(maShapeRanges));
767 maShapeRanges.clear();
768 maShapeRanges.resize(SC_PREVIEW_MAXRANGES);
769 Init();
770 for (sal_Int32 i = 0; i < SC_PREVIEW_MAXRANGES; ++i)
772 FindChanged(aOldShapeRanges[i], maShapeRanges[i]);
776 namespace
778 struct ScVisAreaChanged
780 void operator() (const ScShapeChild& rAccShapeData) const
782 if (rAccShapeData.mpAccShape.is())
784 rAccShapeData.mpAccShape->ViewForwarderChanged();
790 void ScShapeChildren::VisAreaChanged() const
792 for (auto const& shape : maShapeRanges)
794 ScVisAreaChanged aVisAreaChanged;
795 std::for_each(shape.maBackShapes.begin(), shape.maBackShapes.end(), aVisAreaChanged);
796 std::for_each(shape.maControls.begin(), shape.maControls.end(), aVisAreaChanged);
797 std::for_each(shape.maForeShapes.begin(), shape.maForeShapes.end(), aVisAreaChanged);
801 ///===== IAccessibleParent ==============================================
803 bool ScShapeChildren::ReplaceChild (::accessibility::AccessibleShape* /* pCurrentChild */,
804 const css::uno::Reference< css::drawing::XShape >& /* _rxShape */,
805 const tools::Long /* _nIndex */, const ::accessibility::AccessibleShapeTreeInfo& /* _rShapeTreeInfo */)
807 OSL_FAIL("should not be called in the page preview");
808 return false;
811 ///===== Internal ========================================================
813 void ScShapeChildren::Init()
815 if(!mpViewShell)
816 return;
818 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
819 MapMode aMapMode;
820 tools::Rectangle aPixelPaintRect;
821 sal_uInt8 nRangeId;
822 sal_uInt16 nCount(rData.GetDrawRanges());
823 for (sal_uInt16 i = 0; i < nCount; ++i)
825 rData.GetDrawRange(i, aPixelPaintRect, aMapMode, nRangeId);
826 FillShapes(aPixelPaintRect, aMapMode, nRangeId);
830 sal_Int32 ScShapeChildren::GetBackShapeCount() const
832 sal_Int32 nCount(0);
833 for (auto const& shape : maShapeRanges)
834 nCount += shape.maBackShapes.size();
835 return nCount;
838 uno::Reference<XAccessible> ScShapeChildren::GetBackShape(sal_Int32 nIndex) const
840 uno::Reference<XAccessible> xAccessible;
841 for (const auto& rShapeRange : maShapeRanges)
843 sal_Int32 nCount(rShapeRange.maBackShapes.size());
844 if(nIndex < nCount)
845 xAccessible = GetAccShape(rShapeRange.maBackShapes, nIndex);
846 nIndex -= nCount;
847 if (xAccessible.is())
848 break;
851 if (nIndex >= 0)
852 throw lang::IndexOutOfBoundsException();
854 return xAccessible;
857 sal_Int32 ScShapeChildren::GetForeShapeCount() const
859 sal_Int32 nCount(0);
860 for (auto const& shape : maShapeRanges)
861 nCount += shape.maForeShapes.size();
862 return nCount;
865 uno::Reference<XAccessible> ScShapeChildren::GetForeShape(sal_Int32 nIndex) const
867 uno::Reference<XAccessible> xAccessible;
868 for (const auto& rShapeRange : maShapeRanges)
870 sal_Int32 nCount(rShapeRange.maForeShapes.size());
871 if(nIndex < nCount)
872 xAccessible = GetAccShape(rShapeRange.maForeShapes, nIndex);
873 nIndex -= nCount;
874 if (xAccessible.is())
875 break;
878 if (nIndex >= 0)
879 throw lang::IndexOutOfBoundsException();
881 return xAccessible;
884 sal_Int32 ScShapeChildren::GetControlCount() const
886 sal_Int32 nCount(0);
887 for (auto const& shape : maShapeRanges)
888 nCount += shape.maControls.size();
889 return nCount;
892 uno::Reference<XAccessible> ScShapeChildren::GetControl(sal_Int32 nIndex) const
894 uno::Reference<XAccessible> xAccessible;
895 for (const auto& rShapeRange : maShapeRanges)
897 sal_Int32 nCount(rShapeRange.maControls.size());
898 if(nIndex < nCount)
899 xAccessible = GetAccShape(rShapeRange.maControls, nIndex);
900 nIndex -= nCount;
901 if (xAccessible.is())
902 break;
905 if (nIndex >= 0)
906 throw lang::IndexOutOfBoundsException();
908 return xAccessible;
911 namespace {
913 struct ScShapePointFound
915 Point maPoint;
916 explicit ScShapePointFound(const awt::Point& rPoint) : maPoint(VCLPoint(rPoint)) {}
917 bool operator() (const ScShapeChild& rShape)
919 bool bResult(false);
920 if (VCLRectangle(rShape.mpAccShape->getBounds()).IsInside(maPoint))
921 bResult = true;
922 return bResult;
928 uno::Reference<XAccessible> ScShapeChildren::GetForegroundShapeAt(const awt::Point& rPoint) const //inclusive Controls
930 uno::Reference<XAccessible> xAcc;
932 for(const auto& rShapeRange : maShapeRanges)
934 ScShapeChildVec::const_iterator aFindItr = std::find_if(rShapeRange.maForeShapes.begin(), rShapeRange.maForeShapes.end(), ScShapePointFound(rPoint));
935 if (aFindItr != rShapeRange.maForeShapes.end())
936 xAcc = GetAccShape(*aFindItr);
937 else
939 ScShapeChildVec::const_iterator aCtrlItr = std::find_if(rShapeRange.maControls.begin(), rShapeRange.maControls.end(), ScShapePointFound(rPoint));
940 if (aCtrlItr != rShapeRange.maControls.end())
941 xAcc = GetAccShape(*aCtrlItr);
944 if (xAcc.is())
945 break;
948 return xAcc;
951 uno::Reference<XAccessible> ScShapeChildren::GetBackgroundShapeAt(const awt::Point& rPoint) const
953 uno::Reference<XAccessible> xAcc;
955 for(const auto& rShapeRange : maShapeRanges)
957 ScShapeChildVec::const_iterator aFindItr = std::find_if(rShapeRange.maBackShapes.begin(), rShapeRange.maBackShapes.end(), ScShapePointFound(rPoint));
958 if (aFindItr != rShapeRange.maBackShapes.end())
959 xAcc = GetAccShape(*aFindItr);
960 if (xAcc.is())
961 break;
964 return xAcc;
967 ::accessibility::AccessibleShape* ScShapeChildren::GetAccShape(const ScShapeChild& rShape) const
969 if (!rShape.mpAccShape.is())
971 ::accessibility::ShapeTypeHandler& rShapeHandler = ::accessibility::ShapeTypeHandler::Instance();
972 ::accessibility::AccessibleShapeInfo aShapeInfo(rShape.mxShape, mpAccDoc);
974 if (mpViewShell)
976 ::accessibility::AccessibleShapeTreeInfo aShapeTreeInfo;
977 aShapeTreeInfo.SetSdrView(mpViewShell->GetPreview()->GetDrawView());
978 aShapeTreeInfo.SetController(nullptr);
979 aShapeTreeInfo.SetDevice(mpViewShell->GetWindow());
980 aShapeTreeInfo.SetViewForwarder(&(maShapeRanges[rShape.mnRangeId].maViewForwarder));
981 rShape.mpAccShape = rShapeHandler.CreateAccessibleObject(aShapeInfo, aShapeTreeInfo);
982 if (rShape.mpAccShape.is())
984 rShape.mpAccShape->Init();
988 return rShape.mpAccShape.get();
991 ::accessibility::AccessibleShape* ScShapeChildren::GetAccShape(const ScShapeChildVec& rShapes, sal_Int32 nIndex) const
993 return GetAccShape(rShapes[nIndex]);
996 void ScShapeChildren::FillShapes(const tools::Rectangle& aPixelPaintRect, const MapMode& aMapMode, sal_uInt8 nRangeId)
998 OSL_ENSURE(nRangeId < maShapeRanges.size(), "this is not a valid range for draw objects");
999 SdrPage* pPage = GetDrawPage();
1000 vcl::Window* pWin = mpViewShell->GetWindow();
1001 if (!(pPage && pWin))
1002 return;
1004 bool bForeAdded(false);
1005 bool bBackAdded(false);
1006 bool bControlAdded(false);
1007 tools::Rectangle aClippedPixelPaintRect(aPixelPaintRect);
1008 if (mpAccDoc)
1010 tools::Rectangle aRect2(Point(0,0), mpAccDoc->GetBoundingBoxOnScreen().GetSize());
1011 aClippedPixelPaintRect = aPixelPaintRect.GetIntersection(aRect2);
1013 ScIAccessibleViewForwarder aViewForwarder(mpViewShell, mpAccDoc, aMapMode);
1014 maShapeRanges[nRangeId].maViewForwarder = aViewForwarder;
1015 const size_t nCount(pPage->GetObjCount());
1016 for (size_t i = 0; i < nCount; ++i)
1018 SdrObject* pObj = pPage->GetObj(i);
1019 if (pObj)
1021 uno::Reference< drawing::XShape > xShape(pObj->getUnoShape(), uno::UNO_QUERY);
1022 if (xShape.is())
1024 tools::Rectangle aRect(pWin->LogicToPixel(VCLPoint(xShape->getPosition()), aMapMode), pWin->LogicToPixel(VCLSize(xShape->getSize()), aMapMode));
1025 if(!aClippedPixelPaintRect.GetIntersection(aRect).IsEmpty())
1027 ScShapeChild aShape;
1028 aShape.mxShape = xShape;
1029 aShape.mnRangeId = nRangeId;
1030 if (pObj->GetLayer().anyOf(SC_LAYER_INTERN, SC_LAYER_FRONT))
1032 maShapeRanges[nRangeId].maForeShapes.push_back(std::move(aShape));
1033 bForeAdded = true;
1035 else if (pObj->GetLayer() == SC_LAYER_BACK)
1037 maShapeRanges[nRangeId].maBackShapes.push_back(std::move(aShape));
1038 bBackAdded = true;
1040 else if (pObj->GetLayer() == SC_LAYER_CONTROLS)
1042 maShapeRanges[nRangeId].maControls.push_back(std::move(aShape));
1043 bControlAdded = true;
1045 else
1047 OSL_FAIL("I don't know this layer.");
1053 if (bForeAdded)
1054 std::sort(maShapeRanges[nRangeId].maForeShapes.begin(), maShapeRanges[nRangeId].maForeShapes.end(),ScShapeChildLess());
1055 if (bBackAdded)
1056 std::sort(maShapeRanges[nRangeId].maBackShapes.begin(), maShapeRanges[nRangeId].maBackShapes.end(),ScShapeChildLess());
1057 if (bControlAdded)
1058 std::sort(maShapeRanges[nRangeId].maControls.begin(), maShapeRanges[nRangeId].maControls.end(),ScShapeChildLess());
1061 SdrPage* ScShapeChildren::GetDrawPage() const
1063 SCTAB nTab( mpViewShell->GetLocationData().GetPrintTab() );
1064 SdrPage* pDrawPage = nullptr;
1065 ScDocument& rDoc = mpViewShell->GetDocument();
1066 if (rDoc.GetDrawLayer())
1068 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
1069 if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab))
1070 pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(static_cast<sal_Int16>(nTab)));
1072 return pDrawPage;
1075 namespace {
1077 struct ScPagePreviewCountData
1079 // order is background shapes, header, table or notes, footer, foreground shapes, controls
1081 tools::Rectangle aVisRect;
1082 tools::Long nBackShapes;
1083 tools::Long nHeaders;
1084 tools::Long nTables;
1085 tools::Long nNoteParagraphs;
1086 tools::Long nFooters;
1087 tools::Long nForeShapes;
1088 tools::Long nControls;
1090 ScPagePreviewCountData( const ScPreviewLocationData& rData, const vcl::Window* pSizeWindow,
1091 const ScNotesChildren* pNotesChildren, const ScShapeChildren* pShapeChildren );
1093 tools::Long GetTotal() const
1095 return nBackShapes + nHeaders + nTables + nNoteParagraphs + nFooters + nForeShapes + nControls;
1101 ScPagePreviewCountData::ScPagePreviewCountData( const ScPreviewLocationData& rData,
1102 const vcl::Window* pSizeWindow, const ScNotesChildren* pNotesChildren,
1103 const ScShapeChildren* pShapeChildren) :
1104 nBackShapes( 0 ),
1105 nHeaders( 0 ),
1106 nTables( 0 ),
1107 nNoteParagraphs( 0 ),
1108 nFooters( 0 ),
1109 nForeShapes( 0 ),
1110 nControls( 0 )
1112 Size aOutputSize;
1113 if ( pSizeWindow )
1114 aOutputSize = pSizeWindow->GetOutputSizePixel();
1115 aVisRect = tools::Rectangle( Point(), aOutputSize );
1117 tools::Rectangle aObjRect;
1119 if ( rData.GetHeaderPosition( aObjRect ) && aObjRect.IsOver( aVisRect ) )
1120 nHeaders = 1;
1122 if ( rData.GetFooterPosition( aObjRect ) && aObjRect.IsOver( aVisRect ) )
1123 nFooters = 1;
1125 if ( rData.HasCellsInRange( aVisRect ) )
1126 nTables = 1;
1128 //! shapes...
1129 nBackShapes = pShapeChildren->GetBackShapeCount();
1130 nForeShapes = pShapeChildren->GetForeShapeCount();
1131 nControls = pShapeChildren->GetControlCount();
1133 // there are only notes if there is no table
1134 if (nTables == 0)
1135 nNoteParagraphs = pNotesChildren->GetChildrenCount();
1138 //===== internal ========================================================
1140 ScAccessibleDocumentPagePreview::ScAccessibleDocumentPagePreview(
1141 const uno::Reference<XAccessible>& rxParent, ScPreviewShell* pViewShell ) :
1142 ScAccessibleDocumentBase(rxParent),
1143 mpViewShell(pViewShell)
1145 if (pViewShell)
1146 pViewShell->AddAccessibilityObject(*this);
1150 ScAccessibleDocumentPagePreview::~ScAccessibleDocumentPagePreview()
1152 if (!ScAccessibleDocumentBase::IsDefunc() && !rBHelper.bInDispose)
1154 // increment refcount to prevent double call off dtor
1155 osl_atomic_increment( &m_refCount );
1156 // call dispose to inform object which have a weak reference to this object
1157 dispose();
1161 void SAL_CALL ScAccessibleDocumentPagePreview::disposing()
1163 SolarMutexGuard aGuard;
1164 mpTable.clear();
1165 mpHeader.clear();
1166 mpFooter.clear();
1168 if (mpViewShell)
1170 mpViewShell->RemoveAccessibilityObject(*this);
1171 mpViewShell = nullptr;
1174 // no need to Dispose the AccessibleTextHelper,
1175 // as long as mpNotesChildren are destructed here
1176 mpNotesChildren.reset();
1178 mpShapeChildren.reset();
1180 ScAccessibleDocumentBase::disposing();
1183 //===== SfxListener =====================================================
1185 void ScAccessibleDocumentPagePreview::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1187 if ( dynamic_cast<const ScAccWinFocusLostHint*>(&rHint) )
1189 CommitFocusLost();
1191 else if ( dynamic_cast<const ScAccWinFocusGotHint*>(&rHint) )
1193 CommitFocusGained();
1195 else
1197 // only notify if child exist, otherwise it is not necessary
1198 if (rHint.GetId() == SfxHintId::ScDataChanged)
1200 if (mpTable.is()) // if there is no table there is nothing to notify, because no one recognizes the change
1203 uno::Reference<XAccessible> xAcc = mpTable.get();
1204 AccessibleEventObject aEvent;
1205 aEvent.EventId = AccessibleEventId::CHILD;
1206 aEvent.Source = uno::Reference< XAccessibleContext >(this);
1207 aEvent.OldValue <<= xAcc;
1208 CommitChange(aEvent);
1211 mpTable->dispose();
1212 mpTable.clear();
1215 Size aOutputSize;
1216 vcl::Window* pSizeWindow = mpViewShell->GetWindow();
1217 if ( pSizeWindow )
1218 aOutputSize = pSizeWindow->GetOutputSizePixel();
1219 tools::Rectangle aVisRect( Point(), aOutputSize );
1220 GetNotesChildren()->DataChanged(aVisRect);
1222 GetShapeChildren()->DataChanged();
1224 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
1225 ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1227 if (aCount.nTables > 0)
1229 //! order is background shapes, header, table or notes, footer, foreground shapes, controls
1230 sal_Int32 nIndex (aCount.nBackShapes + aCount.nHeaders);
1232 mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex );
1233 mpTable->Init();
1236 uno::Reference<XAccessible> xAcc = mpTable.get();
1237 AccessibleEventObject aEvent;
1238 aEvent.EventId = AccessibleEventId::CHILD;
1239 aEvent.Source = uno::Reference< XAccessibleContext >(this);
1240 aEvent.NewValue <<= xAcc;
1241 CommitChange(aEvent);
1245 else if (rHint.GetId() == SfxHintId::ScAccVisAreaChanged)
1247 Size aOutputSize;
1248 vcl::Window* pSizeWindow = mpViewShell->GetWindow();
1249 if ( pSizeWindow )
1250 aOutputSize = pSizeWindow->GetOutputSizePixel();
1251 tools::Rectangle aVisRect( Point(), aOutputSize );
1252 GetNotesChildren()->DataChanged(aVisRect);
1254 GetShapeChildren()->VisAreaChanged();
1256 AccessibleEventObject aEvent;
1257 aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
1258 aEvent.Source = uno::Reference< XAccessibleContext >(this);
1259 CommitChange(aEvent);
1262 ScAccessibleDocumentBase::Notify(rBC, rHint);
1265 //===== XAccessibleComponent ============================================
1267 uno::Reference< XAccessible > SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleAtPoint( const awt::Point& rPoint )
1269 uno::Reference<XAccessible> xAccessible;
1270 if (containsPoint(rPoint))
1272 SolarMutexGuard aGuard;
1273 IsObjectValid();
1275 if ( mpViewShell )
1277 xAccessible = GetShapeChildren()->GetForegroundShapeAt(rPoint);
1278 if (!xAccessible.is())
1280 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
1281 ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1283 if ( !mpTable.is() && (aCount.nTables > 0) )
1285 //! order is background shapes, header, table or notes, footer, foreground shapes, controls
1286 sal_Int32 nIndex (aCount.nBackShapes + aCount.nHeaders);
1288 mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex );
1289 mpTable->Init();
1291 if (mpTable.is() && VCLRectangle(mpTable->getBounds()).IsInside(VCLPoint(rPoint)))
1292 xAccessible = mpTable.get();
1294 if (!xAccessible.is())
1295 xAccessible = GetNotesChildren()->GetAt(rPoint);
1296 if (!xAccessible.is())
1298 if (!mpHeader.is() || !mpFooter.is())
1300 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
1301 ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1303 if (!mpHeader.is())
1305 mpHeader = new ScAccessiblePageHeader( this, mpViewShell, true, aCount.nBackShapes + aCount.nHeaders - 1);
1307 if (!mpFooter.is())
1309 mpFooter = new ScAccessiblePageHeader( this, mpViewShell, false, aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters - 1 );
1313 Point aPoint(VCLPoint(rPoint));
1315 if (VCLRectangle(mpHeader->getBounds()).IsInside(aPoint))
1316 xAccessible = mpHeader.get();
1317 else if (VCLRectangle(mpFooter->getBounds()).IsInside(aPoint))
1318 xAccessible = mpFooter.get();
1320 if (!xAccessible.is())
1321 xAccessible = GetShapeChildren()->GetBackgroundShapeAt(rPoint);
1325 return xAccessible;
1328 void SAL_CALL ScAccessibleDocumentPagePreview::grabFocus()
1330 SolarMutexGuard aGuard;
1331 IsObjectValid();
1332 if (getAccessibleParent().is())
1334 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1335 if (xAccessibleComponent.is())
1337 // just grab the focus for the window
1338 xAccessibleComponent->grabFocus();
1343 //===== XAccessibleContext ==============================================
1345 sal_Int32 SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleChildCount()
1347 SolarMutexGuard aGuard;
1348 IsObjectValid();
1350 tools::Long nRet = 0;
1351 if ( mpViewShell )
1353 ScPagePreviewCountData aCount( mpViewShell->GetLocationData(), mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1354 nRet = aCount.GetTotal();
1357 return nRet;
1360 uno::Reference<XAccessible> SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleChild(sal_Int32 nIndex)
1362 SolarMutexGuard aGuard;
1363 IsObjectValid();
1364 uno::Reference<XAccessible> xAccessible;
1366 if ( mpViewShell )
1368 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
1369 ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1371 if ( nIndex < aCount.nBackShapes )
1373 xAccessible = GetShapeChildren()->GetBackShape(nIndex);
1375 else if ( nIndex < aCount.nBackShapes + aCount.nHeaders )
1377 if ( !mpHeader.is() )
1379 mpHeader = new ScAccessiblePageHeader( this, mpViewShell, true, nIndex );
1382 xAccessible = mpHeader.get();
1384 else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nTables )
1386 if ( !mpTable.is() )
1388 mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex );
1389 mpTable->Init();
1391 xAccessible = mpTable.get();
1393 else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nNoteParagraphs )
1395 xAccessible = GetNotesChildren()->GetChild(nIndex - aCount.nBackShapes - aCount.nHeaders);
1397 else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters )
1399 if ( !mpFooter.is() )
1401 mpFooter = new ScAccessiblePageHeader( this, mpViewShell, false, nIndex );
1403 xAccessible = mpFooter.get();
1405 else
1407 sal_Int32 nIdx(nIndex - (aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters));
1408 if (nIdx < aCount.nForeShapes)
1409 xAccessible = GetShapeChildren()->GetForeShape(nIdx);
1410 else
1411 xAccessible = GetShapeChildren()->GetControl(nIdx - aCount.nForeShapes);
1415 if ( !xAccessible.is() )
1416 throw lang::IndexOutOfBoundsException();
1418 return xAccessible;
1421 /// Return the set of current states.
1422 uno::Reference<XAccessibleStateSet> SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleStateSet()
1424 SolarMutexGuard aGuard;
1425 uno::Reference<XAccessibleStateSet> xParentStates;
1426 if (getAccessibleParent().is())
1428 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1429 xParentStates = xParentContext->getAccessibleStateSet();
1431 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
1432 if (IsDefunc(xParentStates))
1433 pStateSet->AddState(AccessibleStateType::DEFUNC);
1434 else
1436 // never editable
1437 pStateSet->AddState(AccessibleStateType::ENABLED);
1438 pStateSet->AddState(AccessibleStateType::OPAQUE);
1439 if (isShowing())
1440 pStateSet->AddState(AccessibleStateType::SHOWING);
1441 if (isVisible())
1442 pStateSet->AddState(AccessibleStateType::VISIBLE);
1444 return pStateSet;
1447 //===== XServiceInfo ====================================================
1449 OUString SAL_CALL ScAccessibleDocumentPagePreview::getImplementationName()
1451 return "ScAccessibleDocumentPagePreview";
1454 uno::Sequence< OUString> SAL_CALL ScAccessibleDocumentPagePreview::getSupportedServiceNames()
1456 uno::Sequence< OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
1457 sal_Int32 nOldSize(aSequence.getLength());
1458 aSequence.realloc(nOldSize + 1);
1460 aSequence[nOldSize] = "com.sun.star.AccessibleSpreadsheetPageView";
1462 return aSequence;
1465 //===== XTypeProvider =======================================================
1467 uno::Sequence<sal_Int8> SAL_CALL
1468 ScAccessibleDocumentPagePreview::getImplementationId()
1470 return css::uno::Sequence<sal_Int8>();
1473 //===== internal ========================================================
1475 OUString ScAccessibleDocumentPagePreview::createAccessibleDescription()
1477 return STR_ACC_PREVIEWDOC_DESCR;
1480 OUString ScAccessibleDocumentPagePreview::createAccessibleName()
1482 OUString sName = ScResId(STR_ACC_PREVIEWDOC_NAME);
1483 return sName;
1486 tools::Rectangle ScAccessibleDocumentPagePreview::GetBoundingBoxOnScreen() const
1488 tools::Rectangle aRect;
1489 if (mpViewShell)
1491 vcl::Window* pWindow = mpViewShell->GetWindow();
1492 if (pWindow)
1493 aRect = pWindow->GetWindowExtentsRelative(nullptr);
1495 return aRect;
1498 tools::Rectangle ScAccessibleDocumentPagePreview::GetBoundingBox() const
1500 tools::Rectangle aRect;
1501 if (mpViewShell)
1503 vcl::Window* pWindow = mpViewShell->GetWindow();
1504 if (pWindow)
1505 aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
1507 return aRect;
1510 bool ScAccessibleDocumentPagePreview::IsDefunc(
1511 const uno::Reference<XAccessibleStateSet>& rxParentStates)
1513 return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() ||
1514 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
1517 ScNotesChildren* ScAccessibleDocumentPagePreview::GetNotesChildren()
1519 if (!mpNotesChildren && mpViewShell)
1521 mpNotesChildren.reset( new ScNotesChildren(mpViewShell, this) );
1523 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
1524 ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1526 //! order is background shapes, header, table or notes, footer, foreground shapes, controls
1527 mpNotesChildren->Init(aCount.aVisRect, aCount.nBackShapes + aCount.nHeaders);
1529 return mpNotesChildren.get();
1532 ScShapeChildren* ScAccessibleDocumentPagePreview::GetShapeChildren()
1534 if (!mpShapeChildren && mpViewShell)
1536 mpShapeChildren.reset( new ScShapeChildren(mpViewShell, this) );
1537 mpShapeChildren->Init();
1540 return mpShapeChildren.get();
1543 OUString ScAccessibleDocumentPagePreview::getAccessibleName()
1545 SolarMutexGuard g;
1547 OUString aName = ScResId(STR_ACC_DOC_SPREADSHEET);
1548 ScDocument& rScDoc = mpViewShell->GetDocument();
1550 SfxObjectShell* pObjSh = rScDoc.GetDocumentShell();
1551 if (!pObjSh)
1552 return aName;
1554 OUString aFileName;
1555 SfxMedium* pMed = pObjSh->GetMedium();
1556 if (pMed)
1557 aFileName = pMed->GetName();
1559 if (aFileName.isEmpty())
1560 aFileName = pObjSh->GetTitle(SFX_TITLE_APINAME);
1562 if (!aFileName.isEmpty())
1564 aName = aFileName + " - " + aName + ScResId(STR_ACC_DOC_PREVIEW_SUFFIX);
1568 return aName;
1571 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */