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