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 15 : struct ScShapeDataLess
90 : {
91 : OUString msLayerId;
92 : OUString msZOrder;
93 5 : ScShapeDataLess()
94 : : msLayerId( "LayerID" ),
95 5 : msZOrder( "ZOrder" )
96 : {
97 5 : }
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 2 : void operator() (ScAccessibleShapeData* pData)
208 : {
209 2 : if (pData)
210 0 : DELETEZ(pData);
211 2 : }
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 2 : ScChildrenShapes::ScChildrenShapes(ScAccessibleDocument* pAccessibleDocument, ScTabViewShell* pViewShell, ScSplitPos eSplitPos)
292 : :
293 : mnShapesSelected(0),
294 : mpViewShell(pViewShell),
295 : mpAccessibleDocument(pAccessibleDocument),
296 2 : meSplitPos(eSplitPos)
297 : {
298 2 : FillSelectionSupplier();
299 2 : maZOrderedShapes.push_back(NULL); // add an element which represents the table
300 :
301 2 : GetCount(); // fill list with filtered shapes (no internal shapes)
302 :
303 2 : 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 2 : if (pViewShell)
314 : {
315 2 : SfxBroadcaster* pDrawBC = pViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster();
316 2 : if (pDrawBC)
317 : {
318 2 : StartListening(*pDrawBC);
319 :
320 2 : maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(pViewShell->GetViewData()->GetDocument()->GetDrawLayer()) );
321 2 : maShapeTreeInfo.SetSdrView(pViewShell->GetViewData()->GetScDrawView());
322 2 : maShapeTreeInfo.SetController(NULL);
323 2 : maShapeTreeInfo.SetWindow(pViewShell->GetWindowByPos(meSplitPos));
324 2 : maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument);
325 : }
326 : }
327 2 : }
328 :
329 6 : ScChildrenShapes::~ScChildrenShapes()
330 : {
331 2 : std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), Destroy());
332 2 : if (mpViewShell)
333 : {
334 2 : SfxBroadcaster* pDrawBC = mpViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster();
335 2 : if (pDrawBC)
336 2 : EndListening(*pDrawBC);
337 : }
338 4 : }
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 2 : void ScChildrenShapes::Notify(SfxBroadcaster&, const SfxHint& rHint)
359 : {
360 2 : 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 2 : }
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 12 : sal_Int32 ScChildrenShapes::GetCount() const
455 : {
456 12 : SdrPage* pDrawPage = GetDrawPage();
457 12 : 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 12 : return maZOrderedShapes.size();
472 : }
473 :
474 2 : uno::Reference< XAccessible > ScChildrenShapes::Get(const ScAccessibleShapeData* pData) const
475 : {
476 2 : if (!pData)
477 2 : 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 2 : uno::Reference< XAccessible > ScChildrenShapes::Get(sal_Int32 nIndex) const
500 : {
501 2 : if (maZOrderedShapes.size() <= 1)
502 2 : GetCount(); // fill list with filtered shapes (no internal shapes)
503 :
504 2 : if (static_cast<sal_uInt32>(nIndex) >= maZOrderedShapes.size())
505 0 : return NULL;
506 :
507 2 : 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 5 : sal_Bool ScChildrenShapes::SelectionChanged()
599 : {
600 5 : sal_Bool bResult(false);
601 5 : if (!xSelectionSupplier.is())
602 0 : throw uno::RuntimeException();
603 :
604 5 : uno::Reference<drawing::XShapes> xShapes(xSelectionSupplier->getSelection(), uno::UNO_QUERY);
605 :
606 5 : bResult = FindSelectedShapesChanges(xShapes, sal_True);
607 :
608 5 : 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 12 : SdrPage* ScChildrenShapes::GetDrawPage() const
800 : {
801 12 : SCTAB nTab(mpAccessibleDocument->getVisibleTable());
802 12 : SdrPage* pDrawPage = NULL;
803 12 : if (mpViewShell)
804 : {
805 12 : ScDocument* pDoc = mpViewShell->GetViewData()->GetDocument();
806 12 : if (pDoc && pDoc->GetDrawLayer())
807 : {
808 12 : ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
809 12 : if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab))
810 0 : pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(static_cast<sal_Int16>(nTab)));
811 : }
812 : }
813 12 : return pDrawPage;
814 : }
815 :
816 : struct SetRelation
817 : {
818 : const ScChildrenShapes* mpChildrenShapes;
819 : mutable utl::AccessibleRelationSetHelper* mpRelationSet;
820 : const ScAddress* mpAddress;
821 1 : SetRelation(const ScChildrenShapes* pChildrenShapes, const ScAddress* pAddress)
822 : :
823 : mpChildrenShapes(pChildrenShapes),
824 : mpRelationSet(NULL),
825 1 : mpAddress(pAddress)
826 : {
827 1 : }
828 1 : void operator() (const ScAccessibleShapeData* pAccShapeData) const
829 : {
830 1 : 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 1 : }
845 : };
846 :
847 1 : utl::AccessibleRelationSetHelper* ScChildrenShapes::GetRelationSet(const ScAddress* pAddress) const
848 : {
849 1 : SetRelation aSetRelation(this, pAddress);
850 1 : ::std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), aSetRelation);
851 1 : return aSetRelation.mpRelationSet;
852 : }
853 :
854 5 : sal_Bool ScChildrenShapes::FindSelectedShapesChanges(const uno::Reference<drawing::XShapes>& xShapes, sal_Bool /* bCommitChange */) const
855 : {
856 5 : sal_Bool bResult(false);
857 5 : SortedShapes aShapesList;
858 10 : uno::Reference<container::XIndexAccess> xIndexAcc(xShapes, uno::UNO_QUERY);
859 5 : 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 5 : mnShapesSelected = 0;
876 10 : ScShapeDataLess aLess;
877 5 : std::sort(aShapesList.begin(), aShapesList.end(), aLess);
878 :
879 5 : SortedShapes::iterator aXShapesItr(aShapesList.begin());
880 5 : SortedShapes::const_iterator aXShapesEndItr(aShapesList.end());
881 5 : SortedShapes::iterator aDataItr(maZOrderedShapes.begin());
882 5 : SortedShapes::const_iterator aDataEndItr(maZOrderedShapes.end());
883 5 : SortedShapes::const_iterator aFocusedItr = aDataEndItr;
884 15 : while((aDataItr != aDataEndItr))
885 : {
886 5 : 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 5 : ++aDataItr;
932 : }
933 5 : if ((aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape && (mnShapesSelected == 1))
934 0 : (*aFocusedItr)->pAccShape->SetState(AccessibleStateType::FOCUSED);
935 :
936 5 : std::for_each(aShapesList.begin(), aShapesList.end(), Destroy());
937 :
938 10 : return bResult;
939 : }
940 :
941 2 : void ScChildrenShapes::FillSelectionSupplier() const
942 : {
943 2 : if (!xSelectionSupplier.is() && mpViewShell)
944 : {
945 2 : SfxViewFrame* pViewFrame = mpViewShell->GetViewFrame();
946 2 : if (pViewFrame)
947 : {
948 2 : xSelectionSupplier = uno::Reference<view::XSelectionSupplier>(pViewFrame->GetFrame().GetController(), uno::UNO_QUERY);
949 2 : if (xSelectionSupplier.is())
950 : {
951 2 : if (mpAccessibleDocument)
952 2 : xSelectionSupplier->addSelectionChangeListener(mpAccessibleDocument);
953 2 : uno::Reference<drawing::XShapes> xShapes (xSelectionSupplier->getSelection(), uno::UNO_QUERY);
954 2 : if (xShapes.is())
955 0 : mnShapesSelected = xShapes->getCount();
956 : }
957 : }
958 : }
959 2 : }
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 : else
1026 0 : delete pAddress;
1027 : }
1028 0 : }
1029 :
1030 0 : void ScChildrenShapes::AddShape(const uno::Reference<drawing::XShape>& xShape, sal_Bool bCommitChange) const
1031 : {
1032 0 : SortedShapes::iterator aFindItr;
1033 0 : if (!FindShape(xShape, aFindItr))
1034 : {
1035 0 : ScAccessibleShapeData* pShape = new ScAccessibleShapeData();
1036 0 : pShape->xShape = xShape;
1037 0 : SortedShapes::iterator aNewItr = maZOrderedShapes.insert(aFindItr, pShape);
1038 0 : SetAnchor(xShape, pShape);
1039 :
1040 0 : uno::Reference< beans::XPropertySet > xShapeProp(xShape, uno::UNO_QUERY);
1041 0 : if (xShapeProp.is())
1042 : {
1043 0 : uno::Any aPropAny = xShapeProp->getPropertyValue("LayerID");
1044 0 : sal_Int16 nLayerID = 0;
1045 0 : if( aPropAny >>= nLayerID )
1046 : {
1047 0 : if( (nLayerID == SC_LAYER_INTERN) || (nLayerID == SC_LAYER_HIDDEN) )
1048 0 : pShape->bSelectable = false;
1049 : else
1050 0 : pShape->bSelectable = sal_True;
1051 0 : }
1052 : }
1053 :
1054 :
1055 0 : if (!xSelectionSupplier.is())
1056 0 : throw uno::RuntimeException();
1057 :
1058 0 : uno::Reference<container::XEnumerationAccess> xEnumAcc(xSelectionSupplier->getSelection(), uno::UNO_QUERY);
1059 0 : if (xEnumAcc.is())
1060 : {
1061 0 : uno::Reference<container::XEnumeration> xEnum = xEnumAcc->createEnumeration();
1062 0 : if (xEnum.is())
1063 : {
1064 0 : uno::Reference<drawing::XShape> xSelectedShape;
1065 0 : sal_Bool bFound(false);
1066 0 : while (!bFound && xEnum->hasMoreElements())
1067 : {
1068 0 : xEnum->nextElement() >>= xSelectedShape;
1069 0 : if (xShape.is() && (xShape.get() == xSelectedShape.get()))
1070 : {
1071 0 : pShape->bSelected = sal_True;
1072 0 : bFound = sal_True;
1073 : }
1074 0 : }
1075 0 : }
1076 : }
1077 0 : if (mpAccessibleDocument && bCommitChange)
1078 : {
1079 0 : AccessibleEventObject aEvent;
1080 0 : aEvent.EventId = AccessibleEventId::CHILD;
1081 0 : aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1082 0 : aEvent.NewValue <<= Get(aNewItr - maZOrderedShapes.begin());
1083 :
1084 0 : mpAccessibleDocument->CommitChange(aEvent); // new child - event
1085 0 : }
1086 : }
1087 : else
1088 : {
1089 : OSL_FAIL("shape is always in the list");
1090 : }
1091 0 : }
1092 :
1093 0 : void ScChildrenShapes::RemoveShape(const uno::Reference<drawing::XShape>& xShape) const
1094 : {
1095 0 : SortedShapes::iterator aItr;
1096 0 : if (FindShape(xShape, aItr))
1097 : {
1098 0 : if (mpAccessibleDocument)
1099 : {
1100 0 : uno::Reference<XAccessible> xOldAccessible (Get(aItr - maZOrderedShapes.begin()));
1101 :
1102 0 : delete *aItr;
1103 0 : maZOrderedShapes.erase(aItr);
1104 :
1105 0 : AccessibleEventObject aEvent;
1106 0 : aEvent.EventId = AccessibleEventId::CHILD;
1107 0 : aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument);
1108 0 : aEvent.OldValue <<= uno::makeAny(xOldAccessible);
1109 :
1110 0 : mpAccessibleDocument->CommitChange(aEvent); // child is gone - event
1111 : }
1112 : else
1113 : {
1114 0 : delete *aItr;
1115 0 : maZOrderedShapes.erase(aItr);
1116 : }
1117 : }
1118 : else
1119 : {
1120 : OSL_FAIL("shape was not in internal list");
1121 : }
1122 0 : }
1123 :
1124 0 : sal_Bool ScChildrenShapes::FindShape(const uno::Reference<drawing::XShape>& xShape, ScChildrenShapes::SortedShapes::iterator& rItr) const
1125 : {
1126 0 : sal_Bool bResult(false);
1127 0 : ScAccessibleShapeData aShape;
1128 0 : aShape.xShape = xShape;
1129 0 : ScShapeDataLess aLess;
1130 0 : rItr = std::lower_bound(maZOrderedShapes.begin(), maZOrderedShapes.end(), &aShape, aLess);
1131 0 : if ((rItr != maZOrderedShapes.end()) && (*rItr != NULL) && ((*rItr)->xShape.get() == xShape.get()))
1132 0 : bResult = sal_True; // if the shape is found
1133 :
1134 : #if OSL_DEBUG_LEVEL > 0 // test whether it finds truly the correct shape (perhaps it is not really sorted)
1135 : SortedShapes::iterator aDebugItr = maZOrderedShapes.begin();
1136 : SortedShapes::iterator aEndItr = maZOrderedShapes.end();
1137 : sal_Bool bFound(false);
1138 : while (!bFound && aDebugItr != aEndItr)
1139 : {
1140 : if (*aDebugItr && ((*aDebugItr)->xShape.get() == xShape.get()))
1141 : bFound = sal_True;
1142 : else
1143 : ++aDebugItr;
1144 : }
1145 : sal_Bool bResult2 = (aDebugItr != maZOrderedShapes.end());
1146 : OSL_ENSURE((bResult == bResult2) && ((bResult && (rItr == aDebugItr)) || !bResult), "wrong Shape found");
1147 : #endif
1148 0 : return bResult;
1149 : }
1150 :
1151 0 : sal_Int8 ScChildrenShapes::Compare(const ScAccessibleShapeData* pData1,
1152 : const ScAccessibleShapeData* pData2) const
1153 : {
1154 0 : ScShapeDataLess aLess;
1155 :
1156 0 : sal_Bool bResult1(aLess(pData1, pData2));
1157 0 : sal_Bool bResult2(aLess(pData2, pData1));
1158 :
1159 0 : sal_Int8 nResult(0);
1160 0 : if (!bResult1 && bResult2)
1161 0 : nResult = 1;
1162 0 : else if (bResult1 && !bResult2)
1163 0 : nResult = -1;
1164 :
1165 0 : return nResult;
1166 : }
1167 :
1168 : struct ScVisAreaChanged
1169 : {
1170 : ScAccessibleDocument* mpAccDoc;
1171 0 : ScVisAreaChanged(ScAccessibleDocument* pAccDoc) : mpAccDoc(pAccDoc) {}
1172 0 : void operator() (const ScAccessibleShapeData* pAccShapeData) const
1173 : {
1174 0 : if (pAccShapeData && pAccShapeData->pAccShape)
1175 : {
1176 0 : pAccShapeData->pAccShape->ViewForwarderChanged(::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA, mpAccDoc);
1177 : }
1178 0 : }
1179 : };
1180 :
1181 0 : void ScChildrenShapes::VisAreaChanged() const
1182 : {
1183 0 : ScVisAreaChanged aVisAreaChanged(mpAccessibleDocument);
1184 0 : std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), aVisAreaChanged);
1185 0 : }
1186 :
1187 : // ============================================================================
1188 :
1189 2 : ScAccessibleDocument::ScAccessibleDocument(
1190 : const uno::Reference<XAccessible>& rxParent,
1191 : ScTabViewShell* pViewShell,
1192 : ScSplitPos eSplitPos)
1193 : : ScAccessibleDocumentBase(rxParent),
1194 : mpViewShell(pViewShell),
1195 : meSplitPos(eSplitPos),
1196 : mpAccessibleSpreadsheet(NULL),
1197 : mpChildrenShapes(NULL),
1198 : mpTempAccEdit(NULL),
1199 2 : mbCompleteSheetSelected(false)
1200 : {
1201 2 : if (pViewShell)
1202 : {
1203 2 : pViewShell->AddAccessibilityObject(*this);
1204 2 : Window *pWin = pViewShell->GetWindowByPos(eSplitPos);
1205 2 : if( pWin )
1206 : {
1207 2 : pWin->AddChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1208 2 : sal_uInt16 nCount = pWin->GetChildCount();
1209 2 : for( sal_uInt16 i=0; i < nCount; ++i )
1210 : {
1211 0 : Window *pChildWin = pWin->GetChild( i );
1212 0 : if( pChildWin &&
1213 0 : AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1214 0 : AddChild( pChildWin->GetAccessible(), false );
1215 : }
1216 : }
1217 2 : if (pViewShell->GetViewData()->HasEditView( eSplitPos ))
1218 : {
1219 0 : uno::Reference<XAccessible> xAcc = new ScAccessibleEditObject(this, pViewShell->GetViewData()->GetEditView(eSplitPos),
1220 0 : pViewShell->GetWindowByPos(eSplitPos), GetCurrentCellName(), GetCurrentCellDescription(),
1221 0 : ScAccessibleEditObject::CellInEditMode);
1222 0 : AddChild(xAcc, false);
1223 : }
1224 : }
1225 2 : maVisArea = GetVisibleArea_Impl();
1226 2 : }
1227 :
1228 2 : void ScAccessibleDocument::Init()
1229 : {
1230 2 : if(!mpChildrenShapes)
1231 2 : mpChildrenShapes = new ScChildrenShapes(this, mpViewShell, meSplitPos);
1232 2 : }
1233 :
1234 6 : ScAccessibleDocument::~ScAccessibleDocument(void)
1235 : {
1236 2 : if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
1237 : {
1238 : // increment refcount to prevent double call off dtor
1239 0 : osl_atomic_increment( &m_refCount );
1240 0 : dispose();
1241 : }
1242 4 : }
1243 :
1244 2 : void SAL_CALL ScAccessibleDocument::disposing()
1245 : {
1246 2 : SolarMutexGuard aGuard;
1247 2 : FreeAccessibleSpreadsheet();
1248 2 : if (mpViewShell)
1249 : {
1250 2 : Window *pWin = mpViewShell->GetWindowByPos(meSplitPos);
1251 2 : if( pWin )
1252 2 : pWin->RemoveChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener ));
1253 :
1254 2 : mpViewShell->RemoveAccessibilityObject(*this);
1255 2 : mpViewShell = NULL;
1256 : }
1257 2 : if (mpChildrenShapes)
1258 2 : DELETEZ(mpChildrenShapes);
1259 :
1260 2 : ScAccessibleDocumentBase::disposing();
1261 2 : }
1262 :
1263 0 : void SAL_CALL ScAccessibleDocument::disposing( const lang::EventObject& /* Source */ )
1264 : throw (uno::RuntimeException)
1265 : {
1266 0 : disposing();
1267 0 : }
1268 :
1269 : //===== SfxListener =====================================================
1270 :
1271 12 : IMPL_LINK( ScAccessibleDocument, WindowChildEventListener, VclSimpleEvent*, pEvent )
1272 : {
1273 : OSL_ENSURE( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
1274 6 : if ( pEvent && pEvent->ISA( VclWindowEvent ) )
1275 : {
1276 6 : VclWindowEvent *pVclEvent = static_cast< VclWindowEvent * >( pEvent );
1277 : OSL_ENSURE( pVclEvent->GetWindow(), "Window???" );
1278 6 : switch ( pVclEvent->GetId() )
1279 : {
1280 : case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children
1281 : {
1282 0 : Window* pChildWin = static_cast < Window * >( pVclEvent->GetData() );
1283 0 : if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1284 : {
1285 0 : AddChild( pChildWin->GetAccessible(), sal_True );
1286 : }
1287 : }
1288 0 : break;
1289 : case VCLEVENT_WINDOW_HIDE: // send destroy on hide for direct accessible children
1290 : {
1291 0 : Window* pChildWin = static_cast < Window * >( pVclEvent->GetData() );
1292 0 : if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() )
1293 : {
1294 0 : RemoveChild( pChildWin->GetAccessible(), sal_True );
1295 : }
1296 : }
1297 0 : break;
1298 : }
1299 : }
1300 6 : return 0;
1301 : }
1302 :
1303 18 : void ScAccessibleDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1304 : {
1305 18 : if (rHint.ISA( ScAccGridWinFocusLostHint ) )
1306 : {
1307 2 : const ScAccGridWinFocusLostHint& rRef = (const ScAccGridWinFocusLostHint&)rHint;
1308 2 : if (rRef.GetOldGridWin() == meSplitPos)
1309 : {
1310 2 : if (mxTempAcc.is() && mpTempAccEdit)
1311 0 : mpTempAccEdit->LostFocus();
1312 2 : else if (mpAccessibleSpreadsheet)
1313 2 : mpAccessibleSpreadsheet->LostFocus();
1314 : else
1315 0 : CommitFocusLost();
1316 : }
1317 : }
1318 16 : else if (rHint.ISA( ScAccGridWinFocusGotHint ) )
1319 : {
1320 0 : const ScAccGridWinFocusGotHint& rRef = (const ScAccGridWinFocusGotHint&)rHint;
1321 0 : if (rRef.GetNewGridWin() == meSplitPos)
1322 : {
1323 0 : if (mxTempAcc.is() && mpTempAccEdit)
1324 0 : mpTempAccEdit->GotFocus();
1325 0 : else if (mpAccessibleSpreadsheet)
1326 0 : mpAccessibleSpreadsheet->GotFocus();
1327 : else
1328 0 : CommitFocusGained();
1329 : }
1330 : }
1331 16 : else if (rHint.ISA( SfxSimpleHint ))
1332 : {
1333 16 : const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
1334 : // only notify if child exist, otherwise it is not necessary
1335 16 : if ((rRef.GetId() == SC_HINT_ACC_TABLECHANGED) &&
1336 : mpAccessibleSpreadsheet)
1337 : {
1338 0 : FreeAccessibleSpreadsheet();
1339 0 : if (mpChildrenShapes)
1340 0 : DELETEZ(mpChildrenShapes);
1341 :
1342 : // Accessibility: Shapes / form controls after reload not accessible
1343 0 : if ( !mpChildrenShapes )
1344 : {
1345 0 : mpChildrenShapes = new ScChildrenShapes( this, mpViewShell, meSplitPos );
1346 : }
1347 :
1348 0 : AccessibleEventObject aEvent;
1349 0 : aEvent.EventId = AccessibleEventId::INVALIDATE_ALL_CHILDREN;
1350 0 : aEvent.Source = uno::Reference< XAccessibleContext >(this);
1351 0 : CommitChange(aEvent); // all children changed
1352 : }
1353 16 : else if (rRef.GetId() == SC_HINT_ACC_MAKEDRAWLAYER)
1354 : {
1355 0 : if (mpChildrenShapes)
1356 0 : mpChildrenShapes->SetDrawBroadcaster();
1357 : }
1358 16 : else if ((rRef.GetId() == SC_HINT_ACC_ENTEREDITMODE)) // this event comes only on creating edit field of a cell
1359 : {
1360 0 : if (mpViewShell && mpViewShell->GetViewData()->HasEditView(meSplitPos))
1361 : {
1362 0 : mpTempAccEdit = new ScAccessibleEditObject(this, mpViewShell->GetViewData()->GetEditView(meSplitPos),
1363 0 : mpViewShell->GetWindowByPos(meSplitPos), GetCurrentCellName(),
1364 0 : OUString(String(ScResId(STR_ACC_EDITLINE_DESCR))), ScAccessibleEditObject::CellInEditMode);
1365 0 : uno::Reference<XAccessible> xAcc = mpTempAccEdit;
1366 :
1367 0 : AddChild(xAcc, sal_True);
1368 :
1369 0 : if (mpAccessibleSpreadsheet)
1370 0 : mpAccessibleSpreadsheet->LostFocus();
1371 : else
1372 0 : CommitFocusLost();
1373 :
1374 0 : mpTempAccEdit->GotFocus();
1375 : }
1376 : }
1377 16 : else if (rRef.GetId() == SC_HINT_ACC_LEAVEEDITMODE)
1378 : {
1379 0 : if (mxTempAcc.is())
1380 : {
1381 0 : if (mpTempAccEdit)
1382 0 : mpTempAccEdit->LostFocus();
1383 :
1384 0 : mpTempAccEdit = NULL;
1385 0 : RemoveChild(mxTempAcc, sal_True);
1386 :
1387 0 : if (mpAccessibleSpreadsheet)
1388 0 : mpAccessibleSpreadsheet->GotFocus();
1389 : else
1390 0 : CommitFocusGained();
1391 : }
1392 : }
1393 16 : else if ((rRef.GetId() == SC_HINT_ACC_VISAREACHANGED) || (rRef.GetId() == SC_HINT_ACC_WINDOWRESIZED))
1394 : {
1395 2 : Rectangle aOldVisArea(maVisArea);
1396 2 : maVisArea = GetVisibleArea_Impl();
1397 :
1398 2 : if (maVisArea != aOldVisArea)
1399 : {
1400 0 : if (maVisArea.GetSize() != aOldVisArea.GetSize())
1401 : {
1402 0 : AccessibleEventObject aEvent;
1403 0 : aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED;
1404 0 : aEvent.Source = uno::Reference< XAccessibleContext >(this);
1405 :
1406 0 : CommitChange(aEvent);
1407 :
1408 0 : if (mpAccessibleSpreadsheet)
1409 0 : mpAccessibleSpreadsheet->BoundingBoxChanged();
1410 : }
1411 0 : else if (mpAccessibleSpreadsheet)
1412 : {
1413 0 : mpAccessibleSpreadsheet->VisAreaChanged();
1414 : }
1415 0 : if (mpChildrenShapes)
1416 0 : mpChildrenShapes->VisAreaChanged();
1417 : }
1418 : }
1419 : }
1420 :
1421 18 : ScAccessibleDocumentBase::Notify(rBC, rHint);
1422 18 : }
1423 :
1424 5 : void SAL_CALL ScAccessibleDocument::selectionChanged( const lang::EventObject& /* aEvent */ )
1425 : throw (uno::RuntimeException)
1426 : {
1427 5 : sal_Bool bSelectionChanged(false);
1428 5 : if (mpAccessibleSpreadsheet)
1429 : {
1430 5 : sal_Bool bOldSelected(mbCompleteSheetSelected);
1431 5 : mbCompleteSheetSelected = IsTableSelected();
1432 5 : if (bOldSelected != mbCompleteSheetSelected)
1433 : {
1434 0 : mpAccessibleSpreadsheet->CompleteSelectionChanged(mbCompleteSheetSelected);
1435 0 : bSelectionChanged = sal_True;
1436 : }
1437 : }
1438 :
1439 5 : if (mpChildrenShapes && mpChildrenShapes->SelectionChanged())
1440 0 : bSelectionChanged = sal_True;
1441 :
1442 5 : if (bSelectionChanged)
1443 : {
1444 0 : AccessibleEventObject aEvent;
1445 0 : aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
1446 0 : aEvent.Source = uno::Reference< XAccessibleContext >(this);
1447 :
1448 0 : CommitChange(aEvent);
1449 : }
1450 5 : }
1451 :
1452 : //===== XInterface =====================================================
1453 :
1454 23 : uno::Any SAL_CALL ScAccessibleDocument::queryInterface( uno::Type const & rType )
1455 : throw (uno::RuntimeException)
1456 : {
1457 23 : uno::Any aAny (ScAccessibleDocumentImpl::queryInterface(rType));
1458 23 : return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType);
1459 : }
1460 :
1461 175 : void SAL_CALL ScAccessibleDocument::acquire()
1462 : throw ()
1463 : {
1464 175 : ScAccessibleContextBase::acquire();
1465 175 : }
1466 :
1467 175 : void SAL_CALL ScAccessibleDocument::release()
1468 : throw ()
1469 : {
1470 175 : ScAccessibleContextBase::release();
1471 175 : }
1472 :
1473 : //===== XAccessibleComponent ============================================
1474 :
1475 0 : uno::Reference< XAccessible > SAL_CALL ScAccessibleDocument::getAccessibleAtPoint(
1476 : const awt::Point& rPoint )
1477 : throw (uno::RuntimeException)
1478 : {
1479 0 : uno::Reference<XAccessible> xAccessible = NULL;
1480 0 : if (containsPoint(rPoint))
1481 : {
1482 0 : SolarMutexGuard aGuard;
1483 0 : IsObjectValid();
1484 0 : if (mpChildrenShapes)
1485 0 : xAccessible = mpChildrenShapes->GetAt(rPoint);
1486 0 : if(!xAccessible.is())
1487 : {
1488 0 : if (mxTempAcc.is())
1489 : {
1490 0 : uno::Reference< XAccessibleContext > xCont(mxTempAcc->getAccessibleContext());
1491 0 : uno::Reference< XAccessibleComponent > xComp(xCont, uno::UNO_QUERY);
1492 0 : if (xComp.is())
1493 : {
1494 0 : Rectangle aBound(VCLRectangle(xComp->getBounds()));
1495 0 : if (aBound.IsInside(VCLPoint(rPoint)))
1496 0 : xAccessible = mxTempAcc;
1497 0 : }
1498 : }
1499 0 : if (!xAccessible.is())
1500 0 : xAccessible = GetAccessibleSpreadsheet();
1501 0 : }
1502 : }
1503 0 : return xAccessible;
1504 : }
1505 :
1506 1 : void SAL_CALL ScAccessibleDocument::grabFocus( )
1507 : throw (uno::RuntimeException)
1508 : {
1509 1 : SolarMutexGuard aGuard;
1510 1 : IsObjectValid();
1511 1 : if (getAccessibleParent().is())
1512 : {
1513 1 : uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1514 1 : if (xAccessibleComponent.is())
1515 : {
1516 1 : xAccessibleComponent->grabFocus();
1517 : // grab only focus if it does not have the focus and it is not hidden
1518 3 : if (mpViewShell && mpViewShell->GetViewData() &&
1519 2 : (mpViewShell->GetViewData()->GetActivePart() != meSplitPos) &&
1520 0 : mpViewShell->GetWindowByPos(meSplitPos)->IsVisible())
1521 : {
1522 0 : mpViewShell->ActivatePart(meSplitPos);
1523 : }
1524 1 : }
1525 1 : }
1526 1 : }
1527 :
1528 : //===== XAccessibleContext ==============================================
1529 :
1530 : /// Return the number of currently visible children.
1531 : sal_Int32 SAL_CALL
1532 6 : ScAccessibleDocument::getAccessibleChildCount(void)
1533 : throw (uno::RuntimeException)
1534 : {
1535 6 : SolarMutexGuard aGuard;
1536 6 : IsObjectValid();
1537 6 : sal_Int32 nCount(1);
1538 6 : if (mpChildrenShapes)
1539 6 : nCount = mpChildrenShapes->GetCount(); // returns the count of the shapes inclusive the table
1540 :
1541 6 : if (mxTempAcc.is())
1542 0 : ++nCount;
1543 :
1544 6 : return nCount;
1545 : }
1546 :
1547 : /// Return the specified child or NULL if index is invalid.
1548 : uno::Reference<XAccessible> SAL_CALL
1549 2 : ScAccessibleDocument::getAccessibleChild(sal_Int32 nIndex)
1550 : throw (uno::RuntimeException,
1551 : lang::IndexOutOfBoundsException)
1552 : {
1553 2 : SolarMutexGuard aGuard;
1554 2 : IsObjectValid();
1555 2 : uno::Reference<XAccessible> xAccessible;
1556 2 : if (nIndex >= 0)
1557 : {
1558 2 : sal_Int32 nCount(1);
1559 2 : if (mpChildrenShapes)
1560 : {
1561 2 : xAccessible = mpChildrenShapes->Get(nIndex); // returns NULL if it is the table or out of range
1562 2 : nCount = mpChildrenShapes->GetCount(); //there is always a table
1563 : }
1564 2 : if (!xAccessible.is())
1565 : {
1566 2 : if (nIndex < nCount)
1567 2 : xAccessible = GetAccessibleSpreadsheet();
1568 0 : else if (nIndex == nCount && mxTempAcc.is())
1569 0 : xAccessible = mxTempAcc;
1570 : }
1571 : }
1572 :
1573 2 : if (!xAccessible.is())
1574 0 : throw lang::IndexOutOfBoundsException();
1575 :
1576 2 : return xAccessible;
1577 : }
1578 :
1579 : /// Return the set of current states.
1580 : uno::Reference<XAccessibleStateSet> SAL_CALL
1581 14 : ScAccessibleDocument::getAccessibleStateSet(void)
1582 : throw (uno::RuntimeException)
1583 : {
1584 14 : SolarMutexGuard aGuard;
1585 28 : uno::Reference<XAccessibleStateSet> xParentStates;
1586 14 : if (getAccessibleParent().is())
1587 : {
1588 14 : uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1589 14 : xParentStates = xParentContext->getAccessibleStateSet();
1590 : }
1591 14 : utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
1592 14 : if (IsDefunc(xParentStates))
1593 0 : pStateSet->AddState(AccessibleStateType::DEFUNC);
1594 : else
1595 : {
1596 14 : if (IsEditable(xParentStates))
1597 14 : pStateSet->AddState(AccessibleStateType::EDITABLE);
1598 14 : pStateSet->AddState(AccessibleStateType::ENABLED);
1599 14 : pStateSet->AddState(AccessibleStateType::OPAQUE);
1600 14 : if (isShowing())
1601 14 : pStateSet->AddState(AccessibleStateType::SHOWING);
1602 14 : if (isVisible())
1603 14 : pStateSet->AddState(AccessibleStateType::VISIBLE);
1604 : }
1605 28 : return pStateSet;
1606 : }
1607 :
1608 : ///===== XAccessibleSelection ===========================================
1609 :
1610 : void SAL_CALL
1611 0 : ScAccessibleDocument::selectAccessibleChild( sal_Int32 nChildIndex )
1612 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1613 : {
1614 0 : SolarMutexGuard aGuard;
1615 0 : IsObjectValid();
1616 :
1617 0 : if (mpChildrenShapes)
1618 : {
1619 0 : sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table
1620 0 : if (mxTempAcc.is())
1621 0 : ++nCount;
1622 0 : if (nChildIndex < 0 || nChildIndex >= nCount)
1623 0 : throw lang::IndexOutOfBoundsException();
1624 :
1625 0 : uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1626 0 : if (xAccessible.is())
1627 : {
1628 0 : sal_Bool bWasTableSelected(IsTableSelected());
1629 :
1630 0 : if (mpChildrenShapes)
1631 0 : mpChildrenShapes->Select(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is to high
1632 :
1633 0 : if (bWasTableSelected)
1634 0 : mpViewShell->SelectAll();
1635 : }
1636 : else
1637 : {
1638 0 : if (mpViewShell)
1639 0 : mpViewShell->SelectAll();
1640 0 : }
1641 0 : }
1642 0 : }
1643 :
1644 : sal_Bool SAL_CALL
1645 0 : ScAccessibleDocument::isAccessibleChildSelected( sal_Int32 nChildIndex )
1646 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1647 : {
1648 0 : SolarMutexGuard aGuard;
1649 0 : IsObjectValid();
1650 0 : sal_Bool bResult(false);
1651 :
1652 0 : if (mpChildrenShapes)
1653 : {
1654 0 : sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table
1655 0 : if (mxTempAcc.is())
1656 0 : ++nCount;
1657 0 : if (nChildIndex < 0 || nChildIndex >= nCount)
1658 0 : throw lang::IndexOutOfBoundsException();
1659 :
1660 0 : uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1661 0 : if (xAccessible.is())
1662 : {
1663 0 : uno::Reference<drawing::XShape> xShape;
1664 0 : bResult = mpChildrenShapes->IsSelected(nChildIndex, xShape); // throws no lang::IndexOutOfBoundsException if Index is to high
1665 : }
1666 : else
1667 : {
1668 0 : if (mxTempAcc.is() && nChildIndex == nCount)
1669 0 : bResult = sal_True;
1670 : else
1671 0 : bResult = IsTableSelected();
1672 0 : }
1673 : }
1674 0 : return bResult;
1675 : }
1676 :
1677 : void SAL_CALL
1678 0 : ScAccessibleDocument::clearAccessibleSelection( )
1679 : throw (uno::RuntimeException)
1680 : {
1681 0 : SolarMutexGuard aGuard;
1682 0 : IsObjectValid();
1683 :
1684 0 : if (mpChildrenShapes)
1685 0 : mpChildrenShapes->DeselectAll(); //deselects all (also the table)
1686 0 : }
1687 :
1688 : void SAL_CALL
1689 0 : ScAccessibleDocument::selectAllAccessibleChildren( )
1690 : throw (uno::RuntimeException)
1691 : {
1692 0 : SolarMutexGuard aGuard;
1693 0 : IsObjectValid();
1694 :
1695 0 : if (mpChildrenShapes)
1696 0 : mpChildrenShapes->SelectAll();
1697 :
1698 : // select table after shapes, because while selecting shapes the table will be deselected
1699 0 : if (mpViewShell)
1700 : {
1701 0 : mpViewShell->SelectAll();
1702 0 : }
1703 0 : }
1704 :
1705 : sal_Int32 SAL_CALL
1706 0 : ScAccessibleDocument::getSelectedAccessibleChildCount( )
1707 : throw (uno::RuntimeException)
1708 : {
1709 0 : SolarMutexGuard aGuard;
1710 0 : IsObjectValid();
1711 0 : sal_Int32 nCount(0);
1712 :
1713 0 : if (mpChildrenShapes)
1714 0 : nCount = mpChildrenShapes->GetSelectedCount();
1715 :
1716 0 : if (IsTableSelected())
1717 0 : ++nCount;
1718 :
1719 0 : if (mxTempAcc.is())
1720 0 : ++nCount;
1721 :
1722 0 : return nCount;
1723 : }
1724 :
1725 : uno::Reference<XAccessible > SAL_CALL
1726 0 : ScAccessibleDocument::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
1727 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1728 : {
1729 0 : SolarMutexGuard aGuard;
1730 0 : IsObjectValid();
1731 0 : uno::Reference<XAccessible> xAccessible;
1732 0 : if (mpChildrenShapes)
1733 : {
1734 0 : sal_Int32 nCount(getSelectedAccessibleChildCount()); //all shapes and the table
1735 0 : if (nSelectedChildIndex < 0 || nSelectedChildIndex >= nCount)
1736 0 : throw lang::IndexOutOfBoundsException();
1737 :
1738 0 : sal_Bool bTabMarked(IsTableSelected());
1739 :
1740 0 : if (mpChildrenShapes)
1741 0 : xAccessible = mpChildrenShapes->GetSelected(nSelectedChildIndex, bTabMarked); // throws no lang::IndexOutOfBoundsException if Index is to high
1742 0 : if (mxTempAcc.is() && nSelectedChildIndex == nCount - 1)
1743 0 : xAccessible = mxTempAcc;
1744 0 : else if (bTabMarked)
1745 0 : xAccessible = GetAccessibleSpreadsheet();
1746 : }
1747 :
1748 : OSL_ENSURE(xAccessible.is(), "here should always be an accessible object or a exception throwed");
1749 :
1750 0 : return xAccessible;
1751 : }
1752 :
1753 : void SAL_CALL
1754 0 : ScAccessibleDocument::deselectAccessibleChild( sal_Int32 nChildIndex )
1755 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1756 : {
1757 0 : SolarMutexGuard aGuard;
1758 0 : IsObjectValid();
1759 :
1760 0 : if (mpChildrenShapes)
1761 : {
1762 0 : sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table
1763 0 : if (mxTempAcc.is())
1764 0 : ++nCount;
1765 0 : if (nChildIndex < 0 || nChildIndex >= nCount)
1766 0 : throw lang::IndexOutOfBoundsException();
1767 :
1768 0 : sal_Bool bTabMarked(IsTableSelected());
1769 :
1770 0 : uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex);
1771 0 : if (xAccessible.is())
1772 : {
1773 0 : if (mpChildrenShapes)
1774 0 : mpChildrenShapes->Deselect(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is to high
1775 :
1776 0 : if (bTabMarked)
1777 0 : mpViewShell->SelectAll(); // select the table again
1778 : }
1779 0 : else if (bTabMarked)
1780 0 : mpViewShell->Unmark();
1781 0 : }
1782 0 : }
1783 :
1784 : //===== XServiceInfo ====================================================
1785 :
1786 : OUString SAL_CALL
1787 0 : ScAccessibleDocument::getImplementationName(void)
1788 : throw (uno::RuntimeException)
1789 : {
1790 0 : return OUString("ScAccessibleDocument");
1791 : }
1792 :
1793 : uno::Sequence< OUString> SAL_CALL
1794 0 : ScAccessibleDocument::getSupportedServiceNames(void)
1795 : throw (uno::RuntimeException)
1796 : {
1797 0 : uno::Sequence< OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
1798 0 : sal_Int32 nOldSize(aSequence.getLength());
1799 0 : aSequence.realloc(nOldSize + 1);
1800 0 : OUString* pNames = aSequence.getArray();
1801 :
1802 0 : pNames[nOldSize] = OUString("com.sun.star.AccessibleSpreadsheetDocumentView");
1803 :
1804 0 : return aSequence;
1805 : }
1806 :
1807 : //===== XTypeProvider =======================================================
1808 :
1809 0 : uno::Sequence< uno::Type > SAL_CALL ScAccessibleDocument::getTypes()
1810 : throw (uno::RuntimeException)
1811 : {
1812 0 : return comphelper::concatSequences(ScAccessibleDocumentImpl::getTypes(), ScAccessibleContextBase::getTypes());
1813 : }
1814 :
1815 : namespace
1816 : {
1817 : class theScAccessibleDocumentImplementationId : public rtl::Static< UnoTunnelIdInit, theScAccessibleDocumentImplementationId > {};
1818 : }
1819 :
1820 : uno::Sequence<sal_Int8> SAL_CALL
1821 0 : ScAccessibleDocument::getImplementationId(void)
1822 : throw (uno::RuntimeException)
1823 : {
1824 0 : return theScAccessibleDocumentImplementationId::get().getSeq();
1825 : }
1826 :
1827 : ///===== IAccessibleViewForwarder ========================================
1828 :
1829 0 : sal_Bool ScAccessibleDocument::IsValid (void) const
1830 : {
1831 0 : SolarMutexGuard aGuard;
1832 0 : IsObjectValid();
1833 0 : return (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose);
1834 : }
1835 :
1836 4 : Rectangle ScAccessibleDocument::GetVisibleArea_Impl() const
1837 : {
1838 4 : Rectangle aVisRect(GetBoundingBox());
1839 :
1840 4 : Point aPoint(mpViewShell->GetViewData()->GetPixPos(meSplitPos)); // returns a negative Point
1841 4 : aPoint.setX(-aPoint.getX());
1842 4 : aPoint.setY(-aPoint.getY());
1843 4 : aVisRect.SetPos(aPoint);
1844 :
1845 4 : ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1846 4 : if (pWin)
1847 4 : aVisRect = pWin->PixelToLogic(aVisRect, pWin->GetDrawMapMode());
1848 :
1849 4 : return aVisRect;
1850 : }
1851 :
1852 0 : Rectangle ScAccessibleDocument::GetVisibleArea() const
1853 : {
1854 0 : SolarMutexGuard aGuard;
1855 0 : IsObjectValid();
1856 0 : return maVisArea;
1857 : }
1858 :
1859 0 : Point ScAccessibleDocument::LogicToPixel (const Point& rPoint) const
1860 : {
1861 0 : SolarMutexGuard aGuard;
1862 0 : IsObjectValid();
1863 0 : Point aPoint;
1864 0 : ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1865 0 : if (pWin)
1866 : {
1867 0 : aPoint = pWin->LogicToPixel(rPoint, pWin->GetDrawMapMode());
1868 0 : aPoint += pWin->GetWindowExtentsRelative(NULL).TopLeft();
1869 : }
1870 0 : return aPoint;
1871 : }
1872 :
1873 0 : Size ScAccessibleDocument::LogicToPixel (const Size& rSize) const
1874 : {
1875 0 : SolarMutexGuard aGuard;
1876 0 : IsObjectValid();
1877 0 : Size aSize;
1878 0 : ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1879 0 : if (pWin)
1880 0 : aSize = pWin->LogicToPixel(rSize, pWin->GetDrawMapMode());
1881 0 : return aSize;
1882 : }
1883 :
1884 0 : Point ScAccessibleDocument::PixelToLogic (const Point& rPoint) const
1885 : {
1886 0 : SolarMutexGuard aGuard;
1887 0 : IsObjectValid();
1888 0 : Point aPoint;
1889 0 : ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1890 0 : if (pWin)
1891 : {
1892 0 : aPoint -= pWin->GetWindowExtentsRelative(NULL).TopLeft();
1893 0 : aPoint = pWin->PixelToLogic(rPoint, pWin->GetDrawMapMode());
1894 : }
1895 0 : return aPoint;
1896 : }
1897 :
1898 0 : Size ScAccessibleDocument::PixelToLogic (const Size& rSize) const
1899 : {
1900 0 : SolarMutexGuard aGuard;
1901 0 : IsObjectValid();
1902 0 : Size aSize;
1903 0 : ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos));
1904 0 : if (pWin)
1905 0 : aSize = pWin->PixelToLogic(rSize, pWin->GetDrawMapMode());
1906 0 : return aSize;
1907 : }
1908 :
1909 : //===== internal ========================================================
1910 :
1911 1 : utl::AccessibleRelationSetHelper* ScAccessibleDocument::GetRelationSet(const ScAddress* pAddress) const
1912 : {
1913 1 : utl::AccessibleRelationSetHelper* pRelationSet = NULL;
1914 1 : if (mpChildrenShapes)
1915 1 : pRelationSet = mpChildrenShapes->GetRelationSet(pAddress);
1916 1 : return pRelationSet;
1917 : }
1918 :
1919 : OUString SAL_CALL
1920 2 : ScAccessibleDocument::createAccessibleDescription(void)
1921 : throw (uno::RuntimeException)
1922 : {
1923 2 : OUString sDescription = String(ScResId(STR_ACC_DOC_DESCR));
1924 2 : return sDescription;
1925 : }
1926 :
1927 : OUString SAL_CALL
1928 1 : ScAccessibleDocument::createAccessibleName(void)
1929 : throw (uno::RuntimeException)
1930 : {
1931 1 : SolarMutexGuard aGuard;
1932 1 : IsObjectValid();
1933 1 : OUString sName = String(ScResId(STR_ACC_DOC_NAME));
1934 1 : sal_Int32 nNumber(sal_Int32(meSplitPos) + 1);
1935 1 : sName += OUString::valueOf(nNumber);
1936 1 : return sName;
1937 : }
1938 :
1939 0 : Rectangle ScAccessibleDocument::GetBoundingBoxOnScreen() const
1940 : throw (uno::RuntimeException)
1941 : {
1942 0 : Rectangle aRect;
1943 0 : if (mpViewShell)
1944 : {
1945 0 : Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
1946 0 : if (pWindow)
1947 0 : aRect = pWindow->GetWindowExtentsRelative(NULL);
1948 : }
1949 0 : return aRect;
1950 : }
1951 :
1952 30 : Rectangle ScAccessibleDocument::GetBoundingBox() const
1953 : throw (uno::RuntimeException)
1954 : {
1955 30 : Rectangle aRect;
1956 30 : if (mpViewShell)
1957 : {
1958 30 : Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos);
1959 30 : if (pWindow)
1960 30 : aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
1961 : }
1962 30 : return aRect;
1963 : }
1964 :
1965 21 : SCTAB ScAccessibleDocument::getVisibleTable() const
1966 : {
1967 21 : SCTAB nVisibleTable(0);
1968 21 : if (mpViewShell && mpViewShell->GetViewData())
1969 21 : nVisibleTable = mpViewShell->GetViewData()->GetTabNo();
1970 21 : return nVisibleTable;
1971 : }
1972 :
1973 : uno::Reference < XAccessible >
1974 2 : ScAccessibleDocument::GetAccessibleSpreadsheet()
1975 : {
1976 2 : if (!mpAccessibleSpreadsheet && mpViewShell)
1977 : {
1978 2 : mpAccessibleSpreadsheet = new ScAccessibleSpreadsheet(this, mpViewShell, getVisibleTable(), meSplitPos);
1979 2 : mpAccessibleSpreadsheet->acquire();
1980 2 : mpAccessibleSpreadsheet->Init();
1981 2 : mbCompleteSheetSelected = IsTableSelected();
1982 : }
1983 2 : return mpAccessibleSpreadsheet;
1984 : }
1985 :
1986 2 : void ScAccessibleDocument::FreeAccessibleSpreadsheet()
1987 : {
1988 2 : if (mpAccessibleSpreadsheet)
1989 : {
1990 2 : mpAccessibleSpreadsheet->dispose();
1991 2 : mpAccessibleSpreadsheet->release();
1992 2 : mpAccessibleSpreadsheet = NULL;
1993 : }
1994 2 : }
1995 :
1996 7 : sal_Bool ScAccessibleDocument::IsTableSelected() const
1997 : {
1998 7 : sal_Bool bResult (false);
1999 7 : if(mpViewShell)
2000 : {
2001 7 : SCTAB nTab(getVisibleTable());
2002 : //#103800#; use a copy of MarkData
2003 7 : ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData());
2004 7 : aMarkData.MarkToMulti();
2005 7 : if (aMarkData.IsAllMarked(ScRange(ScAddress(0, 0, nTab),ScAddress(MAXCOL, MAXROW, nTab))))
2006 0 : bResult = sal_True;
2007 : }
2008 7 : return bResult;
2009 : }
2010 :
2011 14 : sal_Bool ScAccessibleDocument::IsDefunc(
2012 : const uno::Reference<XAccessibleStateSet>& rxParentStates)
2013 : {
2014 56 : return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() ||
2015 56 : (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
2016 : }
2017 :
2018 14 : sal_Bool ScAccessibleDocument::IsEditable(
2019 : const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
2020 : {
2021 : // what is with document protection or readonly documents?
2022 14 : return sal_True;
2023 : }
2024 :
2025 0 : void ScAccessibleDocument::AddChild(const uno::Reference<XAccessible>& xAcc, sal_Bool bFireEvent)
2026 : {
2027 : OSL_ENSURE(!mxTempAcc.is(), "this object should be removed before");
2028 0 : if (xAcc.is())
2029 : {
2030 0 : mxTempAcc = xAcc;
2031 0 : if( bFireEvent )
2032 : {
2033 0 : AccessibleEventObject aEvent;
2034 0 : aEvent.Source = uno::Reference<XAccessibleContext>(this);
2035 0 : aEvent.EventId = AccessibleEventId::CHILD;
2036 0 : aEvent.NewValue <<= mxTempAcc;
2037 0 : CommitChange( aEvent );
2038 : }
2039 : }
2040 0 : }
2041 :
2042 0 : void ScAccessibleDocument::RemoveChild(const uno::Reference<XAccessible>& xAcc, sal_Bool bFireEvent)
2043 : {
2044 : OSL_ENSURE(mxTempAcc.is(), "this object should be added before");
2045 0 : if (xAcc.is())
2046 : {
2047 : OSL_ENSURE(xAcc.get() == mxTempAcc.get(), "only the same object should be removed");
2048 0 : if( bFireEvent )
2049 : {
2050 0 : AccessibleEventObject aEvent;
2051 0 : aEvent.Source = uno::Reference<XAccessibleContext>(this);
2052 0 : aEvent.EventId = AccessibleEventId::CHILD;
2053 0 : aEvent.OldValue <<= mxTempAcc;
2054 0 : CommitChange( aEvent );
2055 : }
2056 0 : mxTempAcc = NULL;
2057 : }
2058 0 : }
2059 :
2060 0 : OUString ScAccessibleDocument::GetCurrentCellName() const
2061 : {
2062 0 : String sName( ScResId(STR_ACC_CELL_NAME) );
2063 0 : if (mpViewShell)
2064 : {
2065 0 : String sAddress;
2066 : // Document not needed, because only the cell address, but not the tablename is needed
2067 0 : mpViewShell->GetViewData()->GetCurPos().Format( sAddress, SCA_VALID, NULL );
2068 0 : sName.SearchAndReplaceAscii("%1", sAddress);
2069 : }
2070 0 : return OUString(sName);
2071 : }
2072 :
2073 0 : OUString ScAccessibleDocument::GetCurrentCellDescription() const
2074 : {
2075 0 : return OUString();
2076 93 : }
2077 :
2078 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|