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 "AccessibleDocument.hxx" 33 #include "AccessibleSpreadsheet.hxx" 34 #include "tabvwsh.hxx" 35 #include "AccessibilityHints.hxx" 36 #include "document.hxx" 37 #include "drwlayer.hxx" 38 #include "unoguard.hxx" 39 #include "shapeuno.hxx" 40 #include "DrawModelBroadcaster.hxx" 41 #include "drawview.hxx" 42 #include "gridwin.hxx" 43 #include "AccessibleEditObject.hxx" 44 #include "scresid.hxx" 45 #ifndef SC_SC_HRC 46 #include "sc.hrc" 47 #endif 48 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 49 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_ 50 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 51 #endif 52 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLERELATIONTYPE_HPP_ 53 #include <com/sun/star/accessibility/AccessibleRelationType.hpp> 54 #endif 55 #include <com/sun/star/view/XSelectionSupplier.hpp> 56 #include <com/sun/star/drawing/XShape.hpp> 57 #include <com/sun/star/drawing/XShapes.hpp> 58 59 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX 60 #include <unotools/accessiblestatesethelper.hxx> 61 #endif 62 #include <tools/debug.hxx> 63 #include <tools/gen.hxx> 64 #include <svx/svdpage.hxx> 65 #include <svx/svdobj.hxx> 66 #include <svx/ShapeTypeHandler.hxx> 67 #include <svx/AccessibleShape.hxx> 68 #include <svx/AccessibleShapeTreeInfo.hxx> 69 #include <svx/AccessibleShapeInfo.hxx> 70 #include <comphelper/sequence.hxx> 71 #include <sfx2/viewfrm.hxx> 72 #include <svx/unoshcol.hxx> 73 #include <svx/unoshape.hxx> 74 #include <unotools/accessiblerelationsethelper.hxx> 75 #include <toolkit/helper/convert.hxx> 76 77 #include <list> 78 #include <algorithm> 79 80 using namespace ::com::sun::star; 81 using namespace ::com::sun::star::accessibility; 82 using ::std::for_each; 83 84 //===== internal ======================================================== 85 86 struct ScAccessibleShapeData 87 { 88 ScAccessibleShapeData() : pAccShape(NULL), pRelationCell(NULL), bSelected(sal_False), bSelectable(sal_True) {} 89 ~ScAccessibleShapeData(); 90 mutable ::accessibility::AccessibleShape* pAccShape; 91 mutable ScAddress* pRelationCell; // if it is NULL this shape is anchored on the table 92 // SdrObject* pShape; 93 com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape; 94 mutable sal_Bool bSelected; 95 sal_Bool bSelectable; 96 }; 97 98 ScAccessibleShapeData::~ScAccessibleShapeData() 99 { 100 if (pAccShape) 101 { 102 pAccShape->dispose(); 103 pAccShape->release(); 104 } 105 } 106 107 struct ScShapeDataLess 108 { 109 rtl::OUString msLayerId; 110 rtl::OUString msZOrder; 111 ScShapeDataLess() 112 : msLayerId(RTL_CONSTASCII_USTRINGPARAM( "LayerID" )), 113 msZOrder(RTL_CONSTASCII_USTRINGPARAM( "ZOrder" )) 114 { 115 } 116 void ConvertLayerId(sal_Int16& rLayerID) const // changes the number of the LayerId so it the accessibility order 117 { 118 switch (rLayerID) 119 { 120 case SC_LAYER_FRONT: 121 rLayerID = 1; 122 break; 123 case SC_LAYER_BACK: 124 rLayerID = 0; 125 break; 126 case SC_LAYER_INTERN: 127 rLayerID = 2; 128 break; 129 case SC_LAYER_CONTROLS: 130 rLayerID = 3; 131 break; 132 } 133 } 134 sal_Bool LessThanSheet(const ScAccessibleShapeData* pData) const 135 { 136 sal_Bool bResult(sal_False); 137 uno::Reference< beans::XPropertySet> xProps(pData->xShape, uno::UNO_QUERY); 138 if (xProps.is()) 139 { 140 uno::Any aPropAny = xProps->getPropertyValue(msLayerId); 141 sal_Int16 nLayerID = 0; 142 if( (aPropAny >>= nLayerID) ) 143 { 144 if (nLayerID == SC_LAYER_BACK) 145 bResult = sal_True; 146 } 147 } 148 return bResult; 149 } 150 sal_Bool operator()(const ScAccessibleShapeData* pData1, const ScAccessibleShapeData* pData2) const 151 { 152 sal_Bool bResult(sal_False); 153 if (pData1 && pData2) 154 { 155 uno::Reference< beans::XPropertySet> xProps1(pData1->xShape, uno::UNO_QUERY); 156 uno::Reference< beans::XPropertySet> xProps2(pData2->xShape, uno::UNO_QUERY); 157 if (xProps1.is() && xProps2.is()) 158 { 159 uno::Any aPropAny1 = xProps1->getPropertyValue(msLayerId); 160 uno::Any aPropAny2 = xProps2->getPropertyValue(msLayerId); 161 sal_Int16 nLayerID1(0); 162 sal_Int16 nLayerID2(0); 163 if( (aPropAny1 >>= nLayerID1) && (aPropAny2 >>= nLayerID2) ) 164 { 165 if (nLayerID1 == nLayerID2) 166 { 167 uno::Any aAny1 = xProps1->getPropertyValue(msZOrder); 168 sal_Int32 nZOrder1 = 0; 169 uno::Any aAny2 = xProps2->getPropertyValue(msZOrder); 170 sal_Int32 nZOrder2 = 0; 171 if ( (aAny1 >>= nZOrder1) && (aAny2 >>= nZOrder2) ) 172 bResult = (nZOrder1 < nZOrder2); 173 } 174 else 175 { 176 ConvertLayerId(nLayerID1); 177 ConvertLayerId(nLayerID2); 178 bResult = (nLayerID1 < nLayerID2); 179 } 180 } 181 } 182 } 183 else if (pData1 && !pData2) 184 bResult = LessThanSheet(pData1); 185 else if (!pData1 && pData2) 186 bResult = !LessThanSheet(pData2); 187 else 188 bResult = sal_False; 189 return bResult; 190 } 191 }; 192 193 struct DeselectShape 194 { 195 void operator() (const ScAccessibleShapeData* pAccShapeData) const 196 { 197 if (pAccShapeData) 198 { 199 pAccShapeData->bSelected = sal_False; 200 if (pAccShapeData->pAccShape) 201 pAccShapeData->pAccShape->ResetState(AccessibleStateType::SELECTED); 202 } 203 } 204 }; 205 206 struct SelectShape 207 { 208 uno::Reference < drawing::XShapes > xShapes; 209 SelectShape(uno::Reference<drawing::XShapes>& xTemp) : xShapes(xTemp) {} 210 void operator() (const ScAccessibleShapeData* pAccShapeData) const 211 { 212 if (pAccShapeData && pAccShapeData->bSelectable) 213 { 214 pAccShapeData->bSelected = sal_True; 215 if (pAccShapeData->pAccShape) 216 pAccShapeData->pAccShape->SetState(AccessibleStateType::SELECTED); 217 if (xShapes.is()) 218 xShapes->add(pAccShapeData->xShape); 219 } 220 } 221 }; 222 223 struct Destroy 224 { 225 void operator() (ScAccessibleShapeData* pData) 226 { 227 if (pData) 228 DELETEZ(pData); 229 } 230 }; 231 232 class ScChildrenShapes : public SfxListener, 233 public ::accessibility::IAccessibleParent 234 { 235 public: 236 ScChildrenShapes(ScAccessibleDocument* pAccessibleDocument, ScTabViewShell* pViewShell, ScSplitPos eSplitPos); 237 ~ScChildrenShapes(); 238 239 ///===== SfxListener ===================================================== 240 241 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); 242 243 ///===== IAccessibleParent =============================================== 244 245 virtual sal_Bool ReplaceChild ( 246 ::accessibility::AccessibleShape* pCurrentChild, 247 const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape, 248 const long _nIndex, 249 const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo 250 ) throw (::com::sun::star::uno::RuntimeException); 251 252 ///===== Internal ======================================================== 253 void SetDrawBroadcaster(); 254 255 sal_Int32 GetCount() const; 256 uno::Reference< XAccessible > Get(const ScAccessibleShapeData* pData) const; 257 uno::Reference< XAccessible > Get(sal_Int32 nIndex) const; 258 uno::Reference< XAccessible > GetAt(const awt::Point& rPoint) const; 259 260 // gets the index of the shape starting on 0 (without the index of the table) 261 // returns the selected shape 262 sal_Bool IsSelected(sal_Int32 nIndex, 263 com::sun::star::uno::Reference<com::sun::star::drawing::XShape>& rShape) const; 264 265 sal_Bool SelectionChanged(); 266 267 void Select(sal_Int32 nIndex); 268 void DeselectAll(); // deselect also the table 269 void SelectAll(); 270 sal_Int32 GetSelectedCount() const; 271 uno::Reference< XAccessible > GetSelected(sal_Int32 nSelectedChildIndex, sal_Bool bTabSelected) const; 272 void Deselect(sal_Int32 nChildIndex); 273 274 SdrPage* GetDrawPage() const; 275 276 utl::AccessibleRelationSetHelper* GetRelationSet(const ScAddress* pAddress) const; 277 278 void VisAreaChanged() const; 279 private: 280 typedef std::vector<ScAccessibleShapeData*> SortedShapes; 281 282 mutable SortedShapes maZOrderedShapes; // a null pointer represents the sheet in the correct order 283 284 mutable ::accessibility::AccessibleShapeTreeInfo maShapeTreeInfo; 285 mutable com::sun::star::uno::Reference<com::sun::star::view::XSelectionSupplier> xSelectionSupplier; 286 mutable sal_uInt32 mnSdrObjCount; 287 mutable sal_uInt32 mnShapesSelected; 288 ScTabViewShell* mpViewShell; 289 ScAccessibleDocument* mpAccessibleDocument; 290 ScSplitPos meSplitPos; 291 292 void FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const; 293 sal_Bool FindSelectedShapesChanges(const com::sun::star::uno::Reference<com::sun::star::drawing::XShapes>& xShapes, sal_Bool bCommitChange) const; 294 void FillSelectionSupplier() const; 295 296 ScAddress* GetAnchor(const uno::Reference<drawing::XShape>& xShape) const; 297 uno::Reference<XAccessibleRelationSet> GetRelationSet(const ScAccessibleShapeData* pData) const; 298 void CheckWhetherAnchorChanged(const uno::Reference<drawing::XShape>& xShape) const; 299 void SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const; 300 void AddShape(const uno::Reference<drawing::XShape>& xShape, sal_Bool bCommitChange) const; 301 void RemoveShape(const uno::Reference<drawing::XShape>& xShape) const; 302 303 sal_Bool FindShape(const uno::Reference<drawing::XShape>& xShape, SortedShapes::iterator& rItr) const; 304 305 sal_Int8 Compare(const ScAccessibleShapeData* pData1, 306 const ScAccessibleShapeData* pData2) const; 307 }; 308 309 ScChildrenShapes::ScChildrenShapes(ScAccessibleDocument* pAccessibleDocument, ScTabViewShell* pViewShell, ScSplitPos eSplitPos) 310 : 311 mnShapesSelected(0), 312 mpViewShell(pViewShell), 313 mpAccessibleDocument(pAccessibleDocument), 314 meSplitPos(eSplitPos) 315 { 316 FillSelectionSupplier(); 317 maZOrderedShapes.push_back(NULL); // add an element which represents the table 318 319 GetCount(); // fill list with filtered shapes (no internal shapes) 320 321 if (mnShapesSelected) 322 { 323 //set flag on every selected shape 324 if (!xSelectionSupplier.is()) 325 throw uno::RuntimeException(); 326 327 uno::Reference<drawing::XShapes> xShapes(xSelectionSupplier->getSelection(), uno::UNO_QUERY); 328 if (xShapes.is()) 329 FindSelectedShapesChanges(xShapes, sal_False); 330 } 331 if (pViewShell) 332 { 333 SfxBroadcaster* pDrawBC = pViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster(); 334 if (pDrawBC) 335 { 336 StartListening(*pDrawBC); 337 338 maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(pViewShell->GetViewData()->GetDocument()->GetDrawLayer()) ); 339 maShapeTreeInfo.SetSdrView(pViewShell->GetViewData()->GetScDrawView()); 340 maShapeTreeInfo.SetController(NULL); 341 maShapeTreeInfo.SetWindow(pViewShell->GetWindowByPos(meSplitPos)); 342 maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument); 343 } 344 } 345 } 346 347 ScChildrenShapes::~ScChildrenShapes() 348 { 349 std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), Destroy()); 350 if (mpViewShell) 351 { 352 SfxBroadcaster* pDrawBC = mpViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster(); 353 if (pDrawBC) 354 EndListening(*pDrawBC); 355 } 356 } 357 358 void ScChildrenShapes::SetDrawBroadcaster() 359 { 360 if (mpViewShell) 361 { 362 SfxBroadcaster* pDrawBC = mpViewShell->GetViewData()->GetDocument()->GetDrawBroadcaster(); 363 if (pDrawBC) 364 { 365 StartListening(*pDrawBC, sal_True); 366 367 maShapeTreeInfo.SetModelBroadcaster( new ScDrawModelBroadcaster(mpViewShell->GetViewData()->GetDocument()->GetDrawLayer()) ); 368 maShapeTreeInfo.SetSdrView(mpViewShell->GetViewData()->GetScDrawView()); 369 maShapeTreeInfo.SetController(NULL); 370 maShapeTreeInfo.SetWindow(mpViewShell->GetWindowByPos(meSplitPos)); 371 maShapeTreeInfo.SetViewForwarder(mpAccessibleDocument); 372 } 373 } 374 } 375 376 void ScChildrenShapes::Notify(SfxBroadcaster&, const SfxHint& rHint) 377 { 378 if ( rHint.ISA( SdrHint ) ) 379 { 380 const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint ); 381 if (pSdrHint) 382 { 383 SdrObject* pObj = const_cast<SdrObject*>(pSdrHint->GetObject()); 384 if (pObj && /*(pObj->GetLayer() != SC_LAYER_INTERN) && */(pObj->GetPage() == GetDrawPage()) && 385 (pObj->GetPage() == pObj->GetObjList()) ) //#108480# only do something if the object lies direct on the page 386 { 387 switch (pSdrHint->GetKind()) 388 { 389 case HINT_OBJCHG : // Objekt geaendert 390 { 391 uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY); 392 if (xShape.is()) 393 { 394 ScShapeDataLess aLess; 395 std::sort(maZOrderedShapes.begin(), maZOrderedShapes.end(), aLess); // sort, because the z index or layer could be changed 396 CheckWhetherAnchorChanged(xShape); 397 } 398 } 399 break; 400 case HINT_OBJINSERTED : // Neues Zeichenobjekt eingefuegt 401 { 402 uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY); 403 if (xShape.is()) 404 AddShape(xShape, sal_True); 405 } 406 break; 407 case HINT_OBJREMOVED : // Zeichenobjekt aus Liste entfernt 408 { 409 uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY); 410 if (xShape.is()) 411 RemoveShape(xShape); 412 } 413 break; 414 default : 415 { 416 // other events are not interesting 417 } 418 break; 419 } 420 } 421 } 422 } 423 } 424 425 sal_Bool ScChildrenShapes::ReplaceChild (::accessibility::AccessibleShape* pCurrentChild, 426 const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& _rxShape, 427 const long _nIndex, const ::accessibility::AccessibleShapeTreeInfo& _rShapeTreeInfo) 428 throw (uno::RuntimeException) 429 { 430 // create the new child 431 ::accessibility::AccessibleShape* pReplacement = ::accessibility::ShapeTypeHandler::Instance().CreateAccessibleObject ( 432 ::accessibility::AccessibleShapeInfo ( _rxShape, pCurrentChild->getAccessibleParent(), this, _nIndex ), 433 _rShapeTreeInfo 434 ); 435 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xNewChild( pReplacement ); // keep this alive (do this before calling Init!) 436 if ( pReplacement ) 437 pReplacement->Init(); 438 439 sal_Bool bResult(sal_False); 440 if (pCurrentChild && pReplacement) 441 { 442 DBG_ASSERT(pCurrentChild->GetXShape().get() == pReplacement->GetXShape().get(), "XShape changes and should be inserted sorted"); 443 SortedShapes::iterator aItr; 444 FindShape(pCurrentChild->GetXShape(), aItr); 445 if (aItr != maZOrderedShapes.end() && (*aItr)) 446 { 447 if ((*aItr)->pAccShape) 448 { 449 DBG_ASSERT((*aItr)->pAccShape == pCurrentChild, "wrong child found"); 450 AccessibleEventObject aEvent; 451 aEvent.EventId = AccessibleEventId::CHILD; 452 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument); 453 aEvent.OldValue <<= uno::makeAny(uno::Reference<XAccessible>(pCurrentChild)); 454 455 mpAccessibleDocument->CommitChange(aEvent); // child is gone - event 456 457 pCurrentChild->dispose(); 458 } 459 (*aItr)->pAccShape = pReplacement; 460 AccessibleEventObject aEvent; 461 aEvent.EventId = AccessibleEventId::CHILD; 462 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument); 463 aEvent.NewValue <<= uno::makeAny(uno::Reference<XAccessible>(pReplacement)); 464 465 mpAccessibleDocument->CommitChange(aEvent); // child is new - event 466 bResult = sal_True; 467 } 468 } 469 return bResult; 470 } 471 472 sal_Int32 ScChildrenShapes::GetCount() const 473 { 474 SdrPage* pDrawPage = GetDrawPage(); 475 if (pDrawPage && (maZOrderedShapes.size() == 1)) // the table is always in 476 { 477 mnSdrObjCount = pDrawPage->GetObjCount(); 478 maZOrderedShapes.reserve(mnSdrObjCount + 1); // the table is always in 479 for (sal_uInt32 i = 0; i < mnSdrObjCount; ++i) 480 { 481 SdrObject* pObj = pDrawPage->GetObj(i); 482 if (pObj/* && (pObj->GetLayer() != SC_LAYER_INTERN)*/) 483 { 484 uno::Reference< drawing::XShape > xShape (pObj->getUnoShape(), uno::UNO_QUERY); 485 AddShape(xShape, sal_False); //inserts in the correct order 486 } 487 } 488 } 489 return maZOrderedShapes.size(); 490 } 491 492 uno::Reference< XAccessible > ScChildrenShapes::Get(const ScAccessibleShapeData* pData) const 493 { 494 if (!pData) 495 return NULL; 496 497 if (!pData->pAccShape) 498 { 499 ::accessibility::ShapeTypeHandler& rShapeHandler = ::accessibility::ShapeTypeHandler::Instance(); 500 ::accessibility::AccessibleShapeInfo aShapeInfo(pData->xShape, mpAccessibleDocument, const_cast<ScChildrenShapes*>(this)); 501 pData->pAccShape = rShapeHandler.CreateAccessibleObject( 502 aShapeInfo, maShapeTreeInfo); 503 if (pData->pAccShape) 504 { 505 pData->pAccShape->acquire(); 506 pData->pAccShape->Init(); 507 if (pData->bSelected) 508 pData->pAccShape->SetState(AccessibleStateType::SELECTED); 509 if (!pData->bSelectable) 510 pData->pAccShape->ResetState(AccessibleStateType::SELECTABLE); 511 pData->pAccShape->SetRelationSet(GetRelationSet(pData)); 512 } 513 } 514 return pData->pAccShape; 515 } 516 517 uno::Reference< XAccessible > ScChildrenShapes::Get(sal_Int32 nIndex) const 518 { 519 if (maZOrderedShapes.size() <= 1) 520 GetCount(); // fill list with filtered shapes (no internal shapes) 521 522 if (static_cast<sal_uInt32>(nIndex) >= maZOrderedShapes.size()) 523 return NULL; 524 525 return Get(maZOrderedShapes[nIndex]); 526 } 527 528 uno::Reference< XAccessible > ScChildrenShapes::GetAt(const awt::Point& rPoint) const 529 { 530 uno::Reference<XAccessible> xAccessible; 531 if(mpViewShell) 532 { 533 sal_Int32 i(maZOrderedShapes.size() - 1); 534 sal_Bool bFound(sal_False); 535 while (!bFound && i >= 0) 536 { 537 ScAccessibleShapeData* pShape = maZOrderedShapes[i]; 538 if (pShape) 539 { 540 if (!pShape->pAccShape) 541 Get(pShape); 542 543 if (pShape->pAccShape) 544 { 545 Point aPoint(VCLPoint(rPoint)); 546 aPoint -= VCLRectangle(pShape->pAccShape->getBounds()).TopLeft(); 547 if (pShape->pAccShape->containsPoint(AWTPoint(aPoint))) 548 { 549 xAccessible = pShape->pAccShape; 550 bFound = sal_True; 551 } 552 } 553 else 554 { 555 DBG_ERRORFILE("I should have an accessible shape now!"); 556 } 557 } 558 else 559 bFound = sal_True; // this is the sheet and it lies before the rest of the shapes which are background shapes 560 561 --i; 562 } 563 } 564 return xAccessible; 565 } 566 567 sal_Bool ScChildrenShapes::IsSelected(sal_Int32 nIndex, 568 uno::Reference<drawing::XShape>& rShape) const 569 { 570 sal_Bool bResult (sal_False); 571 if (maZOrderedShapes.size() <= 1) 572 GetCount(); // fill list with filtered shapes (no internal shapes) 573 574 if (!xSelectionSupplier.is()) 575 throw uno::RuntimeException(); 576 577 if (!maZOrderedShapes[nIndex]) 578 return sal_False; 579 580 bResult = maZOrderedShapes[nIndex]->bSelected; 581 rShape = maZOrderedShapes[nIndex]->xShape; 582 583 #ifdef DBG_UTIL // test whether it is truly selected by a slower method 584 uno::Reference< drawing::XShape > xReturnShape; 585 sal_Bool bDebugResult(sal_False); 586 uno::Reference<container::XIndexAccess> xIndexAccess; 587 xSelectionSupplier->getSelection() >>= xIndexAccess; 588 589 if (xIndexAccess.is()) 590 { 591 sal_Int32 nCount(xIndexAccess->getCount()); 592 if (nCount) 593 { 594 uno::Reference< drawing::XShape > xShape; 595 uno::Reference< drawing::XShape > xIndexShape = maZOrderedShapes[nIndex]->xShape; 596 sal_Int32 i(0); 597 while (!bDebugResult && (i < nCount)) 598 { 599 xIndexAccess->getByIndex(i) >>= xShape; 600 if (xShape.is() && (xIndexShape.get() == xShape.get())) 601 { 602 bDebugResult = sal_True; 603 xReturnShape = xShape; 604 } 605 else 606 ++i; 607 } 608 } 609 } 610 DBG_ASSERT((bResult == bDebugResult) && ((bResult && (rShape.get() == xReturnShape.get())) || !bResult), "found the wrong shape or result"); 611 #endif 612 613 return bResult; 614 } 615 616 sal_Bool ScChildrenShapes::SelectionChanged() 617 { 618 sal_Bool bResult(sal_False); 619 if (!xSelectionSupplier.is()) 620 throw uno::RuntimeException(); 621 622 uno::Reference<drawing::XShapes> xShapes(xSelectionSupplier->getSelection(), uno::UNO_QUERY); 623 624 bResult = FindSelectedShapesChanges(xShapes, sal_True); 625 626 return bResult; 627 } 628 629 void ScChildrenShapes::Select(sal_Int32 nIndex) 630 { 631 if (maZOrderedShapes.size() <= 1) 632 GetCount(); // fill list with filtered shapes (no internal shapes) 633 634 if (!xSelectionSupplier.is()) 635 throw uno::RuntimeException(); 636 637 if (!maZOrderedShapes[nIndex]) 638 return; 639 640 uno::Reference<drawing::XShape> xShape; 641 if (!IsSelected(nIndex, xShape) && maZOrderedShapes[nIndex]->bSelectable) 642 { 643 uno::Reference<drawing::XShapes> xShapes; 644 xSelectionSupplier->getSelection() >>= xShapes; 645 646 if (!xShapes.is()) 647 xShapes = new SvxShapeCollection(); 648 649 xShapes->add(maZOrderedShapes[nIndex]->xShape); 650 651 try 652 { 653 xSelectionSupplier->select(uno::makeAny(xShapes)); 654 maZOrderedShapes[nIndex]->bSelected = sal_True; 655 if (maZOrderedShapes[nIndex]->pAccShape) 656 maZOrderedShapes[nIndex]->pAccShape->SetState(AccessibleStateType::SELECTED); 657 } 658 catch (lang::IllegalArgumentException&) 659 { 660 } 661 } 662 } 663 664 void ScChildrenShapes::DeselectAll() 665 { 666 if (!xSelectionSupplier.is()) 667 throw uno::RuntimeException(); 668 669 sal_Bool bSomethingSelected(sal_True); 670 try 671 { 672 xSelectionSupplier->select(uno::Any()); //deselects all 673 } 674 catch (lang::IllegalArgumentException&) 675 { 676 DBG_ERRORFILE("nothing selected before"); 677 bSomethingSelected = sal_False; 678 } 679 680 if (bSomethingSelected) 681 std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), DeselectShape()); 682 } 683 684 void ScChildrenShapes::SelectAll() 685 { 686 if (!xSelectionSupplier.is()) 687 throw uno::RuntimeException(); 688 689 if (maZOrderedShapes.size() <= 1) 690 GetCount(); // fill list with filtered shapes (no internal shapes) 691 692 if (maZOrderedShapes.size() > 1) 693 { 694 uno::Reference<drawing::XShapes> xShapes; 695 xShapes = new SvxShapeCollection(); 696 697 try 698 { 699 std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), SelectShape(xShapes)); 700 xSelectionSupplier->select(uno::makeAny(xShapes)); 701 } 702 catch (lang::IllegalArgumentException&) 703 { 704 SelectionChanged(); // find all selected shapes and set the flags 705 } 706 } 707 } 708 709 void ScChildrenShapes::FillShapes(std::vector < uno::Reference < drawing::XShape > >& rShapes) const 710 { 711 uno::Reference<container::XIndexAccess> xIndexAccess; 712 xSelectionSupplier->getSelection() >>= xIndexAccess; 713 714 if (xIndexAccess.is()) 715 { 716 sal_uInt32 nCount(xIndexAccess->getCount()); 717 for (sal_uInt32 i = 0; i < nCount; ++i) 718 { 719 uno::Reference<drawing::XShape> xShape; 720 xIndexAccess->getByIndex(i) >>= xShape; 721 if (xShape.is()) 722 rShapes.push_back(xShape); 723 } 724 } 725 } 726 727 sal_Int32 ScChildrenShapes::GetSelectedCount() const 728 { 729 if (!xSelectionSupplier.is()) 730 throw uno::RuntimeException(); 731 732 std::vector < uno::Reference < drawing::XShape > > aShapes; 733 FillShapes(aShapes); 734 735 return aShapes.size(); 736 } 737 738 uno::Reference< XAccessible > ScChildrenShapes::GetSelected(sal_Int32 nSelectedChildIndex, sal_Bool bTabSelected) const 739 { 740 uno::Reference< XAccessible > xAccessible; 741 742 if (maZOrderedShapes.size() <= 1) 743 GetCount(); // fill list with shapes 744 745 if (!bTabSelected) 746 { 747 std::vector < uno::Reference < drawing::XShape > > aShapes; 748 FillShapes(aShapes); 749 750 SortedShapes::iterator aItr; 751 if (FindShape(aShapes[nSelectedChildIndex], aItr)) 752 xAccessible = Get(aItr - maZOrderedShapes.begin()); 753 } 754 else 755 { 756 SortedShapes::iterator aItr = maZOrderedShapes.begin(); 757 SortedShapes::iterator aEndItr = maZOrderedShapes.end(); 758 sal_Bool bFound(sal_False); 759 while(!bFound && aItr != aEndItr) 760 { 761 if (*aItr) 762 { 763 if ((*aItr)->bSelected) 764 { 765 if (nSelectedChildIndex == 0) 766 bFound = sal_True; 767 else 768 --nSelectedChildIndex; 769 } 770 } 771 else 772 { 773 if (nSelectedChildIndex == 0) 774 bFound = sal_True; 775 else 776 --nSelectedChildIndex; 777 } 778 if (!bFound) 779 ++aItr; 780 } 781 if (bFound && *aItr) 782 xAccessible = (*aItr)->pAccShape; 783 } 784 785 return xAccessible; 786 } 787 788 void ScChildrenShapes::Deselect(sal_Int32 nChildIndex) 789 { 790 uno::Reference<drawing::XShape> xShape; 791 if (IsSelected(nChildIndex, xShape)) // returns false if it is the sheet 792 { 793 if (xShape.is()) 794 { 795 uno::Reference<drawing::XShapes> xShapes; 796 xSelectionSupplier->getSelection() >>= xShapes; 797 if (xShapes.is()) 798 xShapes->remove(xShape); 799 800 try 801 { 802 xSelectionSupplier->select(uno::makeAny(xShapes)); 803 } 804 catch (lang::IllegalArgumentException&) 805 { 806 DBG_ERRORFILE("something not selectable"); 807 } 808 809 maZOrderedShapes[nChildIndex]->bSelected = sal_False; 810 if (maZOrderedShapes[nChildIndex]->pAccShape) 811 maZOrderedShapes[nChildIndex]->pAccShape->ResetState(AccessibleStateType::SELECTED); 812 } 813 } 814 } 815 816 817 SdrPage* ScChildrenShapes::GetDrawPage() const 818 { 819 SCTAB nTab(mpAccessibleDocument->getVisibleTable()); 820 SdrPage* pDrawPage = NULL; 821 if (mpViewShell) 822 { 823 ScDocument* pDoc = mpViewShell->GetViewData()->GetDocument(); 824 if (pDoc && pDoc->GetDrawLayer()) 825 { 826 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); 827 if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab)) 828 pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(static_cast<sal_Int16>(nTab))); 829 } 830 } 831 return pDrawPage; 832 } 833 834 struct SetRelation 835 { 836 const ScChildrenShapes* mpChildrenShapes; 837 mutable utl::AccessibleRelationSetHelper* mpRelationSet; 838 const ScAddress* mpAddress; 839 SetRelation(const ScChildrenShapes* pChildrenShapes, const ScAddress* pAddress) 840 : 841 mpChildrenShapes(pChildrenShapes), 842 mpRelationSet(NULL), 843 mpAddress(pAddress) 844 { 845 } 846 void operator() (const ScAccessibleShapeData* pAccShapeData) const 847 { 848 if (pAccShapeData && 849 ((!pAccShapeData->pRelationCell && !mpAddress) || 850 (pAccShapeData->pRelationCell && mpAddress && (*(pAccShapeData->pRelationCell) == *mpAddress)))) 851 { 852 if (!mpRelationSet) 853 mpRelationSet = new utl::AccessibleRelationSetHelper(); 854 855 AccessibleRelation aRelation; 856 aRelation.TargetSet.realloc(1); 857 aRelation.TargetSet[0] = mpChildrenShapes->Get(pAccShapeData); 858 aRelation.RelationType = AccessibleRelationType::CONTROLLER_FOR; 859 860 mpRelationSet->AddRelation(aRelation); 861 } 862 } 863 }; 864 865 utl::AccessibleRelationSetHelper* ScChildrenShapes::GetRelationSet(const ScAddress* pAddress) const 866 { 867 SetRelation aSetRelation(this, pAddress); 868 ::std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), aSetRelation); 869 return aSetRelation.mpRelationSet; 870 } 871 872 sal_Bool ScChildrenShapes::FindSelectedShapesChanges(const uno::Reference<drawing::XShapes>& xShapes, sal_Bool /* bCommitChange */) const 873 { 874 sal_Bool bResult(sal_False); 875 SortedShapes aShapesList; 876 uno::Reference<container::XIndexAccess> xIndexAcc(xShapes, uno::UNO_QUERY); 877 if (xIndexAcc.is()) 878 { 879 mnShapesSelected = xIndexAcc->getCount(); 880 for (sal_uInt32 i = 0; i < mnShapesSelected; ++i) 881 { 882 uno::Reference< drawing::XShape > xShape; 883 xIndexAcc->getByIndex(i) >>= xShape; 884 if (xShape.is()) 885 { 886 ScAccessibleShapeData* pShapeData = new ScAccessibleShapeData(); 887 pShapeData->xShape = xShape; 888 aShapesList.push_back(pShapeData); 889 } 890 } 891 } 892 else 893 mnShapesSelected = 0; 894 ScShapeDataLess aLess; 895 std::sort(aShapesList.begin(), aShapesList.end(), aLess); 896 897 SortedShapes::iterator aXShapesItr(aShapesList.begin()); 898 SortedShapes::const_iterator aXShapesEndItr(aShapesList.end()); 899 SortedShapes::iterator aDataItr(maZOrderedShapes.begin()); 900 SortedShapes::const_iterator aDataEndItr(maZOrderedShapes.end()); 901 SortedShapes::const_iterator aFocusedItr = aDataEndItr; 902 while((aDataItr != aDataEndItr)) 903 { 904 if (*aDataItr) // is it realy a shape or only the sheet 905 { 906 sal_Int8 nComp(0); 907 if (aXShapesItr == aXShapesEndItr) 908 nComp = -1; // simulate that the Shape is lower, so the selction state will be removed 909 else 910 nComp = Compare(*aDataItr, *aXShapesItr); 911 if (nComp == 0) 912 { 913 if (!(*aDataItr)->bSelected) 914 { 915 (*aDataItr)->bSelected = sal_True; 916 if ((*aDataItr)->pAccShape) 917 { 918 (*aDataItr)->pAccShape->SetState(AccessibleStateType::SELECTED); 919 (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED); 920 bResult = sal_True; 921 } 922 aFocusedItr = aDataItr; 923 } 924 ++aDataItr; 925 ++aXShapesItr; 926 } 927 else if (nComp < 0) 928 { 929 if ((*aDataItr)->bSelected) 930 { 931 (*aDataItr)->bSelected = sal_False; 932 if ((*aDataItr)->pAccShape) 933 { 934 (*aDataItr)->pAccShape->ResetState(AccessibleStateType::SELECTED); 935 (*aDataItr)->pAccShape->ResetState(AccessibleStateType::FOCUSED); 936 bResult = sal_True; 937 } 938 } 939 ++aDataItr; 940 } 941 else 942 { 943 DBG_ERRORFILE("here is a selected shape which is not in the childlist"); 944 ++aXShapesItr; 945 --mnShapesSelected; 946 } 947 } 948 else 949 ++aDataItr; 950 } 951 if ((aFocusedItr != aDataEndItr) && (*aFocusedItr)->pAccShape && (mnShapesSelected == 1)) 952 (*aFocusedItr)->pAccShape->SetState(AccessibleStateType::FOCUSED); 953 954 std::for_each(aShapesList.begin(), aShapesList.end(), Destroy()); 955 956 return bResult; 957 } 958 959 void ScChildrenShapes::FillSelectionSupplier() const 960 { 961 if (!xSelectionSupplier.is() && mpViewShell) 962 { 963 SfxViewFrame* pViewFrame = mpViewShell->GetViewFrame(); 964 if (pViewFrame) 965 { 966 xSelectionSupplier = uno::Reference<view::XSelectionSupplier>(pViewFrame->GetFrame().GetController(), uno::UNO_QUERY); 967 if (xSelectionSupplier.is()) 968 { 969 if (mpAccessibleDocument) 970 xSelectionSupplier->addSelectionChangeListener(mpAccessibleDocument); 971 uno::Reference<drawing::XShapes> xShapes (xSelectionSupplier->getSelection(), uno::UNO_QUERY); 972 if (xShapes.is()) 973 mnShapesSelected = xShapes->getCount(); 974 } 975 } 976 } 977 } 978 979 ScAddress* ScChildrenShapes::GetAnchor(const uno::Reference<drawing::XShape>& xShape) const 980 { 981 ScAddress* pAddress = NULL; 982 if (mpViewShell) 983 { 984 SvxShape* pShapeImp = SvxShape::getImplementation(xShape); 985 uno::Reference<beans::XPropertySet> xShapeProp(xShape, uno::UNO_QUERY); 986 if (pShapeImp && xShapeProp.is()) 987 { 988 SdrObject *pSdrObj = pShapeImp->GetSdrObject(); 989 if (pSdrObj) 990 { 991 if (ScDrawLayer::GetAnchor(pSdrObj) == SCA_CELL) 992 { 993 ScDocument* pDoc = mpViewShell->GetViewData()->GetDocument(); 994 if (pDoc) 995 { 996 rtl::OUString sCaptionShape(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CaptionShape")); 997 awt::Point aPoint(xShape->getPosition()); 998 awt::Size aSize(xShape->getSize()); 999 rtl::OUString sType(xShape->getShapeType()); 1000 Rectangle aRectangle(aPoint.X, aPoint.Y, aPoint.X + aSize.Width, aPoint.Y + aSize.Height); 1001 if ( sType.equals(sCaptionShape) ) 1002 { 1003 awt::Point aRelativeCaptionPoint; 1004 rtl::OUString sCaptionPoint( RTL_CONSTASCII_USTRINGPARAM( "CaptionPoint" )); 1005 xShapeProp->getPropertyValue( sCaptionPoint ) >>= aRelativeCaptionPoint; 1006 Point aCoreRelativeCaptionPoint(aRelativeCaptionPoint.X, aRelativeCaptionPoint.Y); 1007 Point aCoreAbsoluteCaptionPoint(aPoint.X, aPoint.Y); 1008 aCoreAbsoluteCaptionPoint += aCoreRelativeCaptionPoint; 1009 aRectangle.Union(Rectangle(aCoreAbsoluteCaptionPoint, aCoreAbsoluteCaptionPoint)); 1010 } 1011 ScRange aRange = pDoc->GetRange(mpAccessibleDocument->getVisibleTable(), aRectangle); 1012 pAddress = new ScAddress(aRange.aStart); 1013 } 1014 } 1015 // else 1016 // do nothing, because it is always a NULL Pointer 1017 } 1018 } 1019 } 1020 1021 return pAddress; 1022 } 1023 1024 uno::Reference<XAccessibleRelationSet> ScChildrenShapes::GetRelationSet(const ScAccessibleShapeData* pData) const 1025 { 1026 utl::AccessibleRelationSetHelper* pRelationSet = new utl::AccessibleRelationSetHelper(); 1027 1028 if(pData && pRelationSet && mpAccessibleDocument) 1029 { 1030 uno::Reference<XAccessible> xAccessible = mpAccessibleDocument->GetAccessibleSpreadsheet(); // should be the current table 1031 if (pData->pRelationCell && xAccessible.is()) 1032 { 1033 uno::Reference<XAccessibleTable> xAccTable (xAccessible->getAccessibleContext(), uno::UNO_QUERY); 1034 if (xAccTable.is()) 1035 xAccessible = xAccTable->getAccessibleCellAt(pData->pRelationCell->Row(), pData->pRelationCell->Col()); 1036 } 1037 AccessibleRelation aRelation; 1038 aRelation.TargetSet.realloc(1); 1039 aRelation.TargetSet[0] = xAccessible; 1040 aRelation.RelationType = AccessibleRelationType::CONTROLLED_BY; 1041 pRelationSet->AddRelation(aRelation); 1042 } 1043 1044 return pRelationSet; 1045 } 1046 1047 void ScChildrenShapes::CheckWhetherAnchorChanged(const uno::Reference<drawing::XShape>& xShape) const 1048 { 1049 SortedShapes::iterator aItr; 1050 if (FindShape(xShape, aItr)) 1051 SetAnchor(xShape, *aItr); 1052 } 1053 1054 void ScChildrenShapes::SetAnchor(const uno::Reference<drawing::XShape>& xShape, ScAccessibleShapeData* pData) const 1055 { 1056 if (pData) 1057 { 1058 ScAddress* pAddress = GetAnchor(xShape); 1059 if ((pAddress && pData->pRelationCell && (*pAddress != *(pData->pRelationCell))) || 1060 (!pAddress && pData->pRelationCell) || (pAddress && !pData->pRelationCell)) 1061 { 1062 if (pData->pRelationCell) 1063 delete pData->pRelationCell; 1064 pData->pRelationCell = pAddress; 1065 if (pData->pAccShape) 1066 pData->pAccShape->SetRelationSet(GetRelationSet(pData)); 1067 } 1068 } 1069 } 1070 1071 void ScChildrenShapes::AddShape(const uno::Reference<drawing::XShape>& xShape, sal_Bool bCommitChange) const 1072 { 1073 SortedShapes::iterator aFindItr; 1074 if (!FindShape(xShape, aFindItr)) 1075 { 1076 ScAccessibleShapeData* pShape = new ScAccessibleShapeData(); 1077 pShape->xShape = xShape; 1078 SortedShapes::iterator aNewItr = maZOrderedShapes.insert(aFindItr, pShape); 1079 SetAnchor(xShape, pShape); 1080 1081 uno::Reference< beans::XPropertySet > xShapeProp(xShape, uno::UNO_QUERY); 1082 if (xShapeProp.is()) 1083 { 1084 uno::Any aPropAny = xShapeProp->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "LayerID" ))); 1085 sal_Int16 nLayerID = 0; 1086 if( aPropAny >>= nLayerID ) 1087 { 1088 if( (nLayerID == SC_LAYER_INTERN) || (nLayerID == SC_LAYER_HIDDEN) ) 1089 pShape->bSelectable = sal_False; 1090 else 1091 pShape->bSelectable = sal_True; 1092 } 1093 } 1094 1095 1096 if (!xSelectionSupplier.is()) 1097 throw uno::RuntimeException(); 1098 1099 uno::Reference<container::XEnumerationAccess> xEnumAcc(xSelectionSupplier->getSelection(), uno::UNO_QUERY); 1100 if (xEnumAcc.is()) 1101 { 1102 uno::Reference<container::XEnumeration> xEnum = xEnumAcc->createEnumeration(); 1103 if (xEnum.is()) 1104 { 1105 uno::Reference<drawing::XShape> xSelectedShape; 1106 sal_Bool bFound(sal_False); 1107 while (!bFound && xEnum->hasMoreElements()) 1108 { 1109 xEnum->nextElement() >>= xSelectedShape; 1110 if (xShape.is() && (xShape.get() == xSelectedShape.get())) 1111 { 1112 pShape->bSelected = sal_True; 1113 bFound = sal_True; 1114 } 1115 } 1116 } 1117 } 1118 if (mpAccessibleDocument && bCommitChange) 1119 { 1120 AccessibleEventObject aEvent; 1121 aEvent.EventId = AccessibleEventId::CHILD; 1122 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument); 1123 aEvent.NewValue <<= Get(aNewItr - maZOrderedShapes.begin()); 1124 1125 mpAccessibleDocument->CommitChange(aEvent); // new child - event 1126 } 1127 } 1128 else 1129 { 1130 DBG_ERRORFILE("shape is always in the list"); 1131 } 1132 } 1133 1134 void ScChildrenShapes::RemoveShape(const uno::Reference<drawing::XShape>& xShape) const 1135 { 1136 SortedShapes::iterator aItr; 1137 if (FindShape(xShape, aItr)) 1138 { 1139 if (mpAccessibleDocument) 1140 { 1141 uno::Reference<XAccessible> xOldAccessible (Get(aItr - maZOrderedShapes.begin())); 1142 1143 delete *aItr; 1144 maZOrderedShapes.erase(aItr); 1145 1146 AccessibleEventObject aEvent; 1147 aEvent.EventId = AccessibleEventId::CHILD; 1148 aEvent.Source = uno::Reference< XAccessibleContext >(mpAccessibleDocument); 1149 aEvent.OldValue <<= uno::makeAny(xOldAccessible); 1150 1151 mpAccessibleDocument->CommitChange(aEvent); // child is gone - event 1152 } 1153 else 1154 { 1155 delete *aItr; 1156 maZOrderedShapes.erase(aItr); 1157 } 1158 } 1159 else 1160 { 1161 DBG_ERRORFILE("shape was not in internal list"); 1162 } 1163 } 1164 1165 sal_Bool ScChildrenShapes::FindShape(const uno::Reference<drawing::XShape>& xShape, ScChildrenShapes::SortedShapes::iterator& rItr) const 1166 { 1167 sal_Bool bResult(sal_False); 1168 ScAccessibleShapeData aShape; 1169 aShape.xShape = xShape; 1170 ScShapeDataLess aLess; 1171 rItr = std::lower_bound(maZOrderedShapes.begin(), maZOrderedShapes.end(), &aShape, aLess); 1172 if ((rItr != maZOrderedShapes.end()) && (*rItr != NULL) && ((*rItr)->xShape.get() == xShape.get())) 1173 bResult = sal_True; // if the shape is found 1174 1175 #ifdef DBG_UTIL // test whether it finds truly the correct shape (perhaps it is not really sorted) 1176 SortedShapes::iterator aDebugItr = maZOrderedShapes.begin(); 1177 SortedShapes::iterator aEndItr = maZOrderedShapes.end(); 1178 sal_Bool bFound(sal_False); 1179 while (!bFound && aDebugItr != aEndItr) 1180 { 1181 if (*aDebugItr && ((*aDebugItr)->xShape.get() == xShape.get())) 1182 bFound = sal_True; 1183 else 1184 ++aDebugItr; 1185 } 1186 sal_Bool bResult2 = (aDebugItr != maZOrderedShapes.end()); 1187 DBG_ASSERT((bResult == bResult2) && ((bResult && (rItr == aDebugItr)) || !bResult), "wrong Shape found"); 1188 #endif 1189 return bResult; 1190 } 1191 1192 sal_Int8 ScChildrenShapes::Compare(const ScAccessibleShapeData* pData1, 1193 const ScAccessibleShapeData* pData2) const 1194 { 1195 ScShapeDataLess aLess; 1196 1197 sal_Bool bResult1(aLess(pData1, pData2)); 1198 sal_Bool bResult2(aLess(pData2, pData1)); 1199 1200 sal_Int8 nResult(0); 1201 if (!bResult1 && bResult2) 1202 nResult = 1; 1203 else if (bResult1 && !bResult2) 1204 nResult = -1; 1205 1206 return nResult; 1207 } 1208 1209 struct ScVisAreaChanged 1210 { 1211 ScAccessibleDocument* mpAccDoc; 1212 ScVisAreaChanged(ScAccessibleDocument* pAccDoc) : mpAccDoc(pAccDoc) {} 1213 void operator() (const ScAccessibleShapeData* pAccShapeData) const 1214 { 1215 if (pAccShapeData && pAccShapeData->pAccShape) 1216 { 1217 pAccShapeData->pAccShape->ViewForwarderChanged(::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA, mpAccDoc); 1218 } 1219 } 1220 }; 1221 1222 void ScChildrenShapes::VisAreaChanged() const 1223 { 1224 ScVisAreaChanged aVisAreaChanged(mpAccessibleDocument); 1225 std::for_each(maZOrderedShapes.begin(), maZOrderedShapes.end(), aVisAreaChanged); 1226 } 1227 1228 // ============================================================================ 1229 1230 ScAccessibleDocument::ScAccessibleDocument( 1231 const uno::Reference<XAccessible>& rxParent, 1232 ScTabViewShell* pViewShell, 1233 ScSplitPos eSplitPos) 1234 : ScAccessibleDocumentBase(rxParent), 1235 mpViewShell(pViewShell), 1236 meSplitPos(eSplitPos), 1237 mpAccessibleSpreadsheet(NULL), 1238 mpChildrenShapes(NULL), 1239 mpTempAccEdit(NULL), 1240 mbCompleteSheetSelected(sal_False) 1241 { 1242 if (pViewShell) 1243 { 1244 pViewShell->AddAccessibilityObject(*this); 1245 Window *pWin = pViewShell->GetWindowByPos(eSplitPos); 1246 if( pWin ) 1247 { 1248 pWin->AddChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener )); 1249 sal_uInt16 nCount = pWin->GetChildCount(); 1250 for( sal_uInt16 i=0; i < nCount; ++i ) 1251 { 1252 Window *pChildWin = pWin->GetChild( i ); 1253 if( pChildWin && 1254 AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() ) 1255 AddChild( pChildWin->GetAccessible(), sal_False ); 1256 } 1257 } 1258 if (pViewShell->GetViewData()->HasEditView( eSplitPos )) 1259 { 1260 uno::Reference<XAccessible> xAcc = new ScAccessibleEditObject(this, pViewShell->GetViewData()->GetEditView(eSplitPos), 1261 pViewShell->GetWindowByPos(eSplitPos), GetCurrentCellName(), GetCurrentCellDescription(), 1262 CellInEditMode); 1263 AddChild(xAcc, sal_False); 1264 } 1265 } 1266 maVisArea = GetVisibleArea_Impl(); 1267 } 1268 1269 void ScAccessibleDocument::Init() 1270 { 1271 if(!mpChildrenShapes) 1272 mpChildrenShapes = new ScChildrenShapes(this, mpViewShell, meSplitPos); 1273 } 1274 1275 ScAccessibleDocument::~ScAccessibleDocument(void) 1276 { 1277 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose) 1278 { 1279 // increment refcount to prevent double call off dtor 1280 osl_incrementInterlockedCount( &m_refCount ); 1281 dispose(); 1282 } 1283 } 1284 1285 void SAL_CALL ScAccessibleDocument::disposing() 1286 { 1287 ScUnoGuard aGuard; 1288 FreeAccessibleSpreadsheet(); 1289 if (mpViewShell) 1290 { 1291 Window *pWin = mpViewShell->GetWindowByPos(meSplitPos); 1292 if( pWin ) 1293 pWin->RemoveChildEventListener( LINK( this, ScAccessibleDocument, WindowChildEventListener )); 1294 1295 mpViewShell->RemoveAccessibilityObject(*this); 1296 mpViewShell = NULL; 1297 } 1298 if (mpChildrenShapes) 1299 DELETEZ(mpChildrenShapes); 1300 1301 ScAccessibleDocumentBase::disposing(); 1302 } 1303 1304 void SAL_CALL ScAccessibleDocument::disposing( const lang::EventObject& /* Source */ ) 1305 throw (uno::RuntimeException) 1306 { 1307 disposing(); 1308 } 1309 1310 //===== SfxListener ===================================================== 1311 1312 IMPL_LINK( ScAccessibleDocument, WindowChildEventListener, VclSimpleEvent*, pEvent ) 1313 { 1314 DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" ); 1315 if ( pEvent && pEvent->ISA( VclWindowEvent ) ) 1316 { 1317 VclWindowEvent *pVclEvent = static_cast< VclWindowEvent * >( pEvent ); 1318 DBG_ASSERT( pVclEvent->GetWindow(), "Window???" ); 1319 switch ( pVclEvent->GetId() ) 1320 { 1321 case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children 1322 { 1323 Window* pChildWin = static_cast < Window * >( pVclEvent->GetData() ); 1324 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() ) 1325 { 1326 AddChild( pChildWin->GetAccessible(), sal_True ); 1327 } 1328 } 1329 break; 1330 case VCLEVENT_WINDOW_HIDE: // send destroy on hide for direct accessible children 1331 { 1332 Window* pChildWin = static_cast < Window * >( pVclEvent->GetData() ); 1333 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() ) 1334 { 1335 RemoveChild( pChildWin->GetAccessible(), sal_True ); 1336 } 1337 } 1338 break; 1339 } 1340 } 1341 return 0; 1342 } 1343 1344 void ScAccessibleDocument::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 1345 { 1346 if (rHint.ISA( ScAccGridWinFocusLostHint ) ) 1347 { 1348 const ScAccGridWinFocusLostHint& rRef = (const ScAccGridWinFocusLostHint&)rHint; 1349 if (rRef.GetOldGridWin() == meSplitPos) 1350 { 1351 if (mxTempAcc.is() && mpTempAccEdit) 1352 mpTempAccEdit->LostFocus(); 1353 else if (mpAccessibleSpreadsheet) 1354 mpAccessibleSpreadsheet->LostFocus(); 1355 else 1356 CommitFocusLost(); 1357 } 1358 } 1359 else if (rHint.ISA( ScAccGridWinFocusGotHint ) ) 1360 { 1361 const ScAccGridWinFocusGotHint& rRef = (const ScAccGridWinFocusGotHint&)rHint; 1362 if (rRef.GetNewGridWin() == meSplitPos) 1363 { 1364 if (mxTempAcc.is() && mpTempAccEdit) 1365 mpTempAccEdit->GotFocus(); 1366 else if (mpAccessibleSpreadsheet) 1367 mpAccessibleSpreadsheet->GotFocus(); 1368 else 1369 CommitFocusGained(); 1370 } 1371 } 1372 else if (rHint.ISA( SfxSimpleHint )) 1373 { 1374 const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint; 1375 // only notify if child exist, otherwise it is not necessary 1376 if ((rRef.GetId() == SC_HINT_ACC_TABLECHANGED) && 1377 mpAccessibleSpreadsheet) 1378 { 1379 FreeAccessibleSpreadsheet(); 1380 if (mpChildrenShapes) 1381 DELETEZ(mpChildrenShapes); 1382 1383 // #124567# Accessibility: Shapes / form controls after reload not accessible 1384 if ( !mpChildrenShapes ) 1385 { 1386 mpChildrenShapes = new ScChildrenShapes( this, mpViewShell, meSplitPos ); 1387 } 1388 1389 AccessibleEventObject aEvent; 1390 aEvent.EventId = AccessibleEventId::INVALIDATE_ALL_CHILDREN; 1391 aEvent.Source = uno::Reference< XAccessibleContext >(this); 1392 CommitChange(aEvent); // all childs changed 1393 } 1394 else if (rRef.GetId() == SC_HINT_ACC_MAKEDRAWLAYER) 1395 { 1396 if (mpChildrenShapes) 1397 mpChildrenShapes->SetDrawBroadcaster(); 1398 } 1399 else if ((rRef.GetId() == SC_HINT_ACC_ENTEREDITMODE)) // this event comes only on creating edit field of a cell 1400 { 1401 if (mpViewShell && mpViewShell->GetViewData()->HasEditView(meSplitPos)) 1402 { 1403 mpTempAccEdit = new ScAccessibleEditObject(this, mpViewShell->GetViewData()->GetEditView(meSplitPos), 1404 mpViewShell->GetWindowByPos(meSplitPos), GetCurrentCellName(), 1405 rtl::OUString(String(ScResId(STR_ACC_EDITLINE_DESCR))), CellInEditMode); 1406 uno::Reference<XAccessible> xAcc = mpTempAccEdit; 1407 1408 AddChild(xAcc, sal_True); 1409 1410 if (mpAccessibleSpreadsheet) 1411 mpAccessibleSpreadsheet->LostFocus(); 1412 else 1413 CommitFocusLost(); 1414 1415 mpTempAccEdit->GotFocus(); 1416 } 1417 } 1418 else if (rRef.GetId() == SC_HINT_ACC_LEAVEEDITMODE) 1419 { 1420 if (mxTempAcc.is()) 1421 { 1422 if (mpTempAccEdit) 1423 mpTempAccEdit->LostFocus(); 1424 1425 mpTempAccEdit = NULL; 1426 RemoveChild(mxTempAcc, sal_True); 1427 1428 if (mpAccessibleSpreadsheet) 1429 mpAccessibleSpreadsheet->GotFocus(); 1430 else 1431 CommitFocusGained(); 1432 } 1433 } 1434 else if ((rRef.GetId() == SC_HINT_ACC_VISAREACHANGED) || (rRef.GetId() == SC_HINT_ACC_WINDOWRESIZED)) 1435 { 1436 Rectangle aOldVisArea(maVisArea); 1437 maVisArea = GetVisibleArea_Impl(); 1438 1439 if (maVisArea != aOldVisArea) 1440 { 1441 if (maVisArea.GetSize() != aOldVisArea.GetSize()) 1442 { 1443 AccessibleEventObject aEvent; 1444 aEvent.EventId = AccessibleEventId::BOUNDRECT_CHANGED; 1445 aEvent.Source = uno::Reference< XAccessibleContext >(this); 1446 1447 CommitChange(aEvent); 1448 1449 if (mpAccessibleSpreadsheet) 1450 mpAccessibleSpreadsheet->BoundingBoxChanged(); 1451 } 1452 else if (mpAccessibleSpreadsheet) 1453 { 1454 mpAccessibleSpreadsheet->VisAreaChanged(); 1455 } 1456 if (mpChildrenShapes) 1457 mpChildrenShapes->VisAreaChanged(); 1458 } 1459 } 1460 } 1461 1462 ScAccessibleDocumentBase::Notify(rBC, rHint); 1463 } 1464 1465 void SAL_CALL ScAccessibleDocument::selectionChanged( const lang::EventObject& /* aEvent */ ) 1466 throw (uno::RuntimeException) 1467 { 1468 sal_Bool bSelectionChanged(sal_False); 1469 if (mpAccessibleSpreadsheet) 1470 { 1471 sal_Bool bOldSelected(mbCompleteSheetSelected); 1472 mbCompleteSheetSelected = IsTableSelected(); 1473 if (bOldSelected != mbCompleteSheetSelected) 1474 { 1475 mpAccessibleSpreadsheet->CompleteSelectionChanged(mbCompleteSheetSelected); 1476 bSelectionChanged = sal_True; 1477 } 1478 } 1479 1480 if (mpChildrenShapes && mpChildrenShapes->SelectionChanged()) 1481 bSelectionChanged = sal_True; 1482 1483 if (bSelectionChanged) 1484 { 1485 AccessibleEventObject aEvent; 1486 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED; 1487 aEvent.Source = uno::Reference< XAccessibleContext >(this); 1488 1489 CommitChange(aEvent); 1490 } 1491 } 1492 1493 //===== XInterface ===================================================== 1494 1495 uno::Any SAL_CALL ScAccessibleDocument::queryInterface( uno::Type const & rType ) 1496 throw (uno::RuntimeException) 1497 { 1498 uno::Any aAny (ScAccessibleDocumentImpl::queryInterface(rType)); 1499 return aAny.hasValue() ? aAny : ScAccessibleContextBase::queryInterface(rType); 1500 } 1501 1502 void SAL_CALL ScAccessibleDocument::acquire() 1503 throw () 1504 { 1505 ScAccessibleContextBase::acquire(); 1506 } 1507 1508 void SAL_CALL ScAccessibleDocument::release() 1509 throw () 1510 { 1511 ScAccessibleContextBase::release(); 1512 } 1513 1514 //===== XAccessibleComponent ============================================ 1515 1516 uno::Reference< XAccessible > SAL_CALL ScAccessibleDocument::getAccessibleAtPoint( 1517 const awt::Point& rPoint ) 1518 throw (uno::RuntimeException) 1519 { 1520 uno::Reference<XAccessible> xAccessible = NULL; 1521 if (containsPoint(rPoint)) 1522 { 1523 ScUnoGuard aGuard; 1524 IsObjectValid(); 1525 if (mpChildrenShapes) 1526 xAccessible = mpChildrenShapes->GetAt(rPoint); 1527 if(!xAccessible.is()) 1528 { 1529 if (mxTempAcc.is()) 1530 { 1531 uno::Reference< XAccessibleContext > xCont(mxTempAcc->getAccessibleContext()); 1532 uno::Reference< XAccessibleComponent > xComp(xCont, uno::UNO_QUERY); 1533 if (xComp.is()) 1534 { 1535 Rectangle aBound(VCLRectangle(xComp->getBounds())); 1536 if (aBound.IsInside(VCLPoint(rPoint))) 1537 xAccessible = mxTempAcc; 1538 } 1539 } 1540 if (!xAccessible.is()) 1541 xAccessible = GetAccessibleSpreadsheet(); 1542 } 1543 } 1544 return xAccessible; 1545 } 1546 1547 void SAL_CALL ScAccessibleDocument::grabFocus( ) 1548 throw (uno::RuntimeException) 1549 { 1550 ScUnoGuard aGuard; 1551 IsObjectValid(); 1552 if (getAccessibleParent().is()) 1553 { 1554 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY); 1555 if (xAccessibleComponent.is()) 1556 { 1557 xAccessibleComponent->grabFocus(); 1558 // grab only focus if it does not have the focus and it is not hidden 1559 if (mpViewShell && mpViewShell->GetViewData() && 1560 (mpViewShell->GetViewData()->GetActivePart() != meSplitPos) && 1561 mpViewShell->GetWindowByPos(meSplitPos)->IsVisible()) 1562 { 1563 mpViewShell->ActivatePart(meSplitPos); 1564 } 1565 } 1566 } 1567 } 1568 1569 //===== XAccessibleContext ============================================== 1570 1571 /// Return the number of currently visible children. 1572 sal_Int32 SAL_CALL 1573 ScAccessibleDocument::getAccessibleChildCount(void) 1574 throw (uno::RuntimeException) 1575 { 1576 ScUnoGuard aGuard; 1577 IsObjectValid(); 1578 sal_Int32 nCount(1); 1579 if (mpChildrenShapes) 1580 nCount = mpChildrenShapes->GetCount(); // returns the count of the shapes inclusive the table 1581 1582 if (mxTempAcc.is()) 1583 ++nCount; 1584 1585 return nCount; 1586 } 1587 1588 /// Return the specified child or NULL if index is invalid. 1589 uno::Reference<XAccessible> SAL_CALL 1590 ScAccessibleDocument::getAccessibleChild(sal_Int32 nIndex) 1591 throw (uno::RuntimeException, 1592 lang::IndexOutOfBoundsException) 1593 { 1594 ScUnoGuard aGuard; 1595 IsObjectValid(); 1596 uno::Reference<XAccessible> xAccessible; 1597 if (nIndex >= 0) 1598 { 1599 sal_Int32 nCount(1); 1600 if (mpChildrenShapes) 1601 { 1602 xAccessible = mpChildrenShapes->Get(nIndex); // returns NULL if it is the table or out of range 1603 nCount = mpChildrenShapes->GetCount(); //there is always a table 1604 } 1605 if (!xAccessible.is()) 1606 { 1607 if (nIndex < nCount) 1608 xAccessible = GetAccessibleSpreadsheet(); 1609 else if (nIndex == nCount && mxTempAcc.is()) 1610 xAccessible = mxTempAcc; 1611 } 1612 } 1613 1614 if (!xAccessible.is()) 1615 throw lang::IndexOutOfBoundsException(); 1616 1617 return xAccessible; 1618 } 1619 1620 /// Return the set of current states. 1621 uno::Reference<XAccessibleStateSet> SAL_CALL 1622 ScAccessibleDocument::getAccessibleStateSet(void) 1623 throw (uno::RuntimeException) 1624 { 1625 ScUnoGuard aGuard; 1626 uno::Reference<XAccessibleStateSet> xParentStates; 1627 if (getAccessibleParent().is()) 1628 { 1629 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext(); 1630 xParentStates = xParentContext->getAccessibleStateSet(); 1631 } 1632 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper(); 1633 if (IsDefunc(xParentStates)) 1634 pStateSet->AddState(AccessibleStateType::DEFUNC); 1635 else 1636 { 1637 if (IsEditable(xParentStates)) 1638 pStateSet->AddState(AccessibleStateType::EDITABLE); 1639 pStateSet->AddState(AccessibleStateType::ENABLED); 1640 pStateSet->AddState(AccessibleStateType::OPAQUE); 1641 if (isShowing()) 1642 pStateSet->AddState(AccessibleStateType::SHOWING); 1643 if (isVisible()) 1644 pStateSet->AddState(AccessibleStateType::VISIBLE); 1645 } 1646 return pStateSet; 1647 } 1648 1649 ///===== XAccessibleSelection =========================================== 1650 1651 void SAL_CALL 1652 ScAccessibleDocument::selectAccessibleChild( sal_Int32 nChildIndex ) 1653 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 1654 { 1655 ScUnoGuard aGuard; 1656 IsObjectValid(); 1657 1658 if (mpChildrenShapes) 1659 { 1660 sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table 1661 if (mxTempAcc.is()) 1662 ++nCount; 1663 if (nChildIndex < 0 || nChildIndex >= nCount) 1664 throw lang::IndexOutOfBoundsException(); 1665 1666 uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex); 1667 if (xAccessible.is()) 1668 { 1669 sal_Bool bWasTableSelected(IsTableSelected()); 1670 1671 if (mpChildrenShapes) 1672 mpChildrenShapes->Select(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is to high 1673 1674 if (bWasTableSelected) 1675 mpViewShell->SelectAll(); 1676 } 1677 else 1678 { 1679 if (mpViewShell) 1680 mpViewShell->SelectAll(); 1681 } 1682 } 1683 } 1684 1685 sal_Bool SAL_CALL 1686 ScAccessibleDocument::isAccessibleChildSelected( sal_Int32 nChildIndex ) 1687 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 1688 { 1689 ScUnoGuard aGuard; 1690 IsObjectValid(); 1691 sal_Bool bResult(sal_False); 1692 1693 if (mpChildrenShapes) 1694 { 1695 sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table 1696 if (mxTempAcc.is()) 1697 ++nCount; 1698 if (nChildIndex < 0 || nChildIndex >= nCount) 1699 throw lang::IndexOutOfBoundsException(); 1700 1701 uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex); 1702 if (xAccessible.is()) 1703 { 1704 uno::Reference<drawing::XShape> xShape; 1705 bResult = mpChildrenShapes->IsSelected(nChildIndex, xShape); // throws no lang::IndexOutOfBoundsException if Index is to high 1706 } 1707 else 1708 { 1709 if (mxTempAcc.is() && nChildIndex == nCount) 1710 bResult = sal_True; 1711 else 1712 bResult = IsTableSelected(); 1713 } 1714 } 1715 return bResult; 1716 } 1717 1718 void SAL_CALL 1719 ScAccessibleDocument::clearAccessibleSelection( ) 1720 throw (uno::RuntimeException) 1721 { 1722 ScUnoGuard aGuard; 1723 IsObjectValid(); 1724 1725 if (mpChildrenShapes) 1726 mpChildrenShapes->DeselectAll(); //deselects all (also the table) 1727 } 1728 1729 void SAL_CALL 1730 ScAccessibleDocument::selectAllAccessibleChildren( ) 1731 throw (uno::RuntimeException) 1732 { 1733 ScUnoGuard aGuard; 1734 IsObjectValid(); 1735 1736 if (mpChildrenShapes) 1737 mpChildrenShapes->SelectAll(); 1738 1739 // select table after shapes, because while selecting shapes the table will be deselected 1740 if (mpViewShell) 1741 { 1742 mpViewShell->SelectAll(); 1743 } 1744 } 1745 1746 sal_Int32 SAL_CALL 1747 ScAccessibleDocument::getSelectedAccessibleChildCount( ) 1748 throw (uno::RuntimeException) 1749 { 1750 ScUnoGuard aGuard; 1751 IsObjectValid(); 1752 sal_Int32 nCount(0); 1753 1754 if (mpChildrenShapes) 1755 nCount = mpChildrenShapes->GetSelectedCount(); 1756 1757 if (IsTableSelected()) 1758 ++nCount; 1759 1760 if (mxTempAcc.is()) 1761 ++nCount; 1762 1763 return nCount; 1764 } 1765 1766 uno::Reference<XAccessible > SAL_CALL 1767 ScAccessibleDocument::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) 1768 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 1769 { 1770 ScUnoGuard aGuard; 1771 IsObjectValid(); 1772 uno::Reference<XAccessible> xAccessible; 1773 if (mpChildrenShapes) 1774 { 1775 sal_Int32 nCount(getSelectedAccessibleChildCount()); //all shapes and the table 1776 if (nSelectedChildIndex < 0 || nSelectedChildIndex >= nCount) 1777 throw lang::IndexOutOfBoundsException(); 1778 1779 sal_Bool bTabMarked(IsTableSelected()); 1780 1781 if (mpChildrenShapes) 1782 xAccessible = mpChildrenShapes->GetSelected(nSelectedChildIndex, bTabMarked); // throws no lang::IndexOutOfBoundsException if Index is to high 1783 if (mxTempAcc.is() && nSelectedChildIndex == nCount - 1) 1784 xAccessible = mxTempAcc; 1785 else if (bTabMarked) 1786 xAccessible = GetAccessibleSpreadsheet(); 1787 } 1788 1789 DBG_ASSERT(xAccessible.is(), "here should always be an accessible object or a exception throwed"); 1790 1791 return xAccessible; 1792 } 1793 1794 void SAL_CALL 1795 ScAccessibleDocument::deselectAccessibleChild( sal_Int32 nChildIndex ) 1796 throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 1797 { 1798 ScUnoGuard aGuard; 1799 IsObjectValid(); 1800 1801 if (mpChildrenShapes) 1802 { 1803 sal_Int32 nCount(mpChildrenShapes->GetCount()); //all shapes and the table 1804 if (mxTempAcc.is()) 1805 ++nCount; 1806 if (nChildIndex < 0 || nChildIndex >= nCount) 1807 throw lang::IndexOutOfBoundsException(); 1808 1809 sal_Bool bTabMarked(IsTableSelected()); 1810 1811 uno::Reference < XAccessible > xAccessible = mpChildrenShapes->Get(nChildIndex); 1812 if (xAccessible.is()) 1813 { 1814 if (mpChildrenShapes) 1815 mpChildrenShapes->Deselect(nChildIndex); // throws no lang::IndexOutOfBoundsException if Index is to high 1816 1817 if (bTabMarked) 1818 mpViewShell->SelectAll(); // select the table again 1819 } 1820 else if (bTabMarked) 1821 mpViewShell->Unmark(); 1822 } 1823 } 1824 1825 //===== XServiceInfo ==================================================== 1826 1827 ::rtl::OUString SAL_CALL 1828 ScAccessibleDocument::getImplementationName(void) 1829 throw (uno::RuntimeException) 1830 { 1831 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleDocument")); 1832 } 1833 1834 uno::Sequence< ::rtl::OUString> SAL_CALL 1835 ScAccessibleDocument::getSupportedServiceNames(void) 1836 throw (uno::RuntimeException) 1837 { 1838 uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames(); 1839 sal_Int32 nOldSize(aSequence.getLength()); 1840 aSequence.realloc(nOldSize + 1); 1841 ::rtl::OUString* pNames = aSequence.getArray(); 1842 1843 pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.AccessibleSpreadsheetDocumentView")); 1844 1845 return aSequence; 1846 } 1847 1848 //===== XTypeProvider ======================================================= 1849 1850 uno::Sequence< uno::Type > SAL_CALL ScAccessibleDocument::getTypes() 1851 throw (uno::RuntimeException) 1852 { 1853 return comphelper::concatSequences(ScAccessibleDocumentImpl::getTypes(), ScAccessibleContextBase::getTypes()); 1854 } 1855 1856 uno::Sequence<sal_Int8> SAL_CALL 1857 ScAccessibleDocument::getImplementationId(void) 1858 throw (uno::RuntimeException) 1859 { 1860 ScUnoGuard aGuard; 1861 IsObjectValid(); 1862 static uno::Sequence<sal_Int8> aId; 1863 if (aId.getLength() == 0) 1864 { 1865 aId.realloc (16); 1866 rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True); 1867 } 1868 return aId; 1869 } 1870 1871 ///===== IAccessibleViewForwarder ======================================== 1872 1873 sal_Bool ScAccessibleDocument::IsValid (void) const 1874 { 1875 ScUnoGuard aGuard; 1876 IsObjectValid(); 1877 return (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose); 1878 } 1879 1880 Rectangle ScAccessibleDocument::GetVisibleArea_Impl() const 1881 { 1882 Rectangle aVisRect(GetBoundingBox()); 1883 1884 Point aPoint(mpViewShell->GetViewData()->GetPixPos(meSplitPos)); // returns a negative Point 1885 aPoint.setX(-aPoint.getX()); 1886 aPoint.setY(-aPoint.getY()); 1887 aVisRect.SetPos(aPoint); 1888 1889 ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos)); 1890 if (pWin) 1891 aVisRect = pWin->PixelToLogic(aVisRect, pWin->GetDrawMapMode()); 1892 1893 return aVisRect; 1894 } 1895 1896 Rectangle ScAccessibleDocument::GetVisibleArea() const 1897 { 1898 ScUnoGuard aGuard; 1899 IsObjectValid(); 1900 return maVisArea; 1901 } 1902 1903 Point ScAccessibleDocument::LogicToPixel (const Point& rPoint) const 1904 { 1905 ScUnoGuard aGuard; 1906 IsObjectValid(); 1907 Point aPoint; 1908 ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos)); 1909 if (pWin) 1910 { 1911 aPoint = pWin->LogicToPixel(rPoint, pWin->GetDrawMapMode()); 1912 aPoint += pWin->GetWindowExtentsRelative(NULL).TopLeft(); 1913 } 1914 return aPoint; 1915 } 1916 1917 Size ScAccessibleDocument::LogicToPixel (const Size& rSize) const 1918 { 1919 ScUnoGuard aGuard; 1920 IsObjectValid(); 1921 Size aSize; 1922 ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos)); 1923 if (pWin) 1924 aSize = pWin->LogicToPixel(rSize, pWin->GetDrawMapMode()); 1925 return aSize; 1926 } 1927 1928 Point ScAccessibleDocument::PixelToLogic (const Point& rPoint) const 1929 { 1930 ScUnoGuard aGuard; 1931 IsObjectValid(); 1932 Point aPoint; 1933 ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos)); 1934 if (pWin) 1935 { 1936 aPoint -= pWin->GetWindowExtentsRelative(NULL).TopLeft(); 1937 aPoint = pWin->PixelToLogic(rPoint, pWin->GetDrawMapMode()); 1938 } 1939 return aPoint; 1940 } 1941 1942 Size ScAccessibleDocument::PixelToLogic (const Size& rSize) const 1943 { 1944 ScUnoGuard aGuard; 1945 IsObjectValid(); 1946 Size aSize; 1947 ScGridWindow* pWin = static_cast<ScGridWindow*>(mpViewShell->GetWindowByPos(meSplitPos)); 1948 if (pWin) 1949 aSize = pWin->PixelToLogic(rSize, pWin->GetDrawMapMode()); 1950 return aSize; 1951 } 1952 1953 //===== internal ======================================================== 1954 1955 utl::AccessibleRelationSetHelper* ScAccessibleDocument::GetRelationSet(const ScAddress* pAddress) const 1956 { 1957 utl::AccessibleRelationSetHelper* pRelationSet = NULL; 1958 if (mpChildrenShapes) 1959 pRelationSet = mpChildrenShapes->GetRelationSet(pAddress); 1960 return pRelationSet; 1961 } 1962 1963 ::rtl::OUString SAL_CALL 1964 ScAccessibleDocument::createAccessibleDescription(void) 1965 throw (uno::RuntimeException) 1966 { 1967 rtl::OUString sDescription = String(ScResId(STR_ACC_DOC_DESCR)); 1968 return sDescription; 1969 } 1970 1971 ::rtl::OUString SAL_CALL 1972 ScAccessibleDocument::createAccessibleName(void) 1973 throw (uno::RuntimeException) 1974 { 1975 ScUnoGuard aGuard; 1976 IsObjectValid(); 1977 rtl::OUString sName = String(ScResId(STR_ACC_DOC_NAME)); 1978 sal_Int32 nNumber(sal_Int32(meSplitPos) + 1); 1979 sName += rtl::OUString::valueOf(nNumber); 1980 return sName; 1981 } 1982 1983 Rectangle ScAccessibleDocument::GetBoundingBoxOnScreen() const 1984 throw (uno::RuntimeException) 1985 { 1986 Rectangle aRect; 1987 if (mpViewShell) 1988 { 1989 Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos); 1990 if (pWindow) 1991 aRect = pWindow->GetWindowExtentsRelative(NULL); 1992 } 1993 return aRect; 1994 } 1995 1996 Rectangle ScAccessibleDocument::GetBoundingBox() const 1997 throw (uno::RuntimeException) 1998 { 1999 Rectangle aRect; 2000 if (mpViewShell) 2001 { 2002 Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos); 2003 if (pWindow) 2004 aRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow()); 2005 } 2006 return aRect; 2007 } 2008 2009 SCTAB ScAccessibleDocument::getVisibleTable() const 2010 { 2011 SCTAB nVisibleTable(0); 2012 if (mpViewShell && mpViewShell->GetViewData()) 2013 nVisibleTable = mpViewShell->GetViewData()->GetTabNo(); 2014 return nVisibleTable; 2015 } 2016 2017 uno::Reference < XAccessible > 2018 ScAccessibleDocument::GetAccessibleSpreadsheet() 2019 { 2020 if (!mpAccessibleSpreadsheet && mpViewShell) 2021 { 2022 mpAccessibleSpreadsheet = new ScAccessibleSpreadsheet(this, mpViewShell, getVisibleTable(), meSplitPos); 2023 mpAccessibleSpreadsheet->acquire(); 2024 mpAccessibleSpreadsheet->Init(); 2025 mbCompleteSheetSelected = IsTableSelected(); 2026 } 2027 return mpAccessibleSpreadsheet; 2028 } 2029 2030 void ScAccessibleDocument::FreeAccessibleSpreadsheet() 2031 { 2032 if (mpAccessibleSpreadsheet) 2033 { 2034 mpAccessibleSpreadsheet->dispose(); 2035 mpAccessibleSpreadsheet->release(); 2036 mpAccessibleSpreadsheet = NULL; 2037 } 2038 } 2039 2040 sal_Bool ScAccessibleDocument::IsTableSelected() const 2041 { 2042 sal_Bool bResult (sal_False); 2043 if(mpViewShell) 2044 { 2045 SCTAB nTab(getVisibleTable()); 2046 //#103800#; use a copy of MarkData 2047 ScMarkData aMarkData(mpViewShell->GetViewData()->GetMarkData()); 2048 aMarkData.MarkToMulti(); 2049 if (aMarkData.IsAllMarked(ScRange(ScAddress(0, 0, nTab),ScAddress(MAXCOL, MAXROW, nTab)))) 2050 bResult = sal_True; 2051 } 2052 return bResult; 2053 } 2054 2055 sal_Bool ScAccessibleDocument::IsDefunc( 2056 const uno::Reference<XAccessibleStateSet>& rxParentStates) 2057 { 2058 return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() || 2059 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC)); 2060 } 2061 2062 sal_Bool ScAccessibleDocument::IsEditable( 2063 const uno::Reference<XAccessibleStateSet>& /* rxParentStates */) 2064 { 2065 // what is with document protection or readonly documents? 2066 return sal_True; 2067 } 2068 2069 void ScAccessibleDocument::AddChild(const uno::Reference<XAccessible>& xAcc, sal_Bool bFireEvent) 2070 { 2071 DBG_ASSERT(!mxTempAcc.is(), "this object should be removed before"); 2072 if (xAcc.is()) 2073 { 2074 mxTempAcc = xAcc; 2075 if( bFireEvent ) 2076 { 2077 AccessibleEventObject aEvent; 2078 aEvent.Source = uno::Reference<XAccessibleContext>(this); 2079 aEvent.EventId = AccessibleEventId::CHILD; 2080 aEvent.NewValue <<= mxTempAcc; 2081 CommitChange( aEvent ); 2082 } 2083 } 2084 } 2085 2086 void ScAccessibleDocument::RemoveChild(const uno::Reference<XAccessible>& xAcc, sal_Bool bFireEvent) 2087 { 2088 DBG_ASSERT(mxTempAcc.is(), "this object should be added before"); 2089 if (xAcc.is()) 2090 { 2091 DBG_ASSERT(xAcc.get() == mxTempAcc.get(), "only the same object should be removed"); 2092 if( bFireEvent ) 2093 { 2094 AccessibleEventObject aEvent; 2095 aEvent.Source = uno::Reference<XAccessibleContext>(this); 2096 aEvent.EventId = AccessibleEventId::CHILD; 2097 aEvent.OldValue <<= mxTempAcc; 2098 CommitChange( aEvent ); 2099 } 2100 mxTempAcc = NULL; 2101 } 2102 } 2103 2104 rtl::OUString ScAccessibleDocument::GetCurrentCellName() const 2105 { 2106 String sName( ScResId(STR_ACC_CELL_NAME) ); 2107 if (mpViewShell) 2108 { 2109 String sAddress; 2110 // Document not needed, because only the cell address, but not the tablename is needed 2111 mpViewShell->GetViewData()->GetCurPos().Format( sAddress, SCA_VALID, NULL ); 2112 sName.SearchAndReplaceAscii("%1", sAddress); 2113 } 2114 return rtl::OUString(sName); 2115 } 2116 2117 rtl::OUString ScAccessibleDocument::GetCurrentCellDescription() const 2118 { 2119 return rtl::OUString(); 2120 } 2121