xref: /trunk/main/sw/source/core/access/acccell.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_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