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 throw (uno::RuntimeException)
124 {
125 uno::Any aAny (ScAccessiblePreviewHeaderCellImpl::queryInterface(rType));
126 return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType);
127 }
128
acquire()129 void SAL_CALL ScAccessiblePreviewHeaderCell::acquire()
130 throw ()
131 {
132 ScAccessibleContextBase::acquire();
133 }
134
release()135 void SAL_CALL ScAccessiblePreviewHeaderCell::release()
136 throw ()
137 {
138 ScAccessibleContextBase::release();
139 }
140
141 //===== XAccessibleValue ================================================
142
getCurrentValue()143 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getCurrentValue() throw (uno::RuntimeException)
144 {
145 ScUnoGuard aGuard;
146 IsObjectValid();
147
148 double fValue(0.0);
149 if (mbColumnHeader)
150 fValue = maCellPos.Col();
151 else
152 fValue = maCellPos.Row();
153
154 uno::Any aAny;
155 aAny <<= fValue;
156 return aAny;
157 }
158
setCurrentValue(const uno::Any &)159 sal_Bool SAL_CALL ScAccessiblePreviewHeaderCell::setCurrentValue( const uno::Any& /* aNumber */ )
160 throw (uno::RuntimeException)
161 {
162 // it is not possible to set a value
163 return sal_False;
164 }
165
getMaximumValue()166 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getMaximumValue() throw (uno::RuntimeException)
167 {
168 ScUnoGuard aGuard;
169 IsObjectValid();
170
171 double fValue(0.0);
172 if (mbColumnHeader)
173 fValue = MAXCOL;
174 else
175 fValue = MAXROW;
176 uno::Any aAny;
177 aAny <<= fValue;
178 return aAny;
179 }
180
getMinimumValue()181 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getMinimumValue() throw (uno::RuntimeException)
182 {
183 double fValue(0.0);
184 uno::Any aAny;
185 aAny <<= fValue;
186 return aAny;
187 }
188
189 //===== XAccessibleComponent ============================================
190
getAccessibleAtPoint(const awt::Point & rPoint)191 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleAtPoint( const awt::Point& rPoint )
192 throw (uno::RuntimeException)
193 {
194 uno::Reference<XAccessible> xRet;
195 if (containsPoint(rPoint))
196 {
197 ScUnoGuard aGuard;
198 IsObjectValid();
199
200 if(!mpTextHelper)
201 CreateTextHelper();
202
203 xRet = mpTextHelper->GetAt(rPoint);
204 }
205
206 return xRet;
207 }
208
grabFocus()209 void SAL_CALL ScAccessiblePreviewHeaderCell::grabFocus() throw (uno::RuntimeException)
210 {
211 ScUnoGuard aGuard;
212 IsObjectValid();
213 if (getAccessibleParent().is())
214 {
215 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
216 if (xAccessibleComponent.is())
217 xAccessibleComponent->grabFocus();
218 }
219 }
220
221 //===== XAccessibleContext ==============================================
222
getAccessibleChildCount()223 sal_Int32 SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleChildCount() throw(uno::RuntimeException)
224 {
225 ScUnoGuard aGuard;
226 IsObjectValid();
227 if (!mpTextHelper)
228 CreateTextHelper();
229 return mpTextHelper->GetChildCount();
230 }
231
getAccessibleChild(sal_Int32 nIndex)232 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleChild(sal_Int32 nIndex)
233 throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
234 {
235 ScUnoGuard aGuard;
236 IsObjectValid();
237 if (!mpTextHelper)
238 CreateTextHelper();
239 return mpTextHelper->GetChild(nIndex);
240 }
241
getAccessibleIndexInParent()242 sal_Int32 SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleIndexInParent() throw (uno::RuntimeException)
243 {
244 return mnIndex;
245 }
246
getAccessibleStateSet()247 uno::Reference<XAccessibleStateSet> SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleStateSet()
248 throw(uno::RuntimeException)
249 {
250 ScUnoGuard aGuard;
251
252 uno::Reference<XAccessibleStateSet> xParentStates;
253 if (getAccessibleParent().is())
254 {
255 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
256 xParentStates = xParentContext->getAccessibleStateSet();
257 }
258 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
259 if (IsDefunc(xParentStates))
260 pStateSet->AddState(AccessibleStateType::DEFUNC);
261 else
262 {
263 pStateSet->AddState(AccessibleStateType::ENABLED);
264 pStateSet->AddState(AccessibleStateType::MULTI_LINE);
265 if (isShowing())
266 pStateSet->AddState(AccessibleStateType::SHOWING);
267 pStateSet->AddState(AccessibleStateType::TRANSIENT);
268 if (isVisible())
269 pStateSet->AddState(AccessibleStateType::VISIBLE);
270 }
271 return pStateSet;
272 }
273
274 //===== XServiceInfo ====================================================
275
getImplementationName()276 rtl::OUString SAL_CALL ScAccessiblePreviewHeaderCell::getImplementationName() throw(uno::RuntimeException)
277 {
278 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ScAccessiblePreviewHeaderCell"));
279 }
280
getSupportedServiceNames()281 uno::Sequence<rtl::OUString> SAL_CALL ScAccessiblePreviewHeaderCell::getSupportedServiceNames()
282 throw(uno::RuntimeException)
283 {
284 uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
285 sal_Int32 nOldSize(aSequence.getLength());
286 aSequence.realloc(nOldSize + 1);
287 ::rtl::OUString* pNames = aSequence.getArray();
288
289 pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.table.AccessibleCellView"));
290
291 return aSequence;
292 }
293
294 //===== XTypeProvider =======================================================
295
getTypes()296 uno::Sequence< uno::Type > SAL_CALL ScAccessiblePreviewHeaderCell::getTypes()
297 throw (uno::RuntimeException)
298 {
299 return comphelper::concatSequences(ScAccessiblePreviewHeaderCellImpl::getTypes(), ScAccessibleContextBase::getTypes());
300 }
301
302 uno::Sequence<sal_Int8> SAL_CALL
getImplementationId(void)303 ScAccessiblePreviewHeaderCell::getImplementationId(void)
304 throw (uno::RuntimeException)
305 {
306 ScUnoGuard aGuard;
307 IsObjectValid();
308 static uno::Sequence<sal_Int8> aId;
309 if (aId.getLength() == 0)
310 {
311 aId.realloc (16);
312 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
313 }
314 return aId;
315 }
316
317 //==== internal =========================================================
318
GetBoundingBoxOnScreen() const319 Rectangle ScAccessiblePreviewHeaderCell::GetBoundingBoxOnScreen() const throw (uno::RuntimeException)
320 {
321 Rectangle aCellRect;
322
323 FillTableInfo();
324
325 if (mpTableInfo)
326 {
327 const ScPreviewColRowInfo& rColInfo = mpTableInfo->GetColInfo()[maCellPos.Col()];
328 const ScPreviewColRowInfo& rRowInfo = mpTableInfo->GetRowInfo()[maCellPos.Row()];
329
330 aCellRect = Rectangle( rColInfo.nPixelStart, rRowInfo.nPixelStart, rColInfo.nPixelEnd, rRowInfo.nPixelEnd );
331 }
332
333 if (mpViewShell)
334 {
335 Window* pWindow = mpViewShell->GetWindow();
336 if (pWindow)
337 {
338 Rectangle aRect = pWindow->GetWindowExtentsRelative(NULL);
339 aCellRect.setX(aCellRect.getX() + aRect.getX());
340 aCellRect.setY(aCellRect.getY() + aRect.getY());
341 }
342 }
343 return aCellRect;
344 }
345
GetBoundingBox() const346 Rectangle ScAccessiblePreviewHeaderCell::GetBoundingBox() const throw (uno::RuntimeException)
347 {
348 FillTableInfo();
349
350 if (mpTableInfo)
351 {
352 const ScPreviewColRowInfo& rColInfo = mpTableInfo->GetColInfo()[maCellPos.Col()];
353 const ScPreviewColRowInfo& rRowInfo = mpTableInfo->GetRowInfo()[maCellPos.Row()];
354
355 Rectangle aCellRect( rColInfo.nPixelStart, rRowInfo.nPixelStart, rColInfo.nPixelEnd, rRowInfo.nPixelEnd );
356 uno::Reference<XAccessible> xAccParent = const_cast<ScAccessiblePreviewHeaderCell*>(this)->getAccessibleParent();
357 if (xAccParent.is())
358 {
359 uno::Reference<XAccessibleContext> xAccParentContext = xAccParent->getAccessibleContext();
360 uno::Reference<XAccessibleComponent> xAccParentComp (xAccParentContext, uno::UNO_QUERY);
361 if (xAccParentComp.is())
362 {
363 Rectangle aParentRect (VCLRectangle(xAccParentComp->getBounds()));
364 aCellRect.setX(aCellRect.getX() - aParentRect.getX());
365 aCellRect.setY(aCellRect.getY() - aParentRect.getY());
366 }
367 }
368 return aCellRect;
369 }
370 return Rectangle();
371 }
372
createAccessibleDescription()373 rtl::OUString SAL_CALL ScAccessiblePreviewHeaderCell::createAccessibleDescription() throw(uno::RuntimeException)
374 {
375 rtl::OUString sDescription = String(ScResId(STR_ACC_HEADERCELL_DESCR));
376 return sDescription;
377 }
378
createAccessibleName()379 rtl::OUString SAL_CALL ScAccessiblePreviewHeaderCell::createAccessibleName() throw(uno::RuntimeException)
380 {
381 rtl::OUString sName = String(ScResId(STR_ACC_HEADERCELL_NAME));
382
383 if ( mbColumnHeader )
384 {
385 if ( mbRowHeader )
386 {
387 //! name for corner cell?
388
389 // sName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Column/Row Header"));
390 }
391 else
392 {
393 // name of column header
394 sName += ScColToAlpha( maCellPos.Col() );
395 }
396 }
397 else
398 {
399 // name of row header
400 sName += rtl::OUString::valueOf( (sal_Int32) ( maCellPos.Row() + 1 ) );
401 }
402
403 return sName;
404 }
405
IsDefunc(const uno::Reference<XAccessibleStateSet> & rxParentStates)406 sal_Bool ScAccessiblePreviewHeaderCell::IsDefunc( const uno::Reference<XAccessibleStateSet>& rxParentStates )
407 {
408 return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() ||
409 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
410 }
411
CreateTextHelper()412 void ScAccessiblePreviewHeaderCell::CreateTextHelper()
413 {
414 if (!mpTextHelper)
415 {
416 ::std::auto_ptr < ScAccessibleTextData > pAccessiblePreviewHeaderCellTextData
417 (new ScAccessiblePreviewHeaderCellTextData(mpViewShell, String(getAccessibleName()), maCellPos, mbColumnHeader, mbRowHeader));
418 ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessiblePreviewHeaderCellTextData));
419
420 mpTextHelper = new ::accessibility::AccessibleTextHelper(pEditSource );
421 mpTextHelper->SetEventSource(this);
422 }
423 }
424
FillTableInfo() const425 void ScAccessiblePreviewHeaderCell::FillTableInfo() const
426 {
427 if ( mpViewShell && !mpTableInfo )
428 {
429 Size aOutputSize;
430 Window* pWindow = mpViewShell->GetWindow();
431 if ( pWindow )
432 aOutputSize = pWindow->GetOutputSizePixel();
433 Point aPoint;
434 Rectangle aVisRect( aPoint, aOutputSize );
435
436 mpTableInfo = new ScPreviewTableInfo;
437 mpViewShell->GetLocationData().GetTableInfo( aVisRect, *mpTableInfo );
438 }
439 }
440