update dev300-m58
[ooovba.git] / svx / source / accessibility / AccessibleTextHelper.cxx
blob6217cf9caf0d80058c800750261c37d57ce63a32
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: AccessibleTextHelper.cxx,v $
10 * $Revision: 1.48 $
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_svx.hxx"
34 //------------------------------------------------------------------------
36 // Global header
38 //------------------------------------------------------------------------
40 #include <limits.h>
41 #include <memory>
42 #include <algorithm>
43 #include <deque>
44 #include <vos/mutex.hxx>
45 #include <com/sun/star/uno/Any.hxx>
46 #include <com/sun/star/uno/Reference.hxx>
47 #include <cppuhelper/weakref.hxx>
48 #include <com/sun/star/awt/Point.hpp>
49 #include <com/sun/star/awt/Rectangle.hpp>
50 #include <com/sun/star/lang/DisposedException.hpp>
51 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
52 #include <com/sun/star/accessibility/XAccessible.hpp>
53 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
54 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
55 #include <com/sun/star/accessibility/AccessibleRole.hpp>
56 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
57 #include <com/sun/star/accessibility/XAccessibleText.hpp>
58 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
59 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
60 #include <comphelper/accessibleeventnotifier.hxx>
61 #include <unotools/accessiblestatesethelper.hxx>
62 #include <vcl/unohelp.hxx>
63 #include <vcl/svapp.hxx>
65 //------------------------------------------------------------------------
67 // Project-local header
69 //------------------------------------------------------------------------
70 #include "AccessibleTextEventQueue.hxx"
71 #include <svx/AccessibleTextHelper.hxx>
72 #include <svx/unoshape.hxx>
73 #include "unolingu.hxx"
74 #include <svx/unotext.hxx>
76 #include "unoedhlp.hxx"
77 #include "unopracc.hxx"
78 #include "AccessibleParaManager.hxx"
79 #include "AccessibleEditableTextPara.hxx"
80 #include <svx/svdmodel.hxx>
81 #include <svx/svdpntv.hxx>
82 #include <svx/editdata.hxx>
83 #include <svx/editeng.hxx>
84 #include <svx/editview.hxx>
86 using namespace ::com::sun::star;
87 using namespace ::com::sun::star::accessibility;
89 namespace accessibility
92 //------------------------------------------------------------------------
94 // AccessibleTextHelper_Impl declaration
96 //------------------------------------------------------------------------
98 DBG_NAME( AccessibleTextHelper_Impl )
100 template < typename first_type, typename second_type >
101 ::std::pair< first_type, second_type > makeSortedPair( first_type first,
102 second_type second )
104 if( first > second )
105 return ::std::make_pair( second, first );
106 else
107 return ::std::make_pair( first, second );
110 class AccessibleTextHelper_Impl : public SfxListener
113 public:
114 typedef ::std::vector< sal_Int16 > VectorOfStates;
116 // receive pointer to our frontend class and view window
117 AccessibleTextHelper_Impl();
118 ~AccessibleTextHelper_Impl();
120 // XAccessibleContext child handling methods
121 sal_Int32 SAL_CALL getAccessibleChildCount() SAL_THROW((uno::RuntimeException));
122 uno::Reference< XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException));
124 // XAccessibleEventBroadcaster child related methods
125 void SAL_CALL addEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException));
126 void SAL_CALL removeEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException));
128 // XAccessibleComponent child related methods
129 uno::Reference< XAccessible > SAL_CALL getAccessibleAtPoint( const awt::Point& aPoint ) SAL_THROW((uno::RuntimeException));
131 SvxEditSourceAdapter& GetEditSource() const SAL_THROW((uno::RuntimeException));
132 void SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException));
134 void SetEventSource( const uno::Reference< XAccessible >& rInterface )
136 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
137 mxFrontEnd = rInterface;
139 uno::Reference< XAccessible > GetEventSource() const
141 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
142 return mxFrontEnd;
145 void SetOffset( const Point& );
146 Point GetOffset() const
148 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
149 ::osl::MutexGuard aGuard( maMutex ); Point aPoint( maOffset );
150 return aPoint;
153 void SetStartIndex( sal_Int32 nOffset );
154 sal_Int32 GetStartIndex() const
156 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
157 // Strictly correct only with locked solar mutex, // but
158 // here we rely on the fact that sal_Int32 access is
159 // atomic
160 return mnStartIndex;
163 void SetAdditionalChildStates( const VectorOfStates& rChildStates );
164 const VectorOfStates& GetAdditionalChildStates() const;
166 sal_Bool IsSelected() const;
168 void Dispose();
170 // do NOT hold object mutex when calling this! Danger of deadlock
171 void FireEvent( const sal_Int16 nEventId, const uno::Any& rNewValue = uno::Any(), const uno::Any& rOldValue = uno::Any() ) const;
172 void FireEvent( const AccessibleEventObject& rEvent ) const;
174 void SetFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException));
175 sal_Bool HaveFocus() SAL_THROW((::com::sun::star::uno::RuntimeException));
176 void SetChildFocus( sal_Int32 nChild, sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException));
177 void SetShapeFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException));
178 void ChangeChildFocus( sal_Int32 nNewChild ) SAL_THROW((::com::sun::star::uno::RuntimeException));
180 #ifdef DBG_UTIL
181 void CheckInvariants() const;
182 #endif
184 // checks all children for visibility, throws away invisible ones
185 void UpdateVisibleChildren( bool bBroadcastEvents=true );
187 // check all children for changes in positíon and size
188 void UpdateBoundRect();
190 // calls SetSelection on the forwarder and updates maLastSelection
191 // cache.
192 void UpdateSelection();
194 private:
196 // Process event queue
197 void ProcessQueue();
199 // syntactic sugar for FireEvent
200 void GotPropertyEvent( const uno::Any& rNewValue, const sal_Int16 nEventId ) const { FireEvent( nEventId, rNewValue ); }
201 void LostPropertyEvent( const uno::Any& rOldValue, const sal_Int16 nEventId ) const { FireEvent( nEventId, uno::Any(), rOldValue ); }
203 // shutdown usage of current edit source on myself and the children.
204 void ShutdownEditSource() SAL_THROW((uno::RuntimeException));
206 void ParagraphsMoved( sal_Int32 nFirst, sal_Int32 nMiddle, sal_Int32 nLast );
208 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
210 int getNotifierClientId() const { return mnNotifierClientId; }
212 // lock solar mutex before
213 SvxTextForwarder& GetTextForwarder() const SAL_THROW((uno::RuntimeException));
214 // lock solar mutex before
215 SvxViewForwarder& GetViewForwarder() const SAL_THROW((uno::RuntimeException));
216 // lock solar mutex before
217 SvxEditViewForwarder& GetEditViewForwarder( sal_Bool bCreate = sal_False ) const SAL_THROW((uno::RuntimeException));
219 // are we in edit mode?
220 sal_Bool IsActive() const SAL_THROW((uno::RuntimeException));
222 // our frontend class (the one implementing the actual
223 // interface). That's not necessarily the one containing the impl
224 // pointer!
225 uno::Reference< XAccessible > mxFrontEnd;
227 // a wrapper for the text forwarders (guarded by solar mutex)
228 mutable SvxEditSourceAdapter maEditSource;
230 // store last selection (to correctly report selection changes, guarded by solar mutex)
231 ESelection maLastSelection;
233 // cache range of visible children (guarded by solar mutex)
234 sal_Int32 mnFirstVisibleChild;
235 sal_Int32 mnLastVisibleChild;
237 // offset to add to all our children (unguarded, relying on
238 // the fact that sal_Int32 access is atomic)
239 sal_Int32 mnStartIndex;
241 // the object handling our children (guarded by solar mutex)
242 ::accessibility::AccessibleParaManager maParaManager;
244 // number of not-yet-closed event frames (BEGIN/END sequences) (guarded by solar mutex)
245 sal_Int32 maEventOpenFrames;
247 // Queued events from Notify() (guarded by solar mutex)
248 AccessibleTextEventQueue maEventQueue;
250 // spin lock to prevent notify in notify (guarded by solar mutex)
251 sal_Bool mbInNotify;
253 // whether the object or it's children has the focus set (guarded by solar mutex)
254 sal_Bool mbGroupHasFocus;
256 // whether we (this object) has the focus set (guarded by solar mutex)
257 sal_Bool mbThisHasFocus;
259 mutable ::osl::Mutex maMutex;
261 /// our current offset to the containing shape/cell (guarded by maMutex)
262 Point maOffset;
264 /// client Id from AccessibleEventNotifier
265 int mnNotifierClientId;
268 //------------------------------------------------------------------------
270 // AccessibleTextHelper_Impl implementation
272 //------------------------------------------------------------------------
274 AccessibleTextHelper_Impl::AccessibleTextHelper_Impl() :
275 mxFrontEnd( NULL ),
276 maLastSelection( EE_PARA_NOT_FOUND,EE_PARA_NOT_FOUND,EE_PARA_NOT_FOUND,EE_PARA_NOT_FOUND ),
277 mnFirstVisibleChild( -1 ),
278 mnLastVisibleChild( -2 ),
279 mnStartIndex( 0 ),
280 maEventOpenFrames( 0 ),
281 mbInNotify( sal_False ),
282 mbGroupHasFocus( sal_False ),
283 mbThisHasFocus( sal_False ),
284 maOffset(0,0),
285 // well, that's strictly exception safe, though not really
286 // robust. We rely on the fact that this member is constructed
287 // last, and that the constructor body is empty, thus no
288 // chance for exceptions once the Id is fetched. Nevertheless,
289 // normally should employ RAII here...
290 mnNotifierClientId(::comphelper::AccessibleEventNotifier::registerClient())
292 DBG_CTOR( AccessibleTextHelper_Impl, NULL );
294 #ifdef DBG_UTIL
295 OSL_TRACE( "AccessibleTextHelper_Impl received ID: %d", mnNotifierClientId );
296 #endif
299 AccessibleTextHelper_Impl::~AccessibleTextHelper_Impl()
301 DBG_DTOR( AccessibleTextHelper_Impl, NULL );
303 ::vos::OGuard aGuard( Application::GetSolarMutex() );
307 // call Dispose here, too, since we've some resources not
308 // automatically freed otherwise
309 Dispose();
311 catch( const uno::Exception& ) {}
314 SvxTextForwarder& AccessibleTextHelper_Impl::GetTextForwarder() const SAL_THROW((uno::RuntimeException))
316 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
318 if( !maEditSource.IsValid() )
319 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown edit source")), mxFrontEnd);
321 SvxTextForwarder* pTextForwarder = maEditSource.GetTextForwarder();
323 if( !pTextForwarder )
324 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch text forwarder, model might be dead")), mxFrontEnd);
326 if( pTextForwarder->IsValid() )
327 return *pTextForwarder;
328 else
329 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Text forwarder is invalid, model might be dead")), mxFrontEnd);
332 SvxViewForwarder& AccessibleTextHelper_Impl::GetViewForwarder() const SAL_THROW((uno::RuntimeException))
334 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
336 if( !maEditSource.IsValid() )
337 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown edit source")), mxFrontEnd);
339 SvxViewForwarder* pViewForwarder = maEditSource.GetViewForwarder();
341 if( !pViewForwarder )
342 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch view forwarder, model might be dead")), mxFrontEnd);
344 if( pViewForwarder->IsValid() )
345 return *pViewForwarder;
346 else
347 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, model might be dead")), mxFrontEnd);
350 SvxEditViewForwarder& AccessibleTextHelper_Impl::GetEditViewForwarder( sal_Bool bCreate ) const SAL_THROW((uno::RuntimeException))
352 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
354 if( !maEditSource.IsValid() )
355 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unknown edit source")), mxFrontEnd);
357 SvxEditViewForwarder* pViewForwarder = maEditSource.GetEditViewForwarder( bCreate );
359 if( !pViewForwarder )
361 if( bCreate )
362 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch edit view forwarder, model might be dead")), mxFrontEnd);
363 else
364 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No edit view forwarder, object not in edit mode")), mxFrontEnd);
367 if( pViewForwarder->IsValid() )
368 return *pViewForwarder;
369 else
371 if( bCreate )
372 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, model might be dead")), mxFrontEnd);
373 else
374 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, object not in edit mode")), mxFrontEnd);
378 SvxEditSourceAdapter& AccessibleTextHelper_Impl::GetEditSource() const SAL_THROW((uno::RuntimeException))
380 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
382 if( maEditSource.IsValid() )
383 return maEditSource;
384 else
385 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleTextHelper_Impl::GetEditSource: no edit source")), mxFrontEnd );
388 sal_Bool AccessibleTextHelper_Impl::IsSelected() const
390 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
392 sal_Bool bRet = sal_False;
396 ESelection aSelection;
397 bRet = GetEditViewForwarder().GetSelection( aSelection );
399 catch( const uno::Exception& ) {}
401 return bRet;
404 // functor for sending child events (no stand-alone function, they are maybe not inlined)
405 class AccessibleTextHelper_OffsetChildIndex : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void >
407 public:
408 AccessibleTextHelper_OffsetChildIndex( sal_Int32 nDifference ) : mnDifference(nDifference) {}
409 void operator()( ::accessibility::AccessibleEditableTextPara& rPara )
411 rPara.SetIndexInParent( rPara.GetIndexInParent() + mnDifference );
414 private:
415 const sal_Int32 mnDifference;
418 void AccessibleTextHelper_Impl::SetStartIndex( sal_Int32 nOffset )
420 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
422 sal_Int32 nOldOffset( mnStartIndex );
424 mnStartIndex = nOffset;
426 if( nOldOffset != nOffset )
428 // update children
429 AccessibleTextHelper_OffsetChildIndex aFunctor( nOffset - nOldOffset );
431 ::std::for_each( maParaManager.begin(), maParaManager.end(),
432 AccessibleParaManager::WeakChildAdapter< AccessibleTextHelper_OffsetChildIndex > (aFunctor) );
436 void AccessibleTextHelper_Impl::SetAdditionalChildStates( const VectorOfStates& rChildStates )
438 maParaManager.SetAdditionalChildStates( rChildStates );
441 const AccessibleTextHelper_Impl::VectorOfStates& AccessibleTextHelper_Impl::GetAdditionalChildStates() const
443 return maParaManager.GetAdditionalChildStates();
446 void AccessibleTextHelper_Impl::SetChildFocus( sal_Int32 nChild, sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException))
448 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
450 if( bHaveFocus )
452 if( mbThisHasFocus )
453 SetShapeFocus( sal_False );
455 maParaManager.SetFocus( nChild );
457 // we just received the focus, also send caret event then
458 UpdateSelection();
460 DBG_TRACE1("AccessibleTextHelper_Impl::SetChildFocus(): Paragraph %d received focus", nChild );
462 else
464 maParaManager.SetFocus( -1 );
466 DBG_TRACE1("AccessibleTextHelper_Impl::SetChildFocus(): Paragraph %d lost focus", nChild );
468 if( mbGroupHasFocus )
469 SetShapeFocus( sal_True );
473 void AccessibleTextHelper_Impl::ChangeChildFocus( sal_Int32 nNewChild ) SAL_THROW((::com::sun::star::uno::RuntimeException))
475 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
477 if( mbThisHasFocus )
478 SetShapeFocus( sal_False );
480 mbGroupHasFocus = sal_True;
481 maParaManager.SetFocus( nNewChild );
483 DBG_TRACE1("AccessibleTextHelper_Impl::ChangeChildFocus(): Paragraph %d received focus", nNewChild );
486 void AccessibleTextHelper_Impl::SetShapeFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException))
488 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
490 sal_Bool bOldFocus( mbThisHasFocus );
492 mbThisHasFocus = bHaveFocus;
494 if( bOldFocus != bHaveFocus )
496 if( bHaveFocus )
498 GotPropertyEvent( uno::makeAny(AccessibleStateType::FOCUSED), AccessibleEventId::STATE_CHANGED );
499 DBG_TRACE("AccessibleTextHelper_Impl::SetShapeFocus(): Parent object received focus" );
501 else
503 LostPropertyEvent( uno::makeAny(AccessibleStateType::FOCUSED), AccessibleEventId::STATE_CHANGED );
504 DBG_TRACE("AccessibleTextHelper_Impl::SetShapeFocus(): Parent object lost focus" );
509 void AccessibleTextHelper_Impl::SetFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException))
511 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
513 sal_Bool bOldFocus( mbGroupHasFocus );
515 mbGroupHasFocus = bHaveFocus;
517 if( IsActive() )
521 // find the one with the cursor and get/set focus accordingly
522 ESelection aSelection;
523 if( GetEditViewForwarder().GetSelection( aSelection ) )
524 SetChildFocus( aSelection.nEndPara, bHaveFocus );
526 catch( const uno::Exception& ) {}
528 else if( bOldFocus != bHaveFocus )
530 SetShapeFocus( bHaveFocus );
533 DBG_TRACE2("AccessibleTextHelper_Impl::SetFocus: focus changed, Object %d, state: %s", this, bHaveFocus ? "focused" : "not focused");
536 sal_Bool AccessibleTextHelper_Impl::HaveFocus() SAL_THROW((::com::sun::star::uno::RuntimeException))
538 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
540 // No locking of solar mutex here, since we rely on the fact
541 // that sal_Bool access is atomic
542 return mbThisHasFocus;
545 sal_Bool AccessibleTextHelper_Impl::IsActive() const SAL_THROW((uno::RuntimeException))
547 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
551 SvxEditSource& rEditSource = GetEditSource();
552 SvxEditViewForwarder* pViewForwarder = rEditSource.GetEditViewForwarder();
554 if( !pViewForwarder )
555 return sal_False;
557 if( pViewForwarder->IsValid() )
558 return sal_True;
559 else
560 return sal_False;
562 catch( const uno::RuntimeException& )
564 return sal_False;
568 void AccessibleTextHelper_Impl::UpdateSelection()
570 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
574 ESelection aSelection;
575 if( GetEditViewForwarder().GetSelection( aSelection ) )
577 if( !maLastSelection.IsEqual( aSelection ) &&
578 aSelection.nEndPara < maParaManager.GetNum() )
580 // #103998# Not that important, changed from assertion to trace
581 if( mbThisHasFocus )
583 DBG_TRACE("AccessibleTextHelper_Impl::UpdateSelection(): Parent has focus!");
586 USHORT nMaxValidParaIndex( static_cast< USHORT >( GetTextForwarder().GetParagraphCount() ) - 1 );
588 // notify all affected paragraphs (TODO: may be suboptimal,
589 // since some paragraphs might stay selected)
590 if( maLastSelection.nStartPara != EE_PARA_NOT_FOUND )
592 // Did the caret move from one paragraph to another?
593 // #100530# no caret events if not focused.
594 if( mbGroupHasFocus &&
595 maLastSelection.nEndPara != aSelection.nEndPara )
597 if( maLastSelection.nEndPara < maParaManager.GetNum() )
599 maParaManager.FireEvent( ::std::min( maLastSelection.nEndPara, nMaxValidParaIndex ),
600 ::std::min( maLastSelection.nEndPara, nMaxValidParaIndex )+1,
601 AccessibleEventId::CARET_CHANGED,
602 uno::makeAny(static_cast<sal_Int32>(-1)),
603 uno::makeAny(static_cast<sal_Int32>(maLastSelection.nEndPos)) );
606 ChangeChildFocus( aSelection.nEndPara );
608 DBG_TRACE3("AccessibleTextHelper_Impl::UpdateSelection(): focus changed, Object: %d, Paragraph: %d, Last paragraph: %d",
609 this, aSelection.nEndPara, maLastSelection.nEndPara);
613 // #100530# no caret events if not focused.
614 if( mbGroupHasFocus )
616 uno::Any aOldCursor;
618 // #i13705# The old cursor can only contain valid
619 // values if it's the same paragraph!
620 if( maLastSelection.nStartPara != EE_PARA_NOT_FOUND &&
621 maLastSelection.nEndPara == aSelection.nEndPara )
623 aOldCursor <<= static_cast<sal_Int32>(maLastSelection.nEndPos);
625 else
627 aOldCursor <<= static_cast<sal_Int32>(-1);
630 maParaManager.FireEvent( aSelection.nEndPara,
631 aSelection.nEndPara+1,
632 AccessibleEventId::CARET_CHANGED,
633 uno::makeAny(static_cast<sal_Int32>(aSelection.nEndPos)),
634 aOldCursor );
637 DBG_TRACE5("AccessibleTextHelper_Impl::UpdateSelection(): caret changed, Object: %d, New pos: %d, Old pos: %d, New para: %d, Old para: %d",
638 this, aSelection.nEndPos, maLastSelection.nEndPos, aSelection.nEndPara, maLastSelection.nEndPara);
640 // #108947# Sort new range before calling FireEvent
641 ::std::pair< xub_StrLen, xub_StrLen > sortedSelection(
642 makeSortedPair(::std::min( aSelection.nStartPara, nMaxValidParaIndex ),
643 ::std::min( aSelection.nEndPara, nMaxValidParaIndex ) ) );
645 // #108947# Sort last range before calling FireEvent
646 ::std::pair< xub_StrLen, xub_StrLen > sortedLastSelection(
647 makeSortedPair(::std::min( maLastSelection.nStartPara, nMaxValidParaIndex ),
648 ::std::min( maLastSelection.nEndPara, nMaxValidParaIndex ) ) );
650 // --> OD 2005-12-15 #i27299#
651 // event TEXT_SELECTION_CHANGED has to be submitted.
652 const sal_Int16 nTextSelChgEventId =
653 AccessibleEventId::TEXT_SELECTION_CHANGED;
654 // <--
655 // #107037# notify selection change
656 if( maLastSelection.nStartPara == EE_PARA_NOT_FOUND )
658 // last selection is undefined
659 // --> OD 2005-12-15 #i27299# - use method <ESelection::HasRange()>
660 if ( aSelection.HasRange() )
661 // <--
663 // selection was undefined, now is on
664 maParaManager.FireEvent( sortedSelection.first,
665 sortedSelection.second+1,
666 nTextSelChgEventId );
669 else
671 // last selection is valid
672 // --> OD 2005-12-15 #i27299# - use method <ESelection::HasRange()>
673 if ( maLastSelection.HasRange() &&
674 !aSelection.HasRange() )
675 // <--
677 // selection was on, now is empty
678 maParaManager.FireEvent( sortedLastSelection.first,
679 sortedLastSelection.second+1,
680 nTextSelChgEventId );
682 // --> OD 2005-12-15 #i27299# - use method <ESelection::HasRange()>
683 else if( !maLastSelection.HasRange() &&
684 aSelection.HasRange() )
685 // <--
687 // selection was empty, now is on
688 maParaManager.FireEvent( sortedSelection.first,
689 sortedSelection.second+1,
690 nTextSelChgEventId );
692 // --> OD 2005-12-15 #i27299#
693 // - no event TEXT_SELECTION_CHANGED event, if new and
694 // last selection are empty.
695 else if ( maLastSelection.HasRange() &&
696 aSelection.HasRange() )
697 // <--
699 // --> OD 2005-12-16 #i27299#
700 // - send event TEXT_SELECTION_CHANGED for difference
701 // between last and new selection.
702 // // selection was on, now is different: take union of ranges
703 // maParaManager.FireEvent( ::std::min(sortedSelection.first,
704 // sortedLastSelection.second),
705 // ::std::max(sortedSelection.first,
706 // sortedLastSelection.second)+1,
707 // nTextSelChgEventId );
708 // use sorted last and new selection
709 ESelection aTmpLastSel( maLastSelection );
710 aTmpLastSel.Adjust();
711 ESelection aTmpSel( aSelection );
712 aTmpSel.Adjust();
713 // first submit event for new and changed selection
714 sal_uInt32 nPara = aTmpSel.nStartPara;
715 for ( ; nPara <= aTmpSel.nEndPara; ++nPara )
717 if ( nPara < aTmpLastSel.nStartPara ||
718 nPara > aTmpLastSel.nEndPara )
720 // new selection on paragraph <nPara>
721 maParaManager.FireEvent( nPara,
722 nTextSelChgEventId );
724 else
726 // check for changed selection on paragraph <nPara>
727 const xub_StrLen nParaStartPos =
728 nPara == aTmpSel.nStartPara
729 ? aTmpSel.nStartPos : 0;
730 const xub_StrLen nParaEndPos =
731 nPara == aTmpSel.nEndPara
732 ? aTmpSel.nEndPos : STRING_LEN;
733 const xub_StrLen nLastParaStartPos =
734 nPara == aTmpLastSel.nStartPara
735 ? aTmpLastSel.nStartPos : 0;
736 const xub_StrLen nLastParaEndPos =
737 nPara == aTmpLastSel.nEndPara
738 ? aTmpLastSel.nEndPos : STRING_LEN;
739 if ( nParaStartPos != nLastParaStartPos ||
740 nParaEndPos != nLastParaEndPos )
742 maParaManager.FireEvent(
743 nPara, nTextSelChgEventId );
747 // second submit event for 'old' selections
748 nPara = aTmpLastSel.nStartPara;
749 for ( ; nPara <= aTmpLastSel.nEndPara; ++nPara )
751 if ( nPara < aTmpSel.nStartPara ||
752 nPara > aTmpSel.nEndPara )
754 maParaManager.FireEvent( nPara,
755 nTextSelChgEventId );
761 maLastSelection = aSelection;
765 // no selection? no update actions
766 catch( const uno::RuntimeException& ) {}
769 void AccessibleTextHelper_Impl::ShutdownEditSource() SAL_THROW((uno::RuntimeException))
771 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
773 // This should only be called with solar mutex locked, i.e. from the main office thread
775 // This here is somewhat clumsy: As soon as our children have
776 // a NULL EditSource (maParaManager.SetEditSource()), they
777 // enter the disposed state and cannot be reanimated. Thus, it
778 // is unavoidable and a hard requirement to let go and create
779 // from scratch each and every child.
781 // invalidate children
782 maParaManager.Dispose();
783 maParaManager.SetNum(0);
785 // lost all children
786 if( mxFrontEnd.is() )
787 FireEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN);
789 // quit listen on stale edit source
790 if( maEditSource.IsValid() )
791 EndListening( maEditSource.GetBroadcaster() );
793 maEditSource.SetEditSource( ::std::auto_ptr< SvxEditSource >(NULL) );
796 void AccessibleTextHelper_Impl::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException))
798 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
800 // This should only be called with solar mutex locked, i.e. from the main office thread
802 // shutdown old edit source
803 ShutdownEditSource();
805 // set new edit source
806 maEditSource.SetEditSource( pEditSource );
808 // init child vector to the current child count
809 if( maEditSource.IsValid() )
811 maParaManager.SetNum( GetTextForwarder().GetParagraphCount() );
813 // listen on new edit source
814 StartListening( maEditSource.GetBroadcaster() );
816 UpdateVisibleChildren();
820 void AccessibleTextHelper_Impl::SetOffset( const Point& rPoint )
822 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
824 // guard against non-atomic access to maOffset data structure
826 ::osl::MutexGuard aGuard( maMutex );
827 maOffset = rPoint;
830 maParaManager.SetEEOffset( rPoint );
832 // in all cases, check visibility afterwards.
833 UpdateVisibleChildren();
834 UpdateBoundRect();
837 void AccessibleTextHelper_Impl::UpdateVisibleChildren( bool bBroadcastEvents )
839 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
843 SvxTextForwarder& rCacheTF = GetTextForwarder();
844 SvxViewForwarder& rCacheVF = GetViewForwarder();
846 Rectangle aViewArea = rCacheVF.GetVisArea();
848 if( IsActive() )
850 // maybe the edit view scrolls, adapt aViewArea
851 Rectangle aEditViewArea = GetEditViewForwarder().GetVisArea();
852 aViewArea += aEditViewArea.TopLeft();
854 // now determine intersection
855 aViewArea.Intersection( aEditViewArea );
858 Rectangle aTmpBB, aParaBB;
859 sal_Bool bFirstChild = sal_True;
860 sal_Int32 nCurrPara;
861 sal_Int32 nParas=rCacheTF.GetParagraphCount();
863 mnFirstVisibleChild = -1;
864 mnLastVisibleChild = -2;
866 for( nCurrPara=0; nCurrPara<nParas; ++nCurrPara )
868 DBG_ASSERT(nCurrPara >= 0 && nCurrPara <= USHRT_MAX,
869 "AccessibleTextHelper_Impl::UpdateVisibleChildren: index value overflow");
871 aTmpBB = rCacheTF.GetParaBounds( static_cast< USHORT >( nCurrPara ) );
873 // convert to screen coordinates
874 aParaBB = ::accessibility::AccessibleEditableTextPara::LogicToPixel( aTmpBB, rCacheTF.GetMapMode(), rCacheVF );
876 if( aParaBB.IsOver( aViewArea ) )
878 // at least partially visible
879 if( bFirstChild )
881 bFirstChild = sal_False;
882 mnFirstVisibleChild = nCurrPara;
885 mnLastVisibleChild = nCurrPara;
887 // child not yet created?
888 ::accessibility::AccessibleParaManager::WeakChild aChild( maParaManager.GetChild(nCurrPara) );
889 if( aChild.second.Width == 0 &&
890 aChild.second.Height == 0 &&
891 mxFrontEnd.is() &&
892 bBroadcastEvents )
894 GotPropertyEvent( uno::makeAny( maParaManager.CreateChild( nCurrPara - mnFirstVisibleChild,
895 mxFrontEnd, GetEditSource(), nCurrPara ).first ),
896 AccessibleEventId::CHILD );
899 else
901 // not or no longer visible
902 if( maParaManager.IsReferencable( nCurrPara ) )
904 if( bBroadcastEvents )
905 LostPropertyEvent( uno::makeAny( maParaManager.GetChild( nCurrPara ).first.get().getRef() ),
906 AccessibleEventId::CHILD );
908 // clear reference
909 maParaManager.Release( nCurrPara );
914 catch( const uno::Exception& )
916 DBG_ERROR("AccessibleTextHelper_Impl::UpdateVisibleChildren error while determining visible children");
918 // something failed - currently no children
919 mnFirstVisibleChild = -1;
920 mnLastVisibleChild = -2;
921 maParaManager.SetNum(0);
923 // lost all children
924 if( bBroadcastEvents )
925 FireEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN);
929 // functor for checking changes in paragraph bounding boxes (no stand-alone function, maybe not inlined)
930 class AccessibleTextHelper_UpdateChildBounds : public ::std::unary_function< const ::accessibility::AccessibleParaManager::WeakChild&,
931 ::accessibility::AccessibleParaManager::WeakChild >
933 public:
934 AccessibleTextHelper_UpdateChildBounds( AccessibleTextHelper_Impl& rImpl ) : mrImpl(rImpl) {}
935 ::accessibility::AccessibleParaManager::WeakChild operator()( const ::accessibility::AccessibleParaManager::WeakChild& rChild )
937 // retrieve hard reference from weak one
938 ::accessibility::AccessibleParaManager::WeakPara::HardRefType aHardRef( rChild.first.get() );
940 if( aHardRef.is() )
942 awt::Rectangle aNewRect = aHardRef->getBounds();
943 const awt::Rectangle& aOldRect = rChild.second;
945 if( aNewRect.X != aOldRect.X ||
946 aNewRect.Y != aOldRect.Y ||
947 aNewRect.Width != aOldRect.Width ||
948 aNewRect.Height != aOldRect.Height )
950 // visible data changed
951 aHardRef->FireEvent( AccessibleEventId::BOUNDRECT_CHANGED );
953 // update internal bounds
954 return ::accessibility::AccessibleParaManager::WeakChild( rChild.first, aNewRect );
958 // identity transform
959 return rChild;
962 private:
963 AccessibleTextHelper_Impl& mrImpl;
966 void AccessibleTextHelper_Impl::UpdateBoundRect()
968 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
970 // send BOUNDRECT_CHANGED to affected children
971 AccessibleTextHelper_UpdateChildBounds aFunctor( *this );
972 ::std::transform( maParaManager.begin(), maParaManager.end(), maParaManager.begin(), aFunctor );
975 #ifdef DBG_UTIL
976 void AccessibleTextHelper_Impl::CheckInvariants() const
978 if( mnFirstVisibleChild >= 0 &&
979 mnFirstVisibleChild > mnLastVisibleChild )
981 DBG_ERROR( "AccessibleTextHelper: range invalid" );
984 #endif
986 // functor for sending child events (no stand-alone function, they are maybe not inlined)
987 class AccessibleTextHelper_LostChildEvent : public ::std::unary_function< const ::accessibility::AccessibleParaManager::WeakChild&, void >
989 public:
990 AccessibleTextHelper_LostChildEvent( AccessibleTextHelper_Impl& rImpl ) : mrImpl(rImpl) {}
991 void operator()( const ::accessibility::AccessibleParaManager::WeakChild& rPara )
993 // retrieve hard reference from weak one
994 ::accessibility::AccessibleParaManager::WeakPara::HardRefType aHardRef( rPara.first.get() );
996 if( aHardRef.is() )
997 mrImpl.FireEvent(AccessibleEventId::CHILD, uno::Any(), uno::makeAny( aHardRef.getRef() ) );
1000 private:
1001 AccessibleTextHelper_Impl& mrImpl;
1004 void AccessibleTextHelper_Impl::ParagraphsMoved( sal_Int32 nFirst, sal_Int32 nMiddle, sal_Int32 nLast )
1006 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1008 const sal_Int32 nParas = GetTextForwarder().GetParagraphCount();
1010 /* rotate paragraphs
1011 * =================
1013 * Three cases:
1015 * 1.
1016 * ... nParagraph ... nParam1 ... nParam2 ...
1017 * |______________[xxxxxxxxxxx]
1018 * becomes
1019 * [xxxxxxxxxxx]|______________
1021 * tail is 0
1023 * 2.
1024 * ... nParam1 ... nParagraph ... nParam2 ...
1025 * [xxxxxxxxxxx|xxxxxxxxxxxxxx]____________
1026 * becomes
1027 * ____________[xxxxxxxxxxx|xxxxxxxxxxxxxx]
1029 * tail is nParagraph - nParam1
1031 * 3.
1032 * ... nParam1 ... nParam2 ... nParagraph ...
1033 * [xxxxxxxxxxx]___________|____________
1034 * becomes
1035 * ___________|____________[xxxxxxxxxxx]
1037 * tail is nParam2 - nParam1
1040 // sort nParagraph, nParam1 and nParam2 in ascending order, calc range
1041 if( nMiddle < nFirst )
1043 ::std::swap(nFirst, nMiddle);
1045 else if( nMiddle < nLast )
1047 nLast = nLast + nMiddle - nFirst;
1049 else
1051 ::std::swap(nMiddle, nLast);
1052 nLast = nLast + nMiddle - nFirst;
1055 if( nFirst < nParas && nMiddle < nParas && nLast < nParas )
1057 // since we have no "paragraph index
1058 // changed" event on UAA, remove
1059 // [first,last] and insert again later (in
1060 // UpdateVisibleChildren)
1062 // maParaManager.Rotate( nFirst, nMiddle, nLast );
1064 // send CHILD_EVENT to affected children
1065 ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator begin = maParaManager.begin();
1066 ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator end = begin;
1068 ::std::advance( begin, nFirst );
1069 ::std::advance( end, nLast+1 );
1071 // TODO: maybe optimize here in the following way. If the
1072 // number of removed children exceeds a certain threshold,
1073 // use INVALIDATE_CHILDREN
1074 AccessibleTextHelper_LostChildEvent aFunctor( *this );
1076 ::std::for_each( begin, end, aFunctor );
1078 maParaManager.Release(nFirst, nLast+1);
1079 // should be no need for UpdateBoundRect, since all affected children are cleared.
1083 // functor for sending child events (no stand-alone function, they are maybe not inlined)
1084 class AccessibleTextHelper_ChildrenTextChanged : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void >
1086 public:
1087 void operator()( ::accessibility::AccessibleEditableTextPara& rPara )
1089 rPara.TextChanged();
1093 /** functor processing queue events
1095 Reacts on TEXT_HINT_PARAINSERTED/REMOVED events and stores
1096 their content
1098 class AccessibleTextHelper_QueueFunctor : public ::std::unary_function< const SfxHint*, void >
1100 public:
1101 AccessibleTextHelper_QueueFunctor() :
1102 mnParasChanged( 0 ),
1103 mnParaIndex(-1),
1104 mnHintId(-1)
1106 void operator()( const SfxHint* pEvent )
1108 if( pEvent &&
1109 mnParasChanged != -1 )
1111 // determine hint type
1112 const TextHint* pTextHint = PTR_CAST( TextHint, pEvent );
1113 const SvxEditSourceHint* pEditSourceHint = PTR_CAST( SvxEditSourceHint, pEvent );
1115 if( !pEditSourceHint && pTextHint &&
1116 (pTextHint->GetId() == TEXT_HINT_PARAINSERTED ||
1117 pTextHint->GetId() == TEXT_HINT_PARAREMOVED ) )
1119 if( pTextHint->GetValue() == EE_PARA_ALL )
1121 mnParasChanged = -1;
1123 else
1125 mnHintId = pTextHint->GetId();
1126 mnParaIndex = pTextHint->GetValue();
1127 ++mnParasChanged;
1133 /** Query number of paragraphs changed during queue processing.
1135 @return number of changed paragraphs, -1 for
1136 "every paragraph changed"
1138 int GetNumberOfParasChanged() { return mnParasChanged; }
1139 /** Query index of last added/removed paragraph
1141 @return index of lastly added paragraphs, -1 for none
1142 added so far.
1144 int GetParaIndex() { return mnParaIndex; }
1145 /** Query hint id of last interesting event
1147 @return hint id of last interesting event (REMOVED/INSERTED).
1149 int GetHintId() { return mnHintId; }
1151 private:
1152 /** number of paragraphs changed during queue processing. -1 for
1153 "every paragraph changed"
1155 int mnParasChanged;
1156 /// index of paragraph added/removed last
1157 int mnParaIndex;
1158 /// TextHint ID (removed/inserted) of last interesting event
1159 int mnHintId;
1162 void AccessibleTextHelper_Impl::ProcessQueue()
1164 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1166 // inspect queue for paragraph insert/remove events. If there
1167 // is exactly _one_ of those in the queue, and the number of
1168 // paragraphs has changed by exactly one, use that event to
1169 // determine a priori which paragraph was added/removed. This
1170 // is necessary, since I must sync right here with the
1171 // EditEngine state (number of paragraphs etc.), since I'm
1172 // potentially sending listener events right away.
1173 AccessibleTextHelper_QueueFunctor aFunctor;
1174 maEventQueue.ForEach( aFunctor );
1176 const sal_Int32 nNewParas( GetTextForwarder().GetParagraphCount() );
1177 const sal_Int32 nCurrParas( maParaManager.GetNum() );
1179 // whether every paragraph already is updated (no need to
1180 // repeat that later on, e.g. for PARA_MOVED events)
1181 bool bEverythingUpdated( false );
1183 if( labs( nNewParas - nCurrParas ) == 1 &&
1184 aFunctor.GetNumberOfParasChanged() == 1 )
1186 // #103483# Exactly one paragraph added/removed. This is
1187 // the normal case, optimize event handling here.
1189 if( aFunctor.GetHintId() == TEXT_HINT_PARAINSERTED )
1191 // update num of paras
1192 maParaManager.SetNum( nNewParas );
1194 // release everything from the insertion position until the end
1195 maParaManager.Release(aFunctor.GetParaIndex(), nCurrParas);
1197 // TODO: Clarify whether this behaviour _really_ saves
1198 // anybody anything!
1199 // update children, _don't_ broadcast
1200 UpdateVisibleChildren( false );
1201 UpdateBoundRect();
1203 // send insert event
1204 // #109864# Enforce creation of this paragraph
1207 GotPropertyEvent( uno::makeAny( getAccessibleChild( aFunctor.GetParaIndex() -
1208 mnFirstVisibleChild + GetStartIndex() ) ),
1209 AccessibleEventId::CHILD );
1211 catch( const uno::Exception& )
1213 DBG_ERROR("AccessibleTextHelper_Impl::ProcessQueue: could not create new paragraph");
1216 else if( aFunctor.GetHintId() == TEXT_HINT_PARAREMOVED )
1218 ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator begin = maParaManager.begin();
1219 ::std::advance( begin, aFunctor.GetParaIndex() );
1220 ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator end = begin;
1221 ::std::advance( end, 1 );
1223 // #i61812# remember para to be removed for later notification
1224 // AFTER the new state is applied (that after the para got removed)
1225 ::uno::Reference< XAccessible > xPara;
1226 ::accessibility::AccessibleParaManager::WeakPara::HardRefType aHardRef( begin->first.get() );
1227 if( aHardRef.is() )
1228 xPara = ::uno::Reference< XAccessible >( aHardRef.getRef(), ::uno::UNO_QUERY );
1230 // release everything from the remove position until the end
1231 maParaManager.Release(aFunctor.GetParaIndex(), nCurrParas);
1233 // update num of paras
1234 maParaManager.SetNum( nNewParas );
1236 // TODO: Clarify whether this behaviour _really_ saves
1237 // anybody anything!
1238 // update children, _don't_ broadcast
1239 UpdateVisibleChildren( false );
1240 UpdateBoundRect();
1242 // #i61812# notification for removed para
1243 if (xPara.is())
1244 FireEvent(AccessibleEventId::CHILD, uno::Any(), uno::makeAny( xPara) );
1246 #ifdef DBG_UTIL
1247 else
1248 DBG_ERROR("AccessibleTextHelper_Impl::ProcessQueue() invalid hint id");
1249 #endif
1251 else if( nNewParas != nCurrParas )
1253 // release all paras
1254 maParaManager.Release(0, nCurrParas);
1256 // update num of paras
1257 maParaManager.SetNum( nNewParas );
1259 // #109864# create from scratch, don't broadcast
1260 UpdateVisibleChildren( false );
1261 UpdateBoundRect();
1263 // number of paragraphs somehow changed - but we have no
1264 // chance determining how. Thus, throw away everything and
1265 // create from scratch.
1266 // (child events should be broadcast after the changes are done...)
1267 FireEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN);
1269 // no need for further updates later on
1270 bEverythingUpdated = true;
1273 while( !maEventQueue.IsEmpty() )
1275 ::std::auto_ptr< SfxHint > pHint( maEventQueue.PopFront() );
1276 if( pHint.get() )
1278 const SfxHint& rHint = *(pHint.get());
1280 // determine hint type
1281 const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
1282 const SfxSimpleHint* pSimpleHint = PTR_CAST( SfxSimpleHint, &rHint );
1283 const TextHint* pTextHint = PTR_CAST( TextHint, &rHint );
1284 const SvxViewHint* pViewHint = PTR_CAST( SvxViewHint, &rHint );
1285 const SvxEditSourceHint* pEditSourceHint = PTR_CAST( SvxEditSourceHint, &rHint );
1289 const sal_Int32 nParas = GetTextForwarder().GetParagraphCount();
1291 if( pEditSourceHint )
1293 switch( pEditSourceHint->GetId() )
1295 case EDITSOURCE_HINT_PARASMOVED:
1297 DBG_ASSERT( pEditSourceHint->GetStartValue() < GetTextForwarder().GetParagraphCount() &&
1298 pEditSourceHint->GetEndValue() < GetTextForwarder().GetParagraphCount(),
1299 "AccessibleTextHelper_Impl::NotifyHdl: Invalid notification");
1301 if( !bEverythingUpdated )
1303 ParagraphsMoved(pEditSourceHint->GetStartValue(),
1304 pEditSourceHint->GetValue(),
1305 pEditSourceHint->GetEndValue());
1307 // in all cases, check visibility afterwards.
1308 UpdateVisibleChildren();
1310 break;
1313 case EDITSOURCE_HINT_SELECTIONCHANGED:
1314 // notify listeners
1317 UpdateSelection();
1319 // maybe we're not in edit mode (this is not an error)
1320 catch( const uno::Exception& ) {}
1321 break;
1324 else if( pTextHint )
1326 switch( pTextHint->GetId() )
1328 case TEXT_HINT_MODIFIED:
1330 // notify listeners
1331 sal_Int32 nPara( pTextHint->GetValue() );
1333 // #108900# Delegate change event to children
1334 AccessibleTextHelper_ChildrenTextChanged aNotifyChildrenFunctor;
1336 if( nPara == static_cast<sal_Int32>(EE_PARA_ALL) )
1338 // #108900# Call every child
1339 ::std::for_each( maParaManager.begin(), maParaManager.end(),
1340 AccessibleParaManager::WeakChildAdapter< AccessibleTextHelper_ChildrenTextChanged > (aNotifyChildrenFunctor) );
1342 else
1343 if( nPara < nParas )
1345 // #108900# Call child at index nPara
1346 ::std::for_each( maParaManager.begin()+nPara, maParaManager.begin()+nPara+1,
1347 AccessibleParaManager::WeakChildAdapter< AccessibleTextHelper_ChildrenTextChanged > (aNotifyChildrenFunctor) );
1349 break;
1352 case TEXT_HINT_PARAINSERTED:
1353 // already happened above
1354 break;
1356 case TEXT_HINT_PARAREMOVED:
1357 // already happened above
1358 break;
1360 case TEXT_HINT_TEXTHEIGHTCHANGED:
1361 // visibility changed, done below
1362 break;
1364 case TEXT_HINT_VIEWSCROLLED:
1365 // visibility changed, done below
1366 break;
1369 // in all cases, check visibility afterwards.
1370 UpdateVisibleChildren();
1371 UpdateBoundRect();
1373 else if( pViewHint )
1375 switch( pViewHint->GetHintType() )
1377 case SvxViewHint::SVX_HINT_VIEWCHANGED:
1378 // just check visibility
1379 UpdateVisibleChildren();
1380 UpdateBoundRect();
1381 break;
1384 else if( pSdrHint )
1386 switch( pSdrHint->GetKind() )
1388 case HINT_BEGEDIT:
1390 // change children state
1391 maParaManager.SetActive();
1393 // per definition, edit mode text has the focus
1394 SetFocus( sal_True );
1395 break;
1398 case HINT_ENDEDIT:
1400 // focused child now looses focus
1401 ESelection aSelection;
1402 if( GetEditViewForwarder().GetSelection( aSelection ) )
1403 SetChildFocus( aSelection.nEndPara, sal_False );
1405 // change children state
1406 maParaManager.SetActive( sal_False );
1408 maLastSelection = ESelection( EE_PARA_NOT_FOUND, EE_PARA_NOT_FOUND,
1409 EE_PARA_NOT_FOUND, EE_PARA_NOT_FOUND);
1410 break;
1412 default:
1413 break;
1416 // it's VITAL to keep the SfxSimpleHint last! It's the base of some classes above!
1417 else if( pSimpleHint )
1419 switch( pSimpleHint->GetId() )
1421 case SFX_HINT_DYING:
1422 // edit source is dying under us, become defunc then
1425 // make edit source inaccessible
1426 // Note: cannot destroy it here, since we're called from there!
1427 ShutdownEditSource();
1429 catch( const uno::Exception& ) {}
1431 break;
1435 catch( const uno::Exception& )
1437 #ifdef DBG_UTIL
1438 OSL_TRACE("AccessibleTextHelper_Impl::ProcessQueue: Unhandled exception.");
1439 #endif
1445 void AccessibleTextHelper_Impl::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
1447 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1449 // precondition: solar mutex locked
1450 DBG_TESTSOLARMUTEX();
1452 // precondition: not in a recursion
1453 if( mbInNotify )
1454 return;
1456 mbInNotify = sal_True;
1458 // determine hint type
1459 const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
1460 const SfxSimpleHint* pSimpleHint = PTR_CAST( SfxSimpleHint, &rHint );
1461 const TextHint* pTextHint = PTR_CAST( TextHint, &rHint );
1462 const SvxViewHint* pViewHint = PTR_CAST( SvxViewHint, &rHint );
1463 const SvxEditSourceHint* pEditSourceHint = PTR_CAST( SvxEditSourceHint, &rHint );
1467 // Process notification event
1468 if( pEditSourceHint )
1470 maEventQueue.Append( *pEditSourceHint );
1471 // --> OD 2005-12-19 #i27299#
1472 if( maEventOpenFrames == 0 )
1473 ProcessQueue();
1474 // <--
1476 else if( pTextHint )
1478 switch( pTextHint->GetId() )
1480 case TEXT_HINT_BLOCKNOTIFICATION_END:
1481 case TEXT_HINT_INPUT_END:
1482 --maEventOpenFrames;
1484 if( maEventOpenFrames == 0 )
1486 // #103483#
1487 /* All information should have arrived
1488 * now, process queue. As stated in the
1489 * above bug, we can often avoid throwing
1490 * away all paragraphs by looking forward
1491 * in the event queue (searching for
1492 * PARAINSERT/REMOVE events). Furthermore,
1493 * processing the event queue only at the
1494 * end of an interaction cycle, ensures
1495 * that the EditEngine state and the
1496 * AccessibleText state are the same
1497 * (well, mostly. If there are _multiple_
1498 * interaction cycles in the EE queues, it
1499 * can still happen that EE state is
1500 * different. That's so to say broken by
1501 * design with that delayed EE event
1502 * concept).
1504 ProcessQueue();
1506 break;
1508 case TEXT_HINT_BLOCKNOTIFICATION_START:
1509 case TEXT_HINT_INPUT_START:
1510 ++maEventOpenFrames;
1511 // --> OD 2005-12-19 #i27299# - no FALLTROUGH
1512 // reason: event will not be processes, thus appending
1513 // the event isn't necessary.
1514 break;
1515 // <--
1516 default:
1517 maEventQueue.Append( *pTextHint );
1518 // --> OD 2005-12-19 #i27299#
1519 if( maEventOpenFrames == 0 )
1520 ProcessQueue();
1521 // <--
1522 break;
1525 else if( pViewHint )
1527 maEventQueue.Append( *pViewHint );
1529 // process visibility right away, if not within an
1530 // open EE notification frame. Otherwise, event
1531 // processing would be delayed until next EE
1532 // notification sequence.
1533 if( maEventOpenFrames == 0 )
1534 ProcessQueue();
1536 else if( pSdrHint )
1538 maEventQueue.Append( *pSdrHint );
1540 // process drawing layer events right away, if not
1541 // within an open EE notification frame. Otherwise,
1542 // event processing would be delayed until next EE
1543 // notification sequence.
1544 if( maEventOpenFrames == 0 )
1545 ProcessQueue();
1547 // it's VITAL to keep the SfxSimpleHint last! It's the base of some classes above!
1548 else if( pSimpleHint )
1550 // handle this event _at once_, because after that, objects are invalid
1551 switch( pSimpleHint->GetId() )
1553 case SFX_HINT_DYING:
1554 // edit source is dying under us, become defunc then
1555 maEventQueue.Clear();
1558 // make edit source inaccessible
1559 // Note: cannot destroy it here, since we're called from there!
1560 ShutdownEditSource();
1562 catch( const uno::Exception& ) {}
1564 break;
1568 catch( const uno::Exception& )
1570 #ifdef DBG_UTIL
1571 OSL_TRACE("AccessibleTextHelper_Impl::Notify: Unhandled exception.");
1572 #endif
1573 mbInNotify = sal_False;
1576 mbInNotify = sal_False;
1579 void AccessibleTextHelper_Impl::Dispose()
1581 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1583 if( getNotifierClientId() != -1 )
1587 // #106234# Unregister from EventNotifier
1588 ::comphelper::AccessibleEventNotifier::revokeClient( getNotifierClientId() );
1589 #ifdef DBG_UTIL
1590 OSL_TRACE( "AccessibleTextHelper_Impl disposed ID: %d", mnNotifierClientId );
1591 #endif
1593 catch( const uno::Exception& ) {}
1595 mnNotifierClientId = -1;
1600 // dispose children
1601 maParaManager.Dispose();
1603 catch( const uno::Exception& ) {}
1605 // quit listen on stale edit source
1606 if( maEditSource.IsValid() )
1607 EndListening( maEditSource.GetBroadcaster() );
1609 // clear references
1610 maEditSource.SetEditSource( ::std::auto_ptr< SvxEditSource >(NULL) );
1611 mxFrontEnd = NULL;
1614 void AccessibleTextHelper_Impl::FireEvent( const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue ) const
1616 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1618 // -- object locked --
1619 ::osl::ClearableMutexGuard aGuard( maMutex );
1621 AccessibleEventObject aEvent;
1623 DBG_ASSERT(mxFrontEnd.is(), "AccessibleTextHelper::FireEvent: no event source set" );
1625 if( mxFrontEnd.is() )
1626 aEvent = AccessibleEventObject(mxFrontEnd->getAccessibleContext(), nEventId, rNewValue, rOldValue);
1627 else
1628 aEvent = AccessibleEventObject(uno::Reference< uno::XInterface >(), nEventId, rNewValue, rOldValue);
1630 // no locking necessary, FireEvent internally copies listeners
1631 // if someone removes/adds in between Further locking,
1632 // actually, might lead to deadlocks, since we're calling out
1633 // of this object
1634 aGuard.clear();
1635 // -- until here --
1637 FireEvent(aEvent);
1640 void AccessibleTextHelper_Impl::FireEvent( const AccessibleEventObject& rEvent ) const
1642 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1644 // #102261# Call global queue for focus events
1645 if( rEvent.EventId == AccessibleStateType::FOCUSED )
1646 vcl::unohelper::NotifyAccessibleStateEventGlobally( rEvent );
1648 // #106234# Delegate to EventNotifier
1649 ::comphelper::AccessibleEventNotifier::addEvent( getNotifierClientId(),
1650 rEvent );
1653 // XAccessibleContext
1654 sal_Int32 SAL_CALL AccessibleTextHelper_Impl::getAccessibleChildCount() SAL_THROW((uno::RuntimeException))
1656 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1658 return mnLastVisibleChild - mnFirstVisibleChild + 1;
1661 uno::Reference< XAccessible > SAL_CALL AccessibleTextHelper_Impl::getAccessibleChild( sal_Int32 i ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException))
1663 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1665 i -= GetStartIndex();
1667 if( 0 > i || i >= getAccessibleChildCount() ||
1668 GetTextForwarder().GetParagraphCount() <= i )
1670 throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Invalid child index")), mxFrontEnd);
1673 DBG_ASSERT(mxFrontEnd.is(), "AccessibleTextHelper_Impl::UpdateVisibleChildren: no frontend set");
1675 if( mxFrontEnd.is() )
1676 return maParaManager.CreateChild( i, mxFrontEnd, GetEditSource(), mnFirstVisibleChild + i ).first;
1677 else
1678 return NULL;
1681 void SAL_CALL AccessibleTextHelper_Impl::addEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException))
1683 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1685 if( getNotifierClientId() != -1 )
1686 ::comphelper::AccessibleEventNotifier::addEventListener( getNotifierClientId(), xListener );
1689 void SAL_CALL AccessibleTextHelper_Impl::removeEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException))
1691 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1693 if( getNotifierClientId() != -1 )
1694 ::comphelper::AccessibleEventNotifier::removeEventListener( getNotifierClientId(), xListener );
1697 uno::Reference< XAccessible > SAL_CALL AccessibleTextHelper_Impl::getAccessibleAtPoint( const awt::Point& _aPoint ) SAL_THROW((uno::RuntimeException))
1699 DBG_CHKTHIS( AccessibleTextHelper_Impl, NULL );
1701 // make given position relative
1702 if( !mxFrontEnd.is() )
1703 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleTextHelper_Impl::getAccessibleAt: frontend invalid")), mxFrontEnd );
1705 uno::Reference< XAccessibleContext > xFrontEndContext = mxFrontEnd->getAccessibleContext();
1707 if( !xFrontEndContext.is() )
1708 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleTextHelper_Impl::getAccessibleAt: frontend invalid")), mxFrontEnd );
1710 uno::Reference< XAccessibleComponent > xFrontEndComponent( xFrontEndContext, uno::UNO_QUERY );
1712 if( !xFrontEndComponent.is() )
1713 throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleTextHelper_Impl::getAccessibleAt: frontend is no XAccessibleComponent")),
1714 mxFrontEnd );
1716 // #103862# No longer need to make given position relative
1717 Point aPoint( _aPoint.X, _aPoint.Y );
1719 // respect EditEngine offset to surrounding shape/cell
1720 aPoint -= GetOffset();
1722 // convert to EditEngine coordinate system
1723 SvxTextForwarder& rCacheTF = GetTextForwarder();
1724 Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) );
1726 // iterate over all visible children (including those not yet created)
1727 sal_Int32 nChild;
1728 for( nChild=mnFirstVisibleChild; nChild <= mnLastVisibleChild; ++nChild )
1730 DBG_ASSERT(nChild >= 0 && nChild <= USHRT_MAX,
1731 "AccessibleTextHelper_Impl::getAccessibleAt: index value overflow");
1733 Rectangle aParaBounds( rCacheTF.GetParaBounds( static_cast< USHORT > (nChild) ) );
1735 if( aParaBounds.IsInside( aLogPoint ) )
1736 return getAccessibleChild( nChild - mnFirstVisibleChild + GetStartIndex() );
1739 // found none
1740 return NULL;
1743 //------------------------------------------------------------------------
1745 // AccessibleTextHelper implementation (simply forwards to impl)
1747 //------------------------------------------------------------------------
1749 AccessibleTextHelper::AccessibleTextHelper( ::std::auto_ptr< SvxEditSource > pEditSource ) :
1750 mpImpl( new AccessibleTextHelper_Impl() )
1752 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1754 SetEditSource( pEditSource );
1757 AccessibleTextHelper::~AccessibleTextHelper()
1761 const SvxEditSource& AccessibleTextHelper::GetEditSource() const SAL_THROW((uno::RuntimeException))
1763 #ifdef DBG_UTIL
1764 mpImpl->CheckInvariants();
1766 const SvxEditSource& aEditSource = mpImpl->GetEditSource();
1768 mpImpl->CheckInvariants();
1770 return aEditSource;
1771 #else
1772 return mpImpl->GetEditSource();
1773 #endif
1776 void AccessibleTextHelper::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException))
1778 #ifdef DBG_UTIL
1779 // precondition: solar mutex locked
1780 DBG_TESTSOLARMUTEX();
1782 mpImpl->CheckInvariants();
1783 #endif
1785 mpImpl->SetEditSource( pEditSource );
1787 #ifdef DBG_UTIL
1788 mpImpl->CheckInvariants();
1789 #endif
1792 void AccessibleTextHelper::SetEventSource( const uno::Reference< XAccessible >& rInterface )
1794 #ifdef DBG_UTIL
1795 mpImpl->CheckInvariants();
1796 #endif
1798 mpImpl->SetEventSource( rInterface );
1800 #ifdef DBG_UTIL
1801 mpImpl->CheckInvariants();
1802 #endif
1805 uno::Reference< XAccessible > AccessibleTextHelper::GetEventSource() const
1807 #ifdef DBG_UTIL
1808 mpImpl->CheckInvariants();
1810 uno::Reference< XAccessible > xRet( mpImpl->GetEventSource() );
1812 mpImpl->CheckInvariants();
1814 return xRet;
1815 #else
1816 return mpImpl->GetEventSource();
1817 #endif
1820 void AccessibleTextHelper::SetFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException))
1822 #ifdef DBG_UTIL
1823 // precondition: solar mutex locked
1824 DBG_TESTSOLARMUTEX();
1826 mpImpl->CheckInvariants();
1827 #endif
1829 mpImpl->SetFocus( bHaveFocus );
1831 #ifdef DBG_UTIL
1832 mpImpl->CheckInvariants();
1833 #endif
1836 sal_Bool AccessibleTextHelper::HaveFocus() SAL_THROW((::com::sun::star::uno::RuntimeException))
1838 #ifdef DBG_UTIL
1839 mpImpl->CheckInvariants();
1841 sal_Bool bRet( mpImpl->HaveFocus() );
1843 mpImpl->CheckInvariants();
1845 return bRet;
1846 #else
1847 return mpImpl->HaveFocus();
1848 #endif
1851 void AccessibleTextHelper::FireEvent( const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue ) const
1853 #ifdef DBG_UTIL
1854 mpImpl->CheckInvariants();
1855 #endif
1857 mpImpl->FireEvent( nEventId, rNewValue, rOldValue );
1859 #ifdef DBG_UTIL
1860 mpImpl->CheckInvariants();
1861 #endif
1864 void AccessibleTextHelper::FireEvent( const AccessibleEventObject& rEvent ) const
1866 #ifdef DBG_UTIL
1867 mpImpl->CheckInvariants();
1868 #endif
1870 mpImpl->FireEvent( rEvent );
1872 #ifdef DBG_UTIL
1873 mpImpl->CheckInvariants();
1874 #endif
1877 void AccessibleTextHelper::SetOffset( const Point& rPoint )
1879 #ifdef DBG_UTIL
1880 // precondition: solar mutex locked
1881 DBG_TESTSOLARMUTEX();
1883 mpImpl->CheckInvariants();
1884 #endif
1886 mpImpl->SetOffset( rPoint );
1888 #ifdef DBG_UTIL
1889 mpImpl->CheckInvariants();
1890 #endif
1893 Point AccessibleTextHelper::GetOffset() const
1895 #ifdef DBG_UTIL
1896 mpImpl->CheckInvariants();
1898 Point aPoint( mpImpl->GetOffset() );
1900 mpImpl->CheckInvariants();
1902 return aPoint;
1903 #else
1904 return mpImpl->GetOffset();
1905 #endif
1908 void AccessibleTextHelper::SetStartIndex( sal_Int32 nOffset )
1910 #ifdef DBG_UTIL
1911 // precondition: solar mutex locked
1912 DBG_TESTSOLARMUTEX();
1914 mpImpl->CheckInvariants();
1915 #endif
1917 mpImpl->SetStartIndex( nOffset );
1919 #ifdef DBG_UTIL
1920 mpImpl->CheckInvariants();
1921 #endif
1924 sal_Int32 AccessibleTextHelper::GetStartIndex() const
1926 #ifdef DBG_UTIL
1927 mpImpl->CheckInvariants();
1929 sal_Int32 nOffset = mpImpl->GetStartIndex();
1931 mpImpl->CheckInvariants();
1933 return nOffset;
1934 #else
1935 return mpImpl->GetStartIndex();
1936 #endif
1939 void AccessibleTextHelper::SetAdditionalChildStates( const VectorOfStates& rChildStates )
1941 mpImpl->SetAdditionalChildStates( rChildStates );
1944 const AccessibleTextHelper::VectorOfStates& AccessibleTextHelper::GetAdditionalChildStates() const
1946 return mpImpl->GetAdditionalChildStates();
1949 void AccessibleTextHelper::UpdateChildren() SAL_THROW((::com::sun::star::uno::RuntimeException))
1951 #ifdef DBG_UTIL
1952 // precondition: solar mutex locked
1953 DBG_TESTSOLARMUTEX();
1955 mpImpl->CheckInvariants();
1956 #endif
1958 mpImpl->UpdateVisibleChildren();
1959 mpImpl->UpdateBoundRect();
1961 mpImpl->UpdateSelection();
1963 #ifdef DBG_UTIL
1964 mpImpl->CheckInvariants();
1965 #endif
1968 void AccessibleTextHelper::Dispose()
1970 // As Dispose calls ShutdownEditSource, which in turn
1971 // deregisters as listener on the edit source, have to lock
1972 // here
1973 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1975 #ifdef DBG_UTIL
1976 mpImpl->CheckInvariants();
1977 #endif
1979 mpImpl->Dispose();
1981 #ifdef DBG_UTIL
1982 mpImpl->CheckInvariants();
1983 #endif
1986 sal_Bool AccessibleTextHelper::IsSelected() const
1988 ::vos::OGuard aGuard( Application::GetSolarMutex() );
1990 #ifdef DBG_UTIL
1991 mpImpl->CheckInvariants();
1993 sal_Bool aRet = mpImpl->IsSelected();
1995 mpImpl->CheckInvariants();
1997 return aRet;
1998 #else
1999 return mpImpl->IsSelected();
2000 #endif
2003 // XAccessibleContext
2004 sal_Int32 AccessibleTextHelper::GetChildCount() SAL_THROW((uno::RuntimeException))
2006 ::vos::OGuard aGuard( Application::GetSolarMutex() );
2008 #ifdef DBG_UTIL
2009 mpImpl->CheckInvariants();
2011 sal_Int32 nRet = mpImpl->getAccessibleChildCount();
2013 mpImpl->CheckInvariants();
2015 return nRet;
2016 #else
2017 return mpImpl->getAccessibleChildCount();
2018 #endif
2021 uno::Reference< XAccessible > AccessibleTextHelper::GetChild( sal_Int32 i ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException))
2023 ::vos::OGuard aGuard( Application::GetSolarMutex() );
2025 #ifdef DBG_UTIL
2026 mpImpl->CheckInvariants();
2028 uno::Reference< XAccessible > xRet = mpImpl->getAccessibleChild( i );
2030 mpImpl->CheckInvariants();
2032 return xRet;
2033 #else
2034 return mpImpl->getAccessibleChild( i );
2035 #endif
2038 void AccessibleTextHelper::AddEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException))
2040 #ifdef DBG_UTIL
2041 mpImpl->CheckInvariants();
2043 mpImpl->addEventListener( xListener );
2045 mpImpl->CheckInvariants();
2046 #else
2047 mpImpl->addEventListener( xListener );
2048 #endif
2051 void AccessibleTextHelper::RemoveEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException))
2053 #ifdef DBG_UTIL
2054 mpImpl->CheckInvariants();
2056 mpImpl->removeEventListener( xListener );
2058 mpImpl->CheckInvariants();
2059 #else
2060 mpImpl->removeEventListener( xListener );
2061 #endif
2064 // XAccessibleComponent
2065 uno::Reference< XAccessible > AccessibleTextHelper::GetAt( const awt::Point& aPoint ) SAL_THROW((uno::RuntimeException))
2067 ::vos::OGuard aGuard( Application::GetSolarMutex() );
2069 #ifdef DBG_UTIL
2070 mpImpl->CheckInvariants();
2072 uno::Reference< XAccessible > xChild = mpImpl->getAccessibleAtPoint( aPoint );
2074 mpImpl->CheckInvariants();
2076 return xChild;
2077 #else
2078 return mpImpl->getAccessibleAtPoint( aPoint );
2079 #endif
2082 } // end of namespace accessibility
2084 //------------------------------------------------------------------------