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