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