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