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 which 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 { 140 ::com::sun::star::uno::Any aReturn = ScAccessibleContextBase::queryInterface (rType); 141 if ( ! aReturn.hasValue()) 142 aReturn = ::cppu::queryInterface (rType, 143 static_cast< ::com::sun::star::accessibility::XAccessibleSelection* >(this) 144 ); 145 return aReturn; 146 } 147 void SAL_CALL 148 ScAccessibleEditObject::acquire (void) 149 throw () 150 { 151 ScAccessibleContextBase::acquire (); 152 } 153 void SAL_CALL 154 ScAccessibleEditObject::release (void) 155 throw () 156 { 157 ScAccessibleContextBase::release (); 158 } 159 //===== XAccessibleComponent ============================================ 160 161 uno::Reference< XAccessible > SAL_CALL ScAccessibleEditObject::getAccessibleAtPoint( 162 const awt::Point& rPoint ) 163 { 164 uno::Reference<XAccessible> xRet; 165 if (containsPoint(rPoint)) 166 { 167 ScUnoGuard aGuard; 168 IsObjectValid(); 169 170 if(!mpTextHelper) 171 CreateTextHelper(); 172 173 xRet = mpTextHelper->GetAt(rPoint); 174 } 175 176 return xRet; 177 } 178 179 Rectangle ScAccessibleEditObject::GetBoundingBoxOnScreen(void) const 180 { 181 Rectangle aScreenBounds; 182 183 if ( mpWindow ) 184 { 185 if ( meObjectType == CellInEditMode ) 186 { 187 if ( mpEditView && mpEditView->GetEditEngine() ) 188 { 189 MapMode aMapMode( mpEditView->GetEditEngine()->GetRefMapMode() ); 190 aScreenBounds = mpWindow->LogicToPixel( mpEditView->GetOutputArea(), aMapMode ); 191 Point aCellLoc = aScreenBounds.TopLeft(); 192 Rectangle aWindowRect = mpWindow->GetWindowExtentsRelative( NULL ); 193 Point aWindowLoc = aWindowRect.TopLeft(); 194 Point aPos( aCellLoc.getX() + aWindowLoc.getX(), aCellLoc.getY() + aWindowLoc.getY() ); 195 aScreenBounds.SetPos( aPos ); 196 } 197 } 198 else 199 { 200 aScreenBounds = mpWindow->GetWindowExtentsRelative( NULL ); 201 } 202 } 203 204 return aScreenBounds; 205 } 206 207 Rectangle ScAccessibleEditObject::GetBoundingBox(void) const 208 { 209 Rectangle aBounds( GetBoundingBoxOnScreen() ); 210 211 if ( mpWindow ) 212 { 213 uno::Reference< XAccessible > xThis( mpWindow->GetAccessible() ); 214 if ( xThis.is() ) 215 { 216 uno::Reference< XAccessibleContext > xContext( xThis->getAccessibleContext() ); 217 if ( xContext.is() ) 218 { 219 uno::Reference< XAccessible > xParent( xContext->getAccessibleParent() ); 220 if ( xParent.is() ) 221 { 222 uno::Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY ); 223 if ( xParentComponent.is() ) 224 { 225 Point aScreenLoc = aBounds.TopLeft(); 226 awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen(); 227 Point aPos( aScreenLoc.getX() - aParentScreenLoc.X, aScreenLoc.getY() - aParentScreenLoc.Y ); 228 aBounds.SetPos( aPos ); 229 } 230 } 231 } 232 } 233 } 234 235 return aBounds; 236 } 237 238 //===== XAccessibleContext ============================================== 239 240 sal_Int32 SAL_CALL 241 ScAccessibleEditObject::getAccessibleChildCount(void) 242 { 243 ScUnoGuard aGuard; 244 IsObjectValid(); 245 if (!mpTextHelper) 246 CreateTextHelper(); 247 return mpTextHelper->GetChildCount(); 248 } 249 250 uno::Reference< XAccessible > SAL_CALL 251 ScAccessibleEditObject::getAccessibleChild(sal_Int32 nIndex) 252 { 253 ScUnoGuard aGuard; 254 IsObjectValid(); 255 if (!mpTextHelper) 256 CreateTextHelper(); 257 return mpTextHelper->GetChild(nIndex); 258 } 259 260 uno::Reference<XAccessibleStateSet> SAL_CALL 261 ScAccessibleEditObject::getAccessibleStateSet(void) 262 { 263 ScUnoGuard aGuard; 264 uno::Reference<XAccessibleStateSet> xParentStates; 265 if (getAccessibleParent().is()) 266 { 267 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext(); 268 xParentStates = xParentContext->getAccessibleStateSet(); 269 } 270 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper(); 271 if (IsDefunc(xParentStates)) 272 pStateSet->AddState(AccessibleStateType::DEFUNC); 273 else 274 { 275 // all states are const, because this object exists only in one state 276 pStateSet->AddState(AccessibleStateType::EDITABLE); 277 pStateSet->AddState(AccessibleStateType::ENABLED); 278 pStateSet->AddState(AccessibleStateType::SENSITIVE); 279 pStateSet->AddState(AccessibleStateType::MULTI_LINE); 280 pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE); 281 pStateSet->AddState(AccessibleStateType::SHOWING); 282 pStateSet->AddState(AccessibleStateType::VISIBLE); 283 } 284 return pStateSet; 285 } 286 287 ::rtl::OUString SAL_CALL 288 ScAccessibleEditObject::createAccessibleDescription(void) 289 { 290 // DBG_ERRORFILE("Should never be called, because is set in the constructor.") 291 return rtl::OUString(); 292 } 293 294 ::rtl::OUString SAL_CALL 295 ScAccessibleEditObject::createAccessibleName(void) 296 { 297 DBG_ERRORFILE("Should never be called, because is set in the constructor."); 298 return rtl::OUString(); 299 } 300 301 ///===== XAccessibleEventBroadcaster ===================================== 302 303 void SAL_CALL 304 ScAccessibleEditObject::addEventListener(const uno::Reference<XAccessibleEventListener>& xListener) 305 { 306 if (!mpTextHelper) 307 CreateTextHelper(); 308 309 mpTextHelper->AddEventListener(xListener); 310 311 ScAccessibleContextBase::addEventListener(xListener); 312 } 313 314 void SAL_CALL 315 ScAccessibleEditObject::removeEventListener(const uno::Reference<XAccessibleEventListener>& xListener) 316 { 317 if (!mpTextHelper) 318 CreateTextHelper(); 319 320 mpTextHelper->RemoveEventListener(xListener); 321 322 ScAccessibleContextBase::removeEventListener(xListener); 323 } 324 325 //===== XServiceInfo ==================================================== 326 327 ::rtl::OUString SAL_CALL ScAccessibleEditObject::getImplementationName(void) 328 { 329 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleEditObject")); 330 } 331 332 //===== XTypeProvider ======================================================= 333 334 uno::Sequence<sal_Int8> SAL_CALL 335 ScAccessibleEditObject::getImplementationId(void) 336 { 337 ScUnoGuard aGuard; 338 IsObjectValid(); 339 static uno::Sequence<sal_Int8> aId; 340 if (aId.getLength() == 0) 341 { 342 aId.realloc (16); 343 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True); 344 } 345 return aId; 346 } 347 348 //==== internal ========================================================= 349 350 sal_Bool ScAccessibleEditObject::IsDefunc( 351 const uno::Reference<XAccessibleStateSet>& rxParentStates) 352 { 353 return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() || 354 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC)); 355 } 356 357 void ScAccessibleEditObject::CreateTextHelper() 358 { 359 if (!mpTextHelper) 360 { 361 ::std::auto_ptr < ScAccessibleTextData > pAccessibleTextData; 362 if (meObjectType == CellInEditMode || meObjectType == EditControl) 363 { 364 pAccessibleTextData.reset 365 (new ScAccessibleEditObjectTextData(mpEditView, mpWindow)); 366 } 367 else 368 { 369 pAccessibleTextData.reset 370 (new ScAccessibleEditLineTextData(NULL, mpWindow)); 371 } 372 373 ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessibleTextData)); 374 mpTextHelper = new ::accessibility::AccessibleTextHelper(pEditSource ); 375 mpTextHelper->SetEventSource(this); 376 mpTextHelper->SetFocus(mbHasFocus); 377 378 // #i54814# activate cell in edit mode 379 if( meObjectType == CellInEditMode ) 380 { 381 // do not activate cell object, if top edit line is active 382 const ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl(); 383 if( pInputHdl && !pInputHdl->IsTopMode() ) 384 { 385 SdrHint aHint( HINT_BEGEDIT ); 386 mpTextHelper->GetEditSource().GetBroadcaster().Broadcast( aHint ); 387 } 388 } 389 } 390 } 391 sal_Int32 SAL_CALL ScAccessibleEditObject::getForeground( ) 392 { 393 return GetFgBgColor(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CCOLOR))); 394 } 395 396 sal_Int32 SAL_CALL ScAccessibleEditObject::getBackground( ) 397 { 398 return GetFgBgColor(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CELLBACK))); 399 } 400 sal_Int32 ScAccessibleEditObject::GetFgBgColor( const rtl::OUString &strPropColor) 401 { 402 ScUnoGuard aGuard; 403 sal_Int32 nColor(0); 404 if (m_pScDoc) 405 { 406 SfxObjectShell* pObjSh = m_pScDoc->GetDocumentShell(); 407 if ( pObjSh ) 408 { 409 uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( pObjSh->GetModel(), uno::UNO_QUERY ); 410 if ( xSpreadDoc.is() ) 411 { 412 uno::Reference<sheet::XSpreadsheets> xSheets = xSpreadDoc->getSheets(); 413 uno::Reference<container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY ); 414 if ( xIndex.is() ) 415 { 416 uno::Any aTable = xIndex->getByIndex(m_curCellAddress.Tab()); 417 uno::Reference<sheet::XSpreadsheet> xTable; 418 if (aTable>>=xTable) 419 { 420 uno::Reference<table::XCell> xCell = xTable->getCellByPosition(m_curCellAddress.Col(), m_curCellAddress.Row()); 421 if (xCell.is()) 422 { 423 uno::Reference<beans::XPropertySet> xCellProps(xCell, uno::UNO_QUERY); 424 if (xCellProps.is()) 425 { 426 uno::Any aAny = xCellProps->getPropertyValue(strPropColor); 427 aAny >>= nColor; 428 } 429 } 430 } 431 } 432 } 433 } 434 } 435 return nColor; 436 } 437 //===== XAccessibleSelection ============================================ 438 //-------------------------------------------------------------------------------- 439 void SAL_CALL ScAccessibleEditObject::selectAccessibleChild( sal_Int32 ) 440 { 441 } 442 //---------------------------------------------------------------------------------- 443 sal_Bool SAL_CALL ScAccessibleEditObject::isAccessibleChildSelected( sal_Int32 nChildIndex ) 444 { 445 uno::Reference<XAccessible> xAcc = getAccessibleChild( nChildIndex ); 446 uno::Reference<XAccessibleContext> xContext; 447 if( xAcc.is() ) 448 xContext = xAcc->getAccessibleContext(); 449 if( xContext.is() ) 450 { 451 if( xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH ) 452 { 453 uno::Reference< ::com::sun::star::accessibility::XAccessibleText > 454 xText(xAcc, uno::UNO_QUERY); 455 if( xText.is() ) 456 { 457 if( xText->getSelectionStart() >= 0 ) return sal_True; 458 } 459 } 460 } 461 return sal_False; 462 } 463 //--------------------------------------------------------------------- 464 void SAL_CALL ScAccessibleEditObject::clearAccessibleSelection( ) 465 { 466 } 467 //------------------------------------------------------------------------- 468 void SAL_CALL ScAccessibleEditObject::selectAllAccessibleChildren( ) 469 { 470 } 471 //---------------------------------------------------------------------------- 472 sal_Int32 SAL_CALL ScAccessibleEditObject::getSelectedAccessibleChildCount() 473 { 474 sal_Int32 nCount = 0; 475 sal_Int32 TotalCount = getAccessibleChildCount(); 476 for( sal_Int32 i = 0; i < TotalCount; i++ ) 477 if( isAccessibleChildSelected(i) ) nCount++; 478 return nCount; 479 } 480 //-------------------------------------------------------------------------------------- 481 uno::Reference<XAccessible> SAL_CALL ScAccessibleEditObject::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) 482 { 483 if ( nSelectedChildIndex > getSelectedAccessibleChildCount() ) 484 throw IndexOutOfBoundsException(); 485 sal_Int32 i1, i2; 486 for( i1 = 0, i2 = 0; i1 < getAccessibleChildCount(); i1++ ) 487 if( isAccessibleChildSelected(i1) ) 488 { 489 if( i2 == nSelectedChildIndex ) 490 return getAccessibleChild( i1 ); 491 i2++; 492 } 493 return uno::Reference<XAccessible>(); 494 } 495 //---------------------------------------------------------------------------------- 496 void SAL_CALL ScAccessibleEditObject::deselectAccessibleChild( 497 sal_Int32 ) 498 { 499 } 500 uno::Reference< XAccessibleRelationSet > ScAccessibleEditObject::getAccessibleRelationSet( ) 501 { 502 ScUnoGuard aGuard; 503 Window* pWindow = mpWindow; 504 utl::AccessibleRelationSetHelper* rRelationSet = new utl::AccessibleRelationSetHelper; 505 uno::Reference< XAccessibleRelationSet > rSet = rRelationSet; 506 if ( pWindow ) 507 { 508 Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy(); 509 if ( pLabeledBy && pLabeledBy != pWindow ) 510 { 511 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1); 512 aSequence[0] = pLabeledBy->GetAccessible(); 513 rRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::LABELED_BY, aSequence ) ); 514 } 515 Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf(); 516 if ( pMemberOf && pMemberOf != pWindow ) 517 { 518 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1); 519 aSequence[0] = pMemberOf->GetAccessible(); 520 rRelationSet->AddRelation( AccessibleRelation( AccessibleRelationType::MEMBER_OF, aSequence ) ); 521 } 522 return rSet; 523 } 524 return uno::Reference< XAccessibleRelationSet >(); 525 } 526