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