LibreOffice Module sc (master)  1
AccessibleDocument.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 
20 #include <AccessibleDocument.hxx>
22 #include <tabvwsh.hxx>
23 #include <AccessibilityHints.hxx>
24 #include <document.hxx>
25 #include <drwlayer.hxx>
26 #include <DrawModelBroadcaster.hxx>
27 #include <drawview.hxx>
28 #include <gridwin.hxx>
29 #include <AccessibleEditObject.hxx>
30 #include <userdat.hxx>
31 #include <scresid.hxx>
32 #include <strings.hrc>
33 #include <strings.hxx>
34 #include <markdata.hxx>
35 
36 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
37 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
38 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
39 #include <com/sun/star/accessibility/AccessibleRole.hpp>
40 #include <com/sun/star/view/XSelectionSupplier.hpp>
41 #include <com/sun/star/drawing/ShapeCollection.hpp>
42 #include <com/sun/star/drawing/XShape.hpp>
43 #include <com/sun/star/drawing/XShapes.hpp>
44 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
45 #include <o3tl/safeint.hxx>
47 #include <tools/gen.hxx>
48 #include <svx/svdpage.hxx>
49 #include <svx/svdobj.hxx>
50 #include <svx/ShapeTypeHandler.hxx>
51 #include <svx/AccessibleShape.hxx>
55 #include <comphelper/sequence.hxx>
56 #include <sfx2/viewfrm.hxx>
57 #include <sfx2/docfile.hxx>
58 #include <svx/unoshape.hxx>
61 #include <vcl/svapp.hxx>
62 
64 #include <svx/SvxShapeTypes.hxx>
65 #include <sfx2/objsh.hxx>
66 #include <editeng/editview.hxx>
67 #include <editeng/editeng.hxx>
69 
70 #include <algorithm>
71 
72 #include <svx/unoapi.hxx>
73 #include <scmod.hxx>
74 
75 #ifdef indices
76 #undef indices
77 #endif
78 
79 #ifdef extents
80 #undef extents
81 #endif
82 
83 using namespace ::com::sun::star;
84 using namespace ::com::sun::star::accessibility;
85 
86  //===== internal ========================================================
87 
88 namespace {
89 
90 struct ScAccessibleShapeData
91 {
92  ScAccessibleShapeData(css::uno::Reference< css::drawing::XShape > xShape_);
93  ~ScAccessibleShapeData();
95  mutable std::optional<ScAddress> xRelationCell; // if it is NULL this shape is anchored on the table
96  css::uno::Reference< css::drawing::XShape > xShape;
97  mutable bool bSelected;
98  bool bSelectable;
99  // cache these to make the sorting cheaper
100  std::optional<sal_Int16> mxLayerID;
101  std::optional<sal_Int32> mxZOrder;
102 };
103 
104 }
105 
106 ScAccessibleShapeData::ScAccessibleShapeData(css::uno::Reference< css::drawing::XShape > xShape_)
107  : xShape(xShape_),
108  bSelected(false), bSelectable(true)
109 {
110  static constexpr OUStringLiteral gsLayerId = u"LayerID";
111  static constexpr OUStringLiteral gsZOrder = u"ZOrder";
112  uno::Reference< beans::XPropertySet> xProps(xShape, uno::UNO_QUERY);
113  if (xProps.is())
114  {
115  uno::Any aAny = xProps->getPropertyValue(gsLayerId);
116  sal_Int16 nLayerID;
117  if (aAny >>= nLayerID)
118  mxLayerID = nLayerID;
119  sal_Int32 nZOrder;
120  aAny = xProps->getPropertyValue(gsZOrder);
121  if (aAny >>= nZOrder)
122  mxZOrder = nZOrder;
123  }
124 }
125 
126 ScAccessibleShapeData::~ScAccessibleShapeData()
127 {
128  if (pAccShape.is())
129  {
130  pAccShape->dispose();
131  }
132 }
133 
134 namespace {
135 
136 struct ScShapeDataLess
137 {
138  static void ConvertLayerId(sal_Int16& rLayerID) // changes the number of the LayerId so it the accessibility order
139  {
140  // note: MSVC 2017 ICE's if this is written as "switch" so use "if"
141  if (sal_uInt8(SC_LAYER_FRONT) == rLayerID)
142  {
143  rLayerID = 1;
144  }
145  else if (sal_uInt8(SC_LAYER_BACK) == rLayerID)
146  {
147  rLayerID = 0;
148  }
149  else if (sal_uInt8(SC_LAYER_INTERN) == rLayerID)
150  {
151  rLayerID = 2;
152  }
153  else if (sal_uInt8(SC_LAYER_CONTROLS) == rLayerID)
154  {
155  rLayerID = 3;
156  }
157  }
158  static bool LessThanSheet(const ScAccessibleShapeData* pData)
159  {
160  bool bResult(false);
161  if (pData->mxLayerID)
162  {
163  if (SdrLayerID(*pData->mxLayerID) == SC_LAYER_BACK)
164  bResult = true;
165  }
166  return bResult;
167  }
168  bool operator()(const ScAccessibleShapeData* pData1, const ScAccessibleShapeData* pData2) const
169  {
170  bool bResult(false);
171  if (pData1 && pData2)
172  {
173  if( pData1->mxLayerID && pData2->mxLayerID )
174  {
175  sal_Int16 nLayerID1 = *pData1->mxLayerID;
176  sal_Int16 nLayerID2 = *pData2->mxLayerID;
177  if (nLayerID1 == nLayerID2)
178  {
179  if ( pData1->mxZOrder && pData2->mxZOrder )
180  bResult = (*pData1->mxZOrder < *pData2->mxZOrder);
181  }
182  else
183  {
184  ConvertLayerId(nLayerID1);
185  ConvertLayerId(nLayerID2);
186  bResult = (nLayerID1 < nLayerID2);
187  }
188  }
189  }
190  else if (pData1 && !pData2)
191  bResult = LessThanSheet(pData1);
192  else if (!pData1 && pData2)
193  bResult = !LessThanSheet(pData2);
194  else
195  bResult = false;
196  return bResult;
197  }
198 };
199 
200 }
201 
204 {
205 public:
206  ScChildrenShapes(ScAccessibleDocument* pAccessibleDocument, ScTabViewShell* pViewShell, ScSplitPos eSplitPos);
207  virtual ~ScChildrenShapes() override;
208 
210 
211  virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
212 
214 
215  virtual bool ReplaceChild (
216  ::accessibility::AccessibleShape* pCurrentChild,
217  const css::uno::Reference< css::drawing::XShape >& _rxShape,
218  const tools::Long _nIndex,
219  const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo
220  ) override;
221 
222  virtual ::accessibility::AccessibleControlShape* GetAccControlShapeFromModel
223  (css::beans::XPropertySet* pSet) override;
224  virtual css::uno::Reference< css::accessibility::XAccessible>
225  GetAccessibleCaption (const css::uno::Reference<css::drawing::XShape>& xShape) override;
227  void SetDrawBroadcaster();
228 
229  sal_Int32 GetCount() const;
230  uno::Reference< XAccessible > Get(const ScAccessibleShapeData* pData) const;
231  uno::Reference< XAccessible > Get(sal_Int32 nIndex) const;
232  uno::Reference< XAccessible > GetAt(const awt::Point& rPoint) const;
233 
234  // gets the index of the shape starting on 0 (without the index of the table)
235  // returns the selected shape
236  bool IsSelected(sal_Int32 nIndex,
237  css::uno::Reference<css::drawing::XShape>& rShape) const;
238 
239  bool SelectionChanged();
240 
241  void Select(sal_Int32 nIndex);
242  void DeselectAll(); // deselect also the table
243  void SelectAll();
244  sal_Int32 GetSelectedCount() const;
245  uno::Reference< XAccessible > GetSelected(sal_Int32 nSelectedChildIndex, bool bTabSelected) const;
246  void Deselect(sal_Int32 nChildIndex);
247 
248  SdrPage* GetDrawPage() const;
249 
251 
252  void VisAreaChanged() const;
253 private:
254  typedef std::vector<ScAccessibleShapeData*> SortedShapes;
255  typedef std::unordered_map<css::uno::Reference< css::drawing::XShape >, ScAccessibleShapeData*> ShapesMap;
256 
257  mutable SortedShapes maZOrderedShapes; // a null pointer represents the sheet in the correct order
258  mutable ShapesMap maShapesMap;
259  mutable bool mbShapesNeedSorting; // set if maZOrderedShapes needs sorting
260 
261  mutable ::accessibility::AccessibleShapeTreeInfo maShapeTreeInfo;
262  mutable css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier;
263  mutable size_t mnSdrObjCount;
264  mutable sal_uInt32 mnShapesSelected;
268 
269  void FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const;
270  bool FindSelectedShapesChanges(const css::uno::Reference<css::drawing::XShapes>& xShapes) const;
271 
272  std::optional<ScAddress> GetAnchor(const uno::Reference<drawing::XShape>& xShape) const;
273  uno::Reference<XAccessibleRelationSet> GetRelationSet(const ScAccessibleShapeData* pData) const;
274  void SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const;
275  void AddShape(const uno::Reference<drawing::XShape>& xShape, bool bCommitChange) const;
276  void RemoveShape(const uno::Reference<drawing::XShape>& xShape) const;
277 
278  bool FindShape(const uno::Reference<drawing::XShape>& xShape, SortedShapes::iterator& rItr) const;
279 
280  static sal_Int8 Compare(const ScAccessibleShapeData* pData1,
281  const ScAccessibleShapeData* pData2);
282 };
283 
285  :
286  mbShapesNeedSorting(false),
287  mnShapesSelected(0),
288  mpViewShell(pViewShell),
289  mpAccessibleDocument(pAccessibleDocument),
290  meSplitPos(eSplitPos)
291 {
292  if (mpViewShell)
293  {
294  SfxViewFrame* pViewFrame = mpViewShell->GetViewFrame();
295  if (pViewFrame)
296  {
297  xSelectionSupplier = uno::Reference<view::XSelectionSupplier>(pViewFrame->GetFrame().GetController(), uno::UNO_QUERY);
298  if (xSelectionSupplier.is())
299  {
300  xSelectionSupplier->addSelectionChangeListener(mpAccessibleDocument);
301  uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
302  if (xShapes.is())
303  mnShapesSelected = xShapes->getCount();
304  }
305  }
306  }
307 
308  maZOrderedShapes.push_back(nullptr); // add an element which represents the table
309 
310  GetCount(); // fill list with filtered shapes (no internal shapes)
311 
312  if (mnShapesSelected)
313  {
314  //set flag on every selected shape
315  if (!xSelectionSupplier.is())
316  throw uno::RuntimeException();
317 
318  uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
319  if (xShapes.is())
320  FindSelectedShapesChanges(xShapes);
321  }
322  if (!pViewShell)
323  return;
324 
325  ScViewData& rViewData = pViewShell->GetViewData();
326  SfxBroadcaster* pDrawBC = rViewData.GetDocument().GetDrawBroadcaster();
327  if (pDrawBC)
328  {
329  StartListening(*pDrawBC);
330 
331  maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(rViewData.GetDocument().GetDrawLayer()) );
332  maShapeTreeInfo.SetSdrView(rViewData.GetScDrawView());
333  maShapeTreeInfo.SetController(nullptr);
334  maShapeTreeInfo.SetDevice(pViewShell->GetWindowByPos(meSplitPos));
335  maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
336  }
337 }
338 
340 {
341  for (ScAccessibleShapeData* pShapeData : maZOrderedShapes)
342  delete pShapeData;
343  if (mpViewShell)
344  {
346  if (pDrawBC)
347  EndListening(*pDrawBC);
348  }
350  xSelectionSupplier->removeSelectionChangeListener(mpAccessibleDocument);
351 }
352 
354 {
355  if (!mpViewShell)
356  return;
357 
358  ScViewData& rViewData = mpViewShell->GetViewData();
359  SfxBroadcaster* pDrawBC = rViewData.GetDocument().GetDrawBroadcaster();
360  if (pDrawBC)
361  {
362  StartListening(*pDrawBC, DuplicateHandling::Prevent);
363 
364  maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(rViewData.GetDocument().GetDrawLayer()) );
365  maShapeTreeInfo.SetSdrView(rViewData.GetScDrawView());
366  maShapeTreeInfo.SetController(nullptr);
368  maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
369  }
370 }
371 
373 {
374  if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
375  return;
376  const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
377 
378  SdrObject* pObj = const_cast<SdrObject*>(pSdrHint->GetObject());
379  if (!(pObj && /*(pObj->GetLayer() != SC_LAYER_INTERN) && */(pObj->getSdrPageFromSdrObject() == GetDrawPage()) &&
380  (pObj->getSdrPageFromSdrObject() == pObj->getParentSdrObjListFromSdrObject())) ) //only do something if the object lies direct on the page
381  return;
382 
383  switch (pSdrHint->GetKind())
384  {
385  case SdrHintKind::ObjectChange : // object changed
386  {
387  uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
388  if (xShape.is())
389  {
390  mbShapesNeedSorting = true; // sort, because the z index or layer could be changed
391  auto it = maShapesMap.find(xShape);
392  if (it != maShapesMap.end())
393  SetAnchor(xShape, it->second);
394  }
395  }
396  break;
397  case SdrHintKind::ObjectInserted : // new drawing object inserted
398  {
399  uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
400  if (xShape.is())
401  AddShape(xShape, true);
402  }
403  break;
404  case SdrHintKind::ObjectRemoved : // Removed drawing object from list
405  {
406  uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
407  if (xShape.is())
408  RemoveShape(xShape);
409  }
410  break;
411  default :
412  {
413  // other events are not interesting
414  }
415  break;
416  }
417 }
418 
420  const css::uno::Reference< css::drawing::XShape >& _rxShape,
421  const tools::Long /*_nIndex*/, const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo)
422 {
423  // create the new child
425  ::accessibility::AccessibleShapeInfo ( _rxShape, pCurrentChild->getAccessibleParent(), this ),
426  _rShapeTreeInfo
427  ));
428 
429  bool bResult(false);
430  if (pReplacement.is())
431  {
432  OSL_ENSURE(pCurrentChild->GetXShape().get() == pReplacement->GetXShape().get(), "XShape changes and should be inserted sorted");
433  auto it = maShapesMap.find(pCurrentChild->GetXShape());
434  if (it != maShapesMap.end() && it->second->pAccShape.is())
435  {
436  OSL_ENSURE(it->second->pAccShape == pCurrentChild, "wrong child found");
437  AccessibleEventObject aEvent;
438  aEvent.EventId = AccessibleEventId::CHILD;
439  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
440  aEvent.OldValue <<= uno::Reference<XAccessible>(pCurrentChild);
441 
442  mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
443 
444  pCurrentChild->dispose();
445  }
446 
447  // Init after above possible pCurrentChild->dispose so we don't trigger the assert
448  // ScDrawModelBroadcaster::addShapeEventListener of duplicate listeners
449  pReplacement->Init();
450 
451  if (it != maShapesMap.end())
452  {
453  it->second->pAccShape = pReplacement;
454  AccessibleEventObject aEvent;
455  aEvent.EventId = AccessibleEventId::CHILD;
456  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
457  aEvent.NewValue <<= uno::Reference<XAccessible>(pReplacement.get());
458 
459  mpAccessibleDocument->CommitChange(aEvent); // child is new - event
460  bResult = true;
461  }
462  }
463  return bResult;
464 }
465 
467 {
468  GetCount(); // populate
469  for (ScAccessibleShapeData* pShape : maZOrderedShapes)
470  {
471  if (pShape)
472  {
473  rtl::Reference< ::accessibility::AccessibleShape > pAccShape(pShape->pAccShape);
474  if (pAccShape.is() && ::accessibility::ShapeTypeHandler::Instance().GetTypeId (pAccShape->GetXShape()) == ::accessibility::DRAWING_CONTROL)
475  {
476  ::accessibility::AccessibleControlShape *pCtlAccShape = static_cast < ::accessibility::AccessibleControlShape* >(pAccShape.get());
477  if (pCtlAccShape && pCtlAccShape->GetControlModel() == pSet)
478  return pCtlAccShape;
479  }
480  }
481  }
482  return nullptr;
483 }
484 
485 css::uno::Reference < css::accessibility::XAccessible >
486 ScChildrenShapes::GetAccessibleCaption (const css::uno::Reference < css::drawing::XShape>& xShape)
487 {
488  GetCount(); // populate
489  auto it = maShapesMap.find(xShape);
490  if (it == maShapesMap.end())
491  return nullptr;
492  ScAccessibleShapeData* pShape = it->second;
493  css::uno::Reference< css::accessibility::XAccessible > xNewChild( pShape->pAccShape.get() );
494  if(xNewChild)
495  return xNewChild;
496  return nullptr;
497 }
498 
499 sal_Int32 ScChildrenShapes::GetCount() const
500 {
501  SdrPage* pDrawPage = GetDrawPage();
502  if (pDrawPage && (maZOrderedShapes.size() == 1)) // the table is always in
503  {
504  mnSdrObjCount = pDrawPage->GetObjCount();
505  maZOrderedShapes.reserve(mnSdrObjCount + 1); // the table is always in
506  for (size_t i = 0; i < mnSdrObjCount; ++i)
507  {
508  SdrObject* pObj = pDrawPage->GetObj(i);
509  if (pObj/* && (pObj->GetLayer() != SC_LAYER_INTERN)*/)
510  {
511  uno::Reference< drawing::XShape > xShape (pObj->getUnoShape(), uno::UNO_QUERY);
512  AddShape(xShape, false); //inserts in the correct order
513  }
514  }
515  }
516  return maZOrderedShapes.size();
517 }
518 
519 uno::Reference< XAccessible > ScChildrenShapes::Get(const ScAccessibleShapeData* pData) const
520 {
521  if (!pData)
522  return nullptr;
523 
524  if (!pData->pAccShape.is())
525  {
527  ::accessibility::AccessibleShapeInfo aShapeInfo(pData->xShape, mpAccessibleDocument, const_cast<ScChildrenShapes*>(this));
528  pData->pAccShape = rShapeHandler.CreateAccessibleObject(
529  aShapeInfo, maShapeTreeInfo);
530  if (pData->pAccShape.is())
531  {
532  pData->pAccShape->Init();
533  if (pData->bSelected)
534  pData->pAccShape->SetState(AccessibleStateType::SELECTED);
535  if (!pData->bSelectable)
536  pData->pAccShape->ResetState(AccessibleStateType::SELECTABLE);
537  pData->pAccShape->SetRelationSet(GetRelationSet(pData));
538  }
539  }
540  return pData->pAccShape.get();
541  }
542 
543 uno::Reference< XAccessible > ScChildrenShapes::Get(sal_Int32 nIndex) const
544 {
545  if (maZOrderedShapes.size() <= 1)
546  GetCount(); // fill list with filtered shapes (no internal shapes)
547 
549  {
550  std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
551  mbShapesNeedSorting = false;
552  }
553 
554  if (o3tl::make_unsigned(nIndex) >= maZOrderedShapes.size())
555  return nullptr;
556 
557  return Get(maZOrderedShapes[nIndex]);
558 }
559 
560 uno::Reference< XAccessible > ScChildrenShapes::GetAt(const awt::Point& rPoint) const
561 {
562  uno::Reference<XAccessible> xAccessible;
563  if(mpViewShell)
564  {
566  {
567  std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
568  mbShapesNeedSorting = false;
569  }
570 
571  sal_Int32 i(maZOrderedShapes.size() - 1);
572  bool bFound(false);
573  while (!bFound && i >= 0)
574  {
575  ScAccessibleShapeData* pShape = maZOrderedShapes[i];
576  if (pShape)
577  {
578  if (!pShape->pAccShape.is())
579  Get(pShape);
580 
581  if (pShape->pAccShape.is())
582  {
583  Point aPoint(VCLPoint(rPoint));
584  aPoint -= VCLRectangle(pShape->pAccShape->getBounds()).TopLeft();
585  if (pShape->pAccShape->containsPoint(AWTPoint(aPoint)))
586  {
587  xAccessible = pShape->pAccShape.get();
588  bFound = true;
589  }
590  }
591  else
592  {
593  OSL_FAIL("I should have an accessible shape now!");
594  }
595  }
596  else
597  bFound = true; // this is the sheet and it lies before the rest of the shapes which are background shapes
598 
599  --i;
600  }
601  }
602  return xAccessible;
603 }
604 
605 bool ScChildrenShapes::IsSelected(sal_Int32 nIndex,
606  uno::Reference<drawing::XShape>& rShape) const
607 {
608  bool bResult (false);
609  if (maZOrderedShapes.size() <= 1)
610  GetCount(); // fill list with filtered shapes (no internal shapes)
611 
612  if (!xSelectionSupplier.is())
613  throw uno::RuntimeException();
614 
616  {
617  std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
618  mbShapesNeedSorting = false;
619  }
620 
621  if (!maZOrderedShapes[nIndex])
622  return false;
623 
624  bResult = maZOrderedShapes[nIndex]->bSelected;
625  rShape = maZOrderedShapes[nIndex]->xShape;
626 
627 #if OSL_DEBUG_LEVEL > 0 // test whether it is truly selected by a slower method
628  uno::Reference< drawing::XShape > xReturnShape;
629  bool bDebugResult(false);
630  uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
631 
632  if (xShapes.is())
633  {
634  sal_Int32 nCount(xShapes->getCount());
635  if (nCount)
636  {
637  uno::Reference< drawing::XShape > xShape;
638  uno::Reference< drawing::XShape > xIndexShape = maZOrderedShapes[nIndex]->xShape;
639  sal_Int32 i(0);
640  while (!bDebugResult && (i < nCount))
641  {
642  xShapes->getByIndex(i) >>= xShape;
643  if (xShape.is() && (xIndexShape.get() == xShape.get()))
644  {
645  bDebugResult = true;
646  xReturnShape = xShape;
647  }
648  else
649  ++i;
650  }
651  }
652  }
653  OSL_ENSURE((bResult == bDebugResult) && ((bResult && (rShape.get() == xReturnShape.get())) || !bResult), "found the wrong shape or result");
654 #endif
655 
656  return bResult;
657 }
658 
660 {
661  bool bResult(false);
662  if (!xSelectionSupplier.is())
663  throw uno::RuntimeException();
664 
665  uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
666 
667  bResult = FindSelectedShapesChanges(xShapes);
668 
669  return bResult;
670 }
671 
672 void ScChildrenShapes::Select(sal_Int32 nIndex)
673 {
674  if (maZOrderedShapes.size() <= 1)
675  GetCount(); // fill list with filtered shapes (no internal shapes)
676 
677  if (!xSelectionSupplier.is())
678  throw uno::RuntimeException();
679 
681  {
682  std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
683  mbShapesNeedSorting = false;
684  }
685 
686  if (!maZOrderedShapes[nIndex])
687  return;
688 
689  uno::Reference<drawing::XShape> xShape;
690  if (IsSelected(nIndex, xShape) || !maZOrderedShapes[nIndex]->bSelectable)
691  return;
692 
693  uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
694 
695  if (!xShapes.is())
696  xShapes = drawing::ShapeCollection::create(
698 
699  xShapes->add(maZOrderedShapes[nIndex]->xShape);
700 
701  try
702  {
703  xSelectionSupplier->select(uno::makeAny(xShapes));
704  maZOrderedShapes[nIndex]->bSelected = true;
705  if (maZOrderedShapes[nIndex]->pAccShape.is())
706  maZOrderedShapes[nIndex]->pAccShape->SetState(AccessibleStateType::SELECTED);
707  }
708  catch (lang::IllegalArgumentException&)
709  {
710  }
711 }
712 
714 {
715  if (!xSelectionSupplier.is())
716  throw uno::RuntimeException();
717 
718  bool bSomethingSelected(true);
719  try
720  {
721  xSelectionSupplier->select(uno::Any()); //deselects all
722  }
723  catch (lang::IllegalArgumentException&)
724  {
725  OSL_FAIL("nothing selected before");
726  bSomethingSelected = false;
727  }
728 
729  if (bSomethingSelected)
730  for (const ScAccessibleShapeData* pAccShapeData : maZOrderedShapes)
731  if (pAccShapeData)
732  {
733  pAccShapeData->bSelected = false;
734  if (pAccShapeData->pAccShape.is())
735  pAccShapeData->pAccShape->ResetState(AccessibleStateType::SELECTED);
736  }
737 };
738 
739 
741 {
742  if (!xSelectionSupplier.is())
743  throw uno::RuntimeException();
744 
745  if (maZOrderedShapes.size() <= 1)
746  GetCount(); // fill list with filtered shapes (no internal shapes)
747 
748  if (maZOrderedShapes.size() <= 1)
749  return;
750 
751  uno::Reference<drawing::XShapes> xShapes = drawing::ShapeCollection::create(
753 
754  try
755  {
756  for (const ScAccessibleShapeData* pAccShapeData : maZOrderedShapes)
757  {
758  if (pAccShapeData && pAccShapeData->bSelectable)
759  {
760  pAccShapeData->bSelected = true;
761  if (pAccShapeData->pAccShape.is())
762  pAccShapeData->pAccShape->SetState(AccessibleStateType::SELECTED);
763  if (xShapes.is())
764  xShapes->add(pAccShapeData->xShape);
765  }
766  }
767  xSelectionSupplier->select(uno::makeAny(xShapes));
768  }
769  catch (lang::IllegalArgumentException&)
770  {
771  SelectionChanged(); // find all selected shapes and set the flags
772  }
773 }
774 
775 void ScChildrenShapes::FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const
776 {
777  uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
778  if (xShapes.is())
779  {
780  sal_uInt32 nCount(xShapes->getCount());
781  for (sal_uInt32 i = 0; i < nCount; ++i)
782  {
783  uno::Reference<drawing::XShape> xShape;
784  xShapes->getByIndex(i) >>= xShape;
785  if (xShape.is())
786  rShapes.push_back(xShape);
787  }
788  }
789 }
790 
792 {
793  if (!xSelectionSupplier.is())
794  throw uno::RuntimeException();
795 
796  std::vector < uno::Reference < drawing::XShape > > aShapes;
797  FillShapes(aShapes);
798 
799  return aShapes.size();
800 }
801 
802 uno::Reference< XAccessible > ScChildrenShapes::GetSelected(sal_Int32 nSelectedChildIndex, bool bTabSelected) const
803 {
804  uno::Reference< XAccessible > xAccessible;
805 
806  if (maZOrderedShapes.size() <= 1)
807  GetCount(); // fill list with shapes
808 
809  if (!bTabSelected)
810  {
811  std::vector < uno::Reference < drawing::XShape > > aShapes;
812  FillShapes(aShapes);
813 
814  if (nSelectedChildIndex < 0 || o3tl::make_unsigned(nSelectedChildIndex) >= aShapes.size())
815  return xAccessible;
816 
817  SortedShapes::iterator aItr;
818  if (FindShape(aShapes[nSelectedChildIndex], aItr))
819  xAccessible = Get(*aItr);
820  }
821  else
822  {
824  {
825  std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
826  mbShapesNeedSorting = false;
827  }
828  for(const auto& rpShape : maZOrderedShapes)
829  {
830  if (!rpShape || rpShape->bSelected)
831  {
832  if (nSelectedChildIndex == 0)
833  {
834  if (rpShape)
835  xAccessible = rpShape->pAccShape.get();
836  break;
837  }
838  else
839  --nSelectedChildIndex;
840  }
841  }
842  }
843 
844  return xAccessible;
845 }
846 
847 void ScChildrenShapes::Deselect(sal_Int32 nChildIndex)
848 {
849  uno::Reference<drawing::XShape> xShape;
850  if (!IsSelected(nChildIndex, xShape)) // returns false if it is the sheet
851  return;
852 
853  if (!xShape.is())
854  return;
855 
856  uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
857  if (xShapes.is())
858  xShapes->remove(xShape);
859 
860  try
861  {
862  xSelectionSupplier->select(uno::makeAny(xShapes));
863  }
864  catch (lang::IllegalArgumentException&)
865  {
866  OSL_FAIL("something not selectable");
867  }
868 
869  maZOrderedShapes[nChildIndex]->bSelected = false;
870  if (maZOrderedShapes[nChildIndex]->pAccShape.is())
871  maZOrderedShapes[nChildIndex]->pAccShape->ResetState(AccessibleStateType::SELECTED);
872 }
873 
875 {
877  SdrPage* pDrawPage = nullptr;
878  if (mpViewShell)
879  {
881  if (ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer())
882  {
883  if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab))
884  pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(static_cast<sal_Int16>(nTab)));
885  }
886  }
887  return pDrawPage;
888 }
889 
891 {
892  utl::AccessibleRelationSetHelper* pRelationSet = nullptr;
893  for (const ScAccessibleShapeData* pAccShapeData : maZOrderedShapes)
894  {
895  if (pAccShapeData &&
896  ((!pAccShapeData->xRelationCell && !pAddress) ||
897  (pAccShapeData->xRelationCell && pAddress && (*(pAccShapeData->xRelationCell) == *pAddress))))
898  {
899  if (!pRelationSet)
900  pRelationSet = new utl::AccessibleRelationSetHelper();
901 
902  AccessibleRelation aRelation;
903  aRelation.TargetSet.realloc(1);
904  aRelation.TargetSet[0] = Get(pAccShapeData);
905  aRelation.RelationType = AccessibleRelationType::CONTROLLER_FOR;
906 
907  pRelationSet->AddRelation(aRelation);
908  }
909  }
910  return pRelationSet;
911 }
912 
913 bool ScChildrenShapes::FindSelectedShapesChanges(const uno::Reference<drawing::XShapes>& xShapes) const
914 {
915  bool bResult(false);
916  SortedShapes aShapesList;
917  if (xShapes.is())
918  {
919  mnShapesSelected = xShapes->getCount();
920  for (sal_uInt32 i = 0; i < mnShapesSelected; ++i)
921  {
922  uno::Reference< drawing::XShape > xShape;
923  xShapes->getByIndex(i) >>= xShape;
924  if (xShape.is())
925  {
926  ScAccessibleShapeData* pShapeData = new ScAccessibleShapeData(xShape);
927  aShapesList.push_back(pShapeData);
928  }
929  }
930  }
931  else
932  mnShapesSelected = 0;
933  SdrObject *pFocusedObj = nullptr;
934  if( mnShapesSelected == 1 && aShapesList.size() == 1)
935  {
936  pFocusedObj = GetSdrObjectFromXShape(aShapesList[0]->xShape);
937  }
938  std::sort(aShapesList.begin(), aShapesList.end(), ScShapeDataLess());
939  SortedShapes vecSelectedShapeAdd;
940  SortedShapes vecSelectedShapeRemove;
941  bool bHasSelect=false;
942  SortedShapes::iterator aXShapesItr(aShapesList.begin());
943  SortedShapes::const_iterator aXShapesEndItr(aShapesList.end());
944  SortedShapes::iterator aDataItr(maZOrderedShapes.begin());
945  SortedShapes::const_iterator aDataEndItr(maZOrderedShapes.end());
946  SortedShapes::const_iterator aFocusedItr = aDataEndItr;
947  while(aDataItr != aDataEndItr)
948  {
949  if (*aDataItr) // is it really a shape or only the sheet
950  {
951  sal_Int8 nComp(0);
952  if (aXShapesItr == aXShapesEndItr)
953  nComp = -1; // simulate that the Shape is lower, so the selection state will be removed
954  else
955  nComp = Compare(*aDataItr, *aXShapesItr);
956  if (nComp == 0)
957  {
958  if (!(*aDataItr)->bSelected)
959  {
960  (*aDataItr)->bSelected = true;
961  if ((*aDataItr)->pAccShape.is())
962  {
963  (*aDataItr)->pAccShape->SetState(AccessibleStateType::SELECTED);
964  (*aDataItr)->pAccShape->SetState(AccessibleStateType::FOCUSED);
965  bResult = true;
966  vecSelectedShapeAdd.push_back(*aDataItr);
967  }
968  aFocusedItr = aDataItr;
969  }
970  else
971  {
972  bHasSelect = true;
973  }
974  ++aDataItr;
975  ++aXShapesItr;
976  }
977  else if (nComp < 0)
978  {
979  if ((*aDataItr)->bSelected)
980  {
981  (*aDataItr)->bSelected = false;
982  if ((*aDataItr)->pAccShape.is())
983  {
984  (*aDataItr)->pAccShape->ResetState(AccessibleStateType::SELECTED);
985  (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED);
986  bResult = true;
987  vecSelectedShapeRemove.push_back(*aDataItr);
988  }
989  }
990  ++aDataItr;
991  }
992  else
993  {
994  OSL_FAIL("here is a selected shape which is not in the childlist");
995  ++aXShapesItr;
997  }
998  }
999  else
1000  ++aDataItr;
1001  }
1002  bool bWinFocus=false;
1003  if (mpViewShell)
1004  {
1006  if (pWin)
1007  {
1008  bWinFocus = pWin->HasFocus();
1009  }
1010  }
1011  const SdrMarkList* pMarkList = nullptr;
1012  SdrObject* pMarkedObj = nullptr;
1013  bool bIsFocuseMarked = true;
1014  if( mpViewShell && mnShapesSelected == 1 && bWinFocus)
1015  {
1016  ScDrawView* pScDrawView = mpViewShell->GetViewData().GetScDrawView();
1017  if( pScDrawView )
1018  {
1019  if( pScDrawView->GetMarkedObjectList().GetMarkCount() == 1 )
1020  {
1021  pMarkList = &(pScDrawView->GetMarkedObjectList());
1022  pMarkedObj = pMarkList->GetMark(0)->GetMarkedSdrObj();
1023  uno::Reference< drawing::XShape > xMarkedXShape (pMarkedObj->getUnoShape(), uno::UNO_QUERY);
1024  if( aFocusedItr != aDataEndItr &&
1025  (*aFocusedItr)->xShape.is() &&
1026  xMarkedXShape.is() &&
1027  (*aFocusedItr)->xShape != xMarkedXShape )
1028  bIsFocuseMarked = false;
1029  }
1030  }
1031  }
1032  //if ((aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape.is() && (mnShapesSelected == 1))
1033  if ( bIsFocuseMarked && (aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape.is() && (mnShapesSelected == 1) && bWinFocus)
1034  {
1035  (*aFocusedItr)->pAccShape->SetState(AccessibleStateType::FOCUSED);
1036  }
1037  else if( pFocusedObj && bWinFocus && pMarkList && pMarkList->GetMarkCount() == 1 && mnShapesSelected == 1 )
1038  {
1039  if( pMarkedObj )
1040  {
1041  uno::Reference< drawing::XShape > xMarkedXShape (pMarkedObj->getUnoShape(), uno::UNO_QUERY);
1042  SdrObject* pUpObj = pMarkedObj->getParentSdrObjectFromSdrObject();
1043 
1044  if( pMarkedObj == pFocusedObj && pUpObj )
1045  {
1046  uno::Reference< drawing::XShape > xUpGroupXShape (pUpObj->getUnoShape(), uno::UNO_QUERY);
1047  uno::Reference < XAccessible > xAccGroupShape =
1048  const_cast<ScChildrenShapes*>(this)->GetAccessibleCaption( xUpGroupXShape );
1049  if( xAccGroupShape.is() )
1050  {
1051  ::accessibility::AccessibleShape* pAccGroupShape =
1052  static_cast< ::accessibility::AccessibleShape* >(xAccGroupShape.get());
1053  if( pAccGroupShape )
1054  {
1055  sal_Int32 nCount = pAccGroupShape->getAccessibleChildCount();
1056  for( sal_Int32 i = 0; i < nCount; i++ )
1057  {
1058  uno::Reference<XAccessible> xAccShape = pAccGroupShape->getAccessibleChild(i);
1059  if (xAccShape.is())
1060  {
1061  ::accessibility::AccessibleShape* pChildAccShape = static_cast< ::accessibility::AccessibleShape* >(xAccShape.get());
1062  uno::Reference< drawing::XShape > xChildShape = pChildAccShape->GetXShape();
1063  if (xChildShape == xMarkedXShape)
1064  {
1065  pChildAccShape->SetState(AccessibleStateType::FOCUSED);
1066  }
1067  else
1068  {
1069  pChildAccShape->ResetState(AccessibleStateType::FOCUSED);
1070  }
1071  }
1072  }
1073  }
1074  }
1075  }
1076  }
1077  }
1078  if (vecSelectedShapeAdd.size() >= 10 )
1079  {
1080  AccessibleEventObject aEvent;
1081  aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
1082  aEvent.Source = uno::Reference< XAccessible >(mpAccessibleDocument);
1084  }
1085  else
1086  {
1087  for (const auto& rpShape : vecSelectedShapeAdd)
1088  {
1089  AccessibleEventObject aEvent;
1090  if (bHasSelect)
1091  {
1092  aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_ADD;
1093  }
1094  else
1095  {
1096  aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1097  }
1098  aEvent.Source = uno::Reference< XAccessible >(mpAccessibleDocument);
1099  uno::Reference< XAccessible > xChild( rpShape->pAccShape.get());
1100  aEvent.NewValue <<= xChild;
1102  }
1103  }
1104  for (const auto& rpShape : vecSelectedShapeRemove)
1105  {
1106  AccessibleEventObject aEvent;
1107  aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
1108  aEvent.Source = uno::Reference< XAccessible >(mpAccessibleDocument);
1109  uno::Reference< XAccessible > xChild( rpShape->pAccShape.get());
1110  aEvent.NewValue <<= xChild;
1112  }
1113  for(ScAccessibleShapeData*& pShapeData : aShapesList)
1114  {
1115  delete pShapeData;
1116  pShapeData = nullptr;
1117  }
1118  return bResult;
1119 }
1120 
1121 std::optional<ScAddress> ScChildrenShapes::GetAnchor(const uno::Reference<drawing::XShape>& xShape) const
1122 {
1123  if (mpViewShell)
1124  {
1125  SvxShape* pShapeImp = comphelper::getUnoTunnelImplementation<SvxShape>(xShape);
1126  uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
1127  if (pShapeImp && xShapeProp.is())
1128  {
1129  if (SdrObject *pSdrObj = pShapeImp->GetSdrObject())
1130  {
1131  if (ScDrawObjData *pAnchor = ScDrawLayer::GetObjData(pSdrObj))
1132  return std::optional<ScAddress>(pAnchor->maStart);
1133  }
1134  }
1135  }
1136 
1137  return std::optional<ScAddress>();
1138 }
1139 
1140 uno::Reference<XAccessibleRelationSet> ScChildrenShapes::GetRelationSet(const ScAccessibleShapeData* pData) const
1141 {
1143 
1144  if (pData && mpAccessibleDocument)
1145  {
1146  uno::Reference<XAccessible> xAccessible = mpAccessibleDocument->GetAccessibleSpreadsheet(); // should be the current table
1147  if (pData->xRelationCell && xAccessible.is())
1148  {
1149  sal_Int32 nRow = pData->xRelationCell->Row();
1150  sal_Int32 nColumn = pData->xRelationCell->Col();
1151  bool bPositionUnset = nRow == -1 && nColumn == -1;
1152  if (!bPositionUnset)
1153  {
1154  uno::Reference<XAccessibleTable> xAccTable(xAccessible->getAccessibleContext(), uno::UNO_QUERY);
1155  if (xAccTable.is())
1156  xAccessible = xAccTable->getAccessibleCellAt(nRow, nColumn);
1157  }
1158  }
1159  AccessibleRelation aRelation;
1160  aRelation.TargetSet.realloc(1);
1161  aRelation.TargetSet[0] = xAccessible;
1162  aRelation.RelationType = AccessibleRelationType::CONTROLLED_BY;
1163  pRelationSet->AddRelation(aRelation);
1164  }
1165 
1166  return pRelationSet;
1167 }
1168 
1169 void ScChildrenShapes::SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const
1170 {
1171  if (pData)
1172  {
1173  std::optional<ScAddress> xAddress = GetAnchor(xShape);
1174  if ((xAddress && pData->xRelationCell && (*xAddress != *(pData->xRelationCell))) ||
1175  (!xAddress && pData->xRelationCell) || (xAddress && !pData->xRelationCell))
1176  {
1177  pData->xRelationCell = xAddress;
1178  if (pData->pAccShape.is())
1179  pData->pAccShape->SetRelationSet(GetRelationSet(pData));
1180  }
1181  }
1182 }
1183 
1184 void ScChildrenShapes::AddShape(const uno::Reference<drawing::XShape>& xShape, bool bCommitChange) const
1185 {
1186  assert( maShapesMap.find(xShape) == maShapesMap.end());
1187 
1188  ScAccessibleShapeData* pShape = new ScAccessibleShapeData(xShape);
1189  maZOrderedShapes.push_back(pShape);
1190  mbShapesNeedSorting = true;
1191  maShapesMap[xShape] = pShape;
1192  SetAnchor(xShape, pShape);
1193 
1194  uno::Reference< beans::XPropertySet > xShapeProp(xShape, uno::UNO_QUERY);
1195  if (xShapeProp.is())
1196  {
1197  uno::Any aPropAny = xShapeProp->getPropertyValue("LayerID");
1198  sal_Int16 nLayerID = 0;
1199  if( aPropAny >>= nLayerID )
1200  {
1201  if( (SdrLayerID(nLayerID) == SC_LAYER_INTERN) || (SdrLayerID(nLayerID) == SC_LAYER_HIDDEN) )
1202  pShape->bSelectable = false;
1203  else
1204  pShape->bSelectable = true;
1205  }
1206  }
1207 
1208  if (!xSelectionSupplier.is())
1209  throw uno::RuntimeException();
1210 
1211  uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
1212  uno::Reference<container::XEnumerationAccess> xEnumAcc(xShapes, uno::UNO_QUERY);
1213  if (xEnumAcc.is())
1214  {
1215  uno::Reference<container::XEnumeration> xEnum = xEnumAcc->createEnumeration();
1216  if (xEnum.is())
1217  {
1218  uno::Reference<drawing::XShape> xSelectedShape;
1219  bool bFound(false);
1220  while (!bFound && xEnum->hasMoreElements())
1221  {
1222  xEnum->nextElement() >>= xSelectedShape;
1223  if (xShape.is() && (xShape.get() == xSelectedShape.get()))
1224  {
1225  pShape->bSelected = true;
1226  bFound = true;
1227  }
1228  }
1229  }
1230  }
1231  if (mpAccessibleDocument && bCommitChange)
1232  {
1233  AccessibleEventObject aEvent;
1234  aEvent.EventId = AccessibleEventId::CHILD;
1235  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1236  aEvent.NewValue <<= Get(pShape);
1237 
1238  mpAccessibleDocument->CommitChange(aEvent); // new child - event
1239  }
1240 }
1241 
1242 void ScChildrenShapes::RemoveShape(const uno::Reference<drawing::XShape>& xShape) const
1243 {
1244  if (mbShapesNeedSorting)
1245  {
1246  std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
1247  mbShapesNeedSorting = false;
1248  }
1249  SortedShapes::iterator aItr;
1250  if (FindShape(xShape, aItr))
1251  {
1253  {
1254  uno::Reference<XAccessible> xOldAccessible (Get(*aItr));
1255 
1256  delete *aItr;
1257  maShapesMap.erase((*aItr)->xShape);
1258  maZOrderedShapes.erase(aItr);
1259 
1260  AccessibleEventObject aEvent;
1261  aEvent.EventId = AccessibleEventId::CHILD;
1262  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1263  aEvent.OldValue <<= xOldAccessible;
1264 
1265  mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
1266  }
1267  else
1268  {
1269  delete *aItr;
1270  maShapesMap.erase((*aItr)->xShape);
1271  maZOrderedShapes.erase(aItr);
1272  }
1273  }
1274  else
1275  {
1276  OSL_FAIL("shape was not in internal list");
1277  }
1278 }
1279 
1280 bool ScChildrenShapes::FindShape(const uno::Reference<drawing::XShape>& xShape, ScChildrenShapes::SortedShapes::iterator& rItr) const
1281 {
1282  if (mbShapesNeedSorting)
1283  {
1284  std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
1285  mbShapesNeedSorting = false;
1286  }
1287  bool bResult(false);
1288  ScAccessibleShapeData aShape(xShape);
1289  rItr = std::lower_bound(maZOrderedShapes.begin(), maZOrderedShapes.end(), &aShape, ScShapeDataLess());
1290  if ((rItr != maZOrderedShapes.end()) && (*rItr != nullptr) && ((*rItr)->xShape.get() == xShape.get()))
1291  bResult = true; // if the shape is found
1292 
1293 #if OSL_DEBUG_LEVEL > 0 // test whether it finds truly the correct shape (perhaps it is not really sorted)
1294  SortedShapes::iterator aDebugItr = std::find_if(maZOrderedShapes.begin(), maZOrderedShapes.end(),
1295  [&xShape](const ScAccessibleShapeData* pShape) { return pShape && (pShape->xShape.get() == xShape.get()); });
1296  bool bResult2 = (aDebugItr != maZOrderedShapes.end());
1297  OSL_ENSURE((bResult == bResult2) && ((bResult && (rItr == aDebugItr)) || !bResult), "wrong Shape found");
1298 #endif
1299  return bResult;
1300 }
1301 
1302 sal_Int8 ScChildrenShapes::Compare(const ScAccessibleShapeData* pData1,
1303  const ScAccessibleShapeData* pData2)
1304 {
1305  ScShapeDataLess aLess;
1306 
1307  bool bResult1(aLess(pData1, pData2));
1308  bool bResult2(aLess(pData2, pData1));
1309 
1310  sal_Int8 nResult(0);
1311  if (!bResult1 && bResult2)
1312  nResult = 1;
1313  else if (bResult1 && !bResult2)
1314  nResult = -1;
1315 
1316  return nResult;
1317 }
1318 
1320 {
1321  for (const ScAccessibleShapeData* pAccShapeData: maZOrderedShapes)
1322  if (pAccShapeData && pAccShapeData->pAccShape.is())
1323  pAccShapeData->pAccShape->ViewForwarderChanged();
1324 }
1325 
1327  const uno::Reference<XAccessible>& rxParent,
1328  ScTabViewShell* pViewShell,
1329  ScSplitPos eSplitPos)
1330  : ScAccessibleDocumentBase(rxParent),
1331  mpViewShell(pViewShell),
1332  meSplitPos(eSplitPos),
1333  mpTempAccEdit(nullptr),
1334  mbCompleteSheetSelected(false)
1335 {
1337 }
1338 
1340 {
1341  if (!mpViewShell)
1342  return;
1343 
1346  if( pWin )
1347  {
1348  pWin->AddChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1349  sal_uInt16 nCount = pWin->GetChildCount();
1350  for( sal_uInt16 i=0; i < nCount; ++i )
1351  {
1352  vcl::Window *pChildWin = pWin->GetChild( i );
1353  if( pChildWin &&
1354  AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1355  AddChild( pChildWin->GetAccessible(), false );
1356  }
1357  }
1358  ScViewData& rViewData = mpViewShell->GetViewData();
1359  if (rViewData.HasEditView(meSplitPos))
1360  {
1361  uno::Reference<XAccessible> xAcc = new ScAccessibleEditObject(this, rViewData.GetEditView(meSplitPos),
1364  AddChild(xAcc, false);
1365  }
1366 }
1367 
1369 {
1370  if(!mpChildrenShapes)
1372 }
1373 
1375 {
1376  if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
1377  {
1378  // increment refcount to prevent double call off dtor
1379  osl_atomic_increment( &m_refCount );
1380  dispose();
1381  }
1382 }
1383 
1385 {
1386  SolarMutexGuard aGuard;
1388  if (mpViewShell)
1389  {
1391  if( pWin )
1392  pWin->RemoveChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1393 
1395  mpViewShell = nullptr;
1396  }
1397  mpChildrenShapes.reset();
1398 
1400 }
1401 
1402 void SAL_CALL ScAccessibleDocument::disposing( const lang::EventObject& /* Source */ )
1403 {
1404  disposing();
1405 }
1406 
1407  //===== SfxListener =====================================================
1408 
1409 IMPL_LINK( ScAccessibleDocument, WindowChildEventListener, VclWindowEvent&, rEvent, void )
1410 {
1411  OSL_ENSURE( rEvent.GetWindow(), "Window???" );
1412  switch ( rEvent.GetId() )
1413  {
1414  case VclEventId::WindowShow: // send create on show for direct accessible children
1415  {
1416  vcl::Window* pChildWin = static_cast < vcl::Window * >( rEvent.GetData() );
1417  if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1418  {
1419  AddChild( pChildWin->GetAccessible(), true );
1420  }
1421  }
1422  break;
1423  case VclEventId::WindowHide: // send destroy on hide for direct accessible children
1424  {
1425  vcl::Window* pChildWin = static_cast < vcl::Window * >( rEvent.GetData() );
1426  if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1427  {
1428  RemoveChild( pChildWin->GetAccessible(), true );
1429  }
1430  }
1431  break;
1432  default: break;
1433  }
1434 }
1435 
1437 {
1438  if (auto pFocusLostHint = dynamic_cast<const ScAccGridWinFocusLostHint*>(&rHint) )
1439  {
1440  if (pFocusLostHint->GetOldGridWin() == meSplitPos)
1441  {
1442  if (mxTempAcc.is() && mpTempAccEdit)
1444  else if (mpAccessibleSpreadsheet.is())
1445  mpAccessibleSpreadsheet->LostFocus();
1446  else
1447  CommitFocusLost();
1448  }
1449  }
1450  else if (auto pFocusGotHint = dynamic_cast<const ScAccGridWinFocusGotHint*>(&rHint) )
1451  {
1452  if (pFocusGotHint->GetNewGridWin() == meSplitPos)
1453  {
1454  uno::Reference<XAccessible> xAccessible;
1455  if (mpChildrenShapes)
1456  {
1457  bool bTabMarked(IsTableSelected());
1458  xAccessible = mpChildrenShapes->GetSelected(0, bTabMarked);
1459  }
1460  if( xAccessible.is() )
1461  {
1462  uno::Any aNewValue;
1463  aNewValue<<=AccessibleStateType::FOCUSED;
1464  static_cast< ::accessibility::AccessibleShape* >(xAccessible.get())->
1465  CommitChange(AccessibleEventId::STATE_CHANGED,
1466  aNewValue,
1467  uno::Any() );
1468  }
1469  else
1470  {
1471  if (mxTempAcc.is() && mpTempAccEdit)
1473  else if (mpAccessibleSpreadsheet.is())
1474  mpAccessibleSpreadsheet->GotFocus();
1475  else
1477  }
1478  }
1479  }
1480  else
1481  {
1482  // only notify if child exist, otherwise it is not necessary
1483  if ((rHint.GetId() == SfxHintId::ScAccTableChanged) &&
1485  {
1487 
1488  // Shapes / form controls after reload not accessible, rebuild the
1489  // mpChildrenShapes variable.
1491 
1492  AccessibleEventObject aEvent;
1493  aEvent.EventId = AccessibleEventId::INVALIDATE_ALL_CHILDREN;
1494  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1495  CommitChange(aEvent); // all children changed
1496 
1497  if (mpAccessibleSpreadsheet.is())
1498  mpAccessibleSpreadsheet->FireFirstCellFocus();
1499  }
1500  else if (rHint.GetId() == SfxHintId::ScAccMakeDrawLayer)
1501  {
1502  if (mpChildrenShapes)
1503  mpChildrenShapes->SetDrawBroadcaster();
1504  }
1505  else if (rHint.GetId() == SfxHintId::ScAccEnterEditMode) // this event comes only on creating edit field of a cell
1506  {
1508  {
1509  ScViewData& rViewData = mpViewShell->GetViewData();
1510  const EditEngine* pEditEng = rViewData.GetEditView(meSplitPos)->GetEditEngine();
1511  if (pEditEng && pEditEng->GetUpdateMode())
1512  {
1515  ScResId(STR_ACC_EDITLINE_DESCR), ScAccessibleEditObject::CellInEditMode);
1516  uno::Reference<XAccessible> xAcc = mpTempAccEdit;
1517 
1518  AddChild(xAcc, true);
1519 
1520  if (mpAccessibleSpreadsheet.is())
1521  mpAccessibleSpreadsheet->LostFocus();
1522  else
1523  CommitFocusLost();
1524 
1526  }
1527  }
1528  }
1529  else if (rHint.GetId() == SfxHintId::ScAccLeaveEditMode)
1530  {
1531  if (mxTempAcc.is())
1532  {
1533  if (mpTempAccEdit)
1534  {
1536  }
1537  RemoveChild(mxTempAcc, true);
1538  if (mpTempAccEdit)
1539  {
1540  // tdf#125982 a11y use-after-free of editengine by
1541  // ScAccessibleEditObjectTextData living past the
1542  // the editengine of the editview passed in above
1543  // in ScAccEnterEditMode
1544  mpTempAccEdit->dispose();
1545  mpTempAccEdit = nullptr;
1546  }
1548  mpAccessibleSpreadsheet->GotFocus();
1549  else if( mpViewShell && mpViewShell->IsActive())
1551  }
1552  }
1553  else if ((rHint.GetId() == SfxHintId::ScAccVisAreaChanged) || (rHint.GetId() == SfxHintId::ScAccWindowResized))
1554  {
1555  tools::Rectangle aOldVisArea(maVisArea);
1557 
1558  if (maVisArea != aOldVisArea)
1559  {
1560  if (maVisArea.GetSize() != aOldVisArea.GetSize())
1561  {
1562  AccessibleEventObject aEvent;
1563  aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
1564  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1565 
1566  CommitChange(aEvent);
1567 
1568  if (mpAccessibleSpreadsheet.is())
1569  mpAccessibleSpreadsheet->BoundingBoxChanged();
1571  mpAccessibleSpreadsheet->FireFirstCellFocus();
1572  }
1573  else if (mpAccessibleSpreadsheet.is())
1574  {
1575  mpAccessibleSpreadsheet->VisAreaChanged();
1576  }
1577  if (mpChildrenShapes)
1578  mpChildrenShapes->VisAreaChanged();
1579  }
1580  }
1581  }
1582 
1584 }
1585 
1586 void SAL_CALL ScAccessibleDocument::selectionChanged( const lang::EventObject& /* aEvent */ )
1587 {
1588  bool bSelectionChanged(false);
1589  if (mpAccessibleSpreadsheet.is())
1590  {
1591  bool bOldSelected(mbCompleteSheetSelected);
1593  if (bOldSelected != mbCompleteSheetSelected)
1594  {
1595  mpAccessibleSpreadsheet->CompleteSelectionChanged(mbCompleteSheetSelected);
1596  bSelectionChanged = true;
1597  }
1598  }
1599 
1600  if (mpChildrenShapes && mpChildrenShapes->SelectionChanged())
1601  bSelectionChanged = true;
1602 
1603  if (bSelectionChanged)
1604  {
1605  AccessibleEventObject aEvent;
1606  aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1607  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1608 
1609  CommitChange(aEvent);
1610  }
1611 }
1612 
1613  //===== XInterface =====================================================
1614 
1616 {
1618  return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType);
1619 }
1620 
1622  throw ()
1623 {
1625 }
1626 
1628  throw ()
1629 {
1631 }
1632 
1633  //===== XAccessibleComponent ============================================
1634 
1635 uno::Reference< XAccessible > SAL_CALL ScAccessibleDocument::getAccessibleAtPoint(
1636  const awt::Point& rPoint )
1637 {
1638  uno::Reference<XAccessible> xAccessible;
1639  if (containsPoint(rPoint))
1640  {
1641  SolarMutexGuard aGuard;
1642  IsObjectValid();
1643  if (mpChildrenShapes)
1644  xAccessible = mpChildrenShapes->GetAt(rPoint);
1645  if(!xAccessible.is())
1646  {
1647  if (mxTempAcc.is())
1648  {
1649  uno::Reference< XAccessibleContext > xCont(mxTempAcc->getAccessibleContext());
1650  uno::Reference< XAccessibleComponent > xComp(xCont, uno::UNO_QUERY);
1651  if (xComp.is())
1652  {
1653  tools::Rectangle aBound(VCLRectangle(xComp->getBounds()));
1654  if (aBound.IsInside(VCLPoint(rPoint)))
1655  xAccessible = mxTempAcc;
1656  }
1657  }
1658  if (!xAccessible.is())
1659  xAccessible = GetAccessibleSpreadsheet();
1660  }
1661  }
1662  return xAccessible;
1663 }
1664 
1666 {
1667  SolarMutexGuard aGuard;
1668  IsObjectValid();
1669  if (!getAccessibleParent().is())
1670  return;
1671 
1672  uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1673  if (xAccessibleComponent.is())
1674  {
1675  xAccessibleComponent->grabFocus();
1676  // grab only focus if it does not have the focus and it is not hidden
1677  if (mpViewShell &&
1680  {
1682  }
1683  }
1684 }
1685 
1686  //===== XAccessibleContext ==============================================
1687 
1689 sal_Int32 SAL_CALL
1691 {
1692  SolarMutexGuard aGuard;
1693  IsObjectValid();
1694  sal_Int32 nCount(1);
1695  if (mpChildrenShapes)
1696  nCount = mpChildrenShapes->GetCount(); // returns the count of the shapes inclusive the table
1697 
1698  if (mxTempAcc.is())
1699  ++nCount;
1700 
1701  return nCount;
1702 }
1703 
1705 uno::Reference<XAccessible> SAL_CALL
1707 {
1708  SolarMutexGuard aGuard;
1709  IsObjectValid();
1710  uno::Reference<XAccessible> xAccessible;
1711  if (nIndex >= 0)
1712  {
1713  sal_Int32 nCount(1);
1714  if (mpChildrenShapes)
1715  {
1716  xAccessible = mpChildrenShapes->Get(nIndex); // returns NULL if it is the table or out of range
1717  nCount = mpChildrenShapes->GetCount(); //there is always a table
1718  }
1719  if (!xAccessible.is())
1720  {
1721  if (nIndex < nCount)
1722  xAccessible = GetAccessibleSpreadsheet();
1723  else if (nIndex == nCount && mxTempAcc.is())
1724  xAccessible = mxTempAcc;
1725  }
1726  }
1727 
1728  if (!xAccessible.is())
1729  throw lang::IndexOutOfBoundsException();
1730 
1731  return xAccessible;
1732 }
1733 
1735 uno::Reference<XAccessibleStateSet> SAL_CALL
1737 {
1738  SolarMutexGuard aGuard;
1739  uno::Reference<XAccessibleStateSet> xParentStates;
1740  if (getAccessibleParent().is())
1741  {
1742  uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1743  xParentStates = xParentContext->getAccessibleStateSet();
1744  }
1746  if (IsDefunc(xParentStates))
1747  pStateSet->AddState(AccessibleStateType::DEFUNC);
1748  else
1749  {
1750  pStateSet->AddState(AccessibleStateType::EDITABLE);
1751  pStateSet->AddState(AccessibleStateType::ENABLED);
1752  pStateSet->AddState(AccessibleStateType::OPAQUE);
1753  if (isShowing())
1754  pStateSet->AddState(AccessibleStateType::SHOWING);
1755  if (isVisible())
1756  pStateSet->AddState(AccessibleStateType::VISIBLE);
1757  }
1758  return pStateSet;
1759 }
1760 
1761 OUString SAL_CALL
1763 {
1764  SolarMutexGuard g;
1765 
1766  OUString aName = ScResId(STR_ACC_DOC_SPREADSHEET);
1767  ScDocument* pScDoc = GetDocument();
1768  if (!pScDoc)
1769  return aName;
1770 
1771  SfxObjectShell* pObjSh = pScDoc->GetDocumentShell();
1772  if (!pObjSh)
1773  return aName;
1774 
1775  OUString aFileName;
1776  SfxMedium* pMed = pObjSh->GetMedium();
1777  if (pMed)
1778  aFileName = pMed->GetName();
1779 
1780  if (aFileName.isEmpty())
1781  aFileName = pObjSh->GetTitle(SFX_TITLE_APINAME);
1782 
1783  if (!aFileName.isEmpty())
1784  {
1785  OUString aReadOnly;
1786  if (pObjSh->IsReadOnly())
1787  aReadOnly = ScResId(STR_ACC_DOC_SPREADSHEET_READONLY);
1788 
1789  aName = aFileName + aReadOnly + " - " + aName;
1790  }
1791  return aName;
1792 }
1793 
1795 
1796 void SAL_CALL
1798 {
1799  SolarMutexGuard aGuard;
1800  IsObjectValid();
1801 
1802  if (!(mpChildrenShapes && mpViewShell))
1803  return;
1804 
1805  sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table
1806  if (mxTempAcc.is())
1807  ++nCount;
1808  if (nChildIndex < 0 || nChildIndex >= nCount)
1809  throw lang::IndexOutOfBoundsException();
1810 
1811  uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1812  if (xAccessible.is())
1813  {
1814  bool bWasTableSelected(IsTableSelected());
1815  mpChildrenShapes->Select(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is too high
1816  if (bWasTableSelected)
1818  }
1819  else
1820  {
1822  }
1823 }
1824 
1825 sal_Bool SAL_CALL
1827 {
1828  SolarMutexGuard aGuard;
1829  IsObjectValid();
1830  bool bResult(false);
1831 
1832  if (mpChildrenShapes)
1833  {
1834  sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table
1835  if (mxTempAcc.is())
1836  ++nCount;
1837  if (nChildIndex < 0 || nChildIndex >= nCount)
1838  throw lang::IndexOutOfBoundsException();
1839 
1840  uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1841  if (xAccessible.is())
1842  {
1843  uno::Reference<drawing::XShape> xShape;
1844  bResult = mpChildrenShapes->IsSelected(nChildIndex, xShape); // throws no lang::IndexOutOfBoundsException if Index is too high
1845  }
1846  else
1847  {
1848  if (mxTempAcc.is() && nChildIndex == nCount)
1849  bResult = true;
1850  else
1851  bResult = IsTableSelected();
1852  }
1853  }
1854  return bResult;
1855 }
1856 
1857 void SAL_CALL
1859 {
1860  SolarMutexGuard aGuard;
1861  IsObjectValid();
1862 
1863  if (mpChildrenShapes)
1864  mpChildrenShapes->DeselectAll(); //deselects all (also the table)
1865 }
1866 
1867 void SAL_CALL
1869 {
1870  SolarMutexGuard aGuard;
1871  IsObjectValid();
1872 
1873  if (mpChildrenShapes)
1874  mpChildrenShapes->SelectAll();
1875 
1876  // select table after shapes, because while selecting shapes the table will be deselected
1877  if (mpViewShell)
1878  {
1880  }
1881 }
1882 
1883 sal_Int32 SAL_CALL
1885 {
1886  SolarMutexGuard aGuard;
1887  IsObjectValid();
1888  sal_Int32 nCount(0);
1889 
1890  if (mpChildrenShapes)
1891  nCount = mpChildrenShapes->GetSelectedCount();
1892 
1893  if (IsTableSelected())
1894  ++nCount;
1895 
1896  if (mxTempAcc.is())
1897  ++nCount;
1898 
1899  return nCount;
1900 }
1901 
1902 uno::Reference<XAccessible > SAL_CALL
1903  ScAccessibleDocument::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
1904 {
1905  SolarMutexGuard aGuard;
1906  IsObjectValid();
1907  uno::Reference<XAccessible> xAccessible;
1908  if (mpChildrenShapes)
1909  {
1910  sal_Int32 nCount(getSelectedAccessibleChildCount()); //all shapes and the table
1911  if (nSelectedChildIndex < 0 || nSelectedChildIndex >= nCount)
1912  throw lang::IndexOutOfBoundsException();
1913 
1914  bool bTabMarked(IsTableSelected());
1915 
1916  if (mpChildrenShapes)
1917  xAccessible = mpChildrenShapes->GetSelected(nSelectedChildIndex, bTabMarked); // throws no lang::IndexOutOfBoundsException if Index is too high
1918  if (mxTempAcc.is() && nSelectedChildIndex == nCount - 1)
1919  xAccessible = mxTempAcc;
1920  else if (bTabMarked)
1921  xAccessible = GetAccessibleSpreadsheet();
1922  }
1923 
1924  OSL_ENSURE(xAccessible.is(), "here should always be an accessible object or an exception thrown");
1925 
1926  return xAccessible;
1927 }
1928 
1929 void SAL_CALL
1931 {
1932  SolarMutexGuard aGuard;
1933  IsObjectValid();
1934 
1935  if (!(mpChildrenShapes && mpViewShell))
1936  return;
1937 
1938  sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table
1939  if (mxTempAcc.is())
1940  ++nCount;
1941  if (nChildIndex < 0 || nChildIndex >= nCount)
1942  throw lang::IndexOutOfBoundsException();
1943 
1944  bool bTabMarked(IsTableSelected());
1945 
1946  uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1947  if (xAccessible.is())
1948  {
1949  mpChildrenShapes->Deselect(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is too high
1950  if (bTabMarked)
1951  mpViewShell->SelectAll(); // select the table again
1952  }
1953  else if (bTabMarked)
1954  mpViewShell->Unmark();
1955 }
1956 
1957  //===== XServiceInfo ====================================================
1958 
1959 OUString SAL_CALL
1961 {
1962  return "ScAccessibleDocument";
1963 }
1964 
1965 uno::Sequence< OUString> SAL_CALL
1967 {
1968  uno::Sequence< OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
1969  sal_Int32 nOldSize(aSequence.getLength());
1970  aSequence.realloc(nOldSize + 1);
1971 
1972  aSequence[nOldSize] = "com.sun.star.AccessibleSpreadsheetDocumentView";
1973 
1974  return aSequence;
1975 }
1976 
1977 //===== XTypeProvider =======================================================
1978 
1979 uno::Sequence< uno::Type > SAL_CALL ScAccessibleDocument::getTypes()
1980 {
1982 }
1983 
1984 uno::Sequence<sal_Int8> SAL_CALL
1986 {
1987  return css::uno::Sequence<sal_Int8>();
1988 }
1989 
1991 
1993 {
1994  tools::Rectangle aVisRect(GetBoundingBox());
1995 
1996  if (mpViewShell)
1997  {
1998  Point aPoint(mpViewShell->GetViewData().GetPixPos(meSplitPos)); // returns a negative Point
1999  aPoint.setX(-aPoint.getX());
2000  aPoint.setY(-aPoint.getY());
2001  aVisRect.SetPos(aPoint);
2002 
2004  if (pWin)
2005  aVisRect = pWin->PixelToLogic(aVisRect, pWin->GetDrawMapMode());
2006  }
2007 
2008  return aVisRect;
2009 }
2010 
2012 {
2013  SolarMutexGuard aGuard;
2014  IsObjectValid();
2015  return maVisArea;
2016 }
2017 
2018 Point ScAccessibleDocument::LogicToPixel (const Point& rPoint) const
2019 {
2020  SolarMutexGuard aGuard;
2021  IsObjectValid();
2022  Point aPoint;
2024  if (pWin)
2025  {
2026  aPoint = pWin->LogicToPixel(rPoint, pWin->GetDrawMapMode());
2027  aPoint += pWin->GetWindowExtentsRelative(nullptr).TopLeft();
2028  }
2029  return aPoint;
2030 }
2031 
2033 {
2034  SolarMutexGuard aGuard;
2035  IsObjectValid();
2036  Size aSize;
2038  if (pWin)
2039  aSize = pWin->LogicToPixel(rSize, pWin->GetDrawMapMode());
2040  return aSize;
2041 }
2042 
2043  //===== internal ========================================================
2044 
2046 {
2047  utl::AccessibleRelationSetHelper* pRelationSet = nullptr;
2048  if (mpChildrenShapes)
2049  pRelationSet = mpChildrenShapes->GetRelationSet(pAddress);
2050  return pRelationSet;
2051 }
2052 
2053 OUString
2055 {
2056  return STR_ACC_DOC_DESCR;
2057 }
2058 
2059 OUString
2061 {
2062  SolarMutexGuard aGuard;
2063  IsObjectValid();
2064  OUString sName = ScResId(STR_ACC_DOC_NAME);
2065  sal_Int32 nNumber(sal_Int32(meSplitPos) + 1);
2066  sName += OUString::number(nNumber);
2067  return sName;
2068 }
2069 
2071 {
2072  tools::Rectangle aRect;
2073  if (mpViewShell)
2074  {
2076  if (pWindow)
2077  aRect = pWindow->GetWindowExtentsRelative(nullptr);
2078  }
2079  return aRect;
2080 }
2081 
2083 {
2084  tools::Rectangle aRect;
2085  if (mpViewShell)
2086  {
2088  if (pWindow)
2089  aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
2090  }
2091  return aRect;
2092 }
2093 
2095 {
2096  SCTAB nVisibleTable(0);
2097  if (mpViewShell)
2098  nVisibleTable = mpViewShell->GetViewData().GetTabNo();
2099  return nVisibleTable;
2100 }
2101 
2102 uno::Reference < XAccessible >
2104 {
2105  if (!mpAccessibleSpreadsheet.is() && mpViewShell)
2106  {
2108  mpAccessibleSpreadsheet->Init();
2110  }
2111  return mpAccessibleSpreadsheet.get();
2112 }
2113 
2115 {
2116  if (mpAccessibleSpreadsheet.is())
2117  {
2118  mpAccessibleSpreadsheet->dispose();
2119  mpAccessibleSpreadsheet.clear();
2120  }
2121 }
2122 
2124 {
2125  bool bResult (false);
2126  if(mpViewShell)
2127  {
2128  SCTAB nTab(getVisibleTable());
2129  //#103800#; use a copy of MarkData
2131  aMarkData.MarkToMulti();
2132  ScDocument* pDoc = GetDocument();
2133  if (aMarkData.IsAllMarked( ScRange( 0, 0, nTab, pDoc->MaxCol(), pDoc->MaxRow(), nTab)))
2134  bResult = true;
2135  }
2136  return bResult;
2137 }
2138 
2140  const uno::Reference<XAccessibleStateSet>& rxParentStates)
2141 {
2142  return ScAccessibleContextBase::IsDefunc() || (mpViewShell == nullptr) || !getAccessibleParent().is() ||
2143  (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
2144 }
2145 
2146 void ScAccessibleDocument::AddChild(const uno::Reference<XAccessible>& xAcc, bool bFireEvent)
2147 {
2148  OSL_ENSURE(!mxTempAcc.is(), "this object should be removed before");
2149  if (xAcc.is())
2150  {
2151  mxTempAcc = xAcc;
2152  if( bFireEvent )
2153  {
2154  AccessibleEventObject aEvent;
2155  aEvent.Source = uno::Reference<XAccessibleContext>(this);
2156  aEvent.EventId = AccessibleEventId::CHILD;
2157  aEvent.NewValue <<= mxTempAcc;
2158  CommitChange( aEvent );
2159  }
2160  }
2161 }
2162 
2163 void ScAccessibleDocument::RemoveChild(const uno::Reference<XAccessible>& xAcc, bool bFireEvent)
2164 {
2165  OSL_ENSURE(mxTempAcc.is(), "this object should be added before");
2166  if (!xAcc.is())
2167  return;
2168 
2169  OSL_ENSURE(xAcc.get() == mxTempAcc.get(), "only the same object should be removed");
2170  if( bFireEvent )
2171  {
2172  AccessibleEventObject aEvent;
2173  aEvent.Source = uno::Reference<XAccessibleContext>(this);
2174  aEvent.EventId = AccessibleEventId::CHILD;
2175  aEvent.OldValue <<= mxTempAcc;
2176  CommitChange( aEvent );
2177  }
2178  mxTempAcc = nullptr;
2179 }
2180 
2182 {
2183  OUString sName(ScResId(STR_ACC_CELL_NAME));
2184  if (mpViewShell)
2185  {
2186  // Document not needed, because only the cell address, but not the tablename is needed
2187  OUString sAddress(mpViewShell->GetViewData().GetCurPos().Format(ScRefFlags::VALID));
2188  sName = sName.replaceFirst("%1", sAddress);
2189  }
2190  return sName;
2191 }
2192 
2194 {
2195  return OUString();
2196 }
2197 
2199 {
2200  return mpViewShell ? &mpViewShell->GetViewData().GetDocument() : nullptr;
2201 }
2202 
2204 {
2206 }
2207 
2209 {
2210  SolarMutexGuard g;
2211 
2212  uno::Any anyAttribute;
2213 
2214  sal_uInt16 sheetIndex;
2215  OUString sSheetName;
2216  sheetIndex = getVisibleTable();
2217  if(GetDocument()==nullptr)
2218  return anyAttribute;
2219  GetDocument()->GetName(sheetIndex,sSheetName);
2220  OUString sValue = "page-name:" + sSheetName +
2221  ";page-number:" + OUString::number(sheetIndex+1) +
2222  ";total-pages:" + OUString::number(GetDocument()->GetTableCount()) + ";";
2223  anyAttribute <<= sValue;
2224  return anyAttribute;
2225 }
2226 
2228 {
2229  return sal_Int32(COL_BLACK);
2230 }
2231 
2233 {
2234  SolarMutexGuard aGuard;
2235  IsObjectValid();
2236  return sal_Int32(SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor);
2237 }
2238 
2239 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScMarkData & GetMarkData()
Definition: viewdata.cxx:3046
Point TopLeft() const
SfxViewFrame * GetViewFrame() const
void SetPos(const Point &rPoint)
uno::Reference< XAccessible > GetAt(const awt::Point &rPoint) const
void SelectAll(bool bContinue=false)
Definition: tabview2.cxx:1063
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2107
sal_Int32 GetCount() const
void RemoveShape(const uno::Reference< drawing::XShape > &xShape) const
virtual Point LogicToPixel(const Point &rPoint) const override
Transform the specified point from internal coordinates to an absolute screen position.
bool hasValue()
sal_Int32 nIndex
IMPL_LINK(ScAccessibleDocument, WindowChildEventListener, VclWindowEvent &, rEvent, void)
SdrHintKind GetKind() const
size_t GetMarkCount() const
virtual OUString createAccessibleDescription() override
Return this object's description.
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:43
virtual void SAL_CALL selectionChanged(const css::lang::EventObject &aEvent) override
===== XSelectionListener =============================================
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int32 nIndex) override
Return the specified child or NULL if index is invalid.
css::awt::Point AWTPoint(const ::Point &rVCLPoint)
MapMode GetDrawMapMode(bool bForce=false)
MapMode for the drawinglayer objects.
Definition: gridwin3.cxx:246
sal_Int32 GetSelectedCount() const
OUString GetTitle(sal_uInt16 nMaxLen=0) const
void MarkToMulti()
Definition: markdata.cxx:224
utl::AccessibleRelationSetHelper * GetRelationSet(const ScAddress *pAddress) const
ScAddress GetCurCellAddress() const
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
===== SfxListener =====================================================
signed char sal_Int8
ULONG m_refCount
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex) override
vcl::Window * GetAccessibleParentWindow() const
void Select(sal_Int32 nIndex)
void AddAccessibilityObject(SfxListener &rObject)
Definition: tabvwshh.cxx:207
const OUString & GetName() const
long Long
virtual sal_Bool SAL_CALL isAccessibleChildSelected(sal_Int32 nChildIndex) override
const css::uno::Reference< css::drawing::XShape > & GetXShape() const
static ScDrawObjData * GetObjData(SdrObject *pObj, bool bCreate=false)
Definition: drwlayer.cxx:2282
virtual void SAL_CALL acquire() override
ScTabViewShell * mpViewShell
SdrObject * GetObj(size_t nNum) const
size_t GetObjCount() const
virtual void SAL_CALL grabFocus() override
bool HasEditView(ScSplitPos eWhich) const
Definition: viewdata.hxx:564
SCTAB GetTabNo() const
Definition: viewdata.hxx:395
bool FindShape(const uno::Reference< drawing::XShape > &xShape, SortedShapes::iterator &rItr) const
constexpr SdrLayerID SC_LAYER_BACK(1)
void RemoveChildEventListener(const Link< VclWindowEvent &, void > &rEventListener)
void Unmark()
Definition: tabview3.cxx:1718
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
Return a reference to the parent.
bool IsActive() const
Definition: tabvwsh.hxx:374
ScSplitPos GetActivePart() const
Definition: viewdata.hxx:398
static OUString GetCurrentCellDescription()
SdrMark * GetMark(size_t nNum) const
ScDocument & GetDocument() const
Definition: viewdata.hxx:380
virtual tools::Rectangle GetBoundingBox() const override
Return the object's current bounding box relative to the parent object.
rtl::Reference< AccessibleShape > CreateAccessibleObject(const AccessibleShapeInfo &rShapeInfo, const AccessibleShapeTreeInfo &rShapeTreeInfo) const
std::unordered_map< css::uno::Reference< css::drawing::XShape >, ScAccessibleShapeData * > ShapesMap
virtual void SAL_CALL release() override
virtual ~ScChildrenShapes() override
virtual sal_Int32 SAL_CALL getBackground() override
virtual sal_Bool SAL_CALL containsPoint(const css::awt::Point &rPoint) override
===== XAccessibleComponent ============================================
ScChildrenShapes(ScAccessibleDocument *pAccessibleDocument, ScTabViewShell *pViewShell, ScSplitPos eSplitPos)
virtual bool ReplaceChild(::accessibility::AccessibleShape *pCurrentChild, const css::uno::Reference< css::drawing::XShape > &_rxShape, const tools::Long _nIndex, const ::accessibility::AccessibleShapeTreeInfo &_rShapeTreeInfo) override
===== IAccessibleParent ===============================================
SfxHintId GetId() const
ScSplitPos
Definition: viewdata.hxx:45
virtual OUString createAccessibleName() override
Return the object's current name.
css::uno::Reference< css::drawing::XShapes > getSelectedXShapes()
Definition: viewuno.cxx:825
virtual void SAL_CALL deselectAccessibleChild(sal_Int32 nChildIndex) override
void VisAreaChanged() const
virtual OUString SAL_CALL getImplementationName() override
===== XServiceInfo ===================================================
virtual css::uno::Reference< css::uno::XInterface > getUnoShape()
SdrPage * getSdrPageFromSdrObject() const
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
Returns an implementation id.
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:873
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
css::uno::Reference< css::accessibility::XAccessible > GetAccessible(bool bCreate=true)
virtual void SAL_CALL release() override
virtual OUString SAL_CALL getAccessibleName() override
Return the object's current name.
SfxFrame & GetFrame() const
int nCount
uno::Reference< XAccessible > Get(const ScAccessibleShapeData *pData) const
ScAccessibleDocument * mpAccessibleDocument
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Returns a list of all supported services.
void ActivatePart(ScSplitPos eWhich)
Definition: tabview3.cxx:2868
void AddRelation(const css::accessibility::AccessibleRelation &rRelation)
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
===== SfxListener =====================================================
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(const css::awt::Point &rPoint) override
===== XAccessibleComponent ============================================
tools::Rectangle GetWindowExtentsRelative(const vcl::Window *pRelativeWindow) const
const char * sName
ScDrawView * GetScDrawView()
Definition: viewdata.cxx:3074
ScViewData & GetViewData()
Definition: tabview.hxx:332
void Deselect(sal_Int32 nChildIndex)
virtual void SAL_CALL disposing() override
virtual sal_Int32 SAL_CALL getAccessibleChildCount() override
===== XAccessibleContext ==============================================
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Returns a list of all supported services.
virtual css::uno::Any SAL_CALL getExtendedAttributes() override
Point GetPixPos(ScSplitPos eWhich) const
Definition: viewdata.hxx:629
virtual void SAL_CALL selectAccessibleChild(sal_Int32 nChildIndex) override
===== XAccessibleSelection ===========================================
SdrObject * GetMarkedSdrObj() const
ScAccessibleDocument(const css::uno::Reference< css::accessibility::XAccessible > &rxParent, ScTabViewShell *pViewShell, ScSplitPos eSplitPos)
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
===== SfxListener =====================================================
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1059
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:872
#define SFX_TITLE_APINAME
vcl::Window * GetWindowByPos(ScSplitPos ePos) const
Definition: tabview.hxx:370
int i
SVXCORE_DLLPUBLIC SdrObject * GetSdrObjectFromXShape(const css::uno::Reference< css::drawing::XShape > &xShape)
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
===== XTypeProvider ===================================================
inline::tools::Rectangle VCLRectangle(const css::awt::Rectangle &rAWTRect)
#define SC_MOD()
Definition: scmod.hxx:253
ScSplitPos GetEditActivePart() const
Definition: viewdata.hxx:584
css::uno::Reference< css::accessibility::XAccessible > mxTempAcc
const SdrMarkList & GetMarkedObjectList() const
virtual ::accessibility::AccessibleControlShape * GetAccControlShapeFromModel(css::beans::XPropertySet *pSet) override
void AddShape(const uno::Reference< drawing::XShape > &xShape, bool bCommitChange) const
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
css::uno::Reference< css::accessibility::XAccessible > GetAccessibleSpreadsheet()
const css::uno::Reference< css::beans::XPropertySet > & GetControlModel() const
float u
unsigned char sal_Bool
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
void SetAnchor(const uno::Reference< drawing::XShape > &xShape, ScAccessibleShapeData *pData) const
ScTabViewShell * mpViewShell
bool IsInside(const Point &rPOINT) const
This base class provides an implementation of the AccessibleTable service.
inline::Point VCLPoint(const css::awt::Point &rAWTPoint)
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
SdrPage * GetDrawPage() const
virtual void SAL_CALL acquire() override
css::uno::Sequence< T > concatSequences(const css::uno::Sequence< T > &rS1, const Ss &...rSn)
ScAccessibleEditObject * mpTempAccEdit
Size GetSize() const
mutable::accessibility::AccessibleShapeTreeInfo maShapeTreeInfo
bool IsSelected(sal_Int32 nIndex, css::uno::Reference< css::drawing::XShape > &rShape) const
bool IsReadOnly() const
virtual void SAL_CALL selectAllAccessibleChildren() override
ScAddress GetCurPos() const
Definition: viewdata.cxx:4007
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
Point PixelToLogic(const Point &rDevicePt) const
Point LogicToPixel(const Point &rLogicPt) const
void FillShapes(std::vector< uno::Reference< drawing::XShape > > &rShapes) const
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int32 nIndex) override
virtual tools::Rectangle GetBoundingBoxOnScreen() const override
Return the object's current bounding box relative to the desktop.
tools::Rectangle GetVisibleArea_Impl() const
===== IAccessibleViewForwarder ========================================
sal_uInt16 GetChildCount() const
void AddChild(const css::uno::Reference< css::accessibility::XAccessible > &xAcc, bool bFireEvent)
virtual void SAL_CALL disposing() override
constexpr SdrLayerID SC_LAYER_HIDDEN(4)
virtual sal_Int32 SAL_CALL getForeground() override
unsigned char sal_uInt8
void RemoveAccessibilityObject(SfxListener &rObject)
Definition: tabvwshh.cxx:217
virtual void SAL_CALL clearAccessibleSelection() override
SortedShapes maZOrderedShapes
bool GetUpdateMode() const
virtual css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet() override
Return the set of current states.
constexpr SdrLayerID SC_LAYER_FRONT(0)
bool IsVisible() const
#define STR_ACC_DOC_DESCR
Definition: strings.hxx:14
ShapeTypeId GetTypeId(const OUString &aServiceName) const
css::uno::Reference< css::frame::XController > GetController() const
OUString aName
constexpr SdrLayerID SC_LAYER_INTERN(2)
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
SdrObject * GetSdrObject() const
virtual sal_Int32 SAL_CALL getAccessibleChildCount() override
SfxBroadcaster * GetDrawBroadcaster()
Definition: documen9.cxx:53
void CommitFocusLost() const
Calls all FocusListener to tell they that the focus is lost.
Reference< XComponentContext > getProcessComponentContext()
rtl::Reference< ScAccessibleSpreadsheet > mpAccessibleSpreadsheet
const ::std::vector< Color > ImpSvNumberformatScan::StandardColor COL_BLACK
std::unique_ptr< ScChildrenShapes > mpChildrenShapes
std::optional< ScAddress > GetAnchor(const uno::Reference< drawing::XShape > &xShape) const
tools::Rectangle maVisArea
std::vector< ScAccessibleShapeData * > SortedShapes
virtual void Init() override
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
OUString GetCurrentCellName() const
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
===== XTypeProvider ===================================================
virtual bool ResetState(sal_Int16 aState) override
SdrObject * getParentSdrObjectFromSdrObject() const
virtual tools::Rectangle GetVisibleArea() const override
===== IAccessibleViewForwarder ========================================
void CommitChange(const css::accessibility::AccessibleEventObject &rEvent) const
Calls all Listener to tell they the change.
uno::Reference< XAccessible > GetSelected(sal_Int32 nSelectedChildIndex, bool bTabSelected) const
ScDocument * GetDocument() const
virtual bool SetState(sal_Int16 aState) override
bool FindSelectedShapesChanges(const css::uno::Reference< css::drawing::XShapes > &xShapes) const
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1058
virtual css::uno::Reference< css::accessibility::XAccessible > GetAccessibleCaption(const css::uno::Reference< css::drawing::XShape > &xShape) override
virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount() override
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) override
===== XInterface =====================================================
static sal_Int8 Compare(const ScAccessibleShapeData *pData1, const ScAccessibleShapeData *pData2)
SdrObjList * getParentSdrObjListFromSdrObject() const
void dispose()
utl::AccessibleRelationSetHelper * GetRelationSet(const ScAddress *pAddress) const
======== internal =====================================================
sal_uInt16 GetAccessibleRole() const
void RemoveChild(const css::uno::Reference< css::accessibility::XAccessible > &xAcc, bool bFireEvent)
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) override
===== XInterface =====================================================
bool HasFocus() const
virtual ~ScAccessibleDocument() override
void AddState(sal_Int16 aState)
css::uno::Reference< css::view::XSelectionSupplier > xSelectionSupplier
constexpr SdrLayerID SC_LAYER_CONTROLS(3)
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:213
AnyEventRef aEvent
void GetEditView(ScSplitPos eWhich, EditView *&rViewPtr, SCCOL &rCol, SCROW &rRow)
Definition: viewdata.cxx:2219
void AddChildEventListener(const Link< VclWindowEvent &, void > &rEventListener)
sal_Int16 SCTAB
Definition: types.hxx:23
void SetDrawBroadcaster()
===== Internal ========================================================
virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext() override
===== XAccessible =====================================================
vcl::Window * GetChild(sal_uInt16 nChild) const
const SdrObject * GetObject() const
SfxMedium * GetMedium() const
This base class provides an implementation of the AccessibleCell service.