1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 #include "scitems.hxx" 31 #include <editeng/eeitem.hxx> 32 #include <tools/gen.hxx> 33 #include "AccessibleText.hxx" 34 #include "editsrc.hxx" 35 #include <svx/AccessibleTextHelper.hxx> 36 #include "AccessiblePreviewHeaderCell.hxx" 37 #include "AccessibilityHints.hxx" 38 #include "prevwsh.hxx" 39 #include "unoguard.hxx" 40 #include "miscuno.hxx" 41 #include "prevloc.hxx" 42 #include "scresid.hxx" 43 #ifndef SC_SC_HRC 44 #include "sc.hrc" 45 #endif 46 47 #include <com/sun/star/accessibility/AccessibleRole.hpp> 48 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 49 50 #include <vcl/window.hxx> 51 #include <svl/smplhint.hxx> 52 #include <unotools/accessiblestatesethelper.hxx> 53 #include <comphelper/sequence.hxx> 54 #include <toolkit/helper/convert.hxx> 55 56 using namespace ::com::sun::star; 57 using namespace ::com::sun::star::accessibility; 58 59 //===== internal ============================================================ 60 61 ScAccessiblePreviewHeaderCell::ScAccessiblePreviewHeaderCell( const ::com::sun::star::uno::Reference< 62 ::com::sun::star::accessibility::XAccessible>& rxParent, 63 ScPreviewShell* pViewShell, 64 const ScAddress& rCellPos, sal_Bool bIsColHdr, sal_Bool bIsRowHdr, 65 sal_Int32 nIndex ) : 66 ScAccessibleContextBase( rxParent, AccessibleRole::TABLE_CELL ), 67 mpViewShell( pViewShell ), 68 mpTextHelper( NULL ), 69 mnIndex( nIndex ), 70 maCellPos( rCellPos ), 71 mbColumnHeader( bIsColHdr ), 72 mbRowHeader( bIsRowHdr ), 73 mpTableInfo( NULL ) 74 { 75 if (mpViewShell) 76 mpViewShell->AddAccessibilityObject(*this); 77 } 78 79 ScAccessiblePreviewHeaderCell::~ScAccessiblePreviewHeaderCell() 80 { 81 if (mpViewShell) 82 mpViewShell->RemoveAccessibilityObject(*this); 83 } 84 85 void SAL_CALL ScAccessiblePreviewHeaderCell::disposing() 86 { 87 ScUnoGuard aGuard; 88 if (mpViewShell) 89 { 90 mpViewShell->RemoveAccessibilityObject(*this); 91 mpViewShell = NULL; 92 } 93 94 if (mpTableInfo) 95 DELETEZ (mpTableInfo); 96 97 ScAccessibleContextBase::disposing(); 98 } 99 100 //===== SfxListener ===================================================== 101 102 void ScAccessiblePreviewHeaderCell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 103 { 104 if (rHint.ISA( SfxSimpleHint )) 105 { 106 const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint; 107 sal_uLong nId = rRef.GetId(); 108 if (nId == SC_HINT_ACC_VISAREACHANGED) 109 { 110 if (mpTextHelper) 111 mpTextHelper->UpdateChildren(); 112 } 113 else if ( nId == SFX_HINT_DATACHANGED ) 114 { 115 // column / row layout may change with any document change, 116 // so it must be invalidated 117 DELETEZ( mpTableInfo ); 118 } 119 } 120 121 ScAccessibleContextBase::Notify(rBC, rHint); 122 } 123 124 //===== XInterface ===================================================== 125 126 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::queryInterface( uno::Type const & rType ) 127 throw (uno::RuntimeException) 128 { 129 uno::Any aAny (ScAccessiblePreviewHeaderCellImpl::queryInterface(rType)); 130 return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType); 131 } 132 133 void SAL_CALL ScAccessiblePreviewHeaderCell::acquire() 134 throw () 135 { 136 ScAccessibleContextBase::acquire(); 137 } 138 139 void SAL_CALL ScAccessiblePreviewHeaderCell::release() 140 throw () 141 { 142 ScAccessibleContextBase::release(); 143 } 144 145 //===== XAccessibleValue ================================================ 146 147 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getCurrentValue() throw (uno::RuntimeException) 148 { 149 ScUnoGuard aGuard; 150 IsObjectValid(); 151 152 double fValue(0.0); 153 if (mbColumnHeader) 154 fValue = maCellPos.Col(); 155 else 156 fValue = maCellPos.Row(); 157 158 uno::Any aAny; 159 aAny <<= fValue; 160 return aAny; 161 } 162 163 sal_Bool SAL_CALL ScAccessiblePreviewHeaderCell::setCurrentValue( const uno::Any& /* aNumber */ ) 164 throw (uno::RuntimeException) 165 { 166 // it is not possible to set a value 167 return sal_False; 168 } 169 170 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getMaximumValue() throw (uno::RuntimeException) 171 { 172 ScUnoGuard aGuard; 173 IsObjectValid(); 174 175 double fValue(0.0); 176 if (mbColumnHeader) 177 fValue = MAXCOL; 178 else 179 fValue = MAXROW; 180 uno::Any aAny; 181 aAny <<= fValue; 182 return aAny; 183 } 184 185 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getMinimumValue() throw (uno::RuntimeException) 186 { 187 double fValue(0.0); 188 uno::Any aAny; 189 aAny <<= fValue; 190 return aAny; 191 } 192 193 //===== XAccessibleComponent ============================================ 194 195 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleAtPoint( const awt::Point& rPoint ) 196 throw (uno::RuntimeException) 197 { 198 uno::Reference<XAccessible> xRet; 199 if (containsPoint(rPoint)) 200 { 201 ScUnoGuard aGuard; 202 IsObjectValid(); 203 204 if(!mpTextHelper) 205 CreateTextHelper(); 206 207 xRet = mpTextHelper->GetAt(rPoint); 208 } 209 210 return xRet; 211 } 212 213 void SAL_CALL ScAccessiblePreviewHeaderCell::grabFocus() throw (uno::RuntimeException) 214 { 215 ScUnoGuard aGuard; 216 IsObjectValid(); 217 if (getAccessibleParent().is()) 218 { 219 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY); 220 if (xAccessibleComponent.is()) 221 xAccessibleComponent->grabFocus(); 222 } 223 } 224 225 //===== XAccessibleContext ============================================== 226 227 sal_Int32 SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleChildCount() throw(uno::RuntimeException) 228 { 229 ScUnoGuard aGuard; 230 IsObjectValid(); 231 if (!mpTextHelper) 232 CreateTextHelper(); 233 return mpTextHelper->GetChildCount(); 234 } 235 236 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleChild(sal_Int32 nIndex) 237 throw (uno::RuntimeException, lang::IndexOutOfBoundsException) 238 { 239 ScUnoGuard aGuard; 240 IsObjectValid(); 241 if (!mpTextHelper) 242 CreateTextHelper(); 243 return mpTextHelper->GetChild(nIndex); 244 } 245 246 sal_Int32 SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleIndexInParent() throw (uno::RuntimeException) 247 { 248 return mnIndex; 249 } 250 251 uno::Reference<XAccessibleStateSet> SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleStateSet() 252 throw(uno::RuntimeException) 253 { 254 ScUnoGuard aGuard; 255 256 uno::Reference<XAccessibleStateSet> xParentStates; 257 if (getAccessibleParent().is()) 258 { 259 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext(); 260 xParentStates = xParentContext->getAccessibleStateSet(); 261 } 262 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper(); 263 if (IsDefunc(xParentStates)) 264 pStateSet->AddState(AccessibleStateType::DEFUNC); 265 else 266 { 267 pStateSet->AddState(AccessibleStateType::ENABLED); 268 pStateSet->AddState(AccessibleStateType::MULTI_LINE); 269 if (isShowing()) 270 pStateSet->AddState(AccessibleStateType::SHOWING); 271 pStateSet->AddState(AccessibleStateType::TRANSIENT); 272 if (isVisible()) 273 pStateSet->AddState(AccessibleStateType::VISIBLE); 274 } 275 return pStateSet; 276 } 277 278 //===== XServiceInfo ==================================================== 279 280 rtl::OUString SAL_CALL ScAccessiblePreviewHeaderCell::getImplementationName() throw(uno::RuntimeException) 281 { 282 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ScAccessiblePreviewHeaderCell")); 283 } 284 285 uno::Sequence<rtl::OUString> SAL_CALL ScAccessiblePreviewHeaderCell::getSupportedServiceNames() 286 throw(uno::RuntimeException) 287 { 288 uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames(); 289 sal_Int32 nOldSize(aSequence.getLength()); 290 aSequence.realloc(nOldSize + 1); 291 ::rtl::OUString* pNames = aSequence.getArray(); 292 293 pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.table.AccessibleCellView")); 294 295 return aSequence; 296 } 297 298 //===== XTypeProvider ======================================================= 299 300 uno::Sequence< uno::Type > SAL_CALL ScAccessiblePreviewHeaderCell::getTypes() 301 throw (uno::RuntimeException) 302 { 303 return comphelper::concatSequences(ScAccessiblePreviewHeaderCellImpl::getTypes(), ScAccessibleContextBase::getTypes()); 304 } 305 306 uno::Sequence<sal_Int8> SAL_CALL 307 ScAccessiblePreviewHeaderCell::getImplementationId(void) 308 throw (uno::RuntimeException) 309 { 310 ScUnoGuard aGuard; 311 IsObjectValid(); 312 static uno::Sequence<sal_Int8> aId; 313 if (aId.getLength() == 0) 314 { 315 aId.realloc (16); 316 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True); 317 } 318 return aId; 319 } 320 321 //==== internal ========================================================= 322 323 Rectangle ScAccessiblePreviewHeaderCell::GetBoundingBoxOnScreen() const throw (uno::RuntimeException) 324 { 325 Rectangle aCellRect; 326 327 FillTableInfo(); 328 329 if (mpTableInfo) 330 { 331 const ScPreviewColRowInfo& rColInfo = mpTableInfo->GetColInfo()[maCellPos.Col()]; 332 const ScPreviewColRowInfo& rRowInfo = mpTableInfo->GetRowInfo()[maCellPos.Row()]; 333 334 aCellRect = Rectangle( rColInfo.nPixelStart, rRowInfo.nPixelStart, rColInfo.nPixelEnd, rRowInfo.nPixelEnd ); 335 } 336 337 if (mpViewShell) 338 { 339 Window* pWindow = mpViewShell->GetWindow(); 340 if (pWindow) 341 { 342 Rectangle aRect = pWindow->GetWindowExtentsRelative(NULL); 343 aCellRect.setX(aCellRect.getX() + aRect.getX()); 344 aCellRect.setY(aCellRect.getY() + aRect.getY()); 345 } 346 } 347 return aCellRect; 348 } 349 350 Rectangle ScAccessiblePreviewHeaderCell::GetBoundingBox() const throw (uno::RuntimeException) 351 { 352 FillTableInfo(); 353 354 if (mpTableInfo) 355 { 356 const ScPreviewColRowInfo& rColInfo = mpTableInfo->GetColInfo()[maCellPos.Col()]; 357 const ScPreviewColRowInfo& rRowInfo = mpTableInfo->GetRowInfo()[maCellPos.Row()]; 358 359 Rectangle aCellRect( rColInfo.nPixelStart, rRowInfo.nPixelStart, rColInfo.nPixelEnd, rRowInfo.nPixelEnd ); 360 uno::Reference<XAccessible> xAccParent = const_cast<ScAccessiblePreviewHeaderCell*>(this)->getAccessibleParent(); 361 if (xAccParent.is()) 362 { 363 uno::Reference<XAccessibleContext> xAccParentContext = xAccParent->getAccessibleContext(); 364 uno::Reference<XAccessibleComponent> xAccParentComp (xAccParentContext, uno::UNO_QUERY); 365 if (xAccParentComp.is()) 366 { 367 Rectangle aParentRect (VCLRectangle(xAccParentComp->getBounds())); 368 aCellRect.setX(aCellRect.getX() - aParentRect.getX()); 369 aCellRect.setY(aCellRect.getY() - aParentRect.getY()); 370 } 371 } 372 return aCellRect; 373 } 374 return Rectangle(); 375 } 376 377 rtl::OUString SAL_CALL ScAccessiblePreviewHeaderCell::createAccessibleDescription() throw(uno::RuntimeException) 378 { 379 rtl::OUString sDescription = String(ScResId(STR_ACC_HEADERCELL_DESCR)); 380 return sDescription; 381 } 382 383 rtl::OUString SAL_CALL ScAccessiblePreviewHeaderCell::createAccessibleName() throw(uno::RuntimeException) 384 { 385 rtl::OUString sName = String(ScResId(STR_ACC_HEADERCELL_NAME)); 386 387 if ( mbColumnHeader ) 388 { 389 if ( mbRowHeader ) 390 { 391 //! name for corner cell? 392 393 // sName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Column/Row Header")); 394 } 395 else 396 { 397 // name of column header 398 sName += ScColToAlpha( maCellPos.Col() ); 399 } 400 } 401 else 402 { 403 // name of row header 404 sName += rtl::OUString::valueOf( (sal_Int32) ( maCellPos.Row() + 1 ) ); 405 } 406 407 return sName; 408 } 409 410 sal_Bool ScAccessiblePreviewHeaderCell::IsDefunc( const uno::Reference<XAccessibleStateSet>& rxParentStates ) 411 { 412 return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() || 413 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC)); 414 } 415 416 void ScAccessiblePreviewHeaderCell::CreateTextHelper() 417 { 418 if (!mpTextHelper) 419 { 420 ::std::auto_ptr < ScAccessibleTextData > pAccessiblePreviewHeaderCellTextData 421 (new ScAccessiblePreviewHeaderCellTextData(mpViewShell, String(getAccessibleName()), maCellPos, mbColumnHeader, mbRowHeader)); 422 ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessiblePreviewHeaderCellTextData)); 423 424 mpTextHelper = new ::accessibility::AccessibleTextHelper(pEditSource ); 425 mpTextHelper->SetEventSource(this); 426 } 427 } 428 429 void ScAccessiblePreviewHeaderCell::FillTableInfo() const 430 { 431 if ( mpViewShell && !mpTableInfo ) 432 { 433 Size aOutputSize; 434 Window* pWindow = mpViewShell->GetWindow(); 435 if ( pWindow ) 436 aOutputSize = pWindow->GetOutputSizePixel(); 437 Point aPoint; 438 Rectangle aVisRect( aPoint, aOutputSize ); 439 440 mpTableInfo = new ScPreviewTableInfo; 441 mpViewShell->GetLocationData().GetTableInfo( aVisRect, *mpTableInfo ); 442 } 443 } 444