fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / Accessibility / AccessibleDocumentPagePreview.cxx
blobc127841e54f08cf00ae54368cd533c86170ce6a0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "AccessibleDocumentPagePreview.hxx"
21 #include "AccessiblePreviewTable.hxx"
22 #include "AccessiblePageHeader.hxx"
23 #include "AccessibilityHints.hxx"
24 #include "AccessibleText.hxx"
25 #include "document.hxx"
26 #include "prevwsh.hxx"
27 #include "prevloc.hxx"
28 #include "drwlayer.hxx"
29 #include "editsrc.hxx"
30 #include "scresid.hxx"
31 #include "sc.hrc"
32 #include "DrawModelBroadcaster.hxx"
33 #include "docsh.hxx"
34 #include "drawview.hxx"
35 #include "preview.hxx"
36 #include "postit.hxx"
38 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
39 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
40 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
42 #include <unotools/accessiblestatesethelper.hxx>
43 #include <tools/gen.hxx>
44 #include <svx/svdpage.hxx>
45 #include <svx/svdobj.hxx>
46 #include <svx/AccessibleTextHelper.hxx>
47 #include <svx/AccessibleShape.hxx>
48 #include <svx/ShapeTypeHandler.hxx>
49 #include <toolkit/helper/convert.hxx>
50 #include <svx/unoshape.hxx>
51 #include <unotools/accessiblerelationsethelper.hxx>
52 #include <vcl/svapp.hxx>
53 #include <sfx2/docfile.hxx>
54 #include <comphelper/servicehelper.hxx>
56 #include <utility>
57 #include <vector>
58 #include <list>
59 #include <algorithm>
60 #include <memory>
62 using namespace ::com::sun::star;
63 using namespace ::com::sun::star::accessibility;
65 typedef std::list< uno::Reference< XAccessible > > ScXAccList;
67 struct ScAccNote
69 OUString maNoteText;
70 Rectangle maRect;
71 ScAddress maNoteCell;
72 ::accessibility::AccessibleTextHelper* mpTextHelper;
73 sal_Int32 mnParaCount;
74 bool mbMarkNote;
76 ScAccNote()
77 : mpTextHelper(NULL)
78 , mnParaCount(0)
79 , mbMarkNote(false)
84 class ScNotesChildren
86 public:
87 ScNotesChildren(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc);
88 ~ScNotesChildren();
89 void Init(const Rectangle& rVisRect, sal_Int32 nOffset);
91 sal_Int32 GetChildrenCount() const { return mnParagraphs;}
92 uno::Reference<XAccessible> GetChild(sal_Int32 nIndex) const;
93 uno::Reference<XAccessible> GetAt(const awt::Point& rPoint) const;
95 void DataChanged(const Rectangle& rVisRect);
97 private:
98 ScPreviewShell* mpViewShell;
99 ScAccessibleDocumentPagePreview* mpAccDoc;
100 typedef std::vector<ScAccNote> ScAccNotes;
101 mutable ScAccNotes maNotes;
102 mutable ScAccNotes maMarks;
103 sal_Int32 mnParagraphs;
104 sal_Int32 mnOffset;
106 ::accessibility::AccessibleTextHelper* CreateTextHelper(const OUString& rString, const Rectangle& rVisRect, const ScAddress& aCellPos, bool bMarkNote, sal_Int32 nChildOffset) const;
107 sal_Int32 AddNotes(const ScPreviewLocationData& rData, const Rectangle& rVisRect, bool bMark, ScAccNotes& rNotes);
109 static sal_Int8 CompareCell(const ScAddress& aCell1, const ScAddress& aCell2);
110 static void CollectChildren(const ScAccNote& rNote, ScXAccList& rList);
111 sal_Int32 CheckChanges(const ScPreviewLocationData& rData, const Rectangle& rVisRect,
112 bool bMark, ScAccNotes& rOldNotes, ScAccNotes& rNewNotes,
113 ScXAccList& rOldParas, ScXAccList& rNewParas);
115 inline ScDocument* GetDocument() const;
118 ScNotesChildren::ScNotesChildren(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc)
119 : mpViewShell(pViewShell),
120 mpAccDoc(pAccDoc),
121 mnParagraphs(0),
122 mnOffset(0)
126 struct DeleteAccNote
128 void operator()(ScAccNote& rNote)
130 if (rNote.mpTextHelper)
131 DELETEZ( rNote.mpTextHelper);
135 ScNotesChildren::~ScNotesChildren()
137 std::for_each(maNotes.begin(), maNotes.end(), DeleteAccNote());
138 std::for_each(maMarks.begin(), maMarks.end(), DeleteAccNote());
141 ::accessibility::AccessibleTextHelper* ScNotesChildren::CreateTextHelper(const OUString& rString, const Rectangle& rVisRect, const ScAddress& aCellPos, bool bMarkNote, sal_Int32 nChildOffset) const
143 ::std::unique_ptr < ScAccessibleTextData > pAccessiblePreviewHeaderCellTextData
144 (new ScAccessibleNoteTextData(mpViewShell, rString, aCellPos, bMarkNote));
145 ::std::unique_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(std::move(pAccessiblePreviewHeaderCellTextData)));
147 ::accessibility::AccessibleTextHelper* pTextHelper = new ::accessibility::AccessibleTextHelper(std::move(pEditSource));
149 pTextHelper->SetEventSource(mpAccDoc);
150 pTextHelper->SetStartIndex(nChildOffset);
151 pTextHelper->SetOffset(rVisRect.TopLeft());
153 return pTextHelper;
156 sal_Int32 ScNotesChildren::AddNotes(const ScPreviewLocationData& rData, const Rectangle& rVisRect, bool bMark, ScAccNotes& rNotes)
158 sal_Int32 nCount = rData.GetNoteCountInRange(rVisRect, bMark);
160 rNotes.reserve(nCount);
162 sal_Int32 nParagraphs(0);
163 ScDocument* pDoc = GetDocument();
164 if (pDoc)
166 ScAccNote aNote;
167 aNote.mbMarkNote = bMark;
168 if (bMark)
169 aNote.mnParaCount = 1;
170 for (sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex)
172 if (rData.GetNoteInRange(rVisRect, nIndex, bMark, aNote.maNoteCell, aNote.maRect))
174 if (bMark)
176 // Document not needed, because only the cell address, but not the tablename is needed
177 aNote.maNoteText = aNote.maNoteCell.Format(SCA_VALID, NULL);
179 else
181 if( ScPostIt* pNote = pDoc->GetNote( aNote.maNoteCell ) )
182 aNote.maNoteText = pNote->GetText();
183 aNote.mpTextHelper = CreateTextHelper(aNote.maNoteText, aNote.maRect, aNote.maNoteCell, aNote.mbMarkNote, nParagraphs + mnOffset);
184 if (aNote.mpTextHelper)
185 aNote.mnParaCount = aNote.mpTextHelper->GetChildCount();
187 nParagraphs += aNote.mnParaCount;
188 rNotes.push_back(aNote);
192 return nParagraphs;
195 void ScNotesChildren::Init(const Rectangle& rVisRect, sal_Int32 nOffset)
197 if (mpViewShell && !mnParagraphs)
199 mnOffset = nOffset;
200 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
202 mnParagraphs = AddNotes(rData, rVisRect, false, maMarks);
203 mnParagraphs += AddNotes(rData, rVisRect, true, maNotes);
207 struct ScParaFound
209 sal_Int32 mnIndex;
210 ScParaFound(sal_Int32 nIndex) : mnIndex(nIndex) {}
211 bool operator() (const ScAccNote& rNote)
213 bool bResult(false);
214 if (rNote.mnParaCount > mnIndex)
215 bResult = true;
216 else
217 mnIndex -= rNote.mnParaCount;
218 return bResult;
222 uno::Reference<XAccessible> ScNotesChildren::GetChild(sal_Int32 nIndex) const
224 uno::Reference<XAccessible> xAccessible;
226 if (nIndex < mnParagraphs)
228 if (nIndex < static_cast<sal_Int32>(maMarks.size()))
230 ScAccNotes::iterator aEndItr = maMarks.end();
231 ScParaFound aParaFound(nIndex);
232 ScAccNotes::iterator aItr = std::find_if(maMarks.begin(), aEndItr, aParaFound);
233 if (aItr != aEndItr)
235 OSL_ENSURE((aItr->maNoteCell == maMarks[nIndex].maNoteCell) && (aItr->mbMarkNote == maMarks[nIndex].mbMarkNote), "wrong note found");
236 if (!aItr->mpTextHelper)
237 aItr->mpTextHelper = CreateTextHelper(maMarks[nIndex].maNoteText, maMarks[nIndex].maRect, maMarks[nIndex].maNoteCell, maMarks[nIndex].mbMarkNote, nIndex + mnOffset); // the marks are the first and every mark has only one paragraph
238 xAccessible = aItr->mpTextHelper->GetChild(aParaFound.mnIndex + aItr->mpTextHelper->GetStartIndex());
240 else
242 OSL_FAIL("wrong note found");
245 else
247 nIndex -= maMarks.size();
248 ScAccNotes::iterator aEndItr = maNotes.end();
249 ScParaFound aParaFound(nIndex);
250 ScAccNotes::iterator aItr = std::find_if(maNotes.begin(), aEndItr, aParaFound);
251 if (aEndItr != aItr)
253 if (!aItr->mpTextHelper)
254 aItr->mpTextHelper = CreateTextHelper(aItr->maNoteText, aItr->maRect, aItr->maNoteCell, aItr->mbMarkNote, (nIndex - aParaFound.mnIndex) + mnOffset + maMarks.size());
255 xAccessible = aItr->mpTextHelper->GetChild(aParaFound.mnIndex + aItr->mpTextHelper->GetStartIndex());
260 return xAccessible;
263 struct ScPointFound
265 Rectangle maPoint;
266 sal_Int32 mnParagraphs;
267 ScPointFound(const Point& rPoint) : maPoint(rPoint, Size(0, 0)), mnParagraphs(0) {}
268 bool operator() (const ScAccNote& rNote)
270 bool bResult(false);
271 if (maPoint.IsInside(rNote.maRect))
272 bResult = true;
273 else
274 mnParagraphs += rNote.mnParaCount;
275 return bResult;
279 uno::Reference<XAccessible> ScNotesChildren::GetAt(const awt::Point& rPoint) const
281 uno::Reference<XAccessible> xAccessible;
283 ScPointFound aPointFound(Point(rPoint.X, rPoint.Y));
285 ScAccNotes::iterator aEndItr = maMarks.end();
286 ScAccNotes::iterator aItr = std::find_if(maMarks.begin(), aEndItr, aPointFound);
287 if (aEndItr == aItr)
289 aEndItr = maNotes.end();
290 aItr = std::find_if(maNotes.begin(), aEndItr, aPointFound);
292 if (aEndItr != aItr)
294 if (!aItr->mpTextHelper)
295 aItr->mpTextHelper = CreateTextHelper(aItr->maNoteText, aItr->maRect, aItr->maNoteCell, aItr->mbMarkNote, aPointFound.mnParagraphs + mnOffset);
296 xAccessible = aItr->mpTextHelper->GetAt(rPoint);
299 return xAccessible;
302 sal_Int8 ScNotesChildren::CompareCell(const ScAddress& aCell1, const ScAddress& aCell2)
304 OSL_ENSURE(aCell1.Tab() == aCell2.Tab(), "the notes should be on the same table");
305 sal_Int8 nResult(0);
306 if (aCell1 != aCell2)
308 if (aCell1.Row() == aCell2.Row())
309 nResult = (aCell1.Col() < aCell2.Col()) ? -1 : 1;
310 else
311 nResult = (aCell1.Row() < aCell2.Row()) ? -1 : 1;
313 return nResult;
316 void ScNotesChildren::CollectChildren(const ScAccNote& rNote, ScXAccList& rList)
318 if (rNote.mpTextHelper)
319 for (sal_Int32 i = 0; i < rNote.mnParaCount; ++i)
320 rList.push_back(rNote.mpTextHelper->GetChild(i + rNote.mpTextHelper->GetStartIndex()));
323 sal_Int32 ScNotesChildren::CheckChanges(const ScPreviewLocationData& rData,
324 const Rectangle& rVisRect, bool bMark, ScAccNotes& rOldNotes,
325 ScAccNotes& rNewNotes, ScXAccList& rOldParas, ScXAccList& rNewParas)
327 sal_Int32 nCount = rData.GetNoteCountInRange(rVisRect, bMark);
329 rNewNotes.reserve(nCount);
331 sal_Int32 nParagraphs(0);
332 ScDocument* pDoc = GetDocument();
333 if (pDoc)
335 ScAccNote aNote;
336 aNote.mbMarkNote = bMark;
337 if (bMark)
338 aNote.mnParaCount = 1;
339 ScAccNotes::iterator aItr = rOldNotes.begin();
340 ScAccNotes::iterator aEndItr = rOldNotes.end();
341 bool bAddNote(false);
342 for (sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex)
344 if (rData.GetNoteInRange(rVisRect, nIndex, bMark, aNote.maNoteCell, aNote.maRect))
346 if (bMark)
348 // Document not needed, because only the cell address, but not the tablename is needed
349 aNote.maNoteText = aNote.maNoteCell.Format(SCA_VALID, NULL);
351 else
353 if( ScPostIt* pNote = pDoc->GetNote( aNote.maNoteCell ) )
354 aNote.maNoteText = pNote->GetText();
357 sal_Int8 nCompare(-1); // if there are no more old children it is always a new one
358 if (aItr != aEndItr)
359 nCompare = CompareCell(aNote.maNoteCell, aItr->maNoteCell);
360 if (nCompare == 0)
362 if (aNote.maNoteText == aItr->maNoteText)
364 aNote.mpTextHelper = aItr->mpTextHelper;
365 if (aNote.maRect != aItr->maRect) //neue VisArea setzen
367 aNote.mpTextHelper->SetOffset(aNote.maRect.TopLeft());
368 aNote.mpTextHelper->UpdateChildren();
369 //OSL_ENSURE(aItr->maRect.GetSize() == aNote.maRect.GetSize(), "size should be the same, because the text is not changed");
370 // could be changed, because only a part of the note is visible
373 else
375 aNote.mpTextHelper = CreateTextHelper(aNote.maNoteText, aNote.maRect, aNote.maNoteCell, aNote.mbMarkNote, nParagraphs + mnOffset);
376 if (aNote.mpTextHelper)
377 aNote.mnParaCount = aNote.mpTextHelper->GetChildCount();
378 // collect removed children
379 CollectChildren(*aItr, rOldParas);
380 DELETEZ(aItr->mpTextHelper);
381 // collect new children
382 CollectChildren(aNote, rNewParas);
384 bAddNote = true;
385 // not necessary, because this branch should not be reached if it is the end
386 //if (aItr != aEndItr)
387 ++aItr;
389 else if (nCompare < 0)
391 aNote.mpTextHelper = CreateTextHelper(aNote.maNoteText, aNote.maRect, aNote.maNoteCell, aNote.mbMarkNote, nParagraphs + mnOffset);
392 if (aNote.mpTextHelper)
393 aNote.mnParaCount = aNote.mpTextHelper->GetChildCount();
394 // collect new children
395 CollectChildren(aNote, rNewParas);
396 bAddNote = true;
398 else
400 // collect removed children
401 CollectChildren(*aItr, rOldParas);
402 DELETEZ(aItr->mpTextHelper);
404 // no note to add
405 // not necessary, because this branch should not be reached if it is the end
406 //if (aItr != aEndItr)
407 ++aItr;
409 if (bAddNote)
411 nParagraphs += aNote.mnParaCount;
412 rNewNotes.push_back(aNote);
413 bAddNote = false;
418 return nParagraphs;
421 struct ScChildGone
423 ScAccessibleDocumentPagePreview* mpAccDoc;
424 ScChildGone(ScAccessibleDocumentPagePreview* pAccDoc) : mpAccDoc(pAccDoc) {}
425 void operator() (const uno::Reference<XAccessible>& xAccessible) const
427 if (mpAccDoc)
429 AccessibleEventObject aEvent;
430 aEvent.EventId = AccessibleEventId::CHILD;
431 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccDoc);
432 aEvent.OldValue <<= xAccessible;
434 mpAccDoc->CommitChange(aEvent); // gone child - event
439 struct ScChildNew
441 ScAccessibleDocumentPagePreview* mpAccDoc;
442 ScChildNew(ScAccessibleDocumentPagePreview* pAccDoc) : mpAccDoc(pAccDoc) {}
443 void operator() (const uno::Reference<XAccessible>& xAccessible) const
445 if (mpAccDoc)
447 AccessibleEventObject aEvent;
448 aEvent.EventId = AccessibleEventId::CHILD;
449 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccDoc);
450 aEvent.NewValue <<= xAccessible;
452 mpAccDoc->CommitChange(aEvent); // new child - event
457 void ScNotesChildren::DataChanged(const Rectangle& rVisRect)
459 if (mpViewShell && mpAccDoc)
461 ScXAccList aNewParas;
462 ScXAccList aOldParas;
463 ScAccNotes aNewMarks;
464 mnParagraphs = CheckChanges(mpViewShell->GetLocationData(), rVisRect, true, maMarks, aNewMarks, aOldParas, aNewParas);
465 maMarks = aNewMarks;
466 ScAccNotes aNewNotes;
467 mnParagraphs += CheckChanges(mpViewShell->GetLocationData(), rVisRect, false, maNotes, aNewNotes, aOldParas, aNewParas);
468 maNotes = aNewNotes;
470 std::for_each(aOldParas.begin(), aOldParas.end(), ScChildGone(mpAccDoc));
471 std::for_each(aNewParas.begin(), aNewParas.end(), ScChildNew(mpAccDoc));
475 inline ScDocument* ScNotesChildren::GetDocument() const
477 ScDocument* pDoc = NULL;
478 if (mpViewShell)
479 pDoc = &mpViewShell->GetDocument();
480 return pDoc;
483 class ScIAccessibleViewForwarder : public ::accessibility::IAccessibleViewForwarder
485 public:
486 ScIAccessibleViewForwarder();
487 ScIAccessibleViewForwarder(ScPreviewShell* pViewShell,
488 ScAccessibleDocumentPagePreview* pAccDoc,
489 const MapMode& aMapMode);
490 virtual ~ScIAccessibleViewForwarder();
492 ///===== IAccessibleViewForwarder ========================================
494 virtual bool IsValid() const SAL_OVERRIDE;
495 virtual Rectangle GetVisibleArea() const SAL_OVERRIDE;
496 virtual Point LogicToPixel (const Point& rPoint) const SAL_OVERRIDE;
497 virtual Size LogicToPixel (const Size& rSize) const SAL_OVERRIDE;
498 virtual Point PixelToLogic (const Point& rPoint) const SAL_OVERRIDE;
499 virtual Size PixelToLogic (const Size& rSize) const SAL_OVERRIDE;
501 private:
502 ScPreviewShell* mpViewShell;
503 ScAccessibleDocumentPagePreview* mpAccDoc;
504 MapMode maMapMode;
505 bool mbValid;
508 ScIAccessibleViewForwarder::ScIAccessibleViewForwarder()
509 : mpViewShell(NULL), mpAccDoc(NULL), mbValid(false)
513 ScIAccessibleViewForwarder::ScIAccessibleViewForwarder(ScPreviewShell* pViewShell,
514 ScAccessibleDocumentPagePreview* pAccDoc,
515 const MapMode& aMapMode)
516 : mpViewShell(pViewShell),
517 mpAccDoc(pAccDoc),
518 maMapMode(aMapMode),
519 mbValid(true)
523 ScIAccessibleViewForwarder::~ScIAccessibleViewForwarder()
527 ///===== IAccessibleViewForwarder ========================================
529 bool ScIAccessibleViewForwarder::IsValid() const
531 SolarMutexGuard aGuard;
532 return mbValid;
535 Rectangle ScIAccessibleViewForwarder::GetVisibleArea() const
537 SolarMutexGuard aGuard;
538 Rectangle aVisRect;
539 vcl::Window* pWin = mpViewShell->GetWindow();
540 if (pWin)
542 aVisRect.SetSize(pWin->GetOutputSizePixel());
543 aVisRect.SetPos(Point(0, 0));
545 aVisRect = pWin->PixelToLogic(aVisRect, maMapMode);
548 return aVisRect;
551 Point ScIAccessibleViewForwarder::LogicToPixel (const Point& rPoint) const
553 SolarMutexGuard aGuard;
554 Point aPoint;
555 vcl::Window* pWin = mpViewShell->GetWindow();
556 if (pWin && mpAccDoc)
558 Rectangle aRect(mpAccDoc->GetBoundingBoxOnScreen());
559 aPoint = pWin->LogicToPixel(rPoint, maMapMode) + aRect.TopLeft();
562 return aPoint;
565 Size ScIAccessibleViewForwarder::LogicToPixel (const Size& rSize) const
567 SolarMutexGuard aGuard;
568 Size aSize;
569 vcl::Window* pWin = mpViewShell->GetWindow();
570 if (pWin)
571 aSize = pWin->LogicToPixel(rSize, maMapMode);
572 return aSize;
575 Point ScIAccessibleViewForwarder::PixelToLogic (const Point& rPoint) const
577 SolarMutexGuard aGuard;
578 Point aPoint;
579 vcl::Window* pWin = mpViewShell->GetWindow();
580 if (pWin && mpAccDoc)
582 Rectangle aRect(mpAccDoc->GetBoundingBoxOnScreen());
583 aPoint = pWin->PixelToLogic(rPoint - aRect.TopLeft(), maMapMode);
585 return aPoint;
588 Size ScIAccessibleViewForwarder::PixelToLogic (const Size& rSize) const
590 SolarMutexGuard aGuard;
591 Size aSize;
592 vcl::Window* pWin = mpViewShell->GetWindow();
593 if (pWin)
594 aSize = pWin->PixelToLogic(rSize, maMapMode);
595 return aSize;
598 struct ScShapeChild
600 ScShapeChild()
601 : mpAccShape(NULL)
602 , mnRangeId(0)
605 ScShapeChild(const ScShapeChild& rOld);
606 ~ScShapeChild();
607 mutable ::accessibility::AccessibleShape* mpAccShape;
608 com::sun::star::uno::Reference< com::sun::star::drawing::XShape > mxShape;
609 sal_Int32 mnRangeId;
612 ScShapeChild::ScShapeChild(const ScShapeChild& rOld)
614 mpAccShape(rOld.mpAccShape),
615 mxShape(rOld.mxShape),
616 mnRangeId(rOld.mnRangeId)
618 if (mpAccShape)
619 mpAccShape->acquire();
622 ScShapeChild::~ScShapeChild()
624 if (mpAccShape)
626 mpAccShape->dispose();
627 mpAccShape->release();
631 struct ScShapeChildLess
633 bool operator()(const ScShapeChild& rChild1, const ScShapeChild& rChild2) const
635 bool bResult(false);
636 if (rChild1.mxShape.is() && rChild2.mxShape.is())
637 bResult = (rChild1.mxShape.get() < rChild2.mxShape.get());
638 return bResult;
642 typedef std::vector<ScShapeChild> ScShapeChildVec;
644 struct ScShapeRange
646 ScShapeChildVec maBackShapes;
647 ScShapeChildVec maForeShapes; // inclusive internal shapes
648 ScShapeChildVec maControls;
649 Rectangle maPixelRect;
650 MapMode maMapMode;
651 ScIAccessibleViewForwarder maViewForwarder;
654 typedef std::vector<ScShapeRange> ScShapeRangeVec;
656 class ScShapeChildren : public SfxListener,
657 public ::accessibility::IAccessibleParent
659 public:
660 ScShapeChildren(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc);
661 virtual ~ScShapeChildren();
663 ///===== SfxListener =====================================================
665 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) SAL_OVERRIDE;
667 ///===== IAccessibleParent ==============================================
669 virtual bool ReplaceChild (
670 ::accessibility::AccessibleShape* pCurrentChild,
671 const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape,
672 const long _nIndex,
673 const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo
674 ) throw (::com::sun::star::uno::RuntimeException) SAL_OVERRIDE;
676 ///===== Internal ========================================================
678 void Init();
680 sal_Int32 GetBackShapeCount() const;
681 uno::Reference<XAccessible> GetBackShape(sal_Int32 nIndex) const;
682 sal_Int32 GetForeShapeCount() const;
683 uno::Reference<XAccessible> GetForeShape(sal_Int32 nIndex) const;
684 sal_Int32 GetControlCount() const;
685 uno::Reference<XAccessible> GetControl(sal_Int32 nIndex) const;
686 uno::Reference<XAccessible> GetForegroundShapeAt(const awt::Point& rPoint) const; // inclusive controls
687 uno::Reference<XAccessible> GetBackgroundShapeAt(const awt::Point& rPoint) const;
689 void DataChanged();
690 void VisAreaChanged() const;
692 void SetDrawBroadcaster();
693 private:
694 ScAccessibleDocumentPagePreview* mpAccDoc;
695 ScPreviewShell* mpViewShell;
696 ScShapeRangeVec maShapeRanges;
698 void FindChanged(ScShapeChildVec& aOld, ScShapeChildVec& aNew) const;
699 void FindChanged(ScShapeRange& aOld, ScShapeRange& aNew) const;
700 ::accessibility::AccessibleShape* GetAccShape(const ScShapeChild& rShape) const;
701 ::accessibility::AccessibleShape* GetAccShape(const ScShapeChildVec& rShapes, sal_Int32 nIndex) const;
702 void FillShapes(const Rectangle& aPixelPaintRect, const MapMode& aMapMode, sal_uInt8 nRangeId);
704 // void AddShape(const uno::Reference<drawing::XShape>& xShape, SdrLayerID aLayerID);
705 // void RemoveShape(const uno::Reference<drawing::XShape>& xShape, SdrLayerID aLayerID);
706 SdrPage* GetDrawPage() const;
709 ScShapeChildren::ScShapeChildren(ScPreviewShell* pViewShell, ScAccessibleDocumentPagePreview* pAccDoc)
711 mpAccDoc(pAccDoc),
712 mpViewShell(pViewShell),
713 maShapeRanges(SC_PREVIEW_MAXRANGES)
715 if (pViewShell)
717 SfxBroadcaster* pDrawBC = pViewShell->GetDocument().GetDrawBroadcaster();
718 if (pDrawBC)
719 StartListening(*pDrawBC);
723 ScShapeChildren::~ScShapeChildren()
725 if (mpViewShell)
727 SfxBroadcaster* pDrawBC = mpViewShell->GetDocument().GetDrawBroadcaster();
728 if (pDrawBC)
729 EndListening(*pDrawBC);
733 void ScShapeChildren::SetDrawBroadcaster()
735 if (mpViewShell)
737 SfxBroadcaster* pDrawBC = mpViewShell->GetDocument().GetDrawBroadcaster();
738 if (pDrawBC)
739 StartListening(*pDrawBC, true);
743 void ScShapeChildren::Notify(SfxBroadcaster&, const SfxHint& rHint)
745 const SdrHint* pSdrHint = dynamic_cast<const SdrHint*>( &rHint );
746 if (pSdrHint)
748 SdrObject* pObj = const_cast<SdrObject*>(pSdrHint->GetObject());
749 if (pObj && (pObj->GetPage() == GetDrawPage()))
751 switch (pSdrHint->GetKind())
753 case HINT_OBJCHG : // Objekt geaendert
756 break;
757 default :
759 // other events are not interesting
761 break;
767 void ScShapeChildren::FindChanged(ScShapeChildVec& rOld, ScShapeChildVec& rNew) const
769 ScShapeChildVec::iterator aOldItr = rOld.begin();
770 ScShapeChildVec::iterator aOldEnd = rOld.end();
771 ScShapeChildVec::const_iterator aNewItr = rNew.begin();
772 ScShapeChildVec::const_iterator aNewEnd = rNew.begin();
773 uno::Reference<XAccessible> xAcc;
774 while ((aNewItr != aNewEnd) && (aOldItr != aOldEnd))
776 if (aNewItr->mxShape.get() == aOldItr->mxShape.get())
778 ++aOldItr;
779 ++aNewItr;
781 else if (aNewItr->mxShape.get() < aOldItr->mxShape.get())
783 xAcc = GetAccShape(*aNewItr);
784 AccessibleEventObject aEvent;
785 aEvent.Source = uno::Reference<XAccessibleContext> (mpAccDoc);
786 aEvent.EventId = AccessibleEventId::CHILD;
787 aEvent.NewValue <<= xAcc;
788 mpAccDoc->CommitChange(aEvent);
789 ++aNewItr;
791 else
793 xAcc = GetAccShape(*aOldItr);
794 AccessibleEventObject aEvent;
795 aEvent.Source = uno::Reference<XAccessibleContext> (mpAccDoc);
796 aEvent.EventId = AccessibleEventId::CHILD;
797 aEvent.OldValue <<= xAcc;
798 mpAccDoc->CommitChange(aEvent);
799 ++aOldItr;
802 while (aOldItr != aOldEnd)
804 xAcc = GetAccShape(*aOldItr);
805 AccessibleEventObject aEvent;
806 aEvent.Source = uno::Reference<XAccessibleContext> (mpAccDoc);
807 aEvent.EventId = AccessibleEventId::CHILD;
808 aEvent.OldValue <<= xAcc;
809 mpAccDoc->CommitChange(aEvent);
810 ++aOldItr;
812 while (aNewItr != aNewEnd)
814 xAcc = GetAccShape(*aNewItr);
815 AccessibleEventObject aEvent;
816 aEvent.Source = uno::Reference<XAccessibleContext> (mpAccDoc);
817 aEvent.EventId = AccessibleEventId::CHILD;
818 aEvent.NewValue <<= xAcc;
819 mpAccDoc->CommitChange(aEvent);
820 ++aNewItr;
824 void ScShapeChildren::FindChanged(ScShapeRange& rOld, ScShapeRange& rNew) const
826 FindChanged(rOld.maBackShapes, rNew.maBackShapes);
827 FindChanged(rOld.maForeShapes, rNew.maForeShapes);
828 FindChanged(rOld.maControls, rNew.maControls);
831 void ScShapeChildren::DataChanged()
833 ScShapeRangeVec aOldShapeRanges(maShapeRanges);
834 maShapeRanges.clear();
835 maShapeRanges.resize(SC_PREVIEW_MAXRANGES);
836 Init();
837 for (sal_Int32 i = 0; i < SC_PREVIEW_MAXRANGES; ++i)
839 FindChanged(aOldShapeRanges[i], maShapeRanges[i]);
843 namespace
845 struct ScVisAreaChanged
847 const ScIAccessibleViewForwarder* mpViewForwarder;
848 ScVisAreaChanged(const ScIAccessibleViewForwarder* pViewForwarder) : mpViewForwarder(pViewForwarder) {}
849 void operator() (const ScShapeChild& rAccShapeData) const
851 if (rAccShapeData.mpAccShape)
853 rAccShapeData.mpAccShape->ViewForwarderChanged(::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA, mpViewForwarder);
859 void ScShapeChildren::VisAreaChanged() const
861 ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end();
862 ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin();
863 while (aItr != aEndItr)
865 ScVisAreaChanged aVisAreaChanged(&(aItr->maViewForwarder));
866 std::for_each(aItr->maBackShapes.begin(), aItr->maBackShapes.end(), aVisAreaChanged);
867 std::for_each(aItr->maControls.begin(), aItr->maControls.end(), aVisAreaChanged);
868 std::for_each(aItr->maForeShapes.begin(), aItr->maForeShapes.end(), aVisAreaChanged);
869 ++aItr;
873 ///===== IAccessibleParent ==============================================
875 bool ScShapeChildren::ReplaceChild (::accessibility::AccessibleShape* /* pCurrentChild */,
876 const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& /* _rxShape */,
877 const long /* _nIndex */, const ::accessibility::AccessibleShapeTreeInfo& /* _rShapeTreeInfo */)
878 throw (uno::RuntimeException)
880 OSL_FAIL("should not be called in the page preview");
881 return false;
884 ///===== Internal ========================================================
886 void ScShapeChildren::Init()
888 if(mpViewShell)
890 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
891 MapMode aMapMode;
892 Rectangle aPixelPaintRect;
893 sal_uInt8 nRangeId;
894 sal_uInt16 nCount(rData.GetDrawRanges());
895 for (sal_uInt16 i = 0; i < nCount; ++i)
897 rData.GetDrawRange(i, aPixelPaintRect, aMapMode, nRangeId);
898 FillShapes(aPixelPaintRect, aMapMode, nRangeId);
903 sal_Int32 ScShapeChildren::GetBackShapeCount() const
905 sal_Int32 nCount(0);
906 ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end();
907 for ( ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin(); aItr != aEndItr; ++aItr )
908 nCount += aItr->maBackShapes.size();
909 return nCount;
912 uno::Reference<XAccessible> ScShapeChildren::GetBackShape(sal_Int32 nIndex) const
914 uno::Reference<XAccessible> xAccessible;
915 ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end();
916 ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin();
917 while ((aItr != aEndItr) && !xAccessible.is())
919 sal_Int32 nCount(aItr->maBackShapes.size());
920 if(nIndex < nCount)
921 xAccessible = GetAccShape(aItr->maBackShapes, nIndex);
922 else
923 ++aItr;
924 nIndex -= nCount;
927 if (nIndex >= 0)
928 throw lang::IndexOutOfBoundsException();
930 return xAccessible;
933 sal_Int32 ScShapeChildren::GetForeShapeCount() const
935 sal_Int32 nCount(0);
936 ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end();
937 for ( ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin(); aItr != aEndItr; ++aItr )
938 nCount += aItr->maForeShapes.size();
939 return nCount;
942 uno::Reference<XAccessible> ScShapeChildren::GetForeShape(sal_Int32 nIndex) const
944 uno::Reference<XAccessible> xAccessible;
945 ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end();
946 ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin();
947 while ((aItr != aEndItr) && !xAccessible.is())
949 sal_Int32 nCount(aItr->maForeShapes.size());
950 if(nIndex < nCount)
951 xAccessible = GetAccShape(aItr->maForeShapes, nIndex);
952 else
953 ++aItr;
954 nIndex -= nCount;
957 if (nIndex >= 0)
958 throw lang::IndexOutOfBoundsException();
960 return xAccessible;
963 sal_Int32 ScShapeChildren::GetControlCount() const
965 sal_Int32 nCount(0);
966 ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end();
967 for ( ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin(); aItr != aEndItr; ++aItr )
968 nCount += aItr->maControls.size();
969 return nCount;
972 uno::Reference<XAccessible> ScShapeChildren::GetControl(sal_Int32 nIndex) const
974 uno::Reference<XAccessible> xAccessible;
975 ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end();
976 ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin();
977 while ((aItr != aEndItr) && !xAccessible.is())
979 sal_Int32 nCount(aItr->maControls.size());
980 if(nIndex < nCount)
981 xAccessible = GetAccShape(aItr->maControls, nIndex);
982 else
983 ++aItr;
984 nIndex -= nCount;
987 if (nIndex >= 0)
988 throw lang::IndexOutOfBoundsException();
990 return xAccessible;
993 struct ScShapePointFound
995 Point maPoint;
996 ScShapePointFound(const awt::Point& rPoint) : maPoint(VCLPoint(rPoint)) {}
997 bool operator() (const ScShapeChild& rShape)
999 bool bResult(false);
1000 if ((VCLRectangle(rShape.mpAccShape->getBounds())).IsInside(maPoint))
1001 bResult = true;
1002 return bResult;
1006 uno::Reference<XAccessible> ScShapeChildren::GetForegroundShapeAt(const awt::Point& rPoint) const //inclusive Controls
1008 uno::Reference<XAccessible> xAcc;
1010 ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin();
1011 ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end();
1012 while((aItr != aEndItr) && !xAcc.is())
1014 ScShapeChildVec::const_iterator aFindItr = std::find_if(aItr->maForeShapes.begin(), aItr->maForeShapes.end(), ScShapePointFound(rPoint));
1015 if (aFindItr != aItr->maForeShapes.end())
1016 xAcc = GetAccShape(*aFindItr);
1017 else
1019 ScShapeChildVec::const_iterator aCtrlItr = std::find_if(aItr->maControls.begin(), aItr->maControls.end(), ScShapePointFound(rPoint));
1020 if (aCtrlItr != aItr->maControls.end())
1021 xAcc = GetAccShape(*aCtrlItr);
1022 else
1023 ++aItr;
1027 return xAcc;
1030 uno::Reference<XAccessible> ScShapeChildren::GetBackgroundShapeAt(const awt::Point& rPoint) const
1032 uno::Reference<XAccessible> xAcc;
1034 ScShapeRangeVec::const_iterator aItr = maShapeRanges.begin();
1035 ScShapeRangeVec::const_iterator aEndItr = maShapeRanges.end();
1036 while((aItr != aEndItr) && !xAcc.is())
1038 ScShapeChildVec::const_iterator aFindItr = std::find_if(aItr->maBackShapes.begin(), aItr->maBackShapes.end(), ScShapePointFound(rPoint));
1039 if (aFindItr != aItr->maBackShapes.end())
1040 xAcc = GetAccShape(*aFindItr);
1041 else
1042 ++aItr;
1045 return xAcc;
1048 ::accessibility::AccessibleShape* ScShapeChildren::GetAccShape(const ScShapeChild& rShape) const
1050 if (!rShape.mpAccShape)
1052 ::accessibility::ShapeTypeHandler& rShapeHandler = ::accessibility::ShapeTypeHandler::Instance();
1053 ::accessibility::AccessibleShapeInfo aShapeInfo(rShape.mxShape, mpAccDoc, const_cast<ScShapeChildren*>(this));
1055 if (mpViewShell)
1057 ::accessibility::AccessibleShapeTreeInfo aShapeTreeInfo;
1058 aShapeTreeInfo.SetSdrView(mpViewShell->GetPreview()->GetDrawView());
1059 aShapeTreeInfo.SetController(NULL);
1060 aShapeTreeInfo.SetWindow(mpViewShell->GetWindow());
1061 aShapeTreeInfo.SetViewForwarder(&(maShapeRanges[rShape.mnRangeId].maViewForwarder));
1062 rShape.mpAccShape = rShapeHandler.CreateAccessibleObject(aShapeInfo, aShapeTreeInfo);
1063 if (rShape.mpAccShape)
1065 rShape.mpAccShape->acquire();
1066 rShape.mpAccShape->Init();
1070 return rShape.mpAccShape;
1073 ::accessibility::AccessibleShape* ScShapeChildren::GetAccShape(const ScShapeChildVec& rShapes, sal_Int32 nIndex) const
1075 return (GetAccShape(rShapes[nIndex]));
1078 void ScShapeChildren::FillShapes(const Rectangle& aPixelPaintRect, const MapMode& aMapMode, sal_uInt8 nRangeId)
1080 OSL_ENSURE(nRangeId < maShapeRanges.size(), "this is not a valid range for draw objects");
1081 SdrPage* pPage = GetDrawPage();
1082 vcl::Window* pWin = mpViewShell->GetWindow();
1083 if (pPage && pWin)
1085 bool bForeAdded(false);
1086 bool bBackAdded(false);
1087 bool bControlAdded(false);
1088 Rectangle aClippedPixelPaintRect(aPixelPaintRect);
1089 if (mpAccDoc)
1091 Rectangle aRect2(Point(0,0), mpAccDoc->GetBoundingBoxOnScreen().GetSize());
1092 aClippedPixelPaintRect = aPixelPaintRect.GetIntersection(aRect2);
1094 maShapeRanges[nRangeId].maPixelRect = aClippedPixelPaintRect;
1095 maShapeRanges[nRangeId].maMapMode = aMapMode;
1096 ScIAccessibleViewForwarder aViewForwarder(mpViewShell, mpAccDoc, aMapMode);
1097 maShapeRanges[nRangeId].maViewForwarder = aViewForwarder;
1098 const size_t nCount(pPage->GetObjCount());
1099 for (size_t i = 0; i < nCount; ++i)
1101 SdrObject* pObj = pPage->GetObj(i);
1102 if (pObj)
1104 uno::Reference< drawing::XShape > xShape(pObj->getUnoShape(), uno::UNO_QUERY);
1105 if (xShape.is())
1107 Rectangle aRect(pWin->LogicToPixel(VCLPoint(xShape->getPosition()), aMapMode), pWin->LogicToPixel(VCLSize(xShape->getSize()), aMapMode));
1108 if(!aClippedPixelPaintRect.GetIntersection(aRect).IsEmpty())
1110 ScShapeChild aShape;
1111 aShape.mxShape = xShape;
1112 aShape.mnRangeId = nRangeId;
1113 switch (pObj->GetLayer())
1115 case SC_LAYER_INTERN:
1116 case SC_LAYER_FRONT:
1118 maShapeRanges[nRangeId].maForeShapes.push_back(aShape);
1119 bForeAdded = true;
1121 break;
1122 case SC_LAYER_BACK:
1124 maShapeRanges[nRangeId].maBackShapes.push_back(aShape);
1125 bBackAdded = true;
1127 break;
1128 case SC_LAYER_CONTROLS:
1130 maShapeRanges[nRangeId].maControls.push_back(aShape);
1131 bControlAdded = true;
1133 break;
1134 default:
1136 OSL_FAIL("I don't know this layer.");
1138 break;
1144 if (bForeAdded)
1145 std::sort(maShapeRanges[nRangeId].maForeShapes.begin(), maShapeRanges[nRangeId].maForeShapes.end(),ScShapeChildLess());
1146 if (bBackAdded)
1147 std::sort(maShapeRanges[nRangeId].maBackShapes.begin(), maShapeRanges[nRangeId].maBackShapes.end(),ScShapeChildLess());
1148 if (bControlAdded)
1149 std::sort(maShapeRanges[nRangeId].maControls.begin(), maShapeRanges[nRangeId].maControls.end(),ScShapeChildLess());
1153 SdrPage* ScShapeChildren::GetDrawPage() const
1155 SCTAB nTab( mpViewShell->GetLocationData().GetPrintTab() );
1156 SdrPage* pDrawPage = NULL;
1157 ScDocument& rDoc = mpViewShell->GetDocument();
1158 if (rDoc.GetDrawLayer())
1160 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
1161 if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab))
1162 pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(static_cast<sal_Int16>(nTab)));
1164 return pDrawPage;
1167 struct ScPagePreviewCountData
1169 // order is background shapes, header, table or notes, footer, foreground shapes, controls
1171 Rectangle aVisRect;
1172 long nBackShapes;
1173 long nHeaders;
1174 long nTables;
1175 long nNoteParagraphs;
1176 long nFooters;
1177 long nForeShapes;
1178 long nControls;
1180 ScPagePreviewCountData( const ScPreviewLocationData& rData, vcl::Window* pSizeWindow,
1181 ScNotesChildren* pNotesChildren, ScShapeChildren* pShapeChildren );
1183 long GetTotal() const
1185 return nBackShapes + nHeaders + nTables + nNoteParagraphs + nFooters + nForeShapes + nControls;
1189 ScPagePreviewCountData::ScPagePreviewCountData( const ScPreviewLocationData& rData,
1190 vcl::Window* pSizeWindow, ScNotesChildren* pNotesChildren,
1191 ScShapeChildren* pShapeChildren) :
1192 nBackShapes( 0 ),
1193 nHeaders( 0 ),
1194 nTables( 0 ),
1195 nNoteParagraphs( 0 ),
1196 nFooters( 0 ),
1197 nForeShapes( 0 ),
1198 nControls( 0 )
1200 Size aOutputSize;
1201 if ( pSizeWindow )
1202 aOutputSize = pSizeWindow->GetOutputSizePixel();
1203 Point aPoint;
1204 aVisRect = Rectangle( aPoint, aOutputSize );
1206 Rectangle aObjRect;
1208 if ( rData.GetHeaderPosition( aObjRect ) && aObjRect.IsOver( aVisRect ) )
1209 nHeaders = 1;
1211 if ( rData.GetFooterPosition( aObjRect ) && aObjRect.IsOver( aVisRect ) )
1212 nFooters = 1;
1214 if ( rData.HasCellsInRange( aVisRect ) )
1215 nTables = 1;
1217 //! shapes...
1218 nBackShapes = pShapeChildren->GetBackShapeCount();
1219 nForeShapes = pShapeChildren->GetForeShapeCount();
1220 nControls = pShapeChildren->GetControlCount();
1222 // there are only notes if there is no table
1223 if (nTables == 0)
1224 nNoteParagraphs = pNotesChildren->GetChildrenCount();
1227 //===== internal ========================================================
1229 ScAccessibleDocumentPagePreview::ScAccessibleDocumentPagePreview(
1230 const uno::Reference<XAccessible>& rxParent, ScPreviewShell* pViewShell ) :
1231 ScAccessibleDocumentBase(rxParent),
1232 mpViewShell(pViewShell),
1233 mpNotesChildren(NULL),
1234 mpShapeChildren(NULL),
1235 mpTable(NULL),
1236 mpHeader(NULL),
1237 mpFooter(NULL)
1239 if (pViewShell)
1240 pViewShell->AddAccessibilityObject(*this);
1244 ScAccessibleDocumentPagePreview::~ScAccessibleDocumentPagePreview()
1246 if (!ScAccessibleDocumentBase::IsDefunc() && !rBHelper.bInDispose)
1248 // increment refcount to prevent double call off dtor
1249 osl_atomic_increment( &m_refCount );
1250 // call dispose to inform object which have a weak reference to this object
1251 dispose();
1255 void SAL_CALL ScAccessibleDocumentPagePreview::disposing()
1257 SolarMutexGuard aGuard;
1258 if (mpTable)
1260 mpTable->release();
1261 mpTable = NULL;
1263 if (mpHeader)
1265 mpHeader->release();
1266 mpHeader = NULL;
1268 if (mpFooter)
1270 mpFooter->release();
1271 mpFooter = NULL;
1274 if (mpViewShell)
1276 mpViewShell->RemoveAccessibilityObject(*this);
1277 mpViewShell = NULL;
1280 // no need to Dispose the AccessibleTextHelper,
1281 // as long as mpNotesChildren are destructed here
1282 if (mpNotesChildren)
1283 DELETEZ(mpNotesChildren);
1285 if (mpShapeChildren)
1286 DELETEZ(mpShapeChildren);
1288 ScAccessibleDocumentBase::disposing();
1291 //===== SfxListener =====================================================
1293 void ScAccessibleDocumentPagePreview::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
1295 const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint);
1296 if (pSimpleHint)
1298 // only notify if child exist, otherwise it is not necessary
1299 if (pSimpleHint->GetId() == SC_HINT_DATACHANGED)
1301 if (mpTable) // if there is no table there is nothing to notify, because no one recongnizes the change
1304 uno::Reference<XAccessible> xAcc = mpTable;
1305 AccessibleEventObject aEvent;
1306 aEvent.EventId = AccessibleEventId::CHILD;
1307 aEvent.Source = uno::Reference< XAccessibleContext >(this);
1308 aEvent.OldValue <<= xAcc;
1309 CommitChange(aEvent);
1312 mpTable->dispose();
1313 mpTable->release();
1314 mpTable = NULL;
1317 Size aOutputSize;
1318 vcl::Window* pSizeWindow = mpViewShell->GetWindow();
1319 if ( pSizeWindow )
1320 aOutputSize = pSizeWindow->GetOutputSizePixel();
1321 Point aPoint;
1322 Rectangle aVisRect( aPoint, aOutputSize );
1323 GetNotesChildren()->DataChanged(aVisRect);
1325 GetShapeChildren()->DataChanged();
1327 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
1328 ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1330 if (aCount.nTables > 0)
1332 //! order is background shapes, header, table or notes, footer, foreground shapes, controls
1333 sal_Int32 nIndex (aCount.nBackShapes + aCount.nHeaders);
1335 mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex );
1336 mpTable->acquire();
1337 mpTable->Init();
1340 uno::Reference<XAccessible> xAcc = mpTable;
1341 AccessibleEventObject aEvent;
1342 aEvent.EventId = AccessibleEventId::CHILD;
1343 aEvent.Source = uno::Reference< XAccessibleContext >(this);
1344 aEvent.NewValue <<= xAcc;
1345 CommitChange(aEvent);
1349 else if (pSimpleHint->GetId() == SC_HINT_ACC_MAKEDRAWLAYER)
1351 GetShapeChildren()->SetDrawBroadcaster();
1353 else if (pSimpleHint->GetId() == SC_HINT_ACC_VISAREACHANGED)
1355 Size aOutputSize;
1356 vcl::Window* pSizeWindow = mpViewShell->GetWindow();
1357 if ( pSizeWindow )
1358 aOutputSize = pSizeWindow->GetOutputSizePixel();
1359 Point aPoint;
1360 Rectangle aVisRect( aPoint, aOutputSize );
1361 GetNotesChildren()->DataChanged(aVisRect);
1363 GetShapeChildren()->VisAreaChanged();
1365 AccessibleEventObject aEvent;
1366 aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
1367 aEvent.Source = uno::Reference< XAccessibleContext >(this);
1368 CommitChange(aEvent);
1371 else if ( dynamic_cast<const ScAccWinFocusLostHint*>(&rHint) )
1373 CommitFocusLost();
1375 else if ( dynamic_cast<const ScAccWinFocusGotHint*>(&rHint) )
1377 CommitFocusGained();
1379 ScAccessibleDocumentBase::Notify(rBC, rHint);
1382 //===== XAccessibleComponent ============================================
1384 uno::Reference< XAccessible > SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleAtPoint( const awt::Point& rPoint )
1385 throw (uno::RuntimeException, std::exception)
1387 uno::Reference<XAccessible> xAccessible;
1388 if (containsPoint(rPoint))
1390 SolarMutexGuard aGuard;
1391 IsObjectValid();
1393 if ( mpViewShell )
1395 xAccessible = GetShapeChildren()->GetForegroundShapeAt(rPoint);
1396 if (!xAccessible.is())
1398 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
1399 ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1401 if ( !mpTable && (aCount.nTables > 0) )
1403 //! order is background shapes, header, table or notes, footer, foreground shapes, controls
1404 sal_Int32 nIndex (aCount.nBackShapes + aCount.nHeaders);
1406 mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex );
1407 mpTable->acquire();
1408 mpTable->Init();
1410 if (mpTable && VCLRectangle(mpTable->getBounds()).IsInside(VCLPoint(rPoint)))
1411 xAccessible = mpTable;
1413 if (!xAccessible.is())
1414 xAccessible = GetNotesChildren()->GetAt(rPoint);
1415 if (!xAccessible.is())
1417 if (!mpHeader || !mpFooter)
1419 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
1420 ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1422 if (!mpHeader)
1424 mpHeader = new ScAccessiblePageHeader( this, mpViewShell, true, aCount.nBackShapes + aCount.nHeaders - 1);
1425 mpHeader->acquire();
1427 if (!mpFooter)
1429 mpFooter = new ScAccessiblePageHeader( this, mpViewShell, false, aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters - 1 );
1430 mpFooter->acquire();
1434 Point aPoint(VCLPoint(rPoint));
1436 if (VCLRectangle(mpHeader->getBounds()).IsInside(aPoint))
1437 xAccessible = mpHeader;
1438 else if (VCLRectangle(mpFooter->getBounds()).IsInside(aPoint))
1439 xAccessible = mpFooter;
1441 if (!xAccessible.is())
1442 xAccessible = GetShapeChildren()->GetBackgroundShapeAt(rPoint);
1446 return xAccessible;
1449 void SAL_CALL ScAccessibleDocumentPagePreview::grabFocus() throw (uno::RuntimeException, std::exception)
1451 SolarMutexGuard aGuard;
1452 IsObjectValid();
1453 if (getAccessibleParent().is())
1455 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
1456 if (xAccessibleComponent.is())
1458 // just grab the focus for the window
1459 xAccessibleComponent->grabFocus();
1464 //===== XAccessibleContext ==============================================
1466 sal_Int32 SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleChildCount()
1467 throw (uno::RuntimeException, std::exception)
1469 SolarMutexGuard aGuard;
1470 IsObjectValid();
1472 long nRet = 0;
1473 if ( mpViewShell )
1475 ScPagePreviewCountData aCount( mpViewShell->GetLocationData(), mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1476 nRet = aCount.GetTotal();
1479 return nRet;
1482 uno::Reference<XAccessible> SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleChild(sal_Int32 nIndex)
1483 throw (uno::RuntimeException, lang::IndexOutOfBoundsException, std::exception)
1485 SolarMutexGuard aGuard;
1486 IsObjectValid();
1487 uno::Reference<XAccessible> xAccessible;
1489 if ( mpViewShell )
1491 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
1492 ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1494 if ( nIndex < aCount.nBackShapes )
1496 xAccessible = GetShapeChildren()->GetBackShape(nIndex);
1498 else if ( nIndex < aCount.nBackShapes + aCount.nHeaders )
1500 if ( !mpHeader )
1502 mpHeader = new ScAccessiblePageHeader( this, mpViewShell, true, nIndex );
1503 mpHeader->acquire();
1506 xAccessible = mpHeader;
1508 else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nTables )
1510 if ( !mpTable )
1512 mpTable = new ScAccessiblePreviewTable( this, mpViewShell, nIndex );
1513 mpTable->acquire();
1514 mpTable->Init();
1516 xAccessible = mpTable;
1518 else if ( nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nNoteParagraphs )
1520 xAccessible = GetNotesChildren()->GetChild(nIndex - aCount.nBackShapes - aCount.nHeaders);
1522 else if ( (nIndex < aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters) )
1524 if ( !mpFooter )
1526 mpFooter = new ScAccessiblePageHeader( this, mpViewShell, false, nIndex );
1527 mpFooter->acquire();
1529 xAccessible = mpFooter;
1531 else
1533 sal_Int32 nIdx(nIndex - (aCount.nBackShapes + aCount.nHeaders + aCount.nTables + aCount.nNoteParagraphs + aCount.nFooters));
1534 if (nIdx < aCount.nForeShapes)
1535 xAccessible = GetShapeChildren()->GetForeShape(nIdx);
1536 else
1537 xAccessible = GetShapeChildren()->GetControl(nIdx - aCount.nForeShapes);
1541 if ( !xAccessible.is() )
1542 throw lang::IndexOutOfBoundsException();
1544 return xAccessible;
1547 /// Return the set of current states.
1548 uno::Reference<XAccessibleStateSet> SAL_CALL ScAccessibleDocumentPagePreview::getAccessibleStateSet()
1549 throw (uno::RuntimeException, std::exception)
1551 SolarMutexGuard aGuard;
1552 uno::Reference<XAccessibleStateSet> xParentStates;
1553 if (getAccessibleParent().is())
1555 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1556 xParentStates = xParentContext->getAccessibleStateSet();
1558 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
1559 if (IsDefunc(xParentStates))
1560 pStateSet->AddState(AccessibleStateType::DEFUNC);
1561 else
1563 // never editable
1564 pStateSet->AddState(AccessibleStateType::ENABLED);
1565 pStateSet->AddState(AccessibleStateType::OPAQUE);
1566 if (isShowing())
1567 pStateSet->AddState(AccessibleStateType::SHOWING);
1568 if (isVisible())
1569 pStateSet->AddState(AccessibleStateType::VISIBLE);
1571 return pStateSet;
1574 //===== XServiceInfo ====================================================
1576 OUString SAL_CALL ScAccessibleDocumentPagePreview::getImplementationName()
1577 throw (uno::RuntimeException, std::exception)
1579 return OUString("ScAccessibleDocumentPagePreview");
1582 uno::Sequence< OUString> SAL_CALL ScAccessibleDocumentPagePreview::getSupportedServiceNames()
1583 throw (uno::RuntimeException, std::exception)
1585 uno::Sequence< OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
1586 sal_Int32 nOldSize(aSequence.getLength());
1587 aSequence.realloc(nOldSize + 1);
1589 aSequence[nOldSize] = "com.sun.star.AccessibleSpreadsheetPageView";
1591 return aSequence;
1594 //===== XTypeProvider =======================================================
1596 uno::Sequence<sal_Int8> SAL_CALL
1597 ScAccessibleDocumentPagePreview::getImplementationId()
1598 throw (uno::RuntimeException, std::exception)
1600 return css::uno::Sequence<sal_Int8>();
1603 //===== internal ========================================================
1605 OUString SAL_CALL ScAccessibleDocumentPagePreview::createAccessibleDescription()
1606 throw (uno::RuntimeException)
1608 OUString sDescription = OUString(ScResId(STR_ACC_PREVIEWDOC_DESCR));
1609 return sDescription;
1612 OUString SAL_CALL ScAccessibleDocumentPagePreview::createAccessibleName()
1613 throw (uno::RuntimeException, std::exception)
1615 OUString sName = OUString(ScResId(STR_ACC_PREVIEWDOC_NAME));
1616 return sName;
1619 Rectangle ScAccessibleDocumentPagePreview::GetBoundingBoxOnScreen() const throw (uno::RuntimeException, std::exception)
1621 Rectangle aRect;
1622 if (mpViewShell)
1624 vcl::Window* pWindow = mpViewShell->GetWindow();
1625 if (pWindow)
1626 aRect = pWindow->GetWindowExtentsRelative(NULL);
1628 return aRect;
1631 Rectangle ScAccessibleDocumentPagePreview::GetBoundingBox() const throw (uno::RuntimeException, std::exception)
1633 Rectangle aRect;
1634 if (mpViewShell)
1636 vcl::Window* pWindow = mpViewShell->GetWindow();
1637 if (pWindow)
1638 aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
1640 return aRect;
1643 bool ScAccessibleDocumentPagePreview::IsDefunc(
1644 const uno::Reference<XAccessibleStateSet>& rxParentStates)
1646 return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() ||
1647 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
1650 ScNotesChildren* ScAccessibleDocumentPagePreview::GetNotesChildren()
1652 if (!mpNotesChildren && mpViewShell)
1654 mpNotesChildren = new ScNotesChildren(mpViewShell, this);
1656 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
1657 ScPagePreviewCountData aCount( rData, mpViewShell->GetWindow(), GetNotesChildren(), GetShapeChildren() );
1659 //! order is background shapes, header, table or notes, footer, foreground shapes, controls
1660 mpNotesChildren->Init(aCount.aVisRect, aCount.nBackShapes + aCount.nHeaders);
1662 return mpNotesChildren;
1665 ScShapeChildren* ScAccessibleDocumentPagePreview::GetShapeChildren()
1667 if (!mpShapeChildren && mpViewShell)
1669 mpShapeChildren = new ScShapeChildren(mpViewShell, this);
1670 mpShapeChildren->Init();
1673 return mpShapeChildren;
1676 OUString ScAccessibleDocumentPagePreview::getAccessibleName()
1677 throw (::com::sun::star::uno::RuntimeException, std::exception)
1679 SolarMutexGuard g;
1681 OUString aName = ScResId(STR_ACC_DOC_SPREADSHEET);
1682 ScDocument& rScDoc = mpViewShell->GetDocument();
1684 SfxObjectShell* pObjSh = rScDoc.GetDocumentShell();
1685 if (!pObjSh)
1686 return aName;
1688 OUString aFileName;
1689 SfxMedium* pMed = pObjSh->GetMedium();
1690 if (pMed)
1691 aFileName = pMed->GetName();
1693 if (aFileName.isEmpty())
1694 aFileName = pObjSh->GetTitle(SFX_TITLE_APINAME);
1696 if (!aFileName.isEmpty())
1698 aName = aFileName + " - " + aName;
1699 aName += ScResId(STR_ACC_DOC_PREVIEW_SUFFIX);
1703 return aName;
1706 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */