xref: /trunk/main/sc/source/ui/Accessibility/AccessibleDocument.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 #include "AccessibleDocument.hxx"
33 #include "AccessibleSpreadsheet.hxx"
34 #include "tabvwsh.hxx"
35 #include "AccessibilityHints.hxx"
36 #include "document.hxx"
37 #include "drwlayer.hxx"
38 #include "unoguard.hxx"
39 #include "shapeuno.hxx"
40 #include "DrawModelBroadcaster.hxx"
41 #include "drawview.hxx"
42 #include "gridwin.hxx"
43 #include "AccessibleEditObject.hxx"
44 #include "scresid.hxx"
45 #ifndef SC_SC_HRC
46 #include "sc.hrc"
47 #endif
48 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
49 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
50 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
51 #endif
52 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLERELATIONTYPE_HPP_
53 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
54 #endif
55 #include <com/sun/star/view/XSelectionSupplier.hpp>
56 #include <com/sun/star/drawing/XShape.hpp>
57 #include <com/sun/star/drawing/XShapes.hpp>
58 
59 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
60 #include <unotools/accessiblestatesethelper.hxx>
61 #endif
62 #include <tools/debug.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 <sfx2/viewfrm.hxx>
72 #include <svx/unoshcol.hxx>
73 #include <svx/unoshape.hxx>
74 #include <unotools/accessiblerelationsethelper.hxx>
75 #include <toolkit/helper/convert.hxx>
76 
77 #include <list>
78 #include <algorithm>
79 
80 using namespace ::com::sun::star;
81 using namespace ::com::sun::star::accessibility;
82 using ::std::for_each;
83 
84     //=====  internal  ========================================================
85 
86 struct ScAccessibleShapeData
87 {
88     ScAccessibleShapeData() : pAccShape(NULL), pRelationCell(NULL), bSelected(sal_False), bSelectable(sal_True) {}
89     ~ScAccessibleShapeData();
90     mutable ::accessibility::AccessibleShape* pAccShape;
91     mutable ScAddress*          pRelationCell; // if it is NULL this shape is anchored on the table
92 //    SdrObject*                  pShape;
93     com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape;
94     mutable sal_Bool            bSelected;
95     sal_Bool                    bSelectable;
96 };
97 
98 ScAccessibleShapeData::~ScAccessibleShapeData()
99 {
100     if (pAccShape)
101     {
102         pAccShape->dispose();
103         pAccShape->release();
104     }
105 }
106 
107 struct ScShapeDataLess
108 {
109     rtl::OUString msLayerId;
110     rtl::OUString msZOrder;
111     ScShapeDataLess()
112         : msLayerId(RTL_CONSTASCII_USTRINGPARAM( "LayerID" )),
113         msZOrder(RTL_CONSTASCII_USTRINGPARAM( "ZOrder" ))
114     {
115     }
116     void ConvertLayerId(sal_Int16& rLayerID) const // changes the number of the LayerId so it the accessibility order
117     {
118         switch (rLayerID)
119         {
120         case SC_LAYER_FRONT:
121             rLayerID = 1;
122             break;
123         case SC_LAYER_BACK:
124             rLayerID = 0;
125             break;
126         case SC_LAYER_INTERN:
127             rLayerID = 2;
128             break;
129         case SC_LAYER_CONTROLS:
130             rLayerID = 3;
131             break;
132         }
133     }
134     sal_Bool LessThanSheet(const ScAccessibleShapeData* pData) const
135     {
136         sal_Bool bResult(sal_False);
137         uno::Reference< beans::XPropertySet> xProps(pData->xShape, uno::UNO_QUERY);
138         if (xProps.is())
139         {
140             uno::Any aPropAny = xProps->getPropertyValue(msLayerId);
141             sal_Int16 nLayerID = 0;
142             if( (aPropAny >>= nLayerID) )
143             {
144                 if (nLayerID == SC_LAYER_BACK)
145                     bResult = sal_True;
146             }
147         }
148         return bResult;
149     }
150     sal_Bool operator()(const ScAccessibleShapeData* pData1, const ScAccessibleShapeData* pData2) const
151     {
152         sal_Bool bResult(sal_False);
153         if (pData1 && pData2)
154         {
155             uno::Reference< beans::XPropertySet> xProps1(pData1->xShape, uno::UNO_QUERY);
156             uno::Reference< beans::XPropertySet> xProps2(pData2->xShape, uno::UNO_QUERY);
157             if (xProps1.is() && xProps2.is())
158             {
159                 uno::Any aPropAny1 = xProps1->getPropertyValue(msLayerId);
160                 uno::Any aPropAny2 = xProps2->getPropertyValue(msLayerId);
161                 sal_Int16 nLayerID1(0);
162                 sal_Int16 nLayerID2(0);
163                 if( (aPropAny1 >>= nLayerID1) && (aPropAny2 >>= nLayerID2) )
164                 {
165                     if (nLayerID1 == nLayerID2)
166                     {
167                         uno::Any aAny1 = xProps1->getPropertyValue(msZOrder);
168                         sal_Int32 nZOrder1 = 0;
169                         uno::Any aAny2 = xProps2->getPropertyValue(msZOrder);
170                         sal_Int32 nZOrder2 = 0;
171                         if ( (aAny1 >>= nZOrder1) && (aAny2 >>= nZOrder2) )
172                             bResult = (nZOrder1 < nZOrder2);
173                     }
174                     else
175                     {
176                         ConvertLayerId(nLayerID1);
177                         ConvertLayerId(nLayerID2);
178                         bResult = (nLayerID1 < nLayerID2);
179                     }
180                 }
181             }
182         }
183         else if (pData1 && !pData2)
184             bResult = LessThanSheet(pData1);
185         else if (!pData1 && pData2)
186             bResult = !LessThanSheet(pData2);
187         else
188             bResult = sal_False;
189         return bResult;
190     }
191 };
192 
193 struct DeselectShape
194 {
195     void operator() (const ScAccessibleShapeData* pAccShapeData) const
196     {
197         if (pAccShapeData)
198         {
199             pAccShapeData->bSelected = sal_False;
200             if (pAccShapeData->pAccShape)
201                 pAccShapeData->pAccShape->ResetState(AccessibleStateType::SELECTED);
202         }
203     }
204 };
205 
206 struct SelectShape
207 {
208     uno::Reference < drawing::XShapes > xShapes;
209     SelectShape(uno::Reference<drawing::XShapes>& xTemp) : xShapes(xTemp) {}
210     void operator() (const ScAccessibleShapeData* pAccShapeData) const
211     {
212         if (pAccShapeData && pAccShapeData->bSelectable)
213         {
214             pAccShapeData->bSelected = sal_True;
215             if (pAccShapeData->pAccShape)
216                 pAccShapeData->pAccShape->SetState(AccessibleStateType::SELECTED);
217             if (xShapes.is())
218                 xShapes->add(pAccShapeData->xShape);
219         }
220     }
221 };
222 
223 struct Destroy
224 {
225     void operator() (ScAccessibleShapeData* pData)
226     {
227         if (pData)
228             DELETEZ(pData);
229     }
230 };
231 
232 class ScChildrenShapes : public SfxListener,
233     public ::accessibility::IAccessibleParent
234 {
235 public:
236     ScChildrenShapes(ScAccessibleDocument* pAccessibleDocument, ScTabViewShell* pViewShell, ScSplitPos eSplitPos);
237     ~ScChildrenShapes();
238 
239     ///=====  SfxListener  =====================================================
240 
241     virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
242 
243     ///=====  IAccessibleParent  ===============================================
244 
245     virtual sal_Bool ReplaceChild (
246         ::accessibility::AccessibleShape* pCurrentChild,
247         const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape,
248         const long _nIndex,
249         const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo
250     )   throw (::com::sun::star::uno::RuntimeException);
251 
252     ///=====  Internal  ========================================================
253     void SetDrawBroadcaster();
254 
255     sal_Int32 GetCount() const;
256     uno::Reference< XAccessible > Get(const ScAccessibleShapeData* pData) const;
257     uno::Reference< XAccessible > Get(sal_Int32 nIndex) const;
258     uno::Reference< XAccessible > GetAt(const awt::Point& rPoint) const;
259 
260     // gets the index of the shape starting on 0 (without the index of the table)
261     // returns the selected shape
262     sal_Bool IsSelected(sal_Int32 nIndex,
263         com::sun::star::uno::Reference<com::sun::star::drawing::XShape>& rShape) const;
264 
265     sal_Bool SelectionChanged();
266 
267     void Select(sal_Int32 nIndex);
268     void DeselectAll(); // deselect also the table
269     void SelectAll();
270     sal_Int32 GetSelectedCount() const;
271     uno::Reference< XAccessible > GetSelected(sal_Int32 nSelectedChildIndex, sal_Bool bTabSelected) const;
272     void Deselect(sal_Int32 nChildIndex);
273 
274     SdrPage* GetDrawPage() const;
275 
276     utl::AccessibleRelationSetHelper* GetRelationSet(const ScAddress* pAddress) const;
277 
278     void VisAreaChanged() const;
279 private:
280     typedef std::vector<ScAccessibleShapeData*> SortedShapes;
281 
282     mutable SortedShapes maZOrderedShapes; // a null pointer represents the sheet in the correct order
283 
284     mutable ::accessibility::AccessibleShapeTreeInfo maShapeTreeInfo;
285     mutable com::sun::star::uno::Reference<com::sun::star::view::XSelectionSupplier> xSelectionSupplier;
286     mutable sal_uInt32 mnSdrObjCount;
287     mutable sal_uInt32 mnShapesSelected;
288     ScTabViewShell* mpViewShell;
289     ScAccessibleDocument* mpAccessibleDocument;
290     ScSplitPos meSplitPos;
291 
292     void FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const;
293     sal_Bool FindSelectedShapesChanges(const com::sun::star::uno::Reference<com::sun::star::drawing::XShapes>& xShapes, sal_Bool bCommitChange) const;
294     void FillSelectionSupplier() const;
295 
296     ScAddress* GetAnchor(const uno::Reference<drawing::XShape>& xShape) const;
297     uno::Reference<XAccessibleRelationSet> GetRelationSet(const ScAccessibleShapeData* pData) const;
298     void CheckWhetherAnchorChanged(const uno::Reference<drawing::XShape>& xShape) const;
299     void SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const;
300     void AddShape(const uno::Reference<drawing::XShape>& xShape, sal_Bool bCommitChange) const;
301     void RemoveShape(const uno::Reference<drawing::XShape>& xShape) const;
302 
303     sal_Bool FindShape(const uno::Reference<drawing::XShape>& xShape, SortedShapes::iterator& rItr) const;
304 
305     sal_Int8 Compare(const ScAccessibleShapeData* pData1,
306         const ScAccessibleShapeData* pData2) const;
307 };
308 
309 ScChildrenShapes::ScChildrenShapes(ScAccessibleDocument* pAccessibleDocument, ScTabViewShell* pViewShell, ScSplitPos eSplitPos)
310     :
311     mnShapesSelected(0),
312     mpViewShell(pViewShell),
313     mpAccessibleDocument(pAccessibleDocument),
314     meSplitPos(eSplitPos)
315 {
316     FillSelectionSupplier();
317     maZOrderedShapes.push_back(NULL); // add an element which represents the table
318 
319     GetCount(); // fill list with filtered shapes (no internal shapes)
320 
321     if (mnShapesSelected)
322     {
323         //set flag on every selected shape
324         if (!xSelectionSupplier.is())
325             throw uno::RuntimeException();
326 
327         uno::Reference<drawing::XShapes> xShapes(xSelectionSupplier->getSelection(), uno::UNO_QUERY);
328         if (xShapes.is())
329             FindSelectedShapesChanges(xShapes, sal_False);
330     }
331     if (pViewShell)
332     {
333         SfxBroadcaster* pDrawBC = pViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster();
334         if (pDrawBC)
335         {
336             StartListening(*pDrawBC);
337 
338             maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(pViewShell->GetViewData()->GetDocument()->GetDrawLayer()) );
339             maShapeTreeInfo.SetSdrView(pViewShell->GetViewData()->GetScDrawView());
340             maShapeTreeInfo.SetController(NULL);
341             maShapeTreeInfo.SetWindow(pViewShell->GetWindowByPos(meSplitPos));
342             maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
343         }
344     }
345 }
346 
347 ScChildrenShapes::~ScChildrenShapes()
348 {
349     std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), Destroy());
350     if (mpViewShell)
351     {
352         SfxBroadcaster* pDrawBC = mpViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster();
353         if (pDrawBC)
354             EndListening(*pDrawBC);
355     }
356 }
357 
358 void ScChildrenShapes::SetDrawBroadcaster()
359 {
360     if (mpViewShell)
361     {
362         SfxBroadcaster* pDrawBC = mpViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster();
363         if (pDrawBC)
364         {
365             StartListening(*pDrawBC, sal_True);
366 
367             maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(mpViewShell->GetViewData()->GetDocument()->GetDrawLayer()) );
368             maShapeTreeInfo.SetSdrView(mpViewShell->GetViewData()->GetScDrawView());
369             maShapeTreeInfo.SetController(NULL);
370             maShapeTreeInfo.SetWindow(mpViewShell->GetWindowByPos(meSplitPos));
371             maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
372         }
373     }
374 }
375 
376 void ScChildrenShapes::Notify(SfxBroadcaster&, const SfxHint& rHint)
377 {
378     if ( rHint.ISA( SdrHint ) )
379     {
380         const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
381         if (pSdrHint)
382         {
383             SdrObject* pObj = const_cast<SdrObject*>(pSdrHint->GetObject());
384             if (pObj && /*(pObj->GetLayer() != SC_LAYER_INTERN) && */(pObj->GetPage() == GetDrawPage()) &&
385                 (pObj->GetPage() == pObj->GetObjList()) ) //#108480# only do something if the object lies direct on the page
386             {
387                 switch (pSdrHint->GetKind())
388                 {
389                     case HINT_OBJCHG :         // Objekt geaendert
390                     {
391                         uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
392                         if (xShape.is())
393                         {
394                             ScShapeDataLess aLess;
395                             std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), aLess); // sort, because the z index or layer could be changed
396                             CheckWhetherAnchorChanged(xShape);
397                         }
398                     }
399                     break;
400                     case HINT_OBJINSERTED :    // Neues Zeichenobjekt eingefuegt
401                     {
402                         uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
403                         if (xShape.is())
404                             AddShape(xShape, sal_True);
405                     }
406                     break;
407                     case HINT_OBJREMOVED :     // Zeichenobjekt aus Liste entfernt
408                     {
409                         uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY);
410                         if (xShape.is())
411                             RemoveShape(xShape);
412                     }
413                     break;
414                     default :
415                     {
416                         // other events are not interesting
417                     }
418                     break;
419                 }
420             }
421         }
422     }
423 }
424 
425 sal_Bool ScChildrenShapes::ReplaceChild (::accessibility::AccessibleShape* pCurrentChild,
426         const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape,
427         const long _nIndex, const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo)
428     throw (uno::RuntimeException)
429 {
430     // create the new child
431     ::accessibility::AccessibleShape* pReplacement = ::accessibility::ShapeTypeHandler::Instance().CreateAccessibleObject (
432         ::accessibility::AccessibleShapeInfo ( _rxShape, pCurrentChild->getAccessibleParent(), this, _nIndex ),
433         _rShapeTreeInfo
434     );
435     ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xNewChild( pReplacement ); // keep this alive (do this before calling Init!)
436     if ( pReplacement )
437         pReplacement->Init();
438 
439     sal_Bool bResult(sal_False);
440     if (pCurrentChild && pReplacement)
441     {
442         DBG_ASSERT(pCurrentChild->GetXShape().get() == pReplacement->GetXShape().get(), "XShape changes and should be inserted sorted");
443         SortedShapes::iterator aItr;
444         FindShape(pCurrentChild->GetXShape(), aItr);
445         if (aItr != maZOrderedShapes.end() && (*aItr))
446         {
447             if ((*aItr)->pAccShape)
448             {
449                 DBG_ASSERT((*aItr)->pAccShape == pCurrentChild, "wrong child found");
450                 AccessibleEventObject aEvent;
451                 aEvent.EventId = AccessibleEventId::CHILD;
452                 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
453                 aEvent.OldValue <<= uno::makeAny(uno::Reference<XAccessible>(pCurrentChild));
454 
455                 mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
456 
457                 pCurrentChild->dispose();
458             }
459             (*aItr)->pAccShape = pReplacement;
460             AccessibleEventObject aEvent;
461             aEvent.EventId = AccessibleEventId::CHILD;
462             aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
463             aEvent.NewValue <<= uno::makeAny(uno::Reference<XAccessible>(pReplacement));
464 
465             mpAccessibleDocument->CommitChange(aEvent); // child is new - event
466             bResult = sal_True;
467         }
468     }
469     return bResult;
470 }
471 
472 sal_Int32 ScChildrenShapes::GetCount() const
473 {
474     SdrPage* pDrawPage = GetDrawPage();
475     if (pDrawPage && (maZOrderedShapes.size() == 1)) // the table is always in
476     {
477         mnSdrObjCount = pDrawPage->GetObjCount();
478         maZOrderedShapes.reserve(mnSdrObjCount + 1); // the table is always in
479         for (sal_uInt32 i = 0; i < mnSdrObjCount; ++i)
480         {
481             SdrObject* pObj = pDrawPage->GetObj(i);
482             if (pObj/* && (pObj->GetLayer() != SC_LAYER_INTERN)*/)
483             {
484                 uno::Reference< drawing::XShape > xShape (pObj->getUnoShape(), uno::UNO_QUERY);
485                 AddShape(xShape, sal_False); //inserts in the correct order
486             }
487         }
488     }
489     return maZOrderedShapes.size();
490 }
491 
492 uno::Reference< XAccessible > ScChildrenShapes::Get(const ScAccessibleShapeData* pData) const
493 {
494     if (!pData)
495         return NULL;
496 
497     if (!pData->pAccShape)
498     {
499         ::accessibility::ShapeTypeHandler& rShapeHandler = ::accessibility::ShapeTypeHandler::Instance();
500         ::accessibility::AccessibleShapeInfo aShapeInfo(pData->xShape, mpAccessibleDocument, const_cast<ScChildrenShapes*>(this));
501         pData->pAccShape = rShapeHandler.CreateAccessibleObject(
502             aShapeInfo, maShapeTreeInfo);
503         if (pData->pAccShape)
504         {
505             pData->pAccShape->acquire();
506             pData->pAccShape->Init();
507             if (pData->bSelected)
508                 pData->pAccShape->SetState(AccessibleStateType::SELECTED);
509             if (!pData->bSelectable)
510                 pData->pAccShape->ResetState(AccessibleStateType::SELECTABLE);
511             pData->pAccShape->SetRelationSet(GetRelationSet(pData));
512         }
513     }
514     return pData->pAccShape;
515  }
516 
517 uno::Reference< XAccessible > ScChildrenShapes::Get(sal_Int32 nIndex) const
518 {
519     if (maZOrderedShapes.size() <= 1)
520         GetCount(); // fill list with filtered shapes (no internal shapes)
521 
522     if (static_cast<sal_uInt32>(nIndex) >= maZOrderedShapes.size())
523         return NULL;
524 
525     return Get(maZOrderedShapes[nIndex]);
526 }
527 
528 uno::Reference< XAccessible > ScChildrenShapes::GetAt(const awt::Point& rPoint) const
529 {
530     uno::Reference<XAccessible> xAccessible;
531     if(mpViewShell)
532     {
533         sal_Int32 i(maZOrderedShapes.size() - 1);
534         sal_Bool bFound(sal_False);
535         while (!bFound && i >= 0)
536         {
537             ScAccessibleShapeData* pShape = maZOrderedShapes[i];
538             if (pShape)
539             {
540                 if (!pShape->pAccShape)
541                     Get(pShape);
542 
543                 if (pShape->pAccShape)
544                 {
545                     Point aPoint(VCLPoint(rPoint));
546                     aPoint -= VCLRectangle(pShape->pAccShape->getBounds()).TopLeft();
547                     if (pShape->pAccShape->containsPoint(AWTPoint(aPoint)))
548                     {
549                         xAccessible = pShape->pAccShape;
550                         bFound = sal_True;
551                     }
552                 }
553                 else
554                 {
555                     DBG_ERRORFILE("I should have an accessible shape now!");
556                 }
557             }
558             else
559                 bFound = sal_True; // this is the sheet and it lies before the rest of the shapes which are background shapes
560 
561             --i;
562         }
563     }
564     return xAccessible;
565 }
566 
567 sal_Bool ScChildrenShapes::IsSelected(sal_Int32 nIndex,
568                         uno::Reference<drawing::XShape>& rShape) const
569 {
570     sal_Bool bResult (sal_False);
571     if (maZOrderedShapes.size() <= 1)
572         GetCount(); // fill list with filtered shapes (no internal shapes)
573 
574     if (!xSelectionSupplier.is())
575         throw uno::RuntimeException();
576 
577     if (!maZOrderedShapes[nIndex])
578         return sal_False;
579 
580     bResult = maZOrderedShapes[nIndex]->bSelected;
581     rShape = maZOrderedShapes[nIndex]->xShape;
582 
583 #ifdef DBG_UTIL // test whether it is truly selected by a slower method
584     uno::Reference< drawing::XShape > xReturnShape;
585     sal_Bool bDebugResult(sal_False);
586     uno::Reference<container::XIndexAccess> xIndexAccess;
587     xSelectionSupplier->getSelection() >>= xIndexAccess;
588 
589     if (xIndexAccess.is())
590     {
591         sal_Int32 nCount(xIndexAccess->getCount());
592         if (nCount)
593         {
594             uno::Reference< drawing::XShape > xShape;
595             uno::Reference< drawing::XShape > xIndexShape = maZOrderedShapes[nIndex]->xShape;
596             sal_Int32 i(0);
597             while (!bDebugResult && (i < nCount))
598             {
599                 xIndexAccess->getByIndex(i) >>= xShape;
600                 if (xShape.is() && (xIndexShape.get() == xShape.get()))
601                 {
602                     bDebugResult = sal_True;
603                     xReturnShape = xShape;
604                 }
605                 else
606                     ++i;
607             }
608         }
609     }
610     DBG_ASSERT((bResult == bDebugResult) && ((bResult && (rShape.get() == xReturnShape.get())) || !bResult), "found the wrong shape or result");
611 #endif
612 
613     return bResult;
614 }
615 
616 sal_Bool ScChildrenShapes::SelectionChanged()
617 {
618     sal_Bool bResult(sal_False);
619     if (!xSelectionSupplier.is())
620         throw uno::RuntimeException();
621 
622     uno::Reference<drawing::XShapes> xShapes(xSelectionSupplier->getSelection(), uno::UNO_QUERY);
623 
624     bResult = FindSelectedShapesChanges(xShapes, sal_True);
625 
626     return bResult;
627 }
628 
629 void ScChildrenShapes::Select(sal_Int32 nIndex)
630 {
631     if (maZOrderedShapes.size() <= 1)
632         GetCount(); // fill list with filtered shapes (no internal shapes)
633 
634     if (!xSelectionSupplier.is())
635         throw uno::RuntimeException();
636 
637     if (!maZOrderedShapes[nIndex])
638         return;
639 
640     uno::Reference<drawing::XShape> xShape;
641     if (!IsSelected(nIndex, xShape) && maZOrderedShapes[nIndex]->bSelectable)
642     {
643         uno::Reference<drawing::XShapes> xShapes;
644         xSelectionSupplier->getSelection() >>= xShapes;
645 
646         if (!xShapes.is())
647             xShapes = new SvxShapeCollection();
648 
649         xShapes->add(maZOrderedShapes[nIndex]->xShape);
650 
651         try
652         {
653             xSelectionSupplier->select(uno::makeAny(xShapes));
654             maZOrderedShapes[nIndex]->bSelected = sal_True;
655             if (maZOrderedShapes[nIndex]->pAccShape)
656                 maZOrderedShapes[nIndex]->pAccShape->SetState(AccessibleStateType::SELECTED);
657         }
658         catch (lang::IllegalArgumentException&)
659         {
660         }
661     }
662 }
663 
664 void ScChildrenShapes::DeselectAll()
665 {
666     if (!xSelectionSupplier.is())
667         throw uno::RuntimeException();
668 
669     sal_Bool bSomethingSelected(sal_True);
670     try
671     {
672         xSelectionSupplier->select(uno::Any()); //deselects all
673     }
674     catch (lang::IllegalArgumentException&)
675     {
676         DBG_ERRORFILE("nothing selected before");
677         bSomethingSelected = sal_False;
678     }
679 
680     if (bSomethingSelected)
681         std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), DeselectShape());
682 }
683 
684 void ScChildrenShapes::SelectAll()
685 {
686     if (!xSelectionSupplier.is())
687         throw uno::RuntimeException();
688 
689     if (maZOrderedShapes.size() <= 1)
690         GetCount(); // fill list with filtered shapes (no internal shapes)
691 
692     if (maZOrderedShapes.size() > 1)
693     {
694         uno::Reference<drawing::XShapes> xShapes;
695         xShapes = new SvxShapeCollection();
696 
697         try
698         {
699             std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), SelectShape(xShapes));
700             xSelectionSupplier->select(uno::makeAny(xShapes));
701         }
702         catch (lang::IllegalArgumentException&)
703         {
704             SelectionChanged(); // find all selected shapes and set the flags
705         }
706     }
707 }
708 
709 void ScChildrenShapes::FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const
710 {
711     uno::Reference<container::XIndexAccess> xIndexAccess;
712     xSelectionSupplier->getSelection() >>= xIndexAccess;
713 
714     if (xIndexAccess.is())
715     {
716         sal_uInt32 nCount(xIndexAccess->getCount());
717         for (sal_uInt32 i = 0; i < nCount; ++i)
718         {
719             uno::Reference<drawing::XShape> xShape;
720             xIndexAccess->getByIndex(i) >>= xShape;
721             if (xShape.is())
722                 rShapes.push_back(xShape);
723         }
724     }
725 }
726 
727 sal_Int32 ScChildrenShapes::GetSelectedCount() const
728 {
729     if (!xSelectionSupplier.is())
730         throw uno::RuntimeException();
731 
732     std::vector < uno::Reference < drawing::XShape > > aShapes;
733     FillShapes(aShapes);
734 
735     return aShapes.size();
736 }
737 
738 uno::Reference< XAccessible > ScChildrenShapes::GetSelected(sal_Int32 nSelectedChildIndex, sal_Bool bTabSelected) const
739 {
740     uno::Reference< XAccessible > xAccessible;
741 
742     if (maZOrderedShapes.size() <= 1)
743         GetCount(); // fill list with shapes
744 
745     if (!bTabSelected)
746     {
747         std::vector < uno::Reference < drawing::XShape > > aShapes;
748         FillShapes(aShapes);
749 
750         SortedShapes::iterator aItr;
751         if (FindShape(aShapes[nSelectedChildIndex], aItr))
752             xAccessible = Get(aItr - maZOrderedShapes.begin());
753     }
754     else
755     {
756         SortedShapes::iterator aItr = maZOrderedShapes.begin();
757         SortedShapes::iterator aEndItr = maZOrderedShapes.end();
758         sal_Bool bFound(sal_False);
759         while(!bFound && aItr != aEndItr)
760         {
761             if (*aItr)
762             {
763                 if ((*aItr)->bSelected)
764                 {
765                     if (nSelectedChildIndex == 0)
766                         bFound = sal_True;
767                     else
768                         --nSelectedChildIndex;
769                 }
770             }
771             else
772             {
773                 if (nSelectedChildIndex == 0)
774                     bFound = sal_True;
775                 else
776                     --nSelectedChildIndex;
777             }
778             if (!bFound)
779                 ++aItr;
780         }
781         if (bFound && *aItr)
782             xAccessible = (*aItr)->pAccShape;
783     }
784 
785     return xAccessible;
786 }
787 
788 void ScChildrenShapes::Deselect(sal_Int32 nChildIndex)
789 {
790     uno::Reference<drawing::XShape> xShape;
791     if (IsSelected(nChildIndex, xShape)) // returns false if it is the sheet
792     {
793         if (xShape.is())
794         {
795             uno::Reference<drawing::XShapes> xShapes;
796             xSelectionSupplier->getSelection() >>= xShapes;
797             if (xShapes.is())
798                 xShapes->remove(xShape);
799 
800             try
801             {
802                 xSelectionSupplier->select(uno::makeAny(xShapes));
803             }
804             catch (lang::IllegalArgumentException&)
805             {
806                 DBG_ERRORFILE("something not selectable");
807             }
808 
809             maZOrderedShapes[nChildIndex]->bSelected = sal_False;
810             if (maZOrderedShapes[nChildIndex]->pAccShape)
811                 maZOrderedShapes[nChildIndex]->pAccShape->ResetState(AccessibleStateType::SELECTED);
812         }
813     }
814 }
815 
816 
817 SdrPage* ScChildrenShapes::GetDrawPage() const
818 {
819     SCTAB nTab(mpAccessibleDocument->getVisibleTable());
820     SdrPage* pDrawPage = NULL;
821     if (mpViewShell)
822     {
823         ScDocument* pDoc = mpViewShell->GetViewData()->GetDocument();
824         if (pDoc && pDoc->GetDrawLayer())
825         {
826             ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
827             if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab))
828                 pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(static_cast<sal_Int16>(nTab)));
829         }
830     }
831     return pDrawPage;
832 }
833 
834 struct SetRelation
835 {
836     const ScChildrenShapes* mpChildrenShapes;
837     mutable utl::AccessibleRelationSetHelper* mpRelationSet;
838     const ScAddress* mpAddress;
839     SetRelation(const ScChildrenShapes* pChildrenShapes, const ScAddress* pAddress)
840         :
841         mpChildrenShapes(pChildrenShapes),
842         mpRelationSet(NULL),
843         mpAddress(pAddress)
844     {
845     }
846     void operator() (const ScAccessibleShapeData* pAccShapeData) const
847     {
848         if (pAccShapeData &&
849             ((!pAccShapeData->pRelationCell && !mpAddress) ||
850             (pAccShapeData->pRelationCell && mpAddress && (*(pAccShapeData->pRelationCell) == *mpAddress))))
851         {
852             if (!mpRelationSet)
853                 mpRelationSet = new utl::AccessibleRelationSetHelper();
854 
855             AccessibleRelation aRelation;
856             aRelation.TargetSet.realloc(1);
857             aRelation.TargetSet[0] = mpChildrenShapes->Get(pAccShapeData);
858             aRelation.RelationType = AccessibleRelationType::CONTROLLER_FOR;
859 
860             mpRelationSet->AddRelation(aRelation);
861         }
862     }
863 };
864 
865 utl::AccessibleRelationSetHelper* ScChildrenShapes::GetRelationSet(const ScAddress* pAddress) const
866 {
867     SetRelation aSetRelation(this, pAddress);
868     ::std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), aSetRelation);
869     return aSetRelation.mpRelationSet;
870 }
871 
872 sal_Bool ScChildrenShapes::FindSelectedShapesChanges(const uno::Reference<drawing::XShapes>& xShapes, sal_Bool /* bCommitChange */) const
873 {
874     sal_Bool bResult(sal_False);
875     SortedShapes aShapesList;
876     uno::Reference<container::XIndexAccess> xIndexAcc(xShapes, uno::UNO_QUERY);
877     if (xIndexAcc.is())
878     {
879         mnShapesSelected = xIndexAcc->getCount();
880         for (sal_uInt32 i = 0; i < mnShapesSelected; ++i)
881         {
882             uno::Reference< drawing::XShape > xShape;
883             xIndexAcc->getByIndex(i) >>= xShape;
884             if (xShape.is())
885             {
886                 ScAccessibleShapeData* pShapeData = new ScAccessibleShapeData();
887                 pShapeData->xShape = xShape;
888                 aShapesList.push_back(pShapeData);
889             }
890         }
891     }
892     else
893         mnShapesSelected = 0;
894     ScShapeDataLess aLess;
895     std::sort(aShapesList.begin(), aShapesList.end(), aLess);
896 
897     SortedShapes::iterator aXShapesItr(aShapesList.begin());
898     SortedShapes::const_iterator aXShapesEndItr(aShapesList.end());
899     SortedShapes::iterator aDataItr(maZOrderedShapes.begin());
900     SortedShapes::const_iterator aDataEndItr(maZOrderedShapes.end());
901     SortedShapes::const_iterator aFocusedItr = aDataEndItr;
902     while((aDataItr != aDataEndItr))
903     {
904         if (*aDataItr) // is it realy a shape or only the sheet
905         {
906             sal_Int8 nComp(0);
907             if (aXShapesItr == aXShapesEndItr)
908                 nComp = -1; // simulate that the Shape is lower, so the selction state will be removed
909             else
910                 nComp = Compare(*aDataItr, *aXShapesItr);
911             if (nComp == 0)
912             {
913                 if (!(*aDataItr)->bSelected)
914                 {
915                     (*aDataItr)->bSelected = sal_True;
916                     if ((*aDataItr)->pAccShape)
917                     {
918                         (*aDataItr)->pAccShape->SetState(AccessibleStateType::SELECTED);
919                         (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED);
920                         bResult = sal_True;
921                     }
922                     aFocusedItr = aDataItr;
923                 }
924                 ++aDataItr;
925                 ++aXShapesItr;
926             }
927             else if (nComp < 0)
928             {
929                 if ((*aDataItr)->bSelected)
930                 {
931                     (*aDataItr)->bSelected = sal_False;
932                     if ((*aDataItr)->pAccShape)
933                     {
934                         (*aDataItr)->pAccShape->ResetState(AccessibleStateType::SELECTED);
935                         (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED);
936                         bResult = sal_True;
937                     }
938                 }
939                 ++aDataItr;
940             }
941             else
942             {
943                 DBG_ERRORFILE("here is a selected shape which is not in the childlist");
944                 ++aXShapesItr;
945                 --mnShapesSelected;
946             }
947         }
948         else
949             ++aDataItr;
950     }
951     if ((aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape && (mnShapesSelected == 1))
952         (*aFocusedItr)->pAccShape->SetState(AccessibleStateType::FOCUSED);
953 
954     std::for_each(aShapesList.begin(), aShapesList.end(), Destroy());
955 
956     return bResult;
957 }
958 
959 void ScChildrenShapes::FillSelectionSupplier() const
960 {
961     if (!xSelectionSupplier.is() && mpViewShell)
962     {
963         SfxViewFrame* pViewFrame = mpViewShell->GetViewFrame();
964         if (pViewFrame)
965         {
966             xSelectionSupplier = uno::Reference<view::XSelectionSupplier>(pViewFrame->GetFrame().GetController(), uno::UNO_QUERY);
967             if (xSelectionSupplier.is())
968             {
969                 if (mpAccessibleDocument)
970                     xSelectionSupplier->addSelectionChangeListener(mpAccessibleDocument);
971                 uno::Reference<drawing::XShapes> xShapes (xSelectionSupplier->getSelection(), uno::UNO_QUERY);
972                 if (xShapes.is())
973                     mnShapesSelected = xShapes->getCount();
974             }
975         }
976     }
977 }
978 
979 ScAddress* ScChildrenShapes::GetAnchor(const uno::Reference<drawing::XShape>& xShape) const
980 {
981     ScAddress* pAddress = NULL;
982     if (mpViewShell)
983     {
984         SvxShape* pShapeImp = SvxShape::getImplementation(xShape);
985         uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY);
986         if (pShapeImp && xShapeProp.is())
987         {
988             SdrObject *pSdrObj = pShapeImp->GetSdrObject();
989             if (pSdrObj)
990             {
991                 if (ScDrawLayer::GetAnchor(pSdrObj) == SCA_CELL)
992                 {
993                     ScDocument* pDoc = mpViewShell->GetViewData()->GetDocument();
994                     if (pDoc)
995                     {
996                         rtl::OUString sCaptionShape(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CaptionShape"));
997                         awt::Point aPoint(xShape->getPosition());
998                         awt::Size aSize(xShape->getSize());
999                         rtl::OUString sType(xShape->getShapeType());
1000                         Rectangle aRectangle(aPoint.X, aPoint.Y, aPoint.X + aSize.Width, aPoint.Y + aSize.Height);
1001                         if ( sType.equals(sCaptionShape) )
1002                         {
1003                             awt::Point aRelativeCaptionPoint;
1004                             rtl::OUString sCaptionPoint( RTL_CONSTASCII_USTRINGPARAM( "CaptionPoint" ));
1005                             xShapeProp->getPropertyValue( sCaptionPoint ) >>= aRelativeCaptionPoint;
1006                             Point aCoreRelativeCaptionPoint(aRelativeCaptionPoint.X, aRelativeCaptionPoint.Y);
1007                             Point aCoreAbsoluteCaptionPoint(aPoint.X, aPoint.Y);
1008                             aCoreAbsoluteCaptionPoint += aCoreRelativeCaptionPoint;
1009                             aRectangle.Union(Rectangle(aCoreAbsoluteCaptionPoint, aCoreAbsoluteCaptionPoint));
1010                         }
1011                         ScRange aRange = pDoc->GetRange(mpAccessibleDocument->getVisibleTable(), aRectangle);
1012                         pAddress = new ScAddress(aRange.aStart);
1013                     }
1014                 }
1015 //              else
1016 //                  do nothing, because it is always a NULL Pointer
1017             }
1018         }
1019     }
1020 
1021     return pAddress;
1022 }
1023 
1024 uno::Reference<XAccessibleRelationSet> ScChildrenShapes::GetRelationSet(const ScAccessibleShapeData* pData) const
1025 {
1026     utl::AccessibleRelationSetHelper* pRelationSet = new utl::AccessibleRelationSetHelper();
1027 
1028     if(pData && pRelationSet && mpAccessibleDocument)
1029     {
1030         uno::Reference<XAccessible> xAccessible = mpAccessibleDocument->GetAccessibleSpreadsheet(); // should be the current table
1031         if (pData->pRelationCell && xAccessible.is())
1032         {
1033             uno::Reference<XAccessibleTable> xAccTable (xAccessible->getAccessibleContext(), uno::UNO_QUERY);
1034             if (xAccTable.is())
1035                 xAccessible = xAccTable->getAccessibleCellAt(pData->pRelationCell->Row(), pData->pRelationCell->Col());
1036         }
1037         AccessibleRelation aRelation;
1038         aRelation.TargetSet.realloc(1);
1039         aRelation.TargetSet[0] = xAccessible;
1040         aRelation.RelationType = AccessibleRelationType::CONTROLLED_BY;
1041         pRelationSet->AddRelation(aRelation);
1042     }
1043 
1044     return pRelationSet;
1045 }
1046 
1047 void ScChildrenShapes::CheckWhetherAnchorChanged(const uno::Reference<drawing::XShape>& xShape) const
1048 {
1049     SortedShapes::iterator aItr;
1050     if (FindShape(xShape, aItr))
1051         SetAnchor(xShape, *aItr);
1052 }
1053 
1054 void ScChildrenShapes::SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const
1055 {
1056     if (pData)
1057     {
1058         ScAddress* pAddress = GetAnchor(xShape);
1059         if ((pAddress && pData->pRelationCell && (*pAddress != *(pData->pRelationCell))) ||
1060             (!pAddress && pData->pRelationCell) || (pAddress && !pData->pRelationCell))
1061         {
1062             if (pData->pRelationCell)
1063                 delete pData->pRelationCell;
1064             pData->pRelationCell = pAddress;
1065             if (pData->pAccShape)
1066                 pData->pAccShape->SetRelationSet(GetRelationSet(pData));
1067         }
1068     }
1069 }
1070 
1071 void ScChildrenShapes::AddShape(const uno::Reference<drawing::XShape>& xShape, sal_Bool bCommitChange) const
1072 {
1073     SortedShapes::iterator aFindItr;
1074     if (!FindShape(xShape, aFindItr))
1075     {
1076         ScAccessibleShapeData* pShape = new ScAccessibleShapeData();
1077         pShape->xShape = xShape;
1078         SortedShapes::iterator aNewItr = maZOrderedShapes.insert(aFindItr, pShape);
1079         SetAnchor(xShape, pShape);
1080 
1081         uno::Reference< beans::XPropertySet > xShapeProp(xShape, uno::UNO_QUERY);
1082         if (xShapeProp.is())
1083         {
1084             uno::Any aPropAny = xShapeProp->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(  "LayerID" )));
1085             sal_Int16 nLayerID = 0;
1086             if( aPropAny >>= nLayerID )
1087             {
1088                 if( (nLayerID == SC_LAYER_INTERN) || (nLayerID == SC_LAYER_HIDDEN) )
1089                     pShape->bSelectable = sal_False;
1090                 else
1091                     pShape->bSelectable = sal_True;
1092             }
1093         }
1094 
1095 
1096         if (!xSelectionSupplier.is())
1097             throw uno::RuntimeException();
1098 
1099         uno::Reference<container::XEnumerationAccess> xEnumAcc(xSelectionSupplier->getSelection(), uno::UNO_QUERY);
1100         if (xEnumAcc.is())
1101         {
1102             uno::Reference<container::XEnumeration> xEnum = xEnumAcc->createEnumeration();
1103             if (xEnum.is())
1104             {
1105                 uno::Reference<drawing::XShape> xSelectedShape;
1106                 sal_Bool bFound(sal_False);
1107                 while (!bFound && xEnum->hasMoreElements())
1108                 {
1109                     xEnum->nextElement() >>= xSelectedShape;
1110                     if (xShape.is() && (xShape.get() == xSelectedShape.get()))
1111                     {
1112                         pShape->bSelected = sal_True;
1113                         bFound = sal_True;
1114                     }
1115                 }
1116             }
1117         }
1118         if (mpAccessibleDocument && bCommitChange)
1119         {
1120             AccessibleEventObject aEvent;
1121             aEvent.EventId = AccessibleEventId::CHILD;
1122             aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1123             aEvent.NewValue <<= Get(aNewItr - maZOrderedShapes.begin());
1124 
1125             mpAccessibleDocument->CommitChange(aEvent); // new child - event
1126         }
1127     }
1128     else
1129     {
1130         DBG_ERRORFILE("shape is always in the list");
1131     }
1132 }
1133 
1134 void ScChildrenShapes::RemoveShape(const uno::Reference<drawing::XShape>& xShape) const
1135 {
1136     SortedShapes::iterator aItr;
1137     if (FindShape(xShape, aItr))
1138     {
1139         if (mpAccessibleDocument)
1140         {
1141             uno::Reference<XAccessible> xOldAccessible (Get(aItr - maZOrderedShapes.begin()));
1142 
1143             delete *aItr;
1144             maZOrderedShapes.erase(aItr);
1145 
1146             AccessibleEventObject aEvent;
1147             aEvent.EventId = AccessibleEventId::CHILD;
1148             aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1149             aEvent.OldValue <<= uno::makeAny(xOldAccessible);
1150 
1151             mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
1152         }
1153         else
1154         {
1155             delete *aItr;
1156             maZOrderedShapes.erase(aItr);
1157         }
1158     }
1159     else
1160     {
1161         DBG_ERRORFILE("shape was not in internal list");
1162     }
1163 }
1164 
1165 sal_Bool ScChildrenShapes::FindShape(const uno::Reference<drawing::XShape>& xShape, ScChildrenShapes::SortedShapes::iterator& rItr) const
1166 {
1167     sal_Bool bResult(sal_False);
1168     ScAccessibleShapeData aShape;
1169     aShape.xShape = xShape;
1170     ScShapeDataLess aLess;
1171     rItr = std::lower_bound(maZOrderedShapes.begin(), maZOrderedShapes.end(), &aShape, aLess);
1172     if ((rItr != maZOrderedShapes.end()) && (*rItr != NULL) && ((*rItr)->xShape.get() == xShape.get()))
1173         bResult = sal_True; // if the shape is found
1174 
1175 #ifdef DBG_UTIL // test whether it finds truly the correct shape (perhaps it is not really sorted)
1176     SortedShapes::iterator aDebugItr = maZOrderedShapes.begin();
1177     SortedShapes::iterator aEndItr = maZOrderedShapes.end();
1178     sal_Bool bFound(sal_False);
1179     while (!bFound && aDebugItr != aEndItr)
1180     {
1181         if (*aDebugItr && ((*aDebugItr)->xShape.get() == xShape.get()))
1182             bFound = sal_True;
1183         else
1184             ++aDebugItr;
1185     }
1186     sal_Bool bResult2 = (aDebugItr != maZOrderedShapes.end());
1187     DBG_ASSERT((bResult == bResult2) && ((bResult && (rItr == aDebugItr)) || !bResult), "wrong Shape found");
1188 #endif
1189     return bResult;
1190 }
1191 
1192 sal_Int8 ScChildrenShapes::Compare(const ScAccessibleShapeData* pData1,
1193         const ScAccessibleShapeData* pData2) const
1194 {
1195     ScShapeDataLess aLess;
1196 
1197     sal_Bool bResult1(aLess(pData1, pData2));
1198     sal_Bool bResult2(aLess(pData2, pData1));
1199 
1200     sal_Int8 nResult(0);
1201     if (!bResult1 && bResult2)
1202         nResult = 1;
1203     else if (bResult1 && !bResult2)
1204         nResult = -1;
1205 
1206     return nResult;
1207 }
1208 
1209 struct ScVisAreaChanged
1210 {
1211     ScAccessibleDocument* mpAccDoc;
1212     ScVisAreaChanged(ScAccessibleDocument* pAccDoc) : mpAccDoc(pAccDoc) {}
1213     void operator() (const ScAccessibleShapeData* pAccShapeData) const
1214     {
1215         if (pAccShapeData && pAccShapeData->pAccShape)
1216         {
1217             pAccShapeData->pAccShape->ViewForwarderChanged(::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA, mpAccDoc);
1218         }
1219     }
1220 };
1221 
1222 void ScChildrenShapes::VisAreaChanged() const
1223 {
1224     ScVisAreaChanged aVisAreaChanged(mpAccessibleDocument);
1225     std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), aVisAreaChanged);
1226 }
1227 
1228 // ============================================================================
1229 
1230 ScAccessibleDocument::ScAccessibleDocument(
1231         const uno::Reference<XAccessible>& rxParent,
1232         ScTabViewShell* pViewShell,
1233         ScSplitPos eSplitPos)
1234     : ScAccessibleDocumentBase(rxParent),
1235     mpViewShell(pViewShell),
1236     meSplitPos(eSplitPos),
1237     mpAccessibleSpreadsheet(NULL),
1238     mpChildrenShapes(NULL),
1239     mpTempAccEdit(NULL),
1240     mbCompleteSheetSelected(sal_False)
1241 {
1242     if (pViewShell)
1243     {
1244         pViewShell->AddAccessibilityObject(*this);
1245         Window *pWin = pViewShell->GetWindowByPos(eSplitPos);
1246         if( pWin )
1247         {
1248             pWin->AddChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1249             sal_uInt16 nCount =   pWin->GetChildCount();
1250             for( sal_uInt16 i=0; i < nCount; ++i )
1251             {
1252                 Window *pChildWin = pWin->GetChild( i );
1253                 if( pChildWin &&
1254                     AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1255                     AddChild( pChildWin->GetAccessible(), sal_False );
1256             }
1257         }
1258         if (pViewShell->GetViewData()->HasEditView( eSplitPos ))
1259         {
1260             uno::Reference<XAccessible> xAcc = new ScAccessibleEditObject(this, pViewShell->GetViewData()->GetEditView(eSplitPos),
1261                 pViewShell->GetWindowByPos(eSplitPos), GetCurrentCellName(), GetCurrentCellDescription(),
1262                 CellInEditMode);
1263             AddChild(xAcc, sal_False);
1264         }
1265     }
1266     maVisArea = GetVisibleArea_Impl();
1267 }
1268 
1269 void ScAccessibleDocument::Init()
1270 {
1271     if(!mpChildrenShapes)
1272         mpChildrenShapes = new ScChildrenShapes(this, mpViewShell, meSplitPos);
1273 }
1274 
1275 ScAccessibleDocument::~ScAccessibleDocument(void)
1276 {
1277     if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
1278     {
1279         // increment refcount to prevent double call off dtor
1280         osl_incrementInterlockedCount( &m_refCount );
1281         dispose();
1282     }
1283 }
1284 
1285 void SAL_CALL ScAccessibleDocument::disposing()
1286 {
1287     ScUnoGuard aGuard;
1288     FreeAccessibleSpreadsheet();
1289     if (mpViewShell)
1290     {
1291         Window *pWin = mpViewShell->GetWindowByPos(meSplitPos);
1292         if( pWin )
1293             pWin->RemoveChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1294 
1295         mpViewShell->RemoveAccessibilityObject(*this);
1296         mpViewShell = NULL;
1297     }
1298     if (mpChildrenShapes)
1299         DELETEZ(mpChildrenShapes);
1300 
1301     ScAccessibleDocumentBase::disposing();
1302 }
1303 
1304 void SAL_CALL ScAccessibleDocument::disposing( const lang::EventObject& /* Source */ )
1305         throw (uno::RuntimeException)
1306 {
1307     disposing();
1308 }
1309 
1310     //=====  SfxListener  =====================================================
1311 
1312 IMPL_LINK( ScAccessibleDocument, WindowChildEventListener, VclSimpleEvent*, pEvent )
1313 {
1314     DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
1315     if ( pEvent && pEvent->ISA( VclWindowEvent ) )
1316     {
1317         VclWindowEvent *pVclEvent = static_cast< VclWindowEvent * >( pEvent );
1318         DBG_ASSERT( pVclEvent->GetWindow(), "Window???" );
1319         switch ( pVclEvent->GetId() )
1320         {
1321         case VCLEVENT_WINDOW_SHOW:  // send create on show for direct accessible children
1322             {
1323                 Window* pChildWin = static_cast < Window * >( pVclEvent->GetData() );
1324                 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1325                 {
1326                     AddChild( pChildWin->GetAccessible(), sal_True );
1327                 }
1328             }
1329             break;
1330         case VCLEVENT_WINDOW_HIDE:  // send destroy on hide for direct accessible children
1331             {
1332                 Window* pChildWin = static_cast < Window * >( pVclEvent->GetData() );
1333                 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1334                 {
1335                     RemoveChild( pChildWin->GetAccessible(), sal_True );
1336                 }
1337             }
1338             break;
1339         }
1340     }
1341     return 0;
1342 }
1343 
1344 void ScAccessibleDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1345 {
1346     if (rHint.ISA( ScAccGridWinFocusLostHint ) )
1347     {
1348         const ScAccGridWinFocusLostHint& rRef = (const ScAccGridWinFocusLostHint&)rHint;
1349         if (rRef.GetOldGridWin() == meSplitPos)
1350         {
1351             if (mxTempAcc.is() && mpTempAccEdit)
1352                 mpTempAccEdit->LostFocus();
1353             else if (mpAccessibleSpreadsheet)
1354                 mpAccessibleSpreadsheet->LostFocus();
1355             else
1356                 CommitFocusLost();
1357         }
1358     }
1359     else if (rHint.ISA( ScAccGridWinFocusGotHint ) )
1360     {
1361         const ScAccGridWinFocusGotHint& rRef = (const ScAccGridWinFocusGotHint&)rHint;
1362         if (rRef.GetNewGridWin() == meSplitPos)
1363         {
1364             if (mxTempAcc.is() && mpTempAccEdit)
1365                 mpTempAccEdit->GotFocus();
1366             else if (mpAccessibleSpreadsheet)
1367                 mpAccessibleSpreadsheet->GotFocus();
1368             else
1369                 CommitFocusGained();
1370         }
1371     }
1372     else if (rHint.ISA( SfxSimpleHint ))
1373     {
1374         const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
1375         // only notify if child exist, otherwise it is not necessary
1376         if ((rRef.GetId() == SC_HINT_ACC_TABLECHANGED) &&
1377             mpAccessibleSpreadsheet)
1378         {
1379             FreeAccessibleSpreadsheet();
1380             if (mpChildrenShapes)
1381                 DELETEZ(mpChildrenShapes);
1382 
1383             // #124567# Accessibility: Shapes / form controls after reload not accessible
1384             if ( !mpChildrenShapes )
1385             {
1386                 mpChildrenShapes = new ScChildrenShapes( this, mpViewShell, meSplitPos );
1387             }
1388 
1389             AccessibleEventObject aEvent;
1390             aEvent.EventId = AccessibleEventId::INVALIDATE_ALL_CHILDREN;
1391             aEvent.Source = uno::Reference< XAccessibleContext >(this);
1392             CommitChange(aEvent); // all childs changed
1393         }
1394         else if (rRef.GetId() == SC_HINT_ACC_MAKEDRAWLAYER)
1395         {
1396             if (mpChildrenShapes)
1397                 mpChildrenShapes->SetDrawBroadcaster();
1398         }
1399         else if ((rRef.GetId() == SC_HINT_ACC_ENTEREDITMODE)) // this event comes only on creating edit field of a cell
1400         {
1401             if (mpViewShell && mpViewShell->GetViewData()->HasEditView(meSplitPos))
1402             {
1403                 mpTempAccEdit = new ScAccessibleEditObject(this, mpViewShell->GetViewData()->GetEditView(meSplitPos),
1404                     mpViewShell->GetWindowByPos(meSplitPos), GetCurrentCellName(),
1405                     rtl::OUString(String(ScResId(STR_ACC_EDITLINE_DESCR))), CellInEditMode);
1406                 uno::Reference<XAccessible> xAcc = mpTempAccEdit;
1407 
1408                 AddChild(xAcc, sal_True);
1409 
1410                 if (mpAccessibleSpreadsheet)
1411                     mpAccessibleSpreadsheet->LostFocus();
1412                 else
1413                     CommitFocusLost();
1414 
1415                 mpTempAccEdit->GotFocus();
1416             }
1417         }
1418         else if (rRef.GetId() == SC_HINT_ACC_LEAVEEDITMODE)
1419         {
1420             if (mxTempAcc.is())
1421             {
1422                 if (mpTempAccEdit)
1423                     mpTempAccEdit->LostFocus();
1424 
1425                 mpTempAccEdit = NULL;
1426                 RemoveChild(mxTempAcc, sal_True);
1427 
1428                 if (mpAccessibleSpreadsheet)
1429                     mpAccessibleSpreadsheet->GotFocus();
1430                 else
1431                     CommitFocusGained();
1432             }
1433         }
1434         else if ((rRef.GetId() == SC_HINT_ACC_VISAREACHANGED) || (rRef.GetId() == SC_HINT_ACC_WINDOWRESIZED))
1435         {
1436             Rectangle aOldVisArea(maVisArea);
1437             maVisArea = GetVisibleArea_Impl();
1438 
1439             if (maVisArea != aOldVisArea)
1440             {
1441                 if (maVisArea.GetSize() != aOldVisArea.GetSize())
1442                 {
1443                     AccessibleEventObject aEvent;
1444                     aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
1445                     aEvent.Source = uno::Reference< XAccessibleContext >(this);
1446 
1447                     CommitChange(aEvent);
1448 
1449                     if (mpAccessibleSpreadsheet)
1450                         mpAccessibleSpreadsheet->BoundingBoxChanged();
1451                 }
1452                 else if (mpAccessibleSpreadsheet)
1453                 {
1454                     mpAccessibleSpreadsheet->VisAreaChanged();
1455                 }
1456                 if (mpChildrenShapes)
1457                     mpChildrenShapes->VisAreaChanged();
1458             }
1459         }
1460     }
1461 
1462     ScAccessibleDocumentBase::Notify(rBC, rHint);
1463 }
1464 
1465 void SAL_CALL ScAccessibleDocument::selectionChanged( const lang::EventObject& /* aEvent */ )
1466         throw (uno::RuntimeException)
1467 {
1468     sal_Bool bSelectionChanged(sal_False);
1469     if (mpAccessibleSpreadsheet)
1470     {
1471         sal_Bool bOldSelected(mbCompleteSheetSelected);
1472         mbCompleteSheetSelected = IsTableSelected();
1473         if (bOldSelected != mbCompleteSheetSelected)
1474         {
1475             mpAccessibleSpreadsheet->CompleteSelectionChanged(mbCompleteSheetSelected);
1476             bSelectionChanged = sal_True;
1477         }
1478     }
1479 
1480     if (mpChildrenShapes && mpChildrenShapes->SelectionChanged())
1481         bSelectionChanged = sal_True;
1482 
1483     if (bSelectionChanged)
1484     {
1485         AccessibleEventObject aEvent;
1486         aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1487         aEvent.Source = uno::Reference< XAccessibleContext >(this);
1488 
1489         CommitChange(aEvent);
1490     }
1491 }
1492 
1493     //=====  XInterface  =====================================================
1494 
1495 uno::Any SAL_CALL ScAccessibleDocument::queryInterface( uno::Type const & rType )
1496     throw (uno::RuntimeException)
1497 {
1498     uno::Any aAny (ScAccessibleDocumentImpl::queryInterface(rType));
1499     return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType);
1500 }
1501 
1502 void SAL_CALL ScAccessibleDocument::acquire()
1503     throw ()
1504 {
1505     ScAccessibleContextBase::acquire();
1506 }
1507 
1508 void SAL_CALL ScAccessibleDocument::release()
1509     throw ()
1510 {
1511     ScAccessibleContextBase::release();
1512 }
1513 
1514     //=====  XAccessibleComponent  ============================================
1515 
1516 uno::Reference< XAccessible > SAL_CALL ScAccessibleDocument::getAccessibleAtPoint(
1517         const awt::Point& rPoint )
1518         throw (uno::RuntimeException)
1519 {
1520     uno::Reference<XAccessible> xAccessible = NULL;
1521     if (containsPoint(rPoint))
1522     {
1523         ScUnoGuard aGuard;
1524         IsObjectValid();
1525         if (mpChildrenShapes)
1526             xAccessible = mpChildrenShapes->GetAt(rPoint);
1527         if(!xAccessible.is())
1528         {
1529             if (mxTempAcc.is())
1530             {
1531                 uno::Reference< XAccessibleContext > xCont(mxTempAcc->getAccessibleContext());
1532                 uno::Reference< XAccessibleComponent > xComp(xCont, uno::UNO_QUERY);
1533                 if (xComp.is())
1534                 {
1535                     Rectangle aBound(VCLRectangle(xComp->getBounds()));
1536                     if (aBound.IsInside(VCLPoint(rPoint)))
1537                         xAccessible = mxTempAcc;
1538                 }
1539             }
1540             if (!xAccessible.is())
1541                 xAccessible = GetAccessibleSpreadsheet();
1542         }
1543     }
1544     return xAccessible;
1545 }
1546 
1547 void SAL_CALL ScAccessibleDocument::grabFocus(  )
1548         throw (uno::RuntimeException)
1549 {
1550     ScUnoGuard aGuard;
1551     IsObjectValid();
1552     if (getAccessibleParent().is())
1553     {
1554         uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1555         if (xAccessibleComponent.is())
1556         {
1557             xAccessibleComponent->grabFocus();
1558             // grab only focus if it does not have the focus and it is not hidden
1559             if (mpViewShell && mpViewShell->GetViewData() &&
1560                 (mpViewShell->GetViewData()->GetActivePart() != meSplitPos) &&
1561                 mpViewShell->GetWindowByPos(meSplitPos)->IsVisible())
1562             {
1563                 mpViewShell->ActivatePart(meSplitPos);
1564             }
1565         }
1566     }
1567 }
1568 
1569     //=====  XAccessibleContext  ==============================================
1570 
1571     /// Return the number of currently visible children.
1572 sal_Int32 SAL_CALL
1573     ScAccessibleDocument::getAccessibleChildCount(void)
1574     throw (uno::RuntimeException)
1575 {
1576     ScUnoGuard aGuard;
1577     IsObjectValid();
1578     sal_Int32 nCount(1);
1579     if (mpChildrenShapes)
1580         nCount = mpChildrenShapes->GetCount(); // returns the count of the shapes inclusive the table
1581 
1582     if (mxTempAcc.is())
1583         ++nCount;
1584 
1585     return nCount;
1586 }
1587 
1588     /// Return the specified child or NULL if index is invalid.
1589 uno::Reference<XAccessible> SAL_CALL
1590     ScAccessibleDocument::getAccessibleChild(sal_Int32 nIndex)
1591     throw (uno::RuntimeException,
1592         lang::IndexOutOfBoundsException)
1593 {
1594     ScUnoGuard aGuard;
1595     IsObjectValid();
1596     uno::Reference<XAccessible> xAccessible;
1597     if (nIndex >= 0)
1598     {
1599         sal_Int32 nCount(1);
1600         if (mpChildrenShapes)
1601         {
1602             xAccessible = mpChildrenShapes->Get(nIndex); // returns NULL if it is the table or out of range
1603             nCount = mpChildrenShapes->GetCount(); //there is always a table
1604         }
1605         if (!xAccessible.is())
1606         {
1607             if (nIndex < nCount)
1608                 xAccessible = GetAccessibleSpreadsheet();
1609             else if (nIndex == nCount && mxTempAcc.is())
1610                 xAccessible = mxTempAcc;
1611         }
1612     }
1613 
1614     if (!xAccessible.is())
1615         throw lang::IndexOutOfBoundsException();
1616 
1617     return xAccessible;
1618 }
1619 
1620     /// Return the set of current states.
1621 uno::Reference<XAccessibleStateSet> SAL_CALL
1622     ScAccessibleDocument::getAccessibleStateSet(void)
1623     throw (uno::RuntimeException)
1624 {
1625     ScUnoGuard aGuard;
1626     uno::Reference<XAccessibleStateSet> xParentStates;
1627     if (getAccessibleParent().is())
1628     {
1629         uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1630         xParentStates = xParentContext->getAccessibleStateSet();
1631     }
1632     utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
1633     if (IsDefunc(xParentStates))
1634         pStateSet->AddState(AccessibleStateType::DEFUNC);
1635     else
1636     {
1637         if (IsEditable(xParentStates))
1638             pStateSet->AddState(AccessibleStateType::EDITABLE);
1639         pStateSet->AddState(AccessibleStateType::ENABLED);
1640         pStateSet->AddState(AccessibleStateType::OPAQUE);
1641         if (isShowing())
1642             pStateSet->AddState(AccessibleStateType::SHOWING);
1643         if (isVisible())
1644             pStateSet->AddState(AccessibleStateType::VISIBLE);
1645     }
1646     return pStateSet;
1647 }
1648 
1649     ///=====  XAccessibleSelection  ===========================================
1650 
1651 void SAL_CALL
1652     ScAccessibleDocument::selectAccessibleChild( sal_Int32 nChildIndex )
1653         throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1654 {
1655     ScUnoGuard aGuard;
1656     IsObjectValid();
1657 
1658     if (mpChildrenShapes)
1659     {
1660         sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table
1661         if (mxTempAcc.is())
1662             ++nCount;
1663         if (nChildIndex < 0 || nChildIndex >= nCount)
1664             throw lang::IndexOutOfBoundsException();
1665 
1666         uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1667         if (xAccessible.is())
1668         {
1669             sal_Bool bWasTableSelected(IsTableSelected());
1670 
1671             if (mpChildrenShapes)
1672                 mpChildrenShapes->Select(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is to high
1673 
1674             if (bWasTableSelected)
1675                 mpViewShell->SelectAll();
1676         }
1677         else
1678         {
1679             if (mpViewShell)
1680                 mpViewShell->SelectAll();
1681         }
1682     }
1683 }
1684 
1685 sal_Bool SAL_CALL
1686     ScAccessibleDocument::isAccessibleChildSelected( sal_Int32 nChildIndex )
1687         throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1688 {
1689     ScUnoGuard aGuard;
1690     IsObjectValid();
1691     sal_Bool bResult(sal_False);
1692 
1693     if (mpChildrenShapes)
1694     {
1695         sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table
1696         if (mxTempAcc.is())
1697             ++nCount;
1698         if (nChildIndex < 0 || nChildIndex >= nCount)
1699             throw lang::IndexOutOfBoundsException();
1700 
1701         uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1702         if (xAccessible.is())
1703         {
1704             uno::Reference<drawing::XShape> xShape;
1705             bResult = mpChildrenShapes->IsSelected(nChildIndex, xShape); // throws no lang::IndexOutOfBoundsException if Index is to high
1706         }
1707         else
1708         {
1709             if (mxTempAcc.is() && nChildIndex == nCount)
1710                 bResult = sal_True;
1711             else
1712                 bResult = IsTableSelected();
1713         }
1714     }
1715     return bResult;
1716 }
1717 
1718 void SAL_CALL
1719     ScAccessibleDocument::clearAccessibleSelection(  )
1720         throw (uno::RuntimeException)
1721 {
1722     ScUnoGuard aGuard;
1723     IsObjectValid();
1724 
1725     if (mpChildrenShapes)
1726         mpChildrenShapes->DeselectAll(); //deselects all (also the table)
1727 }
1728 
1729 void SAL_CALL
1730     ScAccessibleDocument::selectAllAccessibleChildren(  )
1731         throw (uno::RuntimeException)
1732 {
1733     ScUnoGuard aGuard;
1734     IsObjectValid();
1735 
1736     if (mpChildrenShapes)
1737         mpChildrenShapes->SelectAll();
1738 
1739     // select table after shapes, because while selecting shapes the table will be deselected
1740     if (mpViewShell)
1741     {
1742         mpViewShell->SelectAll();
1743     }
1744 }
1745 
1746 sal_Int32 SAL_CALL
1747     ScAccessibleDocument::getSelectedAccessibleChildCount(  )
1748         throw (uno::RuntimeException)
1749 {
1750     ScUnoGuard aGuard;
1751     IsObjectValid();
1752     sal_Int32 nCount(0);
1753 
1754     if (mpChildrenShapes)
1755         nCount = mpChildrenShapes->GetSelectedCount();
1756 
1757     if (IsTableSelected())
1758         ++nCount;
1759 
1760     if (mxTempAcc.is())
1761         ++nCount;
1762 
1763     return nCount;
1764 }
1765 
1766 uno::Reference<XAccessible > SAL_CALL
1767     ScAccessibleDocument::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
1768         throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1769 {
1770     ScUnoGuard aGuard;
1771     IsObjectValid();
1772     uno::Reference<XAccessible> xAccessible;
1773     if (mpChildrenShapes)
1774     {
1775         sal_Int32 nCount(getSelectedAccessibleChildCount()); //all shapes and the table
1776         if (nSelectedChildIndex < 0 || nSelectedChildIndex >= nCount)
1777             throw lang::IndexOutOfBoundsException();
1778 
1779         sal_Bool bTabMarked(IsTableSelected());
1780 
1781         if (mpChildrenShapes)
1782             xAccessible = mpChildrenShapes->GetSelected(nSelectedChildIndex, bTabMarked); // throws no lang::IndexOutOfBoundsException if Index is to high
1783         if (mxTempAcc.is() && nSelectedChildIndex == nCount - 1)
1784             xAccessible = mxTempAcc;
1785         else if (bTabMarked)
1786             xAccessible = GetAccessibleSpreadsheet();
1787     }
1788 
1789     DBG_ASSERT(xAccessible.is(), "here should always be an accessible object or a exception throwed");
1790 
1791     return xAccessible;
1792 }
1793 
1794 void SAL_CALL
1795     ScAccessibleDocument::deselectAccessibleChild( sal_Int32 nChildIndex )
1796         throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1797 {
1798     ScUnoGuard aGuard;
1799     IsObjectValid();
1800 
1801     if (mpChildrenShapes)
1802     {
1803         sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table
1804         if (mxTempAcc.is())
1805             ++nCount;
1806         if (nChildIndex < 0 || nChildIndex >= nCount)
1807             throw lang::IndexOutOfBoundsException();
1808 
1809         sal_Bool bTabMarked(IsTableSelected());
1810 
1811         uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1812         if (xAccessible.is())
1813         {
1814             if (mpChildrenShapes)
1815                 mpChildrenShapes->Deselect(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is to high
1816 
1817             if (bTabMarked)
1818                 mpViewShell->SelectAll(); // select the table again
1819         }
1820         else if (bTabMarked)
1821             mpViewShell->Unmark();
1822     }
1823 }
1824 
1825     //=====  XServiceInfo  ====================================================
1826 
1827 ::rtl::OUString SAL_CALL
1828     ScAccessibleDocument::getImplementationName(void)
1829     throw (uno::RuntimeException)
1830 {
1831     return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleDocument"));
1832 }
1833 
1834 uno::Sequence< ::rtl::OUString> SAL_CALL
1835     ScAccessibleDocument::getSupportedServiceNames(void)
1836         throw (uno::RuntimeException)
1837 {
1838     uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
1839     sal_Int32 nOldSize(aSequence.getLength());
1840     aSequence.realloc(nOldSize + 1);
1841     ::rtl::OUString* pNames = aSequence.getArray();
1842 
1843     pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.AccessibleSpreadsheetDocumentView"));
1844 
1845     return aSequence;
1846 }
1847 
1848 //=====  XTypeProvider  =======================================================
1849 
1850 uno::Sequence< uno::Type > SAL_CALL ScAccessibleDocument::getTypes()
1851         throw (uno::RuntimeException)
1852 {
1853     return comphelper::concatSequences(ScAccessibleDocumentImpl::getTypes(), ScAccessibleContextBase::getTypes());
1854 }
1855 
1856 uno::Sequence<sal_Int8> SAL_CALL
1857     ScAccessibleDocument::getImplementationId(void)
1858     throw (uno::RuntimeException)
1859 {
1860     ScUnoGuard aGuard;
1861     IsObjectValid();
1862     static uno::Sequence<sal_Int8> aId;
1863     if (aId.getLength() == 0)
1864     {
1865         aId.realloc (16);
1866         rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
1867     }
1868     return aId;
1869 }
1870 
1871 ///=====  IAccessibleViewForwarder  ========================================
1872 
1873 sal_Bool ScAccessibleDocument::IsValid (void) const
1874 {
1875     ScUnoGuard aGuard;
1876     IsObjectValid();
1877     return (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose);
1878 }
1879 
1880 Rectangle ScAccessibleDocument::GetVisibleArea_Impl() const
1881 {
1882     Rectangle aVisRect(GetBoundingBox());
1883 
1884     Point aPoint(mpViewShell->GetViewData()->GetPixPos(meSplitPos)); // returns a negative Point
1885     aPoint.setX(-aPoint.getX());
1886     aPoint.setY(-aPoint.getY());
1887     aVisRect.SetPos(aPoint);
1888 
1889     ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1890     if (pWin)
1891         aVisRect = pWin->PixelToLogic(aVisRect, pWin->GetDrawMapMode());
1892 
1893     return aVisRect;
1894 }
1895 
1896 Rectangle ScAccessibleDocument::GetVisibleArea() const
1897 {
1898     ScUnoGuard aGuard;
1899     IsObjectValid();
1900     return maVisArea;
1901 }
1902 
1903 Point ScAccessibleDocument::LogicToPixel (const Point& rPoint) const
1904 {
1905     ScUnoGuard aGuard;
1906     IsObjectValid();
1907     Point aPoint;
1908     ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1909     if (pWin)
1910     {
1911         aPoint = pWin->LogicToPixel(rPoint, pWin->GetDrawMapMode());
1912         aPoint += pWin->GetWindowExtentsRelative(NULL).TopLeft();
1913     }
1914     return aPoint;
1915 }
1916 
1917 Size ScAccessibleDocument::LogicToPixel (const Size& rSize) const
1918 {
1919     ScUnoGuard aGuard;
1920     IsObjectValid();
1921     Size aSize;
1922     ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1923     if (pWin)
1924         aSize = pWin->LogicToPixel(rSize, pWin->GetDrawMapMode());
1925     return aSize;
1926 }
1927 
1928 Point ScAccessibleDocument::PixelToLogic (const Point& rPoint) const
1929 {
1930     ScUnoGuard aGuard;
1931     IsObjectValid();
1932     Point aPoint;
1933     ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1934     if (pWin)
1935     {
1936         aPoint -= pWin->GetWindowExtentsRelative(NULL).TopLeft();
1937         aPoint = pWin->PixelToLogic(rPoint, pWin->GetDrawMapMode());
1938     }
1939     return aPoint;
1940 }
1941 
1942 Size ScAccessibleDocument::PixelToLogic (const Size& rSize) const
1943 {
1944     ScUnoGuard aGuard;
1945     IsObjectValid();
1946     Size aSize;
1947     ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1948     if (pWin)
1949         aSize = pWin->PixelToLogic(rSize, pWin->GetDrawMapMode());
1950     return aSize;
1951 }
1952 
1953     //=====  internal  ========================================================
1954 
1955 utl::AccessibleRelationSetHelper* ScAccessibleDocument::GetRelationSet(const ScAddress* pAddress) const
1956 {
1957     utl::AccessibleRelationSetHelper* pRelationSet = NULL;
1958     if (mpChildrenShapes)
1959         pRelationSet = mpChildrenShapes->GetRelationSet(pAddress);
1960     return pRelationSet;
1961 }
1962 
1963 ::rtl::OUString SAL_CALL
1964     ScAccessibleDocument::createAccessibleDescription(void)
1965     throw (uno::RuntimeException)
1966 {
1967     rtl::OUString sDescription = String(ScResId(STR_ACC_DOC_DESCR));
1968     return sDescription;
1969 }
1970 
1971 ::rtl::OUString SAL_CALL
1972     ScAccessibleDocument::createAccessibleName(void)
1973     throw (uno::RuntimeException)
1974 {
1975     ScUnoGuard aGuard;
1976     IsObjectValid();
1977     rtl::OUString sName = String(ScResId(STR_ACC_DOC_NAME));
1978     sal_Int32 nNumber(sal_Int32(meSplitPos) + 1);
1979     sName += rtl::OUString::valueOf(nNumber);
1980     return sName;
1981 }
1982 
1983 Rectangle ScAccessibleDocument::GetBoundingBoxOnScreen() const
1984     throw (uno::RuntimeException)
1985 {
1986     Rectangle aRect;
1987     if (mpViewShell)
1988     {
1989         Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
1990         if (pWindow)
1991             aRect = pWindow->GetWindowExtentsRelative(NULL);
1992     }
1993     return aRect;
1994 }
1995 
1996 Rectangle ScAccessibleDocument::GetBoundingBox() const
1997     throw (uno::RuntimeException)
1998 {
1999     Rectangle aRect;
2000     if (mpViewShell)
2001     {
2002         Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
2003         if (pWindow)
2004             aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
2005     }
2006     return aRect;
2007 }
2008 
2009 SCTAB ScAccessibleDocument::getVisibleTable() const
2010 {
2011     SCTAB nVisibleTable(0);
2012     if (mpViewShell && mpViewShell->GetViewData())
2013         nVisibleTable = mpViewShell->GetViewData()->GetTabNo();
2014     return nVisibleTable;
2015 }
2016 
2017 uno::Reference < XAccessible >
2018     ScAccessibleDocument::GetAccessibleSpreadsheet()
2019 {
2020     if (!mpAccessibleSpreadsheet && mpViewShell)
2021     {
2022         mpAccessibleSpreadsheet = new ScAccessibleSpreadsheet(this, mpViewShell, getVisibleTable(), meSplitPos);
2023         mpAccessibleSpreadsheet->acquire();
2024         mpAccessibleSpreadsheet->Init();
2025         mbCompleteSheetSelected = IsTableSelected();
2026     }
2027     return mpAccessibleSpreadsheet;
2028 }
2029 
2030 void ScAccessibleDocument::FreeAccessibleSpreadsheet()
2031 {
2032     if (mpAccessibleSpreadsheet)
2033     {
2034         mpAccessibleSpreadsheet->dispose();
2035         mpAccessibleSpreadsheet->release();
2036         mpAccessibleSpreadsheet = NULL;
2037     }
2038 }
2039 
2040 sal_Bool ScAccessibleDocument::IsTableSelected() const
2041 {
2042     sal_Bool bResult (sal_False);
2043     if(mpViewShell)
2044     {
2045         SCTAB nTab(getVisibleTable());
2046         //#103800#; use a copy of MarkData
2047         ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData());
2048         aMarkData.MarkToMulti();
2049         if (aMarkData.IsAllMarked(ScRange(ScAddress(0, 0, nTab),ScAddress(MAXCOL, MAXROW, nTab))))
2050             bResult = sal_True;
2051     }
2052     return bResult;
2053 }
2054 
2055 sal_Bool ScAccessibleDocument::IsDefunc(
2056     const uno::Reference<XAccessibleStateSet>& rxParentStates)
2057 {
2058     return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() ||
2059         (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
2060 }
2061 
2062 sal_Bool ScAccessibleDocument::IsEditable(
2063     const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
2064 {
2065     // what is with document protection or readonly documents?
2066     return sal_True;
2067 }
2068 
2069 void ScAccessibleDocument::AddChild(const uno::Reference<XAccessible>& xAcc, sal_Bool bFireEvent)
2070 {
2071     DBG_ASSERT(!mxTempAcc.is(), "this object should be removed before");
2072     if (xAcc.is())
2073     {
2074         mxTempAcc = xAcc;
2075         if( bFireEvent )
2076         {
2077             AccessibleEventObject aEvent;
2078                         aEvent.Source = uno::Reference<XAccessibleContext>(this);
2079             aEvent.EventId = AccessibleEventId::CHILD;
2080             aEvent.NewValue <<= mxTempAcc;
2081             CommitChange( aEvent );
2082         }
2083     }
2084 }
2085 
2086 void ScAccessibleDocument::RemoveChild(const uno::Reference<XAccessible>& xAcc, sal_Bool bFireEvent)
2087 {
2088     DBG_ASSERT(mxTempAcc.is(), "this object should be added before");
2089     if (xAcc.is())
2090     {
2091         DBG_ASSERT(xAcc.get() == mxTempAcc.get(), "only the same object should be removed");
2092         if( bFireEvent )
2093         {
2094             AccessibleEventObject aEvent;
2095                         aEvent.Source = uno::Reference<XAccessibleContext>(this);
2096             aEvent.EventId = AccessibleEventId::CHILD;
2097             aEvent.OldValue <<= mxTempAcc;
2098             CommitChange( aEvent );
2099         }
2100         mxTempAcc = NULL;
2101     }
2102 }
2103 
2104 rtl::OUString ScAccessibleDocument::GetCurrentCellName() const
2105 {
2106     String sName( ScResId(STR_ACC_CELL_NAME) );
2107     if (mpViewShell)
2108     {
2109         String sAddress;
2110         // Document not needed, because only the cell address, but not the tablename is needed
2111         mpViewShell->GetViewData()->GetCurPos().Format( sAddress, SCA_VALID, NULL );
2112         sName.SearchAndReplaceAscii("%1", sAddress);
2113     }
2114     return rtl::OUString(sName);
2115 }
2116 
2117 rtl::OUString ScAccessibleDocument::GetCurrentCellDescription() const
2118 {
2119     return rtl::OUString();
2120 }
2121