xref: /AOO41X/main/sw/source/core/access/acccell.cxx (revision ff0525f24f03981d56b7579b645949f111420994)
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