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& rViewFrame = mpViewShell->GetViewFrame();
292 xSelectionSupplier = uno::Reference<view::XSelectionSupplier>(rViewFrame.GetFrame().GetController(), uno::UNO_QUERY);
293 if (xSelectionSupplier.is())
294 {
295 xSelectionSupplier->addSelectionChangeListener(mpAccessibleDocument);
296 uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
297 if (xShapes.is())
298 mnShapesSelected = xShapes->getCount();
299 }
300 }
301
302 maZOrderedShapes.push_back(nullptr); // add an element which represents the table
303
304 GetCount(); // fill list with filtered shapes (no internal shapes)
305
307 {
308 //set flag on every selected shape
309 if (!xSelectionSupplier.is())
310 throw uno::RuntimeException();
311
312 uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
313 if (xShapes.is())
315 }
316 if (!pViewShell)
317 return;
318
319 ScViewData& rViewData = pViewShell->GetViewData();
320 SfxBroadcaster* pDrawBC = rViewData.GetDocument().GetDrawBroadcaster();
321 if (pDrawBC)
322 {
323 StartListening(*pDrawBC);
324
325 maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(rViewData.GetDocument().GetDrawLayer()) );
326 maShapeTreeInfo.SetSdrView(rViewData.GetScDrawView());
327 maShapeTreeInfo.SetController(nullptr);
328 maShapeTreeInfo.SetWindow(pViewShell->GetWindowByPos(meSplitPos));
329 maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
330 }
331}
332
334{
335 for (ScAccessibleShapeData* pShapeData : maZOrderedShapes)
336 delete pShapeData;
337 if (mpViewShell)
338 {
340 if (pDrawBC)
341 EndListening(*pDrawBC);
342 }
344 xSelectionSupplier->removeSelectionChangeListener(mpAccessibleDocument);
345}
346
348{
349 if (!mpViewShell)
350 return;
351
352 ScViewData& rViewData = mpViewShell->GetViewData();
353 SfxBroadcaster* pDrawBC = rViewData.GetDocument().GetDrawBroadcaster();
354 if (pDrawBC)
355 {
356 StartListening(*pDrawBC, DuplicateHandling::Prevent);
357
358 maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(rViewData.GetDocument().GetDrawLayer()) );
359 maShapeTreeInfo.SetSdrView(rViewData.GetScDrawView());
360 maShapeTreeInfo.SetController(nullptr);
362 maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
363 }
364}
365
367{
368 if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
369 return;
370 const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
371
372 SdrObject* pObj = const_cast<SdrObject*>(pSdrHint->GetObject());
373 if (!(pObj && /*(pObj->GetLayer() != SC_LAYER_INTERN) && */(pObj->getSdrPageFromSdrObject() == GetDrawPage()) &&
374 (pObj->getSdrPageFromSdrObject() == pObj->getParentSdrObjListFromSdrObject())) ) //only do something if the object lies direct on the page
375 return;
376
377 switch (pSdrHint->GetKind())
378 {
379 case SdrHintKind::ObjectChange : // object changed
380 {
381 uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
382 if (xShape.is())
383 {
384 mbShapesNeedSorting = true; // sort, because the z index or layer could be changed
385 auto it = maShapesMap.find(xShape);
386 if (it != maShapesMap.end())
387 SetAnchor(xShape, it->second);
388 }
389 }
390 break;
391 case SdrHintKind::ObjectInserted : // new drawing object inserted
392 {
393 uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
394 if (xShape.is())
395 AddShape(xShape, true);
396 }
397 break;
398 case SdrHintKind::ObjectRemoved : // Removed drawing object from list
399 {
400 uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
401 if (xShape.is())
402 RemoveShape(xShape);
403 }
404 break;
405 default :
406 {
407 // other events are not interesting
408 }
409 break;
410 }
411}
412
414 const css::uno::Reference< css::drawing::XShape >& _rxShape,
415 const tools::Long /*_nIndex*/, const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo)
416{
417 // create the new child
419 ::accessibility::AccessibleShapeInfo ( _rxShape, pCurrentChild->getAccessibleParent(), this ),
420 _rShapeTreeInfo
421 ));
422
423 bool bResult(false);
424 if (pReplacement.is())
425 {
426 OSL_ENSURE(pCurrentChild->GetXShape().get() == pReplacement->GetXShape().get(), "XShape changes and should be inserted sorted");
427 auto it = maShapesMap.find(pCurrentChild->GetXShape());
428 if (it != maShapesMap.end() && it->second->pAccShape.is())
429 {
430 OSL_ENSURE(it->second->pAccShape == pCurrentChild, "wrong child found");
431 AccessibleEventObject aEvent;
432 aEvent.EventId = AccessibleEventId::CHILD;
433 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
434 aEvent.OldValue <<= uno::Reference<XAccessible>(pCurrentChild);
435 aEvent.IndexHint = -1;
436
437 mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
438
439 pCurrentChild->dispose();
440 }
441
442 // Init after above possible pCurrentChild->dispose so we don't trigger the assert
443 // ScDrawModelBroadcaster::addShapeEventListener of duplicate listeners
444 pReplacement->Init();
445
446 if (it != maShapesMap.end())
447 {
448 it->second->pAccShape = pReplacement;
449 AccessibleEventObject aEvent;
450 aEvent.EventId = AccessibleEventId::CHILD;
451 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
452 aEvent.NewValue <<= uno::Reference<XAccessible>(pReplacement);
453 aEvent.IndexHint = -1;
454
455 mpAccessibleDocument->CommitChange(aEvent); // child is new - event
456 bResult = true;
457 }
458 }
459 return bResult;
460}
461
463{
464 GetCount(); // populate
465 for (ScAccessibleShapeData* pShape : maZOrderedShapes)
466 {
467 if (pShape)
468 {
469 rtl::Reference< ::accessibility::AccessibleShape > pAccShape(pShape->pAccShape);
470 if (pAccShape.is() && ::accessibility::ShapeTypeHandler::Instance().GetTypeId (pAccShape->GetXShape()) == ::accessibility::DRAWING_CONTROL)
471 {
472 ::accessibility::AccessibleControlShape *pCtlAccShape = static_cast < ::accessibility::AccessibleControlShape* >(pAccShape.get());
473 if (pCtlAccShape && pCtlAccShape->GetControlModel() == pSet)
474 return pCtlAccShape;
475 }
476 }
477 }
478 return nullptr;
479}
480
481css::uno::Reference < css::accessibility::XAccessible >
482ScChildrenShapes::GetAccessibleCaption (const css::uno::Reference < css::drawing::XShape>& xShape)
483{
484 GetCount(); // populate
485 auto it = maShapesMap.find(xShape);
486 if (it == maShapesMap.end())
487 return nullptr;
488 ScAccessibleShapeData* pShape = it->second;
489 css::uno::Reference< css::accessibility::XAccessible > xNewChild( pShape->pAccShape );
490 if(xNewChild)
491 return xNewChild;
492 return nullptr;
493}
494
496{
497 SdrPage* pDrawPage = GetDrawPage();
498 if (pDrawPage && (maZOrderedShapes.size() == 1)) // the table is always in
499 {
500 size_t nSdrObjCount = pDrawPage->GetObjCount();
501 maZOrderedShapes.reserve(nSdrObjCount + 1); // the table is always in
502 for (size_t i = 0; i < nSdrObjCount; ++i)
503 {
504 SdrObject* pObj = pDrawPage->GetObj(i);
505 if (pObj/* && (pObj->GetLayer() != SC_LAYER_INTERN)*/)
506 {
507 uno::Reference< drawing::XShape > xShape (pObj->getUnoShape(), uno::UNO_QUERY);
508 AddShape(xShape, false); //inserts in the correct order
509 }
510 }
511 }
512 return maZOrderedShapes.size();
513}
514
515uno::Reference< XAccessible > ScChildrenShapes::Get(const ScAccessibleShapeData* pData) const
516{
517 if (!pData)
518 return nullptr;
519
520 if (!pData->pAccShape.is())
521 {
524 pData->pAccShape = rShapeHandler.CreateAccessibleObject(
525 aShapeInfo, maShapeTreeInfo);
526 if (pData->pAccShape.is())
527 {
528 pData->pAccShape->Init();
529 if (pData->bSelected)
530 pData->pAccShape->SetState(AccessibleStateType::SELECTED);
531 if (!pData->bSelectable)
532 pData->pAccShape->ResetState(AccessibleStateType::SELECTABLE);
533 pData->pAccShape->SetRelationSet(GetRelationSet(pData));
534 }
535 }
536 return pData->pAccShape;
537 }
538
539uno::Reference< XAccessible > ScChildrenShapes::Get(sal_Int32 nIndex) const
540{
541 if (maZOrderedShapes.size() <= 1)
542 GetCount(); // fill list with filtered shapes (no internal shapes)
543
545 {
546 std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
547 mbShapesNeedSorting = false;
548 }
549
551 return nullptr;
552
553 return Get(maZOrderedShapes[nIndex]);
554}
555
556uno::Reference< XAccessible > ScChildrenShapes::GetAt(const awt::Point& rPoint) const
557{
558 uno::Reference<XAccessible> xAccessible;
559 if(mpViewShell)
560 {
562 {
563 std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
564 mbShapesNeedSorting = false;
565 }
566
567 sal_Int32 i(maZOrderedShapes.size() - 1);
568 bool bFound(false);
569 while (!bFound && i >= 0)
570 {
571 ScAccessibleShapeData* pShape = maZOrderedShapes[i];
572 if (pShape)
573 {
574 if (!pShape->pAccShape.is())
575 Get(pShape);
576
577 if (pShape->pAccShape.is())
578 {
579 Point aPoint(VCLPoint(rPoint));
580 aPoint -= VCLRectangle(pShape->pAccShape->getBounds()).TopLeft();
581 if (pShape->pAccShape->containsPoint(AWTPoint(aPoint)))
582 {
583 xAccessible = pShape->pAccShape.get();
584 bFound = true;
585 }
586 }
587 else
588 {
589 OSL_FAIL("I should have an accessible shape now!");
590 }
591 }
592 else
593 bFound = true; // this is the sheet and it lies before the rest of the shapes which are background shapes
594
595 --i;
596 }
597 }
598 return xAccessible;
599}
600
601bool ScChildrenShapes::IsSelected(sal_Int32 nIndex,
602 uno::Reference<drawing::XShape>& rShape) const
603{
604 bool bResult (false);
605 if (maZOrderedShapes.size() <= 1)
606 GetCount(); // fill list with filtered shapes (no internal shapes)
607
608 if (!xSelectionSupplier.is())
609 throw uno::RuntimeException();
610
612 {
613 std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
614 mbShapesNeedSorting = false;
615 }
616
618 return false;
619
620 bResult = maZOrderedShapes[nIndex]->bSelected;
621 rShape = maZOrderedShapes[nIndex]->xShape;
622
623#if OSL_DEBUG_LEVEL > 0 // test whether it is truly selected by a slower method
624 uno::Reference< drawing::XShape > xReturnShape;
625 bool bDebugResult(false);
626 uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
627
628 if (xShapes.is())
629 {
630 sal_Int32 nCount(xShapes->getCount());
631 if (nCount)
632 {
633 uno::Reference< drawing::XShape > xShape;
634 uno::Reference< drawing::XShape > xIndexShape = maZOrderedShapes[nIndex]->xShape;
635 sal_Int32 i(0);
636 while (!bDebugResult && (i < nCount))
637 {
638 xShapes->getByIndex(i) >>= xShape;
639 if (xShape.is() && (xIndexShape.get() == xShape.get()))
640 {
641 bDebugResult = true;
642 xReturnShape = xShape;
643 }
644 else
645 ++i;
646 }
647 }
648 }
649 OSL_ENSURE((bResult == bDebugResult) && ((bResult && (rShape.get() == xReturnShape.get())) || !bResult), "found the wrong shape or result");
650#endif
651
652 return bResult;
653}
654
656{
657 bool bResult(false);
658 if (!xSelectionSupplier.is())
659 throw uno::RuntimeException();
660
661 uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
662
663 bResult = FindSelectedShapesChanges(xShapes);
664
665 return bResult;
666}
667
668void ScChildrenShapes::Select(sal_Int32 nIndex)
669{
670 if (maZOrderedShapes.size() <= 1)
671 GetCount(); // fill list with filtered shapes (no internal shapes)
672
673 if (!xSelectionSupplier.is())
674 throw uno::RuntimeException();
675
677 {
678 std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
679 mbShapesNeedSorting = false;
680 }
681
683 return;
684
685 uno::Reference<drawing::XShape> xShape;
686 if (IsSelected(nIndex, xShape) || !maZOrderedShapes[nIndex]->bSelectable)
687 return;
688
689 uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
690
691 if (!xShapes.is())
692 xShapes = drawing::ShapeCollection::create(
694
695 xShapes->add(maZOrderedShapes[nIndex]->xShape);
696
697 try
698 {
699 xSelectionSupplier->select(uno::Any(xShapes));
700 maZOrderedShapes[nIndex]->bSelected = true;
701 if (maZOrderedShapes[nIndex]->pAccShape.is())
702 maZOrderedShapes[nIndex]->pAccShape->SetState(AccessibleStateType::SELECTED);
703 }
704 catch (lang::IllegalArgumentException&)
705 {
706 }
707}
708
710{
711 if (!xSelectionSupplier.is())
712 throw uno::RuntimeException();
713
714 bool bSomethingSelected(true);
715 try
716 {
717 xSelectionSupplier->select(uno::Any()); //deselects all
718 }
719 catch (lang::IllegalArgumentException&)
720 {
721 OSL_FAIL("nothing selected before");
722 bSomethingSelected = false;
723 }
724
725 if (bSomethingSelected)
726 for (const ScAccessibleShapeData* pAccShapeData : maZOrderedShapes)
727 if (pAccShapeData)
728 {
729 pAccShapeData->bSelected = false;
730 if (pAccShapeData->pAccShape.is())
731 pAccShapeData->pAccShape->ResetState(AccessibleStateType::SELECTED);
732 }
733};
734
735
737{
738 if (!xSelectionSupplier.is())
739 throw uno::RuntimeException();
740
741 if (maZOrderedShapes.size() <= 1)
742 GetCount(); // fill list with filtered shapes (no internal shapes)
743
744 if (maZOrderedShapes.size() <= 1)
745 return;
746
747 uno::Reference<drawing::XShapes> xShapes = drawing::ShapeCollection::create(
749
750 try
751 {
752 for (const ScAccessibleShapeData* pAccShapeData : maZOrderedShapes)
753 {
754 if (pAccShapeData && pAccShapeData->bSelectable)
755 {
756 pAccShapeData->bSelected = true;
757 if (pAccShapeData->pAccShape.is())
758 pAccShapeData->pAccShape->SetState(AccessibleStateType::SELECTED);
759 if (xShapes.is())
760 xShapes->add(pAccShapeData->xShape);
761 }
762 }
763 xSelectionSupplier->select(uno::Any(xShapes));
764 }
765 catch (lang::IllegalArgumentException&)
766 {
767 SelectionChanged(); // find all selected shapes and set the flags
768 }
769}
770
771void ScChildrenShapes::FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const
772{
773 uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
774 if (xShapes.is())
775 {
776 sal_uInt32 nCount(xShapes->getCount());
777 for (sal_uInt32 i = 0; i < nCount; ++i)
778 {
779 uno::Reference<drawing::XShape> xShape;
780 xShapes->getByIndex(i) >>= xShape;
781 if (xShape.is())
782 rShapes.push_back(xShape);
783 }
784 }
785}
786
788{
789 if (!xSelectionSupplier.is())
790 throw uno::RuntimeException();
791
792 std::vector < uno::Reference < drawing::XShape > > aShapes;
793 FillShapes(aShapes);
794
795 return aShapes.size();
796}
797
798uno::Reference< XAccessible > ScChildrenShapes::GetSelected(sal_Int32 nSelectedChildIndex, bool bTabSelected) const
799{
800 uno::Reference< XAccessible > xAccessible;
801
802 if (maZOrderedShapes.size() <= 1)
803 GetCount(); // fill list with shapes
804
805 if (!bTabSelected)
806 {
807 std::vector < uno::Reference < drawing::XShape > > aShapes;
808 FillShapes(aShapes);
809
810 if (nSelectedChildIndex < 0 || o3tl::make_unsigned(nSelectedChildIndex) >= aShapes.size())
811 return xAccessible;
812
813 SortedShapes::iterator aItr;
814 if (FindShape(aShapes[nSelectedChildIndex], aItr))
815 xAccessible = Get(*aItr);
816 }
817 else
818 {
820 {
821 std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
822 mbShapesNeedSorting = false;
823 }
824 for(const auto& rpShape : maZOrderedShapes)
825 {
826 if (!rpShape || rpShape->bSelected)
827 {
828 if (nSelectedChildIndex == 0)
829 {
830 if (rpShape)
831 xAccessible = rpShape->pAccShape.get();
832 break;
833 }
834 else
835 --nSelectedChildIndex;
836 }
837 }
838 }
839
840 return xAccessible;
841}
842
843void ScChildrenShapes::Deselect(sal_Int32 nChildIndex)
844{
845 uno::Reference<drawing::XShape> xShape;
846 if (!IsSelected(nChildIndex, xShape)) // returns false if it is the sheet
847 return;
848
849 if (!xShape.is())
850 return;
851
852 uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
853 if (xShapes.is())
854 xShapes->remove(xShape);
855
856 try
857 {
858 xSelectionSupplier->select(uno::Any(xShapes));
859 }
860 catch (lang::IllegalArgumentException&)
861 {
862 OSL_FAIL("something not selectable");
863 }
864
865 maZOrderedShapes[nChildIndex]->bSelected = false;
866 if (maZOrderedShapes[nChildIndex]->pAccShape.is())
867 maZOrderedShapes[nChildIndex]->pAccShape->ResetState(AccessibleStateType::SELECTED);
868}
869
871{
873 SdrPage* pDrawPage = nullptr;
874 if (mpViewShell)
875 {
877 if (ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer())
878 {
879 if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab))
880 pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(static_cast<sal_Int16>(nTab)));
881 }
882 }
883 return pDrawPage;
884}
885
887{
889 for (const ScAccessibleShapeData* pAccShapeData : maZOrderedShapes)
890 {
891 if (pAccShapeData &&
892 ((!pAccShapeData->xRelationCell && !pAddress) ||
893 (pAccShapeData->xRelationCell && pAddress && (*(pAccShapeData->xRelationCell) == *pAddress))))
894 {
895 if (!pRelationSet)
896 pRelationSet = new utl::AccessibleRelationSetHelper();
897
898 AccessibleRelation aRelation;
899 aRelation.TargetSet = { Get(pAccShapeData) };
900 aRelation.RelationType = AccessibleRelationType::CONTROLLER_FOR;
901
902 pRelationSet->AddRelation(aRelation);
903 }
904 }
905 return pRelationSet;
906}
907
908bool ScChildrenShapes::FindSelectedShapesChanges(const uno::Reference<drawing::XShapes>& xShapes) const
909{
910 bool bResult(false);
911 SortedShapes aShapesList;
912 if (xShapes.is())
913 {
914 mnShapesSelected = xShapes->getCount();
915 for (sal_uInt32 i = 0; i < mnShapesSelected; ++i)
916 {
917 uno::Reference< drawing::XShape > xShape;
918 xShapes->getByIndex(i) >>= xShape;
919 if (xShape.is())
920 {
921 ScAccessibleShapeData* pShapeData = new ScAccessibleShapeData(xShape);
922 aShapesList.push_back(pShapeData);
923 }
924 }
925 }
926 else
928 SdrObject *pFocusedObj = nullptr;
929 if( mnShapesSelected == 1 && aShapesList.size() == 1)
930 {
931 pFocusedObj = SdrObject::getSdrObjectFromXShape(aShapesList[0]->xShape);
932 }
933 std::sort(aShapesList.begin(), aShapesList.end(), ScShapeDataLess());
934 SortedShapes vecSelectedShapeAdd;
935 SortedShapes vecSelectedShapeRemove;
936 bool bHasSelect=false;
937 SortedShapes::iterator aXShapesItr(aShapesList.begin());
938 SortedShapes::const_iterator aXShapesEndItr(aShapesList.end());
939 SortedShapes::iterator aDataItr(maZOrderedShapes.begin());
940 SortedShapes::const_iterator aDataEndItr(maZOrderedShapes.end());
941 SortedShapes::const_iterator aFocusedItr = aDataEndItr;
942 while(aDataItr != aDataEndItr)
943 {
944 if (*aDataItr) // is it really a shape or only the sheet
945 {
946 sal_Int8 nComp(0);
947 if (aXShapesItr == aXShapesEndItr)
948 nComp = -1; // simulate that the Shape is lower, so the selection state will be removed
949 else
950 nComp = Compare(*aDataItr, *aXShapesItr);
951 if (nComp == 0)
952 {
953 if (!(*aDataItr)->bSelected)
954 {
955 (*aDataItr)->bSelected = true;
956 if ((*aDataItr)->pAccShape.is())
957 {
958 (*aDataItr)->pAccShape->SetState(AccessibleStateType::SELECTED);
959 (*aDataItr)->pAccShape->SetState(AccessibleStateType::FOCUSED);
960 bResult = true;
961 vecSelectedShapeAdd.push_back(*aDataItr);
962 }
963 aFocusedItr = aDataItr;
964 }
965 else
966 {
967 bHasSelect = true;
968 }
969 ++aDataItr;
970 ++aXShapesItr;
971 }
972 else if (nComp < 0)
973 {
974 if ((*aDataItr)->bSelected)
975 {
976 (*aDataItr)->bSelected = false;
977 if ((*aDataItr)->pAccShape.is())
978 {
979 (*aDataItr)->pAccShape->ResetState(AccessibleStateType::SELECTED);
980 (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED);
981 bResult = true;
982 vecSelectedShapeRemove.push_back(*aDataItr);
983 }
984 }
985 ++aDataItr;
986 }
987 else
988 {
989 OSL_FAIL("here is a selected shape which is not in the childlist");
990 ++aXShapesItr;
992 }
993 }
994 else
995 ++aDataItr;
996 }
997 bool bWinFocus=false;
998 if (mpViewShell)
999 {
1001 if (pWin)
1002 {
1003 bWinFocus = pWin->HasFocus();
1004 }
1005 }
1006 const SdrMarkList* pMarkList = nullptr;
1007 SdrObject* pMarkedObj = nullptr;
1008 bool bIsFocuseMarked = true;
1009 if( mpViewShell && mnShapesSelected == 1 && bWinFocus)
1010 {
1011 ScDrawView* pScDrawView = mpViewShell->GetViewData().GetScDrawView();
1012 if( pScDrawView )
1013 {
1014 if( pScDrawView->GetMarkedObjectList().GetMarkCount() == 1 )
1015 {
1016 pMarkList = &(pScDrawView->GetMarkedObjectList());
1017 pMarkedObj = pMarkList->GetMark(0)->GetMarkedSdrObj();
1018 uno::Reference< drawing::XShape > xMarkedXShape (pMarkedObj->getUnoShape(), uno::UNO_QUERY);
1019 if( aFocusedItr != aDataEndItr &&
1020 (*aFocusedItr)->xShape.is() &&
1021 xMarkedXShape.is() &&
1022 (*aFocusedItr)->xShape != xMarkedXShape )
1023 bIsFocuseMarked = false;
1024 }
1025 }
1026 }
1027 //if ((aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape.is() && (mnShapesSelected == 1))
1028 if ( bIsFocuseMarked && (aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape.is() && (mnShapesSelected == 1) && bWinFocus)
1029 {
1030 (*aFocusedItr)->pAccShape->SetState(AccessibleStateType::FOCUSED);
1031 }
1032 else if( pFocusedObj && bWinFocus && pMarkList && pMarkList->GetMarkCount() == 1 && mnShapesSelected == 1 )
1033 {
1034 if( pMarkedObj )
1035 {
1036 uno::Reference< drawing::XShape > xMarkedXShape (pMarkedObj->getUnoShape(), uno::UNO_QUERY);
1037 SdrObject* pUpObj = pMarkedObj->getParentSdrObjectFromSdrObject();
1038
1039 if( pMarkedObj == pFocusedObj && pUpObj )
1040 {
1041 uno::Reference< drawing::XShape > xUpGroupXShape (pUpObj->getUnoShape(), uno::UNO_QUERY);
1042 uno::Reference < XAccessible > xAccGroupShape =
1043 const_cast<ScChildrenShapes*>(this)->GetAccessibleCaption( xUpGroupXShape );
1044 if( xAccGroupShape.is() )
1045 {
1046 ::accessibility::AccessibleShape* pAccGroupShape =
1047 static_cast< ::accessibility::AccessibleShape* >(xAccGroupShape.get());
1048 if( pAccGroupShape )
1049 {
1050 sal_Int64 nCount = pAccGroupShape->getAccessibleChildCount();
1051 for( sal_Int64 i = 0; i < nCount; i++ )
1052 {
1053 uno::Reference<XAccessible> xAccShape = pAccGroupShape->getAccessibleChild(i);
1054 if (xAccShape.is())
1055 {
1056 ::accessibility::AccessibleShape* pChildAccShape = static_cast< ::accessibility::AccessibleShape* >(xAccShape.get());
1057 uno::Reference< drawing::XShape > xChildShape = pChildAccShape->GetXShape();
1058 if (xChildShape == xMarkedXShape)
1059 {
1060 pChildAccShape->SetState(AccessibleStateType::FOCUSED);
1061 }
1062 else
1063 {
1064 pChildAccShape->ResetState(AccessibleStateType::FOCUSED);
1065 }
1066 }
1067 }
1068 }
1069 }
1070 }
1071 }
1072 }
1073 if (vecSelectedShapeAdd.size() >= 10 )
1074 {
1075 AccessibleEventObject aEvent;
1076 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
1077 aEvent.Source = uno::Reference< XAccessible >(mpAccessibleDocument);
1079 }
1080 else
1081 {
1082 for (const auto& rpShape : vecSelectedShapeAdd)
1083 {
1084 AccessibleEventObject aEvent;
1085 if (bHasSelect)
1086 {
1087 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_ADD;
1088 }
1089 else
1090 {
1091 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1092 }
1093 aEvent.Source = uno::Reference< XAccessible >(mpAccessibleDocument);
1094 uno::Reference< XAccessible > xChild( rpShape->pAccShape );
1095 aEvent.NewValue <<= xChild;
1097 }
1098 }
1099 for (const auto& rpShape : vecSelectedShapeRemove)
1100 {
1101 AccessibleEventObject aEvent;
1102 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
1103 aEvent.Source = uno::Reference< XAccessible >(mpAccessibleDocument);
1104 uno::Reference< XAccessible > xChild( rpShape->pAccShape );
1105 aEvent.NewValue <<= xChild;
1107 }
1108 for(ScAccessibleShapeData*& pShapeData : aShapesList)
1109 {
1110 delete pShapeData;
1111 pShapeData = nullptr;
1112 }
1113 return bResult;
1114}
1115
1116std::optional<ScAddress> ScChildrenShapes::GetAnchor(const uno::Reference<drawing::XShape>& xShape) const
1117{
1118 if (mpViewShell)
1119 {
1121 uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
1122 if (pSdrObj && xShapeProp.is())
1123 {
1124 if (ScDrawObjData *pAnchor = ScDrawLayer::GetObjData(pSdrObj))
1125 return std::optional<ScAddress>(pAnchor->maStart);
1126 }
1127 }
1128
1129 return std::optional<ScAddress>();
1130}
1131
1132uno::Reference<XAccessibleRelationSet> ScChildrenShapes::GetRelationSet(const ScAccessibleShapeData* pData) const
1133{
1135
1137 {
1138 uno::Reference<XAccessible> xAccessible = mpAccessibleDocument->GetAccessibleSpreadsheet(); // should be the current table
1139 if (pData->xRelationCell && xAccessible.is())
1140 {
1141 sal_Int32 nRow = pData->xRelationCell->Row();
1142 sal_Int32 nColumn = pData->xRelationCell->Col();
1143 bool bPositionUnset = nRow == -1 && nColumn == -1;
1144 if (!bPositionUnset)
1145 {
1146 uno::Reference<XAccessibleTable> xAccTable(xAccessible->getAccessibleContext(), uno::UNO_QUERY);
1147 if (xAccTable.is())
1148 xAccessible = xAccTable->getAccessibleCellAt(nRow, nColumn);
1149 }
1150 }
1151 AccessibleRelation aRelation;
1152 aRelation.TargetSet = { xAccessible };
1153 aRelation.RelationType = AccessibleRelationType::CONTROLLED_BY;
1154 pRelationSet->AddRelation(aRelation);
1155 }
1156
1157 return pRelationSet;
1158}
1159
1160void ScChildrenShapes::SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const
1161{
1162 if (pData)
1163 {
1164 std::optional<ScAddress> xAddress = GetAnchor(xShape);
1165 if ((xAddress && pData->xRelationCell && (*xAddress != *(pData->xRelationCell))) ||
1166 (!xAddress && pData->xRelationCell) || (xAddress && !pData->xRelationCell))
1167 {
1168 pData->xRelationCell = xAddress;
1169 if (pData->pAccShape.is())
1170 pData->pAccShape->SetRelationSet(GetRelationSet(pData));
1171 }
1172 }
1173}
1174
1175void ScChildrenShapes::AddShape(const uno::Reference<drawing::XShape>& xShape, bool bCommitChange) const
1176{
1177 assert( maShapesMap.find(xShape) == maShapesMap.end());
1178
1179 ScAccessibleShapeData* pShape = new ScAccessibleShapeData(xShape);
1180 maZOrderedShapes.push_back(pShape);
1181 mbShapesNeedSorting = true;
1182 maShapesMap[xShape] = pShape;
1183 SetAnchor(xShape, pShape);
1184
1185 uno::Reference< beans::XPropertySet > xShapeProp(xShape, uno::UNO_QUERY);
1186 if (xShapeProp.is())
1187 {
1188 uno::Any aPropAny = xShapeProp->getPropertyValue("LayerID");
1189 sal_Int16 nLayerID = 0;
1190 if( aPropAny >>= nLayerID )
1191 {
1192 if( (SdrLayerID(nLayerID) == SC_LAYER_INTERN) || (SdrLayerID(nLayerID) == SC_LAYER_HIDDEN) )
1193 pShape->bSelectable = false;
1194 else
1195 pShape->bSelectable = true;
1196 }
1197 }
1198
1199 if (!xSelectionSupplier.is())
1200 throw uno::RuntimeException();
1201
1202 uno::Reference<drawing::XShapes> xShapes(mpViewShell->getSelectedXShapes());
1203 uno::Reference<container::XEnumerationAccess> xEnumAcc(xShapes, uno::UNO_QUERY);
1204 if (xEnumAcc.is())
1205 {
1206 uno::Reference<container::XEnumeration> xEnum = xEnumAcc->createEnumeration();
1207 if (xEnum.is())
1208 {
1209 uno::Reference<drawing::XShape> xSelectedShape;
1210 bool bFound(false);
1211 while (!bFound && xEnum->hasMoreElements())
1212 {
1213 xEnum->nextElement() >>= xSelectedShape;
1214 if (xShape.is() && (xShape.get() == xSelectedShape.get()))
1215 {
1216 pShape->bSelected = true;
1217 bFound = true;
1218 }
1219 }
1220 }
1221 }
1222 if (mpAccessibleDocument && bCommitChange)
1223 {
1224 AccessibleEventObject aEvent;
1225 aEvent.EventId = AccessibleEventId::CHILD;
1226 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1227 aEvent.NewValue <<= Get(pShape);
1228 aEvent.IndexHint = -1;
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 aEvent.IndexHint = -1;
1257
1258 mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
1259 }
1260 else
1261 {
1262 delete *aItr;
1263 maShapesMap.erase((*aItr)->xShape);
1264 maZOrderedShapes.erase(aItr);
1265 }
1266 }
1267 else
1268 {
1269 OSL_FAIL("shape was not in internal list");
1270 }
1271}
1272
1273bool ScChildrenShapes::FindShape(const uno::Reference<drawing::XShape>& xShape, ScChildrenShapes::SortedShapes::iterator& rItr) const
1274{
1276 {
1277 std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), ScShapeDataLess());
1278 mbShapesNeedSorting = false;
1279 }
1280 bool bResult(false);
1281 ScAccessibleShapeData aShape(xShape);
1282 rItr = std::lower_bound(maZOrderedShapes.begin(), maZOrderedShapes.end(), &aShape, ScShapeDataLess());
1283 if ((rItr != maZOrderedShapes.end()) && (*rItr != nullptr) && ((*rItr)->xShape.get() == xShape.get()))
1284 bResult = true; // if the shape is found
1285
1286#if OSL_DEBUG_LEVEL > 0 // test whether it finds truly the correct shape (perhaps it is not really sorted)
1287 SortedShapes::iterator aDebugItr = std::find_if(maZOrderedShapes.begin(), maZOrderedShapes.end(),
1288 [&xShape](const ScAccessibleShapeData* pShape) { return pShape && (pShape->xShape.get() == xShape.get()); });
1289 bool bResult2 = (aDebugItr != maZOrderedShapes.end());
1290 OSL_ENSURE((bResult == bResult2) && ((bResult && (rItr == aDebugItr)) || !bResult), "wrong Shape found");
1291#endif
1292 return bResult;
1293}
1294
1295sal_Int8 ScChildrenShapes::Compare(const ScAccessibleShapeData* pData1,
1296 const ScAccessibleShapeData* pData2)
1297{
1298 ScShapeDataLess aLess;
1299
1300 bool bResult1(aLess(pData1, pData2));
1301 bool bResult2(aLess(pData2, pData1));
1302
1303 sal_Int8 nResult(0);
1304 if (!bResult1 && bResult2)
1305 nResult = 1;
1306 else if (bResult1 && !bResult2)
1307 nResult = -1;
1308
1309 return nResult;
1310}
1311
1313{
1314 for (const ScAccessibleShapeData* pAccShapeData: maZOrderedShapes)
1315 if (pAccShapeData && pAccShapeData->pAccShape.is())
1316 pAccShapeData->pAccShape->ViewForwarderChanged();
1317}
1318
1320 const uno::Reference<XAccessible>& rxParent,
1321 ScTabViewShell* pViewShell,
1322 ScSplitPos eSplitPos)
1323 : ScAccessibleDocumentBase(rxParent),
1324 mpViewShell(pViewShell),
1325 meSplitPos(eSplitPos),
1326 mbCompleteSheetSelected(false)
1327{
1329}
1330
1332{
1333 if (!mpViewShell)
1334 return;
1335
1338 if( pWin )
1339 {
1340 pWin->AddChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1341 sal_uInt16 nCount = pWin->GetChildCount();
1342 for( sal_uInt16 i=0; i < nCount; ++i )
1343 {
1344 vcl::Window *pChildWin = pWin->GetChild( i );
1345 if( pChildWin &&
1346 AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1347 AddChild( pChildWin->GetAccessible(), false );
1348 }
1349 }
1350 ScViewData& rViewData = mpViewShell->GetViewData();
1351 if (rViewData.HasEditView(meSplitPos))
1352 {
1353 uno::Reference<XAccessible> xAcc = new ScAccessibleEditObject(this, rViewData.GetEditView(meSplitPos),
1356 AddChild(xAcc, false);
1357 }
1358}
1359
1361{
1362 if(!mpChildrenShapes)
1364}
1365
1367{
1368 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
1369 {
1370 // increment refcount to prevent double call off dtor
1371 osl_atomic_increment( &m_refCount );
1372 dispose();
1373 }
1374}
1375
1377{
1378 SolarMutexGuard aGuard;
1380 if (mpViewShell)
1381 {
1383 if( pWin )
1384 pWin->RemoveChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1385
1387 mpViewShell = nullptr;
1388 }
1389 mpChildrenShapes.reset();
1390
1392}
1393
1394void SAL_CALL ScAccessibleDocument::disposing( const lang::EventObject& /* Source */ )
1395{
1396 disposing();
1397}
1398
1399 //===== SfxListener =====================================================
1400
1401IMPL_LINK( ScAccessibleDocument, WindowChildEventListener, VclWindowEvent&, rEvent, void )
1402{
1403 OSL_ENSURE( rEvent.GetWindow(), "Window???" );
1404 switch ( rEvent.GetId() )
1405 {
1406 case VclEventId::WindowShow: // send create on show for direct accessible children
1407 {
1408 vcl::Window* pChildWin = static_cast < vcl::Window * >( rEvent.GetData() );
1409 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1410 {
1411 AddChild( pChildWin->GetAccessible(), true );
1412 }
1413 }
1414 break;
1415 case VclEventId::WindowHide: // send destroy on hide for direct accessible children
1416 {
1417 vcl::Window* pChildWin = static_cast < vcl::Window * >( rEvent.GetData() );
1418 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1419 {
1420 RemoveChild( pChildWin->GetAccessible(), true );
1421 }
1422 }
1423 break;
1424 default: break;
1425 }
1426}
1427
1429{
1430 if (auto pFocusLostHint = dynamic_cast<const ScAccGridWinFocusLostHint*>(&rHint) )
1431 {
1432 if (pFocusLostHint->GetOldGridWin() == meSplitPos)
1433 {
1434 if (mxTempAcc.is() && mpTempAccEdit)
1435 mpTempAccEdit->LostFocus();
1436 else if (mpAccessibleSpreadsheet.is())
1437 mpAccessibleSpreadsheet->LostFocus();
1438 else
1440 }
1441 }
1442 else if (auto pFocusGotHint = dynamic_cast<const ScAccGridWinFocusGotHint*>(&rHint) )
1443 {
1444 if (pFocusGotHint->GetNewGridWin() == meSplitPos)
1445 {
1446 uno::Reference<XAccessible> xAccessible;
1447 if (mpChildrenShapes)
1448 {
1449 bool bTabMarked(IsTableSelected());
1450 xAccessible = mpChildrenShapes->GetSelected(0, bTabMarked);
1451 }
1452 if( xAccessible.is() )
1453 {
1454 uno::Any aNewValue;
1455 aNewValue<<=AccessibleStateType::FOCUSED;
1456 static_cast< ::accessibility::AccessibleShape* >(xAccessible.get())->
1457 CommitChange(AccessibleEventId::STATE_CHANGED,
1458 aNewValue,
1459 uno::Any(), -1 );
1460 }
1461 else
1462 {
1463 if (mxTempAcc.is() && mpTempAccEdit)
1464 mpTempAccEdit->GotFocus();
1465 else if (mpAccessibleSpreadsheet.is())
1466 mpAccessibleSpreadsheet->GotFocus();
1467 else
1469 }
1470 }
1471 }
1472 else
1473 {
1474 // only notify if child exist, otherwise it is not necessary
1475 if ((rHint.GetId() == SfxHintId::ScAccTableChanged) &&
1477 {
1479
1480 // Shapes / form controls after reload not accessible, rebuild the
1481 // mpChildrenShapes variable.
1483
1484 AccessibleEventObject aEvent;
1485 aEvent.EventId = AccessibleEventId::INVALIDATE_ALL_CHILDREN;
1486 aEvent.Source = uno::Reference< XAccessibleContext >(this);
1487 CommitChange(aEvent); // all children changed
1488
1489 if (mpAccessibleSpreadsheet.is())
1490 mpAccessibleSpreadsheet->FireFirstCellFocus();
1491 }
1492 else if (rHint.GetId() == SfxHintId::ScAccMakeDrawLayer)
1493 {
1494 if (mpChildrenShapes)
1495 mpChildrenShapes->SetDrawBroadcaster();
1496 }
1497 else if (rHint.GetId() == SfxHintId::ScAccEnterEditMode) // this event comes only on creating edit field of a cell
1498 {
1500 {
1501 ScViewData& rViewData = mpViewShell->GetViewData();
1502 const EditEngine* pEditEng = rViewData.GetEditView(meSplitPos)->GetEditEngine();
1503 if (pEditEng && pEditEng->IsUpdateLayout())
1504 {
1507 ScResId(STR_ACC_EDITLINE_DESCR), ScAccessibleEditObject::CellInEditMode);
1508 uno::Reference<XAccessible> xAcc = mpTempAccEdit;
1509
1510 AddChild(xAcc, true);
1511
1512 if (mpAccessibleSpreadsheet.is())
1513 mpAccessibleSpreadsheet->LostFocus();
1514 else
1516
1517 mpTempAccEdit->GotFocus();
1518 }
1519 }
1520 }
1521 else if (rHint.GetId() == SfxHintId::ScAccLeaveEditMode)
1522 {
1523 if (mxTempAcc.is())
1524 {
1525 if (mpTempAccEdit)
1526 {
1527 mpTempAccEdit->LostFocus();
1528 }
1529 RemoveChild(mxTempAcc, true);
1530 if (mpTempAccEdit)
1531 {
1532 // tdf#125982 a11y use-after-free of editengine by
1533 // ScAccessibleEditObjectTextData living past the
1534 // the editengine of the editview passed in above
1535 // in ScAccEnterEditMode
1536 mpTempAccEdit->dispose();
1537 mpTempAccEdit = nullptr;
1538 }
1540 mpAccessibleSpreadsheet->GotFocus();
1541 else if( mpViewShell && mpViewShell->IsActive())
1543 }
1544 }
1545 else if ((rHint.GetId() == SfxHintId::ScAccVisAreaChanged) || (rHint.GetId() == SfxHintId::ScAccWindowResized))
1546 {
1547 tools::Rectangle aOldVisArea(maVisArea);
1549
1550 if (maVisArea != aOldVisArea)
1551 {
1552 if (maVisArea.GetSize() != aOldVisArea.GetSize())
1553 {
1554 AccessibleEventObject aEvent;
1555 aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
1556 aEvent.Source = uno::Reference< XAccessibleContext >(this);
1557
1559
1560 if (mpAccessibleSpreadsheet.is())
1561 mpAccessibleSpreadsheet->BoundingBoxChanged();
1563 mpAccessibleSpreadsheet->FireFirstCellFocus();
1564 }
1565 else if (mpAccessibleSpreadsheet.is())
1566 {
1567 mpAccessibleSpreadsheet->VisAreaChanged();
1568 }
1569 if (mpChildrenShapes)
1570 mpChildrenShapes->VisAreaChanged();
1571 }
1572 }
1573 }
1574
1576}
1577
1578void SAL_CALL ScAccessibleDocument::selectionChanged( const lang::EventObject& /* aEvent */ )
1579{
1580 bool bSelectionChanged(false);
1581 if (mpAccessibleSpreadsheet.is())
1582 {
1583 bool bOldSelected(mbCompleteSheetSelected);
1585 if (bOldSelected != mbCompleteSheetSelected)
1586 {
1587 mpAccessibleSpreadsheet->CompleteSelectionChanged(mbCompleteSheetSelected);
1588 bSelectionChanged = true;
1589 }
1590 }
1591
1592 if (mpChildrenShapes && mpChildrenShapes->SelectionChanged())
1593 bSelectionChanged = true;
1594
1595 if (bSelectionChanged)
1596 {
1597 AccessibleEventObject aEvent;
1598 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1599 aEvent.Source = uno::Reference< XAccessibleContext >(this);
1600
1602 }
1603}
1604
1605 //===== XInterface =====================================================
1606
1608{
1610 return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType);
1611}
1612
1614 noexcept
1615{
1616 ScAccessibleContextBase::acquire();
1617}
1618
1620 noexcept
1621{
1622 ScAccessibleContextBase::release();
1623}
1624
1625 //===== XAccessibleComponent ============================================
1626
1627uno::Reference< XAccessible > SAL_CALL ScAccessibleDocument::getAccessibleAtPoint(
1628 const awt::Point& rPoint )
1629{
1630 uno::Reference<XAccessible> xAccessible;
1631 if (containsPoint(rPoint))
1632 {
1633 SolarMutexGuard aGuard;
1634 IsObjectValid();
1635 if (mpChildrenShapes)
1636 xAccessible = mpChildrenShapes->GetAt(rPoint);
1637 if(!xAccessible.is())
1638 {
1639 if (mxTempAcc.is())
1640 {
1641 uno::Reference< XAccessibleContext > xCont(mxTempAcc->getAccessibleContext());
1642 uno::Reference< XAccessibleComponent > xComp(xCont, uno::UNO_QUERY);
1643 if (xComp.is())
1644 {
1645 tools::Rectangle aBound(VCLRectangle(xComp->getBounds()));
1646 if (aBound.Contains(VCLPoint(rPoint)))
1647 xAccessible = mxTempAcc;
1648 }
1649 }
1650 if (!xAccessible.is())
1651 xAccessible = GetAccessibleSpreadsheet();
1652 }
1653 }
1654 return xAccessible;
1655}
1656
1658{
1659 SolarMutexGuard aGuard;
1660 IsObjectValid();
1661 if (!getAccessibleParent().is())
1662 return;
1663
1664 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1665 if (xAccessibleComponent.is())
1666 {
1667 xAccessibleComponent->grabFocus();
1668 // grab only focus if it does not have the focus and it is not hidden
1669 if (mpViewShell &&
1672 {
1674 }
1675 }
1676}
1677
1678 //===== XAccessibleContext ==============================================
1679
1681sal_Int64 SAL_CALL
1683{
1684 SolarMutexGuard aGuard;
1685 IsObjectValid();
1686 sal_Int64 nCount(1);
1687 if (mpChildrenShapes)
1688 nCount = mpChildrenShapes->GetCount(); // returns the count of the shapes inclusive the table
1689
1690 if (mxTempAcc.is())
1691 ++nCount;
1692
1693 return nCount;
1694}
1695
1697uno::Reference<XAccessible> SAL_CALL
1699{
1700 SolarMutexGuard aGuard;
1701 IsObjectValid();
1702 uno::Reference<XAccessible> xAccessible;
1703 if (nIndex >= 0)
1704 {
1705 sal_Int64 nCount(1);
1706 if (mpChildrenShapes)
1707 {
1708 xAccessible = mpChildrenShapes->Get(nIndex); // returns NULL if it is the table or out of range
1709 nCount = mpChildrenShapes->GetCount(); //there is always a table
1710 }
1711 if (!xAccessible.is())
1712 {
1713 if (nIndex < nCount)
1714 xAccessible = GetAccessibleSpreadsheet();
1715 else if (nIndex == nCount && mxTempAcc.is())
1716 xAccessible = mxTempAcc;
1717 }
1718 }
1719
1720 if (!xAccessible.is())
1721 throw lang::IndexOutOfBoundsException();
1722
1723 return xAccessible;
1724}
1725
1727sal_Int64 SAL_CALL
1729{
1730 SolarMutexGuard aGuard;
1731 sal_Int64 nParentStates = 0;
1732 if (getAccessibleParent().is())
1733 {
1734 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1735 nParentStates = xParentContext->getAccessibleStateSet();
1736 }
1737 sal_Int64 nStateSet = 0;
1738 if (IsDefunc(nParentStates))
1739 nStateSet |= AccessibleStateType::DEFUNC;
1740 else
1741 {
1742 nStateSet |= AccessibleStateType::EDITABLE;
1743 nStateSet |= AccessibleStateType::ENABLED;
1744 nStateSet |= AccessibleStateType::OPAQUE;
1745 if (isShowing())
1746 nStateSet |= AccessibleStateType::SHOWING;
1747 if (isVisible())
1748 nStateSet |= AccessibleStateType::VISIBLE;
1749 }
1750 return nStateSet;
1751}
1752
1753OUString SAL_CALL
1755{
1757
1758 OUString aName = ScResId(STR_ACC_DOC_SPREADSHEET);
1759 ScDocument* pScDoc = GetDocument();
1760 if (!pScDoc)
1761 return aName;
1762
1763 SfxObjectShell* pObjSh = pScDoc->GetDocumentShell();
1764 if (!pObjSh)
1765 return aName;
1766
1767 OUString aFileName;
1768 SfxMedium* pMed = pObjSh->GetMedium();
1769 if (pMed)
1770 aFileName = pMed->GetName();
1771
1772 if (aFileName.isEmpty())
1773 aFileName = pObjSh->GetTitle(SFX_TITLE_APINAME);
1774
1775 if (!aFileName.isEmpty())
1776 {
1777 OUString aReadOnly;
1778 if (pObjSh->IsReadOnly())
1779 aReadOnly = ScResId(STR_ACC_DOC_SPREADSHEET_READONLY);
1780
1781 aName = aFileName + aReadOnly + " - " + aName;
1782 }
1783 return aName;
1784}
1785
1787
1788void SAL_CALL
1790{
1791 SolarMutexGuard aGuard;
1792 IsObjectValid();
1793
1794 if (!(mpChildrenShapes && mpViewShell))
1795 return;
1796
1797 sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table
1798 if (mxTempAcc.is())
1799 ++nCount;
1800 if (nChildIndex < 0 || nChildIndex >= nCount)
1801 throw lang::IndexOutOfBoundsException();
1802
1803 uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1804 if (xAccessible.is())
1805 {
1806 bool bWasTableSelected(IsTableSelected());
1807 mpChildrenShapes->Select(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is too high
1808 if (bWasTableSelected)
1810 }
1811 else
1812 {
1814 }
1815}
1816
1817sal_Bool SAL_CALL
1819{
1820 SolarMutexGuard aGuard;
1821 IsObjectValid();
1822 bool bResult(false);
1823
1824 if (mpChildrenShapes)
1825 {
1826 sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table
1827 if (mxTempAcc.is())
1828 ++nCount;
1829 if (nChildIndex < 0 || nChildIndex >= nCount)
1830 throw lang::IndexOutOfBoundsException();
1831
1832 uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1833 if (xAccessible.is())
1834 {
1835 uno::Reference<drawing::XShape> xShape;
1836 bResult = mpChildrenShapes->IsSelected(nChildIndex, xShape); // throws no lang::IndexOutOfBoundsException if Index is too high
1837 }
1838 else
1839 {
1840 if (mxTempAcc.is() && nChildIndex == nCount)
1841 bResult = true;
1842 else
1843 bResult = IsTableSelected();
1844 }
1845 }
1846 return bResult;
1847}
1848
1849void SAL_CALL
1851{
1852 SolarMutexGuard aGuard;
1853 IsObjectValid();
1854
1855 if (mpChildrenShapes)
1856 mpChildrenShapes->DeselectAll(); //deselects all (also the table)
1857}
1858
1859void SAL_CALL
1861{
1862 SolarMutexGuard aGuard;
1863 IsObjectValid();
1864
1865 if (mpChildrenShapes)
1866 mpChildrenShapes->SelectAll();
1867
1868 // select table after shapes, because while selecting shapes the table will be deselected
1869 if (mpViewShell)
1870 {
1872 }
1873}
1874
1875sal_Int64 SAL_CALL
1877{
1878 SolarMutexGuard aGuard;
1879 IsObjectValid();
1880 sal_Int64 nCount(0);
1881
1882 if (mpChildrenShapes)
1883 nCount = mpChildrenShapes->GetSelectedCount();
1884
1885 if (IsTableSelected())
1886 ++nCount;
1887
1888 if (mxTempAcc.is())
1889 ++nCount;
1890
1891 return nCount;
1892}
1893
1894uno::Reference<XAccessible > SAL_CALL
1896{
1897 SolarMutexGuard aGuard;
1898 IsObjectValid();
1899 uno::Reference<XAccessible> xAccessible;
1900 if (mpChildrenShapes)
1901 {
1902 sal_Int64 nCount(getSelectedAccessibleChildCount()); //all shapes and the table
1903 if (nSelectedChildIndex < 0 || nSelectedChildIndex >= nCount)
1904 throw lang::IndexOutOfBoundsException();
1905
1906 bool bTabMarked(IsTableSelected());
1907
1908 if (mpChildrenShapes)
1909 xAccessible = mpChildrenShapes->GetSelected(nSelectedChildIndex, bTabMarked); // throws no lang::IndexOutOfBoundsException if Index is too high
1910 if (mxTempAcc.is() && nSelectedChildIndex == nCount - 1)
1911 xAccessible = mxTempAcc;
1912 else if (bTabMarked)
1913 xAccessible = GetAccessibleSpreadsheet();
1914 }
1915
1916 OSL_ENSURE(xAccessible.is(), "here should always be an accessible object or an exception thrown");
1917
1918 return xAccessible;
1919}
1920
1921void SAL_CALL
1923{
1924 SolarMutexGuard aGuard;
1925 IsObjectValid();
1926
1927 if (!(mpChildrenShapes && mpViewShell))
1928 return;
1929
1930 sal_Int32 nCount(mpChildrenShapes->GetCount()); // all shapes and the table
1931 if (mxTempAcc.is())
1932 ++nCount;
1933 if (nChildIndex < 0 || nChildIndex >= nCount)
1934 throw lang::IndexOutOfBoundsException();
1935
1936 bool bTabMarked(IsTableSelected());
1937
1938 uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1939 if (xAccessible.is())
1940 {
1941 mpChildrenShapes->Deselect(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is too high
1942 if (bTabMarked)
1943 mpViewShell->SelectAll(); // select the table again
1944 }
1945 else if (bTabMarked)
1947}
1948
1949 //===== XServiceInfo ====================================================
1950
1951OUString SAL_CALL
1953{
1954 return "ScAccessibleDocument";
1955}
1956
1957uno::Sequence< OUString> SAL_CALL
1959{
1960 const css::uno::Sequence<OUString> vals { "com.sun.star.AccessibleSpreadsheetDocumentView" };
1962}
1963
1964//===== XTypeProvider =======================================================
1965
1966uno::Sequence< uno::Type > SAL_CALL ScAccessibleDocument::getTypes()
1967{
1968 return comphelper::concatSequences(ScAccessibleDocumentImpl::getTypes(), ScAccessibleContextBase::getTypes());
1969}
1970
1971uno::Sequence<sal_Int8> SAL_CALL
1973{
1974 return css::uno::Sequence<sal_Int8>();
1975}
1976
1978
1980{
1981 tools::Rectangle aVisRect(GetBoundingBox());
1982
1983 if (mpViewShell)
1984 {
1985 Point aPoint(mpViewShell->GetViewData().GetPixPos(meSplitPos)); // returns a negative Point
1986 aPoint.setX(-aPoint.getX());
1987 aPoint.setY(-aPoint.getY());
1988 aVisRect.SetPos(aPoint);
1989
1991 if (pWin)
1992 aVisRect = pWin->PixelToLogic(aVisRect, pWin->GetDrawMapMode());
1993 }
1994
1995 return aVisRect;
1996}
1997
1999{
2000 SolarMutexGuard aGuard;
2001 IsObjectValid();
2002 return maVisArea;
2003}
2004
2006{
2007 SolarMutexGuard aGuard;
2008 IsObjectValid();
2009 Point aPoint;
2011 if (pWin)
2012 {
2013 aPoint = pWin->LogicToPixel(rPoint, pWin->GetDrawMapMode());
2014 aPoint += pWin->GetWindowExtentsAbsolute().TopLeft();
2015 }
2016 return aPoint;
2017}
2018
2020{
2021 SolarMutexGuard aGuard;
2022 IsObjectValid();
2023 Size aSize;
2025 if (pWin)
2026 aSize = pWin->LogicToPixel(rSize, pWin->GetDrawMapMode());
2027 return aSize;
2028}
2029
2030 //===== internal ========================================================
2031
2033{
2035 if (mpChildrenShapes)
2036 pRelationSet = mpChildrenShapes->GetRelationSet(pAddress);
2037 return pRelationSet;
2038}
2039
2040OUString
2042{
2043 return STR_ACC_DOC_DESCR;
2044}
2045
2046OUString
2048{
2049 SolarMutexGuard aGuard;
2050 IsObjectValid();
2051 OUString sName = ScResId(STR_ACC_DOC_NAME);
2052 sal_Int32 nNumber(sal_Int32(meSplitPos) + 1);
2053 sName += OUString::number(nNumber);
2054 return sName;
2055}
2056
2058{
2059 tools::Rectangle aRect;
2060 if (mpViewShell)
2061 {
2063 if (pWindow)
2064 aRect = pWindow->GetWindowExtentsAbsolute();
2065 }
2066 return aRect;
2067}
2068
2070{
2071 tools::Rectangle aRect;
2072 if (mpViewShell)
2073 {
2075 if (pWindow)
2076 aRect = pWindow->GetWindowExtentsRelative(*pWindow->GetAccessibleParentWindow());
2077 }
2078 return aRect;
2079}
2080
2082{
2083 SCTAB nVisibleTable(0);
2084 if (mpViewShell)
2085 nVisibleTable = mpViewShell->GetViewData().GetTabNo();
2086 return nVisibleTable;
2087}
2088
2089uno::Reference < XAccessible >
2091{
2093 {
2097 }
2099}
2100
2102{
2103 if (mpAccessibleSpreadsheet.is())
2104 {
2105 mpAccessibleSpreadsheet->dispose();
2107 }
2108}
2109
2111{
2112 bool bResult (false);
2113 if(mpViewShell)
2114 {
2115 SCTAB nTab(getVisibleTable());
2116 //#103800#; use a copy of MarkData
2118 ScDocument* pDoc = GetDocument();
2119 if (aMarkData.IsAllMarked( ScRange( 0, 0, nTab, pDoc->MaxCol(), pDoc->MaxRow(), nTab)))
2120 bResult = true;
2121 }
2122 return bResult;
2123}
2124
2125bool ScAccessibleDocument::IsDefunc(sal_Int64 nParentStates)
2126{
2127 return ScAccessibleContextBase::IsDefunc() || (mpViewShell == nullptr) || !getAccessibleParent().is() ||
2128 (nParentStates & AccessibleStateType::DEFUNC);
2129}
2130
2131void ScAccessibleDocument::AddChild(const uno::Reference<XAccessible>& xAcc, bool bFireEvent)
2132{
2133 OSL_ENSURE(!mxTempAcc.is(), "this object should be removed before");
2134 if (xAcc.is())
2135 {
2136 mxTempAcc = xAcc;
2137 if( bFireEvent )
2138 {
2139 AccessibleEventObject aEvent;
2140 aEvent.Source = uno::Reference<XAccessibleContext>(this);
2141 aEvent.EventId = AccessibleEventId::CHILD;
2142 aEvent.NewValue <<= mxTempAcc;
2143 aEvent.IndexHint = getAccessibleChildCount() - 1;
2145 }
2146 }
2147}
2148
2149void ScAccessibleDocument::RemoveChild(const uno::Reference<XAccessible>& xAcc, bool bFireEvent)
2150{
2151 OSL_ENSURE(mxTempAcc.is(), "this object should be added before");
2152 if (!xAcc.is())
2153 return;
2154
2155 OSL_ENSURE(xAcc.get() == mxTempAcc.get(), "only the same object should be removed");
2156 if( bFireEvent )
2157 {
2158 AccessibleEventObject aEvent;
2159 aEvent.Source = uno::Reference<XAccessibleContext>(this);
2160 aEvent.EventId = AccessibleEventId::CHILD;
2161 aEvent.OldValue <<= mxTempAcc;
2162 aEvent.IndexHint = -1;
2164 }
2165 mxTempAcc = nullptr;
2166}
2167
2169{
2170 OUString sName(ScResId(STR_ACC_CELL_NAME));
2171 if (mpViewShell)
2172 {
2173 // Document not needed, because only the cell address, but not the tablename is needed
2174 OUString sAddress(mpViewShell->GetViewData().GetCurPos().Format(ScRefFlags::VALID));
2175 sName = sName.replaceFirst("%1", sAddress);
2176 }
2177 return sName;
2178}
2179
2181{
2182 return OUString();
2183}
2184
2186{
2187 return mpViewShell ? &mpViewShell->GetViewData().GetDocument() : nullptr;
2188}
2189
2191{
2193}
2194
2196{
2198
2199 uno::Any anyAttribute;
2200
2201 sal_uInt16 sheetIndex;
2202 OUString sSheetName;
2203 sheetIndex = getVisibleTable();
2204 if(GetDocument()==nullptr)
2205 return anyAttribute;
2206 GetDocument()->GetName(sheetIndex,sSheetName);
2207 OUString sValue = "page-name:" + sSheetName +
2208 ";page-number:" + OUString::number(sheetIndex+1) +
2209 ";total-pages:" + OUString::number(GetDocument()->GetTableCount()) + ";";
2210 anyAttribute <<= sValue;
2211 return anyAttribute;
2212}
2213
2215{
2216 return sal_Int32(COL_BLACK);
2217}
2218
2220{
2221 SolarMutexGuard aGuard;
2222 IsObjectValid();
2223 return sal_Int32(SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor);
2224}
2225
2226/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
IMPL_LINK(ScAccessibleDocument, WindowChildEventListener, VclWindowEvent &, rEvent, void)
AnyEventRef aEvent
bool IsUpdateLayout() const
void setX(tools::Long nX)
void setY(tools::Long nY)
constexpr tools::Long getX() const
constexpr tools::Long getY() const
virtual sal_Bool SAL_CALL containsPoint(const css::awt::Point &rPoint) override
===== XAccessibleComponent ============================================
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::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.
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:892
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:893
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1084
SfxBroadcaster * GetDrawBroadcaster()
Definition: documen9.cxx:56
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1083
SC_DLLPUBLIC bool GetName(SCTAB nTab, OUString &rName) const
Definition: document.cxx:204
static ScDrawObjData * GetObjData(SdrObject *pObj, bool bCreate=false)
Definition: drwlayer.cxx:2874
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:382
void RemoveAccessibilityObject(SfxListener &rObject)
Definition: tabvwshh.cxx:220
css::uno::Reference< css::drawing::XShapes > getSelectedXShapes()
Definition: viewuno.cxx:824
ScViewData & GetViewData()
Definition: tabview.hxx:344
void Unmark()
Definition: tabview3.cxx:1744
void SelectAll(bool bContinue=false)
Definition: tabview2.cxx:1201
void ActivatePart(ScSplitPos eWhich)
Definition: tabview3.cxx:2907
vcl::Window * GetWindowByPos(ScSplitPos ePos) const
Definition: tabview.hxx:382
ScMarkData & GetMarkData()
Definition: viewdata.cxx:3146
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:2284
ScAddress GetCurPos() const
Definition: viewdata.cxx:4119
bool HasEditView(ScSplitPos eWhich) const
Definition: viewdata.hxx:582
ScDrawView * GetScDrawView()
Definition: viewdata.cxx:3174
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
tools::Rectangle GetWindowExtentsAbsolute() const
sal_uInt16 GetAccessibleRole() const
Point LogicToPixel(const Point &rLogicPt) const
sal_uInt16 GetChildCount() const
bool HasFocus() const
vcl::Window * GetAccessibleParentWindow() 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)
tools::Rectangle GetWindowExtentsRelative(const vcl::Window &rRelativeWindow) const
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
OUString sName
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
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:247
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