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_sc.hxx" 26 27 // ============================================================================ 28 #include "AccessibleCsvControl.hxx" 29 #include <com/sun/star/accessibility/AccessibleRole.hpp> 30 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLERELATIONTYPE_HPP_ 31 #include <com/sun/star/accessibility/AccessibleRelationType.hpp> 32 #endif 33 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_ 34 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 35 #endif 36 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 37 #include <com/sun/star/accessibility/AccessibleTextType.hpp> 38 #include <com/sun/star/accessibility/AccessibleTableModelChange.hpp> 39 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp> 40 #include <tools/debug.hxx> 41 #include <rtl/uuid.h> 42 #include <toolkit/helper/convert.hxx> 43 #include <unotools/accessiblerelationsethelper.hxx> 44 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX 45 #include <unotools/accessiblestatesethelper.hxx> 46 #endif 47 #include <comphelper/sequence.hxx> 48 #include "scitems.hxx" 49 #include <editeng/fontitem.hxx> 50 #include <editeng/fhgtitem.hxx> 51 #include <editeng/langitem.hxx> 52 #include "csvcontrol.hxx" 53 #include "csvruler.hxx" 54 #include "csvgrid.hxx" 55 #include "AccessibleText.hxx" 56 #include "editsrc.hxx" 57 #include "unoguard.hxx" 58 #include "scresid.hxx" 59 #include "sc.hrc" 60 #include "scmod.hxx" 61 #include <svtools/colorcfg.hxx> 62 // ause 63 #include "editutil.hxx" 64 65 using ::rtl::OUString; 66 using ::rtl::OUStringBuffer; 67 using ::utl::AccessibleRelationSetHelper; 68 using ::utl::AccessibleStateSetHelper; 69 using ::accessibility::AccessibleStaticTextBase; 70 using ::com::sun::star::uno::Any; 71 using ::com::sun::star::uno::Reference; 72 using ::com::sun::star::uno::Sequence; 73 using ::com::sun::star::uno::RuntimeException; 74 using ::com::sun::star::uno::XInterface; 75 using ::com::sun::star::lang::DisposedException; 76 using ::com::sun::star::lang::IndexOutOfBoundsException; 77 using ::com::sun::star::lang::IllegalArgumentException; 78 using ::com::sun::star::beans::PropertyValue; 79 using namespace ::com::sun::star::accessibility; 80 81 82 // ---------------------------------------------------------------------------- 83 84 const sal_uInt16 nRulerRole = AccessibleRole::TEXT; 85 const sal_uInt16 nGridRole = AccessibleRole::TABLE; 86 const sal_uInt16 nCellRole = AccessibleRole::TEXT; 87 88 #define CREATE_OUSTRING( name ) OUString( RTL_CONSTASCII_USTRINGPARAM( name ) ) 89 90 #define RULER_IMPL_NAME "ScAccessibleCsvRuler" 91 #define GRID_IMPL_NAME "ScAccessibleCsvGrid" 92 #define CELL_IMPL_NAME "ScAccessibleCsvCell" 93 94 const sal_Unicode cRulerDot = '.'; 95 const sal_Unicode cRulerLine = '|'; 96 97 const sal_Int32 CSV_LINE_HEADER = CSV_POS_INVALID; 98 const sal_uInt32 CSV_COLUMN_HEADER = CSV_COLUMN_INVALID; 99 100 101 // CSV base control =========================================================== 102 103 DBG_NAME( ScAccessibleCsvControl ) 104 105 ScAccessibleCsvControl::ScAccessibleCsvControl( 106 const Reference< XAccessible >& rxParent, 107 ScCsvControl& rControl, 108 sal_uInt16 nRole ) : 109 ScAccessibleContextBase( rxParent, nRole ), 110 mpControl( &rControl ) 111 { 112 DBG_CTOR( ScAccessibleCsvControl, NULL ); 113 } 114 115 ScAccessibleCsvControl::~ScAccessibleCsvControl() 116 { 117 DBG_DTOR( ScAccessibleCsvControl, NULL ); 118 implDispose(); 119 } 120 121 void SAL_CALL ScAccessibleCsvControl::disposing() 122 { 123 ScUnoGuard aGuard; 124 mpControl = NULL; 125 ScAccessibleContextBase::disposing(); 126 } 127 128 129 // XAccessibleComponent ------------------------------------------------------- 130 131 Reference< XAccessible > SAL_CALL ScAccessibleCsvControl::getAccessibleAtPoint( const AwtPoint& /* rPoint */ ) 132 { 133 ensureAlive(); 134 return NULL; 135 } 136 137 sal_Bool SAL_CALL ScAccessibleCsvControl::isVisible() 138 { 139 ScUnoGuard aGuard; 140 ensureAlive(); 141 return implGetControl().IsVisible(); 142 } 143 144 void SAL_CALL ScAccessibleCsvControl::grabFocus() 145 { 146 ScUnoGuard aGuard; 147 ensureAlive(); 148 implGetControl().GrabFocus(); 149 } 150 151 152 // events --------------------------------------------------------------------- 153 154 void ScAccessibleCsvControl::SendFocusEvent( bool bFocused ) 155 { 156 if( bFocused ) 157 CommitFocusGained(); 158 else 159 CommitFocusLost(); 160 } 161 162 void ScAccessibleCsvControl::SendCaretEvent() 163 { 164 DBG_ERRORFILE( "ScAccessibleCsvControl::SendCaretEvent - Illegal call" ); 165 } 166 167 void ScAccessibleCsvControl::SendVisibleEvent() 168 { 169 AccessibleEventObject aEvent; 170 aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED; 171 aEvent.Source = Reference< XAccessible >( this ); 172 CommitChange( aEvent ); 173 } 174 175 void ScAccessibleCsvControl::SendSelectionEvent() 176 { 177 AccessibleEventObject aEvent; 178 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED; 179 aEvent.Source = Reference< XAccessible >( this ); 180 CommitChange( aEvent ); 181 } 182 183 void ScAccessibleCsvControl::SendTableUpdateEvent( sal_uInt32 /* nFirstColumn */, sal_uInt32 /* nLastColumn */, bool /* bAllRows */ ) 184 { 185 DBG_ERRORFILE( "ScAccessibleCsvControl::SendTableUpdateEvent - Illegal call" ); 186 } 187 188 void ScAccessibleCsvControl::SendInsertColumnEvent( sal_uInt32 /* nFirstColumn */, sal_uInt32 /* nLastColumn */ ) 189 { 190 DBG_ERRORFILE( "ScAccessibleCsvControl::SendInsertColumnEvent - Illegal call" ); 191 } 192 193 void ScAccessibleCsvControl::SendRemoveColumnEvent( sal_uInt32 /* nFirstColumn */, sal_uInt32 /* nLastColumn */ ) 194 { 195 DBG_ERRORFILE( "ScAccessibleCsvControl::SendRemoveColumnEvent - Illegal call" ); 196 } 197 198 199 // helpers -------------------------------------------------------------------- 200 201 Rectangle ScAccessibleCsvControl::GetBoundingBoxOnScreen() const 202 { 203 ScUnoGuard aGuard; 204 ensureAlive(); 205 return implGetControl().GetWindowExtentsRelative( NULL ); 206 } 207 208 Rectangle ScAccessibleCsvControl::GetBoundingBox() const 209 { 210 ScUnoGuard aGuard; 211 ensureAlive(); 212 return implGetControl().GetWindowExtentsRelative( implGetControl().GetAccessibleParentWindow() ); 213 } 214 215 void ScAccessibleCsvControl::getUuid( Sequence< sal_Int8 >& rSeq ) 216 { 217 ScUnoGuard aGuard; 218 ensureAlive(); 219 if( !rSeq.hasElements() ) 220 { 221 rSeq.realloc( 16 ); 222 rtl_createUuid( reinterpret_cast< sal_uInt8* >( rSeq.getArray() ), NULL, sal_True ); 223 } 224 } 225 226 void ScAccessibleCsvControl::ensureAlive() const 227 { 228 if( !implIsAlive() ) 229 throw DisposedException(); 230 } 231 232 ScCsvControl& ScAccessibleCsvControl::implGetControl() const 233 { 234 DBG_ASSERT( mpControl, "ScAccessibleCsvControl::implGetControl - missing control" ); 235 return *mpControl; 236 } 237 238 Reference< XAccessible > ScAccessibleCsvControl::implGetChildByRole( 239 const Reference< XAccessible >& rxParentObj, sal_uInt16 nRole ) 240 { 241 Reference< XAccessible > xAccObj; 242 if( rxParentObj.is() ) 243 { 244 Reference< XAccessibleContext > xParentCtxt = rxParentObj->getAccessibleContext(); 245 if( xParentCtxt.is() ) 246 { 247 sal_Int32 nCount = xParentCtxt->getAccessibleChildCount(); 248 sal_Int32 nIndex = 0; 249 while( !xAccObj.is() && (nIndex < nCount) ) 250 { 251 Reference< XAccessible > xCurrObj = xParentCtxt->getAccessibleChild( nIndex ); 252 if( xCurrObj.is() ) 253 { 254 Reference< XAccessibleContext > xCurrCtxt = xCurrObj->getAccessibleContext(); 255 if( xCurrCtxt.is() && (xCurrCtxt->getAccessibleRole() == nRole) ) 256 xAccObj = xCurrObj; 257 } 258 ++nIndex; 259 } 260 } 261 } 262 return xAccObj; 263 } 264 265 AccessibleStateSetHelper* ScAccessibleCsvControl::implCreateStateSet() 266 { 267 ScUnoGuard aGuard; 268 AccessibleStateSetHelper* pStateSet = new AccessibleStateSetHelper(); 269 if( implIsAlive() ) 270 { 271 const ScCsvControl& rCtrl = implGetControl(); 272 pStateSet->AddState( AccessibleStateType::OPAQUE ); 273 if( rCtrl.IsEnabled() ) 274 pStateSet->AddState( AccessibleStateType::ENABLED ); 275 if( isShowing() ) 276 pStateSet->AddState( AccessibleStateType::SHOWING ); 277 if( isVisible() ) 278 pStateSet->AddState( AccessibleStateType::VISIBLE ); 279 } 280 else 281 pStateSet->AddState( AccessibleStateType::DEFUNC ); 282 return pStateSet; 283 } 284 285 void ScAccessibleCsvControl::implDispose() 286 { 287 if( implIsAlive() ) 288 { 289 // prevent multiple call of dtor 290 osl_incrementInterlockedCount( &m_refCount ); 291 dispose(); 292 } 293 } 294 295 Point ScAccessibleCsvControl::implGetAbsPos( const Point& rPos ) const 296 { 297 return rPos + implGetControl().GetWindowExtentsRelative( NULL ).TopLeft(); 298 } 299 300 301 // Ruler ====================================================================== 302 303 /** Converts a ruler cursor position to API text index. */ 304 sal_Int32 lcl_GetApiPos( sal_Int32 nRulerPos ) 305 { 306 sal_Int32 nApiPos = nRulerPos; 307 sal_Int32 nStart = (nRulerPos - 1) / 10; 308 sal_Int32 nExp = 1; 309 while( nStart >= nExp ) 310 { 311 nApiPos += nStart - nExp + 1; 312 nExp *= 10; 313 } 314 return ::std::max( nApiPos, static_cast<sal_Int32>(0) ); 315 } 316 317 /** Converts an API text index to a ruler cursor position. */ 318 sal_Int32 lcl_GetRulerPos( sal_Int32 nApiPos ) 319 { 320 sal_Int32 nDiv = 10; 321 sal_Int32 nExp = 10; 322 sal_Int32 nRulerPos = 0; 323 sal_Int32 nApiBase = 0; 324 sal_Int32 nApiLimit = 10; 325 while( nApiPos >= nApiLimit ) 326 { 327 ++nDiv; 328 nRulerPos = nExp; 329 nExp *= 10; 330 nApiBase = nApiLimit; 331 nApiLimit = lcl_GetApiPos( nExp ); 332 } 333 sal_Int32 nRelPos = nApiPos - nApiBase; 334 return nRulerPos + nRelPos / nDiv * 10 + ::std::max( nRelPos % nDiv - nDiv + 10L, 0L ); 335 } 336 337 /** Expands the sequence's size and returns the base index of the new inserted elements. */ 338 inline sal_Int32 lcl_ExpandSequence( Sequence< PropertyValue >& rSeq, sal_Int32 nExp ) 339 { 340 DBG_ASSERT( nExp > 0, "lcl_ExpandSequence - invalid value" ); 341 rSeq.realloc( rSeq.getLength() + nExp ); 342 return rSeq.getLength() - nExp; 343 } 344 345 /** Fills the property value rVal with the specified name and value from the item. */ 346 inline void lcl_FillProperty( PropertyValue& rVal, const OUString& rPropName, const SfxPoolItem& rItem, sal_uInt8 nMID ) 347 { 348 rVal.Name = rPropName; 349 rItem.QueryValue( rVal.Value, nMID ); 350 } 351 352 /** Fills the sequence with all font attributes of rFont. */ 353 void lcl_FillFontAttributes( Sequence< PropertyValue >& rSeq, const Font& rFont ) 354 { 355 SvxFontItem aFontItem( rFont.GetFamily(), rFont.GetName(), rFont.GetStyleName(), rFont.GetPitch(), rFont.GetCharSet(), ATTR_FONT ); 356 SvxFontHeightItem aHeightItem( rFont.GetSize().Height(), 100, ATTR_FONT_HEIGHT ); 357 SvxLanguageItem aLangItem( rFont.GetLanguage(), ATTR_FONT_LANGUAGE ); 358 359 sal_Int32 nIndex = lcl_ExpandSequence( rSeq, 7 ); 360 lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontName" ), aFontItem, MID_FONT_FAMILY_NAME ); 361 lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontFamily" ), aFontItem, MID_FONT_FAMILY ); 362 lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontStyleName" ), aFontItem, MID_FONT_STYLE_NAME ); 363 lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontCharSet" ), aFontItem, MID_FONT_PITCH ); 364 lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharFontPitch" ), aFontItem, MID_FONT_CHAR_SET ); 365 lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharHeight" ), aHeightItem, MID_FONTHEIGHT ); 366 lcl_FillProperty( rSeq[ nIndex++ ], CREATE_OUSTRING( "CharLocale" ), aLangItem, MID_LANG_LOCALE ); 367 } 368 369 370 371 // ---------------------------------------------------------------------------- 372 373 DBG_NAME( ScAccessibleCsvRuler ) 374 375 ScAccessibleCsvRuler::ScAccessibleCsvRuler( ScCsvRuler& rRuler ) : 376 ScAccessibleCsvControl( rRuler.GetAccessibleParentWindow()->GetAccessible(), rRuler, nRulerRole ) 377 { 378 DBG_CTOR( ScAccessibleCsvRuler, NULL ); 379 constructStringBuffer(); 380 } 381 382 ScAccessibleCsvRuler::~ScAccessibleCsvRuler() 383 { 384 DBG_DTOR( ScAccessibleCsvRuler, NULL ); 385 implDispose(); 386 } 387 388 // XAccessibleComponent ----------------------------------------------------- 389 390 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getForeground( ) 391 { 392 ScUnoGuard aGuard; 393 ensureAlive(); 394 return implGetRuler().GetSettings().GetStyleSettings().GetLabelTextColor().GetColor(); 395 } 396 397 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getBackground( ) 398 { 399 ScUnoGuard aGuard; 400 ensureAlive(); 401 return implGetRuler().GetSettings().GetStyleSettings().GetFaceColor().GetColor(); 402 } 403 404 // XAccessibleContext --------------------------------------------------------- 405 406 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getAccessibleChildCount() 407 { 408 ensureAlive(); 409 return 0; 410 } 411 412 Reference< XAccessible > SAL_CALL ScAccessibleCsvRuler::getAccessibleChild( sal_Int32 /* nIndex */ ) 413 { 414 ensureAlive(); 415 throw IndexOutOfBoundsException(); 416 } 417 418 Reference< XAccessibleRelationSet > SAL_CALL ScAccessibleCsvRuler::getAccessibleRelationSet() 419 { 420 ScUnoGuard aGuard; 421 ensureAlive(); 422 AccessibleRelationSetHelper* pRelationSet = new AccessibleRelationSetHelper(); 423 Reference< XAccessible > xAccObj = implGetChildByRole( getAccessibleParent(), nGridRole ); 424 if( xAccObj.is() ) 425 { 426 Sequence< Reference< XInterface > > aSeq( 1 ); 427 aSeq[ 0 ] = xAccObj; 428 pRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::CONTROLLER_FOR, aSeq ) ); 429 } 430 return pRelationSet; 431 } 432 433 Reference< XAccessibleStateSet > SAL_CALL ScAccessibleCsvRuler::getAccessibleStateSet() 434 { 435 ScUnoGuard aGuard; 436 AccessibleStateSetHelper* pStateSet = implCreateStateSet(); 437 if( implIsAlive() ) 438 { 439 pStateSet->AddState( AccessibleStateType::FOCUSABLE ); 440 pStateSet->AddState( AccessibleStateType::SINGLE_LINE ); 441 if( implGetRuler().HasFocus() ) 442 pStateSet->AddState( AccessibleStateType::FOCUSED ); 443 } 444 return pStateSet; 445 } 446 447 448 // XAccessibleText ------------------------------------------------------------ 449 450 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getCaretPosition() 451 { 452 ScUnoGuard aGuard; 453 ensureAlive(); 454 return lcl_GetApiPos( implGetRuler().GetRulerCursorPos() ); 455 } 456 457 sal_Bool SAL_CALL ScAccessibleCsvRuler::setCaretPosition( sal_Int32 nIndex ) 458 { 459 ScUnoGuard aGuard; 460 ensureAlive(); 461 ensureValidIndex( nIndex ); 462 ScCsvRuler& rRuler = implGetRuler(); 463 sal_Int32 nOldCursor = rRuler.GetRulerCursorPos(); 464 rRuler.Execute( CSVCMD_MOVERULERCURSOR, lcl_GetRulerPos( nIndex ) ); 465 return rRuler.GetRulerCursorPos() != nOldCursor; 466 } 467 468 sal_Unicode SAL_CALL ScAccessibleCsvRuler::getCharacter( sal_Int32 nIndex ) 469 { 470 ScUnoGuard aGuard; 471 ensureAlive(); 472 ensureValidIndex( nIndex ); 473 return maBuffer.charAt( nIndex ); 474 } 475 476 Sequence< PropertyValue > SAL_CALL ScAccessibleCsvRuler::getCharacterAttributes( sal_Int32 nIndex, 477 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& /* aRequestedAttributes */ ) 478 { 479 ScUnoGuard aGuard; 480 ensureAlive(); 481 ensureValidIndexWithEnd( nIndex ); 482 Sequence< PropertyValue > aSeq; 483 lcl_FillFontAttributes( aSeq, implGetRuler().GetFont() ); 484 //! TODO split attribute: waiting for #102221# 485 // if( implHasSplit( nIndex ) ) 486 // { 487 // sal_Int32 nIndex = lcl_ExpandSequence( aSeq, 1 ); 488 // aSeq[ nIndex ].Name = CREATE_OUSTRING( "..." ); 489 // aSeq[ nIndex ].Value <<= ...; 490 // } 491 return aSeq; 492 } 493 494 ScAccessibleCsvRuler::AwtRectangle SAL_CALL ScAccessibleCsvRuler::getCharacterBounds( sal_Int32 nIndex ) 495 { 496 ScUnoGuard aGuard; 497 ensureAlive(); 498 ensureValidIndexWithEnd( nIndex ); 499 ScCsvRuler& rRuler = implGetRuler(); 500 Point aPos( rRuler.GetX( lcl_GetRulerPos( nIndex ) ) - rRuler.GetCharWidth() / 2, 0 ); 501 AwtRectangle aRect( aPos.X(), aPos.Y(), rRuler.GetCharWidth(), rRuler.GetSizePixel().Height() ); 502 // #107054# do not return rectangle out of window 503 sal_Int32 nWidth = rRuler.GetOutputSizePixel().Width(); 504 if( aRect.X >= nWidth ) 505 throw IndexOutOfBoundsException(); 506 if( aRect.X + aRect.Width > nWidth ) 507 aRect.Width = nWidth - aRect.X; 508 return aRect; 509 } 510 511 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getCharacterCount() 512 { 513 ScUnoGuard aGuard; 514 ensureAlive(); 515 return implGetTextLength(); 516 } 517 518 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getIndexAtPoint( const AwtPoint& rPoint ) 519 { 520 ScUnoGuard aGuard; 521 ensureAlive(); 522 ScCsvRuler& rRuler = implGetRuler(); 523 // #107054# use object's coordinate system, convert to API position 524 return lcl_GetApiPos( ::std::min( ::std::max( rRuler.GetPosFromX( rPoint.X ), static_cast<sal_Int32>(0) ), rRuler.GetPosCount() ) ); 525 } 526 527 OUString SAL_CALL ScAccessibleCsvRuler::getSelectedText() 528 { 529 ensureAlive(); 530 return OUString(); 531 } 532 533 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getSelectionStart() 534 { 535 ensureAlive(); 536 return -1; 537 } 538 539 sal_Int32 SAL_CALL ScAccessibleCsvRuler::getSelectionEnd() 540 { 541 ensureAlive(); 542 return -1; 543 } 544 545 sal_Bool SAL_CALL ScAccessibleCsvRuler::setSelection( sal_Int32 /* nStartIndex */, sal_Int32 /* nEndIndex */ ) 546 { 547 ensureAlive(); 548 return sal_False; 549 } 550 551 OUString SAL_CALL ScAccessibleCsvRuler::getText() 552 { 553 ScUnoGuard aGuard; 554 ensureAlive(); 555 return OUString( maBuffer.getStr(), implGetTextLength() ); 556 } 557 558 OUString SAL_CALL ScAccessibleCsvRuler::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) 559 { 560 ScUnoGuard aGuard; 561 ensureAlive(); 562 ensureValidRange( nStartIndex, nEndIndex ); 563 return OUString( maBuffer.getStr() + nStartIndex, nEndIndex - nStartIndex ); 564 } 565 566 TextSegment SAL_CALL ScAccessibleCsvRuler::getTextAtIndex( sal_Int32 nIndex, sal_Int16 nTextType ) 567 { 568 ScUnoGuard aGuard; 569 ensureAlive(); 570 571 TextSegment aResult; 572 aResult.SegmentStart = -1; 573 aResult.SegmentEnd = -1; 574 575 if( (nIndex == implGetTextLength()) && (nTextType != AccessibleTextType::LINE) ) 576 return aResult; 577 578 ensureValidIndex( nIndex ); 579 580 OUStringBuffer aResultText; // will be assigned to aResult.SegmentText below 581 sal_Int32 nRulerPos = lcl_GetRulerPos( nIndex ); 582 583 switch( nTextType ) 584 { 585 // single character 586 case AccessibleTextType::CHARACTER: 587 { 588 aResult.SegmentStart = nIndex; 589 aResultText.append( maBuffer.charAt( nIndex ) ); 590 } 591 break; 592 593 // entire number or single dot/line 594 case AccessibleTextType::WORD: 595 case AccessibleTextType::GLYPH: 596 aResult.SegmentStart = nIndex; 597 if( nRulerPos % 10 ) 598 aResultText.append( maBuffer.charAt( nIndex ) ); 599 else 600 aResultText.append( nRulerPos ); // string representation of sal_Int32!!! 601 break; 602 603 // entire text 604 case AccessibleTextType::SENTENCE: 605 case AccessibleTextType::PARAGRAPH: 606 case AccessibleTextType::LINE: 607 aResult.SegmentStart = 0; 608 aResultText.append( maBuffer.getStr(), implGetTextLength() ); 609 break; 610 611 // equal-formatted text 612 case AccessibleTextType::ATTRIBUTE_RUN: 613 { 614 sal_Int32 nFirstIndex = implGetFirstEqualFormatted( nIndex ); 615 sal_Int32 nLastIndex = implGetLastEqualFormatted( nIndex ); 616 aResult.SegmentStart = nFirstIndex; 617 aResultText.append( maBuffer.getStr() + nFirstIndex, nLastIndex - nFirstIndex + 1 ); 618 } 619 break; 620 621 default: 622 throw RuntimeException(); 623 } 624 625 aResult.SegmentText = aResultText.makeStringAndClear(); 626 aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength(); 627 return aResult; 628 } 629 630 TextSegment SAL_CALL ScAccessibleCsvRuler::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 nTextType ) 631 { 632 ScUnoGuard aGuard; 633 ensureAlive(); 634 ensureValidIndexWithEnd( nIndex ); 635 636 TextSegment aResult; 637 aResult.SegmentStart = -1; 638 aResult.SegmentEnd = -1; 639 640 sal_Int32 nRulerPos = lcl_GetRulerPos( nIndex ); 641 642 switch( nTextType ) 643 { 644 // single character 645 case AccessibleTextType::CHARACTER: 646 if( nIndex > 0 ) 647 aResult = getTextAtIndex( nIndex - 1, nTextType ); 648 // else empty 649 break; 650 651 // entire number or single dot/line 652 case AccessibleTextType::WORD: 653 case AccessibleTextType::GLYPH: 654 if( nRulerPos > 0 ) 655 aResult = getTextAtIndex( lcl_GetApiPos( nRulerPos - 1 ), nTextType ); 656 // else empty 657 break; 658 659 // entire text 660 case AccessibleTextType::SENTENCE: 661 case AccessibleTextType::PARAGRAPH: 662 case AccessibleTextType::LINE: 663 // empty 664 break; 665 666 // equal-formatted text 667 case AccessibleTextType::ATTRIBUTE_RUN: 668 { 669 sal_Int32 nFirstIndex = implGetFirstEqualFormatted( nIndex ); 670 if( nFirstIndex > 0 ) 671 aResult = getTextAtIndex( nFirstIndex - 1, nTextType ); 672 // else empty 673 } 674 break; 675 676 default: 677 throw RuntimeException(); 678 } 679 return aResult; 680 } 681 682 TextSegment SAL_CALL ScAccessibleCsvRuler::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 nTextType ) 683 { 684 ScUnoGuard aGuard; 685 ensureAlive(); 686 ensureValidIndexWithEnd( nIndex ); 687 688 TextSegment aResult; 689 aResult.SegmentStart = -1; 690 aResult.SegmentEnd = -1; 691 692 sal_Int32 nRulerPos = lcl_GetRulerPos( nIndex ); 693 sal_Int32 nLastValid = implGetTextLength(); 694 695 switch( nTextType ) 696 { 697 // single character 698 case AccessibleTextType::CHARACTER: 699 if( nIndex < nLastValid ) 700 aResult = getTextAtIndex( nIndex + 1, nTextType ); 701 // else empty 702 break; 703 704 // entire number or single dot/line 705 case AccessibleTextType::WORD: 706 case AccessibleTextType::GLYPH: 707 if( nRulerPos < implGetRuler().GetPosCount() ) 708 aResult = getTextAtIndex( lcl_GetApiPos( nRulerPos + 1 ), nTextType ); 709 // else empty 710 break; 711 712 // entire text 713 case AccessibleTextType::SENTENCE: 714 case AccessibleTextType::PARAGRAPH: 715 case AccessibleTextType::LINE: 716 // empty 717 break; 718 719 // equal-formatted text 720 case AccessibleTextType::ATTRIBUTE_RUN: 721 { 722 sal_Int32 nLastIndex = implGetLastEqualFormatted( nIndex ); 723 if( nLastIndex < nLastValid ) 724 aResult = getTextAtIndex( nLastIndex + 1, nTextType ); 725 // else empty 726 } 727 break; 728 729 default: 730 throw RuntimeException(); 731 } 732 return aResult; 733 } 734 735 sal_Bool SAL_CALL ScAccessibleCsvRuler::copyText( sal_Int32 /* nStartIndex */, sal_Int32 /* nEndIndex */ ) 736 { 737 ensureAlive(); 738 return sal_False; 739 } 740 741 742 // XInterface ----------------------------------------------------------------- 743 744 Any SAL_CALL ScAccessibleCsvRuler::queryInterface( const ::com::sun::star::uno::Type& rType ) 745 { 746 Any aAny( ScAccessibleCsvRulerImpl::queryInterface( rType ) ); 747 return aAny.hasValue() ? aAny : ScAccessibleCsvControl::queryInterface( rType ); 748 } 749 750 void SAL_CALL ScAccessibleCsvRuler::acquire() throw () 751 { 752 ScAccessibleCsvControl::acquire(); 753 } 754 755 void SAL_CALL ScAccessibleCsvRuler::release() throw () 756 { 757 ScAccessibleCsvControl::release(); 758 } 759 760 761 // XServiceInfo --------------------------------------------------------------- 762 763 OUString SAL_CALL ScAccessibleCsvRuler::getImplementationName() 764 { 765 return CREATE_OUSTRING( RULER_IMPL_NAME ); 766 } 767 768 769 // XTypeProvider -------------------------------------------------------------- 770 771 Sequence< ::com::sun::star::uno::Type > SAL_CALL ScAccessibleCsvRuler::getTypes() 772 { 773 Sequence< ::com::sun::star::uno::Type > aSeq( 1 ); 774 aSeq[ 0 ] = getCppuType( static_cast< const Reference< XAccessibleText >* >( NULL ) ); 775 return ::comphelper::concatSequences( ScAccessibleCsvControl::getTypes(), aSeq ); 776 } 777 778 Sequence< sal_Int8 > SAL_CALL ScAccessibleCsvRuler::getImplementationId() 779 { 780 static Sequence< sal_Int8 > aSeq; 781 getUuid( aSeq ); 782 return aSeq; 783 } 784 785 786 // events --------------------------------------------------------------------- 787 788 void ScAccessibleCsvRuler::SendCaretEvent() 789 { 790 sal_Int32 nPos = implGetRuler().GetRulerCursorPos(); 791 if( nPos != CSV_POS_INVALID ) 792 { 793 AccessibleEventObject aEvent; 794 aEvent.EventId = AccessibleEventId::CARET_CHANGED; 795 aEvent.Source = Reference< XAccessible >( this ); 796 aEvent.NewValue <<= nPos; 797 CommitChange( aEvent ); 798 } 799 } 800 801 802 // helpers -------------------------------------------------------------------- 803 804 OUString SAL_CALL ScAccessibleCsvRuler::createAccessibleName() 805 { 806 return String( ScResId( STR_ACC_CSVRULER_NAME ) ); 807 } 808 809 OUString SAL_CALL ScAccessibleCsvRuler::createAccessibleDescription() 810 { 811 return String( ScResId( STR_ACC_CSVRULER_DESCR ) ); 812 } 813 814 void ScAccessibleCsvRuler::ensureValidIndex( sal_Int32 nIndex ) const 815 { 816 if( (nIndex < 0) || (nIndex >= implGetTextLength()) ) 817 throw IndexOutOfBoundsException(); 818 } 819 820 void ScAccessibleCsvRuler::ensureValidIndexWithEnd( sal_Int32 nIndex ) const 821 { 822 if( (nIndex < 0) || (nIndex > implGetTextLength()) ) 823 throw IndexOutOfBoundsException(); 824 } 825 826 void ScAccessibleCsvRuler::ensureValidRange( sal_Int32& rnStartIndex, sal_Int32& rnEndIndex ) const 827 { 828 if( rnStartIndex > rnEndIndex ) 829 ::std::swap( rnStartIndex, rnEndIndex ); 830 if( (rnStartIndex < 0) || (rnEndIndex > implGetTextLength()) ) 831 throw IndexOutOfBoundsException(); 832 } 833 834 ScCsvRuler& ScAccessibleCsvRuler::implGetRuler() const 835 { 836 return static_cast< ScCsvRuler& >( implGetControl() ); 837 } 838 839 void ScAccessibleCsvRuler::constructStringBuffer() 840 { 841 ScUnoGuard aGuard; 842 ensureAlive(); 843 // extend existing string buffer to new ruler size 844 sal_Int32 nRulerCount = implGetRuler().GetPosCount(); 845 sal_Int32 nRulerPos = lcl_GetRulerPos( maBuffer.getLength() ); 846 for( ; nRulerPos <= nRulerCount; ++nRulerPos ) // include last position 847 { 848 switch( nRulerPos % 10 ) 849 { 850 case 0: maBuffer.append( nRulerPos ); break; 851 case 5: maBuffer.append( cRulerLine ); break; 852 default: maBuffer.append( cRulerDot ); 853 } 854 } 855 } 856 857 sal_Int32 ScAccessibleCsvRuler::implGetTextLength() const 858 { 859 return lcl_GetApiPos( implGetRuler().GetPosCount() + 1 ); 860 } 861 862 bool ScAccessibleCsvRuler::implHasSplit( sal_Int32 nApiPos ) 863 { 864 sal_Int32 nRulerPos = lcl_GetRulerPos( nApiPos ); 865 return implGetRuler().HasSplit( nRulerPos ) && (nApiPos == lcl_GetApiPos( nRulerPos )); 866 } 867 868 sal_Int32 ScAccessibleCsvRuler::implGetFirstEqualFormatted( sal_Int32 nApiPos ) 869 { 870 bool bSplit = implHasSplit( nApiPos ); 871 while( (nApiPos > 0) && (implHasSplit( nApiPos - 1 ) == bSplit) ) 872 --nApiPos; 873 return nApiPos; 874 } 875 876 sal_Int32 ScAccessibleCsvRuler::implGetLastEqualFormatted( sal_Int32 nApiPos ) 877 { 878 bool bSplit = implHasSplit( nApiPos ); 879 sal_Int32 nLength = implGetTextLength(); 880 while( (nApiPos < nLength - 1) && (implHasSplit( nApiPos + 1 ) == bSplit) ) 881 ++nApiPos; 882 return nApiPos; 883 } 884 885 886 // Grid ======================================================================= 887 888 /** Converts a grid columnm index to an API column index. */ 889 inline sal_Int32 lcl_GetApiColumn( sal_uInt32 nGridColumn ) 890 { 891 return (nGridColumn != CSV_COLUMN_HEADER) ? static_cast< sal_Int32 >( nGridColumn + 1 ) : 0; 892 } 893 894 /** Converts an API columnm index to a ScCsvGrid column index. */ 895 inline sal_uInt32 lcl_GetGridColumn( sal_Int32 nApiColumn ) 896 { 897 return (nApiColumn > 0) ? static_cast< sal_uInt32 >( nApiColumn - 1 ) : CSV_COLUMN_HEADER; 898 } 899 900 901 // ---------------------------------------------------------------------------- 902 903 DBG_NAME( ScAccessibleCsvGrid ) 904 905 ScAccessibleCsvGrid::ScAccessibleCsvGrid( ScCsvGrid& rGrid ) : 906 ScAccessibleCsvControl( rGrid.GetAccessibleParentWindow()->GetAccessible(), rGrid, nGridRole ) 907 { 908 DBG_CTOR( ScAccessibleCsvGrid, NULL ); 909 } 910 911 ScAccessibleCsvGrid::~ScAccessibleCsvGrid() 912 { 913 DBG_DTOR( ScAccessibleCsvGrid, NULL ); 914 implDispose(); 915 } 916 917 918 // XAccessibleComponent ------------------------------------------------------- 919 920 Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleAtPoint( const AwtPoint& rPoint ) 921 { 922 Reference< XAccessible > xRet; 923 if( containsPoint( rPoint ) ) 924 { 925 ScUnoGuard aGuard; 926 ensureAlive(); 927 928 const ScCsvGrid& rGrid = implGetGrid(); 929 // #102679#; use <= instead of <, because the offset is the size and not the point 930 sal_Int32 nColumn = ((rGrid.GetFirstX() <= rPoint.X) && (rPoint.X <= rGrid.GetLastX())) ? 931 lcl_GetApiColumn( rGrid.GetColumnFromX( rPoint.X ) ) : 0; 932 sal_Int32 nRow = (rPoint.Y >= rGrid.GetHdrHeight()) ? 933 (rGrid.GetLineFromY( rPoint.Y ) - rGrid.GetFirstVisLine() + 1) : 0; 934 xRet = implCreateCellObj( nRow, nColumn ); 935 } 936 return xRet; 937 } 938 939 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getForeground( ) 940 { 941 ScUnoGuard aGuard; 942 ensureAlive(); 943 return implGetGrid().GetSettings().GetStyleSettings().GetButtonTextColor().GetColor(); 944 } 945 946 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getBackground( ) 947 { 948 ScUnoGuard aGuard; 949 ensureAlive(); 950 return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor; 951 } 952 953 // XAccessibleContext --------------------------------------------------------- 954 955 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleChildCount() 956 { 957 ScUnoGuard aGuard; 958 ensureAlive(); 959 return implGetCellCount(); 960 } 961 962 Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleChild( sal_Int32 nIndex ) 963 { 964 ScUnoGuard aGuard; 965 ensureAlive(); 966 ensureValidIndex( nIndex ); 967 return implCreateCellObj( implGetRow( nIndex ), implGetColumn( nIndex ) ); 968 } 969 970 Reference< XAccessibleRelationSet > SAL_CALL ScAccessibleCsvGrid::getAccessibleRelationSet() 971 { 972 ScUnoGuard aGuard; 973 ensureAlive(); 974 AccessibleRelationSetHelper* pRelationSet = new AccessibleRelationSetHelper(); 975 Reference< XAccessible > xAccObj = implGetChildByRole( getAccessibleParent(), nRulerRole ); 976 if( xAccObj.is() ) 977 { 978 Sequence< Reference< XInterface > > aSeq( 1 ); 979 aSeq[ 0 ] = xAccObj; 980 pRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::CONTROLLED_BY, aSeq ) ); 981 } 982 return pRelationSet; 983 } 984 985 Reference< XAccessibleStateSet > SAL_CALL ScAccessibleCsvGrid::getAccessibleStateSet() 986 { 987 ScUnoGuard aGuard; 988 AccessibleStateSetHelper* pStateSet = implCreateStateSet(); 989 if( implIsAlive() ) 990 { 991 pStateSet->AddState( AccessibleStateType::FOCUSABLE ); 992 pStateSet->AddState( AccessibleStateType::MULTI_SELECTABLE ); 993 pStateSet->AddState( AccessibleStateType::MANAGES_DESCENDANTS ); 994 if( implGetGrid().HasFocus() ) 995 pStateSet->AddState( AccessibleStateType::FOCUSED ); 996 } 997 else 998 pStateSet->AddState( AccessibleStateType::DEFUNC ); 999 return pStateSet; 1000 } 1001 1002 1003 // XAccessibleTable ----------------------------------------------------------- 1004 1005 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleRowCount() 1006 { 1007 ScUnoGuard aGuard; 1008 ensureAlive(); 1009 return implGetRowCount(); 1010 } 1011 1012 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnCount() 1013 { 1014 ScUnoGuard aGuard; 1015 ensureAlive(); 1016 return implGetColumnCount(); 1017 } 1018 1019 OUString SAL_CALL ScAccessibleCsvGrid::getAccessibleRowDescription( sal_Int32 nRow ) 1020 { 1021 ScUnoGuard aGuard; 1022 ensureAlive(); 1023 ensureValidPosition( nRow, 0 ); 1024 return implGetCellText( nRow, 0 ); 1025 } 1026 1027 OUString SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnDescription( sal_Int32 nColumn ) 1028 { 1029 ScUnoGuard aGuard; 1030 ensureAlive(); 1031 ensureValidPosition( 0, nColumn ); 1032 return implGetCellText( 0, nColumn ); 1033 } 1034 1035 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleRowExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) 1036 { 1037 ensureAlive(); 1038 ensureValidPosition( nRow, nColumn ); 1039 return 1; 1040 } 1041 1042 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnExtentAt( sal_Int32 nRow, sal_Int32 nColumn ) 1043 { 1044 ensureAlive(); 1045 ensureValidPosition( nRow, nColumn ); 1046 return 1; 1047 } 1048 1049 Reference< XAccessibleTable > SAL_CALL ScAccessibleCsvGrid::getAccessibleRowHeaders() 1050 { 1051 ensureAlive(); 1052 return NULL; 1053 } 1054 1055 Reference< XAccessibleTable > SAL_CALL ScAccessibleCsvGrid::getAccessibleColumnHeaders() 1056 { 1057 ensureAlive(); 1058 return NULL; 1059 } 1060 1061 Sequence< sal_Int32 > SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleRows() 1062 { 1063 ensureAlive(); 1064 return Sequence< sal_Int32 >(); 1065 } 1066 1067 Sequence< sal_Int32 > SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleColumns() 1068 { 1069 ScUnoGuard aGuard; 1070 ensureAlive(); 1071 1072 ScCsvGrid& rGrid = implGetGrid(); 1073 Sequence< sal_Int32 > aSeq( implGetColumnCount() ); 1074 1075 sal_Int32 nSeqIx = 0; 1076 sal_uInt32 nColIx = rGrid.GetFirstSelected(); 1077 for( ; nColIx != CSV_COLUMN_INVALID; ++nSeqIx, nColIx = rGrid.GetNextSelected( nColIx ) ) 1078 aSeq[ nSeqIx ] = lcl_GetApiColumn( nColIx ); 1079 1080 aSeq.realloc( nSeqIx ); 1081 return aSeq; 1082 } 1083 1084 sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleRowSelected( sal_Int32 /* nRow */ ) 1085 { 1086 ensureAlive(); 1087 return sal_False; 1088 } 1089 1090 sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleColumnSelected( sal_Int32 nColumn ) 1091 { 1092 ScUnoGuard aGuard; 1093 ensureAlive(); 1094 ensureValidIndex( nColumn ); 1095 return implIsColumnSelected( nColumn ); 1096 } 1097 1098 Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn ) 1099 { 1100 ScUnoGuard aGuard; 1101 ensureAlive(); 1102 ensureValidPosition( nRow, nColumn ); 1103 return implCreateCellObj( nRow, nColumn ); 1104 } 1105 1106 Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleCaption() 1107 { 1108 ensureAlive(); 1109 return NULL; 1110 } 1111 1112 Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getAccessibleSummary() 1113 { 1114 ensureAlive(); 1115 return NULL; 1116 } 1117 1118 sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleSelected( sal_Int32 /* nRow */, sal_Int32 nColumn ) 1119 { 1120 return isAccessibleColumnSelected( nColumn ); 1121 } 1122 1123 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn ) 1124 { 1125 ScUnoGuard aGuard; 1126 ensureAlive(); 1127 ensureValidPosition( nRow, nColumn ); 1128 return implGetIndex( nRow, nColumn ); 1129 } 1130 1131 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleRow( sal_Int32 nChildIndex ) 1132 { 1133 ScUnoGuard aGuard; 1134 ensureAlive(); 1135 ensureValidIndex( nChildIndex ); 1136 return implGetRow( nChildIndex ); 1137 } 1138 1139 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getAccessibleColumn( sal_Int32 nChildIndex ) 1140 { 1141 ScUnoGuard aGuard; 1142 ensureAlive(); 1143 ensureValidIndex( nChildIndex ); 1144 return implGetColumn( nChildIndex ); 1145 } 1146 1147 1148 // XAccessibleSelection ------------------------------------------------------- 1149 1150 void SAL_CALL ScAccessibleCsvGrid::selectAccessibleChild( sal_Int32 nChildIndex ) 1151 { 1152 ScUnoGuard aGuard; 1153 ensureAlive(); 1154 ensureValidIndex( nChildIndex ); 1155 sal_Int32 nColumn = implGetColumn( nChildIndex ); 1156 if( nChildIndex == 0 ) 1157 implGetGrid().SelectAll(); 1158 else 1159 implSelectColumn( nColumn, true ); 1160 } 1161 1162 sal_Bool SAL_CALL ScAccessibleCsvGrid::isAccessibleChildSelected( sal_Int32 nChildIndex ) 1163 { 1164 ScUnoGuard aGuard; 1165 ensureAlive(); 1166 ensureValidIndex( nChildIndex ); 1167 sal_Int32 nColumn = implGetColumn( nChildIndex ); 1168 return implIsColumnSelected( nColumn ); 1169 } 1170 1171 void SAL_CALL ScAccessibleCsvGrid::clearAccessibleSelection() 1172 { 1173 ScUnoGuard aGuard; 1174 ensureAlive(); 1175 implGetGrid().SelectAll( false ); 1176 } 1177 1178 void SAL_CALL ScAccessibleCsvGrid::selectAllAccessibleChildren() 1179 { 1180 selectAccessibleChild( 0 ); 1181 } 1182 1183 sal_Int32 SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleChildCount() 1184 { 1185 ScUnoGuard aGuard; 1186 ensureAlive(); 1187 return implGetRowCount() * implGetSelColumnCount(); 1188 } 1189 1190 Reference< XAccessible > SAL_CALL ScAccessibleCsvGrid::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) 1191 { 1192 ScUnoGuard aGuard; 1193 ensureAlive(); 1194 sal_Int32 nColumns = implGetSelColumnCount(); 1195 if( nColumns == 0 ) 1196 throw IndexOutOfBoundsException(); 1197 1198 sal_Int32 nRow = nSelectedChildIndex / nColumns; 1199 sal_Int32 nColumn = implGetSelColumn( nSelectedChildIndex % nColumns ); 1200 return getAccessibleCellAt( nRow, nColumn ); 1201 } 1202 1203 void SAL_CALL ScAccessibleCsvGrid::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) 1204 { 1205 ScUnoGuard aGuard; 1206 ensureAlive(); 1207 sal_Int32 nColumns = implGetSelColumnCount(); 1208 if( nColumns == 0 ) 1209 throw IndexOutOfBoundsException(); 1210 1211 sal_Int32 nColumn = implGetSelColumn( nSelectedChildIndex % nColumns ); 1212 ensureValidPosition( nSelectedChildIndex / nColumns, nColumn ); 1213 if( nColumn > 0 ) 1214 implSelectColumn( nColumn, false ); 1215 } 1216 1217 1218 // XInterface ----------------------------------------------------------------- 1219 1220 Any SAL_CALL ScAccessibleCsvGrid::queryInterface( const ::com::sun::star::uno::Type& rType ) 1221 { 1222 Any aAny( ScAccessibleCsvGridImpl::queryInterface( rType ) ); 1223 return aAny.hasValue() ? aAny : ScAccessibleCsvControl::queryInterface( rType ); 1224 } 1225 1226 void SAL_CALL ScAccessibleCsvGrid::acquire() throw () 1227 { 1228 ScAccessibleCsvControl::acquire(); 1229 } 1230 1231 void SAL_CALL ScAccessibleCsvGrid::release() throw () 1232 { 1233 ScAccessibleCsvControl::release(); 1234 } 1235 1236 1237 // XServiceInfo --------------------------------------------------------------- 1238 1239 OUString SAL_CALL ScAccessibleCsvGrid::getImplementationName() 1240 { 1241 return CREATE_OUSTRING( GRID_IMPL_NAME ); 1242 } 1243 1244 1245 // XTypeProvider -------------------------------------------------------------- 1246 1247 Sequence< ::com::sun::star::uno::Type > SAL_CALL ScAccessibleCsvGrid::getTypes() 1248 { 1249 Sequence< ::com::sun::star::uno::Type > aSeq( 2 ); 1250 aSeq[ 0 ] = getCppuType( static_cast< const Reference< XAccessibleTable >* >( NULL ) ); 1251 aSeq[ 1 ] = getCppuType( static_cast< const Reference< XAccessibleSelection >* >( NULL ) ); 1252 return ::comphelper::concatSequences( ScAccessibleCsvControl::getTypes(), aSeq ); 1253 } 1254 1255 Sequence< sal_Int8 > SAL_CALL ScAccessibleCsvGrid::getImplementationId() 1256 { 1257 static Sequence< sal_Int8 > aSeq; 1258 getUuid( aSeq ); 1259 return aSeq; 1260 } 1261 1262 1263 // events --------------------------------------------------------------------- 1264 1265 void ScAccessibleCsvGrid::SendFocusEvent( bool bFocused ) 1266 { 1267 ScAccessibleCsvControl::SendFocusEvent( bFocused ); 1268 1269 AccessibleEventObject aEvent; 1270 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED; 1271 aEvent.Source = Reference< XAccessible >( this ); 1272 (bFocused ? aEvent.NewValue : aEvent.OldValue) <<= 1273 getAccessibleCellAt( 0, lcl_GetApiColumn( implGetGrid().GetFocusColumn() ) ); 1274 CommitChange( aEvent ); 1275 } 1276 1277 void ScAccessibleCsvGrid::SendTableUpdateEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn, bool bAllRows ) 1278 { 1279 if( nFirstColumn <= nLastColumn ) 1280 { 1281 AccessibleTableModelChange aModelChange( 1282 AccessibleTableModelChangeType::UPDATE, 0, bAllRows ? implGetRowCount() - 1 : 0, 1283 lcl_GetApiColumn( nFirstColumn ), lcl_GetApiColumn( nLastColumn ) ); 1284 AccessibleEventObject aEvent; 1285 aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED; 1286 aEvent.Source = Reference< XAccessible >( this ); 1287 aEvent.NewValue <<= aModelChange; 1288 CommitChange( aEvent ); 1289 } 1290 } 1291 1292 void ScAccessibleCsvGrid::SendInsertColumnEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn ) 1293 { 1294 if( nFirstColumn <= nLastColumn ) 1295 { 1296 AccessibleTableModelChange aModelChange( 1297 AccessibleTableModelChangeType::INSERT, 0, implGetRowCount() - 1, 1298 lcl_GetApiColumn( nFirstColumn ), lcl_GetApiColumn( nLastColumn ) ); 1299 AccessibleEventObject aEvent; 1300 aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED; 1301 aEvent.Source = Reference< XAccessible >( this ); 1302 aEvent.NewValue <<= aModelChange; 1303 CommitChange( aEvent ); 1304 } 1305 } 1306 1307 void ScAccessibleCsvGrid::SendRemoveColumnEvent( sal_uInt32 nFirstColumn, sal_uInt32 nLastColumn ) 1308 { 1309 if( nFirstColumn <= nLastColumn ) 1310 { 1311 AccessibleTableModelChange aModelChange( 1312 AccessibleTableModelChangeType::DELETE, 0, implGetRowCount() - 1, 1313 lcl_GetApiColumn( nFirstColumn ), lcl_GetApiColumn( nLastColumn ) ); 1314 AccessibleEventObject aEvent; 1315 aEvent.EventId = AccessibleEventId::TABLE_MODEL_CHANGED; 1316 aEvent.Source = Reference< XAccessible >( this ); 1317 aEvent.NewValue <<= aModelChange; 1318 CommitChange( aEvent ); 1319 } 1320 } 1321 1322 1323 // helpers -------------------------------------------------------------------- 1324 1325 OUString SAL_CALL ScAccessibleCsvGrid::createAccessibleName() 1326 { 1327 return String( ScResId( STR_ACC_CSVGRID_NAME ) ); 1328 } 1329 1330 OUString SAL_CALL ScAccessibleCsvGrid::createAccessibleDescription() 1331 { 1332 return String( ScResId( STR_ACC_CSVGRID_DESCR ) ); 1333 } 1334 1335 void ScAccessibleCsvGrid::ensureValidIndex( sal_Int32 nIndex ) const 1336 { 1337 if( (nIndex < 0) || (nIndex >= implGetCellCount()) ) 1338 throw IndexOutOfBoundsException(); 1339 } 1340 1341 void ScAccessibleCsvGrid::ensureValidPosition( sal_Int32 nRow, sal_Int32 nColumn ) const 1342 { 1343 if( (nRow < 0) || (nRow >= implGetRowCount()) || (nColumn < 0) || (nColumn >= implGetColumnCount()) ) 1344 throw IndexOutOfBoundsException(); 1345 } 1346 1347 ScCsvGrid& ScAccessibleCsvGrid::implGetGrid() const 1348 { 1349 return static_cast< ScCsvGrid& >( implGetControl() ); 1350 } 1351 1352 bool ScAccessibleCsvGrid::implIsColumnSelected( sal_Int32 nColumn ) const 1353 { 1354 return (nColumn > 0) && implGetGrid().IsSelected( lcl_GetGridColumn( nColumn ) ); 1355 } 1356 1357 void ScAccessibleCsvGrid::implSelectColumn( sal_Int32 nColumn, bool bSelect ) 1358 { 1359 if( nColumn > 0 ) 1360 implGetGrid().Select( lcl_GetGridColumn( nColumn ), bSelect ); 1361 } 1362 1363 sal_Int32 ScAccessibleCsvGrid::implGetRowCount() const 1364 { 1365 return static_cast< sal_Int32 >( implGetGrid().GetLastVisLine() - implGetGrid().GetFirstVisLine() + 2 ); 1366 } 1367 1368 sal_Int32 ScAccessibleCsvGrid::implGetColumnCount() const 1369 { 1370 return static_cast< sal_Int32 >( implGetGrid().GetColumnCount() + 1 ); 1371 } 1372 1373 sal_Int32 ScAccessibleCsvGrid::implGetSelColumnCount() const 1374 { 1375 ScCsvGrid& rGrid = implGetGrid(); 1376 sal_Int32 nCount = 0; 1377 for( sal_uInt32 nColIx = rGrid.GetFirstSelected(); nColIx != CSV_COLUMN_INVALID; nColIx = rGrid.GetNextSelected( nColIx ) ) 1378 ++nCount; 1379 return nCount; 1380 } 1381 1382 sal_Int32 ScAccessibleCsvGrid::implGetSelColumn( sal_Int32 nSelColumn ) const 1383 { 1384 ScCsvGrid& rGrid = implGetGrid(); 1385 sal_Int32 nColumn = 0; 1386 for( sal_uInt32 nColIx = rGrid.GetFirstSelected(); nColIx != CSV_COLUMN_INVALID; nColIx = rGrid.GetNextSelected( nColIx ) ) 1387 { 1388 if( nColumn == nSelColumn ) 1389 return static_cast< sal_Int32 >( nColIx + 1 ); 1390 ++nColumn; 1391 } 1392 return 0; 1393 } 1394 1395 String ScAccessibleCsvGrid::implGetCellText( sal_Int32 nRow, sal_Int32 nColumn ) const 1396 { 1397 ScCsvGrid& rGrid = implGetGrid(); 1398 sal_Int32 nLine = nRow + rGrid.GetFirstVisLine() - 1; 1399 String aCellStr; 1400 if( (nColumn > 0) && (nRow > 0) ) 1401 aCellStr = rGrid.GetCellText( lcl_GetGridColumn( nColumn ), nLine ); 1402 else if( nRow > 0 ) 1403 aCellStr = String::CreateFromInt32( nLine + 1L ); 1404 else if( nColumn > 0 ) 1405 aCellStr = rGrid.GetColumnTypeName( lcl_GetGridColumn( nColumn ) ); 1406 return aCellStr; 1407 } 1408 1409 1410 ScAccessibleCsvControl* ScAccessibleCsvGrid::implCreateCellObj( sal_Int32 nRow, sal_Int32 nColumn ) const 1411 { 1412 return new ScAccessibleCsvCell( implGetGrid(), implGetCellText( nRow, nColumn ), nRow, nColumn ); 1413 } 1414 1415 1416 // ============================================================================ 1417 1418 DBG_NAME( ScAccessibleCsvCell ) 1419 1420 ScAccessibleCsvCell::ScAccessibleCsvCell( 1421 ScCsvGrid& rGrid, 1422 const String& rCellText, 1423 sal_Int32 nRow, sal_Int32 nColumn ) : 1424 ScAccessibleCsvControl( rGrid.GetAccessible(), rGrid, nCellRole ), 1425 AccessibleStaticTextBase( SvxEditSourcePtr( NULL ) ), 1426 maCellText( rCellText ), 1427 mnLine( nRow ? (nRow + rGrid.GetFirstVisLine() - 1) : CSV_LINE_HEADER ), 1428 mnColumn( lcl_GetGridColumn( nColumn ) ), 1429 mnIndex( nRow * (rGrid.GetColumnCount() + 1) + nColumn ) 1430 { 1431 DBG_CTOR( ScAccessibleCsvCell, NULL ); 1432 SetEditSource( implCreateEditSource() ); 1433 } 1434 1435 ScAccessibleCsvCell::~ScAccessibleCsvCell() 1436 { 1437 DBG_DTOR( ScAccessibleCsvCell, NULL ); 1438 } 1439 1440 void SAL_CALL ScAccessibleCsvCell::disposing() 1441 { 1442 ScUnoGuard aGuard; 1443 SetEditSource( SvxEditSourcePtr( NULL ) ); 1444 ScAccessibleCsvControl::disposing(); 1445 } 1446 1447 1448 // XAccessibleComponent ------------------------------------------------------- 1449 1450 void SAL_CALL ScAccessibleCsvCell::grabFocus() 1451 { 1452 ScUnoGuard aGuard; 1453 ensureAlive(); 1454 ScCsvGrid& rGrid = implGetGrid(); 1455 rGrid.Execute( CSVCMD_MOVEGRIDCURSOR, rGrid.GetColumnPos( mnColumn ) ); 1456 } 1457 1458 sal_Int32 SAL_CALL ScAccessibleCsvCell::getForeground( ) 1459 { 1460 ScUnoGuard aGuard; 1461 ensureAlive(); 1462 return implGetGrid().GetSettings().GetStyleSettings().GetButtonTextColor().GetColor(); 1463 } 1464 1465 sal_Int32 SAL_CALL ScAccessibleCsvCell::getBackground( ) 1466 { 1467 ScUnoGuard aGuard; 1468 ensureAlive(); 1469 return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor; 1470 } 1471 1472 // XAccessibleContext ----------------------------------------------------- 1473 1474 sal_Int32 SAL_CALL ScAccessibleCsvCell::getAccessibleChildCount() 1475 { 1476 return AccessibleStaticTextBase::getAccessibleChildCount(); 1477 } 1478 1479 Reference< XAccessible > SAL_CALL ScAccessibleCsvCell::getAccessibleChild( sal_Int32 nIndex ) 1480 { 1481 return AccessibleStaticTextBase::getAccessibleChild( nIndex ); 1482 } 1483 1484 sal_Int32 SAL_CALL ScAccessibleCsvCell::getAccessibleIndexInParent() 1485 { 1486 ScUnoGuard aGuard; 1487 ensureAlive(); 1488 return mnIndex; 1489 } 1490 1491 Reference< XAccessibleRelationSet > SAL_CALL ScAccessibleCsvCell::getAccessibleRelationSet() 1492 { 1493 ScUnoGuard aGuard; 1494 ensureAlive(); 1495 return new AccessibleRelationSetHelper(); 1496 } 1497 1498 Reference< XAccessibleStateSet > SAL_CALL ScAccessibleCsvCell::getAccessibleStateSet() 1499 { 1500 ScUnoGuard aGuard; 1501 AccessibleStateSetHelper* pStateSet = implCreateStateSet(); 1502 if( implIsAlive() ) 1503 { 1504 const ScCsvGrid& rGrid = implGetGrid(); 1505 pStateSet->AddState( AccessibleStateType::SINGLE_LINE ); 1506 if( mnColumn != CSV_COLUMN_HEADER ) 1507 pStateSet->AddState( AccessibleStateType::SELECTABLE ); 1508 if( rGrid.HasFocus() && (rGrid.GetFocusColumn() == mnColumn) && (mnLine == CSV_LINE_HEADER) ) 1509 pStateSet->AddState( AccessibleStateType::ACTIVE ); 1510 if( rGrid.IsSelected( mnColumn ) ) 1511 pStateSet->AddState( AccessibleStateType::SELECTED ); 1512 } 1513 return pStateSet; 1514 } 1515 1516 // XInterface ----------------------------------------------------------------- 1517 1518 IMPLEMENT_FORWARD_XINTERFACE2( ScAccessibleCsvCell, ScAccessibleCsvControl, AccessibleStaticTextBase ) 1519 1520 // XTypeProvider -------------------------------------------------------------- 1521 1522 IMPLEMENT_FORWARD_XTYPEPROVIDER2( ScAccessibleCsvCell, ScAccessibleCsvControl, AccessibleStaticTextBase ) 1523 1524 // XServiceInfo --------------------------------------------------------------- 1525 1526 OUString SAL_CALL ScAccessibleCsvCell::getImplementationName() 1527 { 1528 return CREATE_OUSTRING( CELL_IMPL_NAME ); 1529 } 1530 1531 // helpers -------------------------------------------------------------------- 1532 1533 Rectangle ScAccessibleCsvCell::GetBoundingBoxOnScreen() const 1534 { 1535 ScUnoGuard aGuard; 1536 ensureAlive(); 1537 Rectangle aRect( implGetBoundingBox() ); 1538 aRect.SetPos( implGetAbsPos( aRect.TopLeft() ) ); 1539 return aRect; 1540 } 1541 1542 Rectangle ScAccessibleCsvCell::GetBoundingBox() const 1543 { 1544 ScUnoGuard aGuard; 1545 ensureAlive(); 1546 return implGetBoundingBox(); 1547 } 1548 1549 OUString SAL_CALL ScAccessibleCsvCell::createAccessibleName() 1550 { 1551 return maCellText; 1552 } 1553 1554 OUString SAL_CALL ScAccessibleCsvCell::createAccessibleDescription() 1555 { 1556 return OUString(); 1557 } 1558 1559 ScCsvGrid& ScAccessibleCsvCell::implGetGrid() const 1560 { 1561 return static_cast< ScCsvGrid& >( implGetControl() ); 1562 } 1563 1564 Point ScAccessibleCsvCell::implGetRealPos() const 1565 { 1566 ScCsvGrid& rGrid = implGetGrid(); 1567 return Point( 1568 (mnColumn == CSV_COLUMN_HEADER) ? rGrid.GetHdrX() : rGrid.GetColumnX( mnColumn ), 1569 (mnLine == CSV_LINE_HEADER) ? 0 : rGrid.GetY( mnLine ) ); 1570 } 1571 1572 sal_uInt32 ScAccessibleCsvCell::implCalcPixelWidth(sal_uInt32 nChars) const 1573 { 1574 ScCsvGrid& rGrid = implGetGrid(); 1575 return rGrid.GetCharWidth() * nChars; 1576 } 1577 1578 Size ScAccessibleCsvCell::implGetRealSize() const 1579 { 1580 ScCsvGrid& rGrid = implGetGrid(); 1581 return Size( 1582 (mnColumn == CSV_COLUMN_HEADER) ? rGrid.GetHdrWidth() : implCalcPixelWidth( rGrid.GetColumnWidth( mnColumn ) ), 1583 (mnLine == CSV_LINE_HEADER) ? rGrid.GetHdrHeight() : rGrid.GetLineHeight() ); 1584 } 1585 1586 Rectangle ScAccessibleCsvCell::implGetBoundingBox() const 1587 { 1588 ScCsvGrid& rGrid = implGetGrid(); 1589 Rectangle aClipRect( Point( 0, 0 ), rGrid.GetSizePixel() ); 1590 if( mnColumn != CSV_COLUMN_HEADER ) 1591 { 1592 aClipRect.Left() = rGrid.GetFirstX(); 1593 aClipRect.Right() = rGrid.GetLastX(); 1594 } 1595 if( mnLine != CSV_LINE_HEADER ) 1596 aClipRect.Top() = rGrid.GetHdrHeight(); 1597 1598 Rectangle aRect( implGetRealPos(), implGetRealSize() ); 1599 aRect.Intersection( aClipRect ); 1600 if( (aRect.GetWidth() <= 0) || (aRect.GetHeight() <= 0) ) 1601 aRect.SetSize( Size( -1, -1 ) ); 1602 return aRect; 1603 } 1604 1605 ::std::auto_ptr< SvxEditSource > ScAccessibleCsvCell::implCreateEditSource() 1606 { 1607 ScCsvGrid& rGrid = implGetGrid(); 1608 Rectangle aBoundRect( implGetBoundingBox() ); 1609 aBoundRect -= implGetRealPos(); 1610 1611 ::std::auto_ptr< ScAccessibleTextData > pCsvTextData( new ScAccessibleCsvTextData( 1612 &rGrid, rGrid.GetEditEngine(), maCellText, aBoundRect, implGetRealSize() ) ); 1613 1614 ::std::auto_ptr< SvxEditSource > pEditSource( new ScAccessibilityEditSource( pCsvTextData ) ); 1615 return pEditSource; 1616 } 1617 1618 1619 // ============================================================================ 1620