xref: /AOO41X/main/sw/source/core/access/acccell.cxx (revision 46b0c5debffe9fc43e60fe5cac69680d0f706d6b)
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 #include <ndtxt.hxx>
54 #include <editeng/brshitem.hxx>
55 #include <swatrset.hxx>
56 #include <frmatr.hxx>
57 #include "acctable.hxx"
58 
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::accessibility;
61 using ::rtl::OUString;
62 using namespace sw::access;
63 
64 const sal_Char sServiceName[] = "com.sun.star.table.AccessibleCellView";
65 const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleCellView";
66 
IsSelected()67 sal_Bool SwAccessibleCell::IsSelected()
68 {
69     sal_Bool bRet = sal_False;
70 
71     DBG_ASSERT( GetMap(), "no map?" );
72     const ViewShell *pVSh = GetMap()->GetShell();
73     DBG_ASSERT( pVSh, "no shell?" );
74     if( pVSh->ISA( SwCrsrShell ) )
75     {
76         const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh );
77         if( pCSh->IsTableMode() )
78         {
79             const SwCellFrm *pCFrm =
80                 static_cast< const SwCellFrm * >( GetFrm() );
81             SwTableBox *pBox =
82                 const_cast< SwTableBox *>( pCFrm->GetTabBox() ); //SVPtrArr!
83             bRet = pCSh->GetTableCrsr()->GetBoxes().Seek_Entry( pBox );
84         }
85     }
86 
87     return bRet;
88 }
89 
GetStates(::utl::AccessibleStateSetHelper & rStateSet)90 void SwAccessibleCell::GetStates( ::utl::AccessibleStateSetHelper& rStateSet )
91 {
92     SwAccessibleContext::GetStates( rStateSet );
93 
94     // SELECTABLE
95     const ViewShell *pVSh = GetMap()->GetShell();
96     DBG_ASSERT( pVSh, "no shell?" );
97     if( pVSh->ISA( SwCrsrShell ) )
98         rStateSet.AddState( AccessibleStateType::SELECTABLE );
99     //Solution:Add resizable state to table cell.
100     rStateSet.AddState( AccessibleStateType::RESIZABLE );
101 
102     // SELECTED
103     if( IsSelected() )
104     {
105         rStateSet.AddState( AccessibleStateType::SELECTED );
106         ASSERT( bIsSelected, "bSelected out of sync" );
107         ::vos::ORef < SwAccessibleContext > xThis( this );
108         GetMap()->SetCursorContext( xThis );
109     }
110 }
111 
SwAccessibleCell(SwAccessibleMap * pInitMap,const SwCellFrm * pCellFrm)112 SwAccessibleCell::SwAccessibleCell( SwAccessibleMap *pInitMap,
113                                     const SwCellFrm *pCellFrm )
114     : SwAccessibleContext( pInitMap, AccessibleRole::TABLE_CELL, pCellFrm )
115     , aSelectionHelper( *this )
116     , bIsSelected( sal_False )
117     , m_xTableReference( NULL )
118     , m_pAccTable( NULL )
119 {
120     vos::OGuard aGuard( Application::GetSolarMutex() );
121     OUString sBoxName( pCellFrm->GetTabBox()->GetName() );
122     SetName( sBoxName );
123 
124     bIsSelected = IsSelected();
125 
126     m_xTableReference = getAccessibleParent();
127 #if OSL_DEBUG_LEVEL > 1
128     uno::Reference< XAccessibleContext > xContextTable( m_xTableReference, uno::UNO_QUERY );
129     OSL_ASSERT( xContextTable.is() && xContextTable->getAccessibleRole() == AccessibleRole::TABLE );
130 #endif
131     m_pAccTable = static_cast< SwAccessibleTable * >( m_xTableReference.get() );
132 }
133 
_InvalidateMyCursorPos()134 sal_Bool SwAccessibleCell::_InvalidateMyCursorPos()
135 {
136     sal_Bool bNew = IsSelected();
137     sal_Bool bOld;
138     {
139         vos::OGuard aGuard( aMutex );
140         bOld = bIsSelected;
141         bIsSelected = bNew;
142     }
143     if( bNew )
144     {
145         // remember that object as the one that has the caret. This is
146         // neccessary to notify that object if the cursor leaves it.
147         ::vos::ORef < SwAccessibleContext > xThis( this );
148         GetMap()->SetCursorContext( xThis );
149     }
150 
151     sal_Bool bChanged = bOld != bNew;
152     if( bChanged )
153     {
154         FireStateChangedEvent( AccessibleStateType::SELECTED, bNew );
155         if (m_pAccTable)
156         {
157             m_pAccTable->AddSelectionCell(this,bNew);
158         }
159     }
160     return bChanged;
161 }
162 
_InvalidateChildrenCursorPos(const SwFrm * pFrm)163 sal_Bool SwAccessibleCell::_InvalidateChildrenCursorPos( const SwFrm *pFrm )
164 {
165     sal_Bool bChanged = sal_False;
166 
167     const SwAccessibleChildSList aVisList( GetVisArea(), *pFrm, *GetMap() );
168     SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
169     while( aIter != aVisList.end() )
170     {
171         const SwAccessibleChild& rLower = *aIter;
172         const SwFrm *pLower = rLower.GetSwFrm();
173         if( pLower )
174         {
175             if( rLower.IsAccessible( GetMap()->GetShell()->IsPreView() )  )
176             {
177                 ::vos::ORef< SwAccessibleContext > xAccImpl(
178                     GetMap()->GetContextImpl( pLower, sal_False ) );
179                 if( xAccImpl.isValid() )
180                 {
181                     ASSERT( xAccImpl->GetFrm()->IsCellFrm(),
182                             "table child is not a cell frame" )
183                     bChanged = static_cast< SwAccessibleCell *>(
184                             xAccImpl.getBodyPtr() )->_InvalidateMyCursorPos();
185                 }
186                 else
187                     bChanged = sal_True; // If the context is not know we
188                                          // don't know whether the selection
189                                          // changed or not.
190             }
191             else
192             {
193                 // This is a box with sub rows.
194                 bChanged |= _InvalidateChildrenCursorPos( pLower );
195             }
196         }
197         ++aIter;
198     }
199 
200     return bChanged;
201 }
202 
_InvalidateCursorPos()203 void SwAccessibleCell::_InvalidateCursorPos()
204 {
205     if (IsSelected())
206     {
207         const SwAccessibleChild aChild( GetChild( *(GetMap()), 0 ) );
208         if( aChild.IsValid()  && aChild.GetSwFrm() )
209         {
210             ::vos::ORef < SwAccessibleContext > xChildImpl( GetMap()->GetContextImpl( aChild.GetSwFrm())  );
211             if(xChildImpl.isValid())
212             {
213                 AccessibleEventObject aEvent;
214                 aEvent.EventId = AccessibleEventId::STATE_CHANGED;
215                 aEvent.NewValue<<=AccessibleStateType::FOCUSED;
216                 xChildImpl->FireAccessibleEvent( aEvent );
217             }
218         }
219     }
220 
221     const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
222     ASSERT( pParent->IsTabFrm(), "parent is not a tab frame" );
223     const SwTabFrm *pTabFrm = static_cast< const SwTabFrm * >( pParent );
224     if( pTabFrm->IsFollow() )
225         pTabFrm = pTabFrm->FindMaster();
226 
227     while( pTabFrm )
228     {
229                 _InvalidateChildrenCursorPos( pTabFrm );
230 /*
231         sal_Bool bChanged = _InvalidateChildrenCursorPos( pTabFrm );
232         if( bChanged )
233         {
234             ::vos::ORef< SwAccessibleContext > xAccImpl(
235                 GetMap()->GetContextImpl( pTabFrm, sal_False ) );
236             if( xAccImpl.isValid() )
237             {
238                 AccessibleEventObject aEvent;
239                 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
240                 xAccImpl->FireAccessibleEvent( aEvent );
241             }
242         }
243 */
244         pTabFrm = pTabFrm->GetFollow();
245     }
246     if (m_pAccTable)
247     {
248         m_pAccTable->FireSelectionEvent();
249     }
250 }
251 
HasCursor()252 sal_Bool SwAccessibleCell::HasCursor()
253 {
254     vos::OGuard aGuard( aMutex );
255     return bIsSelected;
256 }
257 
~SwAccessibleCell()258 SwAccessibleCell::~SwAccessibleCell()
259 {
260 }
261 
getAccessibleDescription(void)262 OUString SAL_CALL SwAccessibleCell::getAccessibleDescription (void)
263         throw (uno::RuntimeException)
264 {
265     return GetName();
266 }
267 
getImplementationName()268 OUString SAL_CALL SwAccessibleCell::getImplementationName()
269         throw( uno::RuntimeException )
270 {
271     return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
272 }
273 
supportsService(const::rtl::OUString & sTestServiceName)274 sal_Bool SAL_CALL SwAccessibleCell::supportsService(
275         const ::rtl::OUString& sTestServiceName)
276     throw (uno::RuntimeException)
277 {
278     return sTestServiceName.equalsAsciiL( sServiceName,
279                                           sizeof(sServiceName)-1 ) ||
280            sTestServiceName.equalsAsciiL( sAccessibleServiceName,
281                                           sizeof(sAccessibleServiceName)-1 );
282 }
283 
getSupportedServiceNames()284 uno::Sequence< OUString > SAL_CALL SwAccessibleCell::getSupportedServiceNames()
285         throw( uno::RuntimeException )
286 {
287     uno::Sequence< OUString > aRet(2);
288     OUString* pArray = aRet.getArray();
289     pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
290     pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
291     return aRet;
292 }
293 
Dispose(sal_Bool bRecursive)294 void SwAccessibleCell::Dispose( sal_Bool bRecursive )
295 {
296     const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
297     ::vos::ORef< SwAccessibleContext > xAccImpl(
298             GetMap()->GetContextImpl( pParent, sal_False ) );
299     if( xAccImpl.isValid() )
300         xAccImpl->DisposeChild( SwAccessibleChild(GetFrm()), bRecursive );
301     SwAccessibleContext::Dispose( bRecursive );
302 }
303 
InvalidatePosOrSize(const SwRect & rOldBox)304 void SwAccessibleCell::InvalidatePosOrSize( const SwRect& rOldBox )
305 {
306     const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
307     ::vos::ORef< SwAccessibleContext > xAccImpl(
308             GetMap()->GetContextImpl( pParent, sal_False ) );
309     if( xAccImpl.isValid() )
310         xAccImpl->InvalidateChildPosOrSize( SwAccessibleChild(GetFrm()), rOldBox );
311     SwAccessibleContext::InvalidatePosOrSize( rOldBox );
312 }
313 
314 
315 // =====  XAccessibleInterface  ===========================================
316 
queryInterface(const uno::Type & rType)317 uno::Any SwAccessibleCell::queryInterface( const uno::Type& rType )
318     throw( uno::RuntimeException )
319 {
320     if (rType == ::getCppuType((const uno::Reference<XAccessibleExtendedAttributes>*)0))
321     {
322         uno::Any aR;
323         aR <<= uno::Reference<XAccessibleExtendedAttributes>(this);
324         return aR;
325     }
326 
327     if (rType == ::getCppuType((const uno::Reference<XAccessibleSelection>*)0))
328     {
329         uno::Any aR;
330         aR <<= uno::Reference<XAccessibleSelection>(this);
331         return aR;
332     }
333     if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleValue > * >( 0 ) ) )
334     {
335         uno::Reference<XAccessibleValue> xValue = this;
336         uno::Any aRet;
337         aRet <<= xValue;
338         return aRet;
339     }
340     else
341     {
342         return SwAccessibleContext::queryInterface( rType );
343     }
344 }
345 
346 //====== XTypeProvider ====================================================
getTypes()347 uno::Sequence< uno::Type > SAL_CALL SwAccessibleCell::getTypes()
348     throw(uno::RuntimeException)
349 {
350     uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() );
351 
352     sal_Int32 nIndex = aTypes.getLength();
353     aTypes.realloc( nIndex + 1 );
354 
355     uno::Type* pTypes = aTypes.getArray();
356     pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleValue > * >( 0 ) );
357 
358     return aTypes;
359 }
360 
getImplementationId()361 uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleCell::getImplementationId()
362         throw(uno::RuntimeException)
363 {
364     vos::OGuard aGuard(Application::GetSolarMutex());
365     static uno::Sequence< sal_Int8 > aId( 16 );
366     static sal_Bool bInit = sal_False;
367     if(!bInit)
368     {
369         rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
370         bInit = sal_True;
371     }
372     return aId;
373 }
374 
375 // =====  XAccessibleValue  ===============================================
376 
GetTblBoxFormat() const377 SwFrmFmt* SwAccessibleCell::GetTblBoxFormat() const
378 {
379     DBG_ASSERT( GetFrm() != NULL, "no frame?" );
380     DBG_ASSERT( GetFrm()->IsCellFrm(), "no cell frame?" );
381 
382     const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>( GetFrm() );
383     return pCellFrm->GetTabBox()->GetFrmFmt();
384 }
385 
386 //Implement TableCell currentValue
getCurrentValue()387 uno::Any SwAccessibleCell::getCurrentValue( )
388     throw( uno::RuntimeException )
389 {
390     vos::OGuard aGuard(Application::GetSolarMutex());
391     CHECK_FOR_DEFUNC( XAccessibleValue );
392 
393     uno::Any aAny;
394 
395     const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>( GetFrm() );
396     const SwStartNode *pSttNd = pCellFrm->GetTabBox()->GetSttNd();
397     if( pSttNd )
398     {
399         ::rtl::OUString strRet;
400         SwNodeIndex aCntntIdx( *pSttNd, 0 );
401         SwCntntNode* pCNd=NULL;
402         for(int nIndex = 0 ;
403             0 != ( pCNd = pSttNd->GetNodes().GoNext( &aCntntIdx ) ) &&
404             aCntntIdx.GetIndex() < pSttNd->EndOfSectionIndex();
405             ++nIndex )
406         {
407             if(pCNd && pCNd->IsTxtNode())
408             {
409                 if (0 != nIndex)
410                 {
411                     strRet += ::rtl::OUString::createFromAscii(" ");
412                 }
413                 strRet +=((SwTxtNode*)pCNd)->GetTxt();
414             }
415         }
416         aAny <<= strRet;
417     }
418     return aAny;
419 }
420 
setCurrentValue(const uno::Any & aNumber)421 sal_Bool SwAccessibleCell::setCurrentValue( const uno::Any& aNumber )
422     throw( uno::RuntimeException )
423 {
424     vos::OGuard aGuard(Application::GetSolarMutex());
425     CHECK_FOR_DEFUNC( XAccessibleValue );
426 
427     double fValue = 0;
428     sal_Bool bValid = (aNumber >>= fValue);
429     if( bValid )
430     {
431         SwTblBoxValue aValue( fValue );
432         GetTblBoxFormat()->SetFmtAttr( aValue );
433     }
434     return bValid;
435 }
436 
getMaximumValue()437 uno::Any SwAccessibleCell::getMaximumValue( )
438     throw( uno::RuntimeException )
439 {
440     uno::Any aAny;
441     aAny <<= DBL_MAX;
442     return aAny;
443 }
444 
getMinimumValue()445 uno::Any SwAccessibleCell::getMinimumValue(  )
446     throw( uno::RuntimeException )
447 {
448     uno::Any aAny;
449     aAny <<= -DBL_MAX;
450     return aAny;
451 }
452 
ReplaceOneChar(::rtl::OUString oldOUString,::rtl::OUString replacedChar,::rtl::OUString replaceStr)453 ::rtl::OUString ReplaceOneChar(::rtl::OUString oldOUString, ::rtl::OUString replacedChar, ::rtl::OUString replaceStr)
454 {
455     int iReplace = -1;
456     iReplace = oldOUString.lastIndexOf(replacedChar);
457     if (iReplace > -1)
458     {
459         for(;iReplace>-1;)
460         {
461             oldOUString = oldOUString.replaceAt(iReplace,1, replaceStr);
462             iReplace=oldOUString.lastIndexOf(replacedChar,iReplace);
463         }
464     }
465     return oldOUString;
466 }
ReplaceFourChar(::rtl::OUString oldOUString)467 ::rtl::OUString ReplaceFourChar(::rtl::OUString oldOUString)
468 {
469     oldOUString = ReplaceOneChar(oldOUString,OUString::createFromAscii("\\"),OUString::createFromAscii("\\\\"));
470     oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii(";"),::rtl::OUString::createFromAscii("\\;"));
471     oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii("="),::rtl::OUString::createFromAscii("\\="));
472     oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii(","),::rtl::OUString::createFromAscii("\\,"));
473     oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii(":"),::rtl::OUString::createFromAscii("\\:"));
474     return oldOUString;
475 }
476 
getExtendedAttributes()477 ::com::sun::star::uno::Any SAL_CALL SwAccessibleCell::getExtendedAttributes()
478         throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
479 {
480     ::com::sun::star::uno::Any strRet;
481     SwFrmFmt *pFrmFmt = GetTblBoxFormat();
482     DBG_ASSERT(pFrmFmt,"Must be Valid");
483 
484     const SwTblBoxFormula& tbl_formula = pFrmFmt->GetTblBoxFormula();
485 
486     ::rtl::OUString strFormula = ReplaceFourChar(tbl_formula.GetFormula());
487     ::rtl::OUString strFor = ::rtl::OUString::createFromAscii("Formula:");
488     strFor += strFormula;
489     strFor += ::rtl::OUString::createFromAscii(";") ;
490     strRet <<= strFor;
491 
492     return strRet;
493 }
494 
getBackground()495 sal_Int32 SAL_CALL SwAccessibleCell::getBackground()
496         throw (::com::sun::star::uno::RuntimeException)
497 {
498     const SvxBrushItem &rBack = GetFrm()->GetAttrSet()->GetBackground();
499     sal_uInt32 crBack = rBack.GetColor().GetColor();
500 
501     if (COL_AUTO == crBack)
502     {
503         uno::Reference<XAccessible> xAccDoc = getAccessibleParent();
504         if (xAccDoc.is())
505         {
506             uno::Reference<XAccessibleComponent> xCompoentDoc(xAccDoc, uno::UNO_QUERY);
507             if (xCompoentDoc.is())
508             {
509                 crBack = (sal_uInt32)xCompoentDoc->getBackground();
510             }
511         }
512     }
513     return crBack;
514 }
515 
516 //=====  XAccessibleSelection  ============================================
selectAccessibleChild(sal_Int32 nChildIndex)517 void SwAccessibleCell::selectAccessibleChild(
518     sal_Int32 nChildIndex )
519     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
520 {
521     aSelectionHelper.selectAccessibleChild(nChildIndex);
522 }
523 
isAccessibleChildSelected(sal_Int32 nChildIndex)524 sal_Bool SwAccessibleCell::isAccessibleChildSelected(
525     sal_Int32 nChildIndex )
526     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
527 {
528     return aSelectionHelper.isAccessibleChildSelected(nChildIndex);
529 }
530 
clearAccessibleSelection()531 void SwAccessibleCell::clearAccessibleSelection(  )
532     throw ( uno::RuntimeException )
533 {
534     aSelectionHelper.clearAccessibleSelection();
535 }
536 
selectAllAccessibleChildren()537 void SwAccessibleCell::selectAllAccessibleChildren(  )
538     throw ( uno::RuntimeException )
539 {
540     aSelectionHelper.selectAllAccessibleChildren();
541 }
542 
getSelectedAccessibleChildCount()543 sal_Int32 SwAccessibleCell::getSelectedAccessibleChildCount(  )
544     throw ( uno::RuntimeException )
545 {
546     return aSelectionHelper.getSelectedAccessibleChildCount();
547 }
548 
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)549 uno::Reference<XAccessible> SwAccessibleCell::getSelectedAccessibleChild(
550     sal_Int32 nSelectedChildIndex )
551     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException)
552 {
553     return aSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
554 }
555 
deselectAccessibleChild(sal_Int32 nSelectedChildIndex)556 void SwAccessibleCell::deselectAccessibleChild(
557     sal_Int32 nSelectedChildIndex )
558     throw ( lang::IndexOutOfBoundsException, uno::RuntimeException )
559 {
560     aSelectionHelper.deselectAccessibleChild(nSelectedChildIndex);
561 }
562 
563