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 <svx/AccessibleTextHelper.hxx>
32 #include "AccessiblePreviewHeaderCell.hxx"
33 #include "AccessibilityHints.hxx"
34 #include "prevwsh.hxx"
35 #include "unoguard.hxx"
36 #include "miscuno.hxx"
37 #include "prevloc.hxx"
38 #include "scresid.hxx"
39 #ifndef SC_SC_HRC
40 #include "sc.hrc"
41 #endif
42
43 #include <com/sun/star/accessibility/AccessibleRole.hpp>
44 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
45
46 #include <vcl/window.hxx>
47 #include <svl/smplhint.hxx>
48 #include <unotools/accessiblestatesethelper.hxx>
49 #include <comphelper/sequence.hxx>
50 #include <toolkit/helper/convert.hxx>
51
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::accessibility;
54
55 //===== internal ============================================================
56
ScAccessiblePreviewHeaderCell(const::com::sun::star::uno::Reference<::com::sun::star::accessibility::XAccessible> & rxParent,ScPreviewShell * pViewShell,const ScAddress & rCellPos,sal_Bool bIsColHdr,sal_Bool bIsRowHdr,sal_Int32 nIndex)57 ScAccessiblePreviewHeaderCell::ScAccessiblePreviewHeaderCell( const ::com::sun::star::uno::Reference<
58 ::com::sun::star::accessibility::XAccessible>& rxParent,
59 ScPreviewShell* pViewShell,
60 const ScAddress& rCellPos, sal_Bool bIsColHdr, sal_Bool bIsRowHdr,
61 sal_Int32 nIndex ) :
62 ScAccessibleContextBase( rxParent, AccessibleRole::TABLE_CELL ),
63 mpViewShell( pViewShell ),
64 mpTextHelper( NULL ),
65 mnIndex( nIndex ),
66 maCellPos( rCellPos ),
67 mbColumnHeader( bIsColHdr ),
68 mbRowHeader( bIsRowHdr ),
69 mpTableInfo( NULL )
70 {
71 if (mpViewShell)
72 mpViewShell->AddAccessibilityObject(*this);
73 }
74
~ScAccessiblePreviewHeaderCell()75 ScAccessiblePreviewHeaderCell::~ScAccessiblePreviewHeaderCell()
76 {
77 if (mpViewShell)
78 mpViewShell->RemoveAccessibilityObject(*this);
79 }
80
disposing()81 void SAL_CALL ScAccessiblePreviewHeaderCell::disposing()
82 {
83 ScUnoGuard aGuard;
84 if (mpViewShell)
85 {
86 mpViewShell->RemoveAccessibilityObject(*this);
87 mpViewShell = NULL;
88 }
89
90 if (mpTableInfo)
91 DELETEZ (mpTableInfo);
92
93 ScAccessibleContextBase::disposing();
94 }
95
96 //===== SfxListener =====================================================
97
Notify(SfxBroadcaster & rBC,const SfxHint & rHint)98 void ScAccessiblePreviewHeaderCell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
99 {
100 if (rHint.ISA( SfxSimpleHint ))
101 {
102 const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
103 sal_uLong nId = rRef.GetId();
104 if (nId == SC_HINT_ACC_VISAREACHANGED)
105 {
106 if (mpTextHelper)
107 mpTextHelper->UpdateChildren();
108 }
109 else if ( nId == SFX_HINT_DATACHANGED )
110 {
111 // column / row layout may change with any document change,
112 // so it must be invalidated
113 DELETEZ( mpTableInfo );
114 }
115 }
116
117 ScAccessibleContextBase::Notify(rBC, rHint);
118 }
119
120 //===== XInterface =====================================================
121
queryInterface(uno::Type const & rType)122 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::queryInterface( uno::Type const & rType )
123 {
124 uno::Any aAny (ScAccessiblePreviewHeaderCellImpl::queryInterface(rType));
125 return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType);
126 }
127
acquire()128 void SAL_CALL ScAccessiblePreviewHeaderCell::acquire()
129 throw ()
130 {
131 ScAccessibleContextBase::acquire();
132 }
133
release()134 void SAL_CALL ScAccessiblePreviewHeaderCell::release()
135 throw ()
136 {
137 ScAccessibleContextBase::release();
138 }
139
140 //===== XAccessibleValue ================================================
141
getCurrentValue()142 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getCurrentValue()
143 {
144 ScUnoGuard aGuard;
145 IsObjectValid();
146
147 double fValue(0.0);
148 if (mbColumnHeader)
149 fValue = maCellPos.Col();
150 else
151 fValue = maCellPos.Row();
152
153 uno::Any aAny;
154 aAny <<= fValue;
155 return aAny;
156 }
157
setCurrentValue(const uno::Any &)158 sal_Bool SAL_CALL ScAccessiblePreviewHeaderCell::setCurrentValue( const uno::Any& /* aNumber */ )
159 {
160 // it is not possible to set a value
161 return sal_False;
162 }
163
getMaximumValue()164 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getMaximumValue()
165 {
166 ScUnoGuard aGuard;
167 IsObjectValid();
168
169 double fValue(0.0);
170 if (mbColumnHeader)
171 fValue = MAXCOL;
172 else
173 fValue = MAXROW;
174 uno::Any aAny;
175 aAny <<= fValue;
176 return aAny;
177 }
178
getMinimumValue()179 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getMinimumValue()
180 {
181 double fValue(0.0);
182 uno::Any aAny;
183 aAny <<= fValue;
184 return aAny;
185 }
186
187 //===== XAccessibleComponent ============================================
188
getAccessibleAtPoint(const awt::Point & rPoint)189 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleAtPoint( const awt::Point& rPoint )
190 {
191 uno::Reference<XAccessible> xRet;
192 if (containsPoint(rPoint))
193 {
194 ScUnoGuard aGuard;
195 IsObjectValid();
196
197 if(!mpTextHelper)
198 CreateTextHelper();
199
200 xRet = mpTextHelper->GetAt(rPoint);
201 }
202
203 return xRet;
204 }
205
grabFocus()206 void SAL_CALL ScAccessiblePreviewHeaderCell::grabFocus()
207 {
208 ScUnoGuard aGuard;
209 IsObjectValid();
210 if (getAccessibleParent().is())
211 {
212 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
213 if (xAccessibleComponent.is())
214 xAccessibleComponent->grabFocus();
215 }
216 }
217
218 //===== XAccessibleContext ==============================================
219
getAccessibleChildCount()220 sal_Int32 SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleChildCount()
221 {
222 ScUnoGuard aGuard;
223 IsObjectValid();
224 if (!mpTextHelper)
225 CreateTextHelper();
226 return mpTextHelper->GetChildCount();
227 }
228
getAccessibleChild(sal_Int32 nIndex)229 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleChild(sal_Int32 nIndex)
230 {
231 ScUnoGuard aGuard;
232 IsObjectValid();
233 if (!mpTextHelper)
234 CreateTextHelper();
235 return mpTextHelper->GetChild(nIndex);
236 }
237
getAccessibleIndexInParent()238 sal_Int32 SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleIndexInParent()
239 {
240 return mnIndex;
241 }
242
getAccessibleStateSet()243 uno::Reference<XAccessibleStateSet> SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleStateSet()
244 {
245 ScUnoGuard aGuard;
246
247 uno::Reference<XAccessibleStateSet> xParentStates;
248 if (getAccessibleParent().is())
249 {
250 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
251 xParentStates = xParentContext->getAccessibleStateSet();
252 }
253 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
254 if (IsDefunc(xParentStates))
255 pStateSet->AddState(AccessibleStateType::DEFUNC);
256 else
257 {
258 pStateSet->AddState(AccessibleStateType::ENABLED);
259 pStateSet->AddState(AccessibleStateType::MULTI_LINE);
260 if (isShowing())
261 pStateSet->AddState(AccessibleStateType::SHOWING);
262 pStateSet->AddState(AccessibleStateType::TRANSIENT);
263 if (isVisible())
264 pStateSet->AddState(AccessibleStateType::VISIBLE);
265 }
266 return pStateSet;
267 }
268
269 //===== XServiceInfo ====================================================
270
getImplementationName()271 rtl::OUString SAL_CALL ScAccessiblePreviewHeaderCell::getImplementationName()
272 {
273 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ScAccessiblePreviewHeaderCell"));
274 }
275
getSupportedServiceNames()276 uno::Sequence<rtl::OUString> SAL_CALL ScAccessiblePreviewHeaderCell::getSupportedServiceNames()
277 {
278 uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
279 sal_Int32 nOldSize(aSequence.getLength());
280 aSequence.realloc(nOldSize + 1);
281 ::rtl::OUString* pNames = aSequence.getArray();
282
283 pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.table.AccessibleCellView"));
284
285 return aSequence;
286 }
287
288 //===== XTypeProvider =======================================================
289
getTypes()290 uno::Sequence< uno::Type > SAL_CALL ScAccessiblePreviewHeaderCell::getTypes()
291 {
292 return comphelper::concatSequences(ScAccessiblePreviewHeaderCellImpl::getTypes(), ScAccessibleContextBase::getTypes());
293 }
294
295 uno::Sequence<sal_Int8> SAL_CALL
getImplementationId(void)296 ScAccessiblePreviewHeaderCell::getImplementationId(void)
297 {
298 ScUnoGuard aGuard;
299 IsObjectValid();
300 static uno::Sequence<sal_Int8> aId;
301 if (aId.getLength() == 0)
302 {
303 aId.realloc (16);
304 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
305 }
306 return aId;
307 }
308
309 //==== internal =========================================================
310
GetBoundingBoxOnScreen() const311 Rectangle ScAccessiblePreviewHeaderCell::GetBoundingBoxOnScreen() const
312 {
313 Rectangle aCellRect;
314
315 FillTableInfo();
316
317 if (mpTableInfo)
318 {
319 const ScPreviewColRowInfo& rColInfo = mpTableInfo->GetColInfo()[maCellPos.Col()];
320 const ScPreviewColRowInfo& rRowInfo = mpTableInfo->GetRowInfo()[maCellPos.Row()];
321
322 aCellRect = Rectangle( rColInfo.nPixelStart, rRowInfo.nPixelStart, rColInfo.nPixelEnd, rRowInfo.nPixelEnd );
323 }
324
325 if (mpViewShell)
326 {
327 Window* pWindow = mpViewShell->GetWindow();
328 if (pWindow)
329 {
330 Rectangle aRect = pWindow->GetWindowExtentsRelative(NULL);
331 aCellRect.setX(aCellRect.getX() + aRect.getX());
332 aCellRect.setY(aCellRect.getY() + aRect.getY());
333 }
334 }
335 return aCellRect;
336 }
337
GetBoundingBox() const338 Rectangle ScAccessiblePreviewHeaderCell::GetBoundingBox() const
339 {
340 FillTableInfo();
341
342 if (mpTableInfo)
343 {
344 const ScPreviewColRowInfo& rColInfo = mpTableInfo->GetColInfo()[maCellPos.Col()];
345 const ScPreviewColRowInfo& rRowInfo = mpTableInfo->GetRowInfo()[maCellPos.Row()];
346
347 Rectangle aCellRect( rColInfo.nPixelStart, rRowInfo.nPixelStart, rColInfo.nPixelEnd, rRowInfo.nPixelEnd );
348 uno::Reference<XAccessible> xAccParent = const_cast<ScAccessiblePreviewHeaderCell*>(this)->getAccessibleParent();
349 if (xAccParent.is())
350 {
351 uno::Reference<XAccessibleContext> xAccParentContext = xAccParent->getAccessibleContext();
352 uno::Reference<XAccessibleComponent> xAccParentComp (xAccParentContext, uno::UNO_QUERY);
353 if (xAccParentComp.is())
354 {
355 Rectangle aParentRect (VCLRectangle(xAccParentComp->getBounds()));
356 aCellRect.setX(aCellRect.getX() - aParentRect.getX());
357 aCellRect.setY(aCellRect.getY() - aParentRect.getY());
358 }
359 }
360 return aCellRect;
361 }
362 return Rectangle();
363 }
364
createAccessibleDescription()365 rtl::OUString SAL_CALL ScAccessiblePreviewHeaderCell::createAccessibleDescription()
366 {
367 rtl::OUString sDescription = String(ScResId(STR_ACC_HEADERCELL_DESCR));
368 return sDescription;
369 }
370
createAccessibleName()371 rtl::OUString SAL_CALL ScAccessiblePreviewHeaderCell::createAccessibleName()
372 {
373 rtl::OUString sName = String(ScResId(STR_ACC_HEADERCELL_NAME));
374
375 if ( mbColumnHeader )
376 {
377 if ( mbRowHeader )
378 {
379 //! name for corner cell?
380
381 // sName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Column/Row Header"));
382 }
383 else
384 {
385 // name of column header
386 sName += ScColToAlpha( maCellPos.Col() );
387 }
388 }
389 else
390 {
391 // name of row header
392 sName += rtl::OUString::valueOf( (sal_Int32) ( maCellPos.Row() + 1 ) );
393 }
394
395 return sName;
396 }
397
IsDefunc(const uno::Reference<XAccessibleStateSet> & rxParentStates)398 sal_Bool ScAccessiblePreviewHeaderCell::IsDefunc( const uno::Reference<XAccessibleStateSet>& rxParentStates )
399 {
400 return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() ||
401 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
402 }
403
CreateTextHelper()404 void ScAccessiblePreviewHeaderCell::CreateTextHelper()
405 {
406 if (!mpTextHelper)
407 {
408 ::std::auto_ptr < ScAccessibleTextData > pAccessiblePreviewHeaderCellTextData
409 (new ScAccessiblePreviewHeaderCellTextData(mpViewShell, String(getAccessibleName()), maCellPos, mbColumnHeader, mbRowHeader));
410 ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessiblePreviewHeaderCellTextData));
411
412 mpTextHelper = new ::accessibility::AccessibleTextHelper(pEditSource );
413 mpTextHelper->SetEventSource(this);
414 }
415 }
416
FillTableInfo() const417 void ScAccessiblePreviewHeaderCell::FillTableInfo() const
418 {
419 if ( mpViewShell && !mpTableInfo )
420 {
421 Size aOutputSize;
422 Window* pWindow = mpViewShell->GetWindow();
423 if ( pWindow )
424 aOutputSize = pWindow->GetOutputSizePixel();
425 Point aPoint;
426 Rectangle aVisRect( aPoint, aOutputSize );
427
428 mpTableInfo = new ScPreviewTableInfo;
429 mpViewShell->GetLocationData().GetTableInfo( aVisRect, *mpTableInfo );
430 }
431 }
432