fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / Accessibility / AccessibleDocument.cxx
blob4cec4681b857149bcf07338e303eb3a7e8879e4e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 /* Somehow, under same circumstances, MSVC creates object code for 2
21 * inlined functions. Nobody here uses them, so simply define them away
22 * so that there be no dupplicate symbols anymore.
24 * The symbols "extents" and "indices" come from boost::multi_array.
27 #ifdef indices
28 #undef indices
29 #endif
30 #define indices dummy1_indices
32 #ifdef extents
33 #undef extents
34 #endif
35 #define extents dummy1_extents
37 #include "AccessibleDocument.hxx"
38 #include "AccessibleSpreadsheet.hxx"
39 #include "tabvwsh.hxx"
40 #include "AccessibilityHints.hxx"
41 #include "document.hxx"
42 #include "drwlayer.hxx"
43 #include "shapeuno.hxx"
44 #include "DrawModelBroadcaster.hxx"
45 #include "drawview.hxx"
46 #include "gridwin.hxx"
47 #include "AccessibleEditObject.hxx"
48 #include "userdat.hxx"
49 #include "scresid.hxx"
50 #include "sc.hrc"
51 #include "table.hxx"
52 #include "markdata.hxx"
54 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
55 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
56 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
57 #include <com/sun/star/view/XSelectionSupplier.hpp>
58 #include <com/sun/star/drawing/ShapeCollection.hpp>
59 #include <com/sun/star/drawing/XShape.hpp>
60 #include <com/sun/star/drawing/XShapes.hpp>
62 #include <unotools/accessiblestatesethelper.hxx>
63 #include <tools/gen.hxx>
64 #include <svx/svdpage.hxx>
65 #include <svx/svdobj.hxx>
66 #include <svx/ShapeTypeHandler.hxx>
67 #include <svx/AccessibleShape.hxx>
68 #include <svx/AccessibleShapeTreeInfo.hxx>
69 #include <svx/AccessibleShapeInfo.hxx>
70 #include <comphelper/sequence.hxx>
71 #include <comphelper/servicehelper.hxx>
72 #include <sfx2/viewfrm.hxx>
73 #include <sfx2/docfile.hxx>
74 #include <svx/unoshape.hxx>
75 #include <unotools/accessiblerelationsethelper.hxx>
76 #include <toolkit/helper/convert.hxx>
77 #include <vcl/svapp.hxx>
79 #include <svx/AccessibleControlShape.hxx>
80 #include <svx/SvxShapeTypes.hxx>
81 #include <sfx2/objsh.hxx>
82 #include <editeng/editview.hxx>
83 #include <editeng/editeng.hxx>
85 #include <list>
86 #include <algorithm>
88 #include "AccessibleCell.hxx"
90 #include <svx/unoapi.hxx>
91 #include "scmod.hxx"
93 #ifdef indices
94 #undef indices
95 #endif
97 #ifdef extents
98 #undef extents
99 #endif
101 using namespace ::com::sun::star;
102 using namespace ::com::sun::star::accessibility;
103 using ::std::for_each;
105 //===== internal ========================================================
107 struct ScAccessibleShapeData
109 ScAccessibleShapeData() : pAccShape(NULL), pRelationCell(NULL), bSelected(false), bSelectable(true) {}
110 ~ScAccessibleShapeData();
111 mutable ::accessibility::AccessibleShape* pAccShape;
112 mutable ScAddress* pRelationCell; // if it is NULL this shape is anchored on the table
113 com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape;
114 mutable bool bSelected;
115 bool bSelectable;
118 ScAccessibleShapeData::~ScAccessibleShapeData()
120 if (pAccShape)
122 pAccShape->dispose();
123 pAccShape->release();
127 struct ScShapeDataLess
129 OUString msLayerId;
130 OUString msZOrder;
131 ScShapeDataLess()
132 : msLayerId( "LayerID" ),
133 msZOrder( "ZOrder" )
136 static void ConvertLayerId(sal_Int16& rLayerID) // changes the number of the LayerId so it the accessibility order
138 switch (rLayerID)
140 case SC_LAYER_FRONT:
141 rLayerID = 1;
142 break;
143 case SC_LAYER_BACK:
144 rLayerID = 0;
145 break;
146 case SC_LAYER_INTERN:
147 rLayerID = 2;
148 break;
149 case SC_LAYER_CONTROLS:
150 rLayerID = 3;
151 break;
154 bool LessThanSheet(const ScAccessibleShapeData* pData) const
156 bool bResult(false);
157 uno::Reference< beans::XPropertySet> xProps(pData->xShape, uno::UNO_QUERY);
158 if (xProps.is())
160 uno::Any aPropAny = xProps->getPropertyValue(msLayerId);
161 sal_Int16 nLayerID = 0;
162 if( (aPropAny >>= nLayerID) )
164 if (nLayerID == SC_LAYER_BACK)
165 bResult = true;
168 return bResult;
170 bool operator()(const ScAccessibleShapeData* pData1, const ScAccessibleShapeData* pData2) const
172 bool bResult(false);
173 if (pData1 && pData2)
175 uno::Reference< beans::XPropertySet> xProps1(pData1->xShape, uno::UNO_QUERY);
176 uno::Reference< beans::XPropertySet> xProps2(pData2->xShape, uno::UNO_QUERY);
177 if (xProps1.is() && xProps2.is())
179 uno::Any aPropAny1 = xProps1->getPropertyValue(msLayerId);
180 uno::Any aPropAny2 = xProps2->getPropertyValue(msLayerId);
181 sal_Int16 nLayerID1(0);
182 sal_Int16 nLayerID2(0);
183 if( (aPropAny1 >>= nLayerID1) && (aPropAny2 >>= nLayerID2) )
185 if (nLayerID1 == nLayerID2)
187 uno::Any aAny1 = xProps1->getPropertyValue(msZOrder);
188 sal_Int32 nZOrder1 = 0;
189 uno::Any aAny2 = xProps2->getPropertyValue(msZOrder);
190 sal_Int32 nZOrder2 = 0;
191 if ( (aAny1 >>= nZOrder1) && (aAny2 >>= nZOrder2) )
192 bResult = (nZOrder1 < nZOrder2);
194 else
196 ConvertLayerId(nLayerID1);
197 ConvertLayerId(nLayerID2);
198 bResult = (nLayerID1 < nLayerID2);
203 else if (pData1 && !pData2)
204 bResult = LessThanSheet(pData1);
205 else if (!pData1 && pData2)
206 bResult = !LessThanSheet(pData2);
207 else
208 bResult = false;
209 return bResult;
213 struct DeselectShape
215 void operator() (const ScAccessibleShapeData* pAccShapeData) const
217 if (pAccShapeData)
219 pAccShapeData->bSelected = false;
220 if (pAccShapeData->pAccShape)
221 pAccShapeData->pAccShape->ResetState(AccessibleStateType::SELECTED);
226 struct SelectShape
228 uno::Reference < drawing::XShapes > xShapes;
229 SelectShape(uno::Reference<drawing::XShapes>& xTemp) : xShapes(xTemp) {}
230 void operator() (const ScAccessibleShapeData* pAccShapeData) const
232 if (pAccShapeData && pAccShapeData->bSelectable)
234 pAccShapeData->bSelected = true;
235 if (pAccShapeData->pAccShape)
236 pAccShapeData->pAccShape->SetState(AccessibleStateType::SELECTED);
237 if (xShapes.is())
238 xShapes->add(pAccShapeData->xShape);
243 struct Destroy
245 void operator() (ScAccessibleShapeData* pData)
247 if (pData)
248 DELETEZ(pData);
252 class ScChildrenShapes : public SfxListener,
253 public ::accessibility::IAccessibleParent
255 public:
256 ScChildrenShapes(ScAccessibleDocument* pAccessibleDocument, ScTabViewShell* pViewShell, ScSplitPos eSplitPos);
257 virtual ~ScChildrenShapes();
259 ///===== SfxListener =====================================================
261 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) SAL_OVERRIDE;
263 ///===== IAccessibleParent ===============================================
265 virtual bool ReplaceChild (
266 ::accessibility::AccessibleShape* pCurrentChild,
267 const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape,
268 const long _nIndex,
269 const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo
270 ) throw (::com::sun::star::uno::RuntimeException) SAL_OVERRIDE;
272 virtual ::accessibility::AccessibleControlShape* GetAccControlShapeFromModel
273 (::com::sun::star::beans::XPropertySet* pSet)
274 throw (::com::sun::star::uno::RuntimeException) SAL_OVERRIDE;
275 virtual ::com::sun::star::uno::Reference<
276 ::com::sun::star::accessibility::XAccessible>
277 GetAccessibleCaption (const ::com::sun::star::uno::Reference<
278 ::com::sun::star::drawing::XShape>& xShape)
279 throw (::com::sun::star::uno::RuntimeException) SAL_OVERRIDE;
280 ///===== Internal ========================================================
281 void SetDrawBroadcaster();
283 sal_Int32 GetCount() const;
284 uno::Reference< XAccessible > Get(const ScAccessibleShapeData* pData) const;
285 uno::Reference< XAccessible > Get(sal_Int32 nIndex) const;
286 uno::Reference< XAccessible > GetAt(const awt::Point& rPoint) const;
288 // gets the index of the shape starting on 0 (without the index of the table)
289 // returns the selected shape
290 bool IsSelected(sal_Int32 nIndex,
291 com::sun::star::uno::Reference<com::sun::star::drawing::XShape>& rShape) const;
293 bool SelectionChanged();
295 void Select(sal_Int32 nIndex);
296 void DeselectAll(); // deselect also the table
297 void SelectAll();
298 sal_Int32 GetSelectedCount() const;
299 uno::Reference< XAccessible > GetSelected(sal_Int32 nSelectedChildIndex, bool bTabSelected) const;
300 void Deselect(sal_Int32 nChildIndex);
302 SdrPage* GetDrawPage() const;
304 utl::AccessibleRelationSetHelper* GetRelationSet(const ScAddress* pAddress) const;
306 void VisAreaChanged() const;
307 private:
308 typedef std::vector<ScAccessibleShapeData*> SortedShapes;
310 mutable SortedShapes maZOrderedShapes; // a null pointer represents the sheet in the correct order
312 mutable ::accessibility::AccessibleShapeTreeInfo maShapeTreeInfo;
313 mutable com::sun::star::uno::Reference<com::sun::star::view::XSelectionSupplier> xSelectionSupplier;
314 mutable size_t mnSdrObjCount;
315 mutable sal_uInt32 mnShapesSelected;
316 ScTabViewShell* mpViewShell;
317 ScAccessibleDocument* mpAccessibleDocument;
318 ScSplitPos meSplitPos;
320 void FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const;
321 bool FindSelectedShapesChanges(const com::sun::star::uno::Reference<com::sun::star::drawing::XShapes>& xShapes, bool bCommitChange) const;
322 void FillSelectionSupplier() const;
324 ScAddress* GetAnchor(const uno::Reference<drawing::XShape>& xShape) const;
325 uno::Reference<XAccessibleRelationSet> GetRelationSet(const ScAccessibleShapeData* pData) const;
326 void CheckWhetherAnchorChanged(const uno::Reference<drawing::XShape>& xShape) const;
327 void SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const;
328 void AddShape(const uno::Reference<drawing::XShape>& xShape, bool bCommitChange) const;
329 void RemoveShape(const uno::Reference<drawing::XShape>& xShape) const;
331 bool FindShape(const uno::Reference<drawing::XShape>& xShape, SortedShapes::iterator& rItr) const;
333 static sal_Int8 Compare(const ScAccessibleShapeData* pData1,
334 const ScAccessibleShapeData* pData2);
337 ScChildrenShapes::ScChildrenShapes(ScAccessibleDocument* pAccessibleDocument, ScTabViewShell* pViewShell, ScSplitPos eSplitPos)
339 mnShapesSelected(0),
340 mpViewShell(pViewShell),
341 mpAccessibleDocument(pAccessibleDocument),
342 meSplitPos(eSplitPos)
344 FillSelectionSupplier();
345 maZOrderedShapes.push_back(NULL); // add an element which represents the table
347 GetCount(); // fill list with filtered shapes (no internal shapes)
349 if (mnShapesSelected)
351 //set flag on every selected shape
352 if (!xSelectionSupplier.is())
353 throw uno::RuntimeException();
355 uno::Reference<drawing::XShapes> xShapes(xSelectionSupplier->getSelection(), uno::UNO_QUERY);
356 if (xShapes.is())
357 FindSelectedShapesChanges(xShapes, false);
359 if (pViewShell)
361 ScViewData& rViewData = pViewShell->GetViewData();
362 SfxBroadcaster* pDrawBC = rViewData.GetDocument()->GetDrawBroadcaster();
363 if (pDrawBC)
365 StartListening(*pDrawBC);
367 maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(rViewData.GetDocument()->GetDrawLayer()) );
368 maShapeTreeInfo.SetSdrView(rViewData.GetScDrawView());
369 maShapeTreeInfo.SetController(NULL);
370 maShapeTreeInfo.SetWindow(pViewShell->GetWindowByPos(meSplitPos));
371 maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
376 ScChildrenShapes::~ScChildrenShapes()
378 std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), Destroy());
379 if (mpViewShell)
381 SfxBroadcaster* pDrawBC = mpViewShell->GetViewData().GetDocument()->GetDrawBroadcaster();
382 if (pDrawBC)
383 EndListening(*pDrawBC);
387 void ScChildrenShapes::SetDrawBroadcaster()
389 if (mpViewShell)
391 ScViewData& rViewData = mpViewShell->GetViewData();
392 SfxBroadcaster* pDrawBC = rViewData.GetDocument()->GetDrawBroadcaster();
393 if (pDrawBC)
395 StartListening(*pDrawBC, true);
397 maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(rViewData.GetDocument()->GetDrawLayer()) );
398 maShapeTreeInfo.SetSdrView(rViewData.GetScDrawView());
399 maShapeTreeInfo.SetController(NULL);
400 maShapeTreeInfo.SetWindow(mpViewShell->GetWindowByPos(meSplitPos));
401 maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
406 void ScChildrenShapes::Notify(SfxBroadcaster&, const SfxHint& rHint)
408 const SdrHint* pSdrHint = dynamic_cast<const SdrHint*>(&rHint);
409 if (pSdrHint)
411 SdrObject* pObj = const_cast<SdrObject*>(pSdrHint->GetObject());
412 if (pObj && /*(pObj->GetLayer() != SC_LAYER_INTERN) && */(pObj->GetPage() == GetDrawPage()) &&
413 (pObj->GetPage() == pObj->GetObjList()) ) //only do something if the object lies direct on the page
415 switch (pSdrHint->GetKind())
417 case HINT_OBJCHG : // Objekt geaendert
419 uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
420 if (xShape.is())
422 ScShapeDataLess aLess;
423 std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), aLess); // sort, because the z index or layer could be changed
424 CheckWhetherAnchorChanged(xShape);
427 break;
428 case HINT_OBJINSERTED : // Neues Zeichenobjekt eingefuegt
430 uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
431 if (xShape.is())
432 AddShape(xShape, true);
434 break;
435 case HINT_OBJREMOVED : // Zeichenobjekt aus Liste entfernt
437 uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
438 if (xShape.is())
439 RemoveShape(xShape);
441 break;
442 default :
444 // other events are not interesting
446 break;
452 bool ScChildrenShapes::ReplaceChild (::accessibility::AccessibleShape* pCurrentChild,
453 const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape,
454 const long _nIndex, const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo)
455 throw (uno::RuntimeException)
457 // create the new child
458 ::accessibility::AccessibleShape* pReplacement = ::accessibility::ShapeTypeHandler::Instance().CreateAccessibleObject (
459 ::accessibility::AccessibleShapeInfo ( _rxShape, pCurrentChild->getAccessibleParent(), this, _nIndex ),
460 _rShapeTreeInfo
462 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xNewChild( pReplacement ); // keep this alive (do this before calling Init!)
463 if ( pReplacement )
464 pReplacement->Init();
466 bool bResult(false);
467 if (pReplacement)
469 OSL_ENSURE(pCurrentChild->GetXShape().get() == pReplacement->GetXShape().get(), "XShape changes and should be inserted sorted");
470 SortedShapes::iterator aItr;
472 if (FindShape(pCurrentChild->GetXShape(), aItr) || (aItr != maZOrderedShapes.end() && (*aItr)))
474 if ((*aItr)->pAccShape)
476 OSL_ENSURE((*aItr)->pAccShape == pCurrentChild, "wrong child found");
477 AccessibleEventObject aEvent;
478 aEvent.EventId = AccessibleEventId::CHILD;
479 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
480 aEvent.OldValue <<= uno::makeAny(uno::Reference<XAccessible>(pCurrentChild));
482 mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
484 pCurrentChild->dispose();
486 (*aItr)->pAccShape = pReplacement;
487 AccessibleEventObject aEvent;
488 aEvent.EventId = AccessibleEventId::CHILD;
489 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
490 aEvent.NewValue <<= uno::makeAny(uno::Reference<XAccessible>(pReplacement));
492 mpAccessibleDocument->CommitChange(aEvent); // child is new - event
493 bResult = true;
496 return bResult;
499 ::accessibility::AccessibleControlShape * ScChildrenShapes::GetAccControlShapeFromModel(::com::sun::star::beans::XPropertySet* pSet) throw (::com::sun::star::uno::RuntimeException)
501 sal_Int32 count = GetCount();
502 for (sal_Int32 index=0;index<count;index++)
504 ScAccessibleShapeData* pShape = maZOrderedShapes[index];
505 if (pShape)
507 ::accessibility::AccessibleShape* pAccShape = pShape->pAccShape;
508 if (pAccShape && ::accessibility::ShapeTypeHandler::Instance().GetTypeId (pAccShape->GetXShape()) == ::accessibility::DRAWING_CONTROL)
510 ::accessibility::AccessibleControlShape *pCtlAccShape = static_cast < ::accessibility::AccessibleControlShape* >(pAccShape);
511 if (pCtlAccShape && pCtlAccShape->GetControlModel() == pSet)
512 return pCtlAccShape;
516 return NULL;
519 ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessible >
520 ScChildrenShapes::GetAccessibleCaption (const ::com::sun::star::uno::Reference < ::com::sun::star::drawing::XShape>& xShape)
521 throw (::com::sun::star::uno::RuntimeException)
523 sal_Int32 count = GetCount();
524 for (sal_Int32 index=0;index<count;index++)
526 ScAccessibleShapeData* pShape = maZOrderedShapes[index];
527 if (pShape && pShape->xShape == xShape )
529 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xNewChild( pShape->pAccShape );
530 if(xNewChild.get())
531 return xNewChild;
534 return NULL;
537 sal_Int32 ScChildrenShapes::GetCount() const
539 SdrPage* pDrawPage = GetDrawPage();
540 if (pDrawPage && (maZOrderedShapes.size() == 1)) // the table is always in
542 mnSdrObjCount = pDrawPage->GetObjCount();
543 maZOrderedShapes.reserve(mnSdrObjCount + 1); // the table is always in
544 for (size_t i = 0; i < mnSdrObjCount; ++i)
546 SdrObject* pObj = pDrawPage->GetObj(i);
547 if (pObj/* && (pObj->GetLayer() != SC_LAYER_INTERN)*/)
549 uno::Reference< drawing::XShape > xShape (pObj->getUnoShape(), uno::UNO_QUERY);
550 AddShape(xShape, false); //inserts in the correct order
554 return maZOrderedShapes.size();
557 uno::Reference< XAccessible > ScChildrenShapes::Get(const ScAccessibleShapeData* pData) const
559 if (!pData)
560 return NULL;
562 if (!pData->pAccShape)
564 ::accessibility::ShapeTypeHandler& rShapeHandler = ::accessibility::ShapeTypeHandler::Instance();
565 ::accessibility::AccessibleShapeInfo aShapeInfo(pData->xShape, mpAccessibleDocument, const_cast<ScChildrenShapes*>(this));
566 pData->pAccShape = rShapeHandler.CreateAccessibleObject(
567 aShapeInfo, maShapeTreeInfo);
568 if (pData->pAccShape)
570 pData->pAccShape->acquire();
571 pData->pAccShape->Init();
572 if (pData->bSelected)
573 pData->pAccShape->SetState(AccessibleStateType::SELECTED);
574 if (!pData->bSelectable)
575 pData->pAccShape->ResetState(AccessibleStateType::SELECTABLE);
576 pData->pAccShape->SetRelationSet(GetRelationSet(pData));
579 return pData->pAccShape;
582 uno::Reference< XAccessible > ScChildrenShapes::Get(sal_Int32 nIndex) const
584 if (maZOrderedShapes.size() <= 1)
585 GetCount(); // fill list with filtered shapes (no internal shapes)
587 if (static_cast<sal_uInt32>(nIndex) >= maZOrderedShapes.size())
588 return NULL;
590 return Get(maZOrderedShapes[nIndex]);
593 uno::Reference< XAccessible > ScChildrenShapes::GetAt(const awt::Point& rPoint) const
595 uno::Reference<XAccessible> xAccessible;
596 if(mpViewShell)
598 sal_Int32 i(maZOrderedShapes.size() - 1);
599 bool bFound(false);
600 while (!bFound && i >= 0)
602 ScAccessibleShapeData* pShape = maZOrderedShapes[i];
603 if (pShape)
605 if (!pShape->pAccShape)
606 Get(pShape);
608 if (pShape->pAccShape)
610 Point aPoint(VCLPoint(rPoint));
611 aPoint -= VCLRectangle(pShape->pAccShape->getBounds()).TopLeft();
612 if (pShape->pAccShape->containsPoint(AWTPoint(aPoint)))
614 xAccessible = pShape->pAccShape;
615 bFound = true;
618 else
620 OSL_FAIL("I should have an accessible shape now!");
623 else
624 bFound = true; // this is the sheet and it lies before the rest of the shapes which are background shapes
626 --i;
629 return xAccessible;
632 bool ScChildrenShapes::IsSelected(sal_Int32 nIndex,
633 uno::Reference<drawing::XShape>& rShape) const
635 bool bResult (false);
636 if (maZOrderedShapes.size() <= 1)
637 GetCount(); // fill list with filtered shapes (no internal shapes)
639 if (!xSelectionSupplier.is())
640 throw uno::RuntimeException();
642 if (!maZOrderedShapes[nIndex])
643 return false;
645 bResult = maZOrderedShapes[nIndex]->bSelected;
646 rShape = maZOrderedShapes[nIndex]->xShape;
648 #if OSL_DEBUG_LEVEL > 0 // test whether it is truly selected by a slower method
649 uno::Reference< drawing::XShape > xReturnShape;
650 bool bDebugResult(false);
651 uno::Reference<container::XIndexAccess> xIndexAccess;
652 xSelectionSupplier->getSelection() >>= xIndexAccess;
654 if (xIndexAccess.is())
656 sal_Int32 nCount(xIndexAccess->getCount());
657 if (nCount)
659 uno::Reference< drawing::XShape > xShape;
660 uno::Reference< drawing::XShape > xIndexShape = maZOrderedShapes[nIndex]->xShape;
661 sal_Int32 i(0);
662 while (!bDebugResult && (i < nCount))
664 xIndexAccess->getByIndex(i) >>= xShape;
665 if (xShape.is() && (xIndexShape.get() == xShape.get()))
667 bDebugResult = true;
668 xReturnShape = xShape;
670 else
671 ++i;
675 OSL_ENSURE((bResult == bDebugResult) && ((bResult && (rShape.get() == xReturnShape.get())) || !bResult), "found the wrong shape or result");
676 #endif
678 return bResult;
681 bool ScChildrenShapes::SelectionChanged()
683 bool bResult(false);
684 if (!xSelectionSupplier.is())
685 throw uno::RuntimeException();
687 uno::Reference<drawing::XShapes> xShapes(xSelectionSupplier->getSelection(), uno::UNO_QUERY);
689 bResult = FindSelectedShapesChanges(xShapes, true);
691 return bResult;
694 void ScChildrenShapes::Select(sal_Int32 nIndex)
696 if (maZOrderedShapes.size() <= 1)
697 GetCount(); // fill list with filtered shapes (no internal shapes)
699 if (!xSelectionSupplier.is())
700 throw uno::RuntimeException();
702 if (!maZOrderedShapes[nIndex])
703 return;
705 uno::Reference<drawing::XShape> xShape;
706 if (!IsSelected(nIndex, xShape) && maZOrderedShapes[nIndex]->bSelectable)
708 uno::Reference<drawing::XShapes> xShapes;
709 xSelectionSupplier->getSelection() >>= xShapes;
711 if (!xShapes.is())
712 xShapes = drawing::ShapeCollection::create(
713 comphelper::getProcessComponentContext());
715 xShapes->add(maZOrderedShapes[nIndex]->xShape);
719 xSelectionSupplier->select(uno::makeAny(xShapes));
720 maZOrderedShapes[nIndex]->bSelected = true;
721 if (maZOrderedShapes[nIndex]->pAccShape)
722 maZOrderedShapes[nIndex]->pAccShape->SetState(AccessibleStateType::SELECTED);
724 catch (lang::IllegalArgumentException&)
730 void ScChildrenShapes::DeselectAll()
732 if (!xSelectionSupplier.is())
733 throw uno::RuntimeException();
735 bool bSomethingSelected(true);
738 xSelectionSupplier->select(uno::Any()); //deselects all
740 catch (lang::IllegalArgumentException&)
742 OSL_FAIL("nothing selected before");
743 bSomethingSelected = false;
746 if (bSomethingSelected)
747 std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), DeselectShape());
750 void ScChildrenShapes::SelectAll()
752 if (!xSelectionSupplier.is())
753 throw uno::RuntimeException();
755 if (maZOrderedShapes.size() <= 1)
756 GetCount(); // fill list with filtered shapes (no internal shapes)
758 if (maZOrderedShapes.size() > 1)
760 uno::Reference<drawing::XShapes> xShapes = drawing::ShapeCollection::create(
761 comphelper::getProcessComponentContext());
765 std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), SelectShape(xShapes));
766 xSelectionSupplier->select(uno::makeAny(xShapes));
768 catch (lang::IllegalArgumentException&)
770 SelectionChanged(); // find all selected shapes and set the flags
775 void ScChildrenShapes::FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const
777 uno::Reference<container::XIndexAccess> xIndexAccess;
778 xSelectionSupplier->getSelection() >>= xIndexAccess;
780 if (xIndexAccess.is())
782 sal_uInt32 nCount(xIndexAccess->getCount());
783 for (sal_uInt32 i = 0; i < nCount; ++i)
785 uno::Reference<drawing::XShape> xShape;
786 xIndexAccess->getByIndex(i) >>= xShape;
787 if (xShape.is())
788 rShapes.push_back(xShape);
793 sal_Int32 ScChildrenShapes::GetSelectedCount() const
795 if (!xSelectionSupplier.is())
796 throw uno::RuntimeException();
798 std::vector < uno::Reference < drawing::XShape > > aShapes;
799 FillShapes(aShapes);
801 return aShapes.size();
804 uno::Reference< XAccessible > ScChildrenShapes::GetSelected(sal_Int32 nSelectedChildIndex, bool bTabSelected) const
806 uno::Reference< XAccessible > xAccessible;
808 if (maZOrderedShapes.size() <= 1)
809 GetCount(); // fill list with shapes
811 if (!bTabSelected)
813 std::vector < uno::Reference < drawing::XShape > > aShapes;
814 FillShapes(aShapes);
816 if (nSelectedChildIndex < 0 || static_cast<size_t>(nSelectedChildIndex) >= aShapes.size())
817 return xAccessible;
819 SortedShapes::iterator aItr;
820 if (FindShape(aShapes[nSelectedChildIndex], aItr))
821 xAccessible = Get(aItr - maZOrderedShapes.begin());
823 else
825 SortedShapes::iterator aItr = maZOrderedShapes.begin();
826 SortedShapes::iterator aEndItr = maZOrderedShapes.end();
827 bool bFound(false);
828 while(!bFound && aItr != aEndItr)
830 if (*aItr)
832 if ((*aItr)->bSelected)
834 if (nSelectedChildIndex == 0)
835 bFound = true;
836 else
837 --nSelectedChildIndex;
840 else
842 if (nSelectedChildIndex == 0)
843 bFound = true;
844 else
845 --nSelectedChildIndex;
847 if (!bFound)
848 ++aItr;
850 if (bFound && *aItr)
851 xAccessible = (*aItr)->pAccShape;
854 return xAccessible;
857 void ScChildrenShapes::Deselect(sal_Int32 nChildIndex)
859 uno::Reference<drawing::XShape> xShape;
860 if (IsSelected(nChildIndex, xShape)) // returns false if it is the sheet
862 if (xShape.is())
864 uno::Reference<drawing::XShapes> xShapes;
865 xSelectionSupplier->getSelection() >>= xShapes;
866 if (xShapes.is())
867 xShapes->remove(xShape);
871 xSelectionSupplier->select(uno::makeAny(xShapes));
873 catch (lang::IllegalArgumentException&)
875 OSL_FAIL("something not selectable");
878 maZOrderedShapes[nChildIndex]->bSelected = false;
879 if (maZOrderedShapes[nChildIndex]->pAccShape)
880 maZOrderedShapes[nChildIndex]->pAccShape->ResetState(AccessibleStateType::SELECTED);
885 SdrPage* ScChildrenShapes::GetDrawPage() const
887 SCTAB nTab(mpAccessibleDocument->getVisibleTable());
888 SdrPage* pDrawPage = NULL;
889 if (mpViewShell)
891 ScViewData& rViewData = mpViewShell->GetViewData();
892 ScDocument* pDoc = rViewData.GetDocument();
893 if (pDoc && pDoc->GetDrawLayer())
895 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
896 if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab))
897 pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(static_cast<sal_Int16>(nTab)));
900 return pDrawPage;
903 struct SetRelation
905 const ScChildrenShapes* mpChildrenShapes;
906 mutable utl::AccessibleRelationSetHelper* mpRelationSet;
907 const ScAddress* mpAddress;
908 SetRelation(const ScChildrenShapes* pChildrenShapes, const ScAddress* pAddress)
910 mpChildrenShapes(pChildrenShapes),
911 mpRelationSet(NULL),
912 mpAddress(pAddress)
915 void operator() (const ScAccessibleShapeData* pAccShapeData) const
917 if (pAccShapeData &&
918 ((!pAccShapeData->pRelationCell && !mpAddress) ||
919 (pAccShapeData->pRelationCell && mpAddress && (*(pAccShapeData->pRelationCell) == *mpAddress))))
921 if (!mpRelationSet)
922 mpRelationSet = new utl::AccessibleRelationSetHelper();
924 AccessibleRelation aRelation;
925 aRelation.TargetSet.realloc(1);
926 aRelation.TargetSet[0] = mpChildrenShapes->Get(pAccShapeData);
927 aRelation.RelationType = AccessibleRelationType::CONTROLLER_FOR;
929 mpRelationSet->AddRelation(aRelation);
934 utl::AccessibleRelationSetHelper* ScChildrenShapes::GetRelationSet(const ScAddress* pAddress) const
936 SetRelation aSetRelation(this, pAddress);
937 ::std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), aSetRelation);
938 return aSetRelation.mpRelationSet;
941 bool ScChildrenShapes::FindSelectedShapesChanges(const uno::Reference<drawing::XShapes>& xShapes, bool /* bCommitChange */) const
943 bool bResult(false);
944 SortedShapes aShapesList;
945 uno::Reference<container::XIndexAccess> xIndexAcc(xShapes, uno::UNO_QUERY);
946 if (xIndexAcc.is())
948 mnShapesSelected = xIndexAcc->getCount();
949 for (sal_uInt32 i = 0; i < mnShapesSelected; ++i)
951 uno::Reference< drawing::XShape > xShape;
952 xIndexAcc->getByIndex(i) >>= xShape;
953 if (xShape.is())
955 ScAccessibleShapeData* pShapeData = new ScAccessibleShapeData();
956 pShapeData->xShape = xShape;
957 aShapesList.push_back(pShapeData);
961 else
962 mnShapesSelected = 0;
963 SdrObject *pFocusedObj = NULL;
964 if( mnShapesSelected == 1 && aShapesList.size() == 1)
966 pFocusedObj = GetSdrObjectFromXShape(aShapesList[0]->xShape);
968 ScShapeDataLess aLess;
969 std::sort(aShapesList.begin(), aShapesList.end(), aLess);
970 SortedShapes vecSelectedShapeAdd;
971 SortedShapes vecSelectedShapeRemove;
972 bool bHasSelect=false;
973 SortedShapes::iterator aXShapesItr(aShapesList.begin());
974 SortedShapes::const_iterator aXShapesEndItr(aShapesList.end());
975 SortedShapes::iterator aDataItr(maZOrderedShapes.begin());
976 SortedShapes::const_iterator aDataEndItr(maZOrderedShapes.end());
977 SortedShapes::const_iterator aFocusedItr = aDataEndItr;
978 while((aDataItr != aDataEndItr))
980 if (*aDataItr) // is it really a shape or only the sheet
982 sal_Int8 nComp(0);
983 if (aXShapesItr == aXShapesEndItr)
984 nComp = -1; // simulate that the Shape is lower, so the selection state will be removed
985 else
986 nComp = Compare(*aDataItr, *aXShapesItr);
987 if (nComp == 0)
989 if (!(*aDataItr)->bSelected)
991 (*aDataItr)->bSelected = true;
992 if ((*aDataItr)->pAccShape)
994 (*aDataItr)->pAccShape->SetState(AccessibleStateType::SELECTED);
995 (*aDataItr)->pAccShape->SetState(AccessibleStateType::FOCUSED);
996 bResult = true;
997 vecSelectedShapeAdd.push_back((*aDataItr));
999 aFocusedItr = aDataItr;
1001 else
1003 bHasSelect = true;
1005 ++aDataItr;
1006 ++aXShapesItr;
1008 else if (nComp < 0)
1010 if ((*aDataItr)->bSelected)
1012 (*aDataItr)->bSelected = false;
1013 if ((*aDataItr)->pAccShape)
1015 (*aDataItr)->pAccShape->ResetState(AccessibleStateType::SELECTED);
1016 (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED);
1017 bResult = true;
1018 vecSelectedShapeRemove.push_back(*aDataItr);
1021 ++aDataItr;
1023 else
1025 OSL_FAIL("here is a selected shape which is not in the childlist");
1026 ++aXShapesItr;
1027 --mnShapesSelected;
1030 else
1031 ++aDataItr;
1033 bool bWinFocus=false;
1034 if (mpViewShell)
1036 ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1037 if (pWin)
1039 bWinFocus = pWin->HasFocus();
1042 const SdrMarkList* pMarkList = NULL;
1043 SdrObject* pMarkedObj = NULL;
1044 SdrObject* pUpObj = NULL;
1045 bool bIsFocuseMarked = true;
1046 if( mpViewShell && mnShapesSelected == 1 && bWinFocus)
1048 ScDrawView* pScDrawView = mpViewShell->GetViewData().GetScDrawView();
1049 if( pScDrawView )
1051 if( pScDrawView->GetMarkedObjectList().GetMarkCount() == 1 )
1053 pMarkList = &(pScDrawView->GetMarkedObjectList());
1054 pMarkedObj = pMarkList->GetMark(0)->GetMarkedSdrObj();
1055 uno::Reference< drawing::XShape > xMarkedXShape (pMarkedObj->getUnoShape(), uno::UNO_QUERY);
1056 if( aFocusedItr != aDataEndItr &&
1057 (*aFocusedItr)->xShape.is() &&
1058 xMarkedXShape.is() &&
1059 (*aFocusedItr)->xShape != xMarkedXShape )
1060 bIsFocuseMarked = false;
1064 //if ((aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape && (mnShapesSelected == 1))
1065 if ( bIsFocuseMarked && (aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape && (mnShapesSelected == 1) && bWinFocus)
1067 (*aFocusedItr)->pAccShape->SetState(AccessibleStateType::FOCUSED);
1069 else if( pFocusedObj && bWinFocus && pMarkList && pMarkList->GetMarkCount() == 1 && mnShapesSelected == 1 )
1071 if( pMarkedObj )
1073 uno::Reference< drawing::XShape > xMarkedXShape (pMarkedObj->getUnoShape(), uno::UNO_QUERY);
1074 pUpObj = pMarkedObj->GetUpGroup();
1076 if( pMarkedObj == pFocusedObj )
1078 if( pUpObj )
1080 uno::Reference< drawing::XShape > xUpGroupXShape (pUpObj->getUnoShape(), uno::UNO_QUERY);
1081 uno::Reference < XAccessible > xAccGroupShape =
1082 const_cast<ScChildrenShapes*>(this)->GetAccessibleCaption( xUpGroupXShape );
1083 if( xAccGroupShape.is() )
1085 ::accessibility::AccessibleShape* pAccGroupShape =
1086 static_cast< ::accessibility::AccessibleShape* >(xAccGroupShape.get());
1087 if( pAccGroupShape )
1089 sal_Int32 nCount = pAccGroupShape->getAccessibleChildCount();
1090 for( sal_Int32 i = 0; i < nCount; i++ )
1092 uno::Reference<XAccessible> xAccShape = pAccGroupShape->getAccessibleChild(i);
1093 if (xAccShape.is())
1095 ::accessibility::AccessibleShape* pChildAccShape = static_cast< ::accessibility::AccessibleShape* >(xAccShape.get());
1096 uno::Reference< drawing::XShape > xChildShape = pChildAccShape->GetXShape();
1097 if (xChildShape == xMarkedXShape)
1099 pChildAccShape->SetState(AccessibleStateType::FOCUSED);
1101 else
1103 pChildAccShape->ResetState(AccessibleStateType::FOCUSED);
1113 if (vecSelectedShapeAdd.size() >= 10 )
1115 AccessibleEventObject aEvent;
1116 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN;
1117 aEvent.Source = uno::Reference< XAccessible >(mpAccessibleDocument);
1118 mpAccessibleDocument->CommitChange(aEvent);
1120 else
1122 SortedShapes::iterator vi = vecSelectedShapeAdd.begin();
1123 for (; vi != vecSelectedShapeAdd.end() ; ++vi )
1125 AccessibleEventObject aEvent;
1126 if (bHasSelect)
1128 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_ADD;
1130 else
1132 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1134 aEvent.Source = uno::Reference< XAccessible >(mpAccessibleDocument);
1135 uno::Reference< XAccessible > xChild( (*vi)->pAccShape);
1136 aEvent.NewValue <<= xChild;
1137 mpAccessibleDocument->CommitChange(aEvent);
1140 SortedShapes::iterator vi = vecSelectedShapeRemove.begin();
1141 for (; vi != vecSelectedShapeRemove.end() ; ++vi )
1143 AccessibleEventObject aEvent;
1144 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
1145 aEvent.Source = uno::Reference< XAccessible >(mpAccessibleDocument);
1146 uno::Reference< XAccessible > xChild( (*vi)->pAccShape);
1147 aEvent.NewValue <<= xChild;
1148 mpAccessibleDocument->CommitChange(aEvent);
1150 std::for_each(aShapesList.begin(), aShapesList.end(), Destroy());
1152 return bResult;
1155 void ScChildrenShapes::FillSelectionSupplier() const
1157 if (!xSelectionSupplier.is() && mpViewShell)
1159 SfxViewFrame* pViewFrame = mpViewShell->GetViewFrame();
1160 if (pViewFrame)
1162 xSelectionSupplier = uno::Reference<view::XSelectionSupplier>(pViewFrame->GetFrame().GetController(), uno::UNO_QUERY);
1163 if (xSelectionSupplier.is())
1165 if (mpAccessibleDocument)
1166 xSelectionSupplier->addSelectionChangeListener(mpAccessibleDocument);
1167 uno::Reference<drawing::XShapes> xShapes (xSelectionSupplier->getSelection(), uno::UNO_QUERY);
1168 if (xShapes.is())
1169 mnShapesSelected = xShapes->getCount();
1175 ScAddress* ScChildrenShapes::GetAnchor(const uno::Reference<drawing::XShape>& xShape) const
1177 ScAddress* pAddress = NULL;
1178 if (mpViewShell)
1180 SvxShape* pShapeImp = SvxShape::getImplementation(xShape);
1181 uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
1182 if (pShapeImp && xShapeProp.is())
1184 if (SdrObject *pSdrObj = pShapeImp->GetSdrObject())
1186 if (ScDrawObjData *pAnchor = ScDrawLayer::GetObjData(pSdrObj))
1187 return new ScAddress(pAnchor->maStart);
1192 return pAddress;
1195 uno::Reference<XAccessibleRelationSet> ScChildrenShapes::GetRelationSet(const ScAccessibleShapeData* pData) const
1197 utl::AccessibleRelationSetHelper* pRelationSet = new utl::AccessibleRelationSetHelper();
1199 if (pData && mpAccessibleDocument)
1201 uno::Reference<XAccessible> xAccessible = mpAccessibleDocument->GetAccessibleSpreadsheet(); // should be the current table
1202 if (pData->pRelationCell && xAccessible.is())
1204 uno::Reference<XAccessibleTable> xAccTable (xAccessible->getAccessibleContext(), uno::UNO_QUERY);
1205 if (xAccTable.is())
1206 xAccessible = xAccTable->getAccessibleCellAt(pData->pRelationCell->Row(), pData->pRelationCell->Col());
1208 AccessibleRelation aRelation;
1209 aRelation.TargetSet.realloc(1);
1210 aRelation.TargetSet[0] = xAccessible;
1211 aRelation.RelationType = AccessibleRelationType::CONTROLLED_BY;
1212 pRelationSet->AddRelation(aRelation);
1215 return pRelationSet;
1218 void ScChildrenShapes::CheckWhetherAnchorChanged(const uno::Reference<drawing::XShape>& xShape) const
1220 SortedShapes::iterator aItr;
1221 if (FindShape(xShape, aItr))
1222 SetAnchor(xShape, *aItr);
1225 void ScChildrenShapes::SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const
1227 if (pData)
1229 ScAddress* pAddress = GetAnchor(xShape);
1230 if ((pAddress && pData->pRelationCell && (*pAddress != *(pData->pRelationCell))) ||
1231 (!pAddress && pData->pRelationCell) || (pAddress && !pData->pRelationCell))
1233 if (pData->pRelationCell)
1234 delete pData->pRelationCell;
1235 pData->pRelationCell = pAddress;
1236 if (pData->pAccShape)
1237 pData->pAccShape->SetRelationSet(GetRelationSet(pData));
1239 else
1240 delete pAddress;
1244 void ScChildrenShapes::AddShape(const uno::Reference<drawing::XShape>& xShape, bool bCommitChange) const
1246 SortedShapes::iterator aFindItr;
1247 if (!FindShape(xShape, aFindItr))
1249 ScAccessibleShapeData* pShape = new ScAccessibleShapeData();
1250 pShape->xShape = xShape;
1251 SortedShapes::iterator aNewItr = maZOrderedShapes.insert(aFindItr, pShape);
1252 SetAnchor(xShape, pShape);
1254 uno::Reference< beans::XPropertySet > xShapeProp(xShape, uno::UNO_QUERY);
1255 if (xShapeProp.is())
1257 uno::Any aPropAny = xShapeProp->getPropertyValue("LayerID");
1258 sal_Int16 nLayerID = 0;
1259 if( aPropAny >>= nLayerID )
1261 if( (nLayerID == SC_LAYER_INTERN) || (nLayerID == SC_LAYER_HIDDEN) )
1262 pShape->bSelectable = false;
1263 else
1264 pShape->bSelectable = true;
1268 if (!xSelectionSupplier.is())
1269 throw uno::RuntimeException();
1271 uno::Reference<container::XEnumerationAccess> xEnumAcc(xSelectionSupplier->getSelection(), uno::UNO_QUERY);
1272 if (xEnumAcc.is())
1274 uno::Reference<container::XEnumeration> xEnum = xEnumAcc->createEnumeration();
1275 if (xEnum.is())
1277 uno::Reference<drawing::XShape> xSelectedShape;
1278 bool bFound(false);
1279 while (!bFound && xEnum->hasMoreElements())
1281 xEnum->nextElement() >>= xSelectedShape;
1282 if (xShape.is() && (xShape.get() == xSelectedShape.get()))
1284 pShape->bSelected = true;
1285 bFound = true;
1290 if (mpAccessibleDocument && bCommitChange)
1292 AccessibleEventObject aEvent;
1293 aEvent.EventId = AccessibleEventId::CHILD;
1294 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1295 aEvent.NewValue <<= Get(aNewItr - maZOrderedShapes.begin());
1297 mpAccessibleDocument->CommitChange(aEvent); // new child - event
1300 else
1302 OSL_FAIL("shape is always in the list");
1306 void ScChildrenShapes::RemoveShape(const uno::Reference<drawing::XShape>& xShape) const
1308 SortedShapes::iterator aItr;
1309 if (FindShape(xShape, aItr))
1311 if (mpAccessibleDocument)
1313 uno::Reference<XAccessible> xOldAccessible (Get(aItr - maZOrderedShapes.begin()));
1315 delete *aItr;
1316 maZOrderedShapes.erase(aItr);
1318 AccessibleEventObject aEvent;
1319 aEvent.EventId = AccessibleEventId::CHILD;
1320 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1321 aEvent.OldValue <<= uno::makeAny(xOldAccessible);
1323 mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
1325 else
1327 delete *aItr;
1328 maZOrderedShapes.erase(aItr);
1331 else
1333 OSL_FAIL("shape was not in internal list");
1337 bool ScChildrenShapes::FindShape(const uno::Reference<drawing::XShape>& xShape, ScChildrenShapes::SortedShapes::iterator& rItr) const
1339 bool bResult(false);
1340 ScAccessibleShapeData aShape;
1341 aShape.xShape = xShape;
1342 ScShapeDataLess aLess;
1343 rItr = std::lower_bound(maZOrderedShapes.begin(), maZOrderedShapes.end(), &aShape, aLess);
1344 if ((rItr != maZOrderedShapes.end()) && (*rItr != NULL) && ((*rItr)->xShape.get() == xShape.get()))
1345 bResult = true; // if the shape is found
1347 #if OSL_DEBUG_LEVEL > 0 // test whether it finds truly the correct shape (perhaps it is not really sorted)
1348 SortedShapes::iterator aDebugItr = maZOrderedShapes.begin();
1349 SortedShapes::iterator aEndItr = maZOrderedShapes.end();
1350 bool bFound(false);
1351 while (!bFound && aDebugItr != aEndItr)
1353 if (*aDebugItr && ((*aDebugItr)->xShape.get() == xShape.get()))
1354 bFound = true;
1355 else
1356 ++aDebugItr;
1358 bool bResult2 = (aDebugItr != maZOrderedShapes.end());
1359 OSL_ENSURE((bResult == bResult2) && ((bResult && (rItr == aDebugItr)) || !bResult), "wrong Shape found");
1360 #endif
1361 return bResult;
1364 sal_Int8 ScChildrenShapes::Compare(const ScAccessibleShapeData* pData1,
1365 const ScAccessibleShapeData* pData2)
1367 ScShapeDataLess aLess;
1369 bool bResult1(aLess(pData1, pData2));
1370 bool bResult2(aLess(pData2, pData1));
1372 sal_Int8 nResult(0);
1373 if (!bResult1 && bResult2)
1374 nResult = 1;
1375 else if (bResult1 && !bResult2)
1376 nResult = -1;
1378 return nResult;
1381 namespace
1383 struct ScVisAreaChanged
1385 ScAccessibleDocument* mpAccDoc;
1386 ScVisAreaChanged(ScAccessibleDocument* pAccDoc) : mpAccDoc(pAccDoc) {}
1387 void operator() (const ScAccessibleShapeData* pAccShapeData) const
1389 if (pAccShapeData && pAccShapeData->pAccShape)
1391 pAccShapeData->pAccShape->ViewForwarderChanged(::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA, mpAccDoc);
1397 void ScChildrenShapes::VisAreaChanged() const
1399 ScVisAreaChanged aVisAreaChanged(mpAccessibleDocument);
1400 std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), aVisAreaChanged);
1403 ScAccessibleDocument::ScAccessibleDocument(
1404 const uno::Reference<XAccessible>& rxParent,
1405 ScTabViewShell* pViewShell,
1406 ScSplitPos eSplitPos)
1407 : ScAccessibleDocumentBase(rxParent),
1408 mpViewShell(pViewShell),
1409 meSplitPos(eSplitPos),
1410 mpAccessibleSpreadsheet(NULL),
1411 mpChildrenShapes(NULL),
1412 mpTempAccEdit(NULL),
1413 mbCompleteSheetSelected(false)
1415 if (pViewShell)
1417 pViewShell->AddAccessibilityObject(*this);
1418 vcl::Window *pWin = pViewShell->GetWindowByPos(eSplitPos);
1419 if( pWin )
1421 pWin->AddChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1422 sal_uInt16 nCount = pWin->GetChildCount();
1423 for( sal_uInt16 i=0; i < nCount; ++i )
1425 vcl::Window *pChildWin = pWin->GetChild( i );
1426 if( pChildWin &&
1427 AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1428 AddChild( pChildWin->GetAccessible(), false );
1431 ScViewData& rViewData = pViewShell->GetViewData();
1432 if (rViewData.HasEditView(eSplitPos))
1434 uno::Reference<XAccessible> xAcc = new ScAccessibleEditObject(this, rViewData.GetEditView(eSplitPos),
1435 pViewShell->GetWindowByPos(eSplitPos), GetCurrentCellName(), GetCurrentCellDescription(),
1436 ScAccessibleEditObject::CellInEditMode);
1437 AddChild(xAcc, false);
1440 maVisArea = GetVisibleArea_Impl();
1443 void ScAccessibleDocument::Init()
1445 if(!mpChildrenShapes)
1446 mpChildrenShapes = new ScChildrenShapes(this, mpViewShell, meSplitPos);
1449 ScAccessibleDocument::~ScAccessibleDocument()
1451 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
1453 // increment refcount to prevent double call off dtor
1454 osl_atomic_increment( &m_refCount );
1455 dispose();
1459 void SAL_CALL ScAccessibleDocument::disposing()
1461 SolarMutexGuard aGuard;
1462 FreeAccessibleSpreadsheet();
1463 if (mpViewShell)
1465 vcl::Window *pWin = mpViewShell->GetWindowByPos(meSplitPos);
1466 if( pWin )
1467 pWin->RemoveChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1469 mpViewShell->RemoveAccessibilityObject(*this);
1470 mpViewShell = NULL;
1472 if (mpChildrenShapes)
1473 DELETEZ(mpChildrenShapes);
1475 ScAccessibleDocumentBase::disposing();
1478 void SAL_CALL ScAccessibleDocument::disposing( const lang::EventObject& /* Source */ )
1479 throw (uno::RuntimeException, std::exception)
1481 disposing();
1484 //===== SfxListener =====================================================
1486 IMPL_LINK( ScAccessibleDocument, WindowChildEventListener, VclSimpleEvent*, pEvent )
1488 OSL_ENSURE( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
1489 if ( pEvent && pEvent->ISA( VclWindowEvent ) )
1491 VclWindowEvent *pVclEvent = static_cast< VclWindowEvent * >( pEvent );
1492 OSL_ENSURE( pVclEvent->GetWindow(), "Window???" );
1493 switch ( pVclEvent->GetId() )
1495 case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children
1497 vcl::Window* pChildWin = static_cast < vcl::Window * >( pVclEvent->GetData() );
1498 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1500 AddChild( pChildWin->GetAccessible(), true );
1503 break;
1504 case VCLEVENT_WINDOW_HIDE: // send destroy on hide for direct accessible children
1506 vcl::Window* pChildWin = static_cast < vcl::Window * >( pVclEvent->GetData() );
1507 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1509 RemoveChild( pChildWin->GetAccessible(), true );
1512 break;
1515 return 0;
1518 void ScAccessibleDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1520 if (dynamic_cast<const ScAccGridWinFocusLostHint*>(&rHint) )
1522 const ScAccGridWinFocusLostHint* pFocusLostHint = static_cast<const ScAccGridWinFocusLostHint *>(&rHint);
1523 if (pFocusLostHint->GetOldGridWin() == meSplitPos)
1525 if (mxTempAcc.is() && mpTempAccEdit)
1526 mpTempAccEdit->LostFocus();
1527 else if (mpAccessibleSpreadsheet)
1528 mpAccessibleSpreadsheet->LostFocus();
1529 else
1530 CommitFocusLost();
1533 else if (dynamic_cast<const ScAccGridWinFocusGotHint*>(&rHint) )
1535 const ScAccGridWinFocusGotHint* pFocusGotHint = static_cast<const ScAccGridWinFocusGotHint*>(&rHint);
1536 if (pFocusGotHint->GetNewGridWin() == meSplitPos)
1538 uno::Reference<XAccessible> xAccessible;
1539 if (mpChildrenShapes)
1541 bool bTabMarked(IsTableSelected());
1542 xAccessible = mpChildrenShapes->GetSelected(0, bTabMarked);
1544 if( xAccessible.is() )
1546 uno::Any aNewValue;
1547 aNewValue<<=AccessibleStateType::FOCUSED;
1548 static_cast< ::accessibility::AccessibleShape* >(xAccessible.get())->
1549 CommitChange(AccessibleEventId::STATE_CHANGED,
1550 aNewValue,
1551 uno::Any() );
1553 else
1555 if (mxTempAcc.is() && mpTempAccEdit)
1556 mpTempAccEdit->GotFocus();
1557 else if (mpAccessibleSpreadsheet)
1558 mpAccessibleSpreadsheet->GotFocus();
1559 else
1560 CommitFocusGained();
1564 else if (dynamic_cast<const SfxSimpleHint*>(&rHint))
1566 const SfxSimpleHint* pSimpleHint = static_cast<const SfxSimpleHint*>(&rHint);
1567 // only notify if child exist, otherwise it is not necessary
1568 if ((pSimpleHint->GetId() == SC_HINT_ACC_TABLECHANGED) &&
1569 mpAccessibleSpreadsheet)
1571 FreeAccessibleSpreadsheet();
1572 if (mpChildrenShapes)
1573 DELETEZ(mpChildrenShapes);
1575 // Accessibility: Shapes / form controls after reload not accessible
1576 if ( !mpChildrenShapes )
1578 mpChildrenShapes = new ScChildrenShapes( this, mpViewShell, meSplitPos );
1581 //Invoke Init() to rebuild the mpChildrenShapes variable
1582 this->Init();
1584 AccessibleEventObject aEvent;
1585 aEvent.EventId = AccessibleEventId::INVALIDATE_ALL_CHILDREN;
1586 aEvent.Source = uno::Reference< XAccessibleContext >(this);
1587 CommitChange(aEvent); // all children changed
1589 if (mpAccessibleSpreadsheet)
1590 mpAccessibleSpreadsheet->FireFirstCellFocus();
1592 else if (pSimpleHint->GetId() == SC_HINT_ACC_MAKEDRAWLAYER)
1594 if (mpChildrenShapes)
1595 mpChildrenShapes->SetDrawBroadcaster();
1597 else if ((pSimpleHint->GetId() == SC_HINT_ACC_ENTEREDITMODE)) // this event comes only on creating edit field of a cell
1599 if (mpViewShell->GetViewData().HasEditView(meSplitPos))
1601 ScViewData& rViewData = mpViewShell->GetViewData();
1602 const EditEngine* pEditEng = rViewData.GetEditView(meSplitPos)->GetEditEngine();
1603 if (pEditEng && pEditEng->GetUpdateMode())
1605 mpTempAccEdit = new ScAccessibleEditObject(this, rViewData.GetEditView(meSplitPos),
1606 mpViewShell->GetWindowByPos(meSplitPos), GetCurrentCellName(),
1607 OUString(ScResId(STR_ACC_EDITLINE_DESCR)), ScAccessibleEditObject::CellInEditMode);
1608 uno::Reference<XAccessible> xAcc = mpTempAccEdit;
1610 AddChild(xAcc, true);
1612 if (mpAccessibleSpreadsheet)
1613 mpAccessibleSpreadsheet->LostFocus();
1614 else
1615 CommitFocusLost();
1617 mpTempAccEdit->GotFocus();
1621 else if (pSimpleHint->GetId() == SC_HINT_ACC_LEAVEEDITMODE)
1623 if (mxTempAcc.is())
1625 if (mpTempAccEdit)
1626 mpTempAccEdit->LostFocus();
1628 mpTempAccEdit = NULL;
1629 RemoveChild(mxTempAcc, true);
1630 if (mpAccessibleSpreadsheet && mpViewShell && mpViewShell->IsActive())
1631 mpAccessibleSpreadsheet->GotFocus();
1632 else if( mpViewShell && mpViewShell->IsActive())
1633 CommitFocusGained();
1636 else if ((pSimpleHint->GetId() == SC_HINT_ACC_VISAREACHANGED) || (pSimpleHint->GetId() == SC_HINT_ACC_WINDOWRESIZED))
1638 Rectangle aOldVisArea(maVisArea);
1639 maVisArea = GetVisibleArea_Impl();
1641 if (maVisArea != aOldVisArea)
1643 if (maVisArea.GetSize() != aOldVisArea.GetSize())
1645 AccessibleEventObject aEvent;
1646 aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
1647 aEvent.Source = uno::Reference< XAccessibleContext >(this);
1649 CommitChange(aEvent);
1651 if (mpAccessibleSpreadsheet)
1652 mpAccessibleSpreadsheet->BoundingBoxChanged();
1653 if (mpAccessibleSpreadsheet && mpViewShell && mpViewShell->IsActive())
1654 mpAccessibleSpreadsheet->FireFirstCellFocus();
1656 else if (mpAccessibleSpreadsheet)
1658 mpAccessibleSpreadsheet->VisAreaChanged();
1660 if (mpChildrenShapes)
1661 mpChildrenShapes->VisAreaChanged();
1666 ScAccessibleDocumentBase::Notify(rBC, rHint);
1669 void SAL_CALL ScAccessibleDocument::selectionChanged( const lang::EventObject& /* aEvent */ )
1670 throw (uno::RuntimeException, std::exception)
1672 bool bSelectionChanged(false);
1673 if (mpAccessibleSpreadsheet)
1675 bool bOldSelected(mbCompleteSheetSelected);
1676 mbCompleteSheetSelected = IsTableSelected();
1677 if (bOldSelected != mbCompleteSheetSelected)
1679 mpAccessibleSpreadsheet->CompleteSelectionChanged(mbCompleteSheetSelected);
1680 bSelectionChanged = true;
1684 if (mpChildrenShapes && mpChildrenShapes->SelectionChanged())
1685 bSelectionChanged = true;
1687 if (bSelectionChanged)
1689 AccessibleEventObject aEvent;
1690 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1691 aEvent.Source = uno::Reference< XAccessibleContext >(this);
1693 CommitChange(aEvent);
1697 //===== XInterface =====================================================
1699 uno::Any SAL_CALL ScAccessibleDocument::queryInterface( uno::Type const & rType )
1700 throw (uno::RuntimeException, std::exception)
1702 uno::Any aAnyTmp;
1703 if(rType == cppu::UnoType<XAccessibleGetAccFlowTo>::get())
1705 com::sun::star::uno::Reference<XAccessibleGetAccFlowTo> AccFromXShape = this;
1706 aAnyTmp <<= AccFromXShape;
1707 return aAnyTmp;
1709 uno::Any aAny (ScAccessibleDocumentImpl::queryInterface(rType));
1710 return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType);
1713 void SAL_CALL ScAccessibleDocument::acquire()
1714 throw ()
1716 ScAccessibleContextBase::acquire();
1719 void SAL_CALL ScAccessibleDocument::release()
1720 throw ()
1722 ScAccessibleContextBase::release();
1725 //===== XAccessibleComponent ============================================
1727 uno::Reference< XAccessible > SAL_CALL ScAccessibleDocument::getAccessibleAtPoint(
1728 const awt::Point& rPoint )
1729 throw (uno::RuntimeException, std::exception)
1731 uno::Reference<XAccessible> xAccessible = NULL;
1732 if (containsPoint(rPoint))
1734 SolarMutexGuard aGuard;
1735 IsObjectValid();
1736 if (mpChildrenShapes)
1737 xAccessible = mpChildrenShapes->GetAt(rPoint);
1738 if(!xAccessible.is())
1740 if (mxTempAcc.is())
1742 uno::Reference< XAccessibleContext > xCont(mxTempAcc->getAccessibleContext());
1743 uno::Reference< XAccessibleComponent > xComp(xCont, uno::UNO_QUERY);
1744 if (xComp.is())
1746 Rectangle aBound(VCLRectangle(xComp->getBounds()));
1747 if (aBound.IsInside(VCLPoint(rPoint)))
1748 xAccessible = mxTempAcc;
1751 if (!xAccessible.is())
1752 xAccessible = GetAccessibleSpreadsheet();
1755 return xAccessible;
1758 void SAL_CALL ScAccessibleDocument::grabFocus( )
1759 throw (uno::RuntimeException, std::exception)
1761 SolarMutexGuard aGuard;
1762 IsObjectValid();
1763 if (getAccessibleParent().is())
1765 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1766 if (xAccessibleComponent.is())
1768 xAccessibleComponent->grabFocus();
1769 // grab only focus if it does not have the focus and it is not hidden
1770 if (mpViewShell &&
1771 (mpViewShell->GetViewData().GetActivePart() != meSplitPos) &&
1772 mpViewShell->GetWindowByPos(meSplitPos)->IsVisible())
1774 mpViewShell->ActivatePart(meSplitPos);
1780 //===== XAccessibleContext ==============================================
1782 /// Return the number of currently visible children.
1783 sal_Int32 SAL_CALL
1784 ScAccessibleDocument::getAccessibleChildCount()
1785 throw (uno::RuntimeException, std::exception)
1787 SolarMutexGuard aGuard;
1788 IsObjectValid();
1789 sal_Int32 nCount(1);
1790 if (mpChildrenShapes)
1791 nCount = mpChildrenShapes->GetCount(); // returns the count of the shapes inclusive the table
1793 if (mxTempAcc.is())
1794 ++nCount;
1796 return nCount;
1799 /// Return the specified child or NULL if index is invalid.
1800 uno::Reference<XAccessible> SAL_CALL
1801 ScAccessibleDocument::getAccessibleChild(sal_Int32 nIndex)
1802 throw (uno::RuntimeException,
1803 lang::IndexOutOfBoundsException, std::exception)
1805 SolarMutexGuard aGuard;
1806 IsObjectValid();
1807 uno::Reference<XAccessible> xAccessible;
1808 if (nIndex >= 0)
1810 sal_Int32 nCount(1);
1811 if (mpChildrenShapes)
1813 xAccessible = mpChildrenShapes->Get(nIndex); // returns NULL if it is the table or out of range
1814 nCount = mpChildrenShapes->GetCount(); //there is always a table
1816 if (!xAccessible.is())
1818 if (nIndex < nCount)
1819 xAccessible = GetAccessibleSpreadsheet();
1820 else if (nIndex == nCount && mxTempAcc.is())
1821 xAccessible = mxTempAcc;
1825 if (!xAccessible.is())
1826 throw lang::IndexOutOfBoundsException();
1828 return xAccessible;
1831 /// Return the set of current states.
1832 uno::Reference<XAccessibleStateSet> SAL_CALL
1833 ScAccessibleDocument::getAccessibleStateSet()
1834 throw (uno::RuntimeException, std::exception)
1836 SolarMutexGuard aGuard;
1837 uno::Reference<XAccessibleStateSet> xParentStates;
1838 if (getAccessibleParent().is())
1840 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1841 xParentStates = xParentContext->getAccessibleStateSet();
1843 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
1844 if (IsDefunc(xParentStates))
1845 pStateSet->AddState(AccessibleStateType::DEFUNC);
1846 else
1848 pStateSet->AddState(AccessibleStateType::EDITABLE);
1849 pStateSet->AddState(AccessibleStateType::ENABLED);
1850 pStateSet->AddState(AccessibleStateType::OPAQUE);
1851 if (isShowing())
1852 pStateSet->AddState(AccessibleStateType::SHOWING);
1853 if (isVisible())
1854 pStateSet->AddState(AccessibleStateType::VISIBLE);
1856 return pStateSet;
1859 OUString SAL_CALL
1860 ScAccessibleDocument::getAccessibleName()
1861 throw (::com::sun::star::uno::RuntimeException, std::exception)
1863 SolarMutexGuard g;
1865 OUString aName = ScResId(STR_ACC_DOC_SPREADSHEET);
1866 ScDocument* pScDoc = GetDocument();
1867 if (!pScDoc)
1868 return aName;
1870 SfxObjectShell* pObjSh = pScDoc->GetDocumentShell();
1871 if (!pObjSh)
1872 return aName;
1874 OUString aFileName;
1875 SfxMedium* pMed = pObjSh->GetMedium();
1876 if (pMed)
1877 aFileName = pMed->GetName();
1879 if (aFileName.isEmpty())
1880 aFileName = pObjSh->GetTitle(SFX_TITLE_APINAME);
1882 if (!aFileName.isEmpty())
1884 OUString aReadOnly;
1885 if (pObjSh->IsReadOnly())
1886 aReadOnly = ScResId(STR_ACC_DOC_SPREADSHEET_READONLY);
1888 aName = aFileName + aReadOnly + " - " + aName;
1890 return aName;
1893 ///===== XAccessibleSelection ===========================================
1895 void SAL_CALL
1896 ScAccessibleDocument::selectAccessibleChild( sal_Int32 nChildIndex )
1897 throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1899 SolarMutexGuard aGuard;
1900 IsObjectValid();
1902 if (mpChildrenShapes && mpViewShell)
1904 sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table
1905 if (mxTempAcc.is())
1906 ++nCount;
1907 if (nChildIndex < 0 || nChildIndex >= nCount)
1908 throw lang::IndexOutOfBoundsException();
1910 uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1911 if (xAccessible.is())
1913 bool bWasTableSelected(IsTableSelected());
1915 if (mpChildrenShapes)
1916 mpChildrenShapes->Select(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is to high
1918 if (bWasTableSelected)
1919 mpViewShell->SelectAll();
1921 else
1923 if (mpViewShell)
1924 mpViewShell->SelectAll();
1929 sal_Bool SAL_CALL
1930 ScAccessibleDocument::isAccessibleChildSelected( sal_Int32 nChildIndex )
1931 throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1933 SolarMutexGuard aGuard;
1934 IsObjectValid();
1935 bool bResult(false);
1937 if (mpChildrenShapes)
1939 sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table
1940 if (mxTempAcc.is())
1941 ++nCount;
1942 if (nChildIndex < 0 || nChildIndex >= nCount)
1943 throw lang::IndexOutOfBoundsException();
1945 uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1946 if (xAccessible.is())
1948 uno::Reference<drawing::XShape> xShape;
1949 bResult = mpChildrenShapes->IsSelected(nChildIndex, xShape); // throws no lang::IndexOutOfBoundsException if Index is to high
1951 else
1953 if (mxTempAcc.is() && nChildIndex == nCount)
1954 bResult = true;
1955 else
1956 bResult = IsTableSelected();
1959 return bResult;
1962 void SAL_CALL
1963 ScAccessibleDocument::clearAccessibleSelection( )
1964 throw (uno::RuntimeException, std::exception)
1966 SolarMutexGuard aGuard;
1967 IsObjectValid();
1969 if (mpChildrenShapes)
1970 mpChildrenShapes->DeselectAll(); //deselects all (also the table)
1973 void SAL_CALL
1974 ScAccessibleDocument::selectAllAccessibleChildren( )
1975 throw (uno::RuntimeException, std::exception)
1977 SolarMutexGuard aGuard;
1978 IsObjectValid();
1980 if (mpChildrenShapes)
1981 mpChildrenShapes->SelectAll();
1983 // select table after shapes, because while selecting shapes the table will be deselected
1984 if (mpViewShell)
1986 mpViewShell->SelectAll();
1990 sal_Int32 SAL_CALL
1991 ScAccessibleDocument::getSelectedAccessibleChildCount( )
1992 throw (uno::RuntimeException, std::exception)
1994 SolarMutexGuard aGuard;
1995 IsObjectValid();
1996 sal_Int32 nCount(0);
1998 if (mpChildrenShapes)
1999 nCount = mpChildrenShapes->GetSelectedCount();
2001 if (IsTableSelected())
2002 ++nCount;
2004 if (mxTempAcc.is())
2005 ++nCount;
2007 return nCount;
2010 uno::Reference<XAccessible > SAL_CALL
2011 ScAccessibleDocument::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
2012 throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2014 SolarMutexGuard aGuard;
2015 IsObjectValid();
2016 uno::Reference<XAccessible> xAccessible;
2017 if (mpChildrenShapes)
2019 sal_Int32 nCount(getSelectedAccessibleChildCount()); //all shapes and the table
2020 if (nSelectedChildIndex < 0 || nSelectedChildIndex >= nCount)
2021 throw lang::IndexOutOfBoundsException();
2023 bool bTabMarked(IsTableSelected());
2025 if (mpChildrenShapes)
2026 xAccessible = mpChildrenShapes->GetSelected(nSelectedChildIndex, bTabMarked); // throws no lang::IndexOutOfBoundsException if Index is to high
2027 if (mxTempAcc.is() && nSelectedChildIndex == nCount - 1)
2028 xAccessible = mxTempAcc;
2029 else if (bTabMarked)
2030 xAccessible = GetAccessibleSpreadsheet();
2033 OSL_ENSURE(xAccessible.is(), "here should always be an accessible object or a exception throwed");
2035 return xAccessible;
2038 void SAL_CALL
2039 ScAccessibleDocument::deselectAccessibleChild( sal_Int32 nChildIndex )
2040 throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2042 SolarMutexGuard aGuard;
2043 IsObjectValid();
2045 if (mpChildrenShapes && mpViewShell)
2047 sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table
2048 if (mxTempAcc.is())
2049 ++nCount;
2050 if (nChildIndex < 0 || nChildIndex >= nCount)
2051 throw lang::IndexOutOfBoundsException();
2053 bool bTabMarked(IsTableSelected());
2055 uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
2056 if (xAccessible.is())
2058 if (mpChildrenShapes)
2059 mpChildrenShapes->Deselect(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is to high
2061 if (bTabMarked)
2062 mpViewShell->SelectAll(); // select the table again
2064 else if (bTabMarked)
2065 mpViewShell->Unmark();
2069 //===== XServiceInfo ====================================================
2071 OUString SAL_CALL
2072 ScAccessibleDocument::getImplementationName()
2073 throw (uno::RuntimeException, std::exception)
2075 return OUString("ScAccessibleDocument");
2078 uno::Sequence< OUString> SAL_CALL
2079 ScAccessibleDocument::getSupportedServiceNames()
2080 throw (uno::RuntimeException, std::exception)
2082 uno::Sequence< OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
2083 sal_Int32 nOldSize(aSequence.getLength());
2084 aSequence.realloc(nOldSize + 1);
2086 aSequence[nOldSize] = "com.sun.star.AccessibleSpreadsheetDocumentView";
2088 return aSequence;
2091 //===== XTypeProvider =======================================================
2093 uno::Sequence< uno::Type > SAL_CALL ScAccessibleDocument::getTypes()
2094 throw (uno::RuntimeException, std::exception)
2096 return comphelper::concatSequences(ScAccessibleDocumentImpl::getTypes(), ScAccessibleContextBase::getTypes());
2099 uno::Sequence<sal_Int8> SAL_CALL
2100 ScAccessibleDocument::getImplementationId()
2101 throw (uno::RuntimeException, std::exception)
2103 return css::uno::Sequence<sal_Int8>();
2106 ///===== IAccessibleViewForwarder ========================================
2108 bool ScAccessibleDocument::IsValid() const
2110 SolarMutexGuard aGuard;
2111 IsObjectValid();
2112 return (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose);
2115 Rectangle ScAccessibleDocument::GetVisibleArea_Impl() const
2117 Rectangle aVisRect(GetBoundingBox());
2119 if (mpViewShell)
2121 Point aPoint(mpViewShell->GetViewData().GetPixPos(meSplitPos)); // returns a negative Point
2122 aPoint.setX(-aPoint.getX());
2123 aPoint.setY(-aPoint.getY());
2124 aVisRect.SetPos(aPoint);
2126 ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
2127 if (pWin)
2128 aVisRect = pWin->PixelToLogic(aVisRect, pWin->GetDrawMapMode());
2131 return aVisRect;
2134 Rectangle ScAccessibleDocument::GetVisibleArea() const
2136 SolarMutexGuard aGuard;
2137 IsObjectValid();
2138 return maVisArea;
2141 Point ScAccessibleDocument::LogicToPixel (const Point& rPoint) const
2143 SolarMutexGuard aGuard;
2144 IsObjectValid();
2145 Point aPoint;
2146 ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
2147 if (pWin)
2149 aPoint = pWin->LogicToPixel(rPoint, pWin->GetDrawMapMode());
2150 aPoint += pWin->GetWindowExtentsRelative(NULL).TopLeft();
2152 return aPoint;
2155 Size ScAccessibleDocument::LogicToPixel (const Size& rSize) const
2157 SolarMutexGuard aGuard;
2158 IsObjectValid();
2159 Size aSize;
2160 ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
2161 if (pWin)
2162 aSize = pWin->LogicToPixel(rSize, pWin->GetDrawMapMode());
2163 return aSize;
2166 Point ScAccessibleDocument::PixelToLogic (const Point& rPoint) const
2168 SolarMutexGuard aGuard;
2169 IsObjectValid();
2170 Point aPoint;
2171 ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
2172 if (pWin)
2174 aPoint -= pWin->GetWindowExtentsRelative(NULL).TopLeft();
2175 aPoint = pWin->PixelToLogic(rPoint, pWin->GetDrawMapMode());
2177 return aPoint;
2180 Size ScAccessibleDocument::PixelToLogic (const Size& rSize) const
2182 SolarMutexGuard aGuard;
2183 IsObjectValid();
2184 Size aSize;
2185 ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
2186 if (pWin)
2187 aSize = pWin->PixelToLogic(rSize, pWin->GetDrawMapMode());
2188 return aSize;
2191 //===== internal ========================================================
2193 utl::AccessibleRelationSetHelper* ScAccessibleDocument::GetRelationSet(const ScAddress* pAddress) const
2195 utl::AccessibleRelationSetHelper* pRelationSet = NULL;
2196 if (mpChildrenShapes)
2197 pRelationSet = mpChildrenShapes->GetRelationSet(pAddress);
2198 return pRelationSet;
2201 OUString SAL_CALL
2202 ScAccessibleDocument::createAccessibleDescription()
2203 throw (uno::RuntimeException)
2205 OUString sDescription = OUString(ScResId(STR_ACC_DOC_DESCR));
2206 return sDescription;
2209 OUString SAL_CALL
2210 ScAccessibleDocument::createAccessibleName()
2211 throw (uno::RuntimeException, std::exception)
2213 SolarMutexGuard aGuard;
2214 IsObjectValid();
2215 OUString sName = OUString(ScResId(STR_ACC_DOC_NAME));
2216 sal_Int32 nNumber(sal_Int32(meSplitPos) + 1);
2217 sName += OUString::number(nNumber);
2218 return sName;
2221 Rectangle ScAccessibleDocument::GetBoundingBoxOnScreen() const
2222 throw (uno::RuntimeException, std::exception)
2224 Rectangle aRect;
2225 if (mpViewShell)
2227 vcl::Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
2228 if (pWindow)
2229 aRect = pWindow->GetWindowExtentsRelative(NULL);
2231 return aRect;
2234 Rectangle ScAccessibleDocument::GetBoundingBox() const
2235 throw (uno::RuntimeException, std::exception)
2237 Rectangle aRect;
2238 if (mpViewShell)
2240 vcl::Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
2241 if (pWindow)
2242 aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
2244 return aRect;
2247 SCTAB ScAccessibleDocument::getVisibleTable() const
2249 SCTAB nVisibleTable(0);
2250 if (mpViewShell)
2251 nVisibleTable = mpViewShell->GetViewData().GetTabNo();
2252 return nVisibleTable;
2255 uno::Reference < XAccessible >
2256 ScAccessibleDocument::GetAccessibleSpreadsheet()
2258 if (!mpAccessibleSpreadsheet && mpViewShell)
2260 mpAccessibleSpreadsheet = new ScAccessibleSpreadsheet(this, mpViewShell, getVisibleTable(), meSplitPos);
2261 mpAccessibleSpreadsheet->acquire();
2262 mpAccessibleSpreadsheet->Init();
2263 mbCompleteSheetSelected = IsTableSelected();
2265 return mpAccessibleSpreadsheet;
2268 void ScAccessibleDocument::FreeAccessibleSpreadsheet()
2270 if (mpAccessibleSpreadsheet)
2272 mpAccessibleSpreadsheet->dispose();
2273 mpAccessibleSpreadsheet->release();
2274 mpAccessibleSpreadsheet = NULL;
2278 bool ScAccessibleDocument::IsTableSelected() const
2280 bool bResult (false);
2281 if(mpViewShell)
2283 SCTAB nTab(getVisibleTable());
2284 //#103800#; use a copy of MarkData
2285 ScMarkData aMarkData(mpViewShell->GetViewData().GetMarkData());
2286 aMarkData.MarkToMulti();
2287 if (aMarkData.IsAllMarked(ScRange(ScAddress(0, 0, nTab),ScAddress(MAXCOL, MAXROW, nTab))))
2288 bResult = true;
2290 return bResult;
2293 bool ScAccessibleDocument::IsDefunc(
2294 const uno::Reference<XAccessibleStateSet>& rxParentStates)
2296 return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() ||
2297 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
2300 void ScAccessibleDocument::AddChild(const uno::Reference<XAccessible>& xAcc, bool bFireEvent)
2302 OSL_ENSURE(!mxTempAcc.is(), "this object should be removed before");
2303 if (xAcc.is())
2305 mxTempAcc = xAcc;
2306 if( bFireEvent )
2308 AccessibleEventObject aEvent;
2309 aEvent.Source = uno::Reference<XAccessibleContext>(this);
2310 aEvent.EventId = AccessibleEventId::CHILD;
2311 aEvent.NewValue <<= mxTempAcc;
2312 CommitChange( aEvent );
2317 void ScAccessibleDocument::RemoveChild(const uno::Reference<XAccessible>& xAcc, bool bFireEvent)
2319 OSL_ENSURE(mxTempAcc.is(), "this object should be added before");
2320 if (xAcc.is())
2322 OSL_ENSURE(xAcc.get() == mxTempAcc.get(), "only the same object should be removed");
2323 if( bFireEvent )
2325 AccessibleEventObject aEvent;
2326 aEvent.Source = uno::Reference<XAccessibleContext>(this);
2327 aEvent.EventId = AccessibleEventId::CHILD;
2328 aEvent.OldValue <<= mxTempAcc;
2329 CommitChange( aEvent );
2331 mxTempAcc = NULL;
2335 OUString ScAccessibleDocument::GetCurrentCellName() const
2337 OUString sName(SC_RESSTR(STR_ACC_CELL_NAME));
2338 if (mpViewShell)
2340 // Document not needed, because only the cell address, but not the tablename is needed
2341 OUString sAddress(mpViewShell->GetViewData().GetCurPos().Format(SCA_VALID, NULL));
2342 sName = sName.replaceFirst("%1", sAddress);
2344 return sName;
2347 OUString ScAccessibleDocument::GetCurrentCellDescription()
2349 return OUString();
2352 ScDocument *ScAccessibleDocument::GetDocument() const
2354 return mpViewShell ? mpViewShell->GetViewData().GetDocument() : NULL;
2357 ScAddress ScAccessibleDocument::GetCurCellAddress() const
2359 return mpViewShell ? mpViewShell->GetViewData().GetCurPos() : ScAddress();
2362 uno::Any SAL_CALL ScAccessibleDocument::getExtendedAttributes()
2363 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException, std::exception)
2365 SolarMutexGuard g;
2367 uno::Any anyAtrribute;
2369 OUString sName;
2370 OUString sValue;
2371 sal_uInt16 sheetIndex;
2372 OUString sSheetName;
2373 sheetIndex = getVisibleTable();
2374 if(GetDocument()==NULL)
2375 return anyAtrribute;
2376 GetDocument()->GetName(sheetIndex,sSheetName);
2377 sName = "page-name:";
2378 sValue = sName + sSheetName ;
2379 sName = ";page-number:";
2380 sValue += sName;
2381 sValue += OUString::number(sheetIndex+1) ;
2382 sName = ";total-pages:";
2383 sValue += sName;
2384 sValue += OUString::number(GetDocument()->GetTableCount());
2385 sValue += ";";
2386 anyAtrribute <<= sValue;
2387 return anyAtrribute;
2390 com::sun::star::uno::Sequence< com::sun::star::uno::Any > ScAccessibleDocument::GetScAccFlowToSequence()
2392 if ( getAccessibleChildCount() )
2394 uno::Reference < XAccessible > xSCTableAcc = getAccessibleChild( 0 ); // table
2395 if ( xSCTableAcc.is() )
2397 uno::Reference < XAccessibleSelection > xAccSelection( xSCTableAcc, uno::UNO_QUERY );
2398 sal_Int32 nSelCount = xAccSelection->getSelectedAccessibleChildCount();
2399 if( nSelCount )
2401 uno::Reference < XAccessible > xSel = xAccSelection->getSelectedAccessibleChild( 0 ); // selected cell
2402 if ( xSel.is() )
2404 uno::Reference < XAccessibleContext > xSelContext( xSel->getAccessibleContext() );
2405 if ( xSelContext.is() )
2407 if ( xSelContext->getAccessibleRole() == AccessibleRole::TABLE_CELL )
2409 sal_Int32 nParaCount = 0;
2410 uno::Sequence <uno::Any> aSequence(nSelCount);
2411 for ( sal_Int32 i = 0; i < nSelCount; i++ )
2413 xSel = xAccSelection->getSelectedAccessibleChild( i ) ;
2414 if ( xSel.is() )
2416 xSelContext = xSel->getAccessibleContext();
2417 if ( xSelContext.is() )
2419 if ( xSelContext->getAccessibleRole() == AccessibleRole::TABLE_CELL )
2421 aSequence[nParaCount] = uno::makeAny( xSel );
2422 nParaCount++;
2427 return aSequence;
2434 uno::Sequence <uno::Any> aEmpty;
2435 return aEmpty;
2438 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >
2439 SAL_CALL ScAccessibleDocument::getAccFlowTo(const ::com::sun::star::uno::Any& rAny, sal_Int32 nType)
2440 throw ( ::com::sun::star::uno::RuntimeException, std::exception )
2442 SolarMutexGuard g;
2444 const sal_Int32 SPELLCHECKFLOWTO = 1;
2445 const sal_Int32 FINDREPLACEFLOWTO = 2;
2446 if ( nType == SPELLCHECKFLOWTO )
2448 uno::Reference< ::com::sun::star::drawing::XShape > xShape;
2449 rAny >>= xShape;
2450 if ( xShape.is() )
2452 uno::Reference < XAccessible > xAcc = mpChildrenShapes->GetAccessibleCaption(xShape);
2453 uno::Reference < XAccessibleSelection > xAccSelection( xAcc, uno::UNO_QUERY );
2454 if ( xAccSelection.is() )
2456 if ( xAccSelection->getSelectedAccessibleChildCount() )
2458 uno::Reference < XAccessible > xSel = xAccSelection->getSelectedAccessibleChild( 0 );
2459 if ( xSel.is() )
2461 uno::Reference < XAccessibleContext > xSelContext( xSel->getAccessibleContext() );
2462 if ( xSelContext.is() )
2464 //if in sw we find the selected paragraph here
2465 if ( xSelContext->getAccessibleRole() == AccessibleRole::PARAGRAPH )
2467 uno::Sequence<uno::Any> aRet( 1 );
2468 aRet[0] = uno::makeAny( xSel );
2469 return aRet;
2476 else
2478 if ( getSelectedAccessibleChildCount() )
2480 uno::Reference < XAccessible > xSel = getSelectedAccessibleChild( 0 );
2481 if ( xSel.is() )
2483 uno::Reference < XAccessibleContext > xSelContext( xSel->getAccessibleContext() );
2484 if ( xSelContext.is() )
2486 uno::Reference < XAccessibleSelection > xAccChildSelection( xSel, uno::UNO_QUERY );
2487 if ( xAccChildSelection.is() )
2489 if ( xAccChildSelection->getSelectedAccessibleChildCount() )
2491 uno::Reference < XAccessible > xChildSel = xAccChildSelection->getSelectedAccessibleChild( 0 );
2492 if ( xChildSel.is() )
2494 uno::Reference < ::com::sun::star::accessibility::XAccessibleContext > xChildSelContext( xChildSel->getAccessibleContext() );
2495 if ( xChildSelContext.is() &&
2496 xChildSelContext->getAccessibleRole() == ::com::sun::star::accessibility::AccessibleRole::PARAGRAPH )
2498 uno::Sequence<uno::Any> aRet( 1 );
2499 aRet[0] = uno::makeAny( xChildSel );
2500 return aRet;
2510 else if ( nType == FINDREPLACEFLOWTO )
2512 bool bSuccess(false);
2513 rAny >>= bSuccess;
2514 if ( bSuccess )
2516 uno::Sequence< uno::Any> aSeq = GetScAccFlowToSequence();
2517 if ( aSeq.getLength() )
2519 return aSeq;
2521 else if( mpAccessibleSpreadsheet )
2523 uno::Reference < XAccessible > xFindCellAcc = mpAccessibleSpreadsheet->GetActiveCell();
2524 // add xFindCellAcc to the return the Sequence
2525 uno::Sequence< uno::Any> aSeq2(1);
2526 aSeq2[0] = uno::makeAny( xFindCellAcc );
2527 return aSeq2;
2531 uno::Sequence< uno::Any> aEmpty;
2532 return aEmpty;
2535 void ScAccessibleDocument::SwitchViewFireFocus()
2537 if (mpAccessibleSpreadsheet)
2539 mpAccessibleSpreadsheet->FireFirstCellFocus();
2543 sal_Int32 SAL_CALL ScAccessibleDocument::getForeground( )
2544 throw (uno::RuntimeException, std::exception)
2546 return COL_BLACK;
2549 sal_Int32 SAL_CALL ScAccessibleDocument::getBackground( )
2550 throw (uno::RuntimeException, std::exception)
2552 SolarMutexGuard aGuard;
2553 IsObjectValid();
2554 return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor;
2557 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */