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