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