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