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 { 124 uno::Any aAny (ScAccessiblePreviewHeaderCellImpl::queryInterface(rType)); 125 return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType); 126 } 127 128 void SAL_CALL ScAccessiblePreviewHeaderCell::acquire() 129 throw () 130 { 131 ScAccessibleContextBase::acquire(); 132 } 133 134 void SAL_CALL ScAccessiblePreviewHeaderCell::release() 135 throw () 136 { 137 ScAccessibleContextBase::release(); 138 } 139 140 //===== XAccessibleValue ================================================ 141 142 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getCurrentValue() 143 { 144 ScUnoGuard aGuard; 145 IsObjectValid(); 146 147 double fValue(0.0); 148 if (mbColumnHeader) 149 fValue = maCellPos.Col(); 150 else 151 fValue = maCellPos.Row(); 152 153 uno::Any aAny; 154 aAny <<= fValue; 155 return aAny; 156 } 157 158 sal_Bool SAL_CALL ScAccessiblePreviewHeaderCell::setCurrentValue( const uno::Any& /* aNumber */ ) 159 { 160 // it is not possible to set a value 161 return sal_False; 162 } 163 164 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getMaximumValue() 165 { 166 ScUnoGuard aGuard; 167 IsObjectValid(); 168 169 double fValue(0.0); 170 if (mbColumnHeader) 171 fValue = MAXCOL; 172 else 173 fValue = MAXROW; 174 uno::Any aAny; 175 aAny <<= fValue; 176 return aAny; 177 } 178 179 uno::Any SAL_CALL ScAccessiblePreviewHeaderCell::getMinimumValue() 180 { 181 double fValue(0.0); 182 uno::Any aAny; 183 aAny <<= fValue; 184 return aAny; 185 } 186 187 //===== XAccessibleComponent ============================================ 188 189 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleAtPoint( const awt::Point& rPoint ) 190 { 191 uno::Reference<XAccessible> xRet; 192 if (containsPoint(rPoint)) 193 { 194 ScUnoGuard aGuard; 195 IsObjectValid(); 196 197 if(!mpTextHelper) 198 CreateTextHelper(); 199 200 xRet = mpTextHelper->GetAt(rPoint); 201 } 202 203 return xRet; 204 } 205 206 void SAL_CALL ScAccessiblePreviewHeaderCell::grabFocus() 207 { 208 ScUnoGuard aGuard; 209 IsObjectValid(); 210 if (getAccessibleParent().is()) 211 { 212 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY); 213 if (xAccessibleComponent.is()) 214 xAccessibleComponent->grabFocus(); 215 } 216 } 217 218 //===== XAccessibleContext ============================================== 219 220 sal_Int32 SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleChildCount() 221 { 222 ScUnoGuard aGuard; 223 IsObjectValid(); 224 if (!mpTextHelper) 225 CreateTextHelper(); 226 return mpTextHelper->GetChildCount(); 227 } 228 229 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleChild(sal_Int32 nIndex) 230 { 231 ScUnoGuard aGuard; 232 IsObjectValid(); 233 if (!mpTextHelper) 234 CreateTextHelper(); 235 return mpTextHelper->GetChild(nIndex); 236 } 237 238 sal_Int32 SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleIndexInParent() 239 { 240 return mnIndex; 241 } 242 243 uno::Reference<XAccessibleStateSet> SAL_CALL ScAccessiblePreviewHeaderCell::getAccessibleStateSet() 244 { 245 ScUnoGuard aGuard; 246 247 uno::Reference<XAccessibleStateSet> xParentStates; 248 if (getAccessibleParent().is()) 249 { 250 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext(); 251 xParentStates = xParentContext->getAccessibleStateSet(); 252 } 253 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper(); 254 if (IsDefunc(xParentStates)) 255 pStateSet->AddState(AccessibleStateType::DEFUNC); 256 else 257 { 258 pStateSet->AddState(AccessibleStateType::ENABLED); 259 pStateSet->AddState(AccessibleStateType::MULTI_LINE); 260 if (isShowing()) 261 pStateSet->AddState(AccessibleStateType::SHOWING); 262 pStateSet->AddState(AccessibleStateType::TRANSIENT); 263 if (isVisible()) 264 pStateSet->AddState(AccessibleStateType::VISIBLE); 265 } 266 return pStateSet; 267 } 268 269 //===== XServiceInfo ==================================================== 270 271 rtl::OUString SAL_CALL ScAccessiblePreviewHeaderCell::getImplementationName() 272 { 273 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ScAccessiblePreviewHeaderCell")); 274 } 275 276 uno::Sequence<rtl::OUString> SAL_CALL ScAccessiblePreviewHeaderCell::getSupportedServiceNames() 277 { 278 uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames(); 279 sal_Int32 nOldSize(aSequence.getLength()); 280 aSequence.realloc(nOldSize + 1); 281 ::rtl::OUString* pNames = aSequence.getArray(); 282 283 pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.table.AccessibleCellView")); 284 285 return aSequence; 286 } 287 288 //===== XTypeProvider ======================================================= 289 290 uno::Sequence< uno::Type > SAL_CALL ScAccessiblePreviewHeaderCell::getTypes() 291 { 292 return comphelper::concatSequences(ScAccessiblePreviewHeaderCellImpl::getTypes(), ScAccessibleContextBase::getTypes()); 293 } 294 295 uno::Sequence<sal_Int8> SAL_CALL 296 ScAccessiblePreviewHeaderCell::getImplementationId(void) 297 { 298 ScUnoGuard aGuard; 299 IsObjectValid(); 300 static uno::Sequence<sal_Int8> aId; 301 if (aId.getLength() == 0) 302 { 303 aId.realloc (16); 304 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True); 305 } 306 return aId; 307 } 308 309 //==== internal ========================================================= 310 311 Rectangle ScAccessiblePreviewHeaderCell::GetBoundingBoxOnScreen() const 312 { 313 Rectangle aCellRect; 314 315 FillTableInfo(); 316 317 if (mpTableInfo) 318 { 319 const ScPreviewColRowInfo& rColInfo = mpTableInfo->GetColInfo()[maCellPos.Col()]; 320 const ScPreviewColRowInfo& rRowInfo = mpTableInfo->GetRowInfo()[maCellPos.Row()]; 321 322 aCellRect = Rectangle( rColInfo.nPixelStart, rRowInfo.nPixelStart, rColInfo.nPixelEnd, rRowInfo.nPixelEnd ); 323 } 324 325 if (mpViewShell) 326 { 327 Window* pWindow = mpViewShell->GetWindow(); 328 if (pWindow) 329 { 330 Rectangle aRect = pWindow->GetWindowExtentsRelative(NULL); 331 aCellRect.setX(aCellRect.getX() + aRect.getX()); 332 aCellRect.setY(aCellRect.getY() + aRect.getY()); 333 } 334 } 335 return aCellRect; 336 } 337 338 Rectangle ScAccessiblePreviewHeaderCell::GetBoundingBox() const 339 { 340 FillTableInfo(); 341 342 if (mpTableInfo) 343 { 344 const ScPreviewColRowInfo& rColInfo = mpTableInfo->GetColInfo()[maCellPos.Col()]; 345 const ScPreviewColRowInfo& rRowInfo = mpTableInfo->GetRowInfo()[maCellPos.Row()]; 346 347 Rectangle aCellRect( rColInfo.nPixelStart, rRowInfo.nPixelStart, rColInfo.nPixelEnd, rRowInfo.nPixelEnd ); 348 uno::Reference<XAccessible> xAccParent = const_cast<ScAccessiblePreviewHeaderCell*>(this)->getAccessibleParent(); 349 if (xAccParent.is()) 350 { 351 uno::Reference<XAccessibleContext> xAccParentContext = xAccParent->getAccessibleContext(); 352 uno::Reference<XAccessibleComponent> xAccParentComp (xAccParentContext, uno::UNO_QUERY); 353 if (xAccParentComp.is()) 354 { 355 Rectangle aParentRect (VCLRectangle(xAccParentComp->getBounds())); 356 aCellRect.setX(aCellRect.getX() - aParentRect.getX()); 357 aCellRect.setY(aCellRect.getY() - aParentRect.getY()); 358 } 359 } 360 return aCellRect; 361 } 362 return Rectangle(); 363 } 364 365 rtl::OUString SAL_CALL ScAccessiblePreviewHeaderCell::createAccessibleDescription() 366 { 367 rtl::OUString sDescription = String(ScResId(STR_ACC_HEADERCELL_DESCR)); 368 return sDescription; 369 } 370 371 rtl::OUString SAL_CALL ScAccessiblePreviewHeaderCell::createAccessibleName() 372 { 373 rtl::OUString sName = String(ScResId(STR_ACC_HEADERCELL_NAME)); 374 375 if ( mbColumnHeader ) 376 { 377 if ( mbRowHeader ) 378 { 379 //! name for corner cell? 380 381 // sName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Column/Row Header")); 382 } 383 else 384 { 385 // name of column header 386 sName += ScColToAlpha( maCellPos.Col() ); 387 } 388 } 389 else 390 { 391 // name of row header 392 sName += rtl::OUString::valueOf( (sal_Int32) ( maCellPos.Row() + 1 ) ); 393 } 394 395 return sName; 396 } 397 398 sal_Bool ScAccessiblePreviewHeaderCell::IsDefunc( const uno::Reference<XAccessibleStateSet>& rxParentStates ) 399 { 400 return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() || 401 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC)); 402 } 403 404 void ScAccessiblePreviewHeaderCell::CreateTextHelper() 405 { 406 if (!mpTextHelper) 407 { 408 ::std::auto_ptr < ScAccessibleTextData > pAccessiblePreviewHeaderCellTextData 409 (new ScAccessiblePreviewHeaderCellTextData(mpViewShell, String(getAccessibleName()), maCellPos, mbColumnHeader, mbRowHeader)); 410 ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessiblePreviewHeaderCellTextData)); 411 412 mpTextHelper = new ::accessibility::AccessibleTextHelper(pEditSource ); 413 mpTextHelper->SetEventSource(this); 414 } 415 } 416 417 void ScAccessiblePreviewHeaderCell::FillTableInfo() const 418 { 419 if ( mpViewShell && !mpTableInfo ) 420 { 421 Size aOutputSize; 422 Window* pWindow = mpViewShell->GetWindow(); 423 if ( pWindow ) 424 aOutputSize = pWindow->GetOutputSizePixel(); 425 Point aPoint; 426 Rectangle aVisRect( aPoint, aOutputSize ); 427 428 mpTableInfo = new ScPreviewTableInfo; 429 mpViewShell->GetLocationData().GetTableInfo( aVisRect, *mpTableInfo ); 430 } 431 } 432