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