Update ooo320-m1
[ooovba.git] / sw / source / core / access / accmap.cxx
blob4e3b9e7047bbf6d21b99fa4f1c2a5a92102fab5a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: accmap.cxx,v $
10 * $Revision: 1.59 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <vos/ref.hxx>
36 #include <cppuhelper/weakref.hxx>
37 #include <vcl/window.hxx>
38 #include <svx/svdmodel.hxx>
39 #include <svx/unomod.hxx>
40 #include <tools/debug.hxx>
42 #include <map>
43 #include <list>
44 #include <accmap.hxx>
45 #ifndef _ACCCONTEXT_HXX
46 #include <acccontext.hxx>
47 #endif
48 #include <accdoc.hxx>
49 #include <accpreview.hxx>
50 #include <accpage.hxx>
51 #include <accpara.hxx>
52 #include <accheaderfooter.hxx>
53 #include <accfootnote.hxx>
54 #include <acctextframe.hxx>
55 #include <accgraphic.hxx>
56 #include <accembedded.hxx>
57 #include <acccell.hxx>
58 #include <acctable.hxx>
59 #include "fesh.hxx"
60 #include <rootfrm.hxx>
61 #include <txtfrm.hxx>
62 #include <hffrm.hxx>
63 #include <ftnfrm.hxx>
64 #include <cellfrm.hxx>
65 #include <tabfrm.hxx>
66 #include <pagefrm.hxx>
67 #include <ndtyp.hxx>
68 #ifndef IDOCUMENTDRAWMODELACCESS_HXX_INCLUDED
69 #include <IDocumentDrawModelAccess.hxx>
70 #endif
71 #include <svx/ShapeTypeHandler.hxx>
72 #include <vcl/svapp.hxx>
73 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
74 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
75 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
76 #include <cppuhelper/implbase1.hxx>
77 // OD 15.01.2003 #103492#
78 #include <pagepreviewlayout.hxx>
79 // --> OD 2005-12-13 #i27301#
80 #include <pam.hxx>
81 #include <ndtxt.hxx>
82 // <--
84 using namespace ::com::sun::star;
85 using namespace ::com::sun::star::accessibility;
86 using ::rtl::OUString;
88 struct SwFrmFunc
90 sal_Bool operator()( const SwFrm * p1,
91 const SwFrm * p2) const
93 return p1 < p2;
97 typedef ::std::map < const SwFrm *, uno::WeakReference < XAccessible >, SwFrmFunc > _SwAccessibleContextMap_Impl;
99 class SwAccessibleContextMap_Impl: public _SwAccessibleContextMap_Impl
101 public:
103 #ifndef PRODUCT
104 sal_Bool mbLocked;
105 #endif
107 SwAccessibleContextMap_Impl()
108 #ifndef PRODUCT
109 : mbLocked( sal_False )
110 #endif
115 //------------------------------------------------------------------------------
116 class SwDrawModellListener_Impl : public SfxListener,
117 public ::cppu::WeakImplHelper1< document::XEventBroadcaster >
119 mutable ::osl::Mutex maListenerMutex;
120 ::cppu::OInterfaceContainerHelper maEventListeners;
121 SdrModel *mpDrawModel;
122 protected:
123 virtual ~SwDrawModellListener_Impl();
124 public:
126 SwDrawModellListener_Impl( SdrModel *pDrawModel );
129 virtual void SAL_CALL addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException);
130 virtual void SAL_CALL removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException);
132 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
133 void Dispose();
136 SwDrawModellListener_Impl::SwDrawModellListener_Impl( SdrModel *pDrawModel ) :
137 maEventListeners( maListenerMutex ),
138 mpDrawModel( pDrawModel )
140 StartListening( *mpDrawModel );
143 SwDrawModellListener_Impl::~SwDrawModellListener_Impl()
145 EndListening( *mpDrawModel );
148 void SAL_CALL SwDrawModellListener_Impl::addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException)
150 maEventListeners.addInterface( xListener );
153 void SAL_CALL SwDrawModellListener_Impl::removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException)
155 maEventListeners.removeInterface( xListener );
158 void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/,
159 const SfxHint& rHint )
161 // do not broadcast notifications for writer fly frames, because there
162 // are no shapes that need to know about them.
163 // OD 01.07.2003 #110554# - correct condition in order not to broadcast
164 // notifications for writer fly frames.
165 // OD 01.07.2003 #110554# - do not broadcast notifications for plane
166 // <SdrObject>objects
167 const SdrHint *pSdrHint = PTR_CAST( SdrHint, &rHint );
168 if ( !pSdrHint ||
169 ( pSdrHint->GetObject() &&
170 ( pSdrHint->GetObject()->ISA(SwFlyDrawObj) ||
171 pSdrHint->GetObject()->ISA(SwVirtFlyDrawObj) ||
172 IS_TYPE(SdrObject,pSdrHint->GetObject()) ) ) )
174 return;
177 ASSERT( mpDrawModel, "draw model listener is disposed" );
178 if( !mpDrawModel )
179 return;
181 document::EventObject aEvent;
182 if( !SvxUnoDrawMSFactory::createEvent( mpDrawModel, pSdrHint, aEvent ) )
183 return;
185 ::cppu::OInterfaceIteratorHelper aIter( maEventListeners );
186 while( aIter.hasMoreElements() )
188 uno::Reference < document::XEventListener > xListener( aIter.next(),
189 uno::UNO_QUERY );
192 xListener->notifyEvent( aEvent );
194 catch( uno::RuntimeException const & r )
196 (void)r;
197 #if OSL_DEBUG_LEVEL > 1
198 ByteString aError( "Runtime exception caught while notifying shape.:\n" );
199 aError += ByteString( String( r.Message), RTL_TEXTENCODING_ASCII_US );
200 DBG_ERROR( aError.GetBuffer() );
201 #endif
206 void SwDrawModellListener_Impl::Dispose()
208 mpDrawModel = 0;
211 //------------------------------------------------------------------------------
212 struct SwShapeFunc
214 sal_Bool operator()( const SdrObject * p1,
215 const SdrObject * p2) const
217 return p1 < p2;
220 typedef ::std::map < const SdrObject *, uno::WeakReference < XAccessible >, SwShapeFunc > _SwAccessibleShapeMap_Impl;
221 typedef ::std::pair < const SdrObject *, ::vos::ORef < ::accessibility::AccessibleShape > > SwAccessibleObjShape_Impl;
223 class SwAccessibleShapeMap_Impl: public _SwAccessibleShapeMap_Impl
226 ::accessibility::AccessibleShapeTreeInfo maInfo;
228 public:
230 #ifndef PRODUCT
231 sal_Bool mbLocked;
232 #endif
233 SwAccessibleShapeMap_Impl( SwAccessibleMap *pMap )
234 #ifndef PRODUCT
235 : mbLocked( sal_False )
236 #endif
238 maInfo.SetSdrView( pMap->GetShell()->GetDrawView() );
239 maInfo.SetWindow( pMap->GetShell()->GetWin() );
240 maInfo.SetViewForwarder( pMap );
241 // --> OD 2005-08-08 #i52858# - method name changed
242 uno::Reference < document::XEventBroadcaster > xModelBroadcaster =
243 new SwDrawModellListener_Impl(
244 pMap->GetShell()->getIDocumentDrawModelAccess()->GetOrCreateDrawModel() );
245 // <--
246 maInfo.SetControllerBroadcaster( xModelBroadcaster );
249 ~SwAccessibleShapeMap_Impl();
251 const ::accessibility::AccessibleShapeTreeInfo& GetInfo() const { return maInfo; }
253 SwAccessibleObjShape_Impl *Copy( size_t& rSize,
254 const SwFEShell *pFESh = 0,
255 SwAccessibleObjShape_Impl **pSelShape = 0 ) const;
258 SwAccessibleShapeMap_Impl::~SwAccessibleShapeMap_Impl()
260 uno::Reference < document::XEventBroadcaster > xBrd( maInfo.GetControllerBroadcaster() );
261 if( xBrd.is() )
262 static_cast < SwDrawModellListener_Impl * >( xBrd.get() )->Dispose();
265 SwAccessibleObjShape_Impl
266 *SwAccessibleShapeMap_Impl::Copy(
267 size_t& rSize, const SwFEShell *pFESh,
268 SwAccessibleObjShape_Impl **pSelStart ) const
270 SwAccessibleObjShape_Impl *pShapes = 0;
271 SwAccessibleObjShape_Impl *pSelShape = 0;
273 sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
274 rSize = size();
276 if( rSize > 0 )
278 pShapes =
279 new SwAccessibleObjShape_Impl[rSize];
281 const_iterator aIter = begin();
282 const_iterator aEndIter = end();
284 SwAccessibleObjShape_Impl *pShape = pShapes;
285 pSelShape = &(pShapes[rSize]);
286 while( aIter != aEndIter )
288 const SdrObject *pObj = (*aIter).first;
289 uno::Reference < XAccessible > xAcc( (*aIter).second );
290 if( nSelShapes && pFESh->IsObjSelected( *pObj ) )
292 // selected objects are inserted from the back
293 --pSelShape;
294 pSelShape->first = pObj;
295 pSelShape->second =
296 static_cast < ::accessibility::AccessibleShape* >(
297 xAcc.get() );
298 --nSelShapes;
300 else
302 pShape->first = pObj;
303 pShape->second =
304 static_cast < ::accessibility::AccessibleShape* >(
305 xAcc.get() );
306 ++pShape;
308 ++aIter;
310 ASSERT( pSelShape == pShape, "copying shapes went wrong!" );
313 if( pSelStart )
314 *pSelStart = pSelShape;
316 return pShapes;
319 //------------------------------------------------------------------------------
320 struct SwAccessibleEvent_Impl
322 public:
323 enum EventType { CARET_OR_STATES,
324 INVALID_CONTENT,
325 POS_CHANGED,
326 CHILD_POS_CHANGED,
327 SHAPE_SELECTION,
328 DISPOSE,
329 INVALID_ATTR };
331 private:
332 SwRect maOldBox; // the old bounds for CHILD_POS_CHANGED
333 // and POS_CHANGED
334 uno::WeakReference < XAccessible > mxAcc; // The object that fires the event
335 SwFrmOrObj maFrmOrObj; // the child for CHILD_POS_CHANGED and
336 // the same as xAcc for any other
337 // event type
338 EventType meType; // The event type
339 // --> OD 2005-12-12 #i27301# - use new type definition for <mnStates>
340 tAccessibleStates mnStates; // check states or update caret pos
341 // <--
343 SwAccessibleEvent_Impl& operator==( const SwAccessibleEvent_Impl& );
345 public:
346 SwAccessibleEvent_Impl( EventType eT,
347 SwAccessibleContext *pA,
348 const SwFrmOrObj& rFrmOrObj )
349 : mxAcc( pA ),
350 maFrmOrObj( rFrmOrObj ),
351 meType( eT ),
352 mnStates( 0 )
355 SwAccessibleEvent_Impl( EventType eT,
356 const SwFrmOrObj& rFrmOrObj )
357 : maFrmOrObj( rFrmOrObj ),
358 meType( eT ),
359 mnStates( 0 )
361 ASSERT( SwAccessibleEvent_Impl::DISPOSE == meType,
362 "wrong event constructor, DISPOSE only" );
365 SwAccessibleEvent_Impl( EventType eT )
366 : meType( eT ),
367 mnStates( 0 )
369 ASSERT( SwAccessibleEvent_Impl::SHAPE_SELECTION == meType,
370 "wrong event constructor, SHAPE_SELECTION only" );
373 SwAccessibleEvent_Impl( EventType eT,
374 SwAccessibleContext *pA,
375 const SwFrmOrObj& rFrmOrObj,
376 const SwRect& rR )
377 : maOldBox( rR ),
378 mxAcc( pA ),
379 maFrmOrObj( rFrmOrObj ),
380 meType( eT ),
381 mnStates( 0 )
383 ASSERT( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType ||
384 SwAccessibleEvent_Impl::POS_CHANGED == meType,
385 "wrong event constructor, (CHILD_)POS_CHANGED only" );
388 // --> OD 2005-12-12 #i27301# - use new type definition for parameter <_nStates>
389 SwAccessibleEvent_Impl( EventType eT,
390 SwAccessibleContext *pA,
391 const SwFrmOrObj& rFrmOrObj,
392 const tAccessibleStates _nStates )
393 : mxAcc( pA ),
394 maFrmOrObj( rFrmOrObj ),
395 meType( eT ),
396 mnStates( _nStates )
398 ASSERT( SwAccessibleEvent_Impl::CARET_OR_STATES == meType,
399 "wrong event constructor, CARET_OR_STATES only" );
402 // <SetType(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
403 inline void SetType( EventType eT )
405 meType = eT;
407 inline EventType GetType() const
409 return meType;
412 inline ::vos::ORef < SwAccessibleContext > GetContext() const
414 uno::Reference < XAccessible > xTmp( mxAcc );
415 ::vos::ORef < SwAccessibleContext > xAccImpl(
416 static_cast<SwAccessibleContext*>( xTmp.get() ) );
418 return xAccImpl;
421 inline const SwRect& GetOldBox() const
423 return maOldBox;
425 // <SetOldBox(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
426 inline void SetOldBox( const SwRect& rOldBox )
428 maOldBox = rOldBox;
431 inline const SwFrmOrObj& GetFrmOrObj() const
433 return maFrmOrObj;
436 // <SetStates(..)> only used in method <SwAccessibleMap::AppendEvent(..)>
437 // --> OD 2005-12-12 #i27301# - use new type definition for parameter <_nStates>
438 inline void SetStates( tAccessibleStates _nStates )
440 mnStates |= _nStates;
442 // <--
444 inline sal_Bool IsUpdateCursorPos() const
446 return (mnStates & ACC_STATE_CARET) != 0;
448 inline sal_Bool IsInvalidateStates() const
450 return (mnStates & ACC_STATE_MASK) != 0;
452 inline sal_Bool IsInvalidateRelation() const
454 return (mnStates & ACC_STATE_RELATION_MASK) != 0;
456 // --> OD 2005-12-12 #i27301# - new event TEXT_SELECTION_CHANGED
457 inline sal_Bool IsInvalidateTextSelection() const
459 return ( mnStates & ACC_STATE_TEXT_SELECTION_CHANGED ) != 0;
461 // <--
462 // --> OD 2009-01-07 #i88069# - new event TEXT_ATTRIBUTE_CHANGED
463 inline sal_Bool IsInvalidateTextAttrs() const
465 return ( mnStates & ACC_STATE_TEXT_ATTRIBUTE_CHANGED ) != 0;
467 // <--
468 // --> OD 2005-12-12 #i27301# - use new type definition <tAccessibleStates>
469 // for return value
470 inline tAccessibleStates GetStates() const
472 return mnStates & ACC_STATE_MASK;
474 // <--
475 // --> OD 2005-12-12 #i27301# - use new type definition <tAccessibleStates>
476 // for return value
477 inline tAccessibleStates GetAllStates() const
479 return mnStates;
481 // <--
484 //------------------------------------------------------------------------------
485 typedef ::std::list < SwAccessibleEvent_Impl > _SwAccessibleEventList_Impl;
487 class SwAccessibleEventList_Impl: public _SwAccessibleEventList_Impl
489 sal_Bool mbFiring;
491 public:
493 SwAccessibleEventList_Impl()
494 : mbFiring( sal_False )
497 inline void SetFiring()
499 mbFiring = sal_True;
501 inline sal_Bool IsFiring() const
503 return mbFiring;
507 //------------------------------------------------------------------------------
508 // The shape list is filled if an accessible shape is destroyed. It
509 // simply keeps a reference to the accessible shape's XShape. These
510 // references are destroyed within the EndAction when firing events,
511 // There are twp reason for this. First of all, a new accessible shape
512 // for the XShape might be created soon. It's then cheaper if the XShape
513 // still exists. The other reason are situations where an accessible shape
514 // is destroyed within an SwFrmFmt::Modify. In this case, destryoing
515 // the XShape at the same time (indirectly by destroying the accessible
516 // shape) leads to an assert, because a client of the Modify is destroyed
517 // within a Modify call.
519 typedef ::std::list < uno::Reference < drawing::XShape > > _SwShapeList_Impl;
521 class SwShapeList_Impl: public _SwShapeList_Impl
523 public:
525 SwShapeList_Impl() {}
529 //------------------------------------------------------------------------------
530 struct SwFrmOrObjFunc
532 sal_Bool operator()( const SwFrmOrObj& r1,
533 const SwFrmOrObj& r2 ) const
535 const void *p1 = r1.GetSwFrm()
536 ? static_cast < const void * >( r1.GetSwFrm())
537 : static_cast < const void * >( r1.GetSdrObject() );
538 const void *p2 = r2.GetSwFrm()
539 ? static_cast < const void * >( r2.GetSwFrm())
540 : static_cast < const void * >( r2.GetSdrObject() );
541 return p1 < p2;
544 typedef ::std::map < SwFrmOrObj, SwAccessibleEventList_Impl::iterator,
545 SwFrmOrObjFunc > _SwAccessibleEventMap_Impl;
547 class SwAccessibleEventMap_Impl: public _SwAccessibleEventMap_Impl
551 //------------------------------------------------------------------------------
552 // --> OD 2005-12-13 #i27301# - map containing the accessible paragraph, which
553 // have a selection. Needed to keep this information to submit corresponding
554 // TEXT_SELECTION_CHANGED events.
555 struct SwAccessibleParaSelection
557 xub_StrLen nStartOfSelection;
558 xub_StrLen nEndOfSelection;
560 SwAccessibleParaSelection( const xub_StrLen _nStartOfSelection,
561 const xub_StrLen _nEndOfSelection )
562 : nStartOfSelection( _nStartOfSelection ),
563 nEndOfSelection( _nEndOfSelection )
567 struct SwXAccWeakRefComp
569 sal_Bool operator()( const uno::WeakReference<XAccessible>& _rXAccWeakRef1,
570 const uno::WeakReference<XAccessible>& _rXAccWeakRef2 ) const
572 return _rXAccWeakRef1.get() < _rXAccWeakRef2.get();
576 typedef ::std::map< uno::WeakReference < XAccessible >,
577 SwAccessibleParaSelection,
578 SwXAccWeakRefComp > _SwAccessibleSelectedParas_Impl;
580 class SwAccessibleSelectedParas_Impl: public _SwAccessibleSelectedParas_Impl
582 // <--
583 //------------------------------------------------------------------------------
584 static sal_Bool AreInSameTable( const uno::Reference< XAccessible >& rAcc,
585 const SwFrm *pFrm )
587 sal_Bool bRet = sal_False;
589 if( pFrm && pFrm->IsCellFrm() && rAcc.is() )
591 // Is it in the same table? We check that
592 // by comparing the last table frame in the
593 // follow chain, because that's cheaper than
594 // searching the first one.
595 SwAccessibleContext *pAccImpl =
596 static_cast< SwAccessibleContext *>( rAcc.get() );
597 if( pAccImpl->GetFrm()->IsCellFrm() )
599 const SwTabFrm *pTabFrm1 = pAccImpl->GetFrm()->FindTabFrm();
600 while( pTabFrm1->GetFollow() )
601 pTabFrm1 = pTabFrm1->GetFollow();
603 const SwTabFrm *pTabFrm2 = pFrm->FindTabFrm();
604 while( pTabFrm2->GetFollow() )
605 pTabFrm2 = pTabFrm2->GetFollow();
607 bRet = (pTabFrm1 == pTabFrm2);
611 return bRet;
614 void SwAccessibleMap::FireEvent( const SwAccessibleEvent_Impl& rEvent )
616 ::vos::ORef < SwAccessibleContext > xAccImpl( rEvent.GetContext() );
617 if( SwAccessibleEvent_Impl::SHAPE_SELECTION == rEvent.GetType() )
619 DoInvalidateShapeSelection();
621 else if( xAccImpl.isValid() && xAccImpl->GetFrm() )
623 // --> OD 2009-01-07 #i88069#
624 if ( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE &&
625 rEvent.IsInvalidateTextAttrs() )
627 xAccImpl->InvalidateAttr();
629 // <--
630 switch( rEvent.GetType() )
632 case SwAccessibleEvent_Impl::INVALID_CONTENT:
633 xAccImpl->InvalidateContent();
634 break;
635 case SwAccessibleEvent_Impl::POS_CHANGED:
636 xAccImpl->InvalidatePosOrSize( rEvent.GetOldBox() );
637 break;
638 case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
639 xAccImpl->InvalidateChildPosOrSize( rEvent.GetFrmOrObj(),
640 rEvent.GetOldBox() );
641 break;
642 case SwAccessibleEvent_Impl::DISPOSE:
643 ASSERT( xAccImpl.isValid(),
644 "dispose event has been stored" );
645 break;
646 // --> OD 2009-01-06 #i88069#
647 case SwAccessibleEvent_Impl::INVALID_ATTR:
648 // nothing to do here - handled above
649 break;
650 // <--
651 default:
652 break;
654 if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
656 if( rEvent.IsUpdateCursorPos() )
657 xAccImpl->InvalidateCursorPos();
658 if( rEvent.IsInvalidateStates() )
659 xAccImpl->InvalidateStates( rEvent.GetStates() );
660 if( rEvent.IsInvalidateRelation() )
662 // --> OD 2005-12-01 #i27138#
663 // both events CONTENT_FLOWS_FROM_RELATION_CHANGED and
664 // CONTENT_FLOWS_TO_RELATION_CHANGED are possible
665 if ( rEvent.GetAllStates() & ACC_STATE_RELATION_FROM )
667 xAccImpl->InvalidateRelation(
668 AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED );
670 if ( rEvent.GetAllStates() & ACC_STATE_RELATION_TO )
672 xAccImpl->InvalidateRelation(
673 AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
675 // <--
677 // --> OD 2005-12-12 #i27301# - submit event TEXT_SELECTION_CHANGED
678 if ( rEvent.IsInvalidateTextSelection() )
680 xAccImpl->InvalidateTextSelection();
682 // <--
687 void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent )
689 vos::OGuard aGuard( maEventMutex );
691 if( !mpEvents )
692 mpEvents = new SwAccessibleEventList_Impl;
693 if( !mpEventMap )
694 mpEventMap = new SwAccessibleEventMap_Impl;
696 if( mpEvents->IsFiring() )
698 // While events are fired new ones are generated. They have to be fired
699 // now. This does not work for DISPOSE events!
700 ASSERT( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
701 "dispose event while firing events" );
702 FireEvent( rEvent );
704 else
707 SwAccessibleEventMap_Impl::iterator aIter =
708 mpEventMap->find( rEvent.GetFrmOrObj() );
709 if( aIter != mpEventMap->end() )
711 SwAccessibleEvent_Impl aEvent( *(*aIter).second );
712 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
713 "dispose events should not be stored" );
714 sal_Bool bAppendEvent = sal_True;
715 switch( rEvent.GetType() )
717 case SwAccessibleEvent_Impl::CARET_OR_STATES:
718 // A CARET_OR_STATES event is added to any other
719 // event only. It is broadcasted after any other event, so the
720 // event should be put to the back.
721 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
722 "invalid event combination" );
723 aEvent.SetStates( rEvent.GetAllStates() );
724 break;
725 case SwAccessibleEvent_Impl::INVALID_CONTENT:
726 // An INVALID_CONTENT event overwrites a CARET_OR_STATES
727 // event (but keeps its flags) and it is contained in a
728 // POS_CHANGED event.
729 // Therefor, the event's type has to be adapted and the event
730 // has to be put at the end.
731 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
732 "invalid event combination" );
733 if( aEvent.GetType() == SwAccessibleEvent_Impl::CARET_OR_STATES )
734 aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT );
735 break;
736 case SwAccessibleEvent_Impl::POS_CHANGED:
737 // A pos changed event overwrites CARET_STATES (keeping its
738 // flags) as well as INVALID_CONTENT. The old box position
739 // has to be stored however if the old event is not a
740 // POS_CHANGED itself.
741 ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
742 "invalid event combination" );
743 if( aEvent.GetType() != SwAccessibleEvent_Impl::POS_CHANGED )
744 aEvent.SetOldBox( rEvent.GetOldBox() );
745 aEvent.SetType( SwAccessibleEvent_Impl::POS_CHANGED );
746 break;
747 case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
748 // CHILD_POS_CHANGED events can only follow CHILD_POS_CHANGED
749 // events. The only action that needs to be done again is
750 // to put the old event to the back. The new one cannot be used,
751 // because we are interested in the old frame bounds.
752 ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
753 "invalid event combination" );
754 break;
755 case SwAccessibleEvent_Impl::SHAPE_SELECTION:
756 ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::SHAPE_SELECTION,
757 "invalid event combination" );
758 break;
759 case SwAccessibleEvent_Impl::DISPOSE:
760 // DISPOSE events overwrite all others. They are not stored
761 // but executed immediatly to avoid broadcasting of
762 // defunctional objects. So what needs to be done here is to
763 // remove all events for the frame in question.
764 bAppendEvent = sal_False;
765 break;
766 // --> OD 2009-01-06 #i88069#
767 case SwAccessibleEvent_Impl::INVALID_ATTR:
768 ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR,
769 "invalid event combination" );
770 break;
771 // <--
773 if( bAppendEvent )
775 mpEvents->erase( (*aIter).second );
776 (*aIter).second = mpEvents->insert( mpEvents->end(), aEvent );
778 else
780 mpEvents->erase( (*aIter).second );
781 mpEventMap->erase( aIter );
784 else if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
786 SwAccessibleEventMap_Impl::value_type aEntry( rEvent.GetFrmOrObj(),
787 mpEvents->insert( mpEvents->end(), rEvent ) );
788 mpEventMap->insert( aEntry );
793 void SwAccessibleMap::InvalidateCursorPosition(
794 const uno::Reference< XAccessible >& rAcc )
796 SwAccessibleContext *pAccImpl =
797 static_cast< SwAccessibleContext *>( rAcc.get() );
798 ASSERT( pAccImpl, "no caret context" );
799 ASSERT( pAccImpl->GetFrm(), "caret context is disposed" );
800 if( GetShell()->ActionPend() )
802 SwAccessibleEvent_Impl aEvent(
803 SwAccessibleEvent_Impl::CARET_OR_STATES, pAccImpl,
804 pAccImpl->GetFrm(), ACC_STATE_CARET );
805 AppendEvent( aEvent );
807 else
809 FireEvents();
810 // While firing events the current frame might have
811 // been disposed because it moved out of the vis area.
812 // Setting the cursor for such frames is useless and even
813 // causes asserts.
814 if( pAccImpl->GetFrm() )
815 pAccImpl->InvalidateCursorPos();
819 void SwAccessibleMap::InvalidateShapeSelection()
821 if( GetShell()->ActionPend() )
823 SwAccessibleEvent_Impl aEvent(
824 SwAccessibleEvent_Impl::SHAPE_SELECTION );
825 AppendEvent( aEvent );
827 else
829 FireEvents();
830 DoInvalidateShapeSelection();
834 void SwAccessibleMap::DoInvalidateShapeSelection()
836 SwAccessibleObjShape_Impl *pShapes = 0;
837 SwAccessibleObjShape_Impl *pSelShape = 0;
838 size_t nShapes = 0;
840 const ViewShell *pVSh = GetShell();
841 const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
842 static_cast< const SwFEShell * >( pVSh ) : 0;
843 sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
846 vos::OGuard aGuard( maMutex );
847 if( mpShapeMap )
848 pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
851 if( pShapes )
853 ::std::list< const SwFrm * > aParents;
854 Window *pWin = GetShell()->GetWin();
855 sal_Bool bFocused = pWin && pWin->HasFocus();
856 SwAccessibleObjShape_Impl *pShape = pShapes;
857 while( nShapes )
859 if( pShape->second.isValid() )
861 sal_Bool bChanged;
862 if( pShape >= pSelShape )
864 bChanged =
865 pShape->second->SetState( AccessibleStateType::SELECTED );
866 if( bFocused && 1 == nSelShapes )
867 pShape->second->SetState( AccessibleStateType::FOCUSED );
868 else
869 pShape->second->ResetState( AccessibleStateType::FOCUSED );
871 else
873 bChanged =
874 pShape->second->ResetState( AccessibleStateType::SELECTED );
875 pShape->second->ResetState( AccessibleStateType::FOCUSED );
877 if( bChanged )
879 SwFrmOrObj aFrmOrObj( pShape->first );
880 SwFrmOrObj aParent =
881 SwAccessibleFrame::GetParent( aFrmOrObj,
882 GetShell()->IsPreView() );
883 aParents.push_back( aParent.GetSwFrm() );
887 --nShapes;
888 ++pShape;
890 if( aParents.size() > 0 )
892 ::std::list< const SwFrm * >::const_iterator aIter = aParents.begin();
893 ::std::list< const SwFrm * >::const_iterator aEndIter = aParents.end();
894 while( aIter != aEndIter )
896 ::vos::ORef< SwAccessibleContext > xParentAccImpl;
898 vos::OGuard aGuard( maMutex );
899 if( mpFrmMap )
901 SwAccessibleContextMap_Impl::const_iterator aMapIter =
902 mpFrmMap->find( *aIter );
903 if( aMapIter != mpFrmMap->end() )
905 uno::Reference < XAccessible > xAcc( (*aMapIter).second );
906 xParentAccImpl =
907 static_cast< SwAccessibleContext *>( xAcc.get() );
911 if( xParentAccImpl.isValid() )
913 AccessibleEventObject aEvent;
914 aEvent.EventId = AccessibleEventId::SELECTION_CHANGED;
915 xParentAccImpl->FireAccessibleEvent( aEvent );
918 ++aIter;
922 delete[] pShapes;
926 void SwAccessibleMap::DoInvalidateShapeFocus()
928 const ViewShell *pVSh = GetShell();
929 const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ?
930 static_cast< const SwFEShell * >( pVSh ) : 0;
931 sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0;
933 if( nSelShapes != 1 )
934 return;
936 SwAccessibleObjShape_Impl *pShapes = 0;
937 SwAccessibleObjShape_Impl *pSelShape = 0;
938 size_t nShapes = 0;
942 vos::OGuard aGuard( maMutex );
943 if( mpShapeMap )
944 pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape );
947 if( pShapes )
949 Window *pWin = GetShell()->GetWin();
950 sal_Bool bFocused = pWin && pWin->HasFocus();
951 SwAccessibleObjShape_Impl *pShape = pShapes;
952 while( nShapes )
954 if( pShape->second.isValid() )
956 if( bFocused && pShape >= pSelShape )
957 pShape->second->SetState( AccessibleStateType::FOCUSED );
958 else
959 pShape->second->ResetState( AccessibleStateType::FOCUSED );
962 --nShapes;
963 ++pShape;
966 delete[] pShapes;
971 SwAccessibleMap::SwAccessibleMap( ViewShell *pSh ) :
972 mpFrmMap( 0 ),
973 mpShapeMap( 0 ),
974 mpShapes( 0 ),
975 mpEvents( 0 ),
976 mpEventMap( 0 ),
977 // --> OD 2005-12-13 #i27301#
978 mpSelectedParas( 0 ),
979 // <--
980 mpVSh( pSh ),
981 mpPreview( 0 ),
982 mnPara( 1 ),
983 mnFootnote( 1 ),
984 mnEndnote( 1 ),
985 mbShapeSelected( sal_False )
987 pSh->GetLayout()->AddAccessibleShell();
990 SwAccessibleMap::~SwAccessibleMap()
992 uno::Reference < XAccessible > xAcc;
994 vos::OGuard aGuard( maMutex );
995 if( mpFrmMap )
997 const SwRootFrm *pRootFrm = GetShell()->GetLayout();
998 SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
999 if( aIter != mpFrmMap->end() )
1000 xAcc = (*aIter).second;
1001 if( !xAcc.is() )
1002 xAcc = new SwAccessibleDocument( this );
1006 SwAccessibleDocument *pAcc =
1007 static_cast< SwAccessibleDocument * >( xAcc.get() );
1008 pAcc->Dispose( sal_True );
1011 vos::OGuard aGuard( maMutex );
1012 #ifndef PRODUCT
1013 ASSERT( !mpFrmMap || mpFrmMap->empty(),
1014 "Frame map should be empty after disposing the root frame" );
1015 if( mpFrmMap )
1017 SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin();
1018 while( aIter != mpFrmMap->end() )
1020 uno::Reference < XAccessible > xTmp = (*aIter).second;
1021 if( xTmp.is() )
1023 SwAccessibleContext *pTmp =
1024 static_cast< SwAccessibleContext * >( xTmp.get() );
1025 (void) pTmp;
1027 ++aIter;
1030 ASSERT( !mpShapeMap || mpShapeMap->empty(),
1031 "Object map should be empty after disposing the root frame" );
1032 if( mpShapeMap )
1034 SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->begin();
1035 while( aIter != mpShapeMap->end() )
1037 uno::Reference < XAccessible > xTmp = (*aIter).second;
1038 if( xTmp.is() )
1040 ::accessibility::AccessibleShape *pTmp =
1041 static_cast< ::accessibility::AccessibleShape* >( xTmp.get() );
1042 (void) pTmp;
1044 ++aIter;
1047 #endif
1048 delete mpFrmMap;
1049 mpFrmMap = 0;
1050 delete mpShapeMap;
1051 mpShapeMap = 0;
1052 delete mpShapes;
1053 mpShapes = 0;
1054 // --> OD 2005-12-13 #i27301#
1055 delete mpSelectedParas;
1056 mpSelectedParas = 0;
1057 // <--
1060 delete mpPreview;
1061 mpPreview = NULL;
1064 vos::OGuard aGuard( maEventMutex );
1065 #ifndef PRODUCT
1066 ASSERT( !(mpEvents || mpEventMap), "pending events" );
1067 if( mpEvents )
1069 SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
1070 while( aIter != mpEvents->end() )
1072 ++aIter;
1075 if( mpEventMap )
1077 SwAccessibleEventMap_Impl::iterator aIter = mpEventMap->begin();
1078 while( aIter != mpEventMap->end() )
1080 ++aIter;
1083 #endif
1084 delete mpEventMap;
1085 mpEventMap = 0;
1086 delete mpEvents;
1087 mpEvents = 0;
1089 mpVSh->GetLayout()->RemoveAccessibleShell();
1092 uno::Reference< XAccessible > SwAccessibleMap::_GetDocumentView(
1093 sal_Bool bPagePreview )
1095 uno::Reference < XAccessible > xAcc;
1096 sal_Bool bSetVisArea = sal_False;
1099 vos::OGuard aGuard( maMutex );
1101 if( !mpFrmMap )
1103 mpFrmMap = new SwAccessibleContextMap_Impl;
1104 #ifndef PRODUCT
1105 mpFrmMap->mbLocked = sal_False;
1106 #endif
1109 #ifndef PRODUCT
1110 ASSERT( !mpFrmMap->mbLocked, "Map is locked" );
1111 mpFrmMap->mbLocked = sal_True;
1112 #endif
1114 const SwRootFrm *pRootFrm = GetShell()->GetLayout();
1115 SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm );
1116 if( aIter != mpFrmMap->end() )
1117 xAcc = (*aIter).second;
1118 if( xAcc.is() )
1120 bSetVisArea = sal_True; // Set VisArea when map mutex is not
1121 // locked
1123 else
1125 if( bPagePreview )
1126 xAcc = new SwAccessiblePreview( this );
1127 else
1128 xAcc = new SwAccessibleDocument( this );
1130 if( aIter != mpFrmMap->end() )
1132 (*aIter).second = xAcc;
1134 else
1136 SwAccessibleContextMap_Impl::value_type aEntry( pRootFrm, xAcc );
1137 mpFrmMap->insert( aEntry );
1141 #ifndef PRODUCT
1142 mpFrmMap->mbLocked = sal_False;
1143 #endif
1146 if( bSetVisArea )
1148 SwAccessibleDocumentBase *pAcc =
1149 static_cast< SwAccessibleDocumentBase * >( xAcc.get() );
1150 pAcc->SetVisArea();
1153 return xAcc;
1156 uno::Reference< XAccessible > SwAccessibleMap::GetDocumentView( )
1158 return _GetDocumentView( sal_False );
1161 // OD 14.01.2003 #103492# - complete re-factoring of method due to new page/print
1162 // preview functionality.
1163 uno::Reference<XAccessible> SwAccessibleMap::GetDocumentPreview(
1164 const std::vector<PrevwPage*>& _rPrevwPages,
1165 const Fraction& _rScale,
1166 const SwPageFrm* _pSelectedPageFrm,
1167 const Size& _rPrevwWinSize )
1169 // create & update preview data object
1170 if( mpPreview == NULL )
1171 mpPreview = new SwAccPreviewData();
1172 mpPreview->Update( _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize );
1174 uno::Reference<XAccessible> xAcc = _GetDocumentView( sal_True );
1175 return xAcc;
1178 uno::Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrm *pFrm,
1179 sal_Bool bCreate )
1181 uno::Reference < XAccessible > xAcc;
1182 uno::Reference < XAccessible > xOldCursorAcc;
1183 sal_Bool bOldShapeSelected = sal_False;
1186 vos::OGuard aGuard( maMutex );
1188 if( !mpFrmMap && bCreate )
1189 mpFrmMap = new SwAccessibleContextMap_Impl;
1190 if( mpFrmMap )
1192 SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pFrm );
1193 if( aIter != mpFrmMap->end() )
1194 xAcc = (*aIter).second;
1196 if( !xAcc.is() && bCreate )
1198 SwAccessibleContext *pAcc = 0;
1199 switch( pFrm->GetType() )
1201 case FRM_TXT:
1202 mnPara++;
1203 pAcc = new SwAccessibleParagraph( this,
1204 static_cast< const SwTxtFrm * >( pFrm ) );
1205 break;
1206 case FRM_HEADER:
1207 pAcc = new SwAccessibleHeaderFooter( this,
1208 static_cast< const SwHeaderFrm *>( pFrm ) );
1209 break;
1210 case FRM_FOOTER:
1211 pAcc = new SwAccessibleHeaderFooter( this,
1212 static_cast< const SwFooterFrm *>( pFrm ) );
1213 break;
1214 case FRM_FTN:
1216 const SwFtnFrm *pFtnFrm =
1217 static_cast < const SwFtnFrm * >( pFrm );
1218 sal_Bool bIsEndnote =
1219 SwAccessibleFootnote::IsEndnote( pFtnFrm );
1220 pAcc = new SwAccessibleFootnote( this, bIsEndnote,
1221 (bIsEndnote ? mnEndnote++ : mnFootnote++),
1222 pFtnFrm );
1224 break;
1225 case FRM_FLY:
1227 const SwFlyFrm *pFlyFrm =
1228 static_cast < const SwFlyFrm * >( pFrm );
1229 switch( SwAccessibleFrameBase::GetNodeType( pFlyFrm ) )
1231 case ND_GRFNODE:
1232 pAcc = new SwAccessibleGraphic( this, pFlyFrm );
1233 break;
1234 case ND_OLENODE:
1235 pAcc = new SwAccessibleEmbeddedObject( this, pFlyFrm );
1236 break;
1237 default:
1238 pAcc = new SwAccessibleTextFrame( this, pFlyFrm );
1239 break;
1242 break;
1243 case FRM_CELL:
1244 pAcc = new SwAccessibleCell( this,
1245 static_cast< const SwCellFrm *>( pFrm ) );
1246 break;
1247 case FRM_TAB:
1248 pAcc = new SwAccessibleTable( this,
1249 static_cast< const SwTabFrm *>( pFrm ) );
1250 break;
1251 case FRM_PAGE:
1252 DBG_ASSERT( GetShell()->IsPreView(),
1253 "accessible page frames only in PagePreview" );
1254 pAcc = new SwAccessiblePage( this, pFrm );
1255 break;
1257 xAcc = pAcc;
1259 ASSERT( xAcc.is(), "unknown frame type" );
1260 if( xAcc.is() )
1262 if( aIter != mpFrmMap->end() )
1264 (*aIter).second = xAcc;
1266 else
1268 SwAccessibleContextMap_Impl::value_type aEntry( pFrm, xAcc );
1269 mpFrmMap->insert( aEntry );
1272 if( pAcc->HasCursor() &&
1273 !AreInSameTable( mxCursorContext, pFrm ) )
1275 // If the new context has the focus, and if we know
1276 // another context that had the focus, then the focus
1277 // just moves from the old context to the new one. We
1278 // have to send a focus event and a caret event for
1279 // the old context then. We have to to that know,
1280 // because after we have left this method, anyone might
1281 // call getStates for the new context and will get a
1282 // focused state then. Sending the focus changes event
1283 // after that seems to be strange. However, we cannot
1284 // send a focus event fo the new context now, because
1285 // noone except us knows it. In any case, we remeber
1286 // the new context as the one that has the focus
1287 // currently.
1289 xOldCursorAcc = mxCursorContext;
1290 mxCursorContext = xAcc;
1292 bOldShapeSelected = mbShapeSelected;
1293 mbShapeSelected = sal_False;
1300 // Invalidate focus for old object when map is not locked
1301 if( xOldCursorAcc.is() )
1302 InvalidateCursorPosition( xOldCursorAcc );
1303 if( bOldShapeSelected )
1304 InvalidateShapeSelection();
1306 return xAcc;
1309 ::vos::ORef < SwAccessibleContext > SwAccessibleMap::GetContextImpl(
1310 const SwFrm *pFrm,
1311 sal_Bool bCreate )
1313 uno::Reference < XAccessible > xAcc( GetContext( pFrm, bCreate ) );
1315 ::vos::ORef < SwAccessibleContext > xAccImpl(
1316 static_cast< SwAccessibleContext * >( xAcc.get() ) );
1318 return xAccImpl;
1321 uno::Reference< XAccessible> SwAccessibleMap::GetContext(
1322 const SdrObject *pObj,
1323 SwAccessibleContext *pParentImpl,
1324 sal_Bool bCreate )
1326 uno::Reference < XAccessible > xAcc;
1327 uno::Reference < XAccessible > xOldCursorAcc;
1330 vos::OGuard aGuard( maMutex );
1332 if( !mpShapeMap && bCreate )
1333 mpShapeMap = new SwAccessibleShapeMap_Impl( this );
1334 if( mpShapeMap )
1336 SwAccessibleShapeMap_Impl::iterator aIter =
1337 mpShapeMap->find( pObj );
1338 if( aIter != mpShapeMap->end() )
1339 xAcc = (*aIter).second;
1341 if( !xAcc.is() && bCreate )
1343 ::accessibility::AccessibleShape *pAcc = 0;
1344 uno::Reference < drawing::XShape > xShape(
1345 const_cast< SdrObject * >( pObj )->getUnoShape(),
1346 uno::UNO_QUERY );
1347 if( xShape.is() )
1349 ::accessibility::ShapeTypeHandler& rShapeTypeHandler =
1350 ::accessibility::ShapeTypeHandler::Instance();
1351 uno::Reference < XAccessible > xParent( pParentImpl );
1352 ::accessibility::AccessibleShapeInfo aShapeInfo(
1353 xShape, xParent, this );
1355 pAcc = rShapeTypeHandler.CreateAccessibleObject(
1356 aShapeInfo, mpShapeMap->GetInfo() );
1358 xAcc = pAcc;
1360 ASSERT( xAcc.is(), "unknown shape type" );
1361 if( xAcc.is() )
1363 pAcc->Init();
1364 if( aIter != mpShapeMap->end() )
1366 (*aIter).second = xAcc;
1368 else
1370 SwAccessibleShapeMap_Impl::value_type aEntry( pObj,
1371 xAcc );
1372 mpShapeMap->insert( aEntry );
1374 // TODO: focus!!!
1380 // Invalidate focus for old object when map is not locked
1381 if( xOldCursorAcc.is() )
1382 InvalidateCursorPosition( xOldCursorAcc );
1384 return xAcc;
1387 ::vos::ORef < ::accessibility::AccessibleShape > SwAccessibleMap::GetContextImpl(
1388 const SdrObject *pObj,
1389 SwAccessibleContext *pParentImpl,
1390 sal_Bool bCreate )
1392 uno::Reference < XAccessible > xAcc( GetContext( pObj, pParentImpl, bCreate ) );
1394 ::vos::ORef < ::accessibility::AccessibleShape > xAccImpl(
1395 static_cast< ::accessibility::AccessibleShape* >( xAcc.get() ) );
1397 return xAccImpl;
1401 void SwAccessibleMap::RemoveContext( const SwFrm *pFrm )
1403 vos::OGuard aGuard( maMutex );
1405 if( mpFrmMap )
1407 SwAccessibleContextMap_Impl::iterator aIter =
1408 mpFrmMap->find( pFrm );
1409 if( aIter != mpFrmMap->end() )
1411 mpFrmMap->erase( aIter );
1413 // Remove reference to old caret object. Though mxCursorContext
1414 // is a weak reference and cleared automatically, clearing it
1415 // directly makes sure to not keep a defunctional object.
1416 uno::Reference < XAccessible > xOldAcc( mxCursorContext );
1417 if( xOldAcc.is() )
1419 SwAccessibleContext *pOldAccImpl =
1420 static_cast< SwAccessibleContext *>( xOldAcc.get() );
1421 ASSERT( pOldAccImpl->GetFrm(), "old caret context is disposed" );
1422 if( pOldAccImpl->GetFrm() == pFrm )
1424 xOldAcc.clear(); // get an empty ref
1425 mxCursorContext = xOldAcc;
1429 if( mpFrmMap->empty() )
1431 delete mpFrmMap;
1432 mpFrmMap = 0;
1438 void SwAccessibleMap::RemoveContext( const SdrObject *pObj )
1440 vos::OGuard aGuard( maMutex );
1442 if( mpShapeMap )
1444 SwAccessibleShapeMap_Impl::iterator aIter =
1445 mpShapeMap->find( pObj );
1446 if( aIter != mpShapeMap->end() )
1448 mpShapeMap->erase( aIter );
1450 // The shape selection flag is not cleared, but one might do
1451 // so but has to make sure that the removed context is the one
1452 // that is selected.
1454 if( mpShapeMap->empty() )
1456 delete mpShapeMap;
1457 mpShapeMap = 0;
1464 void SwAccessibleMap::Dispose( const SwFrm *pFrm, const SdrObject *pObj,
1465 sal_Bool bRecursive )
1467 SwFrmOrObj aFrmOrObj( pFrm, pObj );
1469 // Indeed, the following assert checks the frame's accessible flag,
1470 // because that's the one that is evaluated in the layout. The frame
1471 // might not be accessible anyway. That's the case for cell frames that
1472 // contain further cells.
1473 ASSERT( !aFrmOrObj.GetSwFrm() || aFrmOrObj.GetSwFrm()->IsAccessibleFrm(),
1474 "non accessible frame should be disposed" );
1476 ::vos::ORef< SwAccessibleContext > xAccImpl;
1477 ::vos::ORef< SwAccessibleContext > xParentAccImpl;
1478 ::vos::ORef< ::accessibility::AccessibleShape > xShapeAccImpl;
1479 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1481 // get accessible context for frame
1483 vos::OGuard aGuard( maMutex );
1485 // First of all look for an accessible context for a frame
1486 if( aFrmOrObj.GetSwFrm() && mpFrmMap )
1488 SwAccessibleContextMap_Impl::iterator aIter =
1489 mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1490 if( aIter != mpFrmMap->end() )
1492 uno::Reference < XAccessible > xAcc( (*aIter).second );
1493 xAccImpl =
1494 static_cast< SwAccessibleContext *>( xAcc.get() );
1497 if( !xAccImpl.isValid() && mpFrmMap )
1499 // If there is none, look if the parent is accessible.
1500 const SwFrm *pParent =
1501 SwAccessibleFrame::GetParent( aFrmOrObj,
1502 GetShell()->IsPreView());
1504 if( pParent )
1506 SwAccessibleContextMap_Impl::iterator aIter =
1507 mpFrmMap->find( pParent );
1508 if( aIter != mpFrmMap->end() )
1510 uno::Reference < XAccessible > xAcc( (*aIter).second );
1511 xParentAccImpl =
1512 static_cast< SwAccessibleContext *>( xAcc.get() );
1516 if( !xParentAccImpl.isValid() && !aFrmOrObj.GetSwFrm() &&
1517 mpShapeMap )
1519 SwAccessibleShapeMap_Impl::iterator aIter =
1520 mpShapeMap->find( aFrmOrObj.GetSdrObject() );
1521 if( aIter != mpShapeMap->end() )
1523 uno::Reference < XAccessible > xAcc( (*aIter).second );
1524 xShapeAccImpl =
1525 static_cast< ::accessibility::AccessibleShape *>( xAcc.get() );
1528 if( pObj && GetShell()->ActionPend() &&
1529 (xParentAccImpl.isValid() || xShapeAccImpl.isValid()) )
1531 // Keep a reference to the XShape to avoid that it
1532 // is deleted with a SwFrmFmt::Modify.
1533 uno::Reference < drawing::XShape > xShape(
1534 const_cast< SdrObject * >( pObj )->getUnoShape(),
1535 uno::UNO_QUERY );
1536 if( xShape.is() )
1538 if( !mpShapes )
1539 mpShapes = new SwShapeList_Impl;
1540 mpShapes->push_back( xShape );
1545 // remove events stored for the frame
1547 vos::OGuard aGuard( maEventMutex );
1548 if( mpEvents )
1550 SwAccessibleEventMap_Impl::iterator aIter =
1551 mpEventMap->find( aFrmOrObj );
1552 if( aIter != mpEventMap->end() )
1554 SwAccessibleEvent_Impl aEvent(
1555 SwAccessibleEvent_Impl::DISPOSE, aFrmOrObj );
1556 AppendEvent( aEvent );
1561 // If the frame is accessible and there is a context for it, dispose
1562 // the frame. If the frame is no context for it but disposing should
1563 // take place recursive, the frame's children have to be disposed
1564 // anyway, so we have to create the context then.
1565 if( xAccImpl.isValid() )
1567 xAccImpl->Dispose( bRecursive );
1569 else if( xParentAccImpl.isValid() )
1571 // If the frame is a cell frame, the table must be notified.
1572 // If we are in an action, a table model change event will
1573 // be broadcasted at the end of the action to give the table
1574 // a chance to generate a single table change event.
1576 xParentAccImpl->DisposeChild( aFrmOrObj, bRecursive );
1578 else if( xShapeAccImpl.isValid() )
1580 RemoveContext( aFrmOrObj.GetSdrObject() );
1581 xShapeAccImpl->dispose();
1584 if( mpPreview && pFrm && pFrm->IsPageFrm() )
1585 mpPreview->DisposePage( static_cast< const SwPageFrm *>( pFrm ) );
1589 void SwAccessibleMap::InvalidatePosOrSize( const SwFrm *pFrm,
1590 const SdrObject *pObj,
1591 const SwRect& rOldBox )
1593 SwFrmOrObj aFrmOrObj( pFrm, pObj );
1594 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1596 ::vos::ORef< SwAccessibleContext > xAccImpl;
1597 ::vos::ORef< SwAccessibleContext > xParentAccImpl;
1599 vos::OGuard aGuard( maMutex );
1601 if( mpFrmMap )
1603 if( aFrmOrObj.GetSwFrm() )
1605 SwAccessibleContextMap_Impl::iterator aIter =
1606 mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1607 if( aIter != mpFrmMap->end() )
1609 // If there is an accesible object already it is
1610 // notified directly.
1611 uno::Reference < XAccessible > xAcc( (*aIter).second );
1612 xAccImpl =
1613 static_cast< SwAccessibleContext *>( xAcc.get() );
1616 if( !xAccImpl.isValid() )
1618 // Otherwise we look if the parent is accessible.
1619 // If not, there is nothing to do.
1620 const SwFrm *pParent =
1621 SwAccessibleFrame::GetParent( aFrmOrObj,
1622 GetShell()->IsPreView());
1624 if( pParent )
1626 SwAccessibleContextMap_Impl::iterator aIter =
1627 mpFrmMap->find( pParent );
1628 if( aIter != mpFrmMap->end() )
1630 uno::Reference < XAccessible > xAcc( (*aIter).second );
1631 xParentAccImpl =
1632 static_cast< SwAccessibleContext *>( xAcc.get() );
1639 if( xAccImpl.isValid() )
1641 if( GetShell()->ActionPend() )
1643 SwAccessibleEvent_Impl aEvent(
1644 SwAccessibleEvent_Impl::POS_CHANGED, xAccImpl.getBodyPtr(),
1645 aFrmOrObj, rOldBox );
1646 AppendEvent( aEvent );
1648 else
1650 FireEvents();
1651 xAccImpl->InvalidatePosOrSize( rOldBox );
1654 else if( xParentAccImpl.isValid() )
1656 if( GetShell()->ActionPend() )
1658 SwAccessibleEvent_Impl aEvent(
1659 SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
1660 xParentAccImpl.getBodyPtr(), aFrmOrObj, rOldBox );
1661 AppendEvent( aEvent );
1663 else
1665 FireEvents();
1666 xParentAccImpl->InvalidateChildPosOrSize( aFrmOrObj,
1667 rOldBox );
1673 void SwAccessibleMap::InvalidateContent( const SwFrm *pFrm )
1675 SwFrmOrObj aFrmOrObj( pFrm );
1676 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1678 uno::Reference < XAccessible > xAcc;
1680 vos::OGuard aGuard( maMutex );
1682 if( mpFrmMap )
1684 SwAccessibleContextMap_Impl::iterator aIter =
1685 mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1686 if( aIter != mpFrmMap->end() )
1687 xAcc = (*aIter).second;
1691 if( xAcc.is() )
1693 SwAccessibleContext *pAccImpl =
1694 static_cast< SwAccessibleContext *>( xAcc.get() );
1695 if( GetShell()->ActionPend() )
1697 SwAccessibleEvent_Impl aEvent(
1698 SwAccessibleEvent_Impl::INVALID_CONTENT, pAccImpl,
1699 aFrmOrObj );
1700 AppendEvent( aEvent );
1702 else
1704 FireEvents();
1705 pAccImpl->InvalidateContent();
1711 // --> OD 2009-01-06 #i88069#
1712 void SwAccessibleMap::InvalidateAttr( const SwTxtFrm& rTxtFrm )
1714 SwFrmOrObj aFrmOrObj( &rTxtFrm );
1715 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1717 uno::Reference < XAccessible > xAcc;
1719 vos::OGuard aGuard( maMutex );
1721 if( mpFrmMap )
1723 SwAccessibleContextMap_Impl::iterator aIter =
1724 mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1725 if( aIter != mpFrmMap->end() )
1726 xAcc = (*aIter).second;
1730 if( xAcc.is() )
1732 SwAccessibleContext *pAccImpl =
1733 static_cast< SwAccessibleContext *>( xAcc.get() );
1734 if( GetShell()->ActionPend() )
1736 SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::INVALID_ATTR,
1737 pAccImpl, aFrmOrObj );
1738 aEvent.SetStates( ACC_STATE_TEXT_ATTRIBUTE_CHANGED );
1739 AppendEvent( aEvent );
1741 else
1743 FireEvents();
1744 pAccImpl->InvalidateAttr();
1749 // <--
1751 void SwAccessibleMap::InvalidateCursorPosition( const SwFrm *pFrm )
1753 SwFrmOrObj aFrmOrObj( pFrm );
1754 sal_Bool bShapeSelected = sal_False;
1755 const ViewShell *pVSh = GetShell();
1756 if( pVSh->ISA( SwCrsrShell ) )
1758 const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh );
1759 if( pCSh->IsTableMode() )
1761 while( aFrmOrObj.GetSwFrm() && !aFrmOrObj.GetSwFrm()->IsCellFrm() )
1762 aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
1764 else if( pVSh->ISA( SwFEShell ) )
1766 sal_uInt16 nObjCount;
1767 const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh );
1768 const SwFrm *pFlyFrm = pFESh->GetCurrFlyFrm();
1769 if( pFlyFrm )
1771 ASSERT( !pFrm || pFrm->FindFlyFrm() == pFlyFrm,
1772 "cursor is not contained in fly frame" );
1773 aFrmOrObj = pFlyFrm;
1775 else if( (nObjCount = pFESh->IsObjSelected()) > 0 )
1777 bShapeSelected = sal_True;
1778 aFrmOrObj = static_cast<const SwFrm *>( 0 );
1783 ASSERT( bShapeSelected || aFrmOrObj.IsAccessible(GetShell()->IsPreView()),
1784 "frame is not accessible" );
1786 uno::Reference < XAccessible > xOldAcc;
1787 uno::Reference < XAccessible > xAcc;
1788 sal_Bool bOldShapeSelected = sal_False;
1791 vos::OGuard aGuard( maMutex );
1793 xOldAcc = mxCursorContext;
1794 mxCursorContext = xAcc; // clear reference
1796 bOldShapeSelected = mbShapeSelected;
1797 mbShapeSelected = bShapeSelected;
1799 if( aFrmOrObj.GetSwFrm() && mpFrmMap )
1801 SwAccessibleContextMap_Impl::iterator aIter =
1802 mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1803 if( aIter != mpFrmMap->end() )
1804 xAcc = (*aIter).second;
1806 // For cells, some extra thoughts are necessary,
1807 // because invalidating the cursor for one cell
1808 // invalidates the cursor for all cells of the same
1809 // table. For this reason, we don't want to
1810 // invalidate the cursor for the old cursor object
1811 // and the new one if they are within the same table,
1812 // because this would result in doing the work twice.
1813 // Moreover, we have to make sure to invalidate the
1814 // cursor even if the current cell has no accessible object.
1815 // If the old cursor objects exists and is in the same
1816 // table, its the best choice, because using it avoids
1817 // an unnessarary cursor invalidation cycle when creating
1818 // a new object for the current cell.
1819 if( aFrmOrObj.GetSwFrm()->IsCellFrm() )
1821 if( xOldAcc.is() &&
1822 AreInSameTable( xOldAcc, aFrmOrObj.GetSwFrm() ) )
1824 if( xAcc.is() )
1825 xOldAcc = xAcc; // avoid extra invalidation
1826 else
1827 xAcc = xOldAcc; // make sure ate least one
1829 if( !xAcc.is() )
1830 xAcc = GetContext( aFrmOrObj.GetSwFrm(), sal_True );
1835 if( xOldAcc.is() && xOldAcc != xAcc )
1836 InvalidateCursorPosition( xOldAcc );
1837 if( bOldShapeSelected || bShapeSelected )
1838 InvalidateShapeSelection();
1839 if( xAcc.is() )
1840 InvalidateCursorPosition( xAcc );
1843 void SwAccessibleMap::InvalidateFocus()
1845 uno::Reference < XAccessible > xAcc;
1846 sal_Bool bShapeSelected;
1848 vos::OGuard aGuard( maMutex );
1850 xAcc = mxCursorContext;
1851 bShapeSelected = mbShapeSelected;
1854 if( xAcc.is() )
1856 SwAccessibleContext *pAccImpl =
1857 static_cast< SwAccessibleContext *>( xAcc.get() );
1858 pAccImpl->InvalidateFocus();
1860 else if( bShapeSelected )
1862 DoInvalidateShapeFocus();
1866 void SwAccessibleMap::SetCursorContext(
1867 const ::vos::ORef < SwAccessibleContext >& rCursorContext )
1869 vos::OGuard aGuard( maMutex );
1870 uno::Reference < XAccessible > xAcc( rCursorContext.getBodyPtr() );
1871 mxCursorContext = xAcc;
1874 // --> OD 2005-12-12 #i27301# - use new type definition for <_nStates>
1875 void SwAccessibleMap::InvalidateStates( tAccessibleStates _nStates,
1876 const SwFrm* _pFrm )
1878 // Start with the frame or the first upper that is accessible
1879 SwFrmOrObj aFrmOrObj( _pFrm );
1880 while( aFrmOrObj.GetSwFrm() &&
1881 !aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1882 aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
1883 if( !aFrmOrObj.GetSwFrm() )
1884 aFrmOrObj = GetShell()->GetLayout();
1886 uno::Reference< XAccessible > xAcc( GetContext( aFrmOrObj.GetSwFrm(), sal_True ) );
1887 SwAccessibleContext *pAccImpl =
1888 static_cast< SwAccessibleContext *>( xAcc.get() );
1889 if( GetShell()->ActionPend() )
1891 SwAccessibleEvent_Impl aEvent(
1892 SwAccessibleEvent_Impl::CARET_OR_STATES, pAccImpl,
1893 pAccImpl->GetFrm(), _nStates );
1894 AppendEvent( aEvent );
1896 else
1898 FireEvents();
1899 pAccImpl->InvalidateStates( _nStates );
1902 // <--
1904 void SwAccessibleMap::_InvalidateRelationSet( const SwFrm* pFrm,
1905 sal_Bool bFrom )
1907 // first, see if this frame is accessible, and if so, get the respective
1908 SwFrmOrObj aFrmOrObj( pFrm );
1909 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1911 uno::Reference < XAccessible > xAcc;
1913 vos::OGuard aGuard( maMutex );
1915 if( mpFrmMap )
1917 SwAccessibleContextMap_Impl::iterator aIter =
1918 mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1919 if( aIter != mpFrmMap->end() )
1921 xAcc = (*aIter).second;
1926 // deliver event directly, or queue event
1927 if( xAcc.is() )
1929 SwAccessibleContext *pAccImpl =
1930 static_cast< SwAccessibleContext *>( xAcc.get() );
1931 if( GetShell()->ActionPend() )
1933 SwAccessibleEvent_Impl aEvent(
1934 SwAccessibleEvent_Impl::CARET_OR_STATES, pAccImpl, pFrm,
1935 bFrom ? ACC_STATE_RELATION_FROM : ACC_STATE_RELATION_TO );
1936 AppendEvent( aEvent );
1938 else
1940 FireEvents();
1941 pAccImpl->InvalidateRelation( bFrom
1942 ? AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED
1943 : AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED );
1949 void SwAccessibleMap::InvalidateRelationSet( const SwFrm* pMaster,
1950 const SwFrm* pFollow )
1952 _InvalidateRelationSet( pMaster, sal_False );
1953 _InvalidateRelationSet( pFollow, sal_True );
1956 /** invalidation CONTENT_FLOW_FROM/_TO relation of a paragraph
1958 OD 2005-12-01 #i27138#
1960 @author OD
1962 void SwAccessibleMap::InvalidateParaFlowRelation( const SwTxtFrm& _rTxtFrm,
1963 const bool _bFrom )
1965 _InvalidateRelationSet( &_rTxtFrm, _bFrom );
1968 /** invalidation of text selection of a paragraph
1970 OD 2005-12-12 #i27301#
1972 @author OD
1974 void SwAccessibleMap::InvalidateParaTextSelection( const SwTxtFrm& _rTxtFrm )
1976 // first, see if this frame is accessible, and if so, get the respective
1977 SwFrmOrObj aFrmOrObj( &_rTxtFrm );
1978 if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) )
1980 uno::Reference < XAccessible > xAcc;
1982 vos::OGuard aGuard( maMutex );
1984 if( mpFrmMap )
1986 SwAccessibleContextMap_Impl::iterator aIter =
1987 mpFrmMap->find( aFrmOrObj.GetSwFrm() );
1988 if( aIter != mpFrmMap->end() )
1990 xAcc = (*aIter).second;
1995 // deliver event directly, or queue event
1996 if( xAcc.is() )
1998 SwAccessibleContext *pAccImpl =
1999 static_cast< SwAccessibleContext *>( xAcc.get() );
2000 if( GetShell()->ActionPend() )
2002 SwAccessibleEvent_Impl aEvent(
2003 SwAccessibleEvent_Impl::CARET_OR_STATES,
2004 pAccImpl, &_rTxtFrm,
2005 ACC_STATE_TEXT_SELECTION_CHANGED );
2006 AppendEvent( aEvent );
2008 else
2010 FireEvents();
2011 pAccImpl->InvalidateTextSelection();
2017 // OD 15.01.2003 #103492# - complete re-factoring of method due to new page/print
2018 // preview functionality.
2019 void SwAccessibleMap::UpdatePreview( const std::vector<PrevwPage*>& _rPrevwPages,
2020 const Fraction& _rScale,
2021 const SwPageFrm* _pSelectedPageFrm,
2022 const Size& _rPrevwWinSize )
2024 DBG_ASSERT( GetShell()->IsPreView(), "no preview?" );
2025 DBG_ASSERT( mpPreview != NULL, "no preview data?" );
2027 // OD 15.01.2003 #103492# - adjustments for changed method signature
2028 mpPreview->Update( _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize );
2030 // propagate change of VisArea through the document's
2031 // accessibility tree; this will also send appropriate scroll
2032 // events
2033 SwAccessibleContext* pDoc =
2034 GetContextImpl( GetShell()->GetLayout() ).getBodyPtr();
2035 static_cast<SwAccessibleDocumentBase*>( pDoc )->SetVisArea();
2037 uno::Reference < XAccessible > xOldAcc;
2038 uno::Reference < XAccessible > xAcc;
2040 vos::OGuard aGuard( maMutex );
2042 xOldAcc = mxCursorContext;
2044 const SwPageFrm *pSelPage = mpPreview->GetSelPage();
2045 if( pSelPage && mpFrmMap )
2047 SwAccessibleContextMap_Impl::iterator aIter =
2048 mpFrmMap->find( pSelPage );
2049 if( aIter != mpFrmMap->end() )
2050 xAcc = (*aIter).second;
2054 if( xOldAcc.is() && xOldAcc != xAcc )
2055 InvalidateCursorPosition( xOldAcc );
2056 if( xAcc.is() )
2057 InvalidateCursorPosition( xAcc );
2060 void SwAccessibleMap::InvalidatePreViewSelection( sal_uInt16 nSelPage )
2062 DBG_ASSERT( GetShell()->IsPreView(), "no preview?" );
2063 DBG_ASSERT( mpPreview != NULL, "no preview data?" );
2065 // OD 16.01.2003 #103492# - changed metthod call due to method signature change.
2066 mpPreview->InvalidateSelection( GetShell()->GetLayout()->GetPageByPageNum( nSelPage ) );
2068 uno::Reference < XAccessible > xOldAcc;
2069 uno::Reference < XAccessible > xAcc;
2071 vos::OGuard aGuard( maMutex );
2073 xOldAcc = mxCursorContext;
2075 const SwPageFrm *pSelPage = mpPreview->GetSelPage();
2076 if( pSelPage && mpFrmMap )
2078 SwAccessibleContextMap_Impl::iterator aIter =
2079 mpFrmMap->find( pSelPage );
2080 if( aIter != mpFrmMap->end() )
2081 xAcc = (*aIter).second;
2085 if( xOldAcc.is() && xOldAcc != xAcc )
2086 InvalidateCursorPosition( xOldAcc );
2087 if( xAcc.is() )
2088 InvalidateCursorPosition( xAcc );
2092 sal_Bool SwAccessibleMap::IsPageSelected( const SwPageFrm *pPageFrm ) const
2094 return mpPreview && mpPreview->GetSelPage() == pPageFrm;
2098 void SwAccessibleMap::FireEvents()
2101 vos::OGuard aGuard( maEventMutex );
2102 if( mpEvents )
2104 mpEvents->SetFiring();
2105 SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
2106 while( aIter != mpEvents->end() )
2108 FireEvent( *aIter );
2109 ++aIter;
2112 delete mpEventMap;
2113 mpEventMap = 0;
2115 delete mpEvents;
2116 mpEvents = 0;
2120 vos::OGuard aGuard( maMutex );
2121 if( mpShapes )
2123 delete mpShapes;
2124 mpShapes = 0;
2130 sal_Bool SwAccessibleMap::IsValid() const
2132 return sal_True;
2135 Rectangle SwAccessibleMap::GetVisibleArea() const
2137 MapMode aSrc( MAP_TWIP );
2138 MapMode aDest( MAP_100TH_MM );
2139 return OutputDevice::LogicToLogic( GetVisArea().SVRect(), aSrc, aDest );
2142 // Convert a MM100 value realtive to the document root into a pixel value
2143 // realtive to the screen!
2144 Point SwAccessibleMap::LogicToPixel( const Point& rPoint ) const
2146 MapMode aSrc( MAP_100TH_MM );
2147 MapMode aDest( MAP_TWIP );
2149 Point aPoint = rPoint;
2151 aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
2152 Window *pWin = GetShell()->GetWin();
2153 if( pWin )
2155 // OD 16.01.2003 #103492# - get mapping mode for LogicToPixel conversion
2156 MapMode aMapMode;
2157 GetMapMode( aPoint, aMapMode );
2158 aPoint = pWin->LogicToPixel( aPoint, aMapMode );
2159 aPoint = pWin->OutputToAbsoluteScreenPixel( aPoint );
2162 return aPoint;
2165 Size SwAccessibleMap::LogicToPixel( const Size& rSize ) const
2167 MapMode aSrc( MAP_100TH_MM );
2168 MapMode aDest( MAP_TWIP );
2169 Size aSize( OutputDevice::LogicToLogic( rSize, aSrc, aDest ) );
2170 if( GetShell()->GetWin() )
2172 // OD 16.01.2003 #103492# - get mapping mode for LogicToPixel conversion
2173 MapMode aMapMode;
2174 GetMapMode( Point(0,0), aMapMode );
2175 aSize = GetShell()->GetWin()->LogicToPixel( aSize, aMapMode );
2178 return aSize;
2181 Point SwAccessibleMap::PixelToLogic( const Point& rPoint ) const
2183 Point aPoint;
2184 Window *pWin = GetShell()->GetWin();
2185 if( pWin )
2187 aPoint = pWin->ScreenToOutputPixel( rPoint );
2188 // OD 16.01.2003 #103492# - get mapping mode for PixelToLogic conversion
2189 MapMode aMapMode;
2190 GetMapMode( aPoint, aMapMode );
2191 aPoint = pWin->PixelToLogic( aPoint, aMapMode );
2192 MapMode aSrc( MAP_TWIP );
2193 MapMode aDest( MAP_100TH_MM );
2194 aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest );
2197 return aPoint;
2200 Size SwAccessibleMap::PixelToLogic( const Size& rSize ) const
2202 Size aSize;
2203 if( GetShell()->GetWin() )
2205 // OD 16.01.2003 #103492# - get mapping mode for PixelToLogic conversion
2206 MapMode aMapMode;
2207 GetMapMode( Point(0,0), aMapMode );
2208 aSize = GetShell()->GetWin()->PixelToLogic( rSize, aMapMode );
2209 MapMode aSrc( MAP_TWIP );
2210 MapMode aDest( MAP_100TH_MM );
2211 aSize = OutputDevice::LogicToLogic( aSize, aSrc, aDest );
2214 return aSize;
2217 sal_Bool SwAccessibleMap::ReplaceChild (
2218 ::accessibility::AccessibleShape* pCurrentChild,
2219 const uno::Reference< drawing::XShape >& _rxShape,
2220 const long /*_nIndex*/,
2221 const ::accessibility::AccessibleShapeTreeInfo& /*_rShapeTreeInfo*/
2222 ) throw (uno::RuntimeException)
2224 const SdrObject *pObj = 0;
2226 vos::OGuard aGuard( maMutex );
2227 if( mpShapeMap )
2229 SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin();
2230 SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end();
2231 while( aIter != aEndIter && !pObj )
2233 uno::Reference < XAccessible > xAcc( (*aIter).second );
2234 ::accessibility::AccessibleShape *pAccShape =
2235 static_cast < ::accessibility::AccessibleShape* >( xAcc.get() );
2236 if( pAccShape == pCurrentChild )
2238 pObj = (*aIter).first;
2240 ++aIter;
2244 if( !pObj )
2245 return sal_False;
2247 uno::Reference < drawing::XShape > xShape( _rxShape ); //keep reference to shape, because
2248 // we might be the only one that
2249 // hold it.
2250 // Also get keep parent.
2251 uno::Reference < XAccessible > xParent( pCurrentChild->getAccessibleParent() );
2252 pCurrentChild = 0; // well be realease by dispose
2253 Dispose( 0, pObj );
2256 vos::OGuard aGuard( maMutex );
2258 if( !mpShapeMap )
2259 mpShapeMap = new SwAccessibleShapeMap_Impl( this );
2261 // create the new child
2262 ::accessibility::ShapeTypeHandler& rShapeTypeHandler =
2263 ::accessibility::ShapeTypeHandler::Instance();
2264 ::accessibility::AccessibleShapeInfo aShapeInfo(
2265 xShape, xParent, this );
2266 ::accessibility::AccessibleShape* pReplacement =
2267 rShapeTypeHandler.CreateAccessibleObject (
2268 aShapeInfo, mpShapeMap->GetInfo() );
2270 uno::Reference < XAccessible > xAcc( pReplacement );
2271 if( xAcc.is() )
2273 pReplacement->Init();
2275 SwAccessibleShapeMap_Impl::iterator aIter =
2276 mpShapeMap->find( pObj );
2277 if( aIter != mpShapeMap->end() )
2279 (*aIter).second = xAcc;
2281 else
2283 SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAcc );
2284 mpShapeMap->insert( aEntry );
2289 SwRect aEmptyRect;
2290 InvalidatePosOrSize( 0, pObj, aEmptyRect );
2292 return sal_True;
2295 Point SwAccessibleMap::PixelToCore( const Point& rPoint ) const
2297 Point aPoint;
2298 if( GetShell()->GetWin() )
2300 // OD 15.01.2003 #103492# - replace <PreviewAdjust(..)> by <GetMapMode(..)>
2301 MapMode aMapMode;
2302 GetMapMode( rPoint, aMapMode );
2303 aPoint = GetShell()->GetWin()->PixelToLogic( rPoint, aMapMode );
2305 return aPoint;
2308 static inline long lcl_CorrectCoarseValue(long aCoarseValue, long aFineValue,
2309 long aRefValue, bool bToLower)
2311 long aResult = aCoarseValue;
2313 if (bToLower)
2315 if (aFineValue < aRefValue)
2316 aResult -= 1;
2318 else
2320 if (aFineValue > aRefValue)
2321 aResult += 1;
2324 return aResult;
2327 static inline void lcl_CorrectRectangle(Rectangle & rRect,
2328 const Rectangle & rSource,
2329 const Rectangle & rInGrid)
2331 rRect.nLeft = lcl_CorrectCoarseValue(rRect.nLeft, rSource.nLeft,
2332 rInGrid.nLeft, false);
2333 rRect.nTop = lcl_CorrectCoarseValue(rRect.nTop, rSource.nTop,
2334 rInGrid.nTop, false);
2335 rRect.nRight = lcl_CorrectCoarseValue(rRect.nRight, rSource.nRight,
2336 rInGrid.nRight, true);
2337 rRect.nBottom = lcl_CorrectCoarseValue(rRect.nBottom, rSource.nBottom,
2338 rInGrid.nBottom, true);
2341 Rectangle SwAccessibleMap::CoreToPixel( const Rectangle& rRect ) const
2343 Rectangle aRect;
2344 if( GetShell()->GetWin() )
2346 // OD 15.01.2003 #103492# - replace <PreviewAdjust(..)> by <GetMapMode(..)>
2347 MapMode aMapMode;
2348 GetMapMode( rRect.TopLeft(), aMapMode );
2349 aRect = GetShell()->GetWin()->LogicToPixel( rRect, aMapMode );
2351 Rectangle aTmpRect = GetShell()->GetWin()->PixelToLogic( aRect, aMapMode );
2352 lcl_CorrectRectangle(aRect, rRect, aTmpRect);
2355 return aRect;
2358 /** get mapping mode for LogicToPixel and PixelToLogic conversions
2360 OD 15.01.2003 #103492#
2361 Replacement method <PreviewAdjust(..)> by new method <GetMapMode>.
2362 Method returns mapping mode of current output device and adjusts it,
2363 if the shell is in page/print preview.
2364 Necessary, because <PreviewAdjust(..)> changes mapping mode at current
2365 output device for mapping logic document positions to page preview window
2366 positions and vice versa and doesn't take care to recover its changes.
2368 @author OD
2370 void SwAccessibleMap::GetMapMode( const Point& _rPoint,
2371 MapMode& _orMapMode ) const
2373 MapMode aMapMode = GetShell()->GetWin()->GetMapMode();
2374 if( GetShell()->IsPreView() )
2376 DBG_ASSERT( mpPreview != NULL, "need preview data" );
2378 mpPreview->AdjustMapMode( aMapMode, _rPoint );
2380 _orMapMode = aMapMode;
2383 /** get size of a dedicated preview page
2385 OD 15.01.2003 #103492#
2387 @author OD
2389 Size SwAccessibleMap::GetPreViewPageSize( sal_uInt16 _nPrevwPageNum ) const
2391 DBG_ASSERT( mpVSh->IsPreView(), "no page preview accessible." );
2392 DBG_ASSERT( mpVSh->IsPreView() && ( mpPreview != NULL ),
2393 "missing accessible preview data at page preview" );
2394 if ( mpVSh->IsPreView() && ( mpPreview != NULL ) )
2396 return mpVSh->PagePreviewLayout()->GetPrevwPageSizeByPageNum( _nPrevwPageNum );
2398 else
2400 return Size( 0, 0 );
2404 /** method to build up a new data structure of the accessible pararaphs,
2405 which have a selection
2407 OD 2005-12-13 #i27301#
2408 Important note: method has to used inside a mutual exclusive section
2410 @author OD
2412 SwAccessibleSelectedParas_Impl* SwAccessibleMap::_BuildSelectedParas()
2414 // no accessible contexts, no selection
2415 if ( !mpFrmMap )
2417 return 0L;
2420 // get cursor as an instance of its base class <SwPaM>
2421 SwPaM* pCrsr( 0L );
2423 SwCrsrShell* pCrsrShell = dynamic_cast<SwCrsrShell*>(GetShell());
2424 if ( pCrsrShell )
2426 SwFEShell* pFEShell = dynamic_cast<SwFEShell*>(pCrsrShell);
2427 if ( !pFEShell ||
2428 ( !pFEShell->IsFrmSelected() &&
2429 pFEShell->IsObjSelected() == 0 ) )
2431 // get cursor without updating an existing table cursor.
2432 pCrsr = pCrsrShell->GetCrsr( FALSE );
2436 // no cursor, no selection
2437 if ( !pCrsr )
2439 return 0L;
2442 SwAccessibleSelectedParas_Impl* pRetSelectedParas( 0L );
2444 // loop on all cursors
2445 SwPaM* pRingStart = pCrsr;
2446 do {
2448 // for a selection the cursor has to have a mark.
2449 // for savety reasons assure that point and mark are in text nodes
2450 if ( pCrsr->HasMark() &&
2451 pCrsr->GetPoint()->nNode.GetNode().IsTxtNode() &&
2452 pCrsr->GetMark()->nNode.GetNode().IsTxtNode() )
2454 SwPosition* pStartPos = pCrsr->Start();
2455 SwPosition* pEndPos = pCrsr->End();
2456 // loop on all text nodes inside the selection
2457 SwNodeIndex aIdx( pStartPos->nNode );
2458 for ( ; aIdx.GetIndex() <= pEndPos->nNode.GetIndex(); ++aIdx )
2460 SwTxtNode* pTxtNode( aIdx.GetNode().GetTxtNode() );
2461 if ( pTxtNode )
2463 // loop on all text frames registered at the text node.
2464 SwClientIter aIter( *pTxtNode );
2465 for( SwFrm* pFrm = (SwFrm*)aIter.First( TYPE(SwFrm) );
2466 pFrm;
2467 pFrm = (SwFrm*)aIter.Next() )
2469 ASSERT( dynamic_cast<SwTxtFrm*>(pFrm),
2470 "<SwAccessibleMap::_BuildSelectedParas()> - unexpected frame type" );
2471 SwTxtFrm* pTxtFrm( dynamic_cast<SwTxtFrm*>(pFrm) );
2472 if ( pTxtFrm )
2474 uno::WeakReference < XAccessible > xWeakAcc;
2475 SwAccessibleContextMap_Impl::iterator aMapIter =
2476 mpFrmMap->find( pTxtFrm );
2477 if( aMapIter != mpFrmMap->end() )
2479 xWeakAcc = (*aMapIter).second;
2480 SwAccessibleParaSelection aDataEntry(
2481 pTxtNode == &(pStartPos->nNode.GetNode())
2482 ? pStartPos->nContent.GetIndex()
2483 : 0,
2484 pTxtNode == &(pEndPos->nNode.GetNode())
2485 ? pEndPos->nContent.GetIndex()
2486 : STRING_LEN );
2487 SwAccessibleSelectedParas_Impl::value_type
2488 aEntry( xWeakAcc, aDataEntry );
2489 if ( !pRetSelectedParas )
2491 pRetSelectedParas =
2492 new SwAccessibleSelectedParas_Impl;
2494 pRetSelectedParas->insert( aEntry );
2502 // prepare next turn: get next cursor in ring
2503 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
2504 } while ( pCrsr != pRingStart );
2506 return pRetSelectedParas;
2509 /** invalidation of text selection of all paragraphs
2511 OD 2005-12-13 #i27301#
2513 @author OD
2515 void SwAccessibleMap::InvalidateTextSelectionOfAllParas()
2517 vos::OGuard aGuard( maMutex );
2519 // keep previously known selected paragraphs
2520 SwAccessibleSelectedParas_Impl* pPrevSelectedParas( mpSelectedParas );
2522 // determine currently selected paragraphs
2523 mpSelectedParas = _BuildSelectedParas();
2525 // compare currently selected paragraphs with the previously selected
2526 // paragraphs and submit corresponding TEXT_SELECTION_CHANGED events.
2527 // first, search for new and changed selections.
2528 // on the run remove selections from previously known ones, if they are
2529 // also in the current ones.
2530 if ( mpSelectedParas )
2532 SwAccessibleSelectedParas_Impl::iterator aIter = mpSelectedParas->begin();
2533 for ( ; aIter != mpSelectedParas->end(); ++aIter )
2535 bool bSubmitEvent( false );
2536 if ( !pPrevSelectedParas )
2538 // new selection
2539 bSubmitEvent = true;
2541 else
2543 SwAccessibleSelectedParas_Impl::iterator aPrevSelected =
2544 pPrevSelectedParas->find( (*aIter).first );
2545 if ( aPrevSelected != pPrevSelectedParas->end() )
2547 // check, if selection has changed
2548 if ( (*aIter).second.nStartOfSelection !=
2549 (*aPrevSelected).second.nStartOfSelection ||
2550 (*aIter).second.nEndOfSelection !=
2551 (*aPrevSelected).second.nEndOfSelection )
2553 // changed selection
2554 bSubmitEvent = true;
2556 pPrevSelectedParas->erase( aPrevSelected );
2558 else
2560 // new selection
2561 bSubmitEvent = true;
2565 if ( bSubmitEvent )
2567 uno::Reference < XAccessible > xAcc( (*aIter).first );
2568 if ( xAcc.is() )
2570 ::vos::ORef < SwAccessibleContext > xAccImpl(
2571 static_cast<SwAccessibleContext*>( xAcc.get() ) );
2572 if ( xAccImpl.isValid() && xAccImpl->GetFrm() )
2574 const SwTxtFrm* pTxtFrm(
2575 dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
2576 ASSERT( pTxtFrm,
2577 "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" );
2578 if ( pTxtFrm )
2580 InvalidateParaTextSelection( *pTxtFrm );
2588 // second, handle previous selections - after the first step the data
2589 // structure of the previously known only contains the 'old' selections
2590 if ( pPrevSelectedParas )
2592 SwAccessibleSelectedParas_Impl::iterator aIter = pPrevSelectedParas->begin();
2593 for ( ; aIter != pPrevSelectedParas->end(); ++aIter )
2595 uno::Reference < XAccessible > xAcc( (*aIter).first );
2596 if ( xAcc.is() )
2598 ::vos::ORef < SwAccessibleContext > xAccImpl(
2599 static_cast<SwAccessibleContext*>( xAcc.get() ) );
2600 if ( xAccImpl.isValid() && xAccImpl->GetFrm() )
2602 const SwTxtFrm* pTxtFrm(
2603 dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) );
2604 ASSERT( pTxtFrm,
2605 "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" );
2606 if ( pTxtFrm )
2608 InvalidateParaTextSelection( *pTxtFrm );
2614 delete pPrevSelectedParas;
2619 // SwAccPreviewData
2622 SwAccPreviewData::SwAccPreviewData() :
2623 mpSelPage( 0 )
2627 SwAccPreviewData::~SwAccPreviewData()
2631 // OD 13.01.2003 #103492# - complete re-factoring of method due to new page/print
2632 // preview functionality.
2633 void SwAccPreviewData::Update( const std::vector<PrevwPage*>& _rPrevwPages,
2634 const Fraction& _rScale,
2635 const SwPageFrm* _pSelectedPageFrm,
2636 const Size& _rPrevwWinSize )
2638 // store preview scaling, maximal preview page size and selected page
2639 maScale = _rScale;
2640 mpSelPage = _pSelectedPageFrm;
2642 // prepare loop on preview pages
2643 maPreviewRects.clear();
2644 maLogicRects.clear();
2645 SwFrmOrObj aPage;
2646 maVisArea.Clear();
2648 // loop on preview pages to calculate <maPreviewRects>, <maLogicRects> and
2649 // <maVisArea>
2650 for ( std::vector<PrevwPage*>::const_iterator aPageIter = _rPrevwPages.begin();
2651 aPageIter != _rPrevwPages.end();
2652 ++aPageIter )
2654 aPage = (*aPageIter)->pPage;
2656 // add preview page rectangle to <maPreviewRects>
2657 Rectangle aPrevwPgRect( (*aPageIter)->aPrevwWinPos, (*aPageIter)->aPageSize );
2658 maPreviewRects.push_back( aPrevwPgRect );
2660 // add logic page rectangle to <maLogicRects>
2661 SwRect aLogicPgSwRect( aPage.GetBox() );
2662 Rectangle aLogicPgRect( aLogicPgSwRect.SVRect() );
2663 maLogicRects.push_back( aLogicPgRect );
2664 // union visible area with visible part of logic page rectangle
2665 if ( (*aPageIter)->bVisible )
2667 if ( !(*aPageIter)->pPage->IsEmptyPage() )
2669 AdjustLogicPgRectToVisibleArea( aLogicPgSwRect,
2670 SwRect( aPrevwPgRect ),
2671 _rPrevwWinSize );
2673 if ( maVisArea.IsEmpty() )
2674 maVisArea = aLogicPgSwRect;
2675 else
2676 maVisArea.Union( aLogicPgSwRect );
2681 // OD 16.01.2003 #103492# - complete re-factoring of method due to new page/print
2682 // preview functionality.
2683 void SwAccPreviewData::InvalidateSelection( const SwPageFrm* _pSelectedPageFrm )
2685 mpSelPage = _pSelectedPageFrm;
2686 ASSERT( mpSelPage, "selected page not found" );
2689 struct ContainsPredicate
2691 const Point& mrPoint;
2692 ContainsPredicate( const Point& rPoint ) : mrPoint(rPoint) {}
2693 bool operator() ( const Rectangle& rRect ) const
2695 return rRect.IsInside( mrPoint ) ? true : false;
2699 const SwRect& SwAccPreviewData::GetVisArea() const
2701 return maVisArea;
2704 void SwAccPreviewData::AdjustMapMode( MapMode& rMapMode,
2705 const Point& rPoint ) const
2707 // adjust scale
2708 rMapMode.SetScaleX( maScale );
2709 rMapMode.SetScaleY( maScale );
2711 // find proper rectangle
2712 Rectangles::const_iterator aBegin = maLogicRects.begin();
2713 Rectangles::const_iterator aEnd = maLogicRects.end();
2714 Rectangles::const_iterator aFound = ::std::find_if( aBegin, aEnd,
2715 ContainsPredicate( rPoint ) );
2717 if( aFound != aEnd )
2719 // found! set new origin
2720 Point aPoint = (maPreviewRects.begin() + (aFound - aBegin))->TopLeft();
2721 aPoint -= (maLogicRects.begin() + (aFound-aBegin))->TopLeft();
2722 rMapMode.SetOrigin( aPoint );
2724 // else: don't adjust MapMode
2727 void SwAccPreviewData::DisposePage(const SwPageFrm *pPageFrm )
2729 if( mpSelPage == pPageFrm )
2730 mpSelPage = 0;
2733 /** adjust logic page retangle to its visible part
2735 OD 17.01.2003 #103492#
2737 @author OD
2739 void SwAccPreviewData::AdjustLogicPgRectToVisibleArea(
2740 SwRect& _iorLogicPgSwRect,
2741 const SwRect& _rPrevwPgSwRect,
2742 const Size& _rPrevwWinSize )
2744 // determine preview window rectangle
2745 const SwRect aPrevwWinSwRect( Point( 0, 0 ), _rPrevwWinSize );
2746 // calculate visible preview page rectangle
2747 SwRect aVisPrevwPgSwRect( _rPrevwPgSwRect );
2748 aVisPrevwPgSwRect.Intersection( aPrevwWinSwRect );
2749 // adjust logic page rectangle
2750 SwTwips nTmpDiff;
2751 // left
2752 nTmpDiff = aVisPrevwPgSwRect.Left() - _rPrevwPgSwRect.Left();
2753 if ( nTmpDiff > 0 )
2754 _iorLogicPgSwRect.Left( _iorLogicPgSwRect.Left() + nTmpDiff );
2755 // top
2756 nTmpDiff = aVisPrevwPgSwRect.Top() - _rPrevwPgSwRect.Top();
2757 if ( nTmpDiff > 0 )
2758 _iorLogicPgSwRect.Top( _iorLogicPgSwRect.Top() + nTmpDiff );
2759 // right
2760 nTmpDiff = _rPrevwPgSwRect.Right() - aVisPrevwPgSwRect.Right();
2761 if ( nTmpDiff > 0 )
2762 _iorLogicPgSwRect.Right( _iorLogicPgSwRect.Right() - nTmpDiff );
2763 // bottom
2764 nTmpDiff = _rPrevwPgSwRect.Bottom() - aVisPrevwPgSwRect.Bottom();
2765 if ( nTmpDiff > 0 )
2766 _iorLogicPgSwRect.Bottom( _iorLogicPgSwRect.Bottom() - nTmpDiff );