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