xref: /trunk/main/sw/source/core/access/acccell.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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         // necessary 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 {
264     return GetName();
265 }
266 
getImplementationName()267 OUString SAL_CALL SwAccessibleCell::getImplementationName()
268 {
269     return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
270 }
271 
supportsService(const::rtl::OUString & sTestServiceName)272 sal_Bool SAL_CALL SwAccessibleCell::supportsService(
273         const ::rtl::OUString& sTestServiceName)
274 {
275     return sTestServiceName.equalsAsciiL( sServiceName,
276                                           sizeof(sServiceName)-1 ) ||
277            sTestServiceName.equalsAsciiL( sAccessibleServiceName,
278                                           sizeof(sAccessibleServiceName)-1 );
279 }
280 
getSupportedServiceNames()281 uno::Sequence< OUString > SAL_CALL SwAccessibleCell::getSupportedServiceNames()
282 {
283     uno::Sequence< OUString > aRet(2);
284     OUString* pArray = aRet.getArray();
285     pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
286     pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
287     return aRet;
288 }
289 
Dispose(sal_Bool bRecursive)290 void SwAccessibleCell::Dispose( sal_Bool bRecursive )
291 {
292     const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
293     ::vos::ORef< SwAccessibleContext > xAccImpl(
294             GetMap()->GetContextImpl( pParent, sal_False ) );
295     if( xAccImpl.isValid() )
296         xAccImpl->DisposeChild( SwAccessibleChild(GetFrm()), bRecursive );
297     SwAccessibleContext::Dispose( bRecursive );
298 }
299 
InvalidatePosOrSize(const SwRect & rOldBox)300 void SwAccessibleCell::InvalidatePosOrSize( const SwRect& rOldBox )
301 {
302     const SwFrm *pParent = GetParent( SwAccessibleChild(GetFrm()), IsInPagePreview() );
303     ::vos::ORef< SwAccessibleContext > xAccImpl(
304             GetMap()->GetContextImpl( pParent, sal_False ) );
305     if( xAccImpl.isValid() )
306         xAccImpl->InvalidateChildPosOrSize( SwAccessibleChild(GetFrm()), rOldBox );
307     SwAccessibleContext::InvalidatePosOrSize( rOldBox );
308 }
309 
310 
311 // =====  XAccessibleInterface  ===========================================
312 
queryInterface(const uno::Type & rType)313 uno::Any SwAccessibleCell::queryInterface( const uno::Type& rType )
314 {
315     if (rType == ::getCppuType((const uno::Reference<XAccessibleExtendedAttributes>*)0))
316     {
317         uno::Any aR;
318         aR <<= uno::Reference<XAccessibleExtendedAttributes>(this);
319         return aR;
320     }
321 
322     if (rType == ::getCppuType((const uno::Reference<XAccessibleSelection>*)0))
323     {
324         uno::Any aR;
325         aR <<= uno::Reference<XAccessibleSelection>(this);
326         return aR;
327     }
328     if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleValue > * >( 0 ) ) )
329     {
330         uno::Reference<XAccessibleValue> xValue = this;
331         uno::Any aRet;
332         aRet <<= xValue;
333         return aRet;
334     }
335     else
336     {
337         return SwAccessibleContext::queryInterface( rType );
338     }
339 }
340 
341 //====== XTypeProvider ====================================================
getTypes()342 uno::Sequence< uno::Type > SAL_CALL SwAccessibleCell::getTypes()
343 {
344     uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() );
345 
346     sal_Int32 nIndex = aTypes.getLength();
347     aTypes.realloc( nIndex + 1 );
348 
349     uno::Type* pTypes = aTypes.getArray();
350     pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleValue > * >( 0 ) );
351 
352     return aTypes;
353 }
354 
getImplementationId()355 uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleCell::getImplementationId()
356 {
357     vos::OGuard aGuard(Application::GetSolarMutex());
358     static uno::Sequence< sal_Int8 > aId( 16 );
359     static sal_Bool bInit = sal_False;
360     if(!bInit)
361     {
362         rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
363         bInit = sal_True;
364     }
365     return aId;
366 }
367 
368 // =====  XAccessibleValue  ===============================================
369 
GetTblBoxFormat() const370 SwFrmFmt* SwAccessibleCell::GetTblBoxFormat() const
371 {
372     DBG_ASSERT( GetFrm() != NULL, "no frame?" );
373     DBG_ASSERT( GetFrm()->IsCellFrm(), "no cell frame?" );
374 
375     const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>( GetFrm() );
376     return pCellFrm->GetTabBox()->GetFrmFmt();
377 }
378 
379 //Implement TableCell currentValue
getCurrentValue()380 uno::Any SwAccessibleCell::getCurrentValue( )
381 {
382     vos::OGuard aGuard(Application::GetSolarMutex());
383     CHECK_FOR_DEFUNC( XAccessibleValue );
384 
385     uno::Any aAny;
386 
387     const SwCellFrm* pCellFrm = static_cast<const SwCellFrm*>( GetFrm() );
388     const SwStartNode *pSttNd = pCellFrm->GetTabBox()->GetSttNd();
389     if( pSttNd )
390     {
391         ::rtl::OUString strRet;
392         SwNodeIndex aCntntIdx( *pSttNd, 0 );
393         SwCntntNode* pCNd=NULL;
394         for(int nIndex = 0 ;
395             0 != ( pCNd = pSttNd->GetNodes().GoNext( &aCntntIdx ) ) &&
396             aCntntIdx.GetIndex() < pSttNd->EndOfSectionIndex();
397             ++nIndex )
398         {
399             if(pCNd && pCNd->IsTxtNode())
400             {
401                 if (0 != nIndex)
402                 {
403                     strRet += ::rtl::OUString::createFromAscii(" ");
404                 }
405                 strRet +=((SwTxtNode*)pCNd)->GetTxt();
406             }
407         }
408         aAny <<= strRet;
409     }
410     return aAny;
411 }
412 
setCurrentValue(const uno::Any & aNumber)413 sal_Bool SwAccessibleCell::setCurrentValue( const uno::Any& aNumber )
414 {
415     vos::OGuard aGuard(Application::GetSolarMutex());
416     CHECK_FOR_DEFUNC( XAccessibleValue );
417 
418     double fValue = 0;
419     sal_Bool bValid = (aNumber >>= fValue);
420     if( bValid )
421     {
422         SwTblBoxValue aValue( fValue );
423         GetTblBoxFormat()->SetFmtAttr( aValue );
424     }
425     return bValid;
426 }
427 
getMaximumValue()428 uno::Any SwAccessibleCell::getMaximumValue( )
429 {
430     uno::Any aAny;
431     aAny <<= DBL_MAX;
432     return aAny;
433 }
434 
getMinimumValue()435 uno::Any SwAccessibleCell::getMinimumValue(  )
436 {
437     uno::Any aAny;
438     aAny <<= -DBL_MAX;
439     return aAny;
440 }
441 
ReplaceOneChar(::rtl::OUString oldOUString,::rtl::OUString replacedChar,::rtl::OUString replaceStr)442 ::rtl::OUString ReplaceOneChar(::rtl::OUString oldOUString, ::rtl::OUString replacedChar, ::rtl::OUString replaceStr)
443 {
444     int iReplace = -1;
445     iReplace = oldOUString.lastIndexOf(replacedChar);
446     if (iReplace > -1)
447     {
448         for(;iReplace>-1;)
449         {
450             oldOUString = oldOUString.replaceAt(iReplace,1, replaceStr);
451             iReplace=oldOUString.lastIndexOf(replacedChar,iReplace);
452         }
453     }
454     return oldOUString;
455 }
ReplaceFourChar(::rtl::OUString oldOUString)456 ::rtl::OUString ReplaceFourChar(::rtl::OUString oldOUString)
457 {
458     oldOUString = ReplaceOneChar(oldOUString,OUString::createFromAscii("\\"),OUString::createFromAscii("\\\\"));
459     oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii(";"),::rtl::OUString::createFromAscii("\\;"));
460     oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii("="),::rtl::OUString::createFromAscii("\\="));
461     oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii(","),::rtl::OUString::createFromAscii("\\,"));
462     oldOUString = ReplaceOneChar(oldOUString,::rtl::OUString::createFromAscii(":"),::rtl::OUString::createFromAscii("\\:"));
463     return oldOUString;
464 }
465 
getExtendedAttributes()466 ::com::sun::star::uno::Any SAL_CALL SwAccessibleCell::getExtendedAttributes()
467 {
468     ::com::sun::star::uno::Any strRet;
469     SwFrmFmt *pFrmFmt = GetTblBoxFormat();
470     DBG_ASSERT(pFrmFmt,"Must be Valid");
471 
472     const SwTblBoxFormula& tbl_formula = pFrmFmt->GetTblBoxFormula();
473 
474     ::rtl::OUString strFormula = ReplaceFourChar(tbl_formula.GetFormula());
475     ::rtl::OUString strFor = ::rtl::OUString::createFromAscii("Formula:");
476     strFor += strFormula;
477     strFor += ::rtl::OUString::createFromAscii(";") ;
478     strRet <<= strFor;
479 
480     return strRet;
481 }
482 
getBackground()483 sal_Int32 SAL_CALL SwAccessibleCell::getBackground()
484 {
485     const SvxBrushItem &rBack = GetFrm()->GetAttrSet()->GetBackground();
486     sal_uInt32 crBack = rBack.GetColor().GetColor();
487 
488     if (COL_AUTO == crBack)
489     {
490         uno::Reference<XAccessible> xAccDoc = getAccessibleParent();
491         if (xAccDoc.is())
492         {
493             uno::Reference<XAccessibleComponent> xCompoentDoc(xAccDoc, uno::UNO_QUERY);
494             if (xCompoentDoc.is())
495             {
496                 crBack = (sal_uInt32)xCompoentDoc->getBackground();
497             }
498         }
499     }
500     return crBack;
501 }
502 
503 //=====  XAccessibleSelection  ============================================
selectAccessibleChild(sal_Int32 nChildIndex)504 void SwAccessibleCell::selectAccessibleChild(
505     sal_Int32 nChildIndex )
506 {
507     aSelectionHelper.selectAccessibleChild(nChildIndex);
508 }
509 
isAccessibleChildSelected(sal_Int32 nChildIndex)510 sal_Bool SwAccessibleCell::isAccessibleChildSelected(
511     sal_Int32 nChildIndex )
512 {
513     return aSelectionHelper.isAccessibleChildSelected(nChildIndex);
514 }
515 
clearAccessibleSelection()516 void SwAccessibleCell::clearAccessibleSelection(  )
517 {
518     aSelectionHelper.clearAccessibleSelection();
519 }
520 
selectAllAccessibleChildren()521 void SwAccessibleCell::selectAllAccessibleChildren(  )
522 {
523     aSelectionHelper.selectAllAccessibleChildren();
524 }
525 
getSelectedAccessibleChildCount()526 sal_Int32 SwAccessibleCell::getSelectedAccessibleChildCount(  )
527 {
528     return aSelectionHelper.getSelectedAccessibleChildCount();
529 }
530 
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)531 uno::Reference<XAccessible> SwAccessibleCell::getSelectedAccessibleChild(
532     sal_Int32 nSelectedChildIndex )
533 {
534     return aSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
535 }
536 
deselectAccessibleChild(sal_Int32 nSelectedChildIndex)537 void SwAccessibleCell::deselectAccessibleChild(
538     sal_Int32 nSelectedChildIndex )
539 {
540     aSelectionHelper.deselectAccessibleChild(nSelectedChildIndex);
541 }
542