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