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 #include "AccessibleEditObject.hxx" 27 #include "scitems.hxx" 28 #include <editeng/eeitem.hxx> 29 #include "unoguard.hxx" 30 #include "AccessibleText.hxx" 31 #include "editsrc.hxx" 32 #include "scmod.hxx" 33 #include "inputhdl.hxx" 34 35 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX 36 #include <unotools/accessiblestatesethelper.hxx> 37 #endif 38 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_ 39 #include <com/sun/star/accessibility/AccessibleRole.hpp> 40 #endif 41 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_ 42 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 43 #endif 44 #include <rtl/uuid.h> 45 #include <tools/debug.hxx> 46 #include <svx/AccessibleTextHelper.hxx> 47 //IAccessibility2 Implementation 2009----- 48 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> 49 #include <com/sun/star/sheet/XSpreadsheet.hpp> 50 #include <editeng/editview.hxx> 51 #include <editeng/editeng.hxx> 52 #include <svx/svdmodel.hxx> 53 #include <sfx2/objsh.hxx> 54 55 #include "unonames.hxx" 56 #include "document.hxx" 57 #include "AccessibleDocument.hxx" 58 #include <com/sun/star/accessibility/AccessibleRelationType.hpp> 59 #include <unotools/accessiblerelationsethelper.hxx> 60 #include <com/sun/star/accessibility/XAccessibleText.hpp> 61 using ::com::sun::star::lang::IndexOutOfBoundsException; 62 using ::com::sun::star::uno::RuntimeException; 63 //-----IAccessibility2 Implementation 2009 64 using namespace ::com::sun::star; 65 using namespace ::com::sun::star::accessibility; 66 67 //===== internal ============================================================ 68 69 ScAccessibleEditObject::ScAccessibleEditObject( 70 const uno::Reference<XAccessible>& rxParent, 71 EditView* pEditView, Window* pWin, const rtl::OUString& rName, 72 const rtl::OUString& rDescription, EditObjectType eObjectType) 73 : 74 ScAccessibleContextBase(rxParent, AccessibleRole::TEXT_FRAME), 75 mpTextHelper(NULL), 76 mpEditView(pEditView), 77 mpWindow(pWin), 78 meObjectType(eObjectType), 79 mbHasFocus(sal_False) 80 { 81 CreateTextHelper(); 82 SetName(rName); 83 SetDescription(rDescription); 84 //IAccessibility2 Implementation 2009----- 85 if( meObjectType == CellInEditMode) 86 { 87 const ScAccessibleDocument *pAccDoc = const_cast<ScAccessibleDocument*>(static_cast<ScAccessibleDocument*>(rxParent.get())) ; 88 if (pAccDoc) 89 { 90 m_pScDoc = pAccDoc->GetDocument(); 91 m_curCellAddress =pAccDoc->GetCurCellAddress(); 92 } 93 else 94 { 95 m_pScDoc=NULL; 96 } 97 } 98 else 99 m_pScDoc=NULL; 100 //-----IAccessibility2 Implementation 2009 101 } 102 103 ScAccessibleEditObject::~ScAccessibleEditObject() 104 { 105 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose) 106 { 107 // increment refcount to prevent double call off dtor 108 osl_incrementInterlockedCount( &m_refCount ); 109 // call dispose to inform object wich have a weak reference to this object 110 dispose(); 111 } 112 } 113 114 void SAL_CALL ScAccessibleEditObject::disposing() 115 { 116 ScUnoGuard aGuard; 117 if (mpTextHelper) 118 DELETEZ(mpTextHelper); 119 120 ScAccessibleContextBase::disposing(); 121 } 122 123 void ScAccessibleEditObject::LostFocus() 124 { 125 mbHasFocus = sal_False; 126 if (mpTextHelper) 127 mpTextHelper->SetFocus(sal_False); 128 CommitFocusLost(); 129 } 130 131 void ScAccessibleEditObject::GotFocus() 132 { 133 mbHasFocus = sal_True; 134 CommitFocusGained(); 135 if (mpTextHelper) 136 mpTextHelper->SetFocus(sal_True); 137 } 138 139 //IAccessibility2 Implementation 2009----- 140 //===== XInterface ========================================================== 141 142 com::sun::star::uno::Any SAL_CALL 143 ScAccessibleEditObject::queryInterface (const com::sun::star::uno::Type & rType) 144 throw (::com::sun::star::uno::RuntimeException) 145 { 146 ::com::sun::star::uno::Any aReturn = ScAccessibleContextBase::queryInterface (rType); 147 if ( ! aReturn.hasValue()) 148 aReturn = ::cppu::queryInterface (rType, 149 static_cast< ::com::sun::star::accessibility::XAccessibleSelection* >(this) 150 ); 151 return aReturn; 152 } 153 void SAL_CALL 154 ScAccessibleEditObject::acquire (void) 155 throw () 156 { 157 ScAccessibleContextBase::acquire (); 158 } 159 void SAL_CALL 160 ScAccessibleEditObject::release (void) 161 throw () 162 { 163 ScAccessibleContextBase::release (); 164 } 165 //-----IAccessibility2 Implementation 2009 166 //===== XAccessibleComponent ============================================ 167 168 uno::Reference< XAccessible > SAL_CALL ScAccessibleEditObject::getAccessibleAtPoint( 169 const awt::Point& rPoint ) 170 throw (uno::RuntimeException) 171 { 172 uno::Reference<XAccessible> xRet; 173 if (containsPoint(rPoint)) 174 { 175 ScUnoGuard aGuard; 176 IsObjectValid(); 177 178 if(!mpTextHelper) 179 CreateTextHelper(); 180 181 xRet = mpTextHelper->GetAt(rPoint); 182 } 183 184 return xRet; 185 } 186 187 Rectangle ScAccessibleEditObject::GetBoundingBoxOnScreen(void) const 188 throw (uno::RuntimeException) 189 { 190 Rectangle aScreenBounds; 191 192 if ( mpWindow ) 193 { 194 if ( meObjectType == CellInEditMode ) 195 { 196 if ( mpEditView && mpEditView->GetEditEngine() ) 197 { 198 MapMode aMapMode( mpEditView->GetEditEngine()->GetRefMapMode() ); 199 aScreenBounds = mpWindow->LogicToPixel( mpEditView->GetOutputArea(), aMapMode ); 200 Point aCellLoc = aScreenBounds.TopLeft(); 201 Rectangle aWindowRect = mpWindow->GetWindowExtentsRelative( NULL ); 202 Point aWindowLoc = aWindowRect.TopLeft(); 203 Point aPos( aCellLoc.getX() + aWindowLoc.getX(), aCellLoc.getY() + aWindowLoc.getY() ); 204 aScreenBounds.SetPos( aPos ); 205 } 206 } 207 else 208 { 209 aScreenBounds = mpWindow->GetWindowExtentsRelative( NULL ); 210 } 211 } 212 213 return aScreenBounds; 214 } 215 216 Rectangle ScAccessibleEditObject::GetBoundingBox(void) const 217 throw (uno::RuntimeException) 218 { 219 Rectangle aBounds( GetBoundingBoxOnScreen() ); 220 221 if ( mpWindow ) 222 { 223 uno::Reference< XAccessible > xThis( mpWindow->GetAccessible() ); 224 if ( xThis.is() ) 225 { 226 uno::Reference< XAccessibleContext > xContext( xThis->getAccessibleContext() ); 227 if ( xContext.is() ) 228 { 229 uno::Reference< XAccessible > xParent( xContext->getAccessibleParent() ); 230 if ( xParent.is() ) 231 { 232 uno::Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY ); 233 if ( xParentComponent.is() ) 234 { 235 Point aScreenLoc = aBounds.TopLeft(); 236 awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen(); 237 Point aPos( aScreenLoc.getX() - aParentScreenLoc.X, aScreenLoc.getY() - aParentScreenLoc.Y ); 238 aBounds.SetPos( aPos ); 239 } 240 } 241 } 242 } 243 } 244 245 return aBounds; 246 } 247 248 //===== XAccessibleContext ============================================== 249 250 sal_Int32 SAL_CALL 251 ScAccessibleEditObject::getAccessibleChildCount(void) 252 throw (uno::RuntimeException) 253 { 254 ScUnoGuard aGuard; 255 IsObjectValid(); 256 if (!mpTextHelper) 257 CreateTextHelper(); 258 return mpTextHelper->GetChildCount(); 259 } 260 261 uno::Reference< XAccessible > SAL_CALL 262 ScAccessibleEditObject::getAccessibleChild(sal_Int32 nIndex) 263 throw (uno::RuntimeException, 264 lang::IndexOutOfBoundsException) 265 { 266 ScUnoGuard aGuard; 267 IsObjectValid(); 268 if (!mpTextHelper) 269 CreateTextHelper(); 270 return mpTextHelper->GetChild(nIndex); 271 } 272 273 uno::Reference<XAccessibleStateSet> SAL_CALL 274 ScAccessibleEditObject::getAccessibleStateSet(void) 275 throw (uno::RuntimeException) 276 { 277 ScUnoGuard aGuard; 278 uno::Reference<XAccessibleStateSet> xParentStates; 279 if (getAccessibleParent().is()) 280 { 281 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext(); 282 xParentStates = xParentContext->getAccessibleStateSet(); 283 } 284 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper(); 285 if (IsDefunc(xParentStates)) 286 pStateSet->AddState(AccessibleStateType::DEFUNC); 287 else 288 { 289 // all states are const, because this object exists only in one state 290 pStateSet->AddState(AccessibleStateType::EDITABLE); 291 pStateSet->AddState(AccessibleStateType::ENABLED); 292 pStateSet->AddState(AccessibleStateType::SENSITIVE); 293 pStateSet->AddState(AccessibleStateType::MULTI_LINE); 294 pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE); 295 pStateSet->AddState(AccessibleStateType::SHOWING); 296 pStateSet->AddState(AccessibleStateType::VISIBLE); 297 } 298 return pStateSet; 299 } 300 301 ::rtl::OUString SAL_CALL 302 ScAccessibleEditObject::createAccessibleDescription(void) 303 throw (uno::RuntimeException) 304 { 305 // DBG_ERRORFILE("Should never be called, because is set in the constructor.") 306 return rtl::OUString(); 307 } 308 309 ::rtl::OUString SAL_CALL 310 ScAccessibleEditObject::createAccessibleName(void) 311 throw (uno::RuntimeException) 312 { 313 DBG_ERRORFILE("Should never be called, because is set in the constructor."); 314 return rtl::OUString(); 315 } 316 317 ///===== XAccessibleEventBroadcaster ===================================== 318 319 void SAL_CALL 320 ScAccessibleEditObject::addEventListener(const uno::Reference<XAccessibleEventListener>& xListener) 321 throw (uno::RuntimeException) 322 { 323 if (!mpTextHelper) 324 CreateTextHelper(); 325 326 mpTextHelper->AddEventListener(xListener); 327 328 ScAccessibleContextBase::addEventListener(xListener); 329 } 330 331 void SAL_CALL 332 ScAccessibleEditObject::removeEventListener(const uno::Reference<XAccessibleEventListener>& xListener) 333 throw (uno::RuntimeException) 334 { 335 if (!mpTextHelper) 336 CreateTextHelper(); 337 338 mpTextHelper->RemoveEventListener(xListener); 339 340 ScAccessibleContextBase::removeEventListener(xListener); 341 } 342 343 //===== XServiceInfo ==================================================== 344 345 ::rtl::OUString SAL_CALL ScAccessibleEditObject::getImplementationName(void) 346 throw (uno::RuntimeException) 347 { 348 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleEditObject")); 349 } 350 351 //===== XTypeProvider ======================================================= 352 353 uno::Sequence<sal_Int8> SAL_CALL 354 ScAccessibleEditObject::getImplementationId(void) 355 throw (uno::RuntimeException) 356 { 357 ScUnoGuard aGuard; 358 IsObjectValid(); 359 static uno::Sequence<sal_Int8> aId; 360 if (aId.getLength() == 0) 361 { 362 aId.realloc (16); 363 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True); 364 } 365 return aId; 366 } 367 368 //==== internal ========================================================= 369 370 sal_Bool ScAccessibleEditObject::IsDefunc( 371 const uno::Reference<XAccessibleStateSet>& rxParentStates) 372 { 373 return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() || 374 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC)); 375 } 376 377 void ScAccessibleEditObject::CreateTextHelper() 378 { 379 if (!mpTextHelper) 380 { 381 ::std::auto_ptr < ScAccessibleTextData > pAccessibleTextData; 382 if (meObjectType == CellInEditMode || meObjectType == EditControl) 383 { 384 pAccessibleTextData.reset 385 (new ScAccessibleEditObjectTextData(mpEditView, mpWindow)); 386 } 387 else 388 { 389 pAccessibleTextData.reset 390 (new ScAccessibleEditLineTextData(NULL, mpWindow)); 391 } 392 393 ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessibleTextData)); 394 mpTextHelper = new ::accessibility::AccessibleTextHelper(pEditSource ); 395 mpTextHelper->SetEventSource(this); 396 mpTextHelper->SetFocus(mbHasFocus); 397 398 // #i54814# activate cell in edit mode 399 if( meObjectType == CellInEditMode ) 400 { 401 // do not activate cell object, if top edit line is active 402 const ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(); 403 if( pInputHdl && !pInputHdl->IsTopMode() ) 404 { 405 SdrHint aHint( HINT_BEGEDIT ); 406 mpTextHelper->GetEditSource().GetBroadcaster().Broadcast( aHint ); 407 } 408 } 409 } 410 } 411 //IAccessibility2 Implementation 2009----- 412 sal_Int32 SAL_CALL ScAccessibleEditObject::getForeground( ) 413 throw (::com::sun::star::uno::RuntimeException) 414 { 415 return GetFgBgColor(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CCOLOR))); 416 } 417 418 sal_Int32 SAL_CALL ScAccessibleEditObject::getBackground( ) 419 throw (::com::sun::star::uno::RuntimeException) 420 { 421 return GetFgBgColor(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CELLBACK))); 422 } 423 sal_Int32 ScAccessibleEditObject::GetFgBgColor( const rtl::OUString &strPropColor) 424 { 425 ScUnoGuard aGuard; 426 sal_Int32 nColor(0); 427 if (m_pScDoc) 428 { 429 SfxObjectShell* pObjSh = m_pScDoc->GetDocumentShell(); 430 if ( pObjSh ) 431 { 432 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( pObjSh->GetModel(), uno::UNO_QUERY ); 433 if ( xSpreadDoc.is() ) 434 { 435 uno::Reference<sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets(); 436 uno::Reference<container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY ); 437 if ( xIndex.is() ) 438 { 439 uno::Any aTable = xIndex->getByIndex(m_curCellAddress.Tab()); 440 uno::Reference<sheet::XSpreadsheet> xTable; 441 if (aTable>>=xTable) 442 { 443 uno::Reference<table::XCell> xCell = xTable->getCellByPosition(m_curCellAddress.Col(), m_curCellAddress.Row()); 444 if (xCell.is()) 445 { 446 uno::Reference<beans::XPropertySet> xCellProps(xCell, uno::UNO_QUERY); 447 if (xCellProps.is()) 448 { 449 uno::Any aAny = xCellProps->getPropertyValue(strPropColor); 450 aAny >>= nColor; 451 } 452 } 453 } 454 } 455 } 456 } 457 } 458 return nColor; 459 } 460 //===== XAccessibleSelection ============================================ 461 //-------------------------------------------------------------------------------- 462 void SAL_CALL ScAccessibleEditObject::selectAccessibleChild( sal_Int32 ) 463 throw ( IndexOutOfBoundsException, RuntimeException ) 464 { 465 } 466 //---------------------------------------------------------------------------------- 467 sal_Bool SAL_CALL ScAccessibleEditObject::isAccessibleChildSelected( sal_Int32 nChildIndex ) 468 throw ( IndexOutOfBoundsException, 469 RuntimeException ) 470 { 471 uno::Reference<XAccessible> xAcc = getAccessibleChild( nChildIndex ); 472 uno::Reference<XAccessibleContext> xContext; 473 if( xAcc.is() ) 474 xContext = xAcc->getAccessibleContext(); 475 if( xContext.is() ) 476 { 477 if( xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH ) 478 { 479 uno::Reference< ::com::sun::star::accessibility::XAccessibleText > 480 xText(xAcc, uno::UNO_QUERY); 481 if( xText.is() ) 482 { 483 if( xText->getSelectionStart() >= 0 ) return sal_True; 484 } 485 } 486 } 487 return sal_False; 488 } 489 //--------------------------------------------------------------------- 490 void SAL_CALL ScAccessibleEditObject::clearAccessibleSelection( ) 491 throw ( RuntimeException ) 492 { 493 } 494 //------------------------------------------------------------------------- 495 void SAL_CALL ScAccessibleEditObject::selectAllAccessibleChildren( ) 496 throw ( RuntimeException ) 497 { 498 } 499 //---------------------------------------------------------------------------- 500 sal_Int32 SAL_CALL ScAccessibleEditObject::getSelectedAccessibleChildCount() 501 throw ( RuntimeException ) 502 { 503 sal_Int32 nCount = 0; 504 sal_Int32 TotalCount = getAccessibleChildCount(); 505 for( sal_Int32 i = 0; i < TotalCount; i++ ) 506 if( isAccessibleChildSelected(i) ) nCount++; 507 return nCount; 508 } 509 //-------------------------------------------------------------------------------------- 510 uno::Reference<XAccessible> SAL_CALL ScAccessibleEditObject::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) 511 throw ( IndexOutOfBoundsException, RuntimeException) 512 { 513 if ( nSelectedChildIndex > getSelectedAccessibleChildCount() ) 514 throw IndexOutOfBoundsException(); 515 sal_Int32 i1, i2; 516 for( i1 = 0, i2 = 0; i1 < getAccessibleChildCount(); i1++ ) 517 if( isAccessibleChildSelected(i1) ) 518 { 519 if( i2 == nSelectedChildIndex ) 520 return getAccessibleChild( i1 ); 521 i2++; 522 } 523 return uno::Reference<XAccessible>(); 524 } 525 //---------------------------------------------------------------------------------- 526 void SAL_CALL ScAccessibleEditObject::deselectAccessibleChild( 527 sal_Int32 ) 528 throw ( IndexOutOfBoundsException, 529 RuntimeException ) 530 { 531 } 532 uno::Reference< XAccessibleRelationSet > ScAccessibleEditObject::getAccessibleRelationSet( ) 533 throw (uno::RuntimeException) 534 { 535 ScUnoGuard aGuard; 536 Window* pWindow = mpWindow; 537 utl::AccessibleRelationSetHelper* rRelationSet = new utl::AccessibleRelationSetHelper; 538 uno::Reference< XAccessibleRelationSet > rSet = rRelationSet; 539 if ( pWindow ) 540 { 541 Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy(); 542 if ( pLabeledBy && pLabeledBy != pWindow ) 543 { 544 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1); 545 aSequence[0] = pLabeledBy->GetAccessible(); 546 rRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::LABELED_BY, aSequence ) ); 547 } 548 Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf(); 549 if ( pMemberOf && pMemberOf != pWindow ) 550 { 551 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1); 552 aSequence[0] = pMemberOf->GetAccessible(); 553 rRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::MEMBER_OF, aSequence ) ); 554 } 555 return rSet; 556 } 557 return uno::Reference< XAccessibleRelationSet >(); 558 } 559 //-----IAccessibility2 Implementation 2009 560 561