LibreOffice Module sc (master)  1
AccessibleDocumentPagePreview.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
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>
35 
36 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
37 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
38 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
39 #include <comphelper/sequence.hxx>
40 
42 #include <tools/gen.hxx>
43 #include <svx/fmview.hxx>
44 #include <svx/svdpage.hxx>
45 #include <svx/svdobj.hxx>
47 #include <svx/AccessibleShape.hxx>
51 #include <svx/ShapeTypeHandler.hxx>
53 #include <vcl/svapp.hxx>
54 #include <sfx2/docfile.hxx>
55 
56 #include <vector>
57 #include <algorithm>
58 #include <memory>
59 #include <utility>
60 
61 using namespace ::com::sun::star;
62 using namespace ::com::sun::star::accessibility;
63 
64 typedef std::vector< uno::Reference< XAccessible > > ScXAccVector;
65 
66 namespace {
67 
68 struct ScAccNote
69 {
70  OUString maNoteText;
71  tools::Rectangle maRect;
72  ScAddress maNoteCell;
74  sal_Int32 mnParaCount;
75  bool mbMarkNote;
76 
77  ScAccNote()
78  : mpTextHelper(nullptr)
79  , mnParaCount(0)
80  , mbMarkNote(false)
81  {
82  }
83 };
84 
85 }
86 
88 {
89 public:
92  void Init(const tools::Rectangle& rVisRect, sal_Int32 nOffset);
93 
94  sal_Int32 GetChildrenCount() const { return mnParagraphs;}
95  uno::Reference<XAccessible> GetChild(sal_Int32 nIndex) const;
96  uno::Reference<XAccessible> GetAt(const awt::Point& rPoint) const;
97 
98  void DataChanged(const tools::Rectangle& rVisRect);
99 
100 private:
103  typedef std::vector<ScAccNote> ScAccNotes;
104  mutable ScAccNotes maNotes;
105  mutable ScAccNotes maMarks;
106  sal_Int32 mnParagraphs;
107  sal_Int32 mnOffset;
108 
109  ::accessibility::AccessibleTextHelper* CreateTextHelper(const OUString& rString, const tools::Rectangle& rVisRect, const ScAddress& aCellPos, bool bMarkNote, sal_Int32 nChildOffset) const;
110  sal_Int32 AddNotes(const ScPreviewLocationData& rData, const tools::Rectangle& rVisRect, bool bMark, ScAccNotes& rNotes);
111 
112  static sal_Int8 CompareCell(const ScAddress& aCell1, const ScAddress& aCell2);
113  static void CollectChildren(const ScAccNote& rNote, ScXAccVector& rVector);
114  sal_Int32 CheckChanges(const ScPreviewLocationData& rData, const tools::Rectangle& rVisRect,
115  bool bMark, ScAccNotes& rOldNotes, ScAccNotes& rNewNotes,
116  ScXAccVector& rOldParas, ScXAccVector& rNewParas);
117 
118  inline ScDocument* GetDocument() const;
119 };
120 
122  : mpViewShell(pViewShell),
123  mpAccDoc(pAccDoc),
124  mnParagraphs(0),
125  mnOffset(0)
126 {
127 }
128 
130 {
131  for (auto & i : maNotes)
132  if (i.mpTextHelper)
133  {
134  delete i.mpTextHelper;
135  i.mpTextHelper = nullptr;
136  }
137  for (auto & i : maMarks)
138  if (i.mpTextHelper)
139  {
140  delete i.mpTextHelper;
141  i.mpTextHelper = nullptr;
142  }
143 }
144 
145 ::accessibility::AccessibleTextHelper* ScNotesChildren::CreateTextHelper(const OUString& rString, const tools::Rectangle& rVisRect, const ScAddress& aCellPos, bool bMarkNote, sal_Int32 nChildOffset) const
146 {
147  ::accessibility::AccessibleTextHelper* pTextHelper = new ::accessibility::AccessibleTextHelper(std::make_unique<ScAccessibilityEditSource>(std::make_unique<ScAccessibleNoteTextData>(mpViewShell, rString, aCellPos, bMarkNote)));
148  pTextHelper->SetEventSource(mpAccDoc);
149  pTextHelper->SetStartIndex(nChildOffset);
150  pTextHelper->SetOffset(rVisRect.TopLeft());
151 
152  return pTextHelper;
153 }
154 
155 sal_Int32 ScNotesChildren::AddNotes(const ScPreviewLocationData& rData, const tools::Rectangle& rVisRect, bool bMark, ScAccNotes& rNotes)
156 {
157  sal_Int32 nCount = rData.GetNoteCountInRange(rVisRect, bMark);
158 
159  rNotes.reserve(nCount);
160 
161  sal_Int32 nParagraphs(0);
162  ScDocument* pDoc = GetDocument();
163  if (pDoc)
164  {
165  ScAccNote aNote;
166  aNote.mbMarkNote = bMark;
167  if (bMark)
168  aNote.mnParaCount = 1;
169  for (sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex)
170  {
171  if (rData.GetNoteInRange(rVisRect, nIndex, bMark, aNote.maNoteCell, aNote.maRect))
172  {
173  if (bMark)
174  {
175  // Document not needed, because only the cell address, but not the tablename is needed
176  aNote.maNoteText = aNote.maNoteCell.Format(ScRefFlags::VALID);
177  }
178  else
179  {
180  if( ScPostIt* pNote = pDoc->GetNote( aNote.maNoteCell ) )
181  aNote.maNoteText = pNote->GetText();
182  aNote.mpTextHelper = CreateTextHelper(aNote.maNoteText, aNote.maRect, aNote.maNoteCell, aNote.mbMarkNote, nParagraphs + mnOffset);
183  if (aNote.mpTextHelper)
184  aNote.mnParaCount = aNote.mpTextHelper->GetChildCount();
185  }
186  nParagraphs += aNote.mnParaCount;
187  rNotes.push_back(aNote);
188  }
189  }
190  }
191  return nParagraphs;
192 }
193 
194 void ScNotesChildren::Init(const tools::Rectangle& rVisRect, sal_Int32 nOffset)
195 {
196  if (mpViewShell && !mnParagraphs)
197  {
198  mnOffset = nOffset;
200 
201  mnParagraphs = AddNotes(rData, rVisRect, false, maMarks);
202  mnParagraphs += AddNotes(rData, rVisRect, true, maNotes);
203  }
204 }
205 
206 namespace {
207 
208 struct ScParaFound
209 {
210  sal_Int32 mnIndex;
211  explicit ScParaFound(sal_Int32 nIndex) : mnIndex(nIndex) {}
212  bool operator() (const ScAccNote& rNote)
213  {
214  bool bResult(false);
215  if (rNote.mnParaCount > mnIndex)
216  bResult = true;
217  else
218  mnIndex -= rNote.mnParaCount;
219  return bResult;
220  }
221 };
222 
223 }
224 
225 uno::Reference<XAccessible> ScNotesChildren::GetChild(sal_Int32 nIndex) const
226 {
227  uno::Reference<XAccessible> xAccessible;
228 
229  if (nIndex < mnParagraphs)
230  {
231  if (nIndex < static_cast<sal_Int32>(maMarks.size()))
232  {
233  ScAccNotes::iterator aEndItr = maMarks.end();
234  ScParaFound aParaFound(nIndex);
235  ScAccNotes::iterator aItr = std::find_if(maMarks.begin(), aEndItr, aParaFound);
236  if (aItr != aEndItr)
237  {
238  OSL_ENSURE((aItr->maNoteCell == maMarks[nIndex].maNoteCell) && (aItr->mbMarkNote == maMarks[nIndex].mbMarkNote), "wrong note found");
239  if (!aItr->mpTextHelper)
240  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
241  xAccessible = aItr->mpTextHelper->GetChild(aParaFound.mnIndex + aItr->mpTextHelper->GetStartIndex());
242  }
243  else
244  {
245  OSL_FAIL("wrong note found");
246  }
247  }
248  else
249  {
250  nIndex -= maMarks.size();
251  ScAccNotes::iterator aEndItr = maNotes.end();
252  ScParaFound aParaFound(nIndex);
253  ScAccNotes::iterator aItr = std::find_if(maNotes.begin(), aEndItr, aParaFound);
254  if (aEndItr != aItr)
255  {
256  if (!aItr->mpTextHelper)
257  aItr->mpTextHelper = CreateTextHelper(aItr->maNoteText, aItr->maRect, aItr->maNoteCell, aItr->mbMarkNote, (nIndex - aParaFound.mnIndex) + mnOffset + maMarks.size());
258  xAccessible = aItr->mpTextHelper->GetChild(aParaFound.mnIndex + aItr->mpTextHelper->GetStartIndex());
259  }
260  }
261  }
262 
263  return xAccessible;
264 }
265 
266 namespace {
267 
268 struct ScPointFound
269 {
271  sal_Int32 mnParagraphs;
272  explicit ScPointFound(const Point& rPoint) : maPoint(rPoint, Size(0, 0)), mnParagraphs(0) {}
273  bool operator() (const ScAccNote& rNote)
274  {
275  bool bResult(false);
276  if (maPoint.Contains(rNote.maRect))
277  bResult = true;
278  else
279  mnParagraphs += rNote.mnParaCount;
280  return bResult;
281  }
282 };
283 
284 }
285 
286 uno::Reference<XAccessible> ScNotesChildren::GetAt(const awt::Point& rPoint) const
287 {
288  uno::Reference<XAccessible> xAccessible;
289 
290  ScPointFound aPointFound(Point(rPoint.X, rPoint.Y));
291 
292  ScAccNotes::iterator aEndItr = maMarks.end();
293  ScAccNotes::iterator aItr = std::find_if(maMarks.begin(), aEndItr, aPointFound);
294  if (aEndItr == aItr)
295  {
296  aEndItr = maNotes.end();
297  aItr = std::find_if(maNotes.begin(), aEndItr, aPointFound);
298  }
299  if (aEndItr != aItr)
300  {
301  if (!aItr->mpTextHelper)
302  aItr->mpTextHelper = CreateTextHelper(aItr->maNoteText, aItr->maRect, aItr->maNoteCell, aItr->mbMarkNote, aPointFound.mnParagraphs + mnOffset);
303  xAccessible = aItr->mpTextHelper->GetAt(rPoint);
304  }
305 
306  return xAccessible;
307 }
308 
310 {
311  OSL_ENSURE(aCell1.Tab() == aCell2.Tab(), "the notes should be on the same table");
312  sal_Int8 nResult(0);
313  if (aCell1 != aCell2)
314  {
315  if (aCell1.Row() == aCell2.Row())
316  nResult = (aCell1.Col() < aCell2.Col()) ? -1 : 1;
317  else
318  nResult = (aCell1.Row() < aCell2.Row()) ? -1 : 1;
319  }
320  return nResult;
321 }
322 
323 void ScNotesChildren::CollectChildren(const ScAccNote& rNote, ScXAccVector& rVector)
324 {
325  if (rNote.mpTextHelper)
326  for (sal_Int32 i = 0; i < rNote.mnParaCount; ++i)
327  rVector.push_back(rNote.mpTextHelper->GetChild(i + rNote.mpTextHelper->GetStartIndex()));
328 }
329 
331  const tools::Rectangle& rVisRect, bool bMark, ScAccNotes& rOldNotes,
332  ScAccNotes& rNewNotes, ScXAccVector& rOldParas, ScXAccVector& rNewParas)
333 {
334  sal_Int32 nCount = rData.GetNoteCountInRange(rVisRect, bMark);
335 
336  rNewNotes.reserve(nCount);
337 
338  sal_Int32 nParagraphs(0);
339  ScDocument* pDoc = GetDocument();
340  if (pDoc)
341  {
342  ScAccNote aNote;
343  aNote.mbMarkNote = bMark;
344  if (bMark)
345  aNote.mnParaCount = 1;
346  ScAccNotes::iterator aItr = rOldNotes.begin();
347  ScAccNotes::iterator aEndItr = rOldNotes.end();
348  bool bAddNote(false);
349  for (sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex)
350  {
351  if (rData.GetNoteInRange(rVisRect, nIndex, bMark, aNote.maNoteCell, aNote.maRect))
352  {
353  if (bMark)
354  {
355  // Document not needed, because only the cell address, but not the tablename is needed
356  aNote.maNoteText = aNote.maNoteCell.Format(ScRefFlags::VALID);
357  }
358  else
359  {
360  if( ScPostIt* pNote = pDoc->GetNote( aNote.maNoteCell ) )
361  aNote.maNoteText = pNote->GetText();
362  }
363 
364  sal_Int8 nCompare(-1); // if there are no more old children it is always a new one
365  if (aItr != aEndItr)
366  nCompare = CompareCell(aNote.maNoteCell, aItr->maNoteCell);
367  if (nCompare == 0)
368  {
369  if (aNote.maNoteText == aItr->maNoteText)
370  {
371  aNote.mpTextHelper = aItr->mpTextHelper;
372  if (aNote.maRect != aItr->maRect) // set new VisArea
373  {
374  aNote.mpTextHelper->SetOffset(aNote.maRect.TopLeft());
375  aNote.mpTextHelper->UpdateChildren();
376  //OSL_ENSURE(aItr->maRect.GetSize() == aNote.maRect.GetSize(), "size should be the same, because the text is not changed");
377  // could be changed, because only a part of the note is visible
378  }
379  }
380  else
381  {
382  aNote.mpTextHelper = CreateTextHelper(aNote.maNoteText, aNote.maRect, aNote.maNoteCell, aNote.mbMarkNote, nParagraphs + mnOffset);
383  if (aNote.mpTextHelper)
384  aNote.mnParaCount = aNote.mpTextHelper->GetChildCount();
385  // collect removed children
386  CollectChildren(*aItr, rOldParas);
387  delete aItr->mpTextHelper;
388  aItr->mpTextHelper = nullptr;;
389  // collect new children
390  CollectChildren(aNote, rNewParas);
391  }
392  bAddNote = true;
393  // not necessary, because this branch should not be reached if it is the end
394  //if (aItr != aEndItr)
395  ++aItr;
396  }
397  else if (nCompare < 0)
398  {
399  aNote.mpTextHelper = CreateTextHelper(aNote.maNoteText, aNote.maRect, aNote.maNoteCell, aNote.mbMarkNote, nParagraphs + mnOffset);
400  if (aNote.mpTextHelper)
401  aNote.mnParaCount = aNote.mpTextHelper->GetChildCount();
402  // collect new children
403  CollectChildren(aNote, rNewParas);
404  bAddNote = true;
405  }
406  else
407  {
408  // collect removed children
409  CollectChildren(*aItr, rOldParas);
410  delete aItr->mpTextHelper;
411  aItr->mpTextHelper = nullptr;
412 
413  // no note to add
414  // not necessary, because this branch should not be reached if it is the end
415  //if (aItr != aEndItr)
416  ++aItr;
417  }
418  if (bAddNote)
419  {
420  nParagraphs += aNote.mnParaCount;
421  rNewNotes.push_back(aNote);
422  bAddNote = false;
423  }
424  }
425  }
426  }
427  return nParagraphs;
428 }
429 
430 namespace {
431 
432 struct ScChildGone
433 {
435  explicit ScChildGone(ScAccessibleDocumentPagePreview* pAccDoc) : mpAccDoc(pAccDoc) {}
436  void operator() (const uno::Reference<XAccessible>& xAccessible) const
437  {
438  if (mpAccDoc)
439  {
440  AccessibleEventObject aEvent;
441  aEvent.EventId = AccessibleEventId::CHILD;
442  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccDoc);
443  aEvent.OldValue <<= xAccessible;
444 
445  mpAccDoc->CommitChange(aEvent); // gone child - event
446  }
447  }
448 };
449 
450 struct ScChildNew
451 {
453  explicit ScChildNew(ScAccessibleDocumentPagePreview* pAccDoc) : mpAccDoc(pAccDoc) {}
454  void operator() (const uno::Reference<XAccessible>& xAccessible) const
455  {
456  if (mpAccDoc)
457  {
458  AccessibleEventObject aEvent;
459  aEvent.EventId = AccessibleEventId::CHILD;
460  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccDoc);
461  aEvent.NewValue <<= xAccessible;
462 
463  mpAccDoc->CommitChange(aEvent); // new child - event
464  }
465  }
466 };
467 
468 }
469 
471 {
472  if (!(mpViewShell && mpAccDoc))
473  return;
474 
475  ScXAccVector aNewParas;
476  ScXAccVector aOldParas;
477  ScAccNotes aNewMarks;
478  mnParagraphs = CheckChanges(mpViewShell->GetLocationData(), rVisRect, true, maMarks, aNewMarks, aOldParas, aNewParas);
479  maMarks = aNewMarks;
480  ScAccNotes aNewNotes;
481  mnParagraphs += CheckChanges(mpViewShell->GetLocationData(), rVisRect, false, maNotes, aNewNotes, aOldParas, aNewParas);
482  maNotes = aNewNotes;
483 
484  std::for_each(aOldParas.begin(), aOldParas.end(), ScChildGone(mpAccDoc));
485  std::for_each(aNewParas.begin(), aNewParas.end(), ScChildNew(mpAccDoc));
486 }
487 
489 {
490  ScDocument* pDoc = nullptr;
491  if (mpViewShell)
492  pDoc = &mpViewShell->GetDocument();
493  return pDoc;
494 }
495 
496 namespace {
497 
498 class ScIAccessibleViewForwarder : public ::accessibility::IAccessibleViewForwarder
499 {
500 public:
501  ScIAccessibleViewForwarder();
502  ScIAccessibleViewForwarder(ScPreviewShell* pViewShell,
504  const MapMode& aMapMode);
505 
507 
508  virtual tools::Rectangle GetVisibleArea() const override;
509  virtual Point LogicToPixel (const Point& rPoint) const override;
510  virtual Size LogicToPixel (const Size& rSize) const override;
511 
512 private:
513  ScPreviewShell* mpViewShell;
515  MapMode maMapMode;
516 };
517 
518 }
519 
520 ScIAccessibleViewForwarder::ScIAccessibleViewForwarder()
521  : mpViewShell(nullptr), mpAccDoc(nullptr)
522 {
523 }
524 
525 ScIAccessibleViewForwarder::ScIAccessibleViewForwarder(ScPreviewShell* pViewShell,
527  const MapMode& aMapMode)
528  : mpViewShell(pViewShell),
529  mpAccDoc(pAccDoc),
530  maMapMode(aMapMode)
531 {
532 }
533 
535 
536 tools::Rectangle ScIAccessibleViewForwarder::GetVisibleArea() const
537 {
538  SolarMutexGuard aGuard;
539  tools::Rectangle aVisRect;
540  vcl::Window* pWin = mpViewShell->GetWindow();
541  if (pWin)
542  {
543  aVisRect.SetSize(pWin->GetOutputSizePixel());
544  aVisRect.SetPos(Point(0, 0));
545 
546  aVisRect = pWin->PixelToLogic(aVisRect, maMapMode);
547  }
548 
549  return aVisRect;
550 }
551 
552 Point ScIAccessibleViewForwarder::LogicToPixel (const Point& rPoint) const
553 {
554  SolarMutexGuard aGuard;
555  Point aPoint;
556  vcl::Window* pWin = mpViewShell->GetWindow();
557  if (pWin && mpAccDoc)
558  {
559  tools::Rectangle aRect(mpAccDoc->GetBoundingBoxOnScreen());
560  aPoint = pWin->LogicToPixel(rPoint, maMapMode) + aRect.TopLeft();
561  }
562 
563  return aPoint;
564 }
565 
566 Size ScIAccessibleViewForwarder::LogicToPixel (const Size& rSize) const
567 {
568  SolarMutexGuard aGuard;
569  Size aSize;
570  vcl::Window* pWin = mpViewShell->GetWindow();
571  if (pWin)
572  aSize = pWin->LogicToPixel(rSize, maMapMode);
573  return aSize;
574 }
575 
576 namespace {
577 
578 struct ScShapeChild
579 {
580  ScShapeChild()
581  : mnRangeId(0)
582  {
583  }
584  ScShapeChild(ScShapeChild const &) = delete;
585  ScShapeChild(ScShapeChild &&) = default;
586  ~ScShapeChild();
587  ScShapeChild & operator =(ScShapeChild const &) = delete;
588  ScShapeChild & operator =(ScShapeChild && other) {
589  std::swap(mpAccShape, other.mpAccShape);
590  mxShape = std::move(other.mxShape);
591  mnRangeId = other.mnRangeId;
592  return *this;
593  }
594 
596  css::uno::Reference< css::drawing::XShape > mxShape;
597  sal_Int32 mnRangeId;
598 };
599 
600 }
601 
602 ScShapeChild::~ScShapeChild()
603 {
604  if (mpAccShape.is())
605  {
606  mpAccShape->dispose();
607  }
608 }
609 
610 namespace {
611 
612 struct ScShapeChildLess
613 {
614  bool operator()(const ScShapeChild& rChild1, const ScShapeChild& rChild2) const
615  {
616  bool bResult(false);
617  if (rChild1.mxShape.is() && rChild2.mxShape.is())
618  bResult = (rChild1.mxShape.get() < rChild2.mxShape.get());
619  return bResult;
620  }
621 };
622 
623 }
624 
625 typedef std::vector<ScShapeChild> ScShapeChildVec;
626 
627 namespace {
628 
629 struct ScShapeRange
630 {
631  ScShapeRange() = default;
632  ScShapeRange(ScShapeRange const &) = delete;
633  ScShapeRange(ScShapeRange &&) = default;
634  ScShapeRange & operator =(ScShapeRange const &) = delete;
635  ScShapeRange & operator =(ScShapeRange &&) = default;
636 
637  ScShapeChildVec maBackShapes;
638  ScShapeChildVec maForeShapes; // inclusive internal shapes
639  ScShapeChildVec maControls;
640  ScIAccessibleViewForwarder maViewForwarder;
641 };
642 
643 }
644 
645 typedef std::vector<ScShapeRange> ScShapeRangeVec;
646 
648 {
649 public:
651 
653 
654  virtual bool ReplaceChild (
655  ::accessibility::AccessibleShape* pCurrentChild,
656  const css::uno::Reference< css::drawing::XShape >& _rxShape,
657  const tools::Long _nIndex,
658  const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo
659  ) override;
660 
662 
663  void Init();
664 
665  sal_Int32 GetBackShapeCount() const;
666  uno::Reference<XAccessible> GetBackShape(sal_Int32 nIndex) const;
667  sal_Int32 GetForeShapeCount() const;
668  uno::Reference<XAccessible> GetForeShape(sal_Int32 nIndex) const;
669  sal_Int32 GetControlCount() const;
670  uno::Reference<XAccessible> GetControl(sal_Int32 nIndex) const;
671  uno::Reference<XAccessible> GetForegroundShapeAt(const awt::Point& rPoint) const; // inclusive controls
672  uno::Reference<XAccessible> GetBackgroundShapeAt(const awt::Point& rPoint) const;
673 
674  void DataChanged();
675  void VisAreaChanged() const;
676 
677 private:
680  ScShapeRangeVec maShapeRanges;
681 
682  void FindChanged(ScShapeChildVec& aOld, ScShapeChildVec& aNew) const;
683  void FindChanged(ScShapeRange& aOld, ScShapeRange& aNew) const;
684  ::accessibility::AccessibleShape* GetAccShape(const ScShapeChild& rShape) const;
685  ::accessibility::AccessibleShape* GetAccShape(const ScShapeChildVec& rShapes, sal_Int32 nIndex) const;
686  void FillShapes(const tools::Rectangle& aPixelPaintRect, const MapMode& aMapMode, sal_uInt8 nRangeId);
687 
688 // void AddShape(const uno::Reference<drawing::XShape>& xShape, SdrLayerID aLayerID);
689 // void RemoveShape(const uno::Reference<drawing::XShape>& xShape, SdrLayerID aLayerID);
690  SdrPage* GetDrawPage() const;
691 };
692 
694  :
695  mpAccDoc(pAccDoc),
696  mpViewShell(pViewShell),
697  maShapeRanges(SC_PREVIEW_MAXRANGES)
698 {
699 }
700 
701 void ScShapeChildren::FindChanged(ScShapeChildVec& rOld, ScShapeChildVec& rNew) const
702 {
703  ScShapeChildVec::iterator aOldItr = rOld.begin();
704  ScShapeChildVec::iterator aOldEnd = rOld.end();
705  ScShapeChildVec::const_iterator aNewItr = rNew.begin();
706  ScShapeChildVec::const_iterator aNewEnd = rNew.end();
707  uno::Reference<XAccessible> xAcc;
708  while ((aNewItr != aNewEnd) && (aOldItr != aOldEnd))
709  {
710  if (aNewItr->mxShape.get() == aOldItr->mxShape.get())
711  {
712  ++aOldItr;
713  ++aNewItr;
714  }
715  else if (aNewItr->mxShape.get() < aOldItr->mxShape.get())
716  {
717  xAcc = GetAccShape(*aNewItr);
718  AccessibleEventObject aEvent;
719  aEvent.Source = uno::Reference<XAccessibleContext> (mpAccDoc);
720  aEvent.EventId = AccessibleEventId::CHILD;
721  aEvent.NewValue <<= xAcc;
722  mpAccDoc->CommitChange(aEvent);
723  ++aNewItr;
724  }
725  else
726  {
727  xAcc = GetAccShape(*aOldItr);
728  AccessibleEventObject aEvent;
729  aEvent.Source = uno::Reference<XAccessibleContext> (mpAccDoc);
730  aEvent.EventId = AccessibleEventId::CHILD;
731  aEvent.OldValue <<= xAcc;
732  mpAccDoc->CommitChange(aEvent);
733  ++aOldItr;
734  }
735  }
736  while (aOldItr != aOldEnd)
737  {
738  xAcc = GetAccShape(*aOldItr);
739  AccessibleEventObject aEvent;
740  aEvent.Source = uno::Reference<XAccessibleContext> (mpAccDoc);
741  aEvent.EventId = AccessibleEventId::CHILD;
742  aEvent.OldValue <<= xAcc;
743  mpAccDoc->CommitChange(aEvent);
744  ++aOldItr;
745  }
746  while (aNewItr != aNewEnd)
747  {
748  xAcc = GetAccShape(*aNewItr);
749  AccessibleEventObject aEvent;
750  aEvent.Source = uno::Reference<XAccessibleContext> (mpAccDoc);
751  aEvent.EventId = AccessibleEventId::CHILD;
752  aEvent.NewValue <<= xAcc;
753  mpAccDoc->CommitChange(aEvent);
754  ++aNewItr;
755  }
756 }
757 
758 void ScShapeChildren::FindChanged(ScShapeRange& rOld, ScShapeRange& rNew) const
759 {
760  FindChanged(rOld.maBackShapes, rNew.maBackShapes);
761  FindChanged(rOld.maForeShapes, rNew.maForeShapes);
762  FindChanged(rOld.maControls, rNew.maControls);
763 }
764 
766 {
767  ScShapeRangeVec aOldShapeRanges(std::move(maShapeRanges));
768  maShapeRanges.clear();
770  Init();
771  for (sal_Int32 i = 0; i < SC_PREVIEW_MAXRANGES; ++i)
772  {
773  FindChanged(aOldShapeRanges[i], maShapeRanges[i]);
774  }
775 }
776 
777 namespace
778 {
779  struct ScVisAreaChanged
780  {
781  void operator() (const ScShapeChild& rAccShapeData) const
782  {
783  if (rAccShapeData.mpAccShape.is())
784  {
785  rAccShapeData.mpAccShape->ViewForwarderChanged();
786  }
787  }
788  };
789 }
790 
792 {
793  for (auto const& shape : maShapeRanges)
794  {
795  ScVisAreaChanged aVisAreaChanged;
796  std::for_each(shape.maBackShapes.begin(), shape.maBackShapes.end(), aVisAreaChanged);
797  std::for_each(shape.maControls.begin(), shape.maControls.end(), aVisAreaChanged);
798  std::for_each(shape.maForeShapes.begin(), shape.maForeShapes.end(), aVisAreaChanged);
799  }
800 }
801 
803 
805  const css::uno::Reference< css::drawing::XShape >& /* _rxShape */,
806  const tools::Long /* _nIndex */, const ::accessibility::AccessibleShapeTreeInfo& /* _rShapeTreeInfo */)
807 {
808  OSL_FAIL("should not be called in the page preview");
809  return false;
810 }
811 
813 
815 {
816  if(!mpViewShell)
817  return;
818 
820  MapMode aMapMode;
821  tools::Rectangle aPixelPaintRect;
822  sal_uInt8 nRangeId;
823  sal_uInt16 nCount(rData.GetDrawRanges());
824  for (sal_uInt16 i = 0; i < nCount; ++i)
825  {
826  rData.GetDrawRange(i, aPixelPaintRect, aMapMode, nRangeId);
827  FillShapes(aPixelPaintRect, aMapMode, nRangeId);
828  }
829 }
830 
832 {
833  sal_Int32 nCount(0);
834  for (auto const& shape : maShapeRanges)
835  nCount += shape.maBackShapes.size();
836  return nCount;
837 }
838 
839 uno::Reference<XAccessible> ScShapeChildren::GetBackShape(sal_Int32 nIndex) const
840 {
841  uno::Reference<XAccessible> xAccessible;
842  for (const auto& rShapeRange : maShapeRanges)
843  {
844  sal_Int32 nCount(rShapeRange.maBackShapes.size());
845  if(nIndex < nCount)
846  xAccessible = GetAccShape(rShapeRange.maBackShapes, nIndex);
847  nIndex -= nCount;
848  if (xAccessible.is())
849  break;
850  }
851 
852  if (nIndex >= 0)
853  throw lang::IndexOutOfBoundsException();
854 
855  return xAccessible;
856 }
857 
859 {
860  sal_Int32 nCount(0);
861  for (auto const& shape : maShapeRanges)
862  nCount += shape.maForeShapes.size();
863  return nCount;
864 }
865 
866 uno::Reference<XAccessible> ScShapeChildren::GetForeShape(sal_Int32 nIndex) const
867 {
868  uno::Reference<XAccessible> xAccessible;
869  for (const auto& rShapeRange : maShapeRanges)
870  {
871  sal_Int32 nCount(rShapeRange.maForeShapes.size());
872  if(nIndex < nCount)
873  xAccessible = GetAccShape(rShapeRange.maForeShapes, nIndex);
874  nIndex -= nCount;
875  if (xAccessible.is())
876  break;
877  }
878 
879  if (nIndex >= 0)
880  throw lang::IndexOutOfBoundsException();
881 
882  return xAccessible;
883 }
884 
886 {
887  sal_Int32 nCount(0);
888  for (auto const& shape : maShapeRanges)
889  nCount += shape.maControls.size();
890  return nCount;
891 }
892 
893 uno::Reference<XAccessible> ScShapeChildren::GetControl(sal_Int32 nIndex) const
894 {
895  uno::Reference<XAccessible> xAccessible;
896  for (const auto& rShapeRange : maShapeRanges)
897  {
898  sal_Int32 nCount(rShapeRange.maControls.size());
899  if(nIndex < nCount)
900  xAccessible = GetAccShape(rShapeRange.maControls, nIndex);
901  nIndex -= nCount;
902  if (xAccessible.is())
903  break;
904  }
905 
906  if (nIndex >= 0)
907  throw lang::IndexOutOfBoundsException();
908 
909  return xAccessible;
910 }
911 
912 namespace {
913 
914 struct ScShapePointFound
915 {
916  Point maPoint;
917  explicit ScShapePointFound(const awt::Point& rPoint) : maPoint(VCLPoint(rPoint)) {}
918  bool operator() (const ScShapeChild& rShape)
919  {
920  bool bResult(false);
921  if (VCLRectangle(rShape.mpAccShape->getBounds()).Contains(maPoint))
922  bResult = true;
923  return bResult;
924  }
925 };
926 
927 }
928 
929 uno::Reference<XAccessible> ScShapeChildren::GetForegroundShapeAt(const awt::Point& rPoint) const //inclusive Controls
930 {
931  uno::Reference<XAccessible> xAcc;
932 
933  for(const auto& rShapeRange : maShapeRanges)
934  {
935  ScShapeChildVec::const_iterator aFindItr = std::find_if(rShapeRange.maForeShapes.begin(), rShapeRange.maForeShapes.end(), ScShapePointFound(rPoint));
936  if (aFindItr != rShapeRange.maForeShapes.end())
937  xAcc = GetAccShape(*aFindItr);
938  else
939  {
940  ScShapeChildVec::const_iterator aCtrlItr = std::find_if(rShapeRange.maControls.begin(), rShapeRange.maControls.end(), ScShapePointFound(rPoint));
941  if (aCtrlItr != rShapeRange.maControls.end())
942  xAcc = GetAccShape(*aCtrlItr);
943  }
944 
945  if (xAcc.is())
946  break;
947  }
948 
949  return xAcc;
950 }
951 
952 uno::Reference<XAccessible> ScShapeChildren::GetBackgroundShapeAt(const awt::Point& rPoint) const
953 {
954  uno::Reference<XAccessible> xAcc;
955 
956  for(const auto& rShapeRange : maShapeRanges)
957  {
958  ScShapeChildVec::const_iterator aFindItr = std::find_if(rShapeRange.maBackShapes.begin(), rShapeRange.maBackShapes.end(), ScShapePointFound(rPoint));
959  if (aFindItr != rShapeRange.maBackShapes.end())
960  xAcc = GetAccShape(*aFindItr);
961  if (xAcc.is())
962  break;
963  }
964 
965  return xAcc;
966 }
967 
969 {
970  if (!rShape.mpAccShape.is())
971  {
973  ::accessibility::AccessibleShapeInfo aShapeInfo(rShape.mxShape, mpAccDoc);
974 
975  if (mpViewShell)
976  {
978  aShapeTreeInfo.SetSdrView(mpViewShell->GetPreview()->GetDrawView());
979  aShapeTreeInfo.SetController(nullptr);
980  aShapeTreeInfo.SetWindow(mpViewShell->GetWindow());
981  aShapeTreeInfo.SetViewForwarder(&(maShapeRanges[rShape.mnRangeId].maViewForwarder));
982  rShape.mpAccShape = rShapeHandler.CreateAccessibleObject(aShapeInfo, aShapeTreeInfo);
983  if (rShape.mpAccShape.is())
984  {
985  rShape.mpAccShape->Init();
986  }
987  }
988  }
989  return rShape.mpAccShape.get();
990 }
991 
992 ::accessibility::AccessibleShape* ScShapeChildren::GetAccShape(const ScShapeChildVec& rShapes, sal_Int32 nIndex) const
993 {
994  return GetAccShape(rShapes[nIndex]);
995 }
996 
997 void ScShapeChildren::FillShapes(const tools::Rectangle& aPixelPaintRect, const MapMode& aMapMode, sal_uInt8 nRangeId)
998 {
999  OSL_ENSURE(nRangeId < maShapeRanges.size(), "this is not a valid range for draw objects");
1000  SdrPage* pPage = GetDrawPage();
1001  vcl::Window* pWin = mpViewShell->GetWindow();
1002  if (!(pPage && pWin))
1003  return;
1004 
1005  bool bForeAdded(false);
1006  bool bBackAdded(false);
1007  bool bControlAdded(false);
1008  tools::Rectangle aClippedPixelPaintRect(aPixelPaintRect);
1009  if (mpAccDoc)
1010  {
1011  tools::Rectangle aRect2(Point(0,0), mpAccDoc->GetBoundingBoxOnScreen().GetSize());
1012  aClippedPixelPaintRect = aPixelPaintRect.GetIntersection(aRect2);
1013  }
1014  ScIAccessibleViewForwarder aViewForwarder(mpViewShell, mpAccDoc, aMapMode);
1015  maShapeRanges[nRangeId].maViewForwarder = aViewForwarder;
1016  const size_t nCount(pPage->GetObjCount());
1017  for (size_t i = 0; i < nCount; ++i)
1018  {
1019  SdrObject* pObj = pPage->GetObj(i);
1020  if (pObj)
1021  {
1022  uno::Reference< drawing::XShape > xShape(pObj->getUnoShape(), uno::UNO_QUERY);
1023  if (xShape.is())
1024  {
1025  tools::Rectangle aRect(pWin->LogicToPixel(VCLPoint(xShape->getPosition()), aMapMode), pWin->LogicToPixel(VCLSize(xShape->getSize()), aMapMode));
1026  if(!aClippedPixelPaintRect.GetIntersection(aRect).IsEmpty())
1027  {
1028  ScShapeChild aShape;
1029  aShape.mxShape = xShape;
1030  aShape.mnRangeId = nRangeId;
1032  {
1033  maShapeRanges[nRangeId].maForeShapes.push_back(std::move(aShape));
1034  bForeAdded = true;
1035  }
1036  else if (pObj->GetLayer() == SC_LAYER_BACK)
1037  {
1038  maShapeRanges[nRangeId].maBackShapes.push_back(std::move(aShape));
1039  bBackAdded = true;
1040  }
1041  else if (pObj->GetLayer() == SC_LAYER_CONTROLS)
1042  {
1043  maShapeRanges[nRangeId].maControls.push_back(std::move(aShape));
1044  bControlAdded = true;
1045  }
1046  else
1047  {
1048  OSL_FAIL("I don't know this layer.");
1049  }
1050  }
1051  }
1052  }
1053  }
1054  if (bForeAdded)
1055  std::sort(maShapeRanges[nRangeId].maForeShapes.begin(), maShapeRanges[nRangeId].maForeShapes.end(),ScShapeChildLess());
1056  if (bBackAdded)
1057  std::sort(maShapeRanges[nRangeId].maBackShapes.begin(), maShapeRanges[nRangeId].maBackShapes.end(),ScShapeChildLess());
1058  if (bControlAdded)
1059  std::sort(maShapeRanges[nRangeId].maControls.begin(), maShapeRanges[nRangeId].maControls.end(),ScShapeChildLess());
1060 }
1061 
1063 {
1065  SdrPage* pDrawPage = nullptr;
1066  ScDocument& rDoc = mpViewShell->GetDocument();
1067  if (rDoc.GetDrawLayer())
1068  {
1069  ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
1070  if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab))
1071  pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(static_cast<sal_Int16>(nTab)));
1072  }
1073  return pDrawPage;
1074 }
1075 
1076 namespace {
1077 
1078 struct ScPagePreviewCountData
1079 {
1080  // order is background shapes, header, table or notes, footer, foreground shapes, controls
1081 
1082  tools::Rectangle aVisRect;
1083  tools::Long nBackShapes;
1084  tools::Long nHeaders;
1085  tools::Long nTables;
1086  tools::Long nNoteParagraphs;
1087  tools::Long nFooters;
1088  tools::Long nForeShapes;
1089  tools::Long nControls;
1090 
1091  ScPagePreviewCountData( const ScPreviewLocationData& rData, const vcl::Window* pSizeWindow,
1092  const ScNotesChildren* pNotesChildren, const ScShapeChildren* pShapeChildren );
1093 
1094  tools::Long GetTotal() const
1095  {
1096  return nBackShapes + nHeaders + nTables + nNoteParagraphs + nFooters + nForeShapes + nControls;
1097  }
1098 };
1099 
1100 }
1101 
1102 ScPagePreviewCountData::ScPagePreviewCountData( const ScPreviewLocationData& rData,
1103  const vcl::Window* pSizeWindow, const ScNotesChildren* pNotesChildren,
1104  const ScShapeChildren* pShapeChildren) :
1105  nBackShapes( 0 ),
1106  nHeaders( 0 ),
1107  nTables( 0 ),
1108  nNoteParagraphs( 0 ),
1109  nFooters( 0 ),
1110  nForeShapes( 0 ),
1111  nControls( 0 )
1112 {
1113  Size aOutputSize;
1114  if ( pSizeWindow )
1115  aOutputSize = pSizeWindow->GetOutputSizePixel();
1116  aVisRect = tools::Rectangle( Point(), aOutputSize );
1117 
1118  tools::Rectangle aObjRect;
1119 
1120  if ( rData.GetHeaderPosition( aObjRect ) && aObjRect.Overlaps( aVisRect ) )
1121  nHeaders = 1;
1122 
1123  if ( rData.GetFooterPosition( aObjRect ) && aObjRect.Overlaps( aVisRect ) )
1124  nFooters = 1;
1125 
1126  if ( rData.HasCellsInRange( aVisRect ) )
1127  nTables = 1;
1128 
1130  nBackShapes = pShapeChildren->GetBackShapeCount();
1131  nForeShapes = pShapeChildren->GetForeShapeCount();
1132  nControls = pShapeChildren->GetControlCount();
1133 
1134  // there are only notes if there is no table
1135  if (nTables == 0)
1136  nNoteParagraphs = pNotesChildren->GetChildrenCount();
1137 }
1138 
1139 //===== internal ========================================================
1140 
1142  const uno::Reference<XAccessible>& rxParent, ScPreviewShell* pViewShell ) :
1143  ScAccessibleDocumentBase(rxParent),
1144  mpViewShell(pViewShell)
1145 {
1146  if (pViewShell)
1147  pViewShell->AddAccessibilityObject(*this);
1148 
1149 }
1150 
1152 {
1153  if (!ScAccessibleDocumentBase::IsDefunc() && !rBHelper.bInDispose)
1154  {
1155  // increment refcount to prevent double call off dtor
1156  osl_atomic_increment( &m_refCount );
1157  // call dispose to inform object which have a weak reference to this object
1158  dispose();
1159  }
1160 }
1161 
1163 {
1164  SolarMutexGuard aGuard;
1165  mpTable.clear();
1166  mpHeader.clear();
1167  mpFooter.clear();
1168 
1169  if (mpViewShell)
1170  {
1172  mpViewShell = nullptr;
1173  }
1174 
1175  // no need to Dispose the AccessibleTextHelper,
1176  // as long as mpNotesChildren are destructed here
1177  mpNotesChildren.reset();
1178 
1179  mpShapeChildren.reset();
1180 
1182 }
1183 
1184 //===== SfxListener =====================================================
1185 
1187 {
1188  if ( dynamic_cast<const ScAccWinFocusLostHint*>(&rHint) )
1189  {
1190  CommitFocusLost();
1191  }
1192  else if ( dynamic_cast<const ScAccWinFocusGotHint*>(&rHint) )
1193  {
1195  }
1196  else
1197  {
1198  // only notify if child exist, otherwise it is not necessary
1199  if (rHint.GetId() == SfxHintId::ScDataChanged)
1200  {
1201  if (mpTable.is()) // if there is no table there is nothing to notify, because no one recognizes the change
1202  {
1203  {
1204  uno::Reference<XAccessible> xAcc = mpTable;
1205  AccessibleEventObject aEvent;
1206  aEvent.EventId = AccessibleEventId::CHILD;
1207  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1208  aEvent.OldValue <<= xAcc;
1209  CommitChange(aEvent);
1210  }
1211 
1212  mpTable->dispose();
1213  mpTable.clear();
1214  }
1215 
1216  Size aOutputSize;
1217  vcl::Window* pSizeWindow = mpViewShell->GetWindow();
1218  if ( pSizeWindow )
1219  aOutputSize = pSizeWindow->GetOutputSizePixel();
1220  tools::Rectangle aVisRect( Point(), aOutputSize );
1221  GetNotesChildren()->DataChanged(aVisRect);
1222 
1224 
1226  ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1227 
1228  if (aCount.nTables > 0)
1229  {
1231  sal_Int32 nIndex (aCount.nBackShapes + aCount.nHeaders);
1232 
1233  mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex );
1234  mpTable->Init();
1235 
1236  {
1237  uno::Reference<XAccessible> xAcc = mpTable;
1238  AccessibleEventObject aEvent;
1239  aEvent.EventId = AccessibleEventId::CHILD;
1240  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1241  aEvent.NewValue <<= xAcc;
1242  CommitChange(aEvent);
1243  }
1244  }
1245  }
1246  else if (rHint.GetId() == SfxHintId::ScAccVisAreaChanged)
1247  {
1248  Size aOutputSize;
1249  vcl::Window* pSizeWindow = mpViewShell->GetWindow();
1250  if ( pSizeWindow )
1251  aOutputSize = pSizeWindow->GetOutputSizePixel();
1252  tools::Rectangle aVisRect( Point(), aOutputSize );
1253  GetNotesChildren()->DataChanged(aVisRect);
1254 
1256 
1257  AccessibleEventObject aEvent;
1258  aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
1259  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1260  CommitChange(aEvent);
1261  }
1262  }
1264 }
1265 
1266 //===== XAccessibleComponent ============================================
1267 
1268 uno::Reference< XAccessible > SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleAtPoint( const awt::Point& rPoint )
1269 {
1270  uno::Reference<XAccessible> xAccessible;
1271  if (containsPoint(rPoint))
1272  {
1273  SolarMutexGuard aGuard;
1274  IsObjectValid();
1275 
1276  if ( mpViewShell )
1277  {
1278  xAccessible = GetShapeChildren()->GetForegroundShapeAt(rPoint);
1279  if (!xAccessible.is())
1280  {
1282  ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1283 
1284  if ( !mpTable.is() && (aCount.nTables > 0) )
1285  {
1287  sal_Int32 nIndex (aCount.nBackShapes + aCount.nHeaders);
1288 
1289  mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex );
1290  mpTable->Init();
1291  }
1292  if (mpTable.is() && VCLRectangle(mpTable->getBounds()).Contains(VCLPoint(rPoint)))
1293  xAccessible = mpTable.get();
1294  }
1295  if (!xAccessible.is())
1296  xAccessible = GetNotesChildren()->GetAt(rPoint);
1297  if (!xAccessible.is())
1298  {
1299  if (!mpHeader.is() || !mpFooter.is())
1300  {
1302  ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1303 
1304  if (!mpHeader.is())
1305  {
1306  mpHeader = new ScAccessiblePageHeader( this, mpViewShell, true, aCount.nBackShapes + aCount.nHeaders - 1);
1307  }
1308  if (!mpFooter.is())
1309  {
1310  mpFooter = new ScAccessiblePageHeader( this, mpViewShell, false, aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters - 1 );
1311  }
1312  }
1313 
1314  Point aPoint(VCLPoint(rPoint));
1315 
1316  if (VCLRectangle(mpHeader->getBounds()).Contains(aPoint))
1317  xAccessible = mpHeader.get();
1318  else if (VCLRectangle(mpFooter->getBounds()).Contains(aPoint))
1319  xAccessible = mpFooter.get();
1320  }
1321  if (!xAccessible.is())
1322  xAccessible = GetShapeChildren()->GetBackgroundShapeAt(rPoint);
1323  }
1324  }
1325 
1326  return xAccessible;
1327 }
1328 
1330 {
1331  SolarMutexGuard aGuard;
1332  IsObjectValid();
1333  if (getAccessibleParent().is())
1334  {
1335  uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1336  if (xAccessibleComponent.is())
1337  {
1338  // just grab the focus for the window
1339  xAccessibleComponent->grabFocus();
1340  }
1341  }
1342 }
1343 
1344 //===== XAccessibleContext ==============================================
1345 
1347 {
1348  SolarMutexGuard aGuard;
1349  IsObjectValid();
1350 
1351  tools::Long nRet = 0;
1352  if ( mpViewShell )
1353  {
1354  ScPagePreviewCountData aCount( mpViewShell->GetLocationData(), mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1355  nRet = aCount.GetTotal();
1356  }
1357 
1358  return nRet;
1359 }
1360 
1361 uno::Reference<XAccessible> SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleChild(sal_Int32 nIndex)
1362 {
1363  SolarMutexGuard aGuard;
1364  IsObjectValid();
1365  uno::Reference<XAccessible> xAccessible;
1366 
1367  if ( mpViewShell )
1368  {
1370  ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1371 
1372  if ( nIndex < aCount.nBackShapes )
1373  {
1374  xAccessible = GetShapeChildren()->GetBackShape(nIndex);
1375  }
1376  else if ( nIndex < aCount.nBackShapes + aCount.nHeaders )
1377  {
1378  if ( !mpHeader.is() )
1379  {
1380  mpHeader = new ScAccessiblePageHeader( this, mpViewShell, true, nIndex );
1381  }
1382 
1383  xAccessible = mpHeader.get();
1384  }
1385  else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nTables )
1386  {
1387  if ( !mpTable.is() )
1388  {
1389  mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex );
1390  mpTable->Init();
1391  }
1392  xAccessible = mpTable.get();
1393  }
1394  else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nNoteParagraphs )
1395  {
1396  xAccessible = GetNotesChildren()->GetChild(nIndex - aCount.nBackShapes - aCount.nHeaders);
1397  }
1398  else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters )
1399  {
1400  if ( !mpFooter.is() )
1401  {
1402  mpFooter = new ScAccessiblePageHeader( this, mpViewShell, false, nIndex );
1403  }
1404  xAccessible = mpFooter.get();
1405  }
1406  else
1407  {
1408  sal_Int32 nIdx(nIndex - (aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters));
1409  if (nIdx < aCount.nForeShapes)
1410  xAccessible = GetShapeChildren()->GetForeShape(nIdx);
1411  else
1412  xAccessible = GetShapeChildren()->GetControl(nIdx - aCount.nForeShapes);
1413  }
1414  }
1415 
1416  if ( !xAccessible.is() )
1417  throw lang::IndexOutOfBoundsException();
1418 
1419  return xAccessible;
1420 }
1421 
1423 uno::Reference<XAccessibleStateSet> SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleStateSet()
1424 {
1425  SolarMutexGuard aGuard;
1426  uno::Reference<XAccessibleStateSet> xParentStates;
1427  if (getAccessibleParent().is())
1428  {
1429  uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1430  xParentStates = xParentContext->getAccessibleStateSet();
1431  }
1433  if (IsDefunc(xParentStates))
1434  pStateSet->AddState(AccessibleStateType::DEFUNC);
1435  else
1436  {
1437  // never editable
1438  pStateSet->AddState(AccessibleStateType::ENABLED);
1439  pStateSet->AddState(AccessibleStateType::OPAQUE);
1440  if (isShowing())
1441  pStateSet->AddState(AccessibleStateType::SHOWING);
1442  if (isVisible())
1443  pStateSet->AddState(AccessibleStateType::VISIBLE);
1444  }
1445  return pStateSet;
1446 }
1447 
1448  //===== XServiceInfo ====================================================
1449 
1451 {
1452  return "ScAccessibleDocumentPagePreview";
1453 }
1454 
1456 {
1457  const css::uno::Sequence<OUString> vals { "com.sun.star.AccessibleSpreadsheetPageView" };
1459 }
1460 
1461 //===== XTypeProvider =======================================================
1462 
1463 uno::Sequence<sal_Int8> SAL_CALL
1465 {
1466  return css::uno::Sequence<sal_Int8>();
1467 }
1468 
1469 //===== internal ========================================================
1470 
1472 {
1473  return STR_ACC_PREVIEWDOC_DESCR;
1474 }
1475 
1477 {
1478  OUString sName = ScResId(STR_ACC_PREVIEWDOC_NAME);
1479  return sName;
1480 }
1481 
1483 {
1484  tools::Rectangle aRect;
1485  if (mpViewShell)
1486  {
1487  vcl::Window* pWindow = mpViewShell->GetWindow();
1488  if (pWindow)
1489  aRect = pWindow->GetWindowExtentsRelative(nullptr);
1490  }
1491  return aRect;
1492 }
1493 
1495 {
1496  tools::Rectangle aRect;
1497  if (mpViewShell)
1498  {
1499  vcl::Window* pWindow = mpViewShell->GetWindow();
1500  if (pWindow)
1501  aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
1502  }
1503  return aRect;
1504 }
1505 
1507  const uno::Reference<XAccessibleStateSet>& rxParentStates)
1508 {
1510  (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
1511 }
1512 
1514 {
1515  if (!mpNotesChildren && mpViewShell)
1516  {
1517  mpNotesChildren.reset( new ScNotesChildren(mpViewShell, this) );
1518 
1520  ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1521 
1523  mpNotesChildren->Init(aCount.aVisRect, aCount.nBackShapes + aCount.nHeaders);
1524  }
1525  return mpNotesChildren.get();
1526 }
1527 
1529 {
1530  if (!mpShapeChildren && mpViewShell)
1531  {
1532  mpShapeChildren.reset( new ScShapeChildren(mpViewShell, this) );
1533  mpShapeChildren->Init();
1534  }
1535 
1536  return mpShapeChildren.get();
1537 }
1538 
1540 {
1541  SolarMutexGuard g;
1542 
1543  OUString aName = ScResId(STR_ACC_DOC_SPREADSHEET);
1544  ScDocument& rScDoc = mpViewShell->GetDocument();
1545 
1546  SfxObjectShell* pObjSh = rScDoc.GetDocumentShell();
1547  if (!pObjSh)
1548  return aName;
1549 
1550  OUString aFileName;
1551  SfxMedium* pMed = pObjSh->GetMedium();
1552  if (pMed)
1553  aFileName = pMed->GetName();
1554 
1555  if (aFileName.isEmpty())
1556  aFileName = pObjSh->GetTitle(SFX_TITLE_APINAME);
1557 
1558  if (!aFileName.isEmpty())
1559  {
1560  aName = aFileName + " - " + aName + ScResId(STR_ACC_DOC_PREVIEW_SUFFIX);
1561 
1562  }
1563 
1564  return aName;
1565 }
1566 
1567 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetPos(const Point &rPoint)
const ScPreviewLocationData & GetLocationData()
Definition: prevwsh.cxx:1178
void AddAccessibilityObject(SfxListener &rObject)
Definition: prevwsh.cxx:1149
sal_Int32 nIndex
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:89
virtual void SAL_CALL disposing() override
sal_Int32 AddNotes(const ScPreviewLocationData &rData, const tools::Rectangle &rVisRect, bool bMark, ScAccNotes &rNotes)
SCROW Row() const
Definition: address.hxx:261
OUString GetTitle(sal_uInt16 nMaxLen=0) const
signed char sal_Int8
bool Contains(const Point &rPOINT) const
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(const css::awt::Point &rPoint) override
===== XAccessibleComponent ============================================
ULONG m_refCount
vcl::Window * GetAccessibleParentWindow() const
const OUString & GetName() const
std::unique_ptr< ScNotesChildren > mpNotesChildren
long Long
void FillShapes(const tools::Rectangle &aPixelPaintRect, const MapMode &aMapMode, sal_uInt8 nRangeId)
void Init(const tools::Rectangle &rVisRect, sal_Int32 nOffset)
const ContentProperties & rData
constexpr SdrLayerID SC_LAYER_BACK(1)
virtual OUString SAL_CALL getAccessibleName() override
Return the object's current name.
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
Return a reference to the parent.
ScNotesChildren(ScPreviewShell *pViewShell, ScAccessibleDocumentPagePreview *pAccDoc)
rtl::Reference< AccessibleShape > CreateAccessibleObject(const AccessibleShapeInfo &rShapeInfo, const AccessibleShapeTreeInfo &rShapeTreeInfo) const
static sal_Int8 CompareCell(const ScAddress &aCell1, const ScAddress &aCell2)
#define SC_PREVIEW_MAXRANGES
Definition: prevloc.hxx:33
uno::Reference< XAccessible > GetControl(sal_Int32 nIndex) const
virtual sal_Bool SAL_CALL containsPoint(const css::awt::Point &rPoint) override
===== XAccessibleComponent ============================================
uno::Reference< XAccessible > GetForegroundShapeAt(const awt::Point &rPoint) const
sal_Int32 mnParaCount
SfxHintId GetId() const
virtual sal_Int32 SAL_CALL getAccessibleChildCount() override
===== XAccessibleContext ==============================================
virtual OUString createAccessibleDescription() override
===== internal ========================================================
void SetOffset(const Point &rPoint)
uno::Reference< drawing::XShape > const mxShape
SC_DLLPUBLIC ScPostIt * GetNote(const ScAddress &rPos)
Notes.
Definition: document.cxx:6517
sal_Int32 CheckChanges(const ScPreviewLocationData &rData, const tools::Rectangle &rVisRect, bool bMark, ScAccNotes &rOldNotes, ScAccNotes &rNewNotes, ScXAccVector &rOldParas, ScXAccVector &rNewParas)
bool GetNoteInRange(const tools::Rectangle &rVisiblePixel, tools::Long nIndex, bool bNoteMarks, ScAddress &rCellPos, tools::Rectangle &rNoteRect) const
Definition: prevloc.cxx:404
virtual tools::Rectangle GetVisibleArea() const =0
virtual bool ReplaceChild(::accessibility::AccessibleShape *pCurrentChild, const css::uno::Reference< css::drawing::XShape > &_rxShape, const tools::Long _nIndex, const ::accessibility::AccessibleShapeTreeInfo &_rShapeTreeInfo) override
===== IAccessibleParent ==============================================
Additional class containing cell annotation data.
Definition: postit.hxx:161
int nCount
virtual css::uno::Reference< css::drawing::XShape > getUnoShape()
std::vector< ScShapeChild > ScShapeChildVec
virtual OUString SAL_CALL getImplementationName() override
===== XServiceInfo ====================================================
void SetController(const css::uno::Reference< css::frame::XController > &rxController)
sal_Int32 GetChildrenCount() const
SCTAB GetPrintTab() const
Definition: prevloc.hxx:117
SCTAB Tab() const
Definition: address.hxx:270
virtual OUString createAccessibleName() override
Return the object's current name.
tools::Rectangle GetIntersection(const tools::Rectangle &rRect) const
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
===== SfxListener =====================================================
ScDocument * GetDocument() const
tools::Rectangle GetWindowExtentsRelative(const vcl::Window *pRelativeWindow) const
bool HasObjects() const
Definition: drwlayer.cxx:357
const char * sName
ScPreview * GetPreview()
Definition: prevwsh.hxx:115
::accessibility::AccessibleShape * GetAccShape(const ScShapeChild &rShape) const
constexpr bool IsEmpty() const
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Returns a list of all supported services.
sal_Int32 GetControlCount() const
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1058
bool GetFooterPosition(tools::Rectangle &rFooterRect) const
Definition: prevloc.cxx:348
#define SFX_TITLE_APINAME
Point LogicToPixel(const Point &rLogicPt) const
virtual css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet() override
Return the set of current states.
std::unique_ptr< ScShapeChildren > mpShapeChildren
int i
#define STR_ACC_PREVIEWDOC_DESCR
Definition: strings.hxx:17
uno::Reference< XAccessible > GetChild(sal_Int32 nIndex) const
bool HasCellsInRange(const tools::Rectangle &rVisiblePixel) const
Definition: prevloc.cxx:322
bool Overlaps(const tools::Rectangle &rRect) const
inline::tools::Rectangle VCLRectangle(const css::awt::Rectangle &rAWTRect)
void SetEventSource(const css::uno::Reference< css::accessibility::XAccessible > &rInterface)
void SetSize(const Size &rSize)
void SetWindow(vcl::Window *pWindow)
const SdrPage * GetPage(sal_uInt16 nPgNum) const
void CommitFocusGained() const
Calls all FocusListener to tell they that the focus is gained.
static ShapeTypeHandler & Instance()
ScAccessibleDocumentPagePreview * mpAccDoc
ScShapeChildren(ScPreviewShell *pViewShell, ScAccessibleDocumentPagePreview *pAccDoc)
static void CollectChildren(const ScAccNote &rNote, ScXAccVector &rVector)
ScAccessibleDocumentPagePreview(const css::uno::Reference< css::accessibility::XAccessible > &rxParent, ScPreviewShell *pViewShell)
inline::Point VCLPoint(const css::awt::Point &rAWTPoint)
rtl::Reference< ScAccessiblePreviewTable > mpTable
sal_uInt16 GetDrawRanges() const
Definition: prevloc.hxx:122
Point PixelToLogic(const Point &rDevicePt) const
uno::Reference< XAccessible > GetBackgroundShapeAt(const awt::Point &rPoint) const
css::uno::Sequence< T > concatSequences(const css::uno::Sequence< T > &rS1, const Ss &...rSn)
virtual Point LogicToPixel(const Point &rPoint) const =0
SCCOL Col() const
Definition: address.hxx:266
std::vector< ScAccNote > ScAccNotes
constexpr Point TopLeft() const
virtual SdrLayerID GetLayer() const
vcl::Window * GetWindow(GetWindowType nType) const
void SetViewForwarder(const IAccessibleViewForwarder *pViewForwarder)
::accessibility::AccessibleTextHelper * CreateTextHelper(const OUString &rString, const tools::Rectangle &rVisRect, const ScAddress &aCellPos, bool bMarkNote, sal_Int32 nChildOffset) const
inline::Size VCLSize(const css::awt::Size &rAWTSize)
std::vector< uno::Reference< XAccessible > > ScXAccVector
constexpr Size GetSize() const
virtual tools::Rectangle GetBoundingBoxOnScreen() const override
Return the object's current bounding box relative to the desktop.
virtual void SAL_CALL disposing() override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Returns a list of all supported services.
std::vector< ScShapeRange > ScShapeRangeVec
B2DPoint maPoint
void RemoveAccessibilityObject(SfxListener &rObject)
Definition: prevwsh.cxx:1157
virtual tools::Rectangle GetBoundingBox() const override
Return the object's current bounding box relative to the parent object.
uno::Reference< XAccessible > GetForeShape(sal_Int32 nIndex) const
unsigned char sal_uInt8
rtl::Reference< ScAccessiblePageHeader > mpFooter
tools::Long GetNoteCountInRange(const tools::Rectangle &rVisiblePixel, bool bNoteMarks) const
Definition: prevloc.cxx:390
void FindChanged(ScShapeChildVec &aOld, ScShapeChildVec &aNew) const
void Init()
===== Internal ========================================================
virtual void SAL_CALL grabFocus() override
constexpr SdrLayerID SC_LAYER_FRONT(0)
OUString aName
ScAccessibleDocumentPagePreview * mpAccDoc
constexpr SdrLayerID SC_LAYER_INTERN(2)
sal_Int32 GetBackShapeCount() const
void GetDrawRange(sal_uInt16 nPos, tools::Rectangle &rPixelRect, MapMode &rMapMode, sal_uInt8 &rRangeId) const
Definition: prevloc.cxx:256
void CommitFocusLost() const
Calls all FocusListener to tell they that the focus is lost.
ScDocument & GetDocument()
Definition: prevwsh.cxx:1183
vcl::Window * GetWindow() const
FmFormView * GetDrawView()
Definition: preview.hxx:157
sal_Int32 GetForeShapeCount() const
void DataChanged(const tools::Rectangle &rVisRect)
Size GetOutputSizePixel() const
void CommitChange(const css::accessibility::AccessibleEventObject &rEvent) const
Calls all Listener to tell they the change.
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1057
uno::Reference< XAccessible > GetBackShape(sal_Int32 nIndex) const
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
===== SfxListener =====================================================
uno::Reference< XAccessible > GetAt(const awt::Point &rPoint) const
void dispose()
int mnIndex
void SetStartIndex(sal_Int32 nOffset)
rtl::Reference< ScAccessiblePageHeader > mpHeader
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int32 nIndex) override
Return the specified child or NULL if index is invalid.
constexpr SdrLayerID SC_LAYER_CONTROLS(3)
AnyEventRef aEvent
sal_uInt16 GetPageCount() const
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
===== XTypeProvider ===================================================
css::uno::Reference< css::accessibility::XAccessible > GetChild(sal_Int32 i)
sal_Int16 SCTAB
Definition: types.hxx:22
bool anyOf(strong_int v) const
bool GetHeaderPosition(tools::Rectangle &rHeaderRect) const
Definition: prevloc.cxx:334
virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext() override
===== XAccessible =====================================================
SfxMedium * GetMedium() const