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 27 28 #include "AccessibleSpreadsheet.hxx" 29 #include "AccessibilityHints.hxx" 30 #include "AccessibleCell.hxx" 31 #include "AccessibleDocument.hxx" 32 #include "tabvwsh.hxx" 33 #include "document.hxx" 34 #include "unoguard.hxx" 35 #include "hints.hxx" 36 #include "scmod.hxx" 37 38 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX 39 #include <unotools/accessiblestatesethelper.hxx> 40 #endif 41 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_ 42 #include <com/sun/star/accessibility/AccessibleRole.hpp> 43 #endif 44 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_ 45 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 46 #endif 47 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 48 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp> 49 #include <rtl/uuid.h> 50 #include <tools/debug.hxx> 51 #include <tools/gen.hxx> 52 #include <svtools/colorcfg.hxx> 53 54 #include <algorithm> 55 56 using namespace ::com::sun::star; 57 using namespace ::com::sun::star::accessibility; 58 59 //===== internal ============================================================ 60 61 ScAccessibleSpreadsheet::ScAccessibleSpreadsheet( 62 ScAccessibleDocument* pAccDoc, 63 ScTabViewShell* pViewShell, 64 SCTAB nTab, 65 ScSplitPos eSplitPos) 66 : 67 ScAccessibleTableBase (pAccDoc, GetDocument(pViewShell), 68 ScRange(ScAddress(0, 0, nTab),ScAddress(MAXCOL, MAXROW, nTab))), 69 mbIsSpreadsheet( sal_True ) 70 { 71 ConstructScAccessibleSpreadsheet( pAccDoc, pViewShell, nTab, eSplitPos ); 72 } 73 74 ScAccessibleSpreadsheet::ScAccessibleSpreadsheet( 75 ScAccessibleSpreadsheet& rParent, const ScRange& rRange ) : 76 ScAccessibleTableBase( rParent.mpAccDoc, rParent.mpDoc, rRange), 77 mbIsSpreadsheet( sal_False ) 78 { 79 ConstructScAccessibleSpreadsheet( rParent.mpAccDoc, rParent.mpViewShell, rParent.mnTab, rParent.meSplitPos ); 80 } 81 82 ScAccessibleSpreadsheet::~ScAccessibleSpreadsheet() 83 { 84 if (mpMarkedRanges) 85 delete mpMarkedRanges; 86 if (mpSortedMarkedCells) 87 delete mpSortedMarkedCells; 88 if (mpViewShell) 89 mpViewShell->RemoveAccessibilityObject(*this); 90 } 91 92 void ScAccessibleSpreadsheet::ConstructScAccessibleSpreadsheet( 93 ScAccessibleDocument* pAccDoc, 94 ScTabViewShell* pViewShell, 95 SCTAB nTab, 96 ScSplitPos eSplitPos) 97 { 98 mpViewShell = pViewShell; 99 mpMarkedRanges = 0; 100 mpSortedMarkedCells = 0; 101 mpAccDoc = pAccDoc; 102 mpAccCell = 0; 103 meSplitPos = eSplitPos; 104 mnTab = nTab; 105 mbHasSelection = sal_False; 106 mbDelIns = sal_False; 107 mbIsFocusSend = sal_False; 108 maVisCells = GetVisCells(GetVisArea(mpViewShell, meSplitPos)); 109 if (mpViewShell) 110 { 111 mpViewShell->AddAccessibilityObject(*this); 112 113 const ScViewData& rViewData = *mpViewShell->GetViewData(); 114 const ScMarkData& rMarkData = rViewData.GetMarkData(); 115 maActiveCell = rViewData.GetCurPos(); 116 mbHasSelection = rMarkData.GetTableSelect(maActiveCell.Tab()) && 117 (rMarkData.IsMarked() || rMarkData.IsMultiMarked()); 118 mpAccCell = GetAccessibleCellAt(maActiveCell.Row(), maActiveCell.Col()); 119 mpAccCell->acquire(); 120 mpAccCell->Init(); 121 } 122 } 123 124 void SAL_CALL ScAccessibleSpreadsheet::disposing() 125 { 126 ScUnoGuard aGuard; 127 if (mpViewShell) 128 { 129 mpViewShell->RemoveAccessibilityObject(*this); 130 mpViewShell = NULL; 131 } 132 if (mpAccCell) 133 { 134 mpAccCell->release(); 135 mpAccCell = NULL; 136 } 137 138 ScAccessibleTableBase::disposing(); 139 } 140 141 void ScAccessibleSpreadsheet::CompleteSelectionChanged(sal_Bool bNewState) 142 { 143 if (mpMarkedRanges) 144 DELETEZ(mpMarkedRanges); 145 if (mpSortedMarkedCells) 146 DELETEZ(mpSortedMarkedCells); 147 148 mbHasSelection = bNewState; 149 150 AccessibleEventObject aEvent; 151 aEvent.EventId = AccessibleEventId::STATE_CHANGED; 152 if (bNewState) 153 aEvent.NewValue = uno::makeAny(AccessibleStateType::SELECTED); 154 else 155 aEvent.OldValue = uno::makeAny(AccessibleStateType::SELECTED); 156 aEvent.Source = uno::Reference< XAccessibleContext >(this); 157 158 CommitChange(aEvent); 159 } 160 161 void ScAccessibleSpreadsheet::LostFocus() 162 { 163 AccessibleEventObject aEvent; 164 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED; 165 aEvent.Source = uno::Reference< XAccessibleContext >(this); 166 uno::Reference< XAccessible > xOld = mpAccCell; 167 aEvent.OldValue <<= xOld; 168 169 CommitChange(aEvent); 170 171 CommitFocusLost(); 172 } 173 174 void ScAccessibleSpreadsheet::GotFocus() 175 { 176 CommitFocusGained(); 177 178 AccessibleEventObject aEvent; 179 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED; 180 aEvent.Source = uno::Reference< XAccessibleContext >(this); 181 uno::Reference< XAccessible > xNew = mpAccCell; 182 aEvent.NewValue <<= xNew; 183 184 CommitChange(aEvent); 185 } 186 187 void ScAccessibleSpreadsheet::BoundingBoxChanged() 188 { 189 AccessibleEventObject aEvent; 190 aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED; 191 aEvent.Source = uno::Reference< XAccessibleContext >(this); 192 193 CommitChange(aEvent); 194 } 195 196 void ScAccessibleSpreadsheet::VisAreaChanged() 197 { 198 AccessibleEventObject aEvent; 199 aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED; 200 aEvent.Source = uno::Reference< XAccessibleContext >(this); 201 202 CommitChange(aEvent); 203 } 204 205 //===== SfxListener ===================================================== 206 207 void ScAccessibleSpreadsheet::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 208 { 209 if (rHint.ISA( SfxSimpleHint ) ) 210 { 211 const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint; 212 // only notify if child exist, otherwise it is not necessary 213 if ((rRef.GetId() == SC_HINT_ACC_CURSORCHANGED)) 214 { 215 if (mpViewShell) 216 { 217 ScAddress aNewCell = mpViewShell->GetViewData()->GetCurPos(); 218 sal_Bool bNewMarked(mpViewShell->GetViewData()->GetMarkData().GetTableSelect(aNewCell.Tab()) && 219 (mpViewShell->GetViewData()->GetMarkData().IsMarked() || 220 mpViewShell->GetViewData()->GetMarkData().IsMultiMarked())); 221 sal_Bool bNewCellSelected(isAccessibleSelected(aNewCell.Row(), aNewCell.Col())); 222 if ((bNewMarked != mbHasSelection) || 223 (!bNewCellSelected && bNewMarked) || 224 (bNewCellSelected && mbHasSelection)) 225 { 226 if (mpMarkedRanges) 227 DELETEZ(mpMarkedRanges); 228 if (mpSortedMarkedCells) 229 DELETEZ(mpSortedMarkedCells); 230 AccessibleEventObject aEvent; 231 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED; 232 aEvent.Source = uno::Reference< XAccessibleContext >(this); 233 234 mbHasSelection = bNewMarked; 235 236 CommitChange(aEvent); 237 } 238 239 // active descendant changed event (new cell selected) 240 bool bFireActiveDescChanged = (aNewCell != maActiveCell) && 241 (aNewCell.Tab() == maActiveCell.Tab()) && IsFocused(); 242 243 /* Remember old active cell and set new active cell. 244 #i82409# always update the class members mpAccCell and 245 maActiveCell, even if the sheet is not focused, e.g. when 246 using the name box in the toolbar. */ 247 uno::Reference< XAccessible > xOld = mpAccCell; 248 mpAccCell->release(); 249 mpAccCell = GetAccessibleCellAt(aNewCell.Row(), aNewCell.Col()); 250 mpAccCell->acquire(); 251 mpAccCell->Init(); 252 uno::Reference< XAccessible > xNew = mpAccCell; 253 maActiveCell = aNewCell; 254 255 // #i14108# fire event only if sheet is focused 256 if( bFireActiveDescChanged ) 257 { 258 AccessibleEventObject aEvent; 259 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED; 260 aEvent.Source = uno::Reference< XAccessibleContext >(this); 261 aEvent.OldValue <<= xOld; 262 aEvent.NewValue <<= xNew; 263 CommitChange(aEvent); 264 } 265 } 266 } 267 else if ((rRef.GetId() == SC_HINT_DATACHANGED)) 268 { 269 if (!mbDelIns) 270 CommitTableModelChange(maRange.aStart.Row(), maRange.aStart.Col(), maRange.aEnd.Row(), maRange.aEnd.Col(), AccessibleTableModelChangeType::UPDATE); 271 else 272 mbDelIns = sal_False; 273 } 274 // no longer needed, because the document calls the VisAreaChanged method 275 /* else if (rRef.GetId() == SC_HINT_ACC_VISAREACHANGED) 276 { 277 AccessibleEventObject aEvent; 278 aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED; 279 aEvent.Source = uno::Reference< XAccessibleContext >(this); 280 281 CommitChange(aEvent);*/ 282 // commented out, because to use a ModelChangeEvent is not the right way 283 // at the moment there is no way, but the Java/Gnome Api should be extended sometime 284 /* if (mpViewShell) 285 { 286 Rectangle aNewVisCells(GetVisCells(GetVisArea(mpViewShell, meSplitPos))); 287 288 Rectangle aNewPos(aNewVisCells); 289 290 if (aNewVisCells.IsOver(maVisCells)) 291 aNewPos.Union(maVisCells); 292 else 293 CommitTableModelChange(maVisCells.Top(), maVisCells.Left(), maVisCells.Bottom(), maVisCells.Right(), AccessibleTableModelChangeType::UPDATE); 294 295 maVisCells = aNewVisCells; 296 297 CommitTableModelChange(aNewPos.Top(), aNewPos.Left(), aNewPos.Bottom(), aNewPos.Right(), AccessibleTableModelChangeType::UPDATE); 298 } 299 }*/ 300 // no longer needed, because the document calls the BoundingBoxChanged method 301 /* else if (rRef.GetId() == SC_HINT_ACC_WINDOWRESIZED) 302 { 303 AccessibleEventObject aEvent; 304 aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED; 305 aEvent.Source = uno::Reference< XAccessibleContext >(this); 306 307 CommitChange(aEvent); 308 }*/ 309 } 310 else if (rHint.ISA( ScUpdateRefHint )) 311 { 312 const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; 313 if (rRef.GetMode() == URM_INSDEL && rRef.GetDz() == 0) //#107250# test whether table is inserted or deleted 314 { 315 if (((rRef.GetRange().aStart.Col() == maRange.aStart.Col()) && 316 (rRef.GetRange().aEnd.Col() == maRange.aEnd.Col())) || 317 ((rRef.GetRange().aStart.Row() == maRange.aStart.Row()) && 318 (rRef.GetRange().aEnd.Row() == maRange.aEnd.Row()))) 319 { 320 // ignore next SC_HINT_DATACHANGED notification 321 mbDelIns = sal_True; 322 323 sal_Int16 nId(0); 324 SCsCOL nX(rRef.GetDx()); 325 SCsROW nY(rRef.GetDy()); 326 ScRange aRange(rRef.GetRange()); 327 if ((nX < 0) || (nY < 0)) 328 { 329 DBG_ASSERT(!((nX < 0) && (nY < 0)), "should not be possible to remove row and column at the same time"); 330 nId = AccessibleTableModelChangeType::DELETE; 331 if (nX < 0) 332 { 333 nX = -nX; 334 nY = aRange.aEnd.Row() - aRange.aStart.Row(); 335 } 336 else 337 { 338 nY = -nY; 339 nX = aRange.aEnd.Col() - aRange.aStart.Col(); 340 } 341 } 342 else if ((nX > 0) || (nY > 0)) 343 { 344 DBG_ASSERT(!((nX > 0) && (nY > 0)), "should not be possible to add row and column at the same time"); 345 nId = AccessibleTableModelChangeType::INSERT; 346 if (nX < 0) 347 nY = aRange.aEnd.Row() - aRange.aStart.Row(); 348 else 349 nX = aRange.aEnd.Col() - aRange.aStart.Col(); 350 } 351 else 352 { 353 DBG_ERROR("is it a deletion or a insertion?"); 354 } 355 356 CommitTableModelChange(rRef.GetRange().aStart.Row(), 357 rRef.GetRange().aStart.Col(), 358 rRef.GetRange().aStart.Row() + nY, 359 rRef.GetRange().aStart.Col() + nX, nId); 360 361 AccessibleEventObject aEvent; 362 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED; 363 aEvent.Source = uno::Reference< XAccessibleContext >(this); 364 uno::Reference< XAccessible > xNew = mpAccCell; 365 aEvent.NewValue <<= xNew; 366 367 CommitChange(aEvent); 368 } 369 } 370 } 371 372 ScAccessibleTableBase::Notify(rBC, rHint); 373 } 374 375 //===== XAccessibleTable ================================================ 376 377 uno::Reference< XAccessibleTable > SAL_CALL ScAccessibleSpreadsheet::getAccessibleRowHeaders( ) 378 throw (uno::RuntimeException) 379 { 380 ScUnoGuard aGuard; 381 IsObjectValid(); 382 uno::Reference< XAccessibleTable > xAccessibleTable; 383 if( mpDoc && mbIsSpreadsheet ) 384 { 385 if( const ScRange* pRowRange = mpDoc->GetRepeatRowRange( mnTab ) ) 386 { 387 SCROW nStart = pRowRange->aStart.Row(); 388 SCROW nEnd = pRowRange->aEnd.Row(); 389 if( (0 <= nStart) && (nStart <= nEnd) && (nEnd <= MAXROW) ) 390 xAccessibleTable.set( new ScAccessibleSpreadsheet( *this, ScRange( 0, nStart, mnTab, MAXCOL, nEnd, mnTab ) ) ); 391 } 392 } 393 return xAccessibleTable; 394 } 395 396 uno::Reference< XAccessibleTable > SAL_CALL ScAccessibleSpreadsheet::getAccessibleColumnHeaders( ) 397 throw (uno::RuntimeException) 398 { 399 ScUnoGuard aGuard; 400 IsObjectValid(); 401 uno::Reference< XAccessibleTable > xAccessibleTable; 402 if( mpDoc && mbIsSpreadsheet ) 403 { 404 if( const ScRange* pColRange = mpDoc->GetRepeatColRange( mnTab ) ) 405 { 406 SCCOL nStart = pColRange->aStart.Col(); 407 SCCOL nEnd = pColRange->aEnd.Col(); 408 if( (0 <= nStart) && (nStart <= nEnd) && (nEnd <= MAXCOL) ) 409 xAccessibleTable.set( new ScAccessibleSpreadsheet( *this, ScRange( nStart, 0, mnTab, nEnd, MAXROW, mnTab ) ) ); 410 } 411 } 412 return xAccessibleTable; 413 } 414 415 uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleSpreadsheet::getSelectedAccessibleRows( ) 416 throw (uno::RuntimeException) 417 { 418 ScUnoGuard aGuard; 419 IsObjectValid(); 420 uno::Sequence<sal_Int32> aSequence; 421 if (mpViewShell && mpViewShell->GetViewData()) 422 { 423 aSequence.realloc(maRange.aEnd.Row() - maRange.aStart.Row() + 1); 424 const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData(); 425 sal_Int32* pSequence = aSequence.getArray(); 426 sal_Int32 nCount(0); 427 for (SCROW i = maRange.aStart.Row(); i <= maRange.aEnd.Row(); ++i) 428 { 429 if (rMarkdata.IsRowMarked(i)) 430 { 431 pSequence[nCount] = i; 432 ++nCount; 433 } 434 } 435 aSequence.realloc(nCount); 436 } 437 else 438 aSequence.realloc(0); 439 return aSequence; 440 } 441 442 uno::Sequence< sal_Int32 > SAL_CALL ScAccessibleSpreadsheet::getSelectedAccessibleColumns( ) 443 throw (uno::RuntimeException) 444 { 445 ScUnoGuard aGuard; 446 IsObjectValid(); 447 uno::Sequence<sal_Int32> aSequence; 448 if (mpViewShell && mpViewShell->GetViewData()) 449 { 450 aSequence.realloc(maRange.aEnd.Col() - maRange.aStart.Col() + 1); 451 const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData(); 452 sal_Int32* pSequence = aSequence.getArray(); 453 sal_Int32 nCount(0); 454 for (SCCOL i = maRange.aStart.Col(); i <= maRange.aEnd.Col(); ++i) 455 { 456 if (rMarkdata.IsColumnMarked(i)) 457 { 458 pSequence[nCount] = i; 459 ++nCount; 460 } 461 } 462 aSequence.realloc(nCount); 463 } 464 else 465 aSequence.realloc(0); 466 return aSequence; 467 } 468 469 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleRowSelected( sal_Int32 nRow ) 470 throw (uno::RuntimeException, lang::IndexOutOfBoundsException) 471 { 472 ScUnoGuard aGuard; 473 IsObjectValid(); 474 475 if ((nRow > (maRange.aEnd.Row() - maRange.aStart.Row())) || (nRow < 0)) 476 throw lang::IndexOutOfBoundsException(); 477 478 sal_Bool bResult(sal_False); 479 if (mpViewShell && mpViewShell->GetViewData()) 480 { 481 const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData(); 482 bResult = rMarkdata.IsRowMarked((SCROW)nRow); 483 } 484 return bResult; 485 } 486 487 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleColumnSelected( sal_Int32 nColumn ) 488 throw (uno::RuntimeException, lang::IndexOutOfBoundsException) 489 { 490 ScUnoGuard aGuard; 491 IsObjectValid(); 492 493 if ((nColumn > (maRange.aEnd.Col() - maRange.aStart.Col())) || (nColumn < 0)) 494 throw lang::IndexOutOfBoundsException(); 495 496 sal_Bool bResult(sal_False); 497 if (mpViewShell && mpViewShell->GetViewData()) 498 { 499 const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData(); 500 bResult = rMarkdata.IsColumnMarked((SCCOL)nColumn); 501 } 502 return bResult; 503 } 504 505 ScAccessibleCell* ScAccessibleSpreadsheet::GetAccessibleCellAt(sal_Int32 nRow, sal_Int32 nColumn) 506 { 507 ScAccessibleCell* pAccessibleCell = NULL; 508 ScAddress aCellAddress(static_cast<SCCOL>(maRange.aStart.Col() + nColumn), 509 static_cast<SCROW>(maRange.aStart.Row() + nRow), maRange.aStart.Tab()); 510 if ((aCellAddress == maActiveCell) && mpAccCell) 511 { 512 pAccessibleCell = mpAccCell; 513 } 514 else 515 pAccessibleCell = new ScAccessibleCell(this, mpViewShell, aCellAddress, getAccessibleIndex(nRow, nColumn), meSplitPos, mpAccDoc); 516 517 return pAccessibleCell; 518 } 519 520 uno::Reference< XAccessible > SAL_CALL ScAccessibleSpreadsheet::getAccessibleCellAt( sal_Int32 nRow, sal_Int32 nColumn ) 521 throw (uno::RuntimeException, lang::IndexOutOfBoundsException) 522 { 523 ScUnoGuard aGuard; 524 IsObjectValid(); 525 if (nRow > (maRange.aEnd.Row() - maRange.aStart.Row()) || 526 nRow < 0 || 527 nColumn > (maRange.aEnd.Col() - maRange.aStart.Col()) || 528 nColumn < 0) 529 throw lang::IndexOutOfBoundsException(); 530 531 uno::Reference<XAccessible> xAccessible; 532 ScAccessibleCell* pAccessibleCell = GetAccessibleCellAt(nRow, nColumn); 533 xAccessible = pAccessibleCell; 534 pAccessibleCell->Init(); 535 return xAccessible; 536 } 537 538 sal_Bool SAL_CALL ScAccessibleSpreadsheet::isAccessibleSelected( sal_Int32 nRow, sal_Int32 nColumn ) 539 throw (uno::RuntimeException, lang::IndexOutOfBoundsException) 540 { 541 ScUnoGuard aGuard; 542 IsObjectValid(); 543 544 if ((nColumn > (maRange.aEnd.Col() - maRange.aStart.Col())) || (nColumn < 0) || 545 (nRow > (maRange.aEnd.Row() - maRange.aStart.Row())) || (nRow < 0)) 546 throw lang::IndexOutOfBoundsException(); 547 548 sal_Bool bResult(sal_False); 549 if (mpViewShell) 550 { 551 const ScMarkData& rMarkdata = mpViewShell->GetViewData()->GetMarkData(); 552 bResult = rMarkdata.IsCellMarked(static_cast<SCCOL>(nColumn), static_cast<SCROW>(nRow)); 553 } 554 return bResult; 555 } 556 557 //===== XAccessibleComponent ============================================ 558 559 uno::Reference< XAccessible > SAL_CALL ScAccessibleSpreadsheet::getAccessibleAtPoint( 560 const awt::Point& rPoint ) 561 throw (uno::RuntimeException) 562 { 563 uno::Reference< XAccessible > xAccessible; 564 if (containsPoint(rPoint)) 565 { 566 ScUnoGuard aGuard; 567 IsObjectValid(); 568 if (mpViewShell) 569 { 570 SCsCOL nX; 571 SCsROW nY; 572 mpViewShell->GetViewData()->GetPosFromPixel( rPoint.X, rPoint.Y, meSplitPos, nX, nY); 573 xAccessible = getAccessibleCellAt(nY, nX); 574 } 575 } 576 return xAccessible; 577 } 578 579 void SAL_CALL ScAccessibleSpreadsheet::grabFocus( ) 580 throw (uno::RuntimeException) 581 { 582 if (getAccessibleParent().is()) 583 { 584 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY); 585 if (xAccessibleComponent.is()) 586 xAccessibleComponent->grabFocus(); 587 } 588 } 589 590 sal_Int32 SAL_CALL ScAccessibleSpreadsheet::getForeground( ) 591 throw (uno::RuntimeException) 592 { 593 return COL_BLACK; 594 } 595 596 sal_Int32 SAL_CALL ScAccessibleSpreadsheet::getBackground( ) 597 throw (uno::RuntimeException) 598 { 599 ScUnoGuard aGuard; 600 IsObjectValid(); 601 return SC_MOD()->GetColorConfig().GetColorValue( ::svtools::DOCCOLOR ).nColor; 602 } 603 604 //===== XAccessibleContext ============================================== 605 606 uno::Reference<XAccessibleRelationSet> SAL_CALL ScAccessibleSpreadsheet::getAccessibleRelationSet(void) 607 throw (::com::sun::star::uno::RuntimeException) 608 { 609 utl::AccessibleRelationSetHelper* pRelationSet = NULL; 610 if(mpAccDoc) 611 pRelationSet = mpAccDoc->GetRelationSet(NULL); 612 if (!pRelationSet) 613 pRelationSet = new utl::AccessibleRelationSetHelper(); 614 return pRelationSet; 615 } 616 617 uno::Reference<XAccessibleStateSet> SAL_CALL 618 ScAccessibleSpreadsheet::getAccessibleStateSet(void) 619 throw (uno::RuntimeException) 620 { 621 ScUnoGuard aGuard; 622 uno::Reference<XAccessibleStateSet> xParentStates; 623 if (getAccessibleParent().is()) 624 { 625 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext(); 626 xParentStates = xParentContext->getAccessibleStateSet(); 627 } 628 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper(); 629 if (IsDefunc(xParentStates)) 630 pStateSet->AddState(AccessibleStateType::DEFUNC); 631 else 632 { 633 pStateSet->AddState(AccessibleStateType::MANAGES_DESCENDANTS); 634 if (IsEditable(xParentStates)) 635 pStateSet->AddState(AccessibleStateType::EDITABLE); 636 pStateSet->AddState(AccessibleStateType::ENABLED); 637 pStateSet->AddState(AccessibleStateType::FOCUSABLE); 638 if (IsFocused()) 639 pStateSet->AddState(AccessibleStateType::FOCUSED); 640 pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE); 641 pStateSet->AddState(AccessibleStateType::OPAQUE); 642 pStateSet->AddState(AccessibleStateType::SELECTABLE); 643 if (IsCompleteSheetSelected()) 644 pStateSet->AddState(AccessibleStateType::SELECTED); 645 if (isShowing()) 646 pStateSet->AddState(AccessibleStateType::SHOWING); 647 if (isVisible()) 648 pStateSet->AddState(AccessibleStateType::VISIBLE); 649 } 650 return pStateSet; 651 } 652 653 ///===== XAccessibleSelection =========================================== 654 655 void SAL_CALL 656 ScAccessibleSpreadsheet::selectAccessibleChild( sal_Int32 nChildIndex ) 657 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 658 { 659 ScUnoGuard aGuard; 660 IsObjectValid(); 661 if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount()) 662 throw lang::IndexOutOfBoundsException(); 663 664 if (mpViewShell) 665 { 666 sal_Int32 nCol(getAccessibleColumn(nChildIndex)); 667 sal_Int32 nRow(getAccessibleRow(nChildIndex)); 668 669 SelectCell(nRow, nCol, sal_False); 670 } 671 } 672 673 void SAL_CALL 674 ScAccessibleSpreadsheet::clearAccessibleSelection( ) 675 throw (uno::RuntimeException) 676 { 677 ScUnoGuard aGuard; 678 IsObjectValid(); 679 if (mpViewShell) 680 { 681 mpViewShell->Unmark(); 682 } 683 } 684 685 void SAL_CALL 686 ScAccessibleSpreadsheet::selectAllAccessibleChildren( ) 687 throw (uno::RuntimeException) 688 { 689 ScUnoGuard aGuard; 690 IsObjectValid(); 691 if (mpViewShell) 692 { 693 mpViewShell->SelectAll(); 694 } 695 } 696 697 sal_Int32 SAL_CALL 698 ScAccessibleSpreadsheet::getSelectedAccessibleChildCount( ) 699 throw (uno::RuntimeException) 700 { 701 ScUnoGuard aGuard; 702 IsObjectValid(); 703 sal_Int32 nResult(0); 704 if (mpViewShell) 705 { 706 if (!mpMarkedRanges) 707 { 708 mpMarkedRanges = new ScRangeList(); 709 ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData()); 710 aMarkData.MarkToMulti(); 711 aMarkData.FillRangeListWithMarks(mpMarkedRanges, sal_False); 712 } 713 // is possible, because there shouldn't be overlapped ranges in it 714 if (mpMarkedRanges) 715 nResult = mpMarkedRanges->GetCellCount(); 716 } 717 return nResult; 718 } 719 720 uno::Reference<XAccessible > SAL_CALL 721 ScAccessibleSpreadsheet::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) 722 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 723 { 724 ScUnoGuard aGuard; 725 IsObjectValid(); 726 uno::Reference < XAccessible > xAccessible; 727 if (mpViewShell) 728 { 729 if (!mpMarkedRanges) 730 { 731 mpMarkedRanges = new ScRangeList(); 732 mpViewShell->GetViewData()->GetMarkData().FillRangeListWithMarks(mpMarkedRanges, sal_False); 733 } 734 if (mpMarkedRanges) 735 { 736 if (!mpSortedMarkedCells) 737 CreateSortedMarkedCells(); 738 if (mpSortedMarkedCells) 739 { 740 if ((nSelectedChildIndex < 0) || 741 (mpSortedMarkedCells->size() <= static_cast<sal_uInt32>(nSelectedChildIndex))) 742 throw lang::IndexOutOfBoundsException(); 743 else 744 xAccessible = getAccessibleCellAt((*mpSortedMarkedCells)[nSelectedChildIndex].Row(), (*mpSortedMarkedCells)[nSelectedChildIndex].Col()); 745 } 746 } 747 } 748 return xAccessible; 749 } 750 751 void SAL_CALL 752 ScAccessibleSpreadsheet::deselectAccessibleChild( sal_Int32 nChildIndex ) 753 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 754 { 755 ScUnoGuard aGuard; 756 IsObjectValid(); 757 758 if (nChildIndex < 0 || nChildIndex >= getAccessibleChildCount()) 759 throw lang::IndexOutOfBoundsException(); 760 761 if (mpViewShell) 762 { 763 sal_Int32 nCol(getAccessibleColumn(nChildIndex)); 764 sal_Int32 nRow(getAccessibleRow(nChildIndex)); 765 766 if (mpViewShell->GetViewData()->GetMarkData().IsCellMarked(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow))) 767 SelectCell(nRow, nCol, sal_True); 768 } 769 } 770 771 void ScAccessibleSpreadsheet::SelectCell(sal_Int32 nRow, sal_Int32 nCol, sal_Bool bDeselect) 772 { 773 mpViewShell->SetTabNo( maRange.aStart.Tab() ); 774 775 mpViewShell->DoneBlockMode( sal_True ); // continue selecting 776 mpViewShell->InitBlockMode( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), maRange.aStart.Tab(), bDeselect, sal_False, sal_False ); 777 778 mpViewShell->SelectionChanged(); 779 } 780 781 void ScAccessibleSpreadsheet::CreateSortedMarkedCells() 782 { 783 mpSortedMarkedCells = new std::vector<ScMyAddress>(); 784 mpSortedMarkedCells->reserve(mpMarkedRanges->GetCellCount()); 785 ScRange* pRange = mpMarkedRanges->First(); 786 while (pRange) 787 { 788 if (pRange->aStart.Tab() != pRange->aEnd.Tab()) 789 { 790 if ((maActiveCell.Tab() >= pRange->aStart.Tab()) || 791 maActiveCell.Tab() <= pRange->aEnd.Tab()) 792 { 793 ScRange aRange(*pRange); 794 aRange.aStart.SetTab(maActiveCell.Tab()); 795 aRange.aEnd.SetTab(maActiveCell.Tab()); 796 AddMarkedRange(aRange); 797 } 798 else 799 { 800 DBG_ERROR("Range of wrong table"); 801 } 802 } 803 else if(pRange->aStart.Tab() == maActiveCell.Tab()) 804 AddMarkedRange(*pRange); 805 else 806 { 807 DBG_ERROR("Range of wrong table"); 808 } 809 pRange = mpMarkedRanges->Next(); 810 } 811 std::sort(mpSortedMarkedCells->begin(), mpSortedMarkedCells->end()); 812 } 813 814 void ScAccessibleSpreadsheet::AddMarkedRange(const ScRange& rRange) 815 { 816 for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow) 817 { 818 for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol) 819 { 820 ScMyAddress aCell(nCol, nRow, maActiveCell.Tab()); 821 mpSortedMarkedCells->push_back(aCell); 822 } 823 } 824 } 825 826 //===== XServiceInfo ==================================================== 827 828 ::rtl::OUString SAL_CALL ScAccessibleSpreadsheet::getImplementationName(void) 829 throw (uno::RuntimeException) 830 { 831 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleSpreadsheet")); 832 } 833 834 uno::Sequence< ::rtl::OUString> SAL_CALL 835 ScAccessibleSpreadsheet::getSupportedServiceNames (void) 836 throw (uno::RuntimeException) 837 { 838 uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleTableBase::getSupportedServiceNames(); 839 sal_Int32 nOldSize(aSequence.getLength()); 840 aSequence.realloc(nOldSize + 1); 841 ::rtl::OUString* pNames = aSequence.getArray(); 842 843 pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.AccessibleSpreadsheet")); 844 845 return aSequence; 846 } 847 848 //===== XTypeProvider ======================================================= 849 850 uno::Sequence<sal_Int8> SAL_CALL 851 ScAccessibleSpreadsheet::getImplementationId(void) 852 throw (uno::RuntimeException) 853 { 854 ScUnoGuard aGuard; 855 IsObjectValid(); 856 static uno::Sequence<sal_Int8> aId; 857 if (aId.getLength() == 0) 858 { 859 aId.realloc (16); 860 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True); 861 } 862 return aId; 863 } 864 865 ///===== XAccessibleEventBroadcaster ===================================== 866 867 void SAL_CALL ScAccessibleSpreadsheet::addEventListener(const uno::Reference<XAccessibleEventListener>& xListener) 868 throw (uno::RuntimeException) 869 { 870 ScUnoGuard aGuard; 871 IsObjectValid(); 872 ScAccessibleTableBase::addEventListener(xListener); 873 874 if (!mbIsFocusSend) 875 { 876 mbIsFocusSend = sal_True; 877 CommitFocusGained(); 878 879 AccessibleEventObject aEvent; 880 aEvent.EventId = AccessibleEventId::ACTIVE_DESCENDANT_CHANGED; 881 aEvent.Source = uno::Reference< XAccessibleContext >(this); 882 aEvent.NewValue <<= getAccessibleCellAt(maActiveCell.Row(), maActiveCell.Col()); 883 884 CommitChange(aEvent); 885 } 886 } 887 888 //==== internal ========================================================= 889 890 Rectangle ScAccessibleSpreadsheet::GetBoundingBoxOnScreen() const 891 throw (uno::RuntimeException) 892 { 893 Rectangle aRect; 894 if (mpViewShell) 895 { 896 Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos); 897 if (pWindow) 898 aRect = pWindow->GetWindowExtentsRelative(NULL); 899 } 900 return aRect; 901 } 902 903 Rectangle ScAccessibleSpreadsheet::GetBoundingBox() const 904 throw (uno::RuntimeException) 905 { 906 Rectangle aRect; 907 if (mpViewShell) 908 { 909 Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos); 910 if (pWindow) 911 //#101986#; extends to the same window, because the parent is the document and it has the same window 912 aRect = pWindow->GetWindowExtentsRelative(pWindow); 913 } 914 return aRect; 915 } 916 917 sal_Bool ScAccessibleSpreadsheet::IsDefunc( 918 const uno::Reference<XAccessibleStateSet>& rxParentStates) 919 { 920 return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() || 921 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC)); 922 } 923 924 sal_Bool ScAccessibleSpreadsheet::IsEditable( 925 const uno::Reference<XAccessibleStateSet>& /* rxParentStates */) 926 { 927 sal_Bool bProtected(sal_False); 928 if (mpDoc && mpDoc->IsTabProtected(maRange.aStart.Tab())) 929 bProtected = sal_True; 930 return !bProtected; 931 } 932 933 sal_Bool ScAccessibleSpreadsheet::IsFocused() 934 { 935 sal_Bool bFocused(sal_False); 936 if (mpViewShell) 937 { 938 if (mpViewShell->GetViewData()->GetActivePart() == meSplitPos) 939 bFocused = mpViewShell->GetActiveWin()->HasFocus(); 940 } 941 return bFocused; 942 } 943 944 sal_Bool ScAccessibleSpreadsheet::IsCompleteSheetSelected() 945 { 946 sal_Bool bResult(sal_False); 947 if(mpViewShell) 948 { 949 //#103800#; use a copy of MarkData 950 ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData()); 951 aMarkData.MarkToMulti(); 952 if (aMarkData.IsAllMarked(maRange)) 953 bResult = sal_True; 954 } 955 return bResult; 956 } 957 958 ScDocument* ScAccessibleSpreadsheet::GetDocument(ScTabViewShell* pViewShell) 959 { 960 ScDocument* pDoc = NULL; 961 if (pViewShell) 962 pDoc = pViewShell->GetViewData()->GetDocument(); 963 return pDoc; 964 } 965 966 Rectangle ScAccessibleSpreadsheet::GetVisArea(ScTabViewShell* pViewShell, ScSplitPos eSplitPos) 967 { 968 Rectangle aVisArea; 969 if (pViewShell) 970 { 971 Window* pWindow = pViewShell->GetWindowByPos(eSplitPos); 972 if (pWindow) 973 { 974 aVisArea.SetPos(pViewShell->GetViewData()->GetPixPos(eSplitPos)); 975 aVisArea.SetSize(pWindow->GetSizePixel()); 976 } 977 } 978 return aVisArea; 979 } 980 981 Rectangle ScAccessibleSpreadsheet::GetVisCells(const Rectangle& rVisArea) 982 { 983 if (mpViewShell) 984 { 985 SCsCOL nStartX, nEndX; 986 SCsROW nStartY, nEndY; 987 988 mpViewShell->GetViewData()->GetPosFromPixel( 1, 1, meSplitPos, nStartX, nStartY); 989 mpViewShell->GetViewData()->GetPosFromPixel( rVisArea.GetWidth(), rVisArea.GetHeight(), meSplitPos, nEndX, nEndY); 990 991 return Rectangle(nStartX, nStartY, nEndX, nEndY); 992 } 993 else 994 return Rectangle(); 995 } 996