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