xref: /aoo41x/main/sw/source/core/access/acccell.cxx (revision cdf0e10c)
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_sw.hxx"
30 
31 
32 #include <vos/mutex.hxx>
33 #include <com/sun/star/accessibility/AccessibleRole.hpp>
34 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
35 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
36 #include <unotools/accessiblestatesethelper.hxx>
37 #include <rtl/uuid.h>
38 #include <vcl/svapp.hxx>
39 #include <cellfrm.hxx>
40 #include <tabfrm.hxx>
41 #include <swtable.hxx>
42 #include "crsrsh.hxx"
43 #include "viscrs.hxx"
44 #include <accfrmobj.hxx>
45 #include <accfrmobjslist.hxx>
46 #include "frmfmt.hxx"
47 #include "cellatr.hxx"
48 #include "accmap.hxx"
49 #include <acccell.hxx>
50 
51 #ifndef _STLP_CFLOAT
52 #include <cfloat>
53 #endif
54 
55 #include <limits.h>
56 
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::accessibility;
59 using ::rtl::OUString;
60 using namespace sw::access;
61 
62 const sal_Char sServiceName[] = "com.sun.star.table.AccessibleCellView";
63 const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleCellView";
64 
65 sal_Bool SwAccessibleCell::IsSelected()
66 {
67 	sal_Bool bRet = sal_False;
68 
69     DBG_ASSERT( GetMap(), "no map?" );
70 	const ViewShell *pVSh = GetMap()->GetShell();
71     DBG_ASSERT( pVSh, "no shell?" );
72 	if( pVSh->ISA( SwCrsrShell ) )
73 	{
74 		const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh );
75 		if( pCSh->IsTableMode() )
76 		{
77 			const SwCellFrm *pCFrm =
78 				static_cast< const SwCellFrm * >( GetFrm() );
79 			SwTableBox *pBox =
80 				const_cast< SwTableBox *>( pCFrm->GetTabBox() ); //SVPtrArr!
81 			bRet = pCSh->GetTableCrsr()->GetBoxes().Seek_Entry( pBox );
82 		}
83 	}
84 
85 	return bRet;
86 }
87 
88 void SwAccessibleCell::GetStates( ::utl::AccessibleStateSetHelper& rStateSet )
89 {
90 	SwAccessibleContext::GetStates( rStateSet );
91 
92 	// SELECTABLE
93 	const ViewShell *pVSh = GetMap()->GetShell();
94     DBG_ASSERT( pVSh, "no shell?" );
95 	if( pVSh->ISA( SwCrsrShell ) )
96 		rStateSet.AddState( AccessibleStateType::SELECTABLE );
97 
98 	// SELECTED
99 	if( IsSelected() )
100 	{
101 		rStateSet.AddState( AccessibleStateType::SELECTED );
102 		ASSERT( bIsSelected, "bSelected out of sync" );
103 		::vos::ORef < SwAccessibleContext > xThis( this );
104 		GetMap()->SetCursorContext( xThis );
105 	}
106 }
107 
108 SwAccessibleCell::SwAccessibleCell( SwAccessibleMap *pInitMap,
109                                     const SwCellFrm *pCellFrm )
110     : SwAccessibleContext( pInitMap, AccessibleRole::TABLE_CELL, pCellFrm )
111     , bIsSelected( sal_False )
112 {
113 	vos::OGuard aGuard(Application::GetSolarMutex());
114     OUString sBoxName( pCellFrm->GetTabBox()->GetName() );
115     SetName( sBoxName );
116 
117 	bIsSelected = IsSelected();
118 }
119 
120 sal_Bool SwAccessibleCell::_InvalidateMyCursorPos()
121 {
122 	sal_Bool bNew = IsSelected();
123 	sal_Bool bOld;
124 	{
125 		vos::OGuard aGuard( aMutex );
126 		bOld = bIsSelected;
127 		bIsSelected = bNew;
128 	}
129 	if( bNew )
130 	{
131 		// remember that object as the one that has the caret. This is
132 		// neccessary to notify that object if the cursor leaves it.
133 		::vos::ORef < SwAccessibleContext > xThis( this );
134 		GetMap()->SetCursorContext( xThis );
135 	}
136 
137 	sal_Bool bChanged = bOld != bNew;
138 	if( bChanged )
139 		FireStateChangedEvent( AccessibleStateType::SELECTED, bNew );
140 
141 	return bChanged;
142 }
143 
144 sal_Bool SwAccessibleCell::_InvalidateChildrenCursorPos( const SwFrm *pFrm )
145 {
146 	sal_Bool bChanged = sal_False;
147 
148     const SwAccessibleChildSList aVisList( GetVisArea(), *pFrm, *GetMap() );
149     SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
150 	while( aIter != aVisList.end() )
151 	{
152         const SwAccessibleChild& rLower = *aIter;
153 		const SwFrm *pLower = rLower.GetSwFrm();
154 		if( pLower )
155 		{
156 			if( rLower.IsAccessible( GetMap()->GetShell()->IsPreView() )  )
157 			{
158 				::vos::ORef< SwAccessibleContext > xAccImpl(
159 					GetMap()->GetContextImpl( pLower, sal_False ) );
160 				if( xAccImpl.isValid() )
161 				{
162 					ASSERT( xAccImpl->GetFrm()->IsCellFrm(),
163 						 	"table child is not a cell frame" )
164 					bChanged |= static_cast< SwAccessibleCell *>(
165 							xAccImpl.getBodyPtr() )->_InvalidateMyCursorPos();
166 				}
167 				else
168 					bChanged = sal_True; // If the context is not know we
169 										 // don't know whether the selection
170 										 // changed or not.
171 			}
172 			else
173 			{
174 				// This is a box with sub rows.
175 				bChanged |= _InvalidateChildrenCursorPos( pLower );
176 			}
177 		}
178 		++aIter;
179 	}
180 
181 	return bChanged;
182 }
183 
184 void SwAccessibleCell::_InvalidateCursorPos()
185 {
186 
187     const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
188 	ASSERT( pParent->IsTabFrm(), "parent is not a tab frame" );
189 	const SwTabFrm *pTabFrm = static_cast< const SwTabFrm * >( pParent );
190 	if( pTabFrm->IsFollow() )
191 		pTabFrm = pTabFrm->FindMaster();
192 
193 	while( pTabFrm )
194 	{
195 		sal_Bool bChanged = _InvalidateChildrenCursorPos( pTabFrm );
196 		if( bChanged )
197 		{
198 			::vos::ORef< SwAccessibleContext > xAccImpl(
199 				GetMap()->GetContextImpl( pTabFrm, sal_False ) );
200 			if( xAccImpl.isValid() )
201 			{
202 				AccessibleEventObject aEvent;
203 				aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
204 				xAccImpl->FireAccessibleEvent( aEvent );
205 			}
206 		}
207 
208 		pTabFrm = pTabFrm->GetFollow();
209 	}
210 }
211 
212 sal_Bool SwAccessibleCell::HasCursor()
213 {
214 	vos::OGuard aGuard( aMutex );
215 	return bIsSelected;
216 }
217 
218 SwAccessibleCell::~SwAccessibleCell()
219 {
220 }
221 
222 OUString SAL_CALL SwAccessibleCell::getAccessibleDescription (void)
223         throw (uno::RuntimeException)
224 {
225 	return GetName();
226 }
227 
228 OUString SAL_CALL SwAccessibleCell::getImplementationName()
229         throw( uno::RuntimeException )
230 {
231 	return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
232 }
233 
234 sal_Bool SAL_CALL SwAccessibleCell::supportsService(
235 		const ::rtl::OUString& sTestServiceName)
236 	throw (uno::RuntimeException)
237 {
238 	return sTestServiceName.equalsAsciiL( sServiceName,
239 										  sizeof(sServiceName)-1 ) ||
240 		   sTestServiceName.equalsAsciiL( sAccessibleServiceName,
241 				   						  sizeof(sAccessibleServiceName)-1 );
242 }
243 
244 uno::Sequence< OUString > SAL_CALL SwAccessibleCell::getSupportedServiceNames()
245 		throw( uno::RuntimeException )
246 {
247 	uno::Sequence< OUString > aRet(2);
248 	OUString* pArray = aRet.getArray();
249 	pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
250 	pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
251 	return aRet;
252 }
253 
254 void SwAccessibleCell::Dispose( sal_Bool bRecursive )
255 {
256     const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
257 	::vos::ORef< SwAccessibleContext > xAccImpl(
258 			GetMap()->GetContextImpl( pParent, sal_False ) );
259 	if( xAccImpl.isValid() )
260         xAccImpl->DisposeChild( SwAccessibleChild(GetFrm()), bRecursive );
261 	SwAccessibleContext::Dispose( bRecursive );
262 }
263 
264 void SwAccessibleCell::InvalidatePosOrSize( const SwRect& rOldBox )
265 {
266     const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
267 	::vos::ORef< SwAccessibleContext > xAccImpl(
268 			GetMap()->GetContextImpl( pParent, sal_False ) );
269 	if( xAccImpl.isValid() )
270         xAccImpl->InvalidateChildPosOrSize( SwAccessibleChild(GetFrm()), rOldBox );
271 	SwAccessibleContext::InvalidatePosOrSize( rOldBox );
272 }
273 
274 
275 // =====  XAccessibleInterface  ===========================================
276 
277 uno::Any SwAccessibleCell::queryInterface( const uno::Type& rType )
278     throw( uno::RuntimeException )
279 {
280     if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleValue > * >( 0 ) ) )
281     {
282         uno::Reference<XAccessibleValue> xValue = this;
283         uno::Any aRet;
284         aRet <<= xValue;
285         return aRet;
286     }
287     else
288     {
289         return SwAccessibleContext::queryInterface( rType );
290     }
291 }
292 
293 //====== XTypeProvider ====================================================
294 uno::Sequence< uno::Type > SAL_CALL SwAccessibleCell::getTypes()
295     throw(uno::RuntimeException)
296 {
297 	uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() );
298 
299 	sal_Int32 nIndex = aTypes.getLength();
300 	aTypes.realloc( nIndex + 1 );
301 
302 	uno::Type* pTypes = aTypes.getArray();
303 	pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleValue > * >( 0 ) );
304 
305 	return aTypes;
306 }
307 
308 uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleCell::getImplementationId()
309 		throw(uno::RuntimeException)
310 {
311     vos::OGuard aGuard(Application::GetSolarMutex());
312     static uno::Sequence< sal_Int8 > aId( 16 );
313     static sal_Bool bInit = sal_False;
314     if(!bInit)
315     {
316         rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
317         bInit = sal_True;
318     }
319     return aId;
320 }
321 
322 // =====  XAccessibleValue  ===============================================
323 
324 SwFrmFmt* SwAccessibleCell::GetTblBoxFormat() const
325 {
326     DBG_ASSERT( GetFrm() != NULL, "no frame?" );
327     DBG_ASSERT( GetFrm()->IsCellFrm(), "no cell frame?" );
328 
329     const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>( GetFrm() );
330     return pCellFrm->GetTabBox()->GetFrmFmt();
331 }
332 
333 
334 uno::Any SwAccessibleCell::getCurrentValue( )
335     throw( uno::RuntimeException )
336 {
337 	vos::OGuard aGuard(Application::GetSolarMutex());
338 	CHECK_FOR_DEFUNC( XAccessibleValue );
339 
340     uno::Any aAny;
341     aAny <<= GetTblBoxFormat()->GetTblBoxValue().GetValue();
342     return aAny;
343 }
344 
345 sal_Bool SwAccessibleCell::setCurrentValue( const uno::Any& aNumber )
346     throw( uno::RuntimeException )
347 {
348 	vos::OGuard aGuard(Application::GetSolarMutex());
349 	CHECK_FOR_DEFUNC( XAccessibleValue );
350 
351     double fValue = 0;
352     sal_Bool bValid = (aNumber >>= fValue);
353     if( bValid )
354     {
355         SwTblBoxValue aValue( fValue );
356         GetTblBoxFormat()->SetFmtAttr( aValue );
357     }
358     return bValid;
359 }
360 
361 uno::Any SwAccessibleCell::getMaximumValue( )
362     throw( uno::RuntimeException )
363 {
364     uno::Any aAny;
365     aAny <<= DBL_MAX;
366     return aAny;
367 }
368 
369 uno::Any SwAccessibleCell::getMinimumValue(  )
370     throw( uno::RuntimeException )
371 {
372     uno::Any aAny;
373     aAny <<= -DBL_MAX;
374     return aAny;
375 }
376