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 
41 #include <tools/gen.hxx>
42 #include <svx/fmview.hxx>
43 #include <svx/svdpage.hxx>
44 #include <svx/svdobj.hxx>
46 #include <svx/AccessibleShape.hxx>
50 #include <svx/ShapeTypeHandler.hxx>
52 #include <vcl/svapp.hxx>
53 #include <sfx2/docfile.hxx>
54 
55 #include <vector>
56 #include <algorithm>
57 #include <memory>
58 #include <utility>
59 
60 using namespace ::com::sun::star;
61 using namespace ::com::sun::star::accessibility;
62 
63 typedef std::vector< uno::Reference< XAccessible > > ScXAccVector;
64 
65 namespace {
66 
67 struct ScAccNote
68 {
69  OUString maNoteText;
70  tools::Rectangle maRect;
71  ScAddress maNoteCell;
73  sal_Int32 mnParaCount;
74  bool mbMarkNote;
75 
76  ScAccNote()
77  : mpTextHelper(nullptr)
78  , mnParaCount(0)
79  , mbMarkNote(false)
80  {
81  }
82 };
83 
84 }
85 
87 {
88 public:
91  void Init(const tools::Rectangle& rVisRect, sal_Int32 nOffset);
92 
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;
96 
97  void DataChanged(const tools::Rectangle& rVisRect);
98 
99 private:
102  typedef std::vector<ScAccNote> ScAccNotes;
103  mutable ScAccNotes maNotes;
104  mutable ScAccNotes maMarks;
105  sal_Int32 mnParagraphs;
106  sal_Int32 mnOffset;
107 
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);
110 
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);
116 
117  inline ScDocument* GetDocument() const;
118 };
119 
121  : mpViewShell(pViewShell),
122  mpAccDoc(pAccDoc),
123  mnParagraphs(0),
124  mnOffset(0)
125 {
126 }
127 
129 {
130  for (auto & i : maNotes)
131  if (i.mpTextHelper)
132  {
133  delete i.mpTextHelper;
134  i.mpTextHelper = nullptr;
135  }
136  for (auto & i : maMarks)
137  if (i.mpTextHelper)
138  {
139  delete i.mpTextHelper;
140  i.mpTextHelper = nullptr;
141  }
142 }
143 
144 ::accessibility::AccessibleTextHelper* ScNotesChildren::CreateTextHelper(const OUString& rString, const tools::Rectangle& rVisRect, const ScAddress& aCellPos, bool bMarkNote, sal_Int32 nChildOffset) const
145 {
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());
150 
151  return pTextHelper;
152 }
153 
154 sal_Int32 ScNotesChildren::AddNotes(const ScPreviewLocationData& rData, const tools::Rectangle& rVisRect, bool bMark, ScAccNotes& rNotes)
155 {
156  sal_Int32 nCount = rData.GetNoteCountInRange(rVisRect, bMark);
157 
158  rNotes.reserve(nCount);
159 
160  sal_Int32 nParagraphs(0);
161  ScDocument* pDoc = GetDocument();
162  if (pDoc)
163  {
164  ScAccNote aNote;
165  aNote.mbMarkNote = bMark;
166  if (bMark)
167  aNote.mnParaCount = 1;
168  for (sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex)
169  {
170  if (rData.GetNoteInRange(rVisRect, nIndex, bMark, aNote.maNoteCell, aNote.maRect))
171  {
172  if (bMark)
173  {
174  // Document not needed, because only the cell address, but not the tablename is needed
175  aNote.maNoteText = aNote.maNoteCell.Format(ScRefFlags::VALID);
176  }
177  else
178  {
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();
184  }
185  nParagraphs += aNote.mnParaCount;
186  rNotes.push_back(aNote);
187  }
188  }
189  }
190  return nParagraphs;
191 }
192 
193 void ScNotesChildren::Init(const tools::Rectangle& rVisRect, sal_Int32 nOffset)
194 {
195  if (mpViewShell && !mnParagraphs)
196  {
197  mnOffset = nOffset;
199 
200  mnParagraphs = AddNotes(rData, rVisRect, false, maMarks);
201  mnParagraphs += AddNotes(rData, rVisRect, true, maNotes);
202  }
203 }
204 
205 namespace {
206 
207 struct ScParaFound
208 {
209  sal_Int32 mnIndex;
210  explicit ScParaFound(sal_Int32 nIndex) : mnIndex(nIndex) {}
211  bool operator() (const ScAccNote& rNote)
212  {
213  bool bResult(false);
214  if (rNote.mnParaCount > mnIndex)
215  bResult = true;
216  else
217  mnIndex -= rNote.mnParaCount;
218  return bResult;
219  }
220 };
221 
222 }
223 
224 uno::Reference<XAccessible> ScNotesChildren::GetChild(sal_Int32 nIndex) const
225 {
226  uno::Reference<XAccessible> xAccessible;
227 
228  if (nIndex < mnParagraphs)
229  {
230  if (nIndex < static_cast<sal_Int32>(maMarks.size()))
231  {
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)
236  {
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());
241  }
242  else
243  {
244  OSL_FAIL("wrong note found");
245  }
246  }
247  else
248  {
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)
254  {
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());
258  }
259  }
260  }
261 
262  return xAccessible;
263 }
264 
265 namespace {
266 
267 struct ScPointFound
268 {
270  sal_Int32 mnParagraphs;
271  explicit ScPointFound(const Point& rPoint) : maPoint(rPoint, Size(0, 0)), mnParagraphs(0) {}
272  bool operator() (const ScAccNote& rNote)
273  {
274  bool bResult(false);
275  if (maPoint.IsInside(rNote.maRect))
276  bResult = true;
277  else
278  mnParagraphs += rNote.mnParaCount;
279  return bResult;
280  }
281 };
282 
283 }
284 
285 uno::Reference<XAccessible> ScNotesChildren::GetAt(const awt::Point& rPoint) const
286 {
287  uno::Reference<XAccessible> xAccessible;
288 
289  ScPointFound aPointFound(Point(rPoint.X, rPoint.Y));
290 
291  ScAccNotes::iterator aEndItr = maMarks.end();
292  ScAccNotes::iterator aItr = std::find_if(maMarks.begin(), aEndItr, aPointFound);
293  if (aEndItr == aItr)
294  {
295  aEndItr = maNotes.end();
296  aItr = std::find_if(maNotes.begin(), aEndItr, aPointFound);
297  }
298  if (aEndItr != aItr)
299  {
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);
303  }
304 
305  return xAccessible;
306 }
307 
309 {
310  OSL_ENSURE(aCell1.Tab() == aCell2.Tab(), "the notes should be on the same table");
311  sal_Int8 nResult(0);
312  if (aCell1 != aCell2)
313  {
314  if (aCell1.Row() == aCell2.Row())
315  nResult = (aCell1.Col() < aCell2.Col()) ? -1 : 1;
316  else
317  nResult = (aCell1.Row() < aCell2.Row()) ? -1 : 1;
318  }
319  return nResult;
320 }
321 
322 void ScNotesChildren::CollectChildren(const ScAccNote& rNote, ScXAccVector& rVector)
323 {
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()));
327 }
328 
330  const tools::Rectangle& rVisRect, bool bMark, ScAccNotes& rOldNotes,
331  ScAccNotes& rNewNotes, ScXAccVector& rOldParas, ScXAccVector& rNewParas)
332 {
333  sal_Int32 nCount = rData.GetNoteCountInRange(rVisRect, bMark);
334 
335  rNewNotes.reserve(nCount);
336 
337  sal_Int32 nParagraphs(0);
338  ScDocument* pDoc = GetDocument();
339  if (pDoc)
340  {
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)
349  {
350  if (rData.GetNoteInRange(rVisRect, nIndex, bMark, aNote.maNoteCell, aNote.maRect))
351  {
352  if (bMark)
353  {
354  // Document not needed, because only the cell address, but not the tablename is needed
355  aNote.maNoteText = aNote.maNoteCell.Format(ScRefFlags::VALID);
356  }
357  else
358  {
359  if( ScPostIt* pNote = pDoc->GetNote( aNote.maNoteCell ) )
360  aNote.maNoteText = pNote->GetText();
361  }
362 
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)
367  {
368  if (aNote.maNoteText == aItr->maNoteText)
369  {
370  aNote.mpTextHelper = aItr->mpTextHelper;
371  if (aNote.maRect != aItr->maRect) // set new VisArea
372  {
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
377  }
378  }
379  else
380  {
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);
390  }
391  bAddNote = true;
392  // not necessary, because this branch should not be reached if it is the end
393  //if (aItr != aEndItr)
394  ++aItr;
395  }
396  else if (nCompare < 0)
397  {
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;
404  }
405  else
406  {
407  // collect removed children
408  CollectChildren(*aItr, rOldParas);
409  delete aItr->mpTextHelper;
410  aItr->mpTextHelper = nullptr;
411 
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;
416  }
417  if (bAddNote)
418  {
419  nParagraphs += aNote.mnParaCount;
420  rNewNotes.push_back(aNote);
421  bAddNote = false;
422  }
423  }
424  }
425  }
426  return nParagraphs;
427 }
428 
429 namespace {
430 
431 struct ScChildGone
432 {
434  explicit ScChildGone(ScAccessibleDocumentPagePreview* pAccDoc) : mpAccDoc(pAccDoc) {}
435  void operator() (const uno::Reference<XAccessible>& xAccessible) const
436  {
437  if (mpAccDoc)
438  {
439  AccessibleEventObject aEvent;
440  aEvent.EventId = AccessibleEventId::CHILD;
441  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccDoc);
442  aEvent.OldValue <<= xAccessible;
443 
444  mpAccDoc->CommitChange(aEvent); // gone child - event
445  }
446  }
447 };
448 
449 struct ScChildNew
450 {
452  explicit ScChildNew(ScAccessibleDocumentPagePreview* pAccDoc) : mpAccDoc(pAccDoc) {}
453  void operator() (const uno::Reference<XAccessible>& xAccessible) const
454  {
455  if (mpAccDoc)
456  {
457  AccessibleEventObject aEvent;
458  aEvent.EventId = AccessibleEventId::CHILD;
459  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccDoc);
460  aEvent.NewValue <<= xAccessible;
461 
462  mpAccDoc->CommitChange(aEvent); // new child - event
463  }
464  }
465 };
466 
467 }
468 
470 {
471  if (!(mpViewShell && mpAccDoc))
472  return;
473 
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;
482 
483  std::for_each(aOldParas.begin(), aOldParas.end(), ScChildGone(mpAccDoc));
484  std::for_each(aNewParas.begin(), aNewParas.end(), ScChildNew(mpAccDoc));
485 }
486 
488 {
489  ScDocument* pDoc = nullptr;
490  if (mpViewShell)
491  pDoc = &mpViewShell->GetDocument();
492  return pDoc;
493 }
494 
495 namespace {
496 
497 class ScIAccessibleViewForwarder : public ::accessibility::IAccessibleViewForwarder
498 {
499 public:
500  ScIAccessibleViewForwarder();
501  ScIAccessibleViewForwarder(ScPreviewShell* pViewShell,
503  const MapMode& aMapMode);
504 
506 
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;
510 
511 private:
512  ScPreviewShell* mpViewShell;
514  MapMode maMapMode;
515 };
516 
517 }
518 
519 ScIAccessibleViewForwarder::ScIAccessibleViewForwarder()
520  : mpViewShell(nullptr), mpAccDoc(nullptr)
521 {
522 }
523 
524 ScIAccessibleViewForwarder::ScIAccessibleViewForwarder(ScPreviewShell* pViewShell,
526  const MapMode& aMapMode)
527  : mpViewShell(pViewShell),
528  mpAccDoc(pAccDoc),
529  maMapMode(aMapMode)
530 {
531 }
532 
534 
535 tools::Rectangle ScIAccessibleViewForwarder::GetVisibleArea() const
536 {
537  SolarMutexGuard aGuard;
538  tools::Rectangle aVisRect;
539  vcl::Window* pWin = mpViewShell->GetWindow();
540  if (pWin)
541  {
542  aVisRect.SetSize(pWin->GetOutputSizePixel());
543  aVisRect.SetPos(Point(0, 0));
544 
545  aVisRect = pWin->PixelToLogic(aVisRect, maMapMode);
546  }
547 
548  return aVisRect;
549 }
550 
551 Point ScIAccessibleViewForwarder::LogicToPixel (const Point& rPoint) const
552 {
553  SolarMutexGuard aGuard;
554  Point aPoint;
555  vcl::Window* pWin = mpViewShell->GetWindow();
556  if (pWin && mpAccDoc)
557  {
558  tools::Rectangle aRect(mpAccDoc->GetBoundingBoxOnScreen());
559  aPoint = pWin->LogicToPixel(rPoint, maMapMode) + aRect.TopLeft();
560  }
561 
562  return aPoint;
563 }
564 
565 Size ScIAccessibleViewForwarder::LogicToPixel (const Size& rSize) const
566 {
567  SolarMutexGuard aGuard;
568  Size aSize;
569  vcl::Window* pWin = mpViewShell->GetWindow();
570  if (pWin)
571  aSize = pWin->LogicToPixel(rSize, maMapMode);
572  return aSize;
573 }
574 
575 namespace {
576 
577 struct ScShapeChild
578 {
579  ScShapeChild()
580  : mnRangeId(0)
581  {
582  }
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;
592  }
593 
595  css::uno::Reference< css::drawing::XShape > mxShape;
596  sal_Int32 mnRangeId;
597 };
598 
599 }
600 
601 ScShapeChild::~ScShapeChild()
602 {
603  if (mpAccShape.is())
604  {
605  mpAccShape->dispose();
606  }
607 }
608 
609 namespace {
610 
611 struct ScShapeChildLess
612 {
613  bool operator()(const ScShapeChild& rChild1, const ScShapeChild& rChild2) const
614  {
615  bool bResult(false);
616  if (rChild1.mxShape.is() && rChild2.mxShape.is())
617  bResult = (rChild1.mxShape.get() < rChild2.mxShape.get());
618  return bResult;
619  }
620 };
621 
622 }
623 
624 typedef std::vector<ScShapeChild> ScShapeChildVec;
625 
626 namespace {
627 
628 struct ScShapeRange
629 {
630  ScShapeRange() = default;
631  ScShapeRange(ScShapeRange const &) = delete;
632  ScShapeRange(ScShapeRange &&) = default;
633  ScShapeRange & operator =(ScShapeRange const &) = delete;
634  ScShapeRange & operator =(ScShapeRange &&) = default;
635 
636  ScShapeChildVec maBackShapes;
637  ScShapeChildVec maForeShapes; // inclusive internal shapes
638  ScShapeChildVec maControls;
639  ScIAccessibleViewForwarder maViewForwarder;
640 };
641 
642 }
643 
644 typedef std::vector<ScShapeRange> ScShapeRangeVec;
645 
647 {
648 public:
650 
652 
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;
659 
661 
662  void Init();
663 
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;
672 
673  void DataChanged();
674  void VisAreaChanged() const;
675 
676 private:
679  ScShapeRangeVec maShapeRanges;
680 
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);
686 
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;
690 };
691 
693  :
694  mpAccDoc(pAccDoc),
695  mpViewShell(pViewShell),
696  maShapeRanges(SC_PREVIEW_MAXRANGES)
697 {
698 }
699 
700 void ScShapeChildren::FindChanged(ScShapeChildVec& rOld, ScShapeChildVec& rNew) const
701 {
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))
708  {
709  if (aNewItr->mxShape.get() == aOldItr->mxShape.get())
710  {
711  ++aOldItr;
712  ++aNewItr;
713  }
714  else if (aNewItr->mxShape.get() < aOldItr->mxShape.get())
715  {
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;
723  }
724  else
725  {
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;
733  }
734  }
735  while (aOldItr != aOldEnd)
736  {
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;
744  }
745  while (aNewItr != aNewEnd)
746  {
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;
754  }
755 }
756 
757 void ScShapeChildren::FindChanged(ScShapeRange& rOld, ScShapeRange& rNew) const
758 {
759  FindChanged(rOld.maBackShapes, rNew.maBackShapes);
760  FindChanged(rOld.maForeShapes, rNew.maForeShapes);
761  FindChanged(rOld.maControls, rNew.maControls);
762 }
763 
765 {
766  ScShapeRangeVec aOldShapeRanges(std::move(maShapeRanges));
767  maShapeRanges.clear();
769  Init();
770  for (sal_Int32 i = 0; i < SC_PREVIEW_MAXRANGES; ++i)
771  {
772  FindChanged(aOldShapeRanges[i], maShapeRanges[i]);
773  }
774 }
775 
776 namespace
777 {
778  struct ScVisAreaChanged
779  {
780  void operator() (const ScShapeChild& rAccShapeData) const
781  {
782  if (rAccShapeData.mpAccShape.is())
783  {
784  rAccShapeData.mpAccShape->ViewForwarderChanged();
785  }
786  }
787  };
788 }
789 
791 {
792  for (auto const& shape : maShapeRanges)
793  {
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);
798  }
799 }
800 
802 
804  const css::uno::Reference< css::drawing::XShape >& /* _rxShape */,
805  const tools::Long /* _nIndex */, const ::accessibility::AccessibleShapeTreeInfo& /* _rShapeTreeInfo */)
806 {
807  OSL_FAIL("should not be called in the page preview");
808  return false;
809 }
810 
812 
814 {
815  if(!mpViewShell)
816  return;
817 
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)
824  {
825  rData.GetDrawRange(i, aPixelPaintRect, aMapMode, nRangeId);
826  FillShapes(aPixelPaintRect, aMapMode, nRangeId);
827  }
828 }
829 
831 {
832  sal_Int32 nCount(0);
833  for (auto const& shape : maShapeRanges)
834  nCount += shape.maBackShapes.size();
835  return nCount;
836 }
837 
838 uno::Reference<XAccessible> ScShapeChildren::GetBackShape(sal_Int32 nIndex) const
839 {
840  uno::Reference<XAccessible> xAccessible;
841  for (const auto& rShapeRange : maShapeRanges)
842  {
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;
849  }
850 
851  if (nIndex >= 0)
852  throw lang::IndexOutOfBoundsException();
853 
854  return xAccessible;
855 }
856 
858 {
859  sal_Int32 nCount(0);
860  for (auto const& shape : maShapeRanges)
861  nCount += shape.maForeShapes.size();
862  return nCount;
863 }
864 
865 uno::Reference<XAccessible> ScShapeChildren::GetForeShape(sal_Int32 nIndex) const
866 {
867  uno::Reference<XAccessible> xAccessible;
868  for (const auto& rShapeRange : maShapeRanges)
869  {
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;
876  }
877 
878  if (nIndex >= 0)
879  throw lang::IndexOutOfBoundsException();
880 
881  return xAccessible;
882 }
883 
885 {
886  sal_Int32 nCount(0);
887  for (auto const& shape : maShapeRanges)
888  nCount += shape.maControls.size();
889  return nCount;
890 }
891 
892 uno::Reference<XAccessible> ScShapeChildren::GetControl(sal_Int32 nIndex) const
893 {
894  uno::Reference<XAccessible> xAccessible;
895  for (const auto& rShapeRange : maShapeRanges)
896  {
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;
903  }
904 
905  if (nIndex >= 0)
906  throw lang::IndexOutOfBoundsException();
907 
908  return xAccessible;
909 }
910 
911 namespace {
912 
913 struct ScShapePointFound
914 {
915  Point maPoint;
916  explicit ScShapePointFound(const awt::Point& rPoint) : maPoint(VCLPoint(rPoint)) {}
917  bool operator() (const ScShapeChild& rShape)
918  {
919  bool bResult(false);
920  if (VCLRectangle(rShape.mpAccShape->getBounds()).IsInside(maPoint))
921  bResult = true;
922  return bResult;
923  }
924 };
925 
926 }
927 
928 uno::Reference<XAccessible> ScShapeChildren::GetForegroundShapeAt(const awt::Point& rPoint) const //inclusive Controls
929 {
930  uno::Reference<XAccessible> xAcc;
931 
932  for(const auto& rShapeRange : maShapeRanges)
933  {
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
938  {
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);
942  }
943 
944  if (xAcc.is())
945  break;
946  }
947 
948  return xAcc;
949 }
950 
951 uno::Reference<XAccessible> ScShapeChildren::GetBackgroundShapeAt(const awt::Point& rPoint) const
952 {
953  uno::Reference<XAccessible> xAcc;
954 
955  for(const auto& rShapeRange : maShapeRanges)
956  {
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;
962  }
963 
964  return xAcc;
965 }
966 
968 {
969  if (!rShape.mpAccShape.is())
970  {
972  ::accessibility::AccessibleShapeInfo aShapeInfo(rShape.mxShape, mpAccDoc);
973 
974  if (mpViewShell)
975  {
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())
983  {
984  rShape.mpAccShape->Init();
985  }
986  }
987  }
988  return rShape.mpAccShape.get();
989 }
990 
991 ::accessibility::AccessibleShape* ScShapeChildren::GetAccShape(const ScShapeChildVec& rShapes, sal_Int32 nIndex) const
992 {
993  return GetAccShape(rShapes[nIndex]);
994 }
995 
996 void ScShapeChildren::FillShapes(const tools::Rectangle& aPixelPaintRect, const MapMode& aMapMode, sal_uInt8 nRangeId)
997 {
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;
1003 
1004  bool bForeAdded(false);
1005  bool bBackAdded(false);
1006  bool bControlAdded(false);
1007  tools::Rectangle aClippedPixelPaintRect(aPixelPaintRect);
1008  if (mpAccDoc)
1009  {
1010  tools::Rectangle aRect2(Point(0,0), mpAccDoc->GetBoundingBoxOnScreen().GetSize());
1011  aClippedPixelPaintRect = aPixelPaintRect.GetIntersection(aRect2);
1012  }
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)
1017  {
1018  SdrObject* pObj = pPage->GetObj(i);
1019  if (pObj)
1020  {
1021  uno::Reference< drawing::XShape > xShape(pObj->getUnoShape(), uno::UNO_QUERY);
1022  if (xShape.is())
1023  {
1024  tools::Rectangle aRect(pWin->LogicToPixel(VCLPoint(xShape->getPosition()), aMapMode), pWin->LogicToPixel(VCLSize(xShape->getSize()), aMapMode));
1025  if(!aClippedPixelPaintRect.GetIntersection(aRect).IsEmpty())
1026  {
1027  ScShapeChild aShape;
1028  aShape.mxShape = xShape;
1029  aShape.mnRangeId = nRangeId;
1031  {
1032  maShapeRanges[nRangeId].maForeShapes.push_back(std::move(aShape));
1033  bForeAdded = true;
1034  }
1035  else if (pObj->GetLayer() == SC_LAYER_BACK)
1036  {
1037  maShapeRanges[nRangeId].maBackShapes.push_back(std::move(aShape));
1038  bBackAdded = true;
1039  }
1040  else if (pObj->GetLayer() == SC_LAYER_CONTROLS)
1041  {
1042  maShapeRanges[nRangeId].maControls.push_back(std::move(aShape));
1043  bControlAdded = true;
1044  }
1045  else
1046  {
1047  OSL_FAIL("I don't know this layer.");
1048  }
1049  }
1050  }
1051  }
1052  }
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());
1059 }
1060 
1062 {
1064  SdrPage* pDrawPage = nullptr;
1065  ScDocument& rDoc = mpViewShell->GetDocument();
1066  if (rDoc.GetDrawLayer())
1067  {
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)));
1071  }
1072  return pDrawPage;
1073 }
1074 
1075 namespace {
1076 
1077 struct ScPagePreviewCountData
1078 {
1079  // order is background shapes, header, table or notes, footer, foreground shapes, controls
1080 
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;
1089 
1090  ScPagePreviewCountData( const ScPreviewLocationData& rData, const vcl::Window* pSizeWindow,
1091  const ScNotesChildren* pNotesChildren, const ScShapeChildren* pShapeChildren );
1092 
1093  tools::Long GetTotal() const
1094  {
1095  return nBackShapes + nHeaders + nTables + nNoteParagraphs + nFooters + nForeShapes + nControls;
1096  }
1097 };
1098 
1099 }
1100 
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 )
1111 {
1112  Size aOutputSize;
1113  if ( pSizeWindow )
1114  aOutputSize = pSizeWindow->GetOutputSizePixel();
1115  aVisRect = tools::Rectangle( Point(), aOutputSize );
1116 
1117  tools::Rectangle aObjRect;
1118 
1119  if ( rData.GetHeaderPosition( aObjRect ) && aObjRect.IsOver( aVisRect ) )
1120  nHeaders = 1;
1121 
1122  if ( rData.GetFooterPosition( aObjRect ) && aObjRect.IsOver( aVisRect ) )
1123  nFooters = 1;
1124 
1125  if ( rData.HasCellsInRange( aVisRect ) )
1126  nTables = 1;
1127 
1129  nBackShapes = pShapeChildren->GetBackShapeCount();
1130  nForeShapes = pShapeChildren->GetForeShapeCount();
1131  nControls = pShapeChildren->GetControlCount();
1132 
1133  // there are only notes if there is no table
1134  if (nTables == 0)
1135  nNoteParagraphs = pNotesChildren->GetChildrenCount();
1136 }
1137 
1138 //===== internal ========================================================
1139 
1141  const uno::Reference<XAccessible>& rxParent, ScPreviewShell* pViewShell ) :
1142  ScAccessibleDocumentBase(rxParent),
1143  mpViewShell(pViewShell)
1144 {
1145  if (pViewShell)
1146  pViewShell->AddAccessibilityObject(*this);
1147 
1148 }
1149 
1151 {
1152  if (!ScAccessibleDocumentBase::IsDefunc() && !rBHelper.bInDispose)
1153  {
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();
1158  }
1159 }
1160 
1162 {
1163  SolarMutexGuard aGuard;
1164  mpTable.clear();
1165  mpHeader.clear();
1166  mpFooter.clear();
1167 
1168  if (mpViewShell)
1169  {
1171  mpViewShell = nullptr;
1172  }
1173 
1174  // no need to Dispose the AccessibleTextHelper,
1175  // as long as mpNotesChildren are destructed here
1176  mpNotesChildren.reset();
1177 
1178  mpShapeChildren.reset();
1179 
1181 }
1182 
1183 //===== SfxListener =====================================================
1184 
1186 {
1187  if ( dynamic_cast<const ScAccWinFocusLostHint*>(&rHint) )
1188  {
1189  CommitFocusLost();
1190  }
1191  else if ( dynamic_cast<const ScAccWinFocusGotHint*>(&rHint) )
1192  {
1194  }
1195  else
1196  {
1197  // only notify if child exist, otherwise it is not necessary
1198  if (rHint.GetId() == SfxHintId::ScDataChanged)
1199  {
1200  if (mpTable.is()) // if there is no table there is nothing to notify, because no one recognizes the change
1201  {
1202  {
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);
1209  }
1210 
1211  mpTable->dispose();
1212  mpTable.clear();
1213  }
1214 
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);
1221 
1223 
1225  ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1226 
1227  if (aCount.nTables > 0)
1228  {
1230  sal_Int32 nIndex (aCount.nBackShapes + aCount.nHeaders);
1231 
1232  mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex );
1233  mpTable->Init();
1234 
1235  {
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);
1242  }
1243  }
1244  }
1245  else if (rHint.GetId() == SfxHintId::ScAccVisAreaChanged)
1246  {
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);
1253 
1255 
1256  AccessibleEventObject aEvent;
1257  aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
1258  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1259  CommitChange(aEvent);
1260  }
1261  }
1263 }
1264 
1265 //===== XAccessibleComponent ============================================
1266 
1267 uno::Reference< XAccessible > SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleAtPoint( const awt::Point& rPoint )
1268 {
1269  uno::Reference<XAccessible> xAccessible;
1270  if (containsPoint(rPoint))
1271  {
1272  SolarMutexGuard aGuard;
1273  IsObjectValid();
1274 
1275  if ( mpViewShell )
1276  {
1277  xAccessible = GetShapeChildren()->GetForegroundShapeAt(rPoint);
1278  if (!xAccessible.is())
1279  {
1281  ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1282 
1283  if ( !mpTable.is() && (aCount.nTables > 0) )
1284  {
1286  sal_Int32 nIndex (aCount.nBackShapes + aCount.nHeaders);
1287 
1288  mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex );
1289  mpTable->Init();
1290  }
1291  if (mpTable.is() && VCLRectangle(mpTable->getBounds()).IsInside(VCLPoint(rPoint)))
1292  xAccessible = mpTable.get();
1293  }
1294  if (!xAccessible.is())
1295  xAccessible = GetNotesChildren()->GetAt(rPoint);
1296  if (!xAccessible.is())
1297  {
1298  if (!mpHeader.is() || !mpFooter.is())
1299  {
1301  ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1302 
1303  if (!mpHeader.is())
1304  {
1305  mpHeader = new ScAccessiblePageHeader( this, mpViewShell, true, aCount.nBackShapes + aCount.nHeaders - 1);
1306  }
1307  if (!mpFooter.is())
1308  {
1309  mpFooter = new ScAccessiblePageHeader( this, mpViewShell, false, aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters - 1 );
1310  }
1311  }
1312 
1313  Point aPoint(VCLPoint(rPoint));
1314 
1315  if (VCLRectangle(mpHeader->getBounds()).IsInside(aPoint))
1316  xAccessible = mpHeader.get();
1317  else if (VCLRectangle(mpFooter->getBounds()).IsInside(aPoint))
1318  xAccessible = mpFooter.get();
1319  }
1320  if (!xAccessible.is())
1321  xAccessible = GetShapeChildren()->GetBackgroundShapeAt(rPoint);
1322  }
1323  }
1324 
1325  return xAccessible;
1326 }
1327 
1329 {
1330  SolarMutexGuard aGuard;
1331  IsObjectValid();
1332  if (getAccessibleParent().is())
1333  {
1334  uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1335  if (xAccessibleComponent.is())
1336  {
1337  // just grab the focus for the window
1338  xAccessibleComponent->grabFocus();
1339  }
1340  }
1341 }
1342 
1343 //===== XAccessibleContext ==============================================
1344 
1346 {
1347  SolarMutexGuard aGuard;
1348  IsObjectValid();
1349 
1350  tools::Long nRet = 0;
1351  if ( mpViewShell )
1352  {
1353  ScPagePreviewCountData aCount( mpViewShell->GetLocationData(), mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1354  nRet = aCount.GetTotal();
1355  }
1356 
1357  return nRet;
1358 }
1359 
1360 uno::Reference<XAccessible> SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleChild(sal_Int32 nIndex)
1361 {
1362  SolarMutexGuard aGuard;
1363  IsObjectValid();
1364  uno::Reference<XAccessible> xAccessible;
1365 
1366  if ( mpViewShell )
1367  {
1369  ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1370 
1371  if ( nIndex < aCount.nBackShapes )
1372  {
1373  xAccessible = GetShapeChildren()->GetBackShape(nIndex);
1374  }
1375  else if ( nIndex < aCount.nBackShapes + aCount.nHeaders )
1376  {
1377  if ( !mpHeader.is() )
1378  {
1379  mpHeader = new ScAccessiblePageHeader( this, mpViewShell, true, nIndex );
1380  }
1381 
1382  xAccessible = mpHeader.get();
1383  }
1384  else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nTables )
1385  {
1386  if ( !mpTable.is() )
1387  {
1388  mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex );
1389  mpTable->Init();
1390  }
1391  xAccessible = mpTable.get();
1392  }
1393  else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nNoteParagraphs )
1394  {
1395  xAccessible = GetNotesChildren()->GetChild(nIndex - aCount.nBackShapes - aCount.nHeaders);
1396  }
1397  else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters )
1398  {
1399  if ( !mpFooter.is() )
1400  {
1401  mpFooter = new ScAccessiblePageHeader( this, mpViewShell, false, nIndex );
1402  }
1403  xAccessible = mpFooter.get();
1404  }
1405  else
1406  {
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);
1412  }
1413  }
1414 
1415  if ( !xAccessible.is() )
1416  throw lang::IndexOutOfBoundsException();
1417 
1418  return xAccessible;
1419 }
1420 
1422 uno::Reference<XAccessibleStateSet> SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleStateSet()
1423 {
1424  SolarMutexGuard aGuard;
1425  uno::Reference<XAccessibleStateSet> xParentStates;
1426  if (getAccessibleParent().is())
1427  {
1428  uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1429  xParentStates = xParentContext->getAccessibleStateSet();
1430  }
1432  if (IsDefunc(xParentStates))
1433  pStateSet->AddState(AccessibleStateType::DEFUNC);
1434  else
1435  {
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);
1443  }
1444  return pStateSet;
1445 }
1446 
1447  //===== XServiceInfo ====================================================
1448 
1450 {
1451  return "ScAccessibleDocumentPagePreview";
1452 }
1453 
1455 {
1456  uno::Sequence< OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
1457  sal_Int32 nOldSize(aSequence.getLength());
1458  aSequence.realloc(nOldSize + 1);
1459 
1460  aSequence[nOldSize] = "com.sun.star.AccessibleSpreadsheetPageView";
1461 
1462  return aSequence;
1463 }
1464 
1465 //===== XTypeProvider =======================================================
1466 
1467 uno::Sequence<sal_Int8> SAL_CALL
1469 {
1470  return css::uno::Sequence<sal_Int8>();
1471 }
1472 
1473 //===== internal ========================================================
1474 
1476 {
1477  return STR_ACC_PREVIEWDOC_DESCR;
1478 }
1479 
1481 {
1482  OUString sName = ScResId(STR_ACC_PREVIEWDOC_NAME);
1483  return sName;
1484 }
1485 
1487 {
1488  tools::Rectangle aRect;
1489  if (mpViewShell)
1490  {
1491  vcl::Window* pWindow = mpViewShell->GetWindow();
1492  if (pWindow)
1493  aRect = pWindow->GetWindowExtentsRelative(nullptr);
1494  }
1495  return aRect;
1496 }
1497 
1499 {
1500  tools::Rectangle aRect;
1501  if (mpViewShell)
1502  {
1503  vcl::Window* pWindow = mpViewShell->GetWindow();
1504  if (pWindow)
1505  aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
1506  }
1507  return aRect;
1508 }
1509 
1511  const uno::Reference<XAccessibleStateSet>& rxParentStates)
1512 {
1514  (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
1515 }
1516 
1518 {
1519  if (!mpNotesChildren && mpViewShell)
1520  {
1521  mpNotesChildren.reset( new ScNotesChildren(mpViewShell, this) );
1522 
1524  ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1525 
1527  mpNotesChildren->Init(aCount.aVisRect, aCount.nBackShapes + aCount.nHeaders);
1528  }
1529  return mpNotesChildren.get();
1530 }
1531 
1533 {
1534  if (!mpShapeChildren && mpViewShell)
1535  {
1536  mpShapeChildren.reset( new ScShapeChildren(mpViewShell, this) );
1537  mpShapeChildren->Init();
1538  }
1539 
1540  return mpShapeChildren.get();
1541 }
1542 
1544 {
1545  SolarMutexGuard g;
1546 
1547  OUString aName = ScResId(STR_ACC_DOC_SPREADSHEET);
1548  ScDocument& rScDoc = mpViewShell->GetDocument();
1549 
1550  SfxObjectShell* pObjSh = rScDoc.GetDocumentShell();
1551  if (!pObjSh)
1552  return aName;
1553 
1554  OUString aFileName;
1555  SfxMedium* pMed = pObjSh->GetMedium();
1556  if (pMed)
1557  aFileName = pMed->GetName();
1558 
1559  if (aFileName.isEmpty())
1560  aFileName = pObjSh->GetTitle(SFX_TITLE_APINAME);
1561 
1562  if (!aFileName.isEmpty())
1563  {
1564  aName = aFileName + " - " + aName + ScResId(STR_ACC_DOC_PREVIEW_SUFFIX);
1565 
1566  }
1567 
1568  return aName;
1569 }
1570 
1571 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Point TopLeft() const
void SetPos(const Point &rPoint)
const ScPreviewLocationData & GetLocationData()
Definition: prevwsh.cxx:1177
void AddAccessibilityObject(SfxListener &rObject)
Definition: prevwsh.cxx:1148
sal_Int32 nIndex
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:262
OUString GetTitle(sal_uInt16 nMaxLen=0) const
signed char sal_Int8
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)
bool IsOver(const tools::Rectangle &rRect) const
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:34
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 ========================================================
bool IsEmpty() const
void SetOffset(const Point &rPoint)
uno::Reference< drawing::XShape > const mxShape
SC_DLLPUBLIC ScPostIt * GetNote(const ScAddress &rPos)
Notes.
Definition: document.cxx:6508
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:403
virtual tools::Rectangle GetVisibleArea() const =0
virtual css::uno::Reference< css::uno::XInterface > getUnoShape()
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:160
int nCount
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:118
SCTAB Tab() const
Definition: address.hxx:271
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:365
const char * sName
ScPreview * GetPreview()
Definition: prevwsh.hxx:117
::accessibility::AccessibleShape * GetAccShape(const ScShapeChild &rShape) 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:1059
bool GetFooterPosition(tools::Rectangle &rFooterRect) const
Definition: prevloc.cxx:347
#define SFX_TITLE_APINAME
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:321
inline::tools::Rectangle VCLRectangle(const css::awt::Rectangle &rAWTRect)
void SetEventSource(const css::uno::Reference< css::accessibility::XAccessible > &rInterface)
void SetSize(const Size &rSize)
const SdrPage * GetPage(sal_uInt16 nPgNum) const
void CommitFocusGained() const
Calls all FocusListener to tell they that the focus is gained.
static ShapeTypeHandler & Instance()
OUString ScResId(const char *pId)
Definition: scdll.cxx:95
ScAccessibleDocumentPagePreview * mpAccDoc
ScShapeChildren(ScPreviewShell *pViewShell, ScAccessibleDocumentPagePreview *pAccDoc)
static void CollectChildren(const ScAccNote &rNote, ScXAccVector &rVector)
bool IsInside(const Point &rPOINT) const
ScAccessibleDocumentPagePreview(const css::uno::Reference< css::accessibility::XAccessible > &rxParent, ScPreviewShell *pViewShell)
inline::Point VCLPoint(const css::awt::Point &rAWTPoint)
rtl::Reference< ScAccessiblePreviewTable > mpTable
Size GetOutputSizePixel() const
sal_uInt16 GetDrawRanges() const
Definition: prevloc.hxx:123
uno::Reference< XAccessible > GetBackgroundShapeAt(const awt::Point &rPoint) const
virtual Point LogicToPixel(const Point &rPoint) const =0
Size GetSize() const
SCCOL Col() const
Definition: address.hxx:267
std::vector< ScAccNote > ScAccNotes
virtual SdrLayerID GetLayer() const
vcl::Window * GetWindow(GetWindowType nType) const
void SetViewForwarder(const IAccessibleViewForwarder *pViewForwarder)
Point PixelToLogic(const Point &rDevicePt) const
Point LogicToPixel(const Point &rLogicPt) const
::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
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:1156
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:389
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:255
void CommitFocusLost() const
Calls all FocusListener to tell they that the focus is lost.
ScDocument & GetDocument()
Definition: prevwsh.cxx:1182
vcl::Window * GetWindow() const
FmFormView * GetDrawView()
Definition: preview.hxx:158
sal_Int32 GetForeShapeCount() const
void DataChanged(const tools::Rectangle &rVisRect)
void CommitChange(const css::accessibility::AccessibleEventObject &rEvent) const
Calls all Listener to tell they the change.
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1058
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()
void SetDevice(OutputDevice *pWindow)
int mnIndex
void SetStartIndex(sal_Int32 nOffset)
void AddState(sal_Int16 aState)
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:23
bool anyOf(strong_int v) const
bool GetHeaderPosition(tools::Rectangle &rHeaderRect) const
Definition: prevloc.cxx:333
virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext() override
===== XAccessible =====================================================
SfxMedium * GetMedium() const