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