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_sw.hxx" 30 31 32 #include <vos/ref.hxx> 33 #include <cppuhelper/weakref.hxx> 34 #include <vcl/window.hxx> 35 #include <svx/svdmodel.hxx> 36 #include <svx/unomod.hxx> 37 #include <tools/debug.hxx> 38 39 #include <map> 40 #include <list> 41 #include <accmap.hxx> 42 #include <acccontext.hxx> 43 #include <accdoc.hxx> 44 #include <accpreview.hxx> 45 #include <accpage.hxx> 46 #include <accpara.hxx> 47 #include <accheaderfooter.hxx> 48 #include <accfootnote.hxx> 49 #include <acctextframe.hxx> 50 #include <accgraphic.hxx> 51 #include <accembedded.hxx> 52 #include <acccell.hxx> 53 #include <acctable.hxx> 54 #include <fesh.hxx> 55 #include <rootfrm.hxx> 56 #include <txtfrm.hxx> 57 #include <hffrm.hxx> 58 #include <ftnfrm.hxx> 59 #include <cellfrm.hxx> 60 #include <tabfrm.hxx> 61 #include <pagefrm.hxx> 62 #include <flyfrm.hxx> 63 #include <ndtyp.hxx> 64 #include <IDocumentDrawModelAccess.hxx> 65 #include <svx/ShapeTypeHandler.hxx> 66 #include <vcl/svapp.hxx> 67 #include <com/sun/star/accessibility/AccessibleRelationType.hpp> 68 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 69 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 70 #include <cppuhelper/implbase1.hxx> 71 #include <pagepreviewlayout.hxx> 72 #include <pam.hxx> 73 #include <ndtxt.hxx> 74 #include <dflyobj.hxx> 75 #include <prevwpage.hxx> 76 #include <switerator.hxx> 77 78 using namespace ::com::sun::star; 79 using namespace ::com::sun::star::accessibility; 80 using ::rtl::OUString; 81 using namespace ::sw::access; 82 83 struct SwFrmFunc 84 { 85 sal_Bool operator()( const SwFrm * p1, 86 const SwFrm * p2) const 87 { 88 return p1 < p2; 89 } 90 }; 91 92 typedef ::std::map < const SwFrm *, uno::WeakReference < XAccessible >, SwFrmFunc > _SwAccessibleContextMap_Impl; 93 94 class SwAccessibleContextMap_Impl: public _SwAccessibleContextMap_Impl 95 { 96 public: 97 98 #ifdef DBG_UTIL 99 sal_Bool mbLocked; 100 #endif 101 102 SwAccessibleContextMap_Impl() 103 #ifdef DBG_UTIL 104 : mbLocked( sal_False ) 105 #endif 106 {} 107 108 }; 109 110 //------------------------------------------------------------------------------ 111 class SwDrawModellListener_Impl : public SfxListener, 112 public ::cppu::WeakImplHelper1< document::XEventBroadcaster > 113 { 114 mutable ::osl::Mutex maListenerMutex; 115 ::cppu::OInterfaceContainerHelper maEventListeners; 116 SdrModel *mpDrawModel; 117 protected: 118 virtual ~SwDrawModellListener_Impl(); 119 public: 120 121 SwDrawModellListener_Impl( SdrModel *pDrawModel ); 122 123 124 virtual void SAL_CALL addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException); 125 virtual void SAL_CALL removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException); 126 127 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); 128 void Dispose(); 129 }; 130 131 SwDrawModellListener_Impl::SwDrawModellListener_Impl( SdrModel *pDrawModel ) : 132 maEventListeners( maListenerMutex ), 133 mpDrawModel( pDrawModel ) 134 { 135 StartListening( *mpDrawModel ); 136 } 137 138 SwDrawModellListener_Impl::~SwDrawModellListener_Impl() 139 { 140 EndListening( *mpDrawModel ); 141 } 142 143 void SAL_CALL SwDrawModellListener_Impl::addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException) 144 { 145 maEventListeners.addInterface( xListener ); 146 } 147 148 void SAL_CALL SwDrawModellListener_Impl::removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException) 149 { 150 maEventListeners.removeInterface( xListener ); 151 } 152 153 void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/, 154 const SfxHint& rHint ) 155 { 156 // do not broadcast notifications for writer fly frames, because there 157 // are no shapes that need to know about them. 158 // OD 01.07.2003 #110554# - correct condition in order not to broadcast 159 // notifications for writer fly frames. 160 // OD 01.07.2003 #110554# - do not broadcast notifications for plane 161 // <SdrObject>objects 162 const SdrHint *pSdrHint = PTR_CAST( SdrHint, &rHint ); 163 if ( !pSdrHint || 164 ( pSdrHint->GetObject() && 165 ( pSdrHint->GetObject()->ISA(SwFlyDrawObj) || 166 pSdrHint->GetObject()->ISA(SwVirtFlyDrawObj) || 167 IS_TYPE(SdrObject,pSdrHint->GetObject()) ) ) ) 168 { 169 return; 170 } 171 172 ASSERT( mpDrawModel, "draw model listener is disposed" ); 173 if( !mpDrawModel ) 174 return; 175 176 document::EventObject aEvent; 177 if( !SvxUnoDrawMSFactory::createEvent( mpDrawModel, pSdrHint, aEvent ) ) 178 return; 179 180 ::cppu::OInterfaceIteratorHelper aIter( maEventListeners ); 181 while( aIter.hasMoreElements() ) 182 { 183 uno::Reference < document::XEventListener > xListener( aIter.next(), 184 uno::UNO_QUERY ); 185 try 186 { 187 xListener->notifyEvent( aEvent ); 188 } 189 catch( uno::RuntimeException const & r ) 190 { 191 (void)r; 192 #if OSL_DEBUG_LEVEL > 1 193 ByteString aError( "Runtime exception caught while notifying shape.:\n" ); 194 aError += ByteString( String( r.Message), RTL_TEXTENCODING_ASCII_US ); 195 DBG_ERROR( aError.GetBuffer() ); 196 #endif 197 } 198 } 199 } 200 201 void SwDrawModellListener_Impl::Dispose() 202 { 203 mpDrawModel = 0; 204 } 205 206 //------------------------------------------------------------------------------ 207 struct SwShapeFunc 208 { 209 sal_Bool operator()( const SdrObject * p1, 210 const SdrObject * p2) const 211 { 212 return p1 < p2; 213 } 214 }; 215 typedef ::std::map < const SdrObject *, uno::WeakReference < XAccessible >, SwShapeFunc > _SwAccessibleShapeMap_Impl; 216 typedef ::std::pair < const SdrObject *, ::vos::ORef < ::accessibility::AccessibleShape > > SwAccessibleObjShape_Impl; 217 218 class SwAccessibleShapeMap_Impl: public _SwAccessibleShapeMap_Impl 219 220 { 221 ::accessibility::AccessibleShapeTreeInfo maInfo; 222 223 public: 224 225 #ifdef DBG_UTIL 226 sal_Bool mbLocked; 227 #endif 228 SwAccessibleShapeMap_Impl( SwAccessibleMap *pMap ) 229 #ifdef DBG_UTIL 230 : mbLocked( sal_False ) 231 #endif 232 { 233 maInfo.SetSdrView( pMap->GetShell()->GetDrawView() ); 234 maInfo.SetWindow( pMap->GetShell()->GetWin() ); 235 maInfo.SetViewForwarder( pMap ); 236 // --> OD 2005-08-08 #i52858# - method name changed 237 uno::Reference < document::XEventBroadcaster > xModelBroadcaster = 238 new SwDrawModellListener_Impl( 239 pMap->GetShell()->getIDocumentDrawModelAccess()->GetOrCreateDrawModel() ); 240 // <-- 241 maInfo.SetControllerBroadcaster( xModelBroadcaster ); 242 } 243 244 ~SwAccessibleShapeMap_Impl(); 245 246 const ::accessibility::AccessibleShapeTreeInfo& GetInfo() const { return maInfo; } 247 248 SwAccessibleObjShape_Impl *Copy( size_t& rSize, 249 const SwFEShell *pFESh = 0, 250 SwAccessibleObjShape_Impl **pSelShape = 0 ) const; 251 }; 252 253 SwAccessibleShapeMap_Impl::~SwAccessibleShapeMap_Impl() 254 { 255 uno::Reference < document::XEventBroadcaster > xBrd( maInfo.GetControllerBroadcaster() ); 256 if( xBrd.is() ) 257 static_cast < SwDrawModellListener_Impl * >( xBrd.get() )->Dispose(); 258 } 259 260 SwAccessibleObjShape_Impl 261 *SwAccessibleShapeMap_Impl::Copy( 262 size_t& rSize, const SwFEShell *pFESh, 263 SwAccessibleObjShape_Impl **pSelStart ) const 264 { 265 SwAccessibleObjShape_Impl *pShapes = 0; 266 SwAccessibleObjShape_Impl *pSelShape = 0; 267 268 sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0; 269 rSize = size(); 270 271 if( rSize > 0 ) 272 { 273 pShapes = 274 new SwAccessibleObjShape_Impl[rSize]; 275 276 const_iterator aIter = begin(); 277 const_iterator aEndIter = end(); 278 279 SwAccessibleObjShape_Impl *pShape = pShapes; 280 pSelShape = &(pShapes[rSize]); 281 while( aIter != aEndIter ) 282 { 283 const SdrObject *pObj = (*aIter).first; 284 uno::Reference < XAccessible > xAcc( (*aIter).second ); 285 if( nSelShapes && pFESh->IsObjSelected( *pObj ) ) 286 { 287 // selected objects are inserted from the back 288 --pSelShape; 289 pSelShape->first = pObj; 290 pSelShape->second = 291 static_cast < ::accessibility::AccessibleShape* >( 292 xAcc.get() ); 293 --nSelShapes; 294 } 295 else 296 { 297 pShape->first = pObj; 298 pShape->second = 299 static_cast < ::accessibility::AccessibleShape* >( 300 xAcc.get() ); 301 ++pShape; 302 } 303 ++aIter; 304 } 305 ASSERT( pSelShape == pShape, "copying shapes went wrong!" ); 306 } 307 308 if( pSelStart ) 309 *pSelStart = pSelShape; 310 311 return pShapes; 312 } 313 314 //------------------------------------------------------------------------------ 315 struct SwAccessibleEvent_Impl 316 { 317 public: 318 enum EventType { CARET_OR_STATES, 319 INVALID_CONTENT, 320 POS_CHANGED, 321 CHILD_POS_CHANGED, 322 SHAPE_SELECTION, 323 DISPOSE, 324 INVALID_ATTR }; 325 326 private: 327 SwRect maOldBox; // the old bounds for CHILD_POS_CHANGED 328 // and POS_CHANGED 329 uno::WeakReference < XAccessible > mxAcc; // The object that fires the event 330 SwAccessibleChild maFrmOrObj; // the child for CHILD_POS_CHANGED and 331 // the same as xAcc for any other 332 // event type 333 EventType meType; // The event type 334 // --> OD 2005-12-12 #i27301# - use new type definition for <mnStates> 335 tAccessibleStates mnStates; // check states or update caret pos 336 // <-- 337 338 SwAccessibleEvent_Impl& operator==( const SwAccessibleEvent_Impl& ); 339 340 public: 341 SwAccessibleEvent_Impl( EventType eT, 342 SwAccessibleContext *pA, 343 const SwAccessibleChild& rFrmOrObj ) 344 : mxAcc( pA ), 345 maFrmOrObj( rFrmOrObj ), 346 meType( eT ), 347 mnStates( 0 ) 348 {} 349 350 SwAccessibleEvent_Impl( EventType eT, 351 const SwAccessibleChild& rFrmOrObj ) 352 : maFrmOrObj( rFrmOrObj ), 353 meType( eT ), 354 mnStates( 0 ) 355 { 356 ASSERT( SwAccessibleEvent_Impl::DISPOSE == meType, 357 "wrong event constructor, DISPOSE only" ); 358 } 359 360 SwAccessibleEvent_Impl( EventType eT ) 361 : meType( eT ), 362 mnStates( 0 ) 363 { 364 ASSERT( SwAccessibleEvent_Impl::SHAPE_SELECTION == meType, 365 "wrong event constructor, SHAPE_SELECTION only" ); 366 } 367 368 SwAccessibleEvent_Impl( EventType eT, 369 SwAccessibleContext *pA, 370 const SwAccessibleChild& rFrmOrObj, 371 const SwRect& rR ) 372 : maOldBox( rR ), 373 mxAcc( pA ), 374 maFrmOrObj( rFrmOrObj ), 375 meType( eT ), 376 mnStates( 0 ) 377 { 378 ASSERT( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType || 379 SwAccessibleEvent_Impl::POS_CHANGED == meType, 380 "wrong event constructor, (CHILD_)POS_CHANGED only" ); 381 } 382 383 // --> OD 2005-12-12 #i27301# - use new type definition for parameter <_nStates> 384 SwAccessibleEvent_Impl( EventType eT, 385 SwAccessibleContext *pA, 386 const SwAccessibleChild& rFrmOrObj, 387 const tAccessibleStates _nStates ) 388 : mxAcc( pA ), 389 maFrmOrObj( rFrmOrObj ), 390 meType( eT ), 391 mnStates( _nStates ) 392 { 393 ASSERT( SwAccessibleEvent_Impl::CARET_OR_STATES == meType, 394 "wrong event constructor, CARET_OR_STATES only" ); 395 } 396 397 // <SetType(..)> only used in method <SwAccessibleMap::AppendEvent(..)> 398 inline void SetType( EventType eT ) 399 { 400 meType = eT; 401 } 402 inline EventType GetType() const 403 { 404 return meType; 405 } 406 407 inline ::vos::ORef < SwAccessibleContext > GetContext() const 408 { 409 uno::Reference < XAccessible > xTmp( mxAcc ); 410 ::vos::ORef < SwAccessibleContext > xAccImpl( 411 static_cast<SwAccessibleContext*>( xTmp.get() ) ); 412 413 return xAccImpl; 414 } 415 416 inline const SwRect& GetOldBox() const 417 { 418 return maOldBox; 419 } 420 // <SetOldBox(..)> only used in method <SwAccessibleMap::AppendEvent(..)> 421 inline void SetOldBox( const SwRect& rOldBox ) 422 { 423 maOldBox = rOldBox; 424 } 425 426 inline const SwAccessibleChild& GetFrmOrObj() const 427 { 428 return maFrmOrObj; 429 } 430 431 // <SetStates(..)> only used in method <SwAccessibleMap::AppendEvent(..)> 432 // --> OD 2005-12-12 #i27301# - use new type definition for parameter <_nStates> 433 inline void SetStates( tAccessibleStates _nStates ) 434 { 435 mnStates |= _nStates; 436 } 437 // <-- 438 439 inline sal_Bool IsUpdateCursorPos() const 440 { 441 return (mnStates & ACC_STATE_CARET) != 0; 442 } 443 inline sal_Bool IsInvalidateStates() const 444 { 445 return (mnStates & ACC_STATE_MASK) != 0; 446 } 447 inline sal_Bool IsInvalidateRelation() const 448 { 449 return (mnStates & ACC_STATE_RELATION_MASK) != 0; 450 } 451 // --> OD 2005-12-12 #i27301# - new event TEXT_SELECTION_CHANGED 452 inline sal_Bool IsInvalidateTextSelection() const 453 { 454 return ( mnStates & ACC_STATE_TEXT_SELECTION_CHANGED ) != 0; 455 } 456 // <-- 457 // --> OD 2009-01-07 #i88069# - new event TEXT_ATTRIBUTE_CHANGED 458 inline sal_Bool IsInvalidateTextAttrs() const 459 { 460 return ( mnStates & ACC_STATE_TEXT_ATTRIBUTE_CHANGED ) != 0; 461 } 462 // <-- 463 // --> OD 2005-12-12 #i27301# - use new type definition <tAccessibleStates> 464 // for return value 465 inline tAccessibleStates GetStates() const 466 { 467 return mnStates & ACC_STATE_MASK; 468 } 469 // <-- 470 // --> OD 2005-12-12 #i27301# - use new type definition <tAccessibleStates> 471 // for return value 472 inline tAccessibleStates GetAllStates() const 473 { 474 return mnStates; 475 } 476 // <-- 477 }; 478 479 //------------------------------------------------------------------------------ 480 typedef ::std::list < SwAccessibleEvent_Impl > _SwAccessibleEventList_Impl; 481 482 class SwAccessibleEventList_Impl: public _SwAccessibleEventList_Impl 483 { 484 sal_Bool mbFiring; 485 486 public: 487 488 SwAccessibleEventList_Impl() 489 : mbFiring( sal_False ) 490 {} 491 492 inline void SetFiring() 493 { 494 mbFiring = sal_True; 495 } 496 inline sal_Bool IsFiring() const 497 { 498 return mbFiring; 499 } 500 }; 501 502 //------------------------------------------------------------------------------ 503 // The shape list is filled if an accessible shape is destroyed. It 504 // simply keeps a reference to the accessible shape's XShape. These 505 // references are destroyed within the EndAction when firing events, 506 // There are twp reason for this. First of all, a new accessible shape 507 // for the XShape might be created soon. It's then cheaper if the XShape 508 // still exists. The other reason are situations where an accessible shape 509 // is destroyed within an SwFrmFmt::Modify. In this case, destryoing 510 // the XShape at the same time (indirectly by destroying the accessible 511 // shape) leads to an assert, because a client of the Modify is destroyed 512 // within a Modify call. 513 514 typedef ::std::list < uno::Reference < drawing::XShape > > _SwShapeList_Impl; 515 516 class SwShapeList_Impl: public _SwShapeList_Impl 517 { 518 public: 519 520 SwShapeList_Impl() {} 521 }; 522 523 524 //------------------------------------------------------------------------------ 525 struct SwAccessibleChildFunc 526 { 527 sal_Bool operator()( const SwAccessibleChild& r1, 528 const SwAccessibleChild& r2 ) const 529 { 530 const void *p1 = r1.GetSwFrm() 531 ? static_cast < const void * >( r1.GetSwFrm()) 532 : ( r1.GetDrawObject() 533 ? static_cast < const void * >( r1.GetDrawObject() ) 534 : static_cast < const void * >( r1.GetWindow() ) ); 535 const void *p2 = r2.GetSwFrm() 536 ? static_cast < const void * >( r2.GetSwFrm()) 537 : ( r2.GetDrawObject() 538 ? static_cast < const void * >( r2.GetDrawObject() ) 539 : static_cast < const void * >( r2.GetWindow() ) ); 540 return p1 < p2; 541 } 542 }; 543 typedef ::std::map < SwAccessibleChild, SwAccessibleEventList_Impl::iterator, 544 SwAccessibleChildFunc > _SwAccessibleEventMap_Impl; 545 546 class SwAccessibleEventMap_Impl: public _SwAccessibleEventMap_Impl 547 { 548 }; 549 550 //------------------------------------------------------------------------------ 551 // --> OD 2005-12-13 #i27301# - map containing the accessible paragraph, which 552 // have a selection. Needed to keep this information to submit corresponding 553 // TEXT_SELECTION_CHANGED events. 554 struct SwAccessibleParaSelection 555 { 556 xub_StrLen nStartOfSelection; 557 xub_StrLen nEndOfSelection; 558 559 SwAccessibleParaSelection( const xub_StrLen _nStartOfSelection, 560 const xub_StrLen _nEndOfSelection ) 561 : nStartOfSelection( _nStartOfSelection ), 562 nEndOfSelection( _nEndOfSelection ) 563 {} 564 }; 565 566 struct SwXAccWeakRefComp 567 { 568 sal_Bool operator()( const uno::WeakReference<XAccessible>& _rXAccWeakRef1, 569 const uno::WeakReference<XAccessible>& _rXAccWeakRef2 ) const 570 { 571 return _rXAccWeakRef1.get() < _rXAccWeakRef2.get(); 572 } 573 }; 574 575 typedef ::std::map< uno::WeakReference < XAccessible >, 576 SwAccessibleParaSelection, 577 SwXAccWeakRefComp > _SwAccessibleSelectedParas_Impl; 578 579 class SwAccessibleSelectedParas_Impl: public _SwAccessibleSelectedParas_Impl 580 {}; 581 // <-- 582 583 // helper class that stores preview data 584 class SwAccPreviewData 585 { 586 typedef std::vector<Rectangle> Rectangles; 587 Rectangles maPreviewRects; 588 Rectangles maLogicRects; 589 590 SwRect maVisArea; 591 Fraction maScale; 592 593 const SwPageFrm *mpSelPage; 594 595 /** adjust logic page retangle to its visible part 596 597 OD 17.01.2003 #103492# 598 599 @author OD 600 601 @param _iorLogicPgSwRect 602 input/output parameter - reference to the logic page rectangle, which 603 has to be adjusted. 604 605 @param _rPrevwPgSwRect 606 input parameter - constant reference to the corresponding preview page 607 rectangle; needed to determine the visible part of the logic page rectangle. 608 609 @param _rPrevwWinSize 610 input paramter - constant reference to the preview window size in TWIP; 611 needed to determine the visible part of the logic page rectangle 612 */ 613 void AdjustLogicPgRectToVisibleArea( SwRect& _iorLogicPgSwRect, 614 const SwRect& _rPrevwPgSwRect, 615 const Size& _rPrevwWinSize ); 616 617 public: 618 SwAccPreviewData(); 619 ~SwAccPreviewData(); 620 621 // OD 14.01.2003 #103492# - complete re-factoring of method due to new 622 // page/print preview functionality. 623 void Update( const SwAccessibleMap& rAccMap, 624 const std::vector<PrevwPage*>& _rPrevwPages, 625 const Fraction& _rScale, 626 const SwPageFrm* _pSelectedPageFrm, 627 const Size& _rPrevwWinSize ); 628 629 // OD 14.01.2003 #103492# - complete re-factoring of method due to new 630 // page/print preview functionality. 631 void InvalidateSelection( const SwPageFrm* _pSelectedPageFrm ); 632 633 const SwRect& GetVisArea() const; 634 635 MapMode GetMapModeForPreview( ) const; 636 637 /** Adjust the MapMode so that the preview page appears at the 638 * proper position. rPoint identifies the page for which the 639 * MapMode should be adjusted. If bFromPreview is true, rPoint is 640 * a preview coordinate; else it's a document coordinate. */ 641 // OD 17.01.2003 #103492# - delete unused 3rd parameter. 642 void AdjustMapMode( MapMode& rMapMode, 643 const Point& rPoint ) const; 644 645 inline const SwPageFrm *GetSelPage() const { return mpSelPage; } 646 647 void DisposePage(const SwPageFrm *pPageFrm ); 648 }; 649 650 SwAccPreviewData::SwAccPreviewData() : 651 mpSelPage( 0 ) 652 { 653 } 654 655 SwAccPreviewData::~SwAccPreviewData() 656 { 657 } 658 659 // OD 13.01.2003 #103492# - complete re-factoring of method due to new page/print 660 // preview functionality. 661 void SwAccPreviewData::Update( const SwAccessibleMap& rAccMap, 662 const std::vector<PrevwPage*>& _rPrevwPages, 663 const Fraction& _rScale, 664 const SwPageFrm* _pSelectedPageFrm, 665 const Size& _rPrevwWinSize ) 666 { 667 // store preview scaling, maximal preview page size and selected page 668 maScale = _rScale; 669 mpSelPage = _pSelectedPageFrm; 670 671 // prepare loop on preview pages 672 maPreviewRects.clear(); 673 maLogicRects.clear(); 674 SwAccessibleChild aPage; 675 maVisArea.Clear(); 676 677 // loop on preview pages to calculate <maPreviewRects>, <maLogicRects> and 678 // <maVisArea> 679 for ( std::vector<PrevwPage*>::const_iterator aPageIter = _rPrevwPages.begin(); 680 aPageIter != _rPrevwPages.end(); 681 ++aPageIter ) 682 { 683 aPage = (*aPageIter)->pPage; 684 685 // add preview page rectangle to <maPreviewRects> 686 Rectangle aPrevwPgRect( (*aPageIter)->aPrevwWinPos, (*aPageIter)->aPageSize ); 687 maPreviewRects.push_back( aPrevwPgRect ); 688 689 // add logic page rectangle to <maLogicRects> 690 SwRect aLogicPgSwRect( aPage.GetBox( rAccMap ) ); 691 Rectangle aLogicPgRect( aLogicPgSwRect.SVRect() ); 692 maLogicRects.push_back( aLogicPgRect ); 693 // union visible area with visible part of logic page rectangle 694 if ( (*aPageIter)->bVisible ) 695 { 696 if ( !(*aPageIter)->pPage->IsEmptyPage() ) 697 { 698 AdjustLogicPgRectToVisibleArea( aLogicPgSwRect, 699 SwRect( aPrevwPgRect ), 700 _rPrevwWinSize ); 701 } 702 if ( maVisArea.IsEmpty() ) 703 maVisArea = aLogicPgSwRect; 704 else 705 maVisArea.Union( aLogicPgSwRect ); 706 } 707 } 708 } 709 710 // OD 16.01.2003 #103492# - complete re-factoring of method due to new page/print 711 // preview functionality. 712 void SwAccPreviewData::InvalidateSelection( const SwPageFrm* _pSelectedPageFrm ) 713 { 714 mpSelPage = _pSelectedPageFrm; 715 ASSERT( mpSelPage, "selected page not found" ); 716 } 717 718 struct ContainsPredicate 719 { 720 const Point& mrPoint; 721 ContainsPredicate( const Point& rPoint ) : mrPoint(rPoint) {} 722 bool operator() ( const Rectangle& rRect ) const 723 { 724 return rRect.IsInside( mrPoint ) ? true : false; 725 } 726 }; 727 728 const SwRect& SwAccPreviewData::GetVisArea() const 729 { 730 return maVisArea; 731 } 732 733 void SwAccPreviewData::AdjustMapMode( MapMode& rMapMode, 734 const Point& rPoint ) const 735 { 736 // adjust scale 737 rMapMode.SetScaleX( maScale ); 738 rMapMode.SetScaleY( maScale ); 739 740 // find proper rectangle 741 Rectangles::const_iterator aBegin = maLogicRects.begin(); 742 Rectangles::const_iterator aEnd = maLogicRects.end(); 743 Rectangles::const_iterator aFound = ::std::find_if( aBegin, aEnd, 744 ContainsPredicate( rPoint ) ); 745 746 if( aFound != aEnd ) 747 { 748 // found! set new origin 749 Point aPoint = (maPreviewRects.begin() + (aFound - aBegin))->TopLeft(); 750 aPoint -= (maLogicRects.begin() + (aFound-aBegin))->TopLeft(); 751 rMapMode.SetOrigin( aPoint ); 752 } 753 // else: don't adjust MapMode 754 } 755 756 void SwAccPreviewData::DisposePage(const SwPageFrm *pPageFrm ) 757 { 758 if( mpSelPage == pPageFrm ) 759 mpSelPage = 0; 760 } 761 762 /** adjust logic page retangle to its visible part 763 764 OD 17.01.2003 #103492# 765 766 @author OD 767 */ 768 void SwAccPreviewData::AdjustLogicPgRectToVisibleArea( 769 SwRect& _iorLogicPgSwRect, 770 const SwRect& _rPrevwPgSwRect, 771 const Size& _rPrevwWinSize ) 772 { 773 // determine preview window rectangle 774 const SwRect aPrevwWinSwRect( Point( 0, 0 ), _rPrevwWinSize ); 775 // calculate visible preview page rectangle 776 SwRect aVisPrevwPgSwRect( _rPrevwPgSwRect ); 777 aVisPrevwPgSwRect.Intersection( aPrevwWinSwRect ); 778 // adjust logic page rectangle 779 SwTwips nTmpDiff; 780 // left 781 nTmpDiff = aVisPrevwPgSwRect.Left() - _rPrevwPgSwRect.Left(); 782 if ( nTmpDiff > 0 ) 783 _iorLogicPgSwRect.Left( _iorLogicPgSwRect.Left() + nTmpDiff ); 784 // top 785 nTmpDiff = aVisPrevwPgSwRect.Top() - _rPrevwPgSwRect.Top(); 786 if ( nTmpDiff > 0 ) 787 _iorLogicPgSwRect.Top( _iorLogicPgSwRect.Top() + nTmpDiff ); 788 // right 789 nTmpDiff = _rPrevwPgSwRect.Right() - aVisPrevwPgSwRect.Right(); 790 if ( nTmpDiff > 0 ) 791 _iorLogicPgSwRect.Right( _iorLogicPgSwRect.Right() - nTmpDiff ); 792 // bottom 793 nTmpDiff = _rPrevwPgSwRect.Bottom() - aVisPrevwPgSwRect.Bottom(); 794 if ( nTmpDiff > 0 ) 795 _iorLogicPgSwRect.Bottom( _iorLogicPgSwRect.Bottom() - nTmpDiff ); 796 } 797 798 //------------------------------------------------------------------------------ 799 static sal_Bool AreInSameTable( const uno::Reference< XAccessible >& rAcc, 800 const SwFrm *pFrm ) 801 { 802 sal_Bool bRet = sal_False; 803 804 if( pFrm && pFrm->IsCellFrm() && rAcc.is() ) 805 { 806 // Is it in the same table? We check that 807 // by comparing the last table frame in the 808 // follow chain, because that's cheaper than 809 // searching the first one. 810 SwAccessibleContext *pAccImpl = 811 static_cast< SwAccessibleContext *>( rAcc.get() ); 812 if( pAccImpl->GetFrm()->IsCellFrm() ) 813 { 814 const SwTabFrm *pTabFrm1 = pAccImpl->GetFrm()->FindTabFrm(); 815 while( pTabFrm1->GetFollow() ) 816 pTabFrm1 = pTabFrm1->GetFollow(); 817 818 const SwTabFrm *pTabFrm2 = pFrm->FindTabFrm(); 819 while( pTabFrm2->GetFollow() ) 820 pTabFrm2 = pTabFrm2->GetFollow(); 821 822 bRet = (pTabFrm1 == pTabFrm2); 823 } 824 } 825 826 return bRet; 827 } 828 829 void SwAccessibleMap::FireEvent( const SwAccessibleEvent_Impl& rEvent ) 830 { 831 ::vos::ORef < SwAccessibleContext > xAccImpl( rEvent.GetContext() ); 832 if( SwAccessibleEvent_Impl::SHAPE_SELECTION == rEvent.GetType() ) 833 { 834 DoInvalidateShapeSelection(); 835 } 836 else if( xAccImpl.isValid() && xAccImpl->GetFrm() ) 837 { 838 // --> OD 2009-01-07 #i88069# 839 if ( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE && 840 rEvent.IsInvalidateTextAttrs() ) 841 { 842 xAccImpl->InvalidateAttr(); 843 } 844 // <-- 845 switch( rEvent.GetType() ) 846 { 847 case SwAccessibleEvent_Impl::INVALID_CONTENT: 848 xAccImpl->InvalidateContent(); 849 break; 850 case SwAccessibleEvent_Impl::POS_CHANGED: 851 xAccImpl->InvalidatePosOrSize( rEvent.GetOldBox() ); 852 break; 853 case SwAccessibleEvent_Impl::CHILD_POS_CHANGED: 854 xAccImpl->InvalidateChildPosOrSize( rEvent.GetFrmOrObj(), 855 rEvent.GetOldBox() ); 856 break; 857 case SwAccessibleEvent_Impl::DISPOSE: 858 ASSERT( xAccImpl.isValid(), 859 "dispose event has been stored" ); 860 break; 861 // --> OD 2009-01-06 #i88069# 862 case SwAccessibleEvent_Impl::INVALID_ATTR: 863 // nothing to do here - handled above 864 break; 865 // <-- 866 default: 867 break; 868 } 869 if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() ) 870 { 871 if( rEvent.IsUpdateCursorPos() ) 872 xAccImpl->InvalidateCursorPos(); 873 if( rEvent.IsInvalidateStates() ) 874 xAccImpl->InvalidateStates( rEvent.GetStates() ); 875 if( rEvent.IsInvalidateRelation() ) 876 { 877 // --> OD 2005-12-01 #i27138# 878 // both events CONTENT_FLOWS_FROM_RELATION_CHANGED and 879 // CONTENT_FLOWS_TO_RELATION_CHANGED are possible 880 if ( rEvent.GetAllStates() & ACC_STATE_RELATION_FROM ) 881 { 882 xAccImpl->InvalidateRelation( 883 AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED ); 884 } 885 if ( rEvent.GetAllStates() & ACC_STATE_RELATION_TO ) 886 { 887 xAccImpl->InvalidateRelation( 888 AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED ); 889 } 890 // <-- 891 } 892 // --> OD 2005-12-12 #i27301# - submit event TEXT_SELECTION_CHANGED 893 if ( rEvent.IsInvalidateTextSelection() ) 894 { 895 xAccImpl->InvalidateTextSelection(); 896 } 897 // <-- 898 } 899 } 900 } 901 902 void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent ) 903 { 904 vos::OGuard aGuard( maEventMutex ); 905 906 if( !mpEvents ) 907 mpEvents = new SwAccessibleEventList_Impl; 908 if( !mpEventMap ) 909 mpEventMap = new SwAccessibleEventMap_Impl; 910 911 if( mpEvents->IsFiring() ) 912 { 913 // While events are fired new ones are generated. They have to be fired 914 // now. This does not work for DISPOSE events! 915 ASSERT( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE, 916 "dispose event while firing events" ); 917 FireEvent( rEvent ); 918 } 919 else 920 { 921 922 SwAccessibleEventMap_Impl::iterator aIter = 923 mpEventMap->find( rEvent.GetFrmOrObj() ); 924 if( aIter != mpEventMap->end() ) 925 { 926 SwAccessibleEvent_Impl aEvent( *(*aIter).second ); 927 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE, 928 "dispose events should not be stored" ); 929 sal_Bool bAppendEvent = sal_True; 930 switch( rEvent.GetType() ) 931 { 932 case SwAccessibleEvent_Impl::CARET_OR_STATES: 933 // A CARET_OR_STATES event is added to any other 934 // event only. It is broadcasted after any other event, so the 935 // event should be put to the back. 936 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED, 937 "invalid event combination" ); 938 aEvent.SetStates( rEvent.GetAllStates() ); 939 break; 940 case SwAccessibleEvent_Impl::INVALID_CONTENT: 941 // An INVALID_CONTENT event overwrites a CARET_OR_STATES 942 // event (but keeps its flags) and it is contained in a 943 // POS_CHANGED event. 944 // Therefor, the event's type has to be adapted and the event 945 // has to be put at the end. 946 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED, 947 "invalid event combination" ); 948 if( aEvent.GetType() == SwAccessibleEvent_Impl::CARET_OR_STATES ) 949 aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT ); 950 break; 951 case SwAccessibleEvent_Impl::POS_CHANGED: 952 // A pos changed event overwrites CARET_STATES (keeping its 953 // flags) as well as INVALID_CONTENT. The old box position 954 // has to be stored however if the old event is not a 955 // POS_CHANGED itself. 956 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED, 957 "invalid event combination" ); 958 if( aEvent.GetType() != SwAccessibleEvent_Impl::POS_CHANGED ) 959 aEvent.SetOldBox( rEvent.GetOldBox() ); 960 aEvent.SetType( SwAccessibleEvent_Impl::POS_CHANGED ); 961 break; 962 case SwAccessibleEvent_Impl::CHILD_POS_CHANGED: 963 // CHILD_POS_CHANGED events can only follow CHILD_POS_CHANGED 964 // events. The only action that needs to be done again is 965 // to put the old event to the back. The new one cannot be used, 966 // because we are interested in the old frame bounds. 967 ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::CHILD_POS_CHANGED, 968 "invalid event combination" ); 969 break; 970 case SwAccessibleEvent_Impl::SHAPE_SELECTION: 971 ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::SHAPE_SELECTION, 972 "invalid event combination" ); 973 break; 974 case SwAccessibleEvent_Impl::DISPOSE: 975 // DISPOSE events overwrite all others. They are not stored 976 // but executed immediatly to avoid broadcasting of 977 // defunctional objects. So what needs to be done here is to 978 // remove all events for the frame in question. 979 bAppendEvent = sal_False; 980 break; 981 // --> OD 2009-01-06 #i88069# 982 case SwAccessibleEvent_Impl::INVALID_ATTR: 983 ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR, 984 "invalid event combination" ); 985 break; 986 // <-- 987 } 988 if( bAppendEvent ) 989 { 990 mpEvents->erase( (*aIter).second ); 991 (*aIter).second = mpEvents->insert( mpEvents->end(), aEvent ); 992 } 993 else 994 { 995 mpEvents->erase( (*aIter).second ); 996 mpEventMap->erase( aIter ); 997 } 998 } 999 else if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() ) 1000 { 1001 SwAccessibleEventMap_Impl::value_type aEntry( rEvent.GetFrmOrObj(), 1002 mpEvents->insert( mpEvents->end(), rEvent ) ); 1003 mpEventMap->insert( aEntry ); 1004 } 1005 } 1006 } 1007 1008 void SwAccessibleMap::InvalidateCursorPosition( 1009 const uno::Reference< XAccessible >& rAcc ) 1010 { 1011 SwAccessibleContext *pAccImpl = 1012 static_cast< SwAccessibleContext *>( rAcc.get() ); 1013 ASSERT( pAccImpl, "no caret context" ); 1014 ASSERT( pAccImpl->GetFrm(), "caret context is disposed" ); 1015 if( GetShell()->ActionPend() ) 1016 { 1017 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES, 1018 pAccImpl, 1019 SwAccessibleChild(pAccImpl->GetFrm()), 1020 ACC_STATE_CARET ); 1021 AppendEvent( aEvent ); 1022 } 1023 else 1024 { 1025 FireEvents(); 1026 // While firing events the current frame might have 1027 // been disposed because it moved out of the vis area. 1028 // Setting the cursor for such frames is useless and even 1029 // causes asserts. 1030 if( pAccImpl->GetFrm() ) 1031 pAccImpl->InvalidateCursorPos(); 1032 } 1033 } 1034 1035 void SwAccessibleMap::InvalidateShapeSelection() 1036 { 1037 if( GetShell()->ActionPend() ) 1038 { 1039 SwAccessibleEvent_Impl aEvent( 1040 SwAccessibleEvent_Impl::SHAPE_SELECTION ); 1041 AppendEvent( aEvent ); 1042 } 1043 else 1044 { 1045 FireEvents(); 1046 DoInvalidateShapeSelection(); 1047 } 1048 } 1049 1050 void SwAccessibleMap::DoInvalidateShapeSelection() 1051 { 1052 SwAccessibleObjShape_Impl *pShapes = 0; 1053 SwAccessibleObjShape_Impl *pSelShape = 0; 1054 size_t nShapes = 0; 1055 1056 const ViewShell *pVSh = GetShell(); 1057 const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ? 1058 static_cast< const SwFEShell * >( pVSh ) : 0; 1059 sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0; 1060 1061 { 1062 vos::OGuard aGuard( maMutex ); 1063 if( mpShapeMap ) 1064 pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape ); 1065 } 1066 1067 if( pShapes ) 1068 { 1069 ::std::list< const SwFrm * > aParents; 1070 Window *pWin = GetShell()->GetWin(); 1071 sal_Bool bFocused = pWin && pWin->HasFocus(); 1072 SwAccessibleObjShape_Impl *pShape = pShapes; 1073 while( nShapes ) 1074 { 1075 if( pShape->second.isValid() ) 1076 { 1077 sal_Bool bChanged; 1078 if( pShape >= pSelShape ) 1079 { 1080 bChanged = 1081 pShape->second->SetState( AccessibleStateType::SELECTED ); 1082 if( bFocused && 1 == nSelShapes ) 1083 pShape->second->SetState( AccessibleStateType::FOCUSED ); 1084 else 1085 pShape->second->ResetState( AccessibleStateType::FOCUSED ); 1086 } 1087 else 1088 { 1089 bChanged = 1090 pShape->second->ResetState( AccessibleStateType::SELECTED ); 1091 pShape->second->ResetState( AccessibleStateType::FOCUSED ); 1092 } 1093 if( bChanged ) 1094 { 1095 const SwFrm* pParent = SwAccessibleFrame::GetParent( 1096 SwAccessibleChild( pShape->first ), 1097 GetShell()->IsPreView() ); 1098 aParents.push_back( pParent ); 1099 } 1100 } 1101 1102 --nShapes; 1103 ++pShape; 1104 } 1105 if( aParents.size() > 0 ) 1106 { 1107 ::std::list< const SwFrm * >::const_iterator aIter = aParents.begin(); 1108 ::std::list< const SwFrm * >::const_iterator aEndIter = aParents.end(); 1109 while( aIter != aEndIter ) 1110 { 1111 ::vos::ORef< SwAccessibleContext > xParentAccImpl; 1112 { 1113 vos::OGuard aGuard( maMutex ); 1114 if( mpFrmMap ) 1115 { 1116 SwAccessibleContextMap_Impl::const_iterator aMapIter = 1117 mpFrmMap->find( *aIter ); 1118 if( aMapIter != mpFrmMap->end() ) 1119 { 1120 uno::Reference < XAccessible > xAcc( (*aMapIter).second ); 1121 xParentAccImpl = 1122 static_cast< SwAccessibleContext *>( xAcc.get() ); 1123 } 1124 } 1125 } 1126 if( xParentAccImpl.isValid() ) 1127 { 1128 AccessibleEventObject aEvent; 1129 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED; 1130 xParentAccImpl->FireAccessibleEvent( aEvent ); 1131 } 1132 1133 ++aIter; 1134 } 1135 } 1136 1137 delete[] pShapes; 1138 } 1139 } 1140 1141 void SwAccessibleMap::DoInvalidateShapeFocus() 1142 { 1143 const ViewShell *pVSh = GetShell(); 1144 const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ? 1145 static_cast< const SwFEShell * >( pVSh ) : 0; 1146 sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0; 1147 1148 if( nSelShapes != 1 ) 1149 return; 1150 1151 SwAccessibleObjShape_Impl *pShapes = 0; 1152 SwAccessibleObjShape_Impl *pSelShape = 0; 1153 size_t nShapes = 0; 1154 1155 1156 { 1157 vos::OGuard aGuard( maMutex ); 1158 if( mpShapeMap ) 1159 pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape ); 1160 } 1161 1162 if( pShapes ) 1163 { 1164 Window *pWin = GetShell()->GetWin(); 1165 sal_Bool bFocused = pWin && pWin->HasFocus(); 1166 SwAccessibleObjShape_Impl *pShape = pShapes; 1167 while( nShapes ) 1168 { 1169 if( pShape->second.isValid() ) 1170 { 1171 if( bFocused && pShape >= pSelShape ) 1172 pShape->second->SetState( AccessibleStateType::FOCUSED ); 1173 else 1174 pShape->second->ResetState( AccessibleStateType::FOCUSED ); 1175 } 1176 1177 --nShapes; 1178 ++pShape; 1179 } 1180 1181 delete[] pShapes; 1182 } 1183 } 1184 1185 1186 SwAccessibleMap::SwAccessibleMap( ViewShell *pSh ) : 1187 mpFrmMap( 0 ), 1188 mpShapeMap( 0 ), 1189 mpShapes( 0 ), 1190 mpEvents( 0 ), 1191 mpEventMap( 0 ), 1192 // --> OD 2005-12-13 #i27301# 1193 mpSelectedParas( 0 ), 1194 // <-- 1195 mpVSh( pSh ), 1196 mpPreview( 0 ), 1197 mnPara( 1 ), 1198 mnFootnote( 1 ), 1199 mnEndnote( 1 ), 1200 mbShapeSelected( sal_False ) 1201 { 1202 pSh->GetLayout()->AddAccessibleShell(); 1203 } 1204 1205 SwAccessibleMap::~SwAccessibleMap() 1206 { 1207 uno::Reference < XAccessible > xAcc; 1208 { 1209 vos::OGuard aGuard( maMutex ); 1210 if( mpFrmMap ) 1211 { 1212 const SwRootFrm *pRootFrm = GetShell()->GetLayout(); 1213 SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm ); 1214 if( aIter != mpFrmMap->end() ) 1215 xAcc = (*aIter).second; 1216 if( !xAcc.is() ) 1217 xAcc = new SwAccessibleDocument( this ); 1218 } 1219 } 1220 1221 SwAccessibleDocument *pAcc = 1222 static_cast< SwAccessibleDocument * >( xAcc.get() ); 1223 pAcc->Dispose( sal_True ); 1224 1225 { 1226 vos::OGuard aGuard( maMutex ); 1227 #ifdef DBG_UTIL 1228 ASSERT( !mpFrmMap || mpFrmMap->empty(), 1229 "Frame map should be empty after disposing the root frame" ); 1230 if( mpFrmMap ) 1231 { 1232 SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin(); 1233 while( aIter != mpFrmMap->end() ) 1234 { 1235 uno::Reference < XAccessible > xTmp = (*aIter).second; 1236 if( xTmp.is() ) 1237 { 1238 SwAccessibleContext *pTmp = 1239 static_cast< SwAccessibleContext * >( xTmp.get() ); 1240 (void) pTmp; 1241 } 1242 ++aIter; 1243 } 1244 } 1245 ASSERT( !mpShapeMap || mpShapeMap->empty(), 1246 "Object map should be empty after disposing the root frame" ); 1247 if( mpShapeMap ) 1248 { 1249 SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->begin(); 1250 while( aIter != mpShapeMap->end() ) 1251 { 1252 uno::Reference < XAccessible > xTmp = (*aIter).second; 1253 if( xTmp.is() ) 1254 { 1255 ::accessibility::AccessibleShape *pTmp = 1256 static_cast< ::accessibility::AccessibleShape* >( xTmp.get() ); 1257 (void) pTmp; 1258 } 1259 ++aIter; 1260 } 1261 } 1262 #endif 1263 delete mpFrmMap; 1264 mpFrmMap = 0; 1265 delete mpShapeMap; 1266 mpShapeMap = 0; 1267 delete mpShapes; 1268 mpShapes = 0; 1269 // --> OD 2005-12-13 #i27301# 1270 delete mpSelectedParas; 1271 mpSelectedParas = 0; 1272 // <-- 1273 } 1274 1275 delete mpPreview; 1276 mpPreview = NULL; 1277 1278 { 1279 vos::OGuard aGuard( maEventMutex ); 1280 #ifdef DBG_UTIL 1281 ASSERT( !(mpEvents || mpEventMap), "pending events" ); 1282 if( mpEvents ) 1283 { 1284 SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin(); 1285 while( aIter != mpEvents->end() ) 1286 { 1287 ++aIter; 1288 } 1289 } 1290 if( mpEventMap ) 1291 { 1292 SwAccessibleEventMap_Impl::iterator aIter = mpEventMap->begin(); 1293 while( aIter != mpEventMap->end() ) 1294 { 1295 ++aIter; 1296 } 1297 } 1298 #endif 1299 delete mpEventMap; 1300 mpEventMap = 0; 1301 delete mpEvents; 1302 mpEvents = 0; 1303 } 1304 mpVSh->GetLayout()->RemoveAccessibleShell(); 1305 } 1306 1307 uno::Reference< XAccessible > SwAccessibleMap::_GetDocumentView( 1308 sal_Bool bPagePreview ) 1309 { 1310 uno::Reference < XAccessible > xAcc; 1311 sal_Bool bSetVisArea = sal_False; 1312 1313 { 1314 vos::OGuard aGuard( maMutex ); 1315 1316 if( !mpFrmMap ) 1317 { 1318 mpFrmMap = new SwAccessibleContextMap_Impl; 1319 #ifdef DBG_UTIL 1320 mpFrmMap->mbLocked = sal_False; 1321 #endif 1322 } 1323 1324 #ifdef DBG_UTIL 1325 ASSERT( !mpFrmMap->mbLocked, "Map is locked" ); 1326 mpFrmMap->mbLocked = sal_True; 1327 #endif 1328 1329 const SwRootFrm *pRootFrm = GetShell()->GetLayout(); 1330 SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm ); 1331 if( aIter != mpFrmMap->end() ) 1332 xAcc = (*aIter).second; 1333 if( xAcc.is() ) 1334 { 1335 bSetVisArea = sal_True; // Set VisArea when map mutex is not 1336 // locked 1337 } 1338 else 1339 { 1340 if( bPagePreview ) 1341 xAcc = new SwAccessiblePreview( this ); 1342 else 1343 xAcc = new SwAccessibleDocument( this ); 1344 1345 if( aIter != mpFrmMap->end() ) 1346 { 1347 (*aIter).second = xAcc; 1348 } 1349 else 1350 { 1351 SwAccessibleContextMap_Impl::value_type aEntry( pRootFrm, xAcc ); 1352 mpFrmMap->insert( aEntry ); 1353 } 1354 } 1355 1356 #ifdef DBG_UTIL 1357 mpFrmMap->mbLocked = sal_False; 1358 #endif 1359 } 1360 1361 if( bSetVisArea ) 1362 { 1363 SwAccessibleDocumentBase *pAcc = 1364 static_cast< SwAccessibleDocumentBase * >( xAcc.get() ); 1365 pAcc->SetVisArea(); 1366 } 1367 1368 return xAcc; 1369 } 1370 1371 uno::Reference< XAccessible > SwAccessibleMap::GetDocumentView( ) 1372 { 1373 return _GetDocumentView( sal_False ); 1374 } 1375 1376 // OD 14.01.2003 #103492# - complete re-factoring of method due to new page/print 1377 // preview functionality. 1378 uno::Reference<XAccessible> SwAccessibleMap::GetDocumentPreview( 1379 const std::vector<PrevwPage*>& _rPrevwPages, 1380 const Fraction& _rScale, 1381 const SwPageFrm* _pSelectedPageFrm, 1382 const Size& _rPrevwWinSize ) 1383 { 1384 // create & update preview data object 1385 if( mpPreview == NULL ) 1386 mpPreview = new SwAccPreviewData(); 1387 mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize ); 1388 1389 uno::Reference<XAccessible> xAcc = _GetDocumentView( sal_True ); 1390 return xAcc; 1391 } 1392 1393 uno::Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrm *pFrm, 1394 sal_Bool bCreate ) 1395 { 1396 uno::Reference < XAccessible > xAcc; 1397 uno::Reference < XAccessible > xOldCursorAcc; 1398 sal_Bool bOldShapeSelected = sal_False; 1399 1400 { 1401 vos::OGuard aGuard( maMutex ); 1402 1403 if( !mpFrmMap && bCreate ) 1404 mpFrmMap = new SwAccessibleContextMap_Impl; 1405 if( mpFrmMap ) 1406 { 1407 SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pFrm ); 1408 if( aIter != mpFrmMap->end() ) 1409 xAcc = (*aIter).second; 1410 1411 if( !xAcc.is() && bCreate ) 1412 { 1413 SwAccessibleContext *pAcc = 0; 1414 switch( pFrm->GetType() ) 1415 { 1416 case FRM_TXT: 1417 mnPara++; 1418 pAcc = new SwAccessibleParagraph( *this, 1419 static_cast< const SwTxtFrm& >( *pFrm ) ); 1420 break; 1421 case FRM_HEADER: 1422 pAcc = new SwAccessibleHeaderFooter( this, 1423 static_cast< const SwHeaderFrm *>( pFrm ) ); 1424 break; 1425 case FRM_FOOTER: 1426 pAcc = new SwAccessibleHeaderFooter( this, 1427 static_cast< const SwFooterFrm *>( pFrm ) ); 1428 break; 1429 case FRM_FTN: 1430 { 1431 const SwFtnFrm *pFtnFrm = 1432 static_cast < const SwFtnFrm * >( pFrm ); 1433 sal_Bool bIsEndnote = 1434 SwAccessibleFootnote::IsEndnote( pFtnFrm ); 1435 pAcc = new SwAccessibleFootnote( this, bIsEndnote, 1436 (bIsEndnote ? mnEndnote++ : mnFootnote++), 1437 pFtnFrm ); 1438 } 1439 break; 1440 case FRM_FLY: 1441 { 1442 const SwFlyFrm *pFlyFrm = 1443 static_cast < const SwFlyFrm * >( pFrm ); 1444 switch( SwAccessibleFrameBase::GetNodeType( pFlyFrm ) ) 1445 { 1446 case ND_GRFNODE: 1447 pAcc = new SwAccessibleGraphic( this, pFlyFrm ); 1448 break; 1449 case ND_OLENODE: 1450 pAcc = new SwAccessibleEmbeddedObject( this, pFlyFrm ); 1451 break; 1452 default: 1453 pAcc = new SwAccessibleTextFrame( this, pFlyFrm ); 1454 break; 1455 } 1456 } 1457 break; 1458 case FRM_CELL: 1459 pAcc = new SwAccessibleCell( this, 1460 static_cast< const SwCellFrm *>( pFrm ) ); 1461 break; 1462 case FRM_TAB: 1463 pAcc = new SwAccessibleTable( this, 1464 static_cast< const SwTabFrm *>( pFrm ) ); 1465 break; 1466 case FRM_PAGE: 1467 DBG_ASSERT( GetShell()->IsPreView(), 1468 "accessible page frames only in PagePreview" ); 1469 pAcc = new SwAccessiblePage( this, pFrm ); 1470 break; 1471 } 1472 xAcc = pAcc; 1473 1474 ASSERT( xAcc.is(), "unknown frame type" ); 1475 if( xAcc.is() ) 1476 { 1477 if( aIter != mpFrmMap->end() ) 1478 { 1479 (*aIter).second = xAcc; 1480 } 1481 else 1482 { 1483 SwAccessibleContextMap_Impl::value_type aEntry( pFrm, xAcc ); 1484 mpFrmMap->insert( aEntry ); 1485 } 1486 1487 if( pAcc->HasCursor() && 1488 !AreInSameTable( mxCursorContext, pFrm ) ) 1489 { 1490 // If the new context has the focus, and if we know 1491 // another context that had the focus, then the focus 1492 // just moves from the old context to the new one. We 1493 // have to send a focus event and a caret event for 1494 // the old context then. We have to to that know, 1495 // because after we have left this method, anyone might 1496 // call getStates for the new context and will get a 1497 // focused state then. Sending the focus changes event 1498 // after that seems to be strange. However, we cannot 1499 // send a focus event fo the new context now, because 1500 // noone except us knows it. In any case, we remeber 1501 // the new context as the one that has the focus 1502 // currently. 1503 1504 xOldCursorAcc = mxCursorContext; 1505 mxCursorContext = xAcc; 1506 1507 bOldShapeSelected = mbShapeSelected; 1508 mbShapeSelected = sal_False; 1509 } 1510 } 1511 } 1512 } 1513 } 1514 1515 // Invalidate focus for old object when map is not locked 1516 if( xOldCursorAcc.is() ) 1517 InvalidateCursorPosition( xOldCursorAcc ); 1518 if( bOldShapeSelected ) 1519 InvalidateShapeSelection(); 1520 1521 return xAcc; 1522 } 1523 1524 ::vos::ORef < SwAccessibleContext > SwAccessibleMap::GetContextImpl( 1525 const SwFrm *pFrm, 1526 sal_Bool bCreate ) 1527 { 1528 uno::Reference < XAccessible > xAcc( GetContext( pFrm, bCreate ) ); 1529 1530 ::vos::ORef < SwAccessibleContext > xAccImpl( 1531 static_cast< SwAccessibleContext * >( xAcc.get() ) ); 1532 1533 return xAccImpl; 1534 } 1535 1536 uno::Reference< XAccessible> SwAccessibleMap::GetContext( 1537 const SdrObject *pObj, 1538 SwAccessibleContext *pParentImpl, 1539 sal_Bool bCreate ) 1540 { 1541 uno::Reference < XAccessible > xAcc; 1542 uno::Reference < XAccessible > xOldCursorAcc; 1543 1544 { 1545 vos::OGuard aGuard( maMutex ); 1546 1547 if( !mpShapeMap && bCreate ) 1548 mpShapeMap = new SwAccessibleShapeMap_Impl( this ); 1549 if( mpShapeMap ) 1550 { 1551 SwAccessibleShapeMap_Impl::iterator aIter = 1552 mpShapeMap->find( pObj ); 1553 if( aIter != mpShapeMap->end() ) 1554 xAcc = (*aIter).second; 1555 1556 if( !xAcc.is() && bCreate ) 1557 { 1558 ::accessibility::AccessibleShape *pAcc = 0; 1559 uno::Reference < drawing::XShape > xShape( 1560 const_cast< SdrObject * >( pObj )->getUnoShape(), 1561 uno::UNO_QUERY ); 1562 if( xShape.is() ) 1563 { 1564 ::accessibility::ShapeTypeHandler& rShapeTypeHandler = 1565 ::accessibility::ShapeTypeHandler::Instance(); 1566 uno::Reference < XAccessible > xParent( pParentImpl ); 1567 ::accessibility::AccessibleShapeInfo aShapeInfo( 1568 xShape, xParent, this ); 1569 1570 pAcc = rShapeTypeHandler.CreateAccessibleObject( 1571 aShapeInfo, mpShapeMap->GetInfo() ); 1572 } 1573 xAcc = pAcc; 1574 1575 ASSERT( xAcc.is(), "unknown shape type" ); 1576 if( xAcc.is() ) 1577 { 1578 pAcc->Init(); 1579 if( aIter != mpShapeMap->end() ) 1580 { 1581 (*aIter).second = xAcc; 1582 } 1583 else 1584 { 1585 SwAccessibleShapeMap_Impl::value_type aEntry( pObj, 1586 xAcc ); 1587 mpShapeMap->insert( aEntry ); 1588 } 1589 // TODO: focus!!! 1590 } 1591 } 1592 } 1593 } 1594 1595 // Invalidate focus for old object when map is not locked 1596 if( xOldCursorAcc.is() ) 1597 InvalidateCursorPosition( xOldCursorAcc ); 1598 1599 return xAcc; 1600 } 1601 1602 ::vos::ORef < ::accessibility::AccessibleShape > SwAccessibleMap::GetContextImpl( 1603 const SdrObject *pObj, 1604 SwAccessibleContext *pParentImpl, 1605 sal_Bool bCreate ) 1606 { 1607 uno::Reference < XAccessible > xAcc( GetContext( pObj, pParentImpl, bCreate ) ); 1608 1609 ::vos::ORef < ::accessibility::AccessibleShape > xAccImpl( 1610 static_cast< ::accessibility::AccessibleShape* >( xAcc.get() ) ); 1611 1612 return xAccImpl; 1613 } 1614 1615 1616 void SwAccessibleMap::RemoveContext( const SwFrm *pFrm ) 1617 { 1618 vos::OGuard aGuard( maMutex ); 1619 1620 if( mpFrmMap ) 1621 { 1622 SwAccessibleContextMap_Impl::iterator aIter = 1623 mpFrmMap->find( pFrm ); 1624 if( aIter != mpFrmMap->end() ) 1625 { 1626 mpFrmMap->erase( aIter ); 1627 1628 // Remove reference to old caret object. Though mxCursorContext 1629 // is a weak reference and cleared automatically, clearing it 1630 // directly makes sure to not keep a defunctional object. 1631 uno::Reference < XAccessible > xOldAcc( mxCursorContext ); 1632 if( xOldAcc.is() ) 1633 { 1634 SwAccessibleContext *pOldAccImpl = 1635 static_cast< SwAccessibleContext *>( xOldAcc.get() ); 1636 ASSERT( pOldAccImpl->GetFrm(), "old caret context is disposed" ); 1637 if( pOldAccImpl->GetFrm() == pFrm ) 1638 { 1639 xOldAcc.clear(); // get an empty ref 1640 mxCursorContext = xOldAcc; 1641 } 1642 } 1643 1644 if( mpFrmMap->empty() ) 1645 { 1646 delete mpFrmMap; 1647 mpFrmMap = 0; 1648 } 1649 } 1650 } 1651 } 1652 1653 void SwAccessibleMap::RemoveContext( const SdrObject *pObj ) 1654 { 1655 vos::OGuard aGuard( maMutex ); 1656 1657 if( mpShapeMap ) 1658 { 1659 SwAccessibleShapeMap_Impl::iterator aIter = 1660 mpShapeMap->find( pObj ); 1661 if( aIter != mpShapeMap->end() ) 1662 { 1663 mpShapeMap->erase( aIter ); 1664 1665 // The shape selection flag is not cleared, but one might do 1666 // so but has to make sure that the removed context is the one 1667 // that is selected. 1668 1669 if( mpShapeMap->empty() ) 1670 { 1671 delete mpShapeMap; 1672 mpShapeMap = 0; 1673 } 1674 } 1675 } 1676 } 1677 1678 1679 void SwAccessibleMap::Dispose( const SwFrm *pFrm, 1680 const SdrObject *pObj, 1681 Window* pWindow, 1682 sal_Bool bRecursive ) 1683 { 1684 SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow ); 1685 1686 // Indeed, the following assert checks the frame's accessible flag, 1687 // because that's the one that is evaluated in the layout. The frame 1688 // might not be accessible anyway. That's the case for cell frames that 1689 // contain further cells. 1690 ASSERT( !aFrmOrObj.GetSwFrm() || aFrmOrObj.GetSwFrm()->IsAccessibleFrm(), 1691 "non accessible frame should be disposed" ); 1692 1693 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) 1694 { 1695 ::vos::ORef< SwAccessibleContext > xAccImpl; 1696 ::vos::ORef< SwAccessibleContext > xParentAccImpl; 1697 ::vos::ORef< ::accessibility::AccessibleShape > xShapeAccImpl; 1698 // get accessible context for frame 1699 { 1700 vos::OGuard aGuard( maMutex ); 1701 1702 // First of all look for an accessible context for a frame 1703 if( aFrmOrObj.GetSwFrm() && mpFrmMap ) 1704 { 1705 SwAccessibleContextMap_Impl::iterator aIter = 1706 mpFrmMap->find( aFrmOrObj.GetSwFrm() ); 1707 if( aIter != mpFrmMap->end() ) 1708 { 1709 uno::Reference < XAccessible > xAcc( (*aIter).second ); 1710 xAccImpl = 1711 static_cast< SwAccessibleContext *>( xAcc.get() ); 1712 } 1713 } 1714 if( !xAccImpl.isValid() && mpFrmMap ) 1715 { 1716 // If there is none, look if the parent is accessible. 1717 const SwFrm *pParent = 1718 SwAccessibleFrame::GetParent( aFrmOrObj, 1719 GetShell()->IsPreView()); 1720 1721 if( pParent ) 1722 { 1723 SwAccessibleContextMap_Impl::iterator aIter = 1724 mpFrmMap->find( pParent ); 1725 if( aIter != mpFrmMap->end() ) 1726 { 1727 uno::Reference < XAccessible > xAcc( (*aIter).second ); 1728 xParentAccImpl = 1729 static_cast< SwAccessibleContext *>( xAcc.get() ); 1730 } 1731 } 1732 } 1733 if( !xParentAccImpl.isValid() && !aFrmOrObj.GetSwFrm() && 1734 mpShapeMap ) 1735 { 1736 SwAccessibleShapeMap_Impl::iterator aIter = 1737 mpShapeMap->find( aFrmOrObj.GetDrawObject() ); 1738 if( aIter != mpShapeMap->end() ) 1739 { 1740 uno::Reference < XAccessible > xAcc( (*aIter).second ); 1741 xShapeAccImpl = 1742 static_cast< ::accessibility::AccessibleShape *>( xAcc.get() ); 1743 } 1744 } 1745 if( pObj && GetShell()->ActionPend() && 1746 (xParentAccImpl.isValid() || xShapeAccImpl.isValid()) ) 1747 { 1748 // Keep a reference to the XShape to avoid that it 1749 // is deleted with a SwFrmFmt::Modify. 1750 uno::Reference < drawing::XShape > xShape( 1751 const_cast< SdrObject * >( pObj )->getUnoShape(), 1752 uno::UNO_QUERY ); 1753 if( xShape.is() ) 1754 { 1755 if( !mpShapes ) 1756 mpShapes = new SwShapeList_Impl; 1757 mpShapes->push_back( xShape ); 1758 } 1759 } 1760 } 1761 1762 // remove events stored for the frame 1763 { 1764 vos::OGuard aGuard( maEventMutex ); 1765 if( mpEvents ) 1766 { 1767 SwAccessibleEventMap_Impl::iterator aIter = 1768 mpEventMap->find( aFrmOrObj ); 1769 if( aIter != mpEventMap->end() ) 1770 { 1771 SwAccessibleEvent_Impl aEvent( 1772 SwAccessibleEvent_Impl::DISPOSE, aFrmOrObj ); 1773 AppendEvent( aEvent ); 1774 } 1775 } 1776 } 1777 1778 // If the frame is accessible and there is a context for it, dispose 1779 // the frame. If the frame is no context for it but disposing should 1780 // take place recursive, the frame's children have to be disposed 1781 // anyway, so we have to create the context then. 1782 if( xAccImpl.isValid() ) 1783 { 1784 xAccImpl->Dispose( bRecursive ); 1785 } 1786 else if( xParentAccImpl.isValid() ) 1787 { 1788 // If the frame is a cell frame, the table must be notified. 1789 // If we are in an action, a table model change event will 1790 // be broadcasted at the end of the action to give the table 1791 // a chance to generate a single table change event. 1792 1793 xParentAccImpl->DisposeChild( aFrmOrObj, bRecursive ); 1794 } 1795 else if( xShapeAccImpl.isValid() ) 1796 { 1797 RemoveContext( aFrmOrObj.GetDrawObject() ); 1798 xShapeAccImpl->dispose(); 1799 } 1800 1801 if( mpPreview && pFrm && pFrm->IsPageFrm() ) 1802 mpPreview->DisposePage( static_cast< const SwPageFrm *>( pFrm ) ); 1803 } 1804 } 1805 1806 void SwAccessibleMap::InvalidatePosOrSize( const SwFrm *pFrm, 1807 const SdrObject *pObj, 1808 Window* pWindow, 1809 const SwRect& rOldBox ) 1810 { 1811 SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow ); 1812 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) 1813 { 1814 ::vos::ORef< SwAccessibleContext > xAccImpl; 1815 ::vos::ORef< SwAccessibleContext > xParentAccImpl; 1816 { 1817 vos::OGuard aGuard( maMutex ); 1818 1819 if( mpFrmMap ) 1820 { 1821 if( aFrmOrObj.GetSwFrm() ) 1822 { 1823 SwAccessibleContextMap_Impl::iterator aIter = 1824 mpFrmMap->find( aFrmOrObj.GetSwFrm() ); 1825 if( aIter != mpFrmMap->end() ) 1826 { 1827 // If there is an accesible object already it is 1828 // notified directly. 1829 uno::Reference < XAccessible > xAcc( (*aIter).second ); 1830 xAccImpl = 1831 static_cast< SwAccessibleContext *>( xAcc.get() ); 1832 } 1833 } 1834 if( !xAccImpl.isValid() ) 1835 { 1836 // Otherwise we look if the parent is accessible. 1837 // If not, there is nothing to do. 1838 const SwFrm *pParent = 1839 SwAccessibleFrame::GetParent( aFrmOrObj, 1840 GetShell()->IsPreView()); 1841 1842 if( pParent ) 1843 { 1844 SwAccessibleContextMap_Impl::iterator aIter = 1845 mpFrmMap->find( pParent ); 1846 if( aIter != mpFrmMap->end() ) 1847 { 1848 uno::Reference < XAccessible > xAcc( (*aIter).second ); 1849 xParentAccImpl = 1850 static_cast< SwAccessibleContext *>( xAcc.get() ); 1851 } 1852 } 1853 } 1854 } 1855 } 1856 1857 if( xAccImpl.isValid() ) 1858 { 1859 if( GetShell()->ActionPend() ) 1860 { 1861 SwAccessibleEvent_Impl aEvent( 1862 SwAccessibleEvent_Impl::POS_CHANGED, xAccImpl.getBodyPtr(), 1863 aFrmOrObj, rOldBox ); 1864 AppendEvent( aEvent ); 1865 } 1866 else 1867 { 1868 FireEvents(); 1869 xAccImpl->InvalidatePosOrSize( rOldBox ); 1870 } 1871 } 1872 else if( xParentAccImpl.isValid() ) 1873 { 1874 if( GetShell()->ActionPend() ) 1875 { 1876 SwAccessibleEvent_Impl aEvent( 1877 SwAccessibleEvent_Impl::CHILD_POS_CHANGED, 1878 xParentAccImpl.getBodyPtr(), aFrmOrObj, rOldBox ); 1879 AppendEvent( aEvent ); 1880 } 1881 else 1882 { 1883 FireEvents(); 1884 xParentAccImpl->InvalidateChildPosOrSize( aFrmOrObj, 1885 rOldBox ); 1886 } 1887 } 1888 } 1889 } 1890 1891 void SwAccessibleMap::InvalidateContent( const SwFrm *pFrm ) 1892 { 1893 SwAccessibleChild aFrmOrObj( pFrm ); 1894 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) 1895 { 1896 uno::Reference < XAccessible > xAcc; 1897 { 1898 vos::OGuard aGuard( maMutex ); 1899 1900 if( mpFrmMap ) 1901 { 1902 SwAccessibleContextMap_Impl::iterator aIter = 1903 mpFrmMap->find( aFrmOrObj.GetSwFrm() ); 1904 if( aIter != mpFrmMap->end() ) 1905 xAcc = (*aIter).second; 1906 } 1907 } 1908 1909 if( xAcc.is() ) 1910 { 1911 SwAccessibleContext *pAccImpl = 1912 static_cast< SwAccessibleContext *>( xAcc.get() ); 1913 if( GetShell()->ActionPend() ) 1914 { 1915 SwAccessibleEvent_Impl aEvent( 1916 SwAccessibleEvent_Impl::INVALID_CONTENT, pAccImpl, 1917 aFrmOrObj ); 1918 AppendEvent( aEvent ); 1919 } 1920 else 1921 { 1922 FireEvents(); 1923 pAccImpl->InvalidateContent(); 1924 } 1925 } 1926 } 1927 } 1928 1929 // --> OD 2009-01-06 #i88069# 1930 void SwAccessibleMap::InvalidateAttr( const SwTxtFrm& rTxtFrm ) 1931 { 1932 SwAccessibleChild aFrmOrObj( &rTxtFrm ); 1933 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) 1934 { 1935 uno::Reference < XAccessible > xAcc; 1936 { 1937 vos::OGuard aGuard( maMutex ); 1938 1939 if( mpFrmMap ) 1940 { 1941 SwAccessibleContextMap_Impl::iterator aIter = 1942 mpFrmMap->find( aFrmOrObj.GetSwFrm() ); 1943 if( aIter != mpFrmMap->end() ) 1944 xAcc = (*aIter).second; 1945 } 1946 } 1947 1948 if( xAcc.is() ) 1949 { 1950 SwAccessibleContext *pAccImpl = 1951 static_cast< SwAccessibleContext *>( xAcc.get() ); 1952 if( GetShell()->ActionPend() ) 1953 { 1954 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::INVALID_ATTR, 1955 pAccImpl, aFrmOrObj ); 1956 aEvent.SetStates( ACC_STATE_TEXT_ATTRIBUTE_CHANGED ); 1957 AppendEvent( aEvent ); 1958 } 1959 else 1960 { 1961 FireEvents(); 1962 pAccImpl->InvalidateAttr(); 1963 } 1964 } 1965 } 1966 } 1967 // <-- 1968 1969 void SwAccessibleMap::InvalidateCursorPosition( const SwFrm *pFrm ) 1970 { 1971 SwAccessibleChild aFrmOrObj( pFrm ); 1972 sal_Bool bShapeSelected = sal_False; 1973 const ViewShell *pVSh = GetShell(); 1974 if( pVSh->ISA( SwCrsrShell ) ) 1975 { 1976 const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh ); 1977 if( pCSh->IsTableMode() ) 1978 { 1979 while( aFrmOrObj.GetSwFrm() && !aFrmOrObj.GetSwFrm()->IsCellFrm() ) 1980 aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper(); 1981 } 1982 else if( pVSh->ISA( SwFEShell ) ) 1983 { 1984 sal_uInt16 nObjCount; 1985 const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh ); 1986 const SwFrm *pFlyFrm = pFESh->GetCurrFlyFrm(); 1987 if( pFlyFrm ) 1988 { 1989 ASSERT( !pFrm || pFrm->FindFlyFrm() == pFlyFrm, 1990 "cursor is not contained in fly frame" ); 1991 aFrmOrObj = pFlyFrm; 1992 } 1993 else if( (nObjCount = pFESh->IsObjSelected()) > 0 ) 1994 { 1995 bShapeSelected = sal_True; 1996 aFrmOrObj = static_cast<const SwFrm *>( 0 ); 1997 } 1998 } 1999 } 2000 2001 ASSERT( bShapeSelected || aFrmOrObj.IsAccessible(GetShell()->IsPreView()), 2002 "frame is not accessible" ); 2003 2004 uno::Reference < XAccessible > xOldAcc; 2005 uno::Reference < XAccessible > xAcc; 2006 sal_Bool bOldShapeSelected = sal_False; 2007 2008 { 2009 vos::OGuard aGuard( maMutex ); 2010 2011 xOldAcc = mxCursorContext; 2012 mxCursorContext = xAcc; // clear reference 2013 2014 bOldShapeSelected = mbShapeSelected; 2015 mbShapeSelected = bShapeSelected; 2016 2017 if( aFrmOrObj.GetSwFrm() && mpFrmMap ) 2018 { 2019 SwAccessibleContextMap_Impl::iterator aIter = 2020 mpFrmMap->find( aFrmOrObj.GetSwFrm() ); 2021 if( aIter != mpFrmMap->end() ) 2022 xAcc = (*aIter).second; 2023 2024 // For cells, some extra thoughts are necessary, 2025 // because invalidating the cursor for one cell 2026 // invalidates the cursor for all cells of the same 2027 // table. For this reason, we don't want to 2028 // invalidate the cursor for the old cursor object 2029 // and the new one if they are within the same table, 2030 // because this would result in doing the work twice. 2031 // Moreover, we have to make sure to invalidate the 2032 // cursor even if the current cell has no accessible object. 2033 // If the old cursor objects exists and is in the same 2034 // table, its the best choice, because using it avoids 2035 // an unnessarary cursor invalidation cycle when creating 2036 // a new object for the current cell. 2037 if( aFrmOrObj.GetSwFrm()->IsCellFrm() ) 2038 { 2039 if( xOldAcc.is() && 2040 AreInSameTable( xOldAcc, aFrmOrObj.GetSwFrm() ) ) 2041 { 2042 if( xAcc.is() ) 2043 xOldAcc = xAcc; // avoid extra invalidation 2044 else 2045 xAcc = xOldAcc; // make sure ate least one 2046 } 2047 if( !xAcc.is() ) 2048 xAcc = GetContext( aFrmOrObj.GetSwFrm(), sal_True ); 2049 } 2050 } 2051 } 2052 2053 if( xOldAcc.is() && xOldAcc != xAcc ) 2054 InvalidateCursorPosition( xOldAcc ); 2055 if( bOldShapeSelected || bShapeSelected ) 2056 InvalidateShapeSelection(); 2057 if( xAcc.is() ) 2058 InvalidateCursorPosition( xAcc ); 2059 } 2060 2061 void SwAccessibleMap::InvalidateFocus() 2062 { 2063 uno::Reference < XAccessible > xAcc; 2064 sal_Bool bShapeSelected; 2065 { 2066 vos::OGuard aGuard( maMutex ); 2067 2068 xAcc = mxCursorContext; 2069 bShapeSelected = mbShapeSelected; 2070 } 2071 2072 if( xAcc.is() ) 2073 { 2074 SwAccessibleContext *pAccImpl = 2075 static_cast< SwAccessibleContext *>( xAcc.get() ); 2076 pAccImpl->InvalidateFocus(); 2077 } 2078 else if( bShapeSelected ) 2079 { 2080 DoInvalidateShapeFocus(); 2081 } 2082 } 2083 2084 void SwAccessibleMap::SetCursorContext( 2085 const ::vos::ORef < SwAccessibleContext >& rCursorContext ) 2086 { 2087 vos::OGuard aGuard( maMutex ); 2088 uno::Reference < XAccessible > xAcc( rCursorContext.getBodyPtr() ); 2089 mxCursorContext = xAcc; 2090 } 2091 2092 // --> OD 2005-12-12 #i27301# - use new type definition for <_nStates> 2093 void SwAccessibleMap::InvalidateStates( tAccessibleStates _nStates, 2094 const SwFrm* _pFrm ) 2095 { 2096 // Start with the frame or the first upper that is accessible 2097 SwAccessibleChild aFrmOrObj( _pFrm ); 2098 while( aFrmOrObj.GetSwFrm() && 2099 !aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) 2100 aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper(); 2101 if( !aFrmOrObj.GetSwFrm() ) 2102 aFrmOrObj = GetShell()->GetLayout(); 2103 2104 uno::Reference< XAccessible > xAcc( GetContext( aFrmOrObj.GetSwFrm(), sal_True ) ); 2105 SwAccessibleContext *pAccImpl = 2106 static_cast< SwAccessibleContext *>( xAcc.get() ); 2107 if( GetShell()->ActionPend() ) 2108 { 2109 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES, 2110 pAccImpl, 2111 SwAccessibleChild(pAccImpl->GetFrm()), 2112 _nStates ); 2113 AppendEvent( aEvent ); 2114 } 2115 else 2116 { 2117 FireEvents(); 2118 pAccImpl->InvalidateStates( _nStates ); 2119 } 2120 } 2121 // <-- 2122 2123 void SwAccessibleMap::_InvalidateRelationSet( const SwFrm* pFrm, 2124 sal_Bool bFrom ) 2125 { 2126 // first, see if this frame is accessible, and if so, get the respective 2127 SwAccessibleChild aFrmOrObj( pFrm ); 2128 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) 2129 { 2130 uno::Reference < XAccessible > xAcc; 2131 { 2132 vos::OGuard aGuard( maMutex ); 2133 2134 if( mpFrmMap ) 2135 { 2136 SwAccessibleContextMap_Impl::iterator aIter = 2137 mpFrmMap->find( aFrmOrObj.GetSwFrm() ); 2138 if( aIter != mpFrmMap->end() ) 2139 { 2140 xAcc = (*aIter).second; 2141 } 2142 } 2143 } 2144 2145 // deliver event directly, or queue event 2146 if( xAcc.is() ) 2147 { 2148 SwAccessibleContext *pAccImpl = 2149 static_cast< SwAccessibleContext *>( xAcc.get() ); 2150 if( GetShell()->ActionPend() ) 2151 { 2152 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES, 2153 pAccImpl, SwAccessibleChild(pFrm), 2154 ( bFrom 2155 ? ACC_STATE_RELATION_FROM 2156 : ACC_STATE_RELATION_TO ) ); 2157 AppendEvent( aEvent ); 2158 } 2159 else 2160 { 2161 FireEvents(); 2162 pAccImpl->InvalidateRelation( bFrom 2163 ? AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED 2164 : AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED ); 2165 } 2166 } 2167 } 2168 } 2169 2170 void SwAccessibleMap::InvalidateRelationSet( const SwFrm* pMaster, 2171 const SwFrm* pFollow ) 2172 { 2173 _InvalidateRelationSet( pMaster, sal_False ); 2174 _InvalidateRelationSet( pFollow, sal_True ); 2175 } 2176 2177 /** invalidation CONTENT_FLOW_FROM/_TO relation of a paragraph 2178 2179 OD 2005-12-01 #i27138# 2180 2181 @author OD 2182 */ 2183 void SwAccessibleMap::InvalidateParaFlowRelation( const SwTxtFrm& _rTxtFrm, 2184 const bool _bFrom ) 2185 { 2186 _InvalidateRelationSet( &_rTxtFrm, _bFrom ); 2187 } 2188 2189 /** invalidation of text selection of a paragraph 2190 2191 OD 2005-12-12 #i27301# 2192 2193 @author OD 2194 */ 2195 void SwAccessibleMap::InvalidateParaTextSelection( const SwTxtFrm& _rTxtFrm ) 2196 { 2197 // first, see if this frame is accessible, and if so, get the respective 2198 SwAccessibleChild aFrmOrObj( &_rTxtFrm ); 2199 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) 2200 { 2201 uno::Reference < XAccessible > xAcc; 2202 { 2203 vos::OGuard aGuard( maMutex ); 2204 2205 if( mpFrmMap ) 2206 { 2207 SwAccessibleContextMap_Impl::iterator aIter = 2208 mpFrmMap->find( aFrmOrObj.GetSwFrm() ); 2209 if( aIter != mpFrmMap->end() ) 2210 { 2211 xAcc = (*aIter).second; 2212 } 2213 } 2214 } 2215 2216 // deliver event directly, or queue event 2217 if( xAcc.is() ) 2218 { 2219 SwAccessibleContext *pAccImpl = 2220 static_cast< SwAccessibleContext *>( xAcc.get() ); 2221 if( GetShell()->ActionPend() ) 2222 { 2223 SwAccessibleEvent_Impl aEvent( 2224 SwAccessibleEvent_Impl::CARET_OR_STATES, 2225 pAccImpl, 2226 SwAccessibleChild( &_rTxtFrm ), 2227 ACC_STATE_TEXT_SELECTION_CHANGED ); 2228 AppendEvent( aEvent ); 2229 } 2230 else 2231 { 2232 FireEvents(); 2233 pAccImpl->InvalidateTextSelection(); 2234 } 2235 } 2236 } 2237 } 2238 2239 sal_Int32 SwAccessibleMap::GetChildIndex( const SwFrm& rParentFrm, 2240 Window& rChild ) const 2241 { 2242 sal_Int32 nIndex( -1 ); 2243 2244 SwAccessibleChild aFrmOrObj( &rParentFrm ); 2245 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) 2246 { 2247 uno::Reference < XAccessible > xAcc; 2248 { 2249 vos::OGuard aGuard( maMutex ); 2250 2251 if( mpFrmMap ) 2252 { 2253 SwAccessibleContextMap_Impl::iterator aIter = 2254 mpFrmMap->find( aFrmOrObj.GetSwFrm() ); 2255 if( aIter != mpFrmMap->end() ) 2256 { 2257 xAcc = (*aIter).second; 2258 } 2259 } 2260 } 2261 2262 if( xAcc.is() ) 2263 { 2264 SwAccessibleContext *pAccImpl = 2265 static_cast< SwAccessibleContext *>( xAcc.get() ); 2266 2267 nIndex = pAccImpl->GetChildIndex( const_cast<SwAccessibleMap&>(*this), 2268 SwAccessibleChild( &rChild ) ); 2269 } 2270 } 2271 2272 return nIndex; 2273 } 2274 2275 2276 // OD 15.01.2003 #103492# - complete re-factoring of method due to new page/print 2277 // preview functionality. 2278 void SwAccessibleMap::UpdatePreview( const std::vector<PrevwPage*>& _rPrevwPages, 2279 const Fraction& _rScale, 2280 const SwPageFrm* _pSelectedPageFrm, 2281 const Size& _rPrevwWinSize ) 2282 { 2283 DBG_ASSERT( GetShell()->IsPreView(), "no preview?" ); 2284 DBG_ASSERT( mpPreview != NULL, "no preview data?" ); 2285 2286 // OD 15.01.2003 #103492# - adjustments for changed method signature 2287 mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize ); 2288 2289 // propagate change of VisArea through the document's 2290 // accessibility tree; this will also send appropriate scroll 2291 // events 2292 SwAccessibleContext* pDoc = 2293 GetContextImpl( GetShell()->GetLayout() ).getBodyPtr(); 2294 static_cast<SwAccessibleDocumentBase*>( pDoc )->SetVisArea(); 2295 2296 uno::Reference < XAccessible > xOldAcc; 2297 uno::Reference < XAccessible > xAcc; 2298 { 2299 vos::OGuard aGuard( maMutex ); 2300 2301 xOldAcc = mxCursorContext; 2302 2303 const SwPageFrm *pSelPage = mpPreview->GetSelPage(); 2304 if( pSelPage && mpFrmMap ) 2305 { 2306 SwAccessibleContextMap_Impl::iterator aIter = 2307 mpFrmMap->find( pSelPage ); 2308 if( aIter != mpFrmMap->end() ) 2309 xAcc = (*aIter).second; 2310 } 2311 } 2312 2313 if( xOldAcc.is() && xOldAcc != xAcc ) 2314 InvalidateCursorPosition( xOldAcc ); 2315 if( xAcc.is() ) 2316 InvalidateCursorPosition( xAcc ); 2317 } 2318 2319 void SwAccessibleMap::InvalidatePreViewSelection( sal_uInt16 nSelPage ) 2320 { 2321 DBG_ASSERT( GetShell()->IsPreView(), "no preview?" ); 2322 DBG_ASSERT( mpPreview != NULL, "no preview data?" ); 2323 2324 // OD 16.01.2003 #103492# - changed metthod call due to method signature change. 2325 mpPreview->InvalidateSelection( GetShell()->GetLayout()->GetPageByPageNum( nSelPage ) ); 2326 2327 uno::Reference < XAccessible > xOldAcc; 2328 uno::Reference < XAccessible > xAcc; 2329 { 2330 vos::OGuard aGuard( maMutex ); 2331 2332 xOldAcc = mxCursorContext; 2333 2334 const SwPageFrm *pSelPage = mpPreview->GetSelPage(); 2335 if( pSelPage && mpFrmMap ) 2336 { 2337 SwAccessibleContextMap_Impl::iterator aIter = 2338 mpFrmMap->find( pSelPage ); 2339 if( aIter != mpFrmMap->end() ) 2340 xAcc = (*aIter).second; 2341 } 2342 } 2343 2344 if( xOldAcc.is() && xOldAcc != xAcc ) 2345 InvalidateCursorPosition( xOldAcc ); 2346 if( xAcc.is() ) 2347 InvalidateCursorPosition( xAcc ); 2348 } 2349 2350 2351 sal_Bool SwAccessibleMap::IsPageSelected( const SwPageFrm *pPageFrm ) const 2352 { 2353 return mpPreview && mpPreview->GetSelPage() == pPageFrm; 2354 } 2355 2356 2357 void SwAccessibleMap::FireEvents() 2358 { 2359 { 2360 vos::OGuard aGuard( maEventMutex ); 2361 if( mpEvents ) 2362 { 2363 mpEvents->SetFiring(); 2364 SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin(); 2365 while( aIter != mpEvents->end() ) 2366 { 2367 FireEvent( *aIter ); 2368 ++aIter; 2369 } 2370 2371 delete mpEventMap; 2372 mpEventMap = 0; 2373 2374 delete mpEvents; 2375 mpEvents = 0; 2376 } 2377 } 2378 { 2379 vos::OGuard aGuard( maMutex ); 2380 if( mpShapes ) 2381 { 2382 delete mpShapes; 2383 mpShapes = 0; 2384 } 2385 } 2386 2387 } 2388 2389 sal_Bool SwAccessibleMap::IsValid() const 2390 { 2391 return sal_True; 2392 } 2393 2394 Rectangle SwAccessibleMap::GetVisibleArea() const 2395 { 2396 MapMode aSrc( MAP_TWIP ); 2397 MapMode aDest( MAP_100TH_MM ); 2398 return OutputDevice::LogicToLogic( GetVisArea().SVRect(), aSrc, aDest ); 2399 } 2400 2401 // Convert a MM100 value realtive to the document root into a pixel value 2402 // realtive to the screen! 2403 Point SwAccessibleMap::LogicToPixel( const Point& rPoint ) const 2404 { 2405 MapMode aSrc( MAP_100TH_MM ); 2406 MapMode aDest( MAP_TWIP ); 2407 2408 Point aPoint = rPoint; 2409 2410 aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest ); 2411 Window *pWin = GetShell()->GetWin(); 2412 if( pWin ) 2413 { 2414 // OD 16.01.2003 #103492# - get mapping mode for LogicToPixel conversion 2415 MapMode aMapMode; 2416 GetMapMode( aPoint, aMapMode ); 2417 aPoint = pWin->LogicToPixel( aPoint, aMapMode ); 2418 aPoint = pWin->OutputToAbsoluteScreenPixel( aPoint ); 2419 } 2420 2421 return aPoint; 2422 } 2423 2424 Size SwAccessibleMap::LogicToPixel( const Size& rSize ) const 2425 { 2426 MapMode aSrc( MAP_100TH_MM ); 2427 MapMode aDest( MAP_TWIP ); 2428 Size aSize( OutputDevice::LogicToLogic( rSize, aSrc, aDest ) ); 2429 if( GetShell()->GetWin() ) 2430 { 2431 // OD 16.01.2003 #103492# - get mapping mode for LogicToPixel conversion 2432 MapMode aMapMode; 2433 GetMapMode( Point(0,0), aMapMode ); 2434 aSize = GetShell()->GetWin()->LogicToPixel( aSize, aMapMode ); 2435 } 2436 2437 return aSize; 2438 } 2439 2440 Point SwAccessibleMap::PixelToLogic( const Point& rPoint ) const 2441 { 2442 Point aPoint; 2443 Window *pWin = GetShell()->GetWin(); 2444 if( pWin ) 2445 { 2446 aPoint = pWin->ScreenToOutputPixel( rPoint ); 2447 // OD 16.01.2003 #103492# - get mapping mode for PixelToLogic conversion 2448 MapMode aMapMode; 2449 GetMapMode( aPoint, aMapMode ); 2450 aPoint = pWin->PixelToLogic( aPoint, aMapMode ); 2451 MapMode aSrc( MAP_TWIP ); 2452 MapMode aDest( MAP_100TH_MM ); 2453 aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest ); 2454 } 2455 2456 return aPoint; 2457 } 2458 2459 Size SwAccessibleMap::PixelToLogic( const Size& rSize ) const 2460 { 2461 Size aSize; 2462 if( GetShell()->GetWin() ) 2463 { 2464 // OD 16.01.2003 #103492# - get mapping mode for PixelToLogic conversion 2465 MapMode aMapMode; 2466 GetMapMode( Point(0,0), aMapMode ); 2467 aSize = GetShell()->GetWin()->PixelToLogic( rSize, aMapMode ); 2468 MapMode aSrc( MAP_TWIP ); 2469 MapMode aDest( MAP_100TH_MM ); 2470 aSize = OutputDevice::LogicToLogic( aSize, aSrc, aDest ); 2471 } 2472 2473 return aSize; 2474 } 2475 2476 sal_Bool SwAccessibleMap::ReplaceChild ( 2477 ::accessibility::AccessibleShape* pCurrentChild, 2478 const uno::Reference< drawing::XShape >& _rxShape, 2479 const long /*_nIndex*/, 2480 const ::accessibility::AccessibleShapeTreeInfo& /*_rShapeTreeInfo*/ 2481 ) throw (uno::RuntimeException) 2482 { 2483 const SdrObject *pObj = 0; 2484 { 2485 vos::OGuard aGuard( maMutex ); 2486 if( mpShapeMap ) 2487 { 2488 SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin(); 2489 SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end(); 2490 while( aIter != aEndIter && !pObj ) 2491 { 2492 uno::Reference < XAccessible > xAcc( (*aIter).second ); 2493 ::accessibility::AccessibleShape *pAccShape = 2494 static_cast < ::accessibility::AccessibleShape* >( xAcc.get() ); 2495 if( pAccShape == pCurrentChild ) 2496 { 2497 pObj = (*aIter).first; 2498 } 2499 ++aIter; 2500 } 2501 } 2502 } 2503 if( !pObj ) 2504 return sal_False; 2505 2506 uno::Reference < drawing::XShape > xShape( _rxShape ); //keep reference to shape, because 2507 // we might be the only one that 2508 // hold it. 2509 // Also get keep parent. 2510 uno::Reference < XAccessible > xParent( pCurrentChild->getAccessibleParent() ); 2511 pCurrentChild = 0; // well be realease by dispose 2512 Dispose( 0, pObj, 0 ); 2513 2514 { 2515 vos::OGuard aGuard( maMutex ); 2516 2517 if( !mpShapeMap ) 2518 mpShapeMap = new SwAccessibleShapeMap_Impl( this ); 2519 2520 // create the new child 2521 ::accessibility::ShapeTypeHandler& rShapeTypeHandler = 2522 ::accessibility::ShapeTypeHandler::Instance(); 2523 ::accessibility::AccessibleShapeInfo aShapeInfo( 2524 xShape, xParent, this ); 2525 ::accessibility::AccessibleShape* pReplacement = 2526 rShapeTypeHandler.CreateAccessibleObject ( 2527 aShapeInfo, mpShapeMap->GetInfo() ); 2528 2529 uno::Reference < XAccessible > xAcc( pReplacement ); 2530 if( xAcc.is() ) 2531 { 2532 pReplacement->Init(); 2533 2534 SwAccessibleShapeMap_Impl::iterator aIter = 2535 mpShapeMap->find( pObj ); 2536 if( aIter != mpShapeMap->end() ) 2537 { 2538 (*aIter).second = xAcc; 2539 } 2540 else 2541 { 2542 SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAcc ); 2543 mpShapeMap->insert( aEntry ); 2544 } 2545 } 2546 } 2547 2548 SwRect aEmptyRect; 2549 InvalidatePosOrSize( 0, pObj, 0, aEmptyRect ); 2550 2551 return sal_True; 2552 } 2553 2554 Point SwAccessibleMap::PixelToCore( const Point& rPoint ) const 2555 { 2556 Point aPoint; 2557 if( GetShell()->GetWin() ) 2558 { 2559 // OD 15.01.2003 #103492# - replace <PreviewAdjust(..)> by <GetMapMode(..)> 2560 MapMode aMapMode; 2561 GetMapMode( rPoint, aMapMode ); 2562 aPoint = GetShell()->GetWin()->PixelToLogic( rPoint, aMapMode ); 2563 } 2564 return aPoint; 2565 } 2566 2567 static inline long lcl_CorrectCoarseValue(long aCoarseValue, long aFineValue, 2568 long aRefValue, bool bToLower) 2569 { 2570 long aResult = aCoarseValue; 2571 2572 if (bToLower) 2573 { 2574 if (aFineValue < aRefValue) 2575 aResult -= 1; 2576 } 2577 else 2578 { 2579 if (aFineValue > aRefValue) 2580 aResult += 1; 2581 } 2582 2583 return aResult; 2584 } 2585 2586 static inline void lcl_CorrectRectangle(Rectangle & rRect, 2587 const Rectangle & rSource, 2588 const Rectangle & rInGrid) 2589 { 2590 rRect.nLeft = lcl_CorrectCoarseValue(rRect.nLeft, rSource.nLeft, 2591 rInGrid.nLeft, false); 2592 rRect.nTop = lcl_CorrectCoarseValue(rRect.nTop, rSource.nTop, 2593 rInGrid.nTop, false); 2594 rRect.nRight = lcl_CorrectCoarseValue(rRect.nRight, rSource.nRight, 2595 rInGrid.nRight, true); 2596 rRect.nBottom = lcl_CorrectCoarseValue(rRect.nBottom, rSource.nBottom, 2597 rInGrid.nBottom, true); 2598 } 2599 2600 Rectangle SwAccessibleMap::CoreToPixel( const Rectangle& rRect ) const 2601 { 2602 Rectangle aRect; 2603 if( GetShell()->GetWin() ) 2604 { 2605 // OD 15.01.2003 #103492# - replace <PreviewAdjust(..)> by <GetMapMode(..)> 2606 MapMode aMapMode; 2607 GetMapMode( rRect.TopLeft(), aMapMode ); 2608 aRect = GetShell()->GetWin()->LogicToPixel( rRect, aMapMode ); 2609 2610 Rectangle aTmpRect = GetShell()->GetWin()->PixelToLogic( aRect, aMapMode ); 2611 lcl_CorrectRectangle(aRect, rRect, aTmpRect); 2612 } 2613 2614 return aRect; 2615 } 2616 2617 /** get mapping mode for LogicToPixel and PixelToLogic conversions 2618 2619 OD 15.01.2003 #103492# 2620 Replacement method <PreviewAdjust(..)> by new method <GetMapMode>. 2621 Method returns mapping mode of current output device and adjusts it, 2622 if the shell is in page/print preview. 2623 Necessary, because <PreviewAdjust(..)> changes mapping mode at current 2624 output device for mapping logic document positions to page preview window 2625 positions and vice versa and doesn't take care to recover its changes. 2626 2627 @author OD 2628 */ 2629 void SwAccessibleMap::GetMapMode( const Point& _rPoint, 2630 MapMode& _orMapMode ) const 2631 { 2632 MapMode aMapMode = GetShell()->GetWin()->GetMapMode(); 2633 if( GetShell()->IsPreView() ) 2634 { 2635 DBG_ASSERT( mpPreview != NULL, "need preview data" ); 2636 2637 mpPreview->AdjustMapMode( aMapMode, _rPoint ); 2638 } 2639 _orMapMode = aMapMode; 2640 } 2641 2642 /** get size of a dedicated preview page 2643 2644 OD 15.01.2003 #103492# 2645 2646 @author OD 2647 */ 2648 Size SwAccessibleMap::GetPreViewPageSize( sal_uInt16 _nPrevwPageNum ) const 2649 { 2650 DBG_ASSERT( mpVSh->IsPreView(), "no page preview accessible." ); 2651 DBG_ASSERT( mpVSh->IsPreView() && ( mpPreview != NULL ), 2652 "missing accessible preview data at page preview" ); 2653 if ( mpVSh->IsPreView() && ( mpPreview != NULL ) ) 2654 { 2655 return mpVSh->PagePreviewLayout()->GetPrevwPageSizeByPageNum( _nPrevwPageNum ); 2656 } 2657 else 2658 { 2659 return Size( 0, 0 ); 2660 } 2661 } 2662 2663 /** method to build up a new data structure of the accessible pararaphs, 2664 which have a selection 2665 2666 OD 2005-12-13 #i27301# 2667 Important note: method has to used inside a mutual exclusive section 2668 2669 @author OD 2670 */ 2671 SwAccessibleSelectedParas_Impl* SwAccessibleMap::_BuildSelectedParas() 2672 { 2673 // no accessible contexts, no selection 2674 if ( !mpFrmMap ) 2675 { 2676 return 0L; 2677 } 2678 2679 // get cursor as an instance of its base class <SwPaM> 2680 SwPaM* pCrsr( 0L ); 2681 { 2682 SwCrsrShell* pCrsrShell = dynamic_cast<SwCrsrShell*>(GetShell()); 2683 if ( pCrsrShell ) 2684 { 2685 SwFEShell* pFEShell = dynamic_cast<SwFEShell*>(pCrsrShell); 2686 if ( !pFEShell || 2687 ( !pFEShell->IsFrmSelected() && 2688 pFEShell->IsObjSelected() == 0 ) ) 2689 { 2690 // get cursor without updating an existing table cursor. 2691 pCrsr = pCrsrShell->GetCrsr( sal_False ); 2692 } 2693 } 2694 } 2695 // no cursor, no selection 2696 if ( !pCrsr ) 2697 { 2698 return 0L; 2699 } 2700 2701 SwAccessibleSelectedParas_Impl* pRetSelectedParas( 0L ); 2702 2703 // loop on all cursors 2704 SwPaM* pRingStart = pCrsr; 2705 do { 2706 2707 // for a selection the cursor has to have a mark. 2708 // for savety reasons assure that point and mark are in text nodes 2709 if ( pCrsr->HasMark() && 2710 pCrsr->GetPoint()->nNode.GetNode().IsTxtNode() && 2711 pCrsr->GetMark()->nNode.GetNode().IsTxtNode() ) 2712 { 2713 SwPosition* pStartPos = pCrsr->Start(); 2714 SwPosition* pEndPos = pCrsr->End(); 2715 // loop on all text nodes inside the selection 2716 SwNodeIndex aIdx( pStartPos->nNode ); 2717 for ( ; aIdx.GetIndex() <= pEndPos->nNode.GetIndex(); ++aIdx ) 2718 { 2719 SwTxtNode* pTxtNode( aIdx.GetNode().GetTxtNode() ); 2720 if ( pTxtNode ) 2721 { 2722 // loop on all text frames registered at the text node. 2723 SwIterator<SwTxtFrm,SwTxtNode> aIter( *pTxtNode ); 2724 for( SwTxtFrm* pTxtFrm = aIter.First(); pTxtFrm; pTxtFrm = aIter.Next() ) 2725 { 2726 uno::WeakReference < XAccessible > xWeakAcc; 2727 SwAccessibleContextMap_Impl::iterator aMapIter = 2728 mpFrmMap->find( pTxtFrm ); 2729 if( aMapIter != mpFrmMap->end() ) 2730 { 2731 xWeakAcc = (*aMapIter).second; 2732 SwAccessibleParaSelection aDataEntry( 2733 pTxtNode == &(pStartPos->nNode.GetNode()) 2734 ? pStartPos->nContent.GetIndex() 2735 : 0, 2736 pTxtNode == &(pEndPos->nNode.GetNode()) 2737 ? pEndPos->nContent.GetIndex() 2738 : STRING_LEN ); 2739 SwAccessibleSelectedParas_Impl::value_type 2740 aEntry( xWeakAcc, aDataEntry ); 2741 if ( !pRetSelectedParas ) 2742 { 2743 pRetSelectedParas = 2744 new SwAccessibleSelectedParas_Impl; 2745 } 2746 pRetSelectedParas->insert( aEntry ); 2747 } 2748 } 2749 } 2750 } 2751 } 2752 2753 // prepare next turn: get next cursor in ring 2754 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() ); 2755 } while ( pCrsr != pRingStart ); 2756 2757 return pRetSelectedParas; 2758 } 2759 2760 /** invalidation of text selection of all paragraphs 2761 2762 OD 2005-12-13 #i27301# 2763 2764 @author OD 2765 */ 2766 void SwAccessibleMap::InvalidateTextSelectionOfAllParas() 2767 { 2768 vos::OGuard aGuard( maMutex ); 2769 2770 // keep previously known selected paragraphs 2771 SwAccessibleSelectedParas_Impl* pPrevSelectedParas( mpSelectedParas ); 2772 2773 // determine currently selected paragraphs 2774 mpSelectedParas = _BuildSelectedParas(); 2775 2776 // compare currently selected paragraphs with the previously selected 2777 // paragraphs and submit corresponding TEXT_SELECTION_CHANGED events. 2778 // first, search for new and changed selections. 2779 // on the run remove selections from previously known ones, if they are 2780 // also in the current ones. 2781 if ( mpSelectedParas ) 2782 { 2783 SwAccessibleSelectedParas_Impl::iterator aIter = mpSelectedParas->begin(); 2784 for ( ; aIter != mpSelectedParas->end(); ++aIter ) 2785 { 2786 bool bSubmitEvent( false ); 2787 if ( !pPrevSelectedParas ) 2788 { 2789 // new selection 2790 bSubmitEvent = true; 2791 } 2792 else 2793 { 2794 SwAccessibleSelectedParas_Impl::iterator aPrevSelected = 2795 pPrevSelectedParas->find( (*aIter).first ); 2796 if ( aPrevSelected != pPrevSelectedParas->end() ) 2797 { 2798 // check, if selection has changed 2799 if ( (*aIter).second.nStartOfSelection != 2800 (*aPrevSelected).second.nStartOfSelection || 2801 (*aIter).second.nEndOfSelection != 2802 (*aPrevSelected).second.nEndOfSelection ) 2803 { 2804 // changed selection 2805 bSubmitEvent = true; 2806 } 2807 pPrevSelectedParas->erase( aPrevSelected ); 2808 } 2809 else 2810 { 2811 // new selection 2812 bSubmitEvent = true; 2813 } 2814 } 2815 2816 if ( bSubmitEvent ) 2817 { 2818 uno::Reference < XAccessible > xAcc( (*aIter).first ); 2819 if ( xAcc.is() ) 2820 { 2821 ::vos::ORef < SwAccessibleContext > xAccImpl( 2822 static_cast<SwAccessibleContext*>( xAcc.get() ) ); 2823 if ( xAccImpl.isValid() && xAccImpl->GetFrm() ) 2824 { 2825 const SwTxtFrm* pTxtFrm( 2826 dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) ); 2827 ASSERT( pTxtFrm, 2828 "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" ); 2829 if ( pTxtFrm ) 2830 { 2831 InvalidateParaTextSelection( *pTxtFrm ); 2832 } 2833 } 2834 } 2835 } 2836 } 2837 } 2838 2839 // second, handle previous selections - after the first step the data 2840 // structure of the previously known only contains the 'old' selections 2841 if ( pPrevSelectedParas ) 2842 { 2843 SwAccessibleSelectedParas_Impl::iterator aIter = pPrevSelectedParas->begin(); 2844 for ( ; aIter != pPrevSelectedParas->end(); ++aIter ) 2845 { 2846 uno::Reference < XAccessible > xAcc( (*aIter).first ); 2847 if ( xAcc.is() ) 2848 { 2849 ::vos::ORef < SwAccessibleContext > xAccImpl( 2850 static_cast<SwAccessibleContext*>( xAcc.get() ) ); 2851 if ( xAccImpl.isValid() && xAccImpl->GetFrm() ) 2852 { 2853 const SwTxtFrm* pTxtFrm( 2854 dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) ); 2855 ASSERT( pTxtFrm, 2856 "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" ); 2857 if ( pTxtFrm ) 2858 { 2859 InvalidateParaTextSelection( *pTxtFrm ); 2860 } 2861 } 2862 } 2863 } 2864 2865 delete pPrevSelectedParas; 2866 } 2867 } 2868 2869 const SwRect& SwAccessibleMap::GetVisArea() const 2870 { 2871 DBG_ASSERT( !GetShell()->IsPreView() || (mpPreview != NULL), 2872 "preview without preview data?" ); 2873 2874 return GetShell()->IsPreView() 2875 ? mpPreview->GetVisArea() 2876 : GetShell()->VisArea(); 2877 } 2878 2879