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