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