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 = "LayerID";
111  static constexpr OUStringLiteral gsZOrder = "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 long _nIndex,
219  const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo
220  ) override;
221 
222  virtual ::accessibility::AccessibleControlShape* GetAccControlShapeFromModel
223  (css::beans::XPropertySet* pSet) override;
224  virtual css::uno::Reference< css::accessibility::XAccessible>
225  GetAccessibleCaption (const css::uno::Reference<css::drawing::XShape>& xShape) override;
227  void SetDrawBroadcaster();
228 
229  sal_Int32 GetCount() const;
230  uno::Reference< XAccessible > Get(const ScAccessibleShapeData* pData) const;
231  uno::Reference< XAccessible > Get(sal_Int32 nIndex) const;
232  uno::Reference< XAccessible > GetAt(const awt::Point& rPoint) const;
233 
234  // gets the index of the shape starting on 0 (without the index of the table)
235  // returns the selected shape
236  bool IsSelected(sal_Int32 nIndex,
237  css::uno::Reference<css::drawing::XShape>& rShape) const;
238 
239  bool SelectionChanged();
240 
241  void Select(sal_Int32 nIndex);
242  void DeselectAll(); // deselect also the table
243  void SelectAll();
244  sal_Int32 GetSelectedCount() const;
245  uno::Reference< XAccessible > GetSelected(sal_Int32 nSelectedChildIndex, bool bTabSelected) const;
246  void Deselect(sal_Int32 nChildIndex);
247 
248  SdrPage* GetDrawPage() const;
249 
251 
252  void VisAreaChanged() const;
253 private:
254  typedef std::vector<ScAccessibleShapeData*> SortedShapes;
255  typedef std::unordered_map<css::uno::Reference< css::drawing::XShape >, ScAccessibleShapeData*> ShapesMap;
256 
257  mutable SortedShapes maZOrderedShapes; // a null pointer represents the sheet in the correct order
258  mutable ShapesMap maShapesMap;
259  mutable bool mbShapesNeedSorting; // set if maZOrderedShapes needs sorting
260 
261  mutable ::accessibility::AccessibleShapeTreeInfo maShapeTreeInfo;
262  mutable css::uno::Reference<css::view::XSelectionSupplier> xSelectionSupplier;
263  mutable size_t mnSdrObjCount;
264  mutable sal_uInt32 mnShapesSelected;
268 
269  void FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const;
270  bool FindSelectedShapesChanges(const css::uno::Reference<css::drawing::XShapes>& xShapes) const;
271 
272  std::optional<ScAddress> GetAnchor(const uno::Reference<drawing::XShape>& xShape) const;
273  uno::Reference<XAccessibleRelationSet> GetRelationSet(const ScAccessibleShapeData* pData) const;
274  void SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const;
275  void AddShape(const uno::Reference<drawing::XShape>& xShape, bool bCommitChange) const;
276  void RemoveShape(const uno::Reference<drawing::XShape>& xShape) const;
277 
278  bool FindShape(const uno::Reference<drawing::XShape>& xShape, SortedShapes::iterator& rItr) const;
279 
280  static sal_Int8 Compare(const ScAccessibleShapeData* pData1,
281  const ScAccessibleShapeData* pData2);
282 };
283 
285  :
286  mbShapesNeedSorting(false),
287  mnShapesSelected(0),
288  mpViewShell(pViewShell),
289  mpAccessibleDocument(pAccessibleDocument),
290  meSplitPos(eSplitPos)
291 {
292  if (mpViewShell)
293  {
294  SfxViewFrame* pViewFrame = mpViewShell->GetViewFrame();
295  if (pViewFrame)
296  {
297  xSelectionSupplier = uno::Reference<view::XSelectionSupplier>(pViewFrame->GetFrame().GetController(), uno::UNO_QUERY);
298  if (xSelectionSupplier.is())
299  {
300  xSelectionSupplier->addSelectionChangeListener(mpAccessibleDocument);
301  uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
302  if (xShapes.is())
303  mnShapesSelected = xShapes->getCount();
304  }
305  }
306  }
307 
308  maZOrderedShapes.push_back(nullptr); // add an element which represents the table
309 
310  GetCount(); // fill list with filtered shapes (no internal shapes)
311 
312  if (mnShapesSelected)
313  {
314  //set flag on every selected shape
315  if (!xSelectionSupplier.is())
316  throw uno::RuntimeException();
317 
318  uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
319  if (xShapes.is())
320  FindSelectedShapesChanges(xShapes);
321  }
322  if (!pViewShell)
323  return;
324 
325  ScViewData& rViewData = pViewShell->GetViewData();
326  SfxBroadcaster* pDrawBC = rViewData.GetDocument()->GetDrawBroadcaster();
327  if (pDrawBC)
328  {
329  StartListening(*pDrawBC);
330 
331  maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(rViewData.GetDocument()->GetDrawLayer()) );
332  maShapeTreeInfo.SetSdrView(rViewData.GetScDrawView());
333  maShapeTreeInfo.SetController(nullptr);
334  maShapeTreeInfo.SetDevice(pViewShell->GetWindowByPos(meSplitPos));
335  maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
336  }
337 }
338 
340 {
341  for (ScAccessibleShapeData* pShapeData : maZOrderedShapes)
342  delete pShapeData;
343  if (mpViewShell)
344  {
346  if (pDrawBC)
347  EndListening(*pDrawBC);
348  }
350  xSelectionSupplier->removeSelectionChangeListener(mpAccessibleDocument);
351 }
352 
354 {
355  if (!mpViewShell)
356  return;
357 
358  ScViewData& rViewData = mpViewShell->GetViewData();
359  SfxBroadcaster* pDrawBC = rViewData.GetDocument()->GetDrawBroadcaster();
360  if (pDrawBC)
361  {
362  StartListening(*pDrawBC, DuplicateHandling::Prevent);
363 
364  maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(rViewData.GetDocument()->GetDrawLayer()) );
365  maShapeTreeInfo.SetSdrView(rViewData.GetScDrawView());
366  maShapeTreeInfo.SetController(nullptr);
368  maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
369  }
370 }
371 
373 {
374  if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
375  return;
376  const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
377 
378  SdrObject* pObj = const_cast<SdrObject*>(pSdrHint->GetObject());
379  if (!(pObj && /*(pObj->GetLayer() != SC_LAYER_INTERN) && */(pObj->getSdrPageFromSdrObject() == GetDrawPage()) &&
380  (pObj->getSdrPageFromSdrObject() == pObj->getParentSdrObjListFromSdrObject())) ) //only do something if the object lies direct on the page
381  return;
382 
383  switch (pSdrHint->GetKind())
384  {
385  case SdrHintKind::ObjectChange : // object changed
386  {
387  uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
388  if (xShape.is())
389  {
390  mbShapesNeedSorting = true; // sort, because the z index or layer could be changed
391  auto it = maShapesMap.find(xShape);
392  if (it != maShapesMap.end())
393  SetAnchor(xShape, it->second);
394  }
395  }
396  break;
397  case SdrHintKind::ObjectInserted : // new drawing object inserted
398  {
399  uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
400  if (xShape.is())
401  AddShape(xShape, true);
402  }
403  break;
404  case SdrHintKind::ObjectRemoved : // Removed drawing object from list
405  {
406  uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
407  if (xShape.is())
408  RemoveShape(xShape);
409  }
410  break;
411  default :
412  {
413  // other events are not interesting
414  }
415  break;
416  }
417 }
418 
420  const css::uno::Reference< css::drawing::XShape >& _rxShape,
421  const long /*_nIndex*/, const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo)
422 {
423  // create the new child
425  ::accessibility::AccessibleShapeInfo ( _rxShape, pCurrentChild->getAccessibleParent(), this ),
426  _rShapeTreeInfo
427  ));
428  if ( pReplacement.is() )
429  pReplacement->Init();
430 
431  bool bResult(false);
432  if (pReplacement.is())
433  {
434  OSL_ENSURE(pCurrentChild->GetXShape().get() == pReplacement->GetXShape().get(), "XShape changes and should be inserted sorted");
435  auto it = maShapesMap.find(pCurrentChild->GetXShape());
436  if (it != maShapesMap.end())
437  {
438  if (it->second->pAccShape.is())
439  {
440  OSL_ENSURE(it->second->pAccShape == pCurrentChild, "wrong child found");
441  AccessibleEventObject aEvent;
442  aEvent.EventId = AccessibleEventId::CHILD;
443  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
444  aEvent.OldValue <<= uno::Reference<XAccessible>(pCurrentChild);
445 
446  mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
447 
448  pCurrentChild->dispose();
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.get());
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.get() );
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  mnSdrObjCount = pDrawPage->GetObjCount();
502  maZOrderedShapes.reserve(mnSdrObjCount + 1); // the table is always in
503  for (size_t i = 0; i < mnSdrObjCount; ++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.get();
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::makeAny(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::makeAny(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::makeAny(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 (pDoc && pDoc->GetDrawLayer())
879  {
880  ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
881  if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab))
882  pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(static_cast<sal_Int16>(nTab)));
883  }
884  }
885  return pDrawPage;
886 }
887 
889 {
890  utl::AccessibleRelationSetHelper* pRelationSet = nullptr;
891  for (const ScAccessibleShapeData* pAccShapeData : maZOrderedShapes)
892  {
893  if (pAccShapeData &&
894  ((!pAccShapeData->xRelationCell && !pAddress) ||
895  (pAccShapeData->xRelationCell && pAddress && (*(pAccShapeData->xRelationCell) == *pAddress))))
896  {
897  if (!pRelationSet)
898  pRelationSet = new utl::AccessibleRelationSetHelper();
899 
900  AccessibleRelation aRelation;
901  aRelation.TargetSet.realloc(1);
902  aRelation.TargetSet[0] = Get(pAccShapeData);
903  aRelation.RelationType = AccessibleRelationType::CONTROLLER_FOR;
904 
905  pRelationSet->AddRelation(aRelation);
906  }
907  }
908  return pRelationSet;
909 }
910 
911 bool ScChildrenShapes::FindSelectedShapesChanges(const uno::Reference<drawing::XShapes>& xShapes) const
912 {
913  bool bResult(false);
914  SortedShapes aShapesList;
915  if (xShapes.is())
916  {
917  mnShapesSelected = xShapes->getCount();
918  for (sal_uInt32 i = 0; i < mnShapesSelected; ++i)
919  {
920  uno::Reference< drawing::XShape > xShape;
921  xShapes->getByIndex(i) >>= xShape;
922  if (xShape.is())
923  {
924  ScAccessibleShapeData* pShapeData = new ScAccessibleShapeData(xShape);
925  aShapesList.push_back(pShapeData);
926  }
927  }
928  }
929  else
930  mnShapesSelected = 0;
931  SdrObject *pFocusedObj = nullptr;
932  if( mnShapesSelected == 1 && aShapesList.size() == 1)
933  {
934  pFocusedObj = GetSdrObjectFromXShape(aShapesList[0]->xShape);
935  }
936  std::sort(aShapesList.begin(), aShapesList.end(), ScShapeDataLess());
937  SortedShapes vecSelectedShapeAdd;
938  SortedShapes vecSelectedShapeRemove;
939  bool bHasSelect=false;
940  SortedShapes::iterator aXShapesItr(aShapesList.begin());
941  SortedShapes::const_iterator aXShapesEndItr(aShapesList.end());
942  SortedShapes::iterator aDataItr(maZOrderedShapes.begin());
943  SortedShapes::const_iterator aDataEndItr(maZOrderedShapes.end());
944  SortedShapes::const_iterator aFocusedItr = aDataEndItr;
945  while(aDataItr != aDataEndItr)
946  {
947  if (*aDataItr) // is it really a shape or only the sheet
948  {
949  sal_Int8 nComp(0);
950  if (aXShapesItr == aXShapesEndItr)
951  nComp = -1; // simulate that the Shape is lower, so the selection state will be removed
952  else
953  nComp = Compare(*aDataItr, *aXShapesItr);
954  if (nComp == 0)
955  {
956  if (!(*aDataItr)->bSelected)
957  {
958  (*aDataItr)->bSelected = true;
959  if ((*aDataItr)->pAccShape.is())
960  {
961  (*aDataItr)->pAccShape->SetState(AccessibleStateType::SELECTED);
962  (*aDataItr)->pAccShape->SetState(AccessibleStateType::FOCUSED);
963  bResult = true;
964  vecSelectedShapeAdd.push_back(*aDataItr);
965  }
966  aFocusedItr = aDataItr;
967  }
968  else
969  {
970  bHasSelect = true;
971  }
972  ++aDataItr;
973  ++aXShapesItr;
974  }
975  else if (nComp < 0)
976  {
977  if ((*aDataItr)->bSelected)
978  {
979  (*aDataItr)->bSelected = false;
980  if ((*aDataItr)->pAccShape.is())
981  {
982  (*aDataItr)->pAccShape->ResetState(AccessibleStateType::SELECTED);
983  (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED);
984  bResult = true;
985  vecSelectedShapeRemove.push_back(*aDataItr);
986  }
987  }
988  ++aDataItr;
989  }
990  else
991  {
992  OSL_FAIL("here is a selected shape which is not in the childlist");
993  ++aXShapesItr;
995  }
996  }
997  else
998  ++aDataItr;
999  }
1000  bool bWinFocus=false;
1001  if (mpViewShell)
1002  {
1004  if (pWin)
1005  {
1006  bWinFocus = pWin->HasFocus();
1007  }
1008  }
1009  const SdrMarkList* pMarkList = nullptr;
1010  SdrObject* pMarkedObj = nullptr;
1011  SdrObject* pUpObj = 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  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.get());
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.get());
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  SvxShape* pShapeImp = comphelper::getUnoTunnelImplementation<SvxShape>(xShape);
1125  uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
1126  if (pShapeImp && xShapeProp.is())
1127  {
1128  if (SdrObject *pSdrObj = pShapeImp->GetSdrObject())
1129  {
1130  if (ScDrawObjData *pAnchor = ScDrawLayer::GetObjData(pSdrObj))
1131  return std::optional<ScAddress>(pAnchor->maStart);
1132  }
1133  }
1134  }
1135 
1136  return std::optional<ScAddress>();
1137 }
1138 
1139 uno::Reference<XAccessibleRelationSet> ScChildrenShapes::GetRelationSet(const ScAccessibleShapeData* pData) const
1140 {
1142 
1143  if (pData && mpAccessibleDocument)
1144  {
1145  uno::Reference<XAccessible> xAccessible = mpAccessibleDocument->GetAccessibleSpreadsheet(); // should be the current table
1146  if (pData->xRelationCell && xAccessible.is())
1147  {
1148  sal_Int32 nRow = pData->xRelationCell->Row();
1149  sal_Int32 nColumn = pData->xRelationCell->Col();
1150  bool bPositionUnset = nRow == -1 && nColumn == -1;
1151  if (!bPositionUnset)
1152  {
1153  uno::Reference<XAccessibleTable> xAccTable(xAccessible->getAccessibleContext(), uno::UNO_QUERY);
1154  if (xAccTable.is())
1155  xAccessible = xAccTable->getAccessibleCellAt(nRow, nColumn);
1156  }
1157  }
1158  AccessibleRelation aRelation;
1159  aRelation.TargetSet.realloc(1);
1160  aRelation.TargetSet[0] = xAccessible;
1161  aRelation.RelationType = AccessibleRelationType::CONTROLLED_BY;
1162  pRelationSet->AddRelation(aRelation);
1163  }
1164 
1165  return pRelationSet;
1166 }
1167 
1168 void ScChildrenShapes::SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const
1169 {
1170  if (pData)
1171  {
1172  std::optional<ScAddress> xAddress = GetAnchor(xShape);
1173  if ((xAddress && pData->xRelationCell && (*xAddress != *(pData->xRelationCell))) ||
1174  (!xAddress && pData->xRelationCell) || (xAddress && !pData->xRelationCell))
1175  {
1176  pData->xRelationCell = xAddress;
1177  if (pData->pAccShape.is())
1178  pData->pAccShape->SetRelationSet(GetRelationSet(pData));
1179  }
1180  }
1181 }
1182 
1183 void ScChildrenShapes::AddShape(const uno::Reference<drawing::XShape>& xShape, bool bCommitChange) const
1184 {
1185  assert( maShapesMap.find(xShape) == maShapesMap.end());
1186 
1187  ScAccessibleShapeData* pShape = new ScAccessibleShapeData(xShape);
1188  maZOrderedShapes.push_back(pShape);
1189  mbShapesNeedSorting = true;
1190  maShapesMap[xShape] = pShape;
1191  SetAnchor(xShape, pShape);
1192 
1193  uno::Reference< beans::XPropertySet > xShapeProp(xShape, uno::UNO_QUERY);
1194  if (xShapeProp.is())
1195  {
1196  uno::Any aPropAny = xShapeProp->getPropertyValue("LayerID");
1197  sal_Int16 nLayerID = 0;
1198  if( aPropAny >>= nLayerID )
1199  {
1200  if( (SdrLayerID(nLayerID) == SC_LAYER_INTERN) || (SdrLayerID(nLayerID) == SC_LAYER_HIDDEN) )
1201  pShape->bSelectable = false;
1202  else
1203  pShape->bSelectable = true;
1204  }
1205  }
1206 
1207  if (!xSelectionSupplier.is())
1208  throw uno::RuntimeException();
1209 
1210  uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
1211  uno::Reference<container::XEnumerationAccess> xEnumAcc(xShapes, uno::UNO_QUERY);
1212  if (xEnumAcc.is())
1213  {
1214  uno::Reference<container::XEnumeration> xEnum = xEnumAcc->createEnumeration();
1215  if (xEnum.is())
1216  {
1217  uno::Reference<drawing::XShape> xSelectedShape;
1218  bool bFound(false);
1219  while (!bFound && xEnum->hasMoreElements())
1220  {
1221  xEnum->nextElement() >>= xSelectedShape;
1222  if (xShape.is() && (xShape.get() == xSelectedShape.get()))
1223  {
1224  pShape->bSelected = true;
1225  bFound = true;
1226  }
1227  }
1228  }
1229  }
1230  if (mpAccessibleDocument && bCommitChange)
1231  {
1232  AccessibleEventObject aEvent;
1233  aEvent.EventId = AccessibleEventId::CHILD;
1234  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1235  aEvent.NewValue <<= Get(pShape);
1236 
1237  mpAccessibleDocument->CommitChange(aEvent); // new child - event
1238  }
1239 }
1240 
1241 void ScChildrenShapes::RemoveShape(const uno::Reference<drawing::XShape>& xShape) const
1242 {
1243  if (mbShapesNeedSorting)
1244  {
1245  std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
1246  mbShapesNeedSorting = false;
1247  }
1248  SortedShapes::iterator aItr;
1249  if (FindShape(xShape, aItr))
1250  {
1252  {
1253  uno::Reference<XAccessible> xOldAccessible (Get(*aItr));
1254 
1255  delete *aItr;
1256  maShapesMap.erase((*aItr)->xShape);
1257  maZOrderedShapes.erase(aItr);
1258 
1259  AccessibleEventObject aEvent;
1260  aEvent.EventId = AccessibleEventId::CHILD;
1261  aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1262  aEvent.OldValue <<= xOldAccessible;
1263 
1264  mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
1265  }
1266  else
1267  {
1268  delete *aItr;
1269  maShapesMap.erase((*aItr)->xShape);
1270  maZOrderedShapes.erase(aItr);
1271  }
1272  }
1273  else
1274  {
1275  OSL_FAIL("shape was not in internal list");
1276  }
1277 }
1278 
1279 bool ScChildrenShapes::FindShape(const uno::Reference<drawing::XShape>& xShape, ScChildrenShapes::SortedShapes::iterator& rItr) const
1280 {
1281  if (mbShapesNeedSorting)
1282  {
1283  std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
1284  mbShapesNeedSorting = false;
1285  }
1286  bool bResult(false);
1287  ScAccessibleShapeData aShape(xShape);
1288  rItr = std::lower_bound(maZOrderedShapes.begin(), maZOrderedShapes.end(), &aShape, ScShapeDataLess());
1289  if ((rItr != maZOrderedShapes.end()) && (*rItr != nullptr) && ((*rItr)->xShape.get() == xShape.get()))
1290  bResult = true; // if the shape is found
1291 
1292 #if OSL_DEBUG_LEVEL > 0 // test whether it finds truly the correct shape (perhaps it is not really sorted)
1293  SortedShapes::iterator aDebugItr = std::find_if(maZOrderedShapes.begin(), maZOrderedShapes.end(),
1294  [&xShape](const ScAccessibleShapeData* pShape) { return pShape && (pShape->xShape.get() == xShape.get()); });
1295  bool bResult2 = (aDebugItr != maZOrderedShapes.end());
1296  OSL_ENSURE((bResult == bResult2) && ((bResult && (rItr == aDebugItr)) || !bResult), "wrong Shape found");
1297 #endif
1298  return bResult;
1299 }
1300 
1301 sal_Int8 ScChildrenShapes::Compare(const ScAccessibleShapeData* pData1,
1302  const ScAccessibleShapeData* pData2)
1303 {
1304  ScShapeDataLess aLess;
1305 
1306  bool bResult1(aLess(pData1, pData2));
1307  bool bResult2(aLess(pData2, pData1));
1308 
1309  sal_Int8 nResult(0);
1310  if (!bResult1 && bResult2)
1311  nResult = 1;
1312  else if (bResult1 && !bResult2)
1313  nResult = -1;
1314 
1315  return nResult;
1316 }
1317 
1319 {
1320  for (const ScAccessibleShapeData* pAccShapeData: maZOrderedShapes)
1321  if (pAccShapeData && pAccShapeData->pAccShape.is())
1322  pAccShapeData->pAccShape->ViewForwarderChanged();
1323 }
1324 
1326  const uno::Reference<XAccessible>& rxParent,
1327  ScTabViewShell* pViewShell,
1328  ScSplitPos eSplitPos)
1329  : ScAccessibleDocumentBase(rxParent),
1330  mpViewShell(pViewShell),
1331  meSplitPos(eSplitPos),
1332  mpTempAccEdit(nullptr),
1333  mbCompleteSheetSelected(false)
1334 {
1336 }
1337 
1339 {
1340  if (!mpViewShell)
1341  return;
1342 
1345  if( pWin )
1346  {
1347  pWin->AddChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1348  sal_uInt16 nCount = pWin->GetChildCount();
1349  for( sal_uInt16 i=0; i < nCount; ++i )
1350  {
1351  vcl::Window *pChildWin = pWin->GetChild( i );
1352  if( pChildWin &&
1353  AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1354  AddChild( pChildWin->GetAccessible(), false );
1355  }
1356  }
1357  ScViewData& rViewData = mpViewShell->GetViewData();
1358  if (rViewData.HasEditView(meSplitPos))
1359  {
1360  uno::Reference<XAccessible> xAcc = new ScAccessibleEditObject(this, rViewData.GetEditView(meSplitPos),
1363  AddChild(xAcc, false);
1364  }
1365 }
1366 
1368 {
1369  if(!mpChildrenShapes)
1371 }
1372 
1374 {
1375  if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
1376  {
1377  // increment refcount to prevent double call off dtor
1378  osl_atomic_increment( &m_refCount );
1379  dispose();
1380  }
1381 }
1382 
1384 {
1385  SolarMutexGuard aGuard;
1387  if (mpViewShell)
1388  {
1390  if( pWin )
1391  pWin->RemoveChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1392 
1394  mpViewShell = nullptr;
1395  }
1396  mpChildrenShapes.reset();
1397 
1399 }
1400 
1401 void SAL_CALL ScAccessibleDocument::disposing( const lang::EventObject& /* Source */ )
1402 {
1403  disposing();
1404 }
1405 
1406  //===== SfxListener =====================================================
1407 
1408 IMPL_LINK( ScAccessibleDocument, WindowChildEventListener, VclWindowEvent&, rEvent, void )
1409 {
1410  OSL_ENSURE( rEvent.GetWindow(), "Window???" );
1411  switch ( rEvent.GetId() )
1412  {
1413  case VclEventId::WindowShow: // send create on show for direct accessible children
1414  {
1415  vcl::Window* pChildWin = static_cast < vcl::Window * >( rEvent.GetData() );
1416  if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1417  {
1418  AddChild( pChildWin->GetAccessible(), true );
1419  }
1420  }
1421  break;
1422  case VclEventId::WindowHide: // send destroy on hide for direct accessible children
1423  {
1424  vcl::Window* pChildWin = static_cast < vcl::Window * >( rEvent.GetData() );
1425  if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1426  {
1427  RemoveChild( pChildWin->GetAccessible(), true );
1428  }
1429  }
1430  break;
1431  default: break;
1432  }
1433 }
1434 
1436 {
1437  if (dynamic_cast<const ScAccGridWinFocusLostHint*>(&rHint) )
1438  {
1439  const ScAccGridWinFocusLostHint* pFocusLostHint = static_cast<const ScAccGridWinFocusLostHint *>(&rHint);
1440  if (pFocusLostHint->GetOldGridWin() == meSplitPos)
1441  {
1442  if (mxTempAcc.is() && mpTempAccEdit)
1444  else if (mpAccessibleSpreadsheet.is())
1445  mpAccessibleSpreadsheet->LostFocus();
1446  else
1447  CommitFocusLost();
1448  }
1449  }
1450  else if (dynamic_cast<const ScAccGridWinFocusGotHint*>(&rHint) )
1451  {
1452  const ScAccGridWinFocusGotHint* pFocusGotHint = static_cast<const ScAccGridWinFocusGotHint*>(&rHint);
1453  if (pFocusGotHint->GetNewGridWin() == meSplitPos)
1454  {
1455  uno::Reference<XAccessible> xAccessible;
1456  if (mpChildrenShapes)
1457  {
1458  bool bTabMarked(IsTableSelected());
1459  xAccessible = mpChildrenShapes->GetSelected(0, bTabMarked);
1460  }
1461  if( xAccessible.is() )
1462  {
1463  uno::Any aNewValue;
1464  aNewValue<<=AccessibleStateType::FOCUSED;
1465  static_cast< ::accessibility::AccessibleShape* >(xAccessible.get())->
1466  CommitChange(AccessibleEventId::STATE_CHANGED,
1467  aNewValue,
1468  uno::Any() );
1469  }
1470  else
1471  {
1472  if (mxTempAcc.is() && mpTempAccEdit)
1474  else if (mpAccessibleSpreadsheet.is())
1475  mpAccessibleSpreadsheet->GotFocus();
1476  else
1478  }
1479  }
1480  }
1481  else
1482  {
1483  // only notify if child exist, otherwise it is not necessary
1484  if ((rHint.GetId() == SfxHintId::ScAccTableChanged) &&
1486  {
1488 
1489  // Shapes / form controls after reload not accessible, rebuild the
1490  // mpChildrenShapes variable.
1492 
1493  AccessibleEventObject aEvent;
1494  aEvent.EventId = AccessibleEventId::INVALIDATE_ALL_CHILDREN;
1495  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1496  CommitChange(aEvent); // all children changed
1497 
1498  if (mpAccessibleSpreadsheet.is())
1499  mpAccessibleSpreadsheet->FireFirstCellFocus();
1500  }
1501  else if (rHint.GetId() == SfxHintId::ScAccMakeDrawLayer)
1502  {
1503  if (mpChildrenShapes)
1504  mpChildrenShapes->SetDrawBroadcaster();
1505  }
1506  else if (rHint.GetId() == SfxHintId::ScAccEnterEditMode) // this event comes only on creating edit field of a cell
1507  {
1509  {
1510  ScViewData& rViewData = mpViewShell->GetViewData();
1511  const EditEngine* pEditEng = rViewData.GetEditView(meSplitPos)->GetEditEngine();
1512  if (pEditEng && pEditEng->GetUpdateMode())
1513  {
1516  ScResId(STR_ACC_EDITLINE_DESCR), ScAccessibleEditObject::CellInEditMode);
1517  uno::Reference<XAccessible> xAcc = mpTempAccEdit;
1518 
1519  AddChild(xAcc, true);
1520 
1521  if (mpAccessibleSpreadsheet.is())
1522  mpAccessibleSpreadsheet->LostFocus();
1523  else
1524  CommitFocusLost();
1525 
1527  }
1528  }
1529  }
1530  else if (rHint.GetId() == SfxHintId::ScAccLeaveEditMode)
1531  {
1532  if (mxTempAcc.is())
1533  {
1534  if (mpTempAccEdit)
1535  {
1537  }
1538  RemoveChild(mxTempAcc, true);
1539  if (mpTempAccEdit)
1540  {
1541  // tdf#125982 a11y use-after-free of editengine by
1542  // ScAccessibleEditObjectTextData living past the
1543  // the editengine of the editview passed in above
1544  // in ScAccEnterEditMode
1545  mpTempAccEdit->dispose();
1546  mpTempAccEdit = nullptr;
1547  }
1549  mpAccessibleSpreadsheet->GotFocus();
1550  else if( mpViewShell && mpViewShell->IsActive())
1552  }
1553  }
1554  else if ((rHint.GetId() == SfxHintId::ScAccVisAreaChanged) || (rHint.GetId() == SfxHintId::ScAccWindowResized))
1555  {
1556  tools::Rectangle aOldVisArea(maVisArea);
1558 
1559  if (maVisArea != aOldVisArea)
1560  {
1561  if (maVisArea.GetSize() != aOldVisArea.GetSize())
1562  {
1563  AccessibleEventObject aEvent;
1564  aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
1565  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1566 
1567  CommitChange(aEvent);
1568 
1569  if (mpAccessibleSpreadsheet.is())
1570  mpAccessibleSpreadsheet->BoundingBoxChanged();
1572  mpAccessibleSpreadsheet->FireFirstCellFocus();
1573  }
1574  else if (mpAccessibleSpreadsheet.is())
1575  {
1576  mpAccessibleSpreadsheet->VisAreaChanged();
1577  }
1578  if (mpChildrenShapes)
1579  mpChildrenShapes->VisAreaChanged();
1580  }
1581  }
1582  }
1583 
1585 }
1586 
1587 void SAL_CALL ScAccessibleDocument::selectionChanged( const lang::EventObject& /* aEvent */ )
1588 {
1589  bool bSelectionChanged(false);
1590  if (mpAccessibleSpreadsheet.is())
1591  {
1592  bool bOldSelected(mbCompleteSheetSelected);
1594  if (bOldSelected != mbCompleteSheetSelected)
1595  {
1596  mpAccessibleSpreadsheet->CompleteSelectionChanged(mbCompleteSheetSelected);
1597  bSelectionChanged = true;
1598  }
1599  }
1600 
1601  if (mpChildrenShapes && mpChildrenShapes->SelectionChanged())
1602  bSelectionChanged = true;
1603 
1604  if (bSelectionChanged)
1605  {
1606  AccessibleEventObject aEvent;
1607  aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1608  aEvent.Source = uno::Reference< XAccessibleContext >(this);
1609 
1610  CommitChange(aEvent);
1611  }
1612 }
1613 
1614  //===== XInterface =====================================================
1615 
1617 {
1619  return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType);
1620 }
1621 
1623  throw ()
1624 {
1626 }
1627 
1629  throw ()
1630 {
1632 }
1633 
1634  //===== XAccessibleComponent ============================================
1635 
1636 uno::Reference< XAccessible > SAL_CALL ScAccessibleDocument::getAccessibleAtPoint(
1637  const awt::Point& rPoint )
1638 {
1639  uno::Reference<XAccessible> xAccessible;
1640  if (containsPoint(rPoint))
1641  {
1642  SolarMutexGuard aGuard;
1643  IsObjectValid();
1644  if (mpChildrenShapes)
1645  xAccessible = mpChildrenShapes->GetAt(rPoint);
1646  if(!xAccessible.is())
1647  {
1648  if (mxTempAcc.is())
1649  {
1650  uno::Reference< XAccessibleContext > xCont(mxTempAcc->getAccessibleContext());
1651  uno::Reference< XAccessibleComponent > xComp(xCont, uno::UNO_QUERY);
1652  if (xComp.is())
1653  {
1654  tools::Rectangle aBound(VCLRectangle(xComp->getBounds()));
1655  if (aBound.IsInside(VCLPoint(rPoint)))
1656  xAccessible = mxTempAcc;
1657  }
1658  }
1659  if (!xAccessible.is())
1660  xAccessible = GetAccessibleSpreadsheet();
1661  }
1662  }
1663  return xAccessible;
1664 }
1665 
1667 {
1668  SolarMutexGuard aGuard;
1669  IsObjectValid();
1670  if (!getAccessibleParent().is())
1671  return;
1672 
1673  uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1674  if (xAccessibleComponent.is())
1675  {
1676  xAccessibleComponent->grabFocus();
1677  // grab only focus if it does not have the focus and it is not hidden
1678  if (mpViewShell &&
1681  {
1683  }
1684  }
1685 }
1686 
1687  //===== XAccessibleContext ==============================================
1688 
1690 sal_Int32 SAL_CALL
1692 {
1693  SolarMutexGuard aGuard;
1694  IsObjectValid();
1695  sal_Int32 nCount(1);
1696  if (mpChildrenShapes)
1697  nCount = mpChildrenShapes->GetCount(); // returns the count of the shapes inclusive the table
1698 
1699  if (mxTempAcc.is())
1700  ++nCount;
1701 
1702  return nCount;
1703 }
1704 
1706 uno::Reference<XAccessible> SAL_CALL
1708 {
1709  SolarMutexGuard aGuard;
1710  IsObjectValid();
1711  uno::Reference<XAccessible> xAccessible;
1712  if (nIndex >= 0)
1713  {
1714  sal_Int32 nCount(1);
1715  if (mpChildrenShapes)
1716  {
1717  xAccessible = mpChildrenShapes->Get(nIndex); // returns NULL if it is the table or out of range
1718  nCount = mpChildrenShapes->GetCount(); //there is always a table
1719  }
1720  if (!xAccessible.is())
1721  {
1722  if (nIndex < nCount)
1723  xAccessible = GetAccessibleSpreadsheet();
1724  else if (nIndex == nCount && mxTempAcc.is())
1725  xAccessible = mxTempAcc;
1726  }
1727  }
1728 
1729  if (!xAccessible.is())
1730  throw lang::IndexOutOfBoundsException();
1731 
1732  return xAccessible;
1733 }
1734 
1736 uno::Reference<XAccessibleStateSet> SAL_CALL
1738 {
1739  SolarMutexGuard aGuard;
1740  uno::Reference<XAccessibleStateSet> xParentStates;
1741  if (getAccessibleParent().is())
1742  {
1743  uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1744  xParentStates = xParentContext->getAccessibleStateSet();
1745  }
1747  if (IsDefunc(xParentStates))
1748  pStateSet->AddState(AccessibleStateType::DEFUNC);
1749  else
1750  {
1751  pStateSet->AddState(AccessibleStateType::EDITABLE);
1752  pStateSet->AddState(AccessibleStateType::ENABLED);
1753  pStateSet->AddState(AccessibleStateType::OPAQUE);
1754  if (isShowing())
1755  pStateSet->AddState(AccessibleStateType::SHOWING);
1756  if (isVisible())
1757  pStateSet->AddState(AccessibleStateType::VISIBLE);
1758  }
1759  return pStateSet;
1760 }
1761 
1762 OUString SAL_CALL
1764 {
1765  SolarMutexGuard g;
1766 
1767  OUString aName = ScResId(STR_ACC_DOC_SPREADSHEET);
1768  ScDocument* pScDoc = GetDocument();
1769  if (!pScDoc)
1770  return aName;
1771 
1772  SfxObjectShell* pObjSh = pScDoc->GetDocumentShell();
1773  if (!pObjSh)
1774  return aName;
1775 
1776  OUString aFileName;
1777  SfxMedium* pMed = pObjSh->GetMedium();
1778  if (pMed)
1779  aFileName = pMed->GetName();
1780 
1781  if (aFileName.isEmpty())
1782  aFileName = pObjSh->GetTitle(SFX_TITLE_APINAME);
1783 
1784  if (!aFileName.isEmpty())
1785  {
1786  OUString aReadOnly;
1787  if (pObjSh->IsReadOnly())
1788  aReadOnly = ScResId(STR_ACC_DOC_SPREADSHEET_READONLY);
1789 
1790  aName = aFileName + aReadOnly + " - " + aName;
1791  }
1792  return aName;
1793 }
1794 
1796 
1797 void SAL_CALL
1799 {
1800  SolarMutexGuard aGuard;
1801  IsObjectValid();
1802 
1803  if (!(mpChildrenShapes && mpViewShell))
1804  return;
1805 
1806  sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table
1807  if (mxTempAcc.is())
1808  ++nCount;
1809  if (nChildIndex < 0 || nChildIndex >= nCount)
1810  throw lang::IndexOutOfBoundsException();
1811 
1812  uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1813  if (xAccessible.is())
1814  {
1815  bool bWasTableSelected(IsTableSelected());
1816  mpChildrenShapes->Select(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is too high
1817  if (bWasTableSelected)
1819  }
1820  else
1821  {
1823  }
1824 }
1825 
1826 sal_Bool SAL_CALL
1828 {
1829  SolarMutexGuard aGuard;
1830  IsObjectValid();
1831  bool bResult(false);
1832 
1833  if (mpChildrenShapes)
1834  {
1835  sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table
1836  if (mxTempAcc.is())
1837  ++nCount;
1838  if (nChildIndex < 0 || nChildIndex >= nCount)
1839  throw lang::IndexOutOfBoundsException();
1840 
1841  uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1842  if (xAccessible.is())
1843  {
1844  uno::Reference<drawing::XShape> xShape;
1845  bResult = mpChildrenShapes->IsSelected(nChildIndex, xShape); // throws no lang::IndexOutOfBoundsException if Index is too high
1846  }
1847  else
1848  {
1849  if (mxTempAcc.is() && nChildIndex == nCount)
1850  bResult = true;
1851  else
1852  bResult = IsTableSelected();
1853  }
1854  }
1855  return bResult;
1856 }
1857 
1858 void SAL_CALL
1860 {
1861  SolarMutexGuard aGuard;
1862  IsObjectValid();
1863 
1864  if (mpChildrenShapes)
1865  mpChildrenShapes->DeselectAll(); //deselects all (also the table)
1866 }
1867 
1868 void SAL_CALL
1870 {
1871  SolarMutexGuard aGuard;
1872  IsObjectValid();
1873 
1874  if (mpChildrenShapes)
1875  mpChildrenShapes->SelectAll();
1876 
1877  // select table after shapes, because while selecting shapes the table will be deselected
1878  if (mpViewShell)
1879  {
1881  }
1882 }
1883 
1884 sal_Int32 SAL_CALL
1886 {
1887  SolarMutexGuard aGuard;
1888  IsObjectValid();
1889  sal_Int32 nCount(0);
1890 
1891  if (mpChildrenShapes)
1892  nCount = mpChildrenShapes->GetSelectedCount();
1893 
1894  if (IsTableSelected())
1895  ++nCount;
1896 
1897  if (mxTempAcc.is())
1898  ++nCount;
1899 
1900  return nCount;
1901 }
1902 
1903 uno::Reference<XAccessible > SAL_CALL
1904  ScAccessibleDocument::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
1905 {
1906  SolarMutexGuard aGuard;
1907  IsObjectValid();
1908  uno::Reference<XAccessible> xAccessible;
1909  if (mpChildrenShapes)
1910  {
1911  sal_Int32 nCount(getSelectedAccessibleChildCount()); //all shapes and the table
1912  if (nSelectedChildIndex < 0 || nSelectedChildIndex >= nCount)
1913  throw lang::IndexOutOfBoundsException();
1914 
1915  bool bTabMarked(IsTableSelected());
1916 
1917  if (mpChildrenShapes)
1918  xAccessible = mpChildrenShapes->GetSelected(nSelectedChildIndex, bTabMarked); // throws no lang::IndexOutOfBoundsException if Index is too high
1919  if (mxTempAcc.is() && nSelectedChildIndex == nCount - 1)
1920  xAccessible = mxTempAcc;
1921  else if (bTabMarked)
1922  xAccessible = GetAccessibleSpreadsheet();
1923  }
1924 
1925  OSL_ENSURE(xAccessible.is(), "here should always be an accessible object or an exception thrown");
1926 
1927  return xAccessible;
1928 }
1929 
1930 void SAL_CALL
1932 {
1933  SolarMutexGuard aGuard;
1934  IsObjectValid();
1935 
1936  if (!(mpChildrenShapes && mpViewShell))
1937  return;
1938 
1939  sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table
1940  if (mxTempAcc.is())
1941  ++nCount;
1942  if (nChildIndex < 0 || nChildIndex >= nCount)
1943  throw lang::IndexOutOfBoundsException();
1944 
1945  bool bTabMarked(IsTableSelected());
1946 
1947  uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1948  if (xAccessible.is())
1949  {
1950  mpChildrenShapes->Deselect(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is too high
1951  if (bTabMarked)
1952  mpViewShell->SelectAll(); // select the table again
1953  }
1954  else if (bTabMarked)
1955  mpViewShell->Unmark();
1956 }
1957 
1958  //===== XServiceInfo ====================================================
1959 
1960 OUString SAL_CALL
1962 {
1963  return "ScAccessibleDocument";
1964 }
1965 
1966 uno::Sequence< OUString> SAL_CALL
1968 {
1969  uno::Sequence< OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
1970  sal_Int32 nOldSize(aSequence.getLength());
1971  aSequence.realloc(nOldSize + 1);
1972 
1973  aSequence[nOldSize] = "com.sun.star.AccessibleSpreadsheetDocumentView";
1974 
1975  return aSequence;
1976 }
1977 
1978 //===== XTypeProvider =======================================================
1979 
1980 uno::Sequence< uno::Type > SAL_CALL ScAccessibleDocument::getTypes()
1981 {
1983 }
1984 
1985 uno::Sequence<sal_Int8> SAL_CALL
1987 {
1988  return css::uno::Sequence<sal_Int8>();
1989 }
1990 
1992 
1994 {
1995  tools::Rectangle aVisRect(GetBoundingBox());
1996 
1997  if (mpViewShell)
1998  {
1999  Point aPoint(mpViewShell->GetViewData().GetPixPos(meSplitPos)); // returns a negative Point
2000  aPoint.setX(-aPoint.getX());
2001  aPoint.setY(-aPoint.getY());
2002  aVisRect.SetPos(aPoint);
2003 
2005  if (pWin)
2006  aVisRect = pWin->PixelToLogic(aVisRect, pWin->GetDrawMapMode());
2007  }
2008 
2009  return aVisRect;
2010 }
2011 
2013 {
2014  SolarMutexGuard aGuard;
2015  IsObjectValid();
2016  return maVisArea;
2017 }
2018 
2019 Point ScAccessibleDocument::LogicToPixel (const Point& rPoint) const
2020 {
2021  SolarMutexGuard aGuard;
2022  IsObjectValid();
2023  Point aPoint;
2025  if (pWin)
2026  {
2027  aPoint = pWin->LogicToPixel(rPoint, pWin->GetDrawMapMode());
2028  aPoint += pWin->GetWindowExtentsRelative(nullptr).TopLeft();
2029  }
2030  return aPoint;
2031 }
2032 
2034 {
2035  SolarMutexGuard aGuard;
2036  IsObjectValid();
2037  Size aSize;
2039  if (pWin)
2040  aSize = pWin->LogicToPixel(rSize, pWin->GetDrawMapMode());
2041  return aSize;
2042 }
2043 
2044  //===== internal ========================================================
2045 
2047 {
2048  utl::AccessibleRelationSetHelper* pRelationSet = nullptr;
2049  if (mpChildrenShapes)
2050  pRelationSet = mpChildrenShapes->GetRelationSet(pAddress);
2051  return pRelationSet;
2052 }
2053 
2054 OUString
2056 {
2057  return STR_ACC_DOC_DESCR;
2058 }
2059 
2060 OUString
2062 {
2063  SolarMutexGuard aGuard;
2064  IsObjectValid();
2065  OUString sName = ScResId(STR_ACC_DOC_NAME);
2066  sal_Int32 nNumber(sal_Int32(meSplitPos) + 1);
2067  sName += OUString::number(nNumber);
2068  return sName;
2069 }
2070 
2072 {
2073  tools::Rectangle aRect;
2074  if (mpViewShell)
2075  {
2077  if (pWindow)
2078  aRect = pWindow->GetWindowExtentsRelative(nullptr);
2079  }
2080  return aRect;
2081 }
2082 
2084 {
2085  tools::Rectangle aRect;
2086  if (mpViewShell)
2087  {
2089  if (pWindow)
2090  aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
2091  }
2092  return aRect;
2093 }
2094 
2096 {
2097  SCTAB nVisibleTable(0);
2098  if (mpViewShell)
2099  nVisibleTable = mpViewShell->GetViewData().GetTabNo();
2100  return nVisibleTable;
2101 }
2102 
2103 uno::Reference < XAccessible >
2105 {
2106  if (!mpAccessibleSpreadsheet.is() && mpViewShell)
2107  {
2109  mpAccessibleSpreadsheet->Init();
2111  }
2112  return mpAccessibleSpreadsheet.get();
2113 }
2114 
2116 {
2117  if (mpAccessibleSpreadsheet.is())
2118  {
2119  mpAccessibleSpreadsheet->dispose();
2120  mpAccessibleSpreadsheet.clear();
2121  }
2122 }
2123 
2125 {
2126  bool bResult (false);
2127  if(mpViewShell)
2128  {
2129  SCTAB nTab(getVisibleTable());
2130  //#103800#; use a copy of MarkData
2132  aMarkData.MarkToMulti();
2133  ScDocument* pDoc = GetDocument();
2134  if (aMarkData.IsAllMarked( ScRange( 0, 0, nTab, pDoc->MaxCol(), pDoc->MaxRow(), nTab)))
2135  bResult = true;
2136  }
2137  return bResult;
2138 }
2139 
2141  const uno::Reference<XAccessibleStateSet>& rxParentStates)
2142 {
2143  return ScAccessibleContextBase::IsDefunc() || (mpViewShell == nullptr) || !getAccessibleParent().is() ||
2144  (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
2145 }
2146 
2147 void ScAccessibleDocument::AddChild(const uno::Reference<XAccessible>& xAcc, bool bFireEvent)
2148 {
2149  OSL_ENSURE(!mxTempAcc.is(), "this object should be removed before");
2150  if (xAcc.is())
2151  {
2152  mxTempAcc = xAcc;
2153  if( bFireEvent )
2154  {
2155  AccessibleEventObject aEvent;
2156  aEvent.Source = uno::Reference<XAccessibleContext>(this);
2157  aEvent.EventId = AccessibleEventId::CHILD;
2158  aEvent.NewValue <<= mxTempAcc;
2159  CommitChange( aEvent );
2160  }
2161  }
2162 }
2163 
2164 void ScAccessibleDocument::RemoveChild(const uno::Reference<XAccessible>& xAcc, bool bFireEvent)
2165 {
2166  OSL_ENSURE(mxTempAcc.is(), "this object should be added before");
2167  if (!xAcc.is())
2168  return;
2169 
2170  OSL_ENSURE(xAcc.get() == mxTempAcc.get(), "only the same object should be removed");
2171  if( bFireEvent )
2172  {
2173  AccessibleEventObject aEvent;
2174  aEvent.Source = uno::Reference<XAccessibleContext>(this);
2175  aEvent.EventId = AccessibleEventId::CHILD;
2176  aEvent.OldValue <<= mxTempAcc;
2177  CommitChange( aEvent );
2178  }
2179  mxTempAcc = nullptr;
2180 }
2181 
2183 {
2184  OUString sName(ScResId(STR_ACC_CELL_NAME));
2185  if (mpViewShell)
2186  {
2187  // Document not needed, because only the cell address, but not the tablename is needed
2188  OUString sAddress(mpViewShell->GetViewData().GetCurPos().Format(ScRefFlags::VALID));
2189  sName = sName.replaceFirst("%1", sAddress);
2190  }
2191  return sName;
2192 }
2193 
2195 {
2196  return OUString();
2197 }
2198 
2200 {
2201  return mpViewShell ? mpViewShell->GetViewData().GetDocument() : nullptr;
2202 }
2203 
2205 {
2207 }
2208 
2210 {
2211  SolarMutexGuard g;
2212 
2213  uno::Any anyAtrribute;
2214 
2215  sal_uInt16 sheetIndex;
2216  OUString sSheetName;
2217  sheetIndex = getVisibleTable();
2218  if(GetDocument()==nullptr)
2219  return anyAtrribute;
2220  GetDocument()->GetName(sheetIndex,sSheetName);
2221  OUString sValue = "page-name:" + sSheetName +
2222  ";page-number:" + OUString::number(sheetIndex+1) +
2223  ";total-pages:" + OUString::number(GetDocument()->GetTableCount()) + ";";
2224  anyAtrribute <<= sValue;
2225  return anyAtrribute;
2226 }
2227 
2229 {
2230  return sal_Int32(COL_BLACK);
2231 }
2232 
2234 {
2235  SolarMutexGuard aGuard;
2236  IsObjectValid();
2237  return sal_Int32(SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor);
2238 }
2239 
2240 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScMarkData & GetMarkData()
Definition: viewdata.cxx:3053
Point TopLeft() const
SfxViewFrame * GetViewFrame() const
void SetPos(const Point &rPoint)
uno::Reference< XAccessible > GetAt(const awt::Point &rPoint) const
void SelectAll(bool bContinue=false)
Definition: tabview2.cxx:1063
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2111
sal_Int32 GetCount() const
void RemoveShape(const uno::Reference< drawing::XShape > &xShape) const
virtual Point LogicToPixel(const Point &rPoint) const override
Transform the specified point from internal coordinates to an absolute screen position.
bool hasValue()
sal_Int32 nIndex
IMPL_LINK(ScAccessibleDocument, WindowChildEventListener, VclWindowEvent &, rEvent, void)
SdrHintKind GetKind() const
size_t GetMarkCount() const
virtual OUString createAccessibleDescription() override
Return this object's description.
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:43
virtual void SAL_CALL selectionChanged(const css::lang::EventObject &aEvent) override
===== XSelectionListener =============================================
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int32 nIndex) override
Return the specified child or NULL if index is invalid.
css::awt::Point AWTPoint(const ::Point &rVCLPoint)
MapMode GetDrawMapMode(bool bForce=false)
MapMode for the drawinglayer objects.
Definition: gridwin3.cxx:246
sal_Int32 GetSelectedCount() const
OUString GetTitle(sal_uInt16 nMaxLen=0) const
void MarkToMulti()
Definition: markdata.cxx:224
utl::AccessibleRelationSetHelper * GetRelationSet(const ScAddress *pAddress) const
ScAddress GetCurCellAddress() const
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
===== SfxListener =====================================================
signed char sal_Int8
virtual bool ReplaceChild(::accessibility::AccessibleShape *pCurrentChild, const css::uno::Reference< css::drawing::XShape > &_rxShape, const long _nIndex, const ::accessibility::AccessibleShapeTreeInfo &_rShapeTreeInfo) override
===== IAccessibleParent ===============================================
ULONG m_refCount
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex) override
vcl::Window * GetAccessibleParentWindow() const
void Select(sal_Int32 nIndex)
void AddAccessibilityObject(SfxListener &rObject)
Definition: tabvwshh.cxx:207
const OUString & GetName() const
virtual sal_Bool SAL_CALL isAccessibleChildSelected(sal_Int32 nChildIndex) override
const css::uno::Reference< css::drawing::XShape > & GetXShape() const
static ScDrawObjData * GetObjData(SdrObject *pObj, bool bCreate=false)
Definition: drwlayer.cxx:2282
virtual void SAL_CALL acquire() override
ScTabViewShell * mpViewShell
SdrObject * GetObj(size_t nNum) const
size_t GetObjCount() const
ScSplitPos GetNewGridWin() const
virtual void SAL_CALL grabFocus() override
bool HasEditView(ScSplitPos eWhich) const
Definition: viewdata.hxx:569
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:1711
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
Return a reference to the parent.
bool IsActive() const
Definition: tabvwsh.hxx:374
ScSplitPos GetActivePart() const
Definition: viewdata.hxx:398
static OUString GetCurrentCellDescription()
SdrMark * GetMark(size_t nNum) const
virtual tools::Rectangle GetBoundingBox() const override
Return the object's current bounding box relative to the parent object.
rtl::Reference< AccessibleShape > CreateAccessibleObject(const AccessibleShapeInfo &rShapeInfo, const AccessibleShapeTreeInfo &rShapeTreeInfo) const
std::unordered_map< css::uno::Reference< css::drawing::XShape >, ScAccessibleShapeData * > ShapesMap
virtual void SAL_CALL release() override
virtual ~ScChildrenShapes() override
virtual sal_Int32 SAL_CALL getBackground() override
virtual sal_Bool SAL_CALL containsPoint(const css::awt::Point &rPoint) override
===== XAccessibleComponent ============================================
ScChildrenShapes(ScAccessibleDocument *pAccessibleDocument, ScTabViewShell *pViewShell, ScSplitPos eSplitPos)
SfxHintId GetId() const
ScSplitPos
Definition: viewdata.hxx:45
virtual OUString createAccessibleName() override
Return the object's current name.
css::uno::Reference< css::drawing::XShapes > getSelectedXShapes()
Definition: viewuno.cxx:825
virtual void SAL_CALL deselectAccessibleChild(sal_Int32 nChildIndex) override
void VisAreaChanged() const
virtual OUString SAL_CALL getImplementationName() override
===== XServiceInfo ===================================================
virtual css::uno::Reference< css::uno::XInterface > getUnoShape()
SdrPage * getSdrPageFromSdrObject() const
virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override
Returns an implementation id.
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:873
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
css::uno::Reference< css::accessibility::XAccessible > GetAccessible(bool bCreate=true)
virtual void SAL_CALL release() override
virtual OUString SAL_CALL getAccessibleName() override
Return the object's current name.
SfxFrame & GetFrame() const
int nCount
uno::Reference< XAccessible > Get(const ScAccessibleShapeData *pData) const
ScAccessibleDocument * mpAccessibleDocument
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Returns a list of all supported services.
void ActivatePart(ScSplitPos eWhich)
Definition: tabview3.cxx:2861
void AddRelation(const css::accessibility::AccessibleRelation &rRelation)
ScDocument * GetDocument() const
Definition: viewdata.cxx:859
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 ============================================
bool HasObjects() const
Definition: drwlayer.cxx:365
const char * sName
ScDrawView * GetScDrawView()
Definition: viewdata.cxx:3081
ScViewData & GetViewData()
Definition: tabview.hxx:332
void Deselect(sal_Int32 nChildIndex)
virtual void SAL_CALL disposing() override
virtual sal_Int32 SAL_CALL getAccessibleChildCount() override
===== XAccessibleContext ==============================================
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Returns a list of all supported services.
virtual css::uno::Any SAL_CALL getExtendedAttributes() override
Point GetPixPos(ScSplitPos eWhich) const
Definition: viewdata.hxx:634
virtual void SAL_CALL selectAccessibleChild(sal_Int32 nChildIndex) override
===== XAccessibleSelection ===========================================
SdrObject * GetMarkedSdrObj() const
ScAccessibleDocument(const css::uno::Reference< css::accessibility::XAccessible > &rxParent, ScTabViewShell *pViewShell, ScSplitPos eSplitPos)
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
===== SfxListener =====================================================
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1059
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:872
#define SFX_TITLE_APINAME
vcl::Window * GetWindowByPos(ScSplitPos ePos) const
Definition: tabview.hxx:370
ScSplitPos GetOldGridWin() const
int i
SVXCORE_DLLPUBLIC SdrObject * GetSdrObjectFromXShape(const css::uno::Reference< css::drawing::XShape > &xShape)
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
===== XTypeProvider ===================================================
inline::tools::Rectangle VCLRectangle(const css::awt::Rectangle &rAWTRect)
#define SC_MOD()
Definition: scmod.hxx:253
ScSplitPos GetEditActivePart() const
Definition: viewdata.hxx:589
css::uno::Reference< css::accessibility::XAccessible > mxTempAcc
const SdrMarkList & GetMarkedObjectList() const
const SdrPage * GetPage(sal_uInt16 nPgNum) 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
unsigned char sal_Bool
void CommitFocusGained() const
Calls all FocusListener to tell they that the focus is gained.
static ShapeTypeHandler & Instance()
OUString ScResId(const char *pId)
Definition: scdll.cxx:95
void SetAnchor(const uno::Reference< drawing::XShape > &xShape, ScAccessibleShapeData *pData) const
ScTabViewShell * mpViewShell
bool IsInside(const Point &rPOINT) const
This base class provides an implementation of the AccessibleTable service.
inline::Point VCLPoint(const css::awt::Point &rAWTPoint)
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
SdrPage * GetDrawPage() const
virtual void SAL_CALL acquire() override
css::uno::Sequence< T > concatSequences(const css::uno::Sequence< T > &rS1, const Ss &...rSn)
ScAccessibleEditObject * mpTempAccEdit
Size GetSize() const
mutable::accessibility::AccessibleShapeTreeInfo maShapeTreeInfo
bool IsSelected(sal_Int32 nIndex, css::uno::Reference< css::drawing::XShape > &rShape) const
bool IsReadOnly() const
virtual void SAL_CALL selectAllAccessibleChildren() override
ScAddress GetCurPos() const
Definition: viewdata.cxx:4023
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) SAL_OVERRIDE
Point PixelToLogic(const Point &rDevicePt) const
Point LogicToPixel(const Point &rLogicPt) const
void FillShapes(std::vector< uno::Reference< drawing::XShape > > &rShapes) const
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int32 nIndex) override
virtual tools::Rectangle GetBoundingBoxOnScreen() const override
Return the object's current bounding box relative to the desktop.
tools::Rectangle GetVisibleArea_Impl() const
===== IAccessibleViewForwarder ========================================
sal_uInt16 GetChildCount() const
void AddChild(const css::uno::Reference< css::accessibility::XAccessible > &xAcc, bool bFireEvent)
virtual void SAL_CALL disposing() override
constexpr SdrLayerID SC_LAYER_HIDDEN(4)
virtual sal_Int32 SAL_CALL getForeground() override
unsigned char sal_uInt8
void RemoveAccessibilityObject(SfxListener &rObject)
Definition: tabvwshh.cxx:218
virtual void SAL_CALL clearAccessibleSelection() override
SortedShapes maZOrderedShapes
bool GetUpdateMode() const
virtual css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet() override
Return the set of current states.
constexpr SdrLayerID SC_LAYER_FRONT(0)
bool IsVisible() const
#define STR_ACC_DOC_DESCR
Definition: strings.hxx:14
ShapeTypeId GetTypeId(const OUString &aServiceName) const
css::uno::Reference< css::frame::XController > GetController() const
OUString aName
constexpr SdrLayerID SC_LAYER_INTERN(2)
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
SdrObject * GetSdrObject() const
virtual sal_Int32 SAL_CALL getAccessibleChildCount() override
SfxBroadcaster * GetDrawBroadcaster()
Definition: documen9.cxx:53
void CommitFocusLost() const
Calls all FocusListener to tell they that the focus is lost.
Reference< XComponentContext > getProcessComponentContext()
rtl::Reference< ScAccessibleSpreadsheet > mpAccessibleSpreadsheet
std::unique_ptr< ScChildrenShapes > mpChildrenShapes
std::optional< ScAddress > GetAnchor(const uno::Reference< drawing::XShape > &xShape) const
tools::Rectangle maVisArea
std::vector< ScAccessibleShapeData * > SortedShapes
virtual void Init() override
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() SAL_OVERRIDE
OUString GetCurrentCellName() const
virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override
===== XTypeProvider ===================================================
virtual bool ResetState(sal_Int16 aState) override
SdrObject * getParentSdrObjectFromSdrObject() const
virtual tools::Rectangle GetVisibleArea() const override
===== IAccessibleViewForwarder ========================================
void CommitChange(const css::accessibility::AccessibleEventObject &rEvent) const
Calls all Listener to tell they the change.
uno::Reference< XAccessible > GetSelected(sal_Int32 nSelectedChildIndex, bool bTabSelected) const
ScDocument * GetDocument() const
virtual bool SetState(sal_Int16 aState) override
bool FindSelectedShapesChanges(const css::uno::Reference< css::drawing::XShapes > &xShapes) const
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1058
virtual css::uno::Reference< css::accessibility::XAccessible > GetAccessibleCaption(const css::uno::Reference< css::drawing::XShape > &xShape) override
virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount() override
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) override
===== XInterface =====================================================
static sal_Int8 Compare(const ScAccessibleShapeData *pData1, const ScAccessibleShapeData *pData2)
SdrObjList * getParentSdrObjListFromSdrObject() const
void dispose()
utl::AccessibleRelationSetHelper * GetRelationSet(const ScAddress *pAddress) const
======== internal =====================================================
sal_uInt16 GetAccessibleRole() const
void RemoveChild(const css::uno::Reference< css::accessibility::XAccessible > &xAcc, bool bFireEvent)
virtual css::uno::Any SAL_CALL queryInterface(css::uno::Type const &rType) override
===== XInterface =====================================================
bool HasFocus() const
virtual ~ScAccessibleDocument() override
void AddState(sal_Int16 aState)
css::uno::Reference< css::view::XSelectionSupplier > xSelectionSupplier
constexpr SdrLayerID SC_LAYER_CONTROLS(3)
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:213
AnyEventRef aEvent
void GetEditView(ScSplitPos eWhich, EditView *&rViewPtr, SCCOL &rCol, SCROW &rRow)
Definition: viewdata.cxx:2225
tools::Rectangle GetWindowExtentsRelative(vcl::Window *pRelativeWindow) const
void AddChildEventListener(const Link< VclWindowEvent &, void > &rEventListener)
sal_uInt16 GetPageCount() const
sal_Int16 SCTAB
Definition: types.hxx:23
void SetDrawBroadcaster()
===== Internal ========================================================
virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext() override
===== XAccessible =====================================================
vcl::Window * GetChild(sal_uInt16 nChild) const
const SdrObject * GetObject() const
SfxMedium * GetMedium() const
This base class provides an implementation of the AccessibleCell service.