xref: /trunk/main/sc/source/ui/Accessibility/AccessiblePreviewCell.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 #include "scitems.hxx"
31 #include <editeng/eeitem.hxx>
32 #include <tools/gen.hxx>
33 #include "AccessibleText.hxx"
34 #include "editsrc.hxx"
35 #include "AccessiblePreviewCell.hxx"
36 #include "AccessibilityHints.hxx"
37 #include "prevwsh.hxx"
38 #include "unoguard.hxx"
39 #include "prevloc.hxx"
40 #include "document.hxx"
41 #include <svx/AccessibleTextHelper.hxx>
42 #include <unotools/accessiblestatesethelper.hxx>
43 #include <editeng/brshitem.hxx>
44 #include <vcl/window.hxx>
45 #include <toolkit/helper/convert.hxx>
46 
47 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
48 
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::accessibility;
51 
52 //=====  internal  ============================================================
53 
54 ScAccessiblePreviewCell::ScAccessiblePreviewCell( const ::com::sun::star::uno::Reference<
55                                 ::com::sun::star::accessibility::XAccessible>& rxParent,
56                             ScPreviewShell* pViewShell, /* const */ ScAddress& rCellAddress,
57                             sal_Int32 nIndex ) :
58     ScAccessibleCellBase( rxParent, ( pViewShell ? pViewShell->GetDocument() : NULL ), rCellAddress, nIndex ),
59     mpViewShell( pViewShell ),
60     mpTextHelper(NULL)
61 {
62     if (mpViewShell)
63         mpViewShell->AddAccessibilityObject(*this);
64 }
65 
66 ScAccessiblePreviewCell::~ScAccessiblePreviewCell()
67 {
68     if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
69     {
70         // increment refcount to prevent double call off dtor
71         osl_incrementInterlockedCount( &m_refCount );
72         // call dispose to inform object wich have a weak reference to this object
73         dispose();
74     }
75 }
76 
77 void SAL_CALL ScAccessiblePreviewCell::disposing()
78 {
79     ScUnoGuard aGuard;
80     if (mpViewShell)
81     {
82         mpViewShell->RemoveAccessibilityObject(*this);
83         mpViewShell = NULL;
84     }
85 
86     if (mpTextHelper)
87         DELETEZ(mpTextHelper);
88 
89     ScAccessibleCellBase::disposing();
90 }
91 
92 void ScAccessiblePreviewCell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
93 {
94     if (rHint.ISA( SfxSimpleHint ))
95     {
96         const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
97         if (rRef.GetId() == SC_HINT_ACC_VISAREACHANGED)
98         {
99             if (mpTextHelper)
100                 mpTextHelper->UpdateChildren();
101         }
102     }
103 
104     ScAccessibleContextBase::Notify(rBC, rHint);
105 }
106 
107 //=====  XAccessibleComponent  ============================================
108 
109 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewCell::getAccessibleAtPoint( const awt::Point& rPoint )
110                                 throw (uno::RuntimeException)
111 {
112     uno::Reference<XAccessible> xRet;
113     if (containsPoint(rPoint))
114     {
115         ScUnoGuard aGuard;
116         IsObjectValid();
117 
118         if(!mpTextHelper)
119             CreateTextHelper();
120 
121         xRet = mpTextHelper->GetAt(rPoint);
122     }
123 
124     return xRet;
125 }
126 
127 void SAL_CALL ScAccessiblePreviewCell::grabFocus() throw (uno::RuntimeException)
128 {
129     ScUnoGuard aGuard;
130     IsObjectValid();
131     if (getAccessibleParent().is())
132     {
133         uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
134         if (xAccessibleComponent.is())
135             xAccessibleComponent->grabFocus();
136     }
137 }
138 
139 //=====  XAccessibleContext  ==============================================
140 
141 sal_Int32 SAL_CALL ScAccessiblePreviewCell::getAccessibleChildCount() throw(uno::RuntimeException)
142 {
143     ScUnoGuard aGuard;
144     IsObjectValid();
145     if (!mpTextHelper)
146         CreateTextHelper();
147     return mpTextHelper->GetChildCount();
148 }
149 
150 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewCell::getAccessibleChild(sal_Int32 nIndex)
151                             throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
152 {
153     ScUnoGuard aGuard;
154     IsObjectValid();
155     if (!mpTextHelper)
156         CreateTextHelper();
157     return mpTextHelper->GetChild(nIndex);
158 }
159 
160 uno::Reference<XAccessibleStateSet> SAL_CALL ScAccessiblePreviewCell::getAccessibleStateSet()
161                             throw(uno::RuntimeException)
162 {
163     ScUnoGuard aGuard;
164 
165     uno::Reference<XAccessibleStateSet> xParentStates;
166     if (getAccessibleParent().is())
167     {
168         uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
169         xParentStates = xParentContext->getAccessibleStateSet();
170     }
171     utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
172     if (IsDefunc(xParentStates))
173         pStateSet->AddState(AccessibleStateType::DEFUNC);
174     else
175     {
176         pStateSet->AddState(AccessibleStateType::ENABLED);
177         pStateSet->AddState(AccessibleStateType::MULTI_LINE);
178         if (IsOpaque(xParentStates))
179             pStateSet->AddState(AccessibleStateType::OPAQUE);
180         if (isShowing())
181             pStateSet->AddState(AccessibleStateType::SHOWING);
182         pStateSet->AddState(AccessibleStateType::TRANSIENT);
183         if (isVisible())
184             pStateSet->AddState(AccessibleStateType::VISIBLE);
185         // #111635# MANAGES_DESCENDANTS (for paragraphs)
186         pStateSet->AddState(AccessibleStateType::MANAGES_DESCENDANTS);
187     }
188     return pStateSet;
189 }
190 
191 //=====  XServiceInfo  ====================================================
192 
193 rtl::OUString SAL_CALL ScAccessiblePreviewCell::getImplementationName() throw(uno::RuntimeException)
194 {
195     return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ScAccessiblePreviewCell"));
196 }
197 
198 uno::Sequence<rtl::OUString> SAL_CALL ScAccessiblePreviewCell::getSupportedServiceNames()
199                                                     throw(uno::RuntimeException)
200 {
201     uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
202     sal_Int32 nOldSize(aSequence.getLength());
203     aSequence.realloc(nOldSize + 1);
204     ::rtl::OUString* pNames = aSequence.getArray();
205 
206     pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.table.AccessibleCellView"));
207 
208     return aSequence;
209 }
210 
211 //=====  XTypeProvider  =======================================================
212 
213 uno::Sequence<sal_Int8> SAL_CALL
214     ScAccessiblePreviewCell::getImplementationId(void)
215     throw (uno::RuntimeException)
216 {
217     ScUnoGuard aGuard;
218     IsObjectValid();
219     static uno::Sequence<sal_Int8> aId;
220     if (aId.getLength() == 0)
221     {
222         aId.realloc (16);
223         rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
224     }
225     return aId;
226 }
227 
228 //====  internal  =========================================================
229 
230 Rectangle ScAccessiblePreviewCell::GetBoundingBoxOnScreen() const throw (uno::RuntimeException)
231 {
232     Rectangle aCellRect;
233     if (mpViewShell)
234     {
235         mpViewShell->GetLocationData().GetCellPosition( maCellAddress, aCellRect );
236         Window* pWindow = mpViewShell->GetWindow();
237         if (pWindow)
238         {
239             Rectangle aRect = pWindow->GetWindowExtentsRelative(NULL);
240             aCellRect.setX(aCellRect.getX() + aRect.getX());
241             aCellRect.setY(aCellRect.getY() + aRect.getY());
242         }
243     }
244     return aCellRect;
245 }
246 
247 Rectangle ScAccessiblePreviewCell::GetBoundingBox() const throw (uno::RuntimeException)
248 {
249     Rectangle aCellRect;
250     if (mpViewShell)
251     {
252         mpViewShell->GetLocationData().GetCellPosition( maCellAddress, aCellRect );
253         uno::Reference<XAccessible> xAccParent = const_cast<ScAccessiblePreviewCell*>(this)->getAccessibleParent();
254         if (xAccParent.is())
255         {
256             uno::Reference<XAccessibleContext> xAccParentContext = xAccParent->getAccessibleContext();
257             uno::Reference<XAccessibleComponent> xAccParentComp (xAccParentContext, uno::UNO_QUERY);
258             if (xAccParentComp.is())
259             {
260                 Rectangle aParentRect (VCLRectangle(xAccParentComp->getBounds()));
261                 aCellRect.setX(aCellRect.getX() - aParentRect.getX());
262                 aCellRect.setY(aCellRect.getY() - aParentRect.getY());
263             }
264         }
265     }
266     return aCellRect;
267 }
268 
269 sal_Bool ScAccessiblePreviewCell::IsDefunc(
270     const uno::Reference<XAccessibleStateSet>& rxParentStates)
271 {
272     return ScAccessibleContextBase::IsDefunc() || (mpDoc == NULL) || (mpViewShell == NULL) || !getAccessibleParent().is() ||
273          (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
274 }
275 
276 sal_Bool ScAccessiblePreviewCell::IsEditable(
277     const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
278 {
279     return sal_False;
280 }
281 
282 sal_Bool ScAccessiblePreviewCell::IsOpaque(
283     const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
284 {
285     // test whether there is a background color
286     //! could be moved to ScAccessibleCellBase
287 
288     sal_Bool bOpaque(sal_True);
289     if (mpDoc)
290     {
291         const SvxBrushItem* pItem = (const SvxBrushItem*)mpDoc->GetAttr(
292             maCellAddress.Col(), maCellAddress.Row(), maCellAddress.Tab(), ATTR_BACKGROUND);
293         if (pItem)
294             bOpaque = pItem->GetColor() != COL_TRANSPARENT;
295     }
296     return bOpaque;
297 }
298 
299 void ScAccessiblePreviewCell::CreateTextHelper()
300 {
301     if (!mpTextHelper)
302     {
303         ::std::auto_ptr < ScAccessibleTextData > pAccessiblePreviewCellTextData
304             (new ScAccessiblePreviewCellTextData(mpViewShell, maCellAddress));
305         ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessiblePreviewCellTextData));
306 
307         mpTextHelper = new ::accessibility::AccessibleTextHelper( pEditSource );
308         mpTextHelper->SetEventSource( this );
309 
310         // #111635# paragraphs in preview are transient
311         ::accessibility::AccessibleTextHelper::VectorOfStates aChildStates;
312         aChildStates.push_back( AccessibleStateType::TRANSIENT );
313         mpTextHelper->SetAdditionalChildStates( aChildStates );
314     }
315 }
316 
317