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.SetWindow(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);
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 );
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;
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 {
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 = { Get(pAccShapeData) };
904  aRelation.RelationType = AccessibleRelationType::CONTROLLER_FOR;
905 
906  pRelationSet->AddRelation(aRelation);
907  }
908  }
909  return pRelationSet;
910 }
911 
912 bool ScChildrenShapes::FindSelectedShapesChanges(const uno::Reference<drawing::XShapes>& xShapes) const
913 {
914  bool bResult(false);
915  SortedShapes aShapesList;
916  if (xShapes.is())
917  {
918  mnShapesSelected = xShapes->getCount();
919  for (sal_uInt32 i = 0; i < mnShapesSelected; ++i)
920  {
921  uno::Reference< drawing::XShape > xShape;
922  xShapes->getByIndex(i) >>= xShape;
923  if (xShape.is())
924  {
925  ScAccessibleShapeData* pShapeData = new ScAccessibleShapeData(xShape);
926  aShapesList.push_back(pShapeData);
927  }
928  }
929  }
930  else
931  mnShapesSelected = 0;
932  SdrObject *pFocusedObj = nullptr;
933  if( mnShapesSelected == 1 && aShapesList.size() == 1)
934  {
935  pFocusedObj = SdrObject::getSdrObjectFromXShape(aShapesList[0]->xShape);
936  }
937  std::sort(aShapesList.begin(), aShapesList.end(), ScShapeDataLess());
938  SortedShapes vecSelectedShapeAdd;
939  SortedShapes vecSelectedShapeRemove;
940  bool bHasSelect=false;
941  SortedShapes::iterator aXShapesItr(aShapesList.begin());
942  SortedShapes::const_iterator aXShapesEndItr(aShapesList.end());
943  SortedShapes::iterator aDataItr(maZOrderedShapes.begin());
944  SortedShapes::const_iterator aDataEndItr(maZOrderedShapes.end());
945  SortedShapes::const_iterator aFocusedItr = aDataEndItr;
946  while(aDataItr != aDataEndItr)
947  {
948  if (*aDataItr) // is it really a shape or only the sheet
949  {
950  sal_Int8 nComp(0);
951  if (aXShapesItr == aXShapesEndItr)
952  nComp = -1; // simulate that the Shape is lower, so the selection state will be removed
953  else
954  nComp = Compare(*aDataItr, *aXShapesItr);
955  if (nComp == 0)
956  {
957  if (!(*aDataItr)->bSelected)
958  {
959  (*aDataItr)->bSelected = true;
960  if ((*aDataItr)->pAccShape.is())
961  {
962  (*aDataItr)->pAccShape->SetState(AccessibleStateType::SELECTED);
963  (*aDataItr)->pAccShape->SetState(AccessibleStateType::FOCUSED);
964  bResult = true;
965  vecSelectedShapeAdd.push_back(*aDataItr);
966  }
967  aFocusedItr = aDataItr;
968  }
969  else
970  {
971  bHasSelect = true;
972  }
973  ++aDataItr;
974  ++aXShapesItr;
975  }
976  else if (nComp < 0)
977  {
978  if ((*aDataItr)->bSelected)
979  {
980  (*aDataItr)->bSelected = false;
981  if ((*aDataItr)->pAccShape.is())
982  {
983  (*aDataItr)->pAccShape->ResetState(AccessibleStateType::SELECTED);
984  (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED);
985  bResult = true;
986  vecSelectedShapeRemove.push_back(*aDataItr);
987  }
988  }
989  ++aDataItr;
990  }
991  else
992  {
993  OSL_FAIL("here is a selected shape which is not in the childlist");
994  ++aXShapesItr;
996  }
997  }
998  else
999  ++aDataItr;
1000  }
1001  bool bWinFocus=false;
1002  if (mpViewShell)
1003  {
1005  if (pWin)
1006  {
1007  bWinFocus = pWin->HasFocus();
1008  }
1009  }
1010  const SdrMarkList* pMarkList = nullptr;
1011  SdrObject* pMarkedObj = nullptr;
1012  bool bIsFocuseMarked = true;
1013  if( mpViewShell && mnShapesSelected == 1 && bWinFocus)
1014  {
1015  ScDrawView* pScDrawView = mpViewShell->GetViewData().GetScDrawView();
1016  if( pScDrawView )
1017  {
1018  if( pScDrawView->GetMarkedObjectList().GetMarkCount() == 1 )
1019  {
1020  pMarkList = &(pScDrawView->GetMarkedObjectList());
1021  pMarkedObj = pMarkList->GetMark(0)->GetMarkedSdrObj();
1022  uno::Reference< drawing::XShape > xMarkedXShape (pMarkedObj->getUnoShape(), uno::UNO_QUERY);
1023  if( aFocusedItr != aDataEndItr &&
1024  (*aFocusedItr)->xShape.is() &&
1025  xMarkedXShape.is() &&
1026  (*aFocusedItr)->xShape != xMarkedXShape )
1027  bIsFocuseMarked = false;
1028  }
1029  }
1030  }
1031  //if ((aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape.is() && (mnShapesSelected == 1))
1032  if ( bIsFocuseMarked && (aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape.is() && (mnShapesSelected == 1) && bWinFocus)
1033  {
1034  (*aFocusedItr)->pAccShape->SetState(AccessibleStateType::FOCUSED);
1035  }
1036  else if( pFocusedObj && bWinFocus && pMarkList && pMarkList->GetMarkCount() == 1 && mnShapesSelected == 1 )
1037  {
1038  if( pMarkedObj )
1039  {
1040  uno::Reference< drawing::XShape > xMarkedXShape (pMarkedObj->getUnoShape(), uno::UNO_QUERY);
1041  SdrObject* pUpObj = pMarkedObj->getParentSdrObjectFromSdrObject();
1042 
1043  if( pMarkedObj == pFocusedObj && pUpObj )
1044  {
1045  uno::Reference< drawing::XShape > xUpGroupXShape (pUpObj->getUnoShape(), uno::UNO_QUERY);
1046  uno::Reference < XAccessible > xAccGroupShape =
1047  const_cast<ScChildrenShapes*>(this)->GetAccessibleCaption( xUpGroupXShape );
1048  if( xAccGroupShape.is() )
1049  {
1050  ::accessibility::AccessibleShape* pAccGroupShape =
1051  static_cast< ::accessibility::AccessibleShape* >(xAccGroupShape.get());
1052  if( pAccGroupShape )
1053  {
1054  sal_Int32 nCount = pAccGroupShape->getAccessibleChildCount();
1055  for( sal_Int32 i = 0; i < nCount; i++ )
1056  {
1057  uno::Reference<XAccessible> xAccShape = pAccGroupShape->getAccessibleChild(i);
1058  if (xAccShape.is())
1059  {
1060  ::accessibility::AccessibleShape* pChildAccShape = static_cast< ::accessibility::AccessibleShape* >(xAccShape.get());
1061  uno::Reference< drawing::XShape > xChildShape = pChildAccShape->GetXShape();
1062  if (xChildShape == xMarkedXShape)
1063  {
1064  pChildAccShape->SetState(AccessibleStateType::FOCUSED);
1065  }
1066  else
1067  {
1068  pChildAccShape->ResetState(AccessibleStateType::FOCUSED);
1069  }
1070  }
1071  }
1072  }
1073  }
1074  }
1075  }
1076  }
1077  if (vecSelectedShapeAdd.size() >= 10 )
1078  {
1079  AccessibleEventObject aEvent;
1080  aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
1081  aEvent.Source = uno::Reference< XAccessible >(mpAccessibleDocument);
1083  }
1084  else
1085  {
1086  for (const auto& rpShape : vecSelectedShapeAdd)
1087  {
1088  AccessibleEventObject aEvent;
1089  if (bHasSelect)
1090  {
1091  aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_ADD;
1092  }
1093  else
1094  {
1095  aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1096  }
1097  aEvent.Source = uno::Reference< XAccessible >(mpAccessibleDocument);
1098  uno::Reference< XAccessible > xChild( rpShape->pAccShape );
1099  aEvent.NewValue <<= xChild;
1101  }
1102  }
1103  for (const auto& rpShape : vecSelectedShapeRemove)
1104  {
1105  AccessibleEventObject aEvent;
1106  aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
1107  aEvent.Source = uno::Reference< XAccessible >(mpAccessibleDocument);
1108  uno::Reference< XAccessible > xChild( rpShape->pAccShape );
1109  aEvent.NewValue <<= xChild;
1111  }
1112  for(ScAccessibleShapeData*& pShapeData : aShapesList)
1113  {
1114  delete pShapeData;
1115  pShapeData = nullptr;
1116  }
1117  return bResult;
1118 }
1119 
1120 std::optional<ScAddress> ScChildrenShapes::GetAnchor(const uno::Reference<drawing::XShape>& xShape) const
1121 {
1122  if (mpViewShell)
1123  {
1124  SdrObject* pSdrObj = SdrObject::getSdrObjectFromXShape(xShape);
1125  uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
1126  if (pSdrObj && xShapeProp.is())
1127  {
1128  if (ScDrawObjData *pAnchor = ScDrawLayer::GetObjData(pSdrObj))
1129  return std::optional<ScAddress>(pAnchor->maStart);
1130  }
1131  }
1132 
1133  return std::optional<ScAddress>();
1134 }
1135 
1136 uno::Reference<XAccessibleRelationSet> ScChildrenShapes::GetRelationSet(const ScAccessibleShapeData* pData) const
1137 {
1139 
1140  if (pData && mpAccessibleDocument)
1141  {
1142  uno::Reference<XAccessible> xAccessible = mpAccessibleDocument->GetAccessibleSpreadsheet(); // should be the current table
1143  if (pData->xRelationCell && xAccessible.is())
1144  {
1145  sal_Int32 nRow = pData->xRelationCell->Row();
1146  sal_Int32 nColumn = pData->xRelationCell->Col();
1147  bool bPositionUnset = nRow == -1 && nColumn == -1;
1148  if (!bPositionUnset)
1149  {
1150  uno::Reference<XAccessibleTable> xAccTable(xAccessible->getAccessibleContext(), uno::UNO_QUERY);
1151  if (xAccTable.is())
1152  xAccessible = xAccTable->getAccessibleCellAt(nRow, nColumn);
1153  }
1154  }
1155  AccessibleRelation aRelation;
1156  aRelation.TargetSet = { xAccessible };
1157  aRelation.RelationType = AccessibleRelationType::CONTROLLED_BY;
1158  pRelationSet->AddRelation(aRelation);
1159  }
1160 
1161  return pRelationSet;
1162 }
1163 
1164 void ScChildrenShapes::SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const
1165 {
1166  if (pData)
1167  {
1168  std::optional<ScAddress> xAddress = GetAnchor(xShape);
1169  if ((xAddress && pData->xRelationCell && (*xAddress != *(pData->xRelationCell))) ||
1170  (!xAddress && pData->xRelationCell) || (xAddress && !pData->xRelationCell))
1171  {
1172  pData->xRelationCell = xAddress;
1173  if (pData->pAccShape.is())
1174  pData->pAccShape->SetRelationSet(GetRelationSet(pData));
1175  }
1176  }
1177 }
1178 
1179 void ScChildrenShapes::AddShape(const uno::Reference<drawing::XShape>& xShape, bool bCommitChange) const
1180 {
1181  assert( maShapesMap.find(xShape) == maShapesMap.end());
1182 
1183  ScAccessibleShapeData* pShape = new ScAccessibleShapeData(xShape);
1184  maZOrderedShapes.push_back(pShape);
1185  mbShapesNeedSorting = true;
1186  maShapesMap[xShape] = pShape;
1187  SetAnchor(xShape, pShape);
1188 
1189  uno::Reference< beans::XPropertySet > xShapeProp(xShape, uno::UNO_QUERY);
1190  if (xShapeProp.is())
1191  {
1192  uno::Any aPropAny = xShapeProp->getPropertyValue("LayerID");
1193  sal_Int16 nLayerID = 0;
1194  if( aPropAny >>= nLayerID )
1195  {
1196  if( (SdrLayerID(nLayerID) == SC_LAYER_INTERN) || (SdrLayerID(nLayerID) == SC_LAYER_HIDDEN) )
1197  pShape->bSelectable = false;
1198  else
1199  pShape->bSelectable = true;
1200  }
1201  }
1202 
1203  if (!xSelectionSupplier.is())
1204  throw uno::RuntimeException();
1205 
1206  uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
1207  uno::Reference<container::XEnumerationAccess> xEnumAcc(xShapes, uno::UNO_QUERY);
1208  if (xEnumAcc.is())
1209  {
1210  uno::Reference<container::XEnumeration> xEnum = xEnumAcc->createEnumeration();
1211  if (xEnum.is())
1212  {
1213  uno::Reference<drawing::XShape> xSelectedShape;
1214  bool bFound(false);
1215  while (!bFound && xEnum->hasMoreElements())
1216  {
1217  xEnum->nextElement() >>= xSelectedShape;
1218  if (xShape.is() && (xShape.get() == xSelectedShape.get()))
1219  {
1220  pShape->bSelected = true;
1221  bFound = true;
1222  }
1223  }
1224  }
1225  }
1226  if (mpAccessibleDocument && bCommitChange)
1227  {
1228  AccessibleEventObject aEvent;
1229  aEvent.EventId = AccessibleEventId::CHILD;
1230  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1231  aEvent.NewValue <<= Get(pShape);
1232 
1233  mpAccessibleDocument->CommitChange(aEvent); // new child - event
1234  }
1235 }
1236 
1237 void ScChildrenShapes::RemoveShape(const uno::Reference<drawing::XShape>& xShape) const
1238 {
1239  if (mbShapesNeedSorting)
1240  {
1241  std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
1242  mbShapesNeedSorting = false;
1243  }
1244  SortedShapes::iterator aItr;
1245  if (FindShape(xShape, aItr))
1246  {
1248  {
1249  uno::Reference<XAccessible> xOldAccessible (Get(*aItr));
1250 
1251  delete *aItr;
1252  maShapesMap.erase((*aItr)->xShape);
1253  maZOrderedShapes.erase(aItr);
1254 
1255  AccessibleEventObject aEvent;
1256  aEvent.EventId = AccessibleEventId::CHILD;
1257  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1258  aEvent.OldValue <<= xOldAccessible;
1259 
1260  mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
1261  }
1262  else
1263  {
1264  delete *aItr;
1265  maShapesMap.erase((*aItr)->xShape);
1266  maZOrderedShapes.erase(aItr);
1267  }
1268  }
1269  else
1270  {
1271  OSL_FAIL("shape was not in internal list");
1272  }
1273 }
1274 
1275 bool ScChildrenShapes::FindShape(const uno::Reference<drawing::XShape>& xShape, ScChildrenShapes::SortedShapes::iterator& rItr) const
1276 {
1277  if (mbShapesNeedSorting)
1278  {
1279  std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
1280  mbShapesNeedSorting = false;
1281  }
1282  bool bResult(false);
1283  ScAccessibleShapeData aShape(xShape);
1284  rItr = std::lower_bound(maZOrderedShapes.begin(), maZOrderedShapes.end(), &aShape, ScShapeDataLess());
1285  if ((rItr != maZOrderedShapes.end()) && (*rItr != nullptr) && ((*rItr)->xShape.get() == xShape.get()))
1286  bResult = true; // if the shape is found
1287 
1288 #if OSL_DEBUG_LEVEL > 0 // test whether it finds truly the correct shape (perhaps it is not really sorted)
1289  SortedShapes::iterator aDebugItr = std::find_if(maZOrderedShapes.begin(), maZOrderedShapes.end(),
1290  [&xShape](const ScAccessibleShapeData* pShape) { return pShape && (pShape->xShape.get() == xShape.get()); });
1291  bool bResult2 = (aDebugItr != maZOrderedShapes.end());
1292  OSL_ENSURE((bResult == bResult2) && ((bResult && (rItr == aDebugItr)) || !bResult), "wrong Shape found");
1293 #endif
1294  return bResult;
1295 }
1296 
1297 sal_Int8 ScChildrenShapes::Compare(const ScAccessibleShapeData* pData1,
1298  const ScAccessibleShapeData* pData2)
1299 {
1300  ScShapeDataLess aLess;
1301 
1302  bool bResult1(aLess(pData1, pData2));
1303  bool bResult2(aLess(pData2, pData1));
1304 
1305  sal_Int8 nResult(0);
1306  if (!bResult1 && bResult2)
1307  nResult = 1;
1308  else if (bResult1 && !bResult2)
1309  nResult = -1;
1310 
1311  return nResult;
1312 }
1313 
1315 {
1316  for (const ScAccessibleShapeData* pAccShapeData: maZOrderedShapes)
1317  if (pAccShapeData && pAccShapeData->pAccShape.is())
1318  pAccShapeData->pAccShape->ViewForwarderChanged();
1319 }
1320 
1322  const uno::Reference<XAccessible>& rxParent,
1323  ScTabViewShell* pViewShell,
1324  ScSplitPos eSplitPos)
1325  : ScAccessibleDocumentBase(rxParent),
1326  mpViewShell(pViewShell),
1327  meSplitPos(eSplitPos),
1328  mbCompleteSheetSelected(false)
1329 {
1331 }
1332 
1334 {
1335  if (!mpViewShell)
1336  return;
1337 
1340  if( pWin )
1341  {
1342  pWin->AddChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1343  sal_uInt16 nCount = pWin->GetChildCount();
1344  for( sal_uInt16 i=0; i < nCount; ++i )
1345  {
1346  vcl::Window *pChildWin = pWin->GetChild( i );
1347  if( pChildWin &&
1348  AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1349  AddChild( pChildWin->GetAccessible(), false );
1350  }
1351  }
1352  ScViewData& rViewData = mpViewShell->GetViewData();
1353  if (rViewData.HasEditView(meSplitPos))
1354  {
1355  uno::Reference<XAccessible> xAcc = new ScAccessibleEditObject(this, rViewData.GetEditView(meSplitPos),
1358  AddChild(xAcc, false);
1359  }
1360 }
1361 
1363 {
1364  if(!mpChildrenShapes)
1366 }
1367 
1369 {
1370  if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
1371  {
1372  // increment refcount to prevent double call off dtor
1373  osl_atomic_increment( &m_refCount );
1374  dispose();
1375  }
1376 }
1377 
1379 {
1380  SolarMutexGuard aGuard;
1382  if (mpViewShell)
1383  {
1385  if( pWin )
1386  pWin->RemoveChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1387 
1389  mpViewShell = nullptr;
1390  }
1391  mpChildrenShapes.reset();
1392 
1394 }
1395 
1396 void SAL_CALL ScAccessibleDocument::disposing( const lang::EventObject& /* Source */ )
1397 {
1398  disposing();
1399 }
1400 
1401  //===== SfxListener =====================================================
1402 
1403 IMPL_LINK( ScAccessibleDocument, WindowChildEventListener, VclWindowEvent&, rEvent, void )
1404 {
1405  OSL_ENSURE( rEvent.GetWindow(), "Window???" );
1406  switch ( rEvent.GetId() )
1407  {
1408  case VclEventId::WindowShow: // send create on show for direct accessible children
1409  {
1410  vcl::Window* pChildWin = static_cast < vcl::Window * >( rEvent.GetData() );
1411  if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1412  {
1413  AddChild( pChildWin->GetAccessible(), true );
1414  }
1415  }
1416  break;
1417  case VclEventId::WindowHide: // send destroy on hide for direct accessible children
1418  {
1419  vcl::Window* pChildWin = static_cast < vcl::Window * >( rEvent.GetData() );
1420  if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1421  {
1422  RemoveChild( pChildWin->GetAccessible(), true );
1423  }
1424  }
1425  break;
1426  default: break;
1427  }
1428 }
1429 
1431 {
1432  if (auto pFocusLostHint = dynamic_cast<const ScAccGridWinFocusLostHint*>(&rHint) )
1433  {
1434  if (pFocusLostHint->GetOldGridWin() == meSplitPos)
1435  {
1436  if (mxTempAcc.is() && mpTempAccEdit)
1437  mpTempAccEdit->LostFocus();
1438  else if (mpAccessibleSpreadsheet.is())
1439  mpAccessibleSpreadsheet->LostFocus();
1440  else
1441  CommitFocusLost();
1442  }
1443  }
1444  else if (auto pFocusGotHint = dynamic_cast<const ScAccGridWinFocusGotHint*>(&rHint) )
1445  {
1446  if (pFocusGotHint->GetNewGridWin() == meSplitPos)
1447  {
1448  uno::Reference<XAccessible> xAccessible;
1449  if (mpChildrenShapes)
1450  {
1451  bool bTabMarked(IsTableSelected());
1452  xAccessible = mpChildrenShapes->GetSelected(0, bTabMarked);
1453  }
1454  if( xAccessible.is() )
1455  {
1456  uno::Any aNewValue;
1457  aNewValue<<=AccessibleStateType::FOCUSED;
1458  static_cast< ::accessibility::AccessibleShape* >(xAccessible.get())->
1459  CommitChange(AccessibleEventId::STATE_CHANGED,
1460  aNewValue,
1461  uno::Any() );
1462  }
1463  else
1464  {
1465  if (mxTempAcc.is() && mpTempAccEdit)
1466  mpTempAccEdit->GotFocus();
1467  else if (mpAccessibleSpreadsheet.is())
1468  mpAccessibleSpreadsheet->GotFocus();
1469  else
1471  }
1472  }
1473  }
1474  else
1475  {
1476  // only notify if child exist, otherwise it is not necessary
1477  if ((rHint.GetId() == SfxHintId::ScAccTableChanged) &&
1479  {
1481 
1482  // Shapes / form controls after reload not accessible, rebuild the
1483  // mpChildrenShapes variable.
1485 
1486  AccessibleEventObject aEvent;
1487  aEvent.EventId = AccessibleEventId::INVALIDATE_ALL_CHILDREN;
1488  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1489  CommitChange(aEvent); // all children changed
1490 
1491  if (mpAccessibleSpreadsheet.is())
1492  mpAccessibleSpreadsheet->FireFirstCellFocus();
1493  }
1494  else if (rHint.GetId() == SfxHintId::ScAccMakeDrawLayer)
1495  {
1496  if (mpChildrenShapes)
1497  mpChildrenShapes->SetDrawBroadcaster();
1498  }
1499  else if (rHint.GetId() == SfxHintId::ScAccEnterEditMode) // this event comes only on creating edit field of a cell
1500  {
1502  {
1503  ScViewData& rViewData = mpViewShell->GetViewData();
1504  const EditEngine* pEditEng = rViewData.GetEditView(meSplitPos)->GetEditEngine();
1505  if (pEditEng && pEditEng->IsUpdateLayout())
1506  {
1509  ScResId(STR_ACC_EDITLINE_DESCR), ScAccessibleEditObject::CellInEditMode);
1510  uno::Reference<XAccessible> xAcc = mpTempAccEdit;
1511 
1512  AddChild(xAcc, true);
1513 
1514  if (mpAccessibleSpreadsheet.is())
1515  mpAccessibleSpreadsheet->LostFocus();
1516  else
1517  CommitFocusLost();
1518 
1519  mpTempAccEdit->GotFocus();
1520  }
1521  }
1522  }
1523  else if (rHint.GetId() == SfxHintId::ScAccLeaveEditMode)
1524  {
1525  if (mxTempAcc.is())
1526  {
1527  if (mpTempAccEdit)
1528  {
1529  mpTempAccEdit->LostFocus();
1530  }
1531  RemoveChild(mxTempAcc, true);
1532  if (mpTempAccEdit)
1533  {
1534  // tdf#125982 a11y use-after-free of editengine by
1535  // ScAccessibleEditObjectTextData living past the
1536  // the editengine of the editview passed in above
1537  // in ScAccEnterEditMode
1538  mpTempAccEdit->dispose();
1539  mpTempAccEdit = nullptr;
1540  }
1542  mpAccessibleSpreadsheet->GotFocus();
1543  else if( mpViewShell && mpViewShell->IsActive())
1545  }
1546  }
1547  else if ((rHint.GetId() == SfxHintId::ScAccVisAreaChanged) || (rHint.GetId() == SfxHintId::ScAccWindowResized))
1548  {
1549  tools::Rectangle aOldVisArea(maVisArea);
1551 
1552  if (maVisArea != aOldVisArea)
1553  {
1554  if (maVisArea.GetSize() != aOldVisArea.GetSize())
1555  {
1556  AccessibleEventObject aEvent;
1557  aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
1558  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1559 
1560  CommitChange(aEvent);
1561 
1562  if (mpAccessibleSpreadsheet.is())
1563  mpAccessibleSpreadsheet->BoundingBoxChanged();
1565  mpAccessibleSpreadsheet->FireFirstCellFocus();
1566  }
1567  else if (mpAccessibleSpreadsheet.is())
1568  {
1569  mpAccessibleSpreadsheet->VisAreaChanged();
1570  }
1571  if (mpChildrenShapes)
1572  mpChildrenShapes->VisAreaChanged();
1573  }
1574  }
1575  }
1576 
1578 }
1579 
1580 void SAL_CALL ScAccessibleDocument::selectionChanged( const lang::EventObject& /* aEvent */ )
1581 {
1582  bool bSelectionChanged(false);
1583  if (mpAccessibleSpreadsheet.is())
1584  {
1585  bool bOldSelected(mbCompleteSheetSelected);
1587  if (bOldSelected != mbCompleteSheetSelected)
1588  {
1589  mpAccessibleSpreadsheet->CompleteSelectionChanged(mbCompleteSheetSelected);
1590  bSelectionChanged = true;
1591  }
1592  }
1593 
1594  if (mpChildrenShapes && mpChildrenShapes->SelectionChanged())
1595  bSelectionChanged = true;
1596 
1597  if (bSelectionChanged)
1598  {
1599  AccessibleEventObject aEvent;
1600  aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1601  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1602 
1603  CommitChange(aEvent);
1604  }
1605 }
1606 
1607  //===== XInterface =====================================================
1608 
1610 {
1612  return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType);
1613 }
1614 
1616  noexcept
1617 {
1619 }
1620 
1622  noexcept
1623 {
1625 }
1626 
1627  //===== XAccessibleComponent ============================================
1628 
1629 uno::Reference< XAccessible > SAL_CALL ScAccessibleDocument::getAccessibleAtPoint(
1630  const awt::Point& rPoint )
1631 {
1632  uno::Reference<XAccessible> xAccessible;
1633  if (containsPoint(rPoint))
1634  {
1635  SolarMutexGuard aGuard;
1636  IsObjectValid();
1637  if (mpChildrenShapes)
1638  xAccessible = mpChildrenShapes->GetAt(rPoint);
1639  if(!xAccessible.is())
1640  {
1641  if (mxTempAcc.is())
1642  {
1643  uno::Reference< XAccessibleContext > xCont(mxTempAcc->getAccessibleContext());
1644  uno::Reference< XAccessibleComponent > xComp(xCont, uno::UNO_QUERY);
1645  if (xComp.is())
1646  {
1647  tools::Rectangle aBound(VCLRectangle(xComp->getBounds()));
1648  if (aBound.Contains(VCLPoint(rPoint)))
1649  xAccessible = mxTempAcc;
1650  }
1651  }
1652  if (!xAccessible.is())
1653  xAccessible = GetAccessibleSpreadsheet();
1654  }
1655  }
1656  return xAccessible;
1657 }
1658 
1660 {
1661  SolarMutexGuard aGuard;
1662  IsObjectValid();
1663  if (!getAccessibleParent().is())
1664  return;
1665 
1666  uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1667  if (xAccessibleComponent.is())
1668  {
1669  xAccessibleComponent->grabFocus();
1670  // grab only focus if it does not have the focus and it is not hidden
1671  if (mpViewShell &&
1674  {
1676  }
1677  }
1678 }
1679 
1680  //===== XAccessibleContext ==============================================
1681 
1683 sal_Int32 SAL_CALL
1685 {
1686  SolarMutexGuard aGuard;
1687  IsObjectValid();
1688  sal_Int32 nCount(1);
1689  if (mpChildrenShapes)
1690  nCount = mpChildrenShapes->GetCount(); // returns the count of the shapes inclusive the table
1691 
1692  if (mxTempAcc.is())
1693  ++nCount;
1694 
1695  return nCount;
1696 }
1697 
1699 uno::Reference<XAccessible> SAL_CALL
1701 {
1702  SolarMutexGuard aGuard;
1703  IsObjectValid();
1704  uno::Reference<XAccessible> xAccessible;
1705  if (nIndex >= 0)
1706  {
1707  sal_Int32 nCount(1);
1708  if (mpChildrenShapes)
1709  {
1710  xAccessible = mpChildrenShapes->Get(nIndex); // returns NULL if it is the table or out of range
1711  nCount = mpChildrenShapes->GetCount(); //there is always a table
1712  }
1713  if (!xAccessible.is())
1714  {
1715  if (nIndex < nCount)
1716  xAccessible = GetAccessibleSpreadsheet();
1717  else if (nIndex == nCount && mxTempAcc.is())
1718  xAccessible = mxTempAcc;
1719  }
1720  }
1721 
1722  if (!xAccessible.is())
1723  throw lang::IndexOutOfBoundsException();
1724 
1725  return xAccessible;
1726 }
1727 
1729 uno::Reference<XAccessibleStateSet> SAL_CALL
1731 {
1732  SolarMutexGuard aGuard;
1733  uno::Reference<XAccessibleStateSet> xParentStates;
1734  if (getAccessibleParent().is())
1735  {
1736  uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1737  xParentStates = xParentContext->getAccessibleStateSet();
1738  }
1740  if (IsDefunc(xParentStates))
1741  pStateSet->AddState(AccessibleStateType::DEFUNC);
1742  else
1743  {
1744  pStateSet->AddState(AccessibleStateType::EDITABLE);
1745  pStateSet->AddState(AccessibleStateType::ENABLED);
1746  pStateSet->AddState(AccessibleStateType::OPAQUE);
1747  if (isShowing())
1748  pStateSet->AddState(AccessibleStateType::SHOWING);
1749  if (isVisible())
1750  pStateSet->AddState(AccessibleStateType::VISIBLE);
1751  }
1752  return pStateSet;
1753 }
1754 
1755 OUString SAL_CALL
1757 {
1758  SolarMutexGuard g;
1759 
1760  OUString aName = ScResId(STR_ACC_DOC_SPREADSHEET);
1761  ScDocument* pScDoc = GetDocument();
1762  if (!pScDoc)
1763  return aName;
1764 
1765  SfxObjectShell* pObjSh = pScDoc->GetDocumentShell();
1766  if (!pObjSh)
1767  return aName;
1768 
1769  OUString aFileName;
1770  SfxMedium* pMed = pObjSh->GetMedium();
1771  if (pMed)
1772  aFileName = pMed->GetName();
1773 
1774  if (aFileName.isEmpty())
1775  aFileName = pObjSh->GetTitle(SFX_TITLE_APINAME);
1776 
1777  if (!aFileName.isEmpty())
1778  {
1779  OUString aReadOnly;
1780  if (pObjSh->IsReadOnly())
1781  aReadOnly = ScResId(STR_ACC_DOC_SPREADSHEET_READONLY);
1782 
1783  aName = aFileName + aReadOnly + " - " + aName;
1784  }
1785  return aName;
1786 }
1787 
1789 
1790 void SAL_CALL
1792 {
1793  SolarMutexGuard aGuard;
1794  IsObjectValid();
1795 
1796  if (!(mpChildrenShapes && mpViewShell))
1797  return;
1798 
1799  sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table
1800  if (mxTempAcc.is())
1801  ++nCount;
1802  if (nChildIndex < 0 || nChildIndex >= nCount)
1803  throw lang::IndexOutOfBoundsException();
1804 
1805  uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1806  if (xAccessible.is())
1807  {
1808  bool bWasTableSelected(IsTableSelected());
1809  mpChildrenShapes->Select(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is too high
1810  if (bWasTableSelected)
1812  }
1813  else
1814  {
1816  }
1817 }
1818 
1819 sal_Bool SAL_CALL
1821 {
1822  SolarMutexGuard aGuard;
1823  IsObjectValid();
1824  bool bResult(false);
1825 
1826  if (mpChildrenShapes)
1827  {
1828  sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table
1829  if (mxTempAcc.is())
1830  ++nCount;
1831  if (nChildIndex < 0 || nChildIndex >= nCount)
1832  throw lang::IndexOutOfBoundsException();
1833 
1834  uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1835  if (xAccessible.is())
1836  {
1837  uno::Reference<drawing::XShape> xShape;
1838  bResult = mpChildrenShapes->IsSelected(nChildIndex, xShape); // throws no lang::IndexOutOfBoundsException if Index is too high
1839  }
1840  else
1841  {
1842  if (mxTempAcc.is() && nChildIndex == nCount)
1843  bResult = true;
1844  else
1845  bResult = IsTableSelected();
1846  }
1847  }
1848  return bResult;
1849 }
1850 
1851 void SAL_CALL
1853 {
1854  SolarMutexGuard aGuard;
1855  IsObjectValid();
1856 
1857  if (mpChildrenShapes)
1858  mpChildrenShapes->DeselectAll(); //deselects all (also the table)
1859 }
1860 
1861 void SAL_CALL
1863 {
1864  SolarMutexGuard aGuard;
1865  IsObjectValid();
1866 
1867  if (mpChildrenShapes)
1868  mpChildrenShapes->SelectAll();
1869 
1870  // select table after shapes, because while selecting shapes the table will be deselected
1871  if (mpViewShell)
1872  {
1874  }
1875 }
1876 
1877 sal_Int32 SAL_CALL
1879 {
1880  SolarMutexGuard aGuard;
1881  IsObjectValid();
1882  sal_Int32 nCount(0);
1883 
1884  if (mpChildrenShapes)
1885  nCount = mpChildrenShapes->GetSelectedCount();
1886 
1887  if (IsTableSelected())
1888  ++nCount;
1889 
1890  if (mxTempAcc.is())
1891  ++nCount;
1892 
1893  return nCount;
1894 }
1895 
1896 uno::Reference<XAccessible > SAL_CALL
1897  ScAccessibleDocument::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
1898 {
1899  SolarMutexGuard aGuard;
1900  IsObjectValid();
1901  uno::Reference<XAccessible> xAccessible;
1902  if (mpChildrenShapes)
1903  {
1904  sal_Int32 nCount(getSelectedAccessibleChildCount()); //all shapes and the table
1905  if (nSelectedChildIndex < 0 || nSelectedChildIndex >= nCount)
1906  throw lang::IndexOutOfBoundsException();
1907 
1908  bool bTabMarked(IsTableSelected());
1909 
1910  if (mpChildrenShapes)
1911  xAccessible = mpChildrenShapes->GetSelected(nSelectedChildIndex, bTabMarked); // throws no lang::IndexOutOfBoundsException if Index is too high
1912  if (mxTempAcc.is() && nSelectedChildIndex == nCount - 1)
1913  xAccessible = mxTempAcc;
1914  else if (bTabMarked)
1915  xAccessible = GetAccessibleSpreadsheet();
1916  }
1917 
1918  OSL_ENSURE(xAccessible.is(), "here should always be an accessible object or an exception thrown");
1919 
1920  return xAccessible;
1921 }
1922 
1923 void SAL_CALL
1925 {
1926  SolarMutexGuard aGuard;
1927  IsObjectValid();
1928 
1929  if (!(mpChildrenShapes && mpViewShell))
1930  return;
1931 
1932  sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table
1933  if (mxTempAcc.is())
1934  ++nCount;
1935  if (nChildIndex < 0 || nChildIndex >= nCount)
1936  throw lang::IndexOutOfBoundsException();
1937 
1938  bool bTabMarked(IsTableSelected());
1939 
1940  uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1941  if (xAccessible.is())
1942  {
1943  mpChildrenShapes->Deselect(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is too high
1944  if (bTabMarked)
1945  mpViewShell->SelectAll(); // select the table again
1946  }
1947  else if (bTabMarked)
1948  mpViewShell->Unmark();
1949 }
1950 
1951  //===== XServiceInfo ====================================================
1952 
1953 OUString SAL_CALL
1955 {
1956  return "ScAccessibleDocument";
1957 }
1958 
1959 uno::Sequence< OUString> SAL_CALL
1961 {
1962  const css::uno::Sequence<OUString> vals { "com.sun.star.AccessibleSpreadsheetDocumentView" };
1964 }
1965 
1966 //===== XTypeProvider =======================================================
1967 
1968 uno::Sequence< uno::Type > SAL_CALL ScAccessibleDocument::getTypes()
1969 {
1971 }
1972 
1973 uno::Sequence<sal_Int8> SAL_CALL
1975 {
1976  return css::uno::Sequence<sal_Int8>();
1977 }
1978 
1980 
1982 {
1983  tools::Rectangle aVisRect(GetBoundingBox());
1984 
1985  if (mpViewShell)
1986  {
1987  Point aPoint(mpViewShell->GetViewData().GetPixPos(meSplitPos)); // returns a negative Point
1988  aPoint.setX(-aPoint.getX());
1989  aPoint.setY(-aPoint.getY());
1990  aVisRect.SetPos(aPoint);
1991 
1993  if (pWin)
1994  aVisRect = pWin->PixelToLogic(aVisRect, pWin->GetDrawMapMode());
1995  }
1996 
1997  return aVisRect;
1998 }
1999 
2001 {
2002  SolarMutexGuard aGuard;
2003  IsObjectValid();
2004  return maVisArea;
2005 }
2006 
2007 Point ScAccessibleDocument::LogicToPixel (const Point& rPoint) const
2008 {
2009  SolarMutexGuard aGuard;
2010  IsObjectValid();
2011  Point aPoint;
2013  if (pWin)
2014  {
2015  aPoint = pWin->LogicToPixel(rPoint, pWin->GetDrawMapMode());
2016  aPoint += pWin->GetWindowExtentsRelative(nullptr).TopLeft();
2017  }
2018  return aPoint;
2019 }
2020 
2022 {
2023  SolarMutexGuard aGuard;
2024  IsObjectValid();
2025  Size aSize;
2027  if (pWin)
2028  aSize = pWin->LogicToPixel(rSize, pWin->GetDrawMapMode());
2029  return aSize;
2030 }
2031 
2032  //===== internal ========================================================
2033 
2035 {
2037  if (mpChildrenShapes)
2038  pRelationSet = mpChildrenShapes->GetRelationSet(pAddress);
2039  return pRelationSet;
2040 }
2041 
2042 OUString
2044 {
2045  return STR_ACC_DOC_DESCR;
2046 }
2047 
2048 OUString
2050 {
2051  SolarMutexGuard aGuard;
2052  IsObjectValid();
2053  OUString sName = ScResId(STR_ACC_DOC_NAME);
2054  sal_Int32 nNumber(sal_Int32(meSplitPos) + 1);
2055  sName += OUString::number(nNumber);
2056  return sName;
2057 }
2058 
2060 {
2061  tools::Rectangle aRect;
2062  if (mpViewShell)
2063  {
2065  if (pWindow)
2066  aRect = pWindow->GetWindowExtentsRelative(nullptr);
2067  }
2068  return aRect;
2069 }
2070 
2072 {
2073  tools::Rectangle aRect;
2074  if (mpViewShell)
2075  {
2077  if (pWindow)
2078  aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
2079  }
2080  return aRect;
2081 }
2082 
2084 {
2085  SCTAB nVisibleTable(0);
2086  if (mpViewShell)
2087  nVisibleTable = mpViewShell->GetViewData().GetTabNo();
2088  return nVisibleTable;
2089 }
2090 
2091 uno::Reference < XAccessible >
2093 {
2094  if (!mpAccessibleSpreadsheet.is() && mpViewShell)
2095  {
2097  mpAccessibleSpreadsheet->Init();
2099  }
2100  return mpAccessibleSpreadsheet;
2101 }
2102 
2104 {
2105  if (mpAccessibleSpreadsheet.is())
2106  {
2107  mpAccessibleSpreadsheet->dispose();
2108  mpAccessibleSpreadsheet.clear();
2109  }
2110 }
2111 
2113 {
2114  bool bResult (false);
2115  if(mpViewShell)
2116  {
2117  SCTAB nTab(getVisibleTable());
2118  //#103800#; use a copy of MarkData
2120  aMarkData.MarkToMulti();
2121  ScDocument* pDoc = GetDocument();
2122  if (aMarkData.IsAllMarked( ScRange( 0, 0, nTab, pDoc->MaxCol(), pDoc->MaxRow(), nTab)))
2123  bResult = true;
2124  }
2125  return bResult;
2126 }
2127 
2129  const uno::Reference<XAccessibleStateSet>& rxParentStates)
2130 {
2131  return ScAccessibleContextBase::IsDefunc() || (mpViewShell == nullptr) || !getAccessibleParent().is() ||
2132  (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
2133 }
2134 
2135 void ScAccessibleDocument::AddChild(const uno::Reference<XAccessible>& xAcc, bool bFireEvent)
2136 {
2137  OSL_ENSURE(!mxTempAcc.is(), "this object should be removed before");
2138  if (xAcc.is())
2139  {
2140  mxTempAcc = xAcc;
2141  if( bFireEvent )
2142  {
2143  AccessibleEventObject aEvent;
2144  aEvent.Source = uno::Reference<XAccessibleContext>(this);
2145  aEvent.EventId = AccessibleEventId::CHILD;
2146  aEvent.NewValue <<= mxTempAcc;
2147  CommitChange( aEvent );
2148  }
2149  }
2150 }
2151 
2152 void ScAccessibleDocument::RemoveChild(const uno::Reference<XAccessible>& xAcc, bool bFireEvent)
2153 {
2154  OSL_ENSURE(mxTempAcc.is(), "this object should be added before");
2155  if (!xAcc.is())
2156  return;
2157 
2158  OSL_ENSURE(xAcc.get() == mxTempAcc.get(), "only the same object should be removed");
2159  if( bFireEvent )
2160  {
2161  AccessibleEventObject aEvent;
2162  aEvent.Source = uno::Reference<XAccessibleContext>(this);
2163  aEvent.EventId = AccessibleEventId::CHILD;
2164  aEvent.OldValue <<= mxTempAcc;
2165  CommitChange( aEvent );
2166  }
2167  mxTempAcc = nullptr;
2168 }
2169 
2171 {
2172  OUString sName(ScResId(STR_ACC_CELL_NAME));
2173  if (mpViewShell)
2174  {
2175  // Document not needed, because only the cell address, but not the tablename is needed
2176  OUString sAddress(mpViewShell->GetViewData().GetCurPos().Format(ScRefFlags::VALID));
2177  sName = sName.replaceFirst("%1", sAddress);
2178  }
2179  return sName;
2180 }
2181 
2183 {
2184  return OUString();
2185 }
2186 
2188 {
2189  return mpViewShell ? &mpViewShell->GetViewData().GetDocument() : nullptr;
2190 }
2191 
2193 {
2195 }
2196 
2198 {
2199  SolarMutexGuard g;
2200 
2201  uno::Any anyAttribute;
2202 
2203  sal_uInt16 sheetIndex;
2204  OUString sSheetName;
2205  sheetIndex = getVisibleTable();
2206  if(GetDocument()==nullptr)
2207  return anyAttribute;
2208  GetDocument()->GetName(sheetIndex,sSheetName);
2209  OUString sValue = "page-name:" + sSheetName +
2210  ";page-number:" + OUString::number(sheetIndex+1) +
2211  ";total-pages:" + OUString::number(GetDocument()->GetTableCount()) + ";";
2212  anyAttribute <<= sValue;
2213  return anyAttribute;
2214 }
2215 
2217 {
2218  return sal_Int32(COL_BLACK);
2219 }
2220 
2222 {
2223  SolarMutexGuard aGuard;
2224  IsObjectValid();
2225  return sal_Int32(SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor);
2226 }
2227 
2228 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScMarkData & GetMarkData()
Definition: viewdata.cxx:3109
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:1064
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2117
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:89
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
void MarkToMulti()
Definition: markdata.cxx:223
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:2593
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:572
virtual void SAL_CALL release() noexcept override
SCTAB GetTabNo() const
Definition: viewdata.hxx:394
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:1723
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
Return a reference to the parent.
bool IsActive() const
Definition: tabvwsh.hxx:372
ScSplitPos GetActivePart() const
Definition: viewdata.hxx:397
static OUString GetCurrentCellDescription()
SdrMark * GetMark(size_t nNum) const
ScDocument & GetDocument() const
Definition: viewdata.hxx:379
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:820
virtual void SAL_CALL deselectAccessibleChild(sal_Int32 nChildIndex) override
void VisAreaChanged() const
virtual OUString SAL_CALL getImplementationName() override
===== XServiceInfo ===================================================
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:872
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:2879
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:3137
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:637
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:1058
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:871
#define SFX_TITLE_APINAME
vcl::Window * GetWindowByPos(ScSplitPos ePos) const
Definition: tabview.hxx:371
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:250
ScSplitPos GetEditActivePart() const
Definition: viewdata.hxx:592
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:4077
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
unsigned char sal_uInt8
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
#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
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:1057
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:213
AnyEventRef aEvent
void GetEditView(ScSplitPos eWhich, EditView *&rViewPtr, SCCOL &rCol, SCROW &rRow)
Definition: viewdata.cxx:2280
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 =====================================================
vcl::Window * GetChild(sal_uInt16 nChild) const
const SdrObject * GetObject() const
SfxMedium * GetMedium() const
This base class provides an implementation of the AccessibleCell service.