Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 :
22 :
23 : // Global header
24 :
25 :
26 :
27 : #include <limits.h>
28 : #include <memory>
29 : #include <algorithm>
30 : #include <deque>
31 : #include <osl/mutex.hxx>
32 : #include <com/sun/star/uno/Any.hxx>
33 : #include <com/sun/star/uno/Reference.hxx>
34 : #include <cppuhelper/weakref.hxx>
35 : #include <com/sun/star/awt/Point.hpp>
36 : #include <com/sun/star/awt/Rectangle.hpp>
37 : #include <com/sun/star/lang/DisposedException.hpp>
38 : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
39 : #include <com/sun/star/accessibility/XAccessible.hpp>
40 : #include <com/sun/star/accessibility/XAccessibleContext.hpp>
41 : #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
42 : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
43 : #include <comphelper/accessibleeventnotifier.hxx>
44 : #include <unotools/accessiblestatesethelper.hxx>
45 : #include <vcl/svapp.hxx>
46 : #include <vcl/textdata.hxx>
47 : #include <vcl/unohelp.hxx>
48 : #include <sfx2/viewfrm.hxx>
49 : #include <sfx2/viewsh.hxx>
50 :
51 :
52 :
53 : // Project-local header
54 :
55 :
56 : #include "AccessibleTextEventQueue.hxx"
57 : #include <svx/AccessibleTextHelper.hxx>
58 : #include <svx/unoshape.hxx>
59 : #include "editeng/unolingu.hxx"
60 : #include <editeng/unotext.hxx>
61 :
62 : #include "editeng/unoedhlp.hxx"
63 : #include "editeng/unopracc.hxx"
64 : #include "editeng/AccessibleParaManager.hxx"
65 : #include "editeng/AccessibleEditableTextPara.hxx"
66 : #include <svx/svdmodel.hxx>
67 : #include <svx/svdpntv.hxx>
68 : #include "../table/cell.hxx"
69 : #include "../table/accessiblecell.hxx"
70 : #include <editeng/editdata.hxx>
71 : #include <editeng/editeng.hxx>
72 : #include <editeng/editview.hxx>
73 :
74 : using namespace ::com::sun::star;
75 : using namespace ::com::sun::star::accessibility;
76 :
77 : namespace accessibility
78 : {
79 :
80 :
81 :
82 : // AccessibleTextHelper_Impl declaration
83 :
84 :
85 :
86 :
87 : template < typename first_type, typename second_type >
88 0 : ::std::pair< first_type, second_type > makeSortedPair( first_type first,
89 : second_type second )
90 : {
91 0 : if( first > second )
92 0 : return ::std::make_pair( second, first );
93 : else
94 0 : return ::std::make_pair( first, second );
95 : }
96 :
97 : class AccessibleTextHelper_Impl : public SfxListener
98 : {
99 :
100 : public:
101 : typedef ::std::vector< sal_Int16 > VectorOfStates;
102 :
103 : // receive pointer to our frontend class and view window
104 : AccessibleTextHelper_Impl();
105 : virtual ~AccessibleTextHelper_Impl();
106 :
107 : // XAccessibleContext child handling methods
108 : sal_Int32 SAL_CALL getAccessibleChildCount() SAL_THROW((uno::RuntimeException));
109 : uno::Reference< XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException));
110 :
111 : // XAccessibleEventBroadcaster child related methods
112 : void SAL_CALL addAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException));
113 : void SAL_CALL removeAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException));
114 :
115 : // XAccessibleComponent child related methods
116 : uno::Reference< XAccessible > SAL_CALL getAccessibleAtPoint( const awt::Point& aPoint ) SAL_THROW((uno::RuntimeException));
117 :
118 : SvxEditSourceAdapter& GetEditSource() const SAL_THROW((uno::RuntimeException));
119 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
120 : void SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException));
121 : SAL_WNODEPRECATED_DECLARATIONS_POP
122 :
123 0 : void SetEventSource( const uno::Reference< XAccessible >& rInterface )
124 : {
125 0 : mxFrontEnd = rInterface;
126 0 : }
127 0 : uno::Reference< XAccessible > GetEventSource() const
128 : {
129 0 : return mxFrontEnd;
130 : }
131 :
132 : void SetOffset( const Point& );
133 0 : Point GetOffset() const
134 : {
135 0 : ::osl::MutexGuard aGuard( maMutex ); Point aPoint( maOffset );
136 0 : return aPoint;
137 : }
138 :
139 : void SetStartIndex( sal_Int32 nOffset );
140 0 : sal_Int32 GetStartIndex() const
141 : {
142 : // Strictly correct only with locked solar mutex, // but
143 : // here we rely on the fact that sal_Int32 access is
144 : // atomic
145 0 : return mnStartIndex;
146 : }
147 :
148 : void SetAdditionalChildStates( const VectorOfStates& rChildStates );
149 :
150 : sal_Bool IsSelected() const;
151 :
152 : void Dispose();
153 :
154 : // do NOT hold object mutex when calling this! Danger of deadlock
155 : void FireEvent( const sal_Int16 nEventId, const uno::Any& rNewValue = uno::Any(), const uno::Any& rOldValue = uno::Any() ) const;
156 : void FireEvent( const AccessibleEventObject& rEvent ) const;
157 :
158 : void SetFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException));
159 : sal_Bool HaveFocus() SAL_THROW((::com::sun::star::uno::RuntimeException));
160 : void SetChildFocus( sal_Int32 nChild, sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException));
161 : void SetShapeFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException));
162 : void ChangeChildFocus( sal_Int32 nNewChild ) SAL_THROW((::com::sun::star::uno::RuntimeException));
163 :
164 : #ifdef DBG_UTIL
165 : void CheckInvariants() const;
166 : #endif
167 :
168 : // checks all children for visibility, throws away invisible ones
169 : void UpdateVisibleChildren( bool bBroadcastEvents=true );
170 :
171 : // check all children for changes in position and size
172 : void UpdateBoundRect();
173 :
174 : // calls SetSelection on the forwarder and updates maLastSelection
175 : // cache.
176 : void UpdateSelection();
177 :
178 : private:
179 :
180 : // Process event queue
181 : void ProcessQueue();
182 :
183 : // syntactic sugar for FireEvent
184 0 : void GotPropertyEvent( const uno::Any& rNewValue, const sal_Int16 nEventId ) const { FireEvent( nEventId, rNewValue ); }
185 0 : void LostPropertyEvent( const uno::Any& rOldValue, const sal_Int16 nEventId ) const { FireEvent( nEventId, uno::Any(), rOldValue ); }
186 :
187 : // shutdown usage of current edit source on myself and the children.
188 : void ShutdownEditSource() SAL_THROW((uno::RuntimeException));
189 :
190 : void ParagraphsMoved( sal_Int32 nFirst, sal_Int32 nMiddle, sal_Int32 nLast );
191 :
192 : virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) SAL_OVERRIDE;
193 :
194 0 : int getNotifierClientId() const { return mnNotifierClientId; }
195 :
196 : // lock solar mutex before
197 : SvxTextForwarder& GetTextForwarder() const SAL_THROW((uno::RuntimeException));
198 : // lock solar mutex before
199 : SvxViewForwarder& GetViewForwarder() const SAL_THROW((uno::RuntimeException));
200 : // lock solar mutex before
201 : SvxEditViewForwarder& GetEditViewForwarder( sal_Bool bCreate = sal_False ) const SAL_THROW((uno::RuntimeException));
202 :
203 : // are we in edit mode?
204 : sal_Bool IsActive() const SAL_THROW((uno::RuntimeException));
205 :
206 : // our frontend class (the one implementing the actual
207 : // interface). That's not necessarily the one containing the impl
208 : // pointer!
209 : uno::Reference< XAccessible > mxFrontEnd;
210 :
211 : // a wrapper for the text forwarders (guarded by solar mutex)
212 : mutable SvxEditSourceAdapter maEditSource;
213 :
214 : // store last selection (to correctly report selection changes, guarded by solar mutex)
215 : ESelection maLastSelection;
216 :
217 : // cache range of visible children (guarded by solar mutex)
218 : sal_Int32 mnFirstVisibleChild;
219 : sal_Int32 mnLastVisibleChild;
220 :
221 : // offset to add to all our children (unguarded, relying on
222 : // the fact that sal_Int32 access is atomic)
223 : sal_Int32 mnStartIndex;
224 :
225 : // the object handling our children (guarded by solar mutex)
226 : ::accessibility::AccessibleParaManager maParaManager;
227 :
228 : // number of not-yet-closed event frames (BEGIN/END sequences) (guarded by solar mutex)
229 : sal_Int32 maEventOpenFrames;
230 :
231 : // Queued events from Notify() (guarded by solar mutex)
232 : AccessibleTextEventQueue maEventQueue;
233 :
234 : // spin lock to prevent notify in notify (guarded by solar mutex)
235 : bool mbInNotify;
236 :
237 : // whether the object or its children has the focus set (guarded by solar mutex)
238 : sal_Bool mbGroupHasFocus;
239 :
240 : // whether we (this object) has the focus set (guarded by solar mutex)
241 : sal_Bool mbThisHasFocus;
242 :
243 : mutable ::osl::Mutex maMutex;
244 :
245 : /// our current offset to the containing shape/cell (guarded by maMutex)
246 : Point maOffset;
247 :
248 : /// client Id from AccessibleEventNotifier
249 : int mnNotifierClientId;
250 : };
251 :
252 :
253 :
254 : // AccessibleTextHelper_Impl implementation
255 :
256 :
257 :
258 0 : AccessibleTextHelper_Impl::AccessibleTextHelper_Impl() :
259 : mxFrontEnd( NULL ),
260 : maLastSelection( EE_PARA_NOT_FOUND,EE_INDEX_NOT_FOUND,EE_PARA_NOT_FOUND,EE_INDEX_NOT_FOUND ),
261 : mnFirstVisibleChild( -1 ),
262 : mnLastVisibleChild( -2 ),
263 : mnStartIndex( 0 ),
264 : maEventOpenFrames( 0 ),
265 : mbInNotify( false ),
266 : mbGroupHasFocus( sal_False ),
267 : mbThisHasFocus( sal_False ),
268 : maOffset(0,0),
269 : // well, that's strictly exception safe, though not really
270 : // robust. We rely on the fact that this member is constructed
271 : // last, and that the constructor body is empty, thus no
272 : // chance for exceptions once the Id is fetched. Nevertheless,
273 : // normally should employ RAII here...
274 0 : mnNotifierClientId(::comphelper::AccessibleEventNotifier::registerClient())
275 : {
276 :
277 : #ifdef DBG_UTIL
278 : OSL_TRACE( "AccessibleTextHelper_Impl received ID: %d", mnNotifierClientId );
279 : #endif
280 0 : }
281 :
282 0 : AccessibleTextHelper_Impl::~AccessibleTextHelper_Impl()
283 : {
284 :
285 0 : SolarMutexGuard aGuard;
286 :
287 : try
288 : {
289 : // call Dispose here, too, since we've some resources not
290 : // automatically freed otherwise
291 0 : Dispose();
292 : }
293 0 : catch( const uno::Exception& ) {}
294 0 : }
295 :
296 0 : SvxTextForwarder& AccessibleTextHelper_Impl::GetTextForwarder() const SAL_THROW((uno::RuntimeException))
297 : {
298 :
299 0 : if( !maEditSource.IsValid() )
300 0 : throw uno::RuntimeException("Unknown edit source", mxFrontEnd);
301 :
302 0 : SvxTextForwarder* pTextForwarder = maEditSource.GetTextForwarder();
303 :
304 0 : if( !pTextForwarder )
305 0 : throw uno::RuntimeException("Unable to fetch text forwarder, model might be dead", mxFrontEnd);
306 :
307 0 : if( pTextForwarder->IsValid() )
308 0 : return *pTextForwarder;
309 : else
310 0 : throw uno::RuntimeException("Text forwarder is invalid, model might be dead", mxFrontEnd);
311 : }
312 :
313 0 : SvxViewForwarder& AccessibleTextHelper_Impl::GetViewForwarder() const SAL_THROW((uno::RuntimeException))
314 : {
315 :
316 0 : if( !maEditSource.IsValid() )
317 0 : throw uno::RuntimeException("Unknown edit source", mxFrontEnd);
318 :
319 0 : SvxViewForwarder* pViewForwarder = maEditSource.GetViewForwarder();
320 :
321 0 : if( !pViewForwarder )
322 0 : throw uno::RuntimeException("Unable to fetch view forwarder, model might be dead", mxFrontEnd);
323 :
324 0 : if( pViewForwarder->IsValid() )
325 0 : return *pViewForwarder;
326 : else
327 0 : throw uno::RuntimeException("View forwarder is invalid, model might be dead", mxFrontEnd);
328 : }
329 :
330 0 : SvxEditViewForwarder& AccessibleTextHelper_Impl::GetEditViewForwarder( sal_Bool bCreate ) const SAL_THROW((uno::RuntimeException))
331 : {
332 :
333 0 : if( !maEditSource.IsValid() )
334 0 : throw uno::RuntimeException("Unknown edit source", mxFrontEnd);
335 :
336 0 : SvxEditViewForwarder* pViewForwarder = maEditSource.GetEditViewForwarder( bCreate );
337 :
338 0 : if( !pViewForwarder )
339 : {
340 0 : if( bCreate )
341 0 : throw uno::RuntimeException("Unable to fetch edit view forwarder, model might be dead", mxFrontEnd);
342 : else
343 0 : throw uno::RuntimeException("No edit view forwarder, object not in edit mode", mxFrontEnd);
344 : }
345 :
346 0 : if( pViewForwarder->IsValid() )
347 0 : return *pViewForwarder;
348 : else
349 : {
350 0 : if( bCreate )
351 0 : throw uno::RuntimeException("View forwarder is invalid, model might be dead", mxFrontEnd);
352 : else
353 0 : throw uno::RuntimeException("View forwarder is invalid, object not in edit mode", mxFrontEnd);
354 : }
355 : }
356 :
357 0 : SvxEditSourceAdapter& AccessibleTextHelper_Impl::GetEditSource() const SAL_THROW((uno::RuntimeException))
358 : {
359 :
360 0 : if( maEditSource.IsValid() )
361 0 : return maEditSource;
362 : else
363 0 : throw uno::RuntimeException("AccessibleTextHelper_Impl::GetEditSource: no edit source", mxFrontEnd );
364 : }
365 :
366 0 : sal_Bool AccessibleTextHelper_Impl::IsSelected() const
367 : {
368 :
369 0 : sal_Bool bRet = sal_False;
370 :
371 : try
372 : {
373 0 : ESelection aSelection;
374 0 : bRet = GetEditViewForwarder().GetSelection( aSelection );
375 : }
376 0 : catch( const uno::Exception& ) {}
377 :
378 0 : return bRet;
379 : }
380 :
381 : // functor for sending child events (no stand-alone function, they are maybe not inlined)
382 : class AccessibleTextHelper_OffsetChildIndex : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void >
383 : {
384 : public:
385 0 : AccessibleTextHelper_OffsetChildIndex( sal_Int32 nDifference ) : mnDifference(nDifference) {}
386 0 : void operator()( ::accessibility::AccessibleEditableTextPara& rPara )
387 : {
388 0 : rPara.SetIndexInParent( rPara.GetIndexInParent() + mnDifference );
389 0 : }
390 :
391 : private:
392 : const sal_Int32 mnDifference;
393 : };
394 :
395 0 : void AccessibleTextHelper_Impl::SetStartIndex( sal_Int32 nOffset )
396 : {
397 :
398 0 : sal_Int32 nOldOffset( mnStartIndex );
399 :
400 0 : mnStartIndex = nOffset;
401 :
402 0 : if( nOldOffset != nOffset )
403 : {
404 : // update children
405 0 : AccessibleTextHelper_OffsetChildIndex aFunctor( nOffset - nOldOffset );
406 :
407 : ::std::for_each( maParaManager.begin(), maParaManager.end(),
408 0 : AccessibleParaManager::WeakChildAdapter< AccessibleTextHelper_OffsetChildIndex > (aFunctor) );
409 : }
410 0 : }
411 :
412 0 : void AccessibleTextHelper_Impl::SetAdditionalChildStates( const VectorOfStates& rChildStates )
413 : {
414 0 : maParaManager.SetAdditionalChildStates( rChildStates );
415 0 : }
416 :
417 0 : void AccessibleTextHelper_Impl::SetChildFocus( sal_Int32 nChild, sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException))
418 : {
419 :
420 0 : if( bHaveFocus )
421 : {
422 0 : if( mbThisHasFocus )
423 0 : SetShapeFocus( sal_False );
424 :
425 0 : maParaManager.SetFocus( nChild );
426 :
427 : // we just received the focus, also send caret event then
428 0 : UpdateSelection();
429 :
430 : OSL_TRACE("AccessibleTextHelper_Impl::SetChildFocus(): Paragraph %d received focus", nChild );
431 : }
432 : else
433 : {
434 0 : maParaManager.SetFocus( -1 );
435 :
436 : OSL_TRACE("AccessibleTextHelper_Impl::SetChildFocus(): Paragraph %d lost focus", nChild );
437 :
438 0 : if( mbGroupHasFocus )
439 0 : SetShapeFocus( sal_True );
440 : }
441 0 : }
442 :
443 0 : void AccessibleTextHelper_Impl::ChangeChildFocus( sal_Int32 nNewChild ) SAL_THROW((::com::sun::star::uno::RuntimeException))
444 : {
445 :
446 0 : if( mbThisHasFocus )
447 0 : SetShapeFocus( sal_False );
448 :
449 0 : mbGroupHasFocus = sal_True;
450 0 : maParaManager.SetFocus( nNewChild );
451 :
452 : OSL_TRACE("AccessibleTextHelper_Impl::ChangeChildFocus(): Paragraph %d received focus", nNewChild );
453 0 : }
454 :
455 0 : void AccessibleTextHelper_Impl::SetShapeFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException))
456 : {
457 :
458 0 : sal_Bool bOldFocus( mbThisHasFocus );
459 :
460 0 : mbThisHasFocus = bHaveFocus;
461 :
462 0 : if( bOldFocus != bHaveFocus )
463 : {
464 0 : if( bHaveFocus )
465 : {
466 0 : if( mxFrontEnd.is() )
467 : {
468 0 : AccessibleCell* pAccessibleCell = dynamic_cast< AccessibleCell* > ( mxFrontEnd.get() );
469 0 : if ( !pAccessibleCell )
470 0 : GotPropertyEvent( uno::makeAny(AccessibleStateType::FOCUSED), AccessibleEventId::STATE_CHANGED );
471 : else // the focus event on cell should be fired on table directly
472 : {
473 0 : AccessibleTableShape* pAccTable = pAccessibleCell->GetParentTable();
474 0 : if (pAccTable)
475 0 : pAccTable->SetStateDirectly(AccessibleStateType::FOCUSED);
476 : }
477 : }
478 : OSL_TRACE("AccessibleTextHelper_Impl::SetShapeFocus(): Parent object received focus" );
479 : }
480 : else
481 : {
482 : // The focus state should be reset directly on table.
483 : //LostPropertyEvent( uno::makeAny(AccessibleStateType::FOCUSED), AccessibleEventId::STATE_CHANGED );
484 0 : if( mxFrontEnd.is() )
485 : {
486 0 : AccessibleCell* pAccessibleCell = dynamic_cast< AccessibleCell* > ( mxFrontEnd.get() );
487 0 : if ( !pAccessibleCell )
488 0 : LostPropertyEvent( uno::makeAny(AccessibleStateType::FOCUSED), AccessibleEventId::STATE_CHANGED );
489 : else
490 : {
491 0 : AccessibleTableShape* pAccTable = pAccessibleCell->GetParentTable();
492 0 : if (pAccTable)
493 0 : pAccTable->ResetStateDirectly(AccessibleStateType::FOCUSED);
494 : }
495 : }
496 : OSL_TRACE("AccessibleTextHelper_Impl::SetShapeFocus(): Parent object lost focus" );
497 : }
498 : }
499 0 : }
500 :
501 0 : void AccessibleTextHelper_Impl::SetFocus( sal_Bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException))
502 : {
503 :
504 0 : sal_Bool bOldFocus( mbGroupHasFocus );
505 :
506 0 : mbGroupHasFocus = bHaveFocus;
507 :
508 0 : if( IsActive() )
509 : {
510 : try
511 : {
512 : // find the one with the cursor and get/set focus accordingly
513 0 : ESelection aSelection;
514 0 : if( GetEditViewForwarder().GetSelection( aSelection ) )
515 0 : SetChildFocus( aSelection.nEndPara, bHaveFocus );
516 : }
517 0 : catch( const uno::Exception& ) {}
518 : }
519 0 : else if( bOldFocus != bHaveFocus )
520 : {
521 0 : SetShapeFocus( bHaveFocus );
522 : }
523 :
524 : OSL_TRACE("AccessibleTextHelper_Impl::SetFocus: focus changed, Object %p, state: %s", this, bHaveFocus ? "focused" : "not focused");
525 0 : }
526 :
527 0 : sal_Bool AccessibleTextHelper_Impl::HaveFocus() SAL_THROW((::com::sun::star::uno::RuntimeException))
528 : {
529 :
530 : // No locking of solar mutex here, since we rely on the fact
531 : // that sal_Bool access is atomic
532 0 : return mbThisHasFocus;
533 : }
534 :
535 0 : sal_Bool AccessibleTextHelper_Impl::IsActive() const SAL_THROW((uno::RuntimeException))
536 : {
537 :
538 : try
539 : {
540 0 : SvxEditSource& rEditSource = GetEditSource();
541 0 : SvxEditViewForwarder* pViewForwarder = rEditSource.GetEditViewForwarder();
542 :
543 0 : if( !pViewForwarder )
544 0 : return sal_False;
545 :
546 0 : if( mxFrontEnd.is() )
547 : {
548 0 : AccessibleCell* pAccessibleCell = dynamic_cast< AccessibleCell* > ( mxFrontEnd.get() );
549 0 : if ( pAccessibleCell )
550 : {
551 0 : sdr::table::CellRef xCell = pAccessibleCell->getCellRef();
552 0 : if ( xCell.is() )
553 0 : return xCell->IsTextEditActive();
554 : }
555 : }
556 0 : if( pViewForwarder->IsValid() )
557 0 : return sal_True;
558 : else
559 0 : return sal_False;
560 : }
561 0 : catch( const uno::RuntimeException& )
562 : {
563 0 : return sal_False;
564 : }
565 : }
566 :
567 0 : void AccessibleTextHelper_Impl::UpdateSelection()
568 : {
569 :
570 : try
571 : {
572 0 : ESelection aSelection;
573 0 : if( GetEditViewForwarder().GetSelection( aSelection ) )
574 : {
575 0 : if( !maLastSelection.IsEqual( aSelection ) &&
576 0 : aSelection.nEndPara < maParaManager.GetNum() )
577 : {
578 : // #103998# Not that important, changed from assertion to trace
579 0 : if( mbThisHasFocus )
580 : {
581 : OSL_TRACE("AccessibleTextHelper_Impl::UpdateSelection(): Parent has focus!");
582 : }
583 :
584 0 : sal_Int32 nMaxValidParaIndex( GetTextForwarder().GetParagraphCount() - 1 );
585 :
586 : // notify all affected paragraphs (TODO: may be suboptimal,
587 : // since some paragraphs might stay selected)
588 0 : if( maLastSelection.nStartPara != EE_PARA_NOT_FOUND )
589 : {
590 : // Did the caret move from one paragraph to another?
591 : // #100530# no caret events if not focused.
592 0 : if( mbGroupHasFocus &&
593 0 : maLastSelection.nEndPara != aSelection.nEndPara )
594 : {
595 0 : if( maLastSelection.nEndPara < maParaManager.GetNum() )
596 : {
597 0 : maParaManager.FireEvent( ::std::min( maLastSelection.nEndPara, nMaxValidParaIndex ),
598 0 : ::std::min( maLastSelection.nEndPara, nMaxValidParaIndex )+1,
599 : AccessibleEventId::CARET_CHANGED,
600 : uno::makeAny(static_cast<sal_Int32>(-1)),
601 0 : uno::makeAny(static_cast<sal_Int32>(maLastSelection.nEndPos)) );
602 : }
603 :
604 0 : ChangeChildFocus( aSelection.nEndPara );
605 :
606 : OSL_TRACE("AccessibleTextHelper_Impl::UpdateSelection(): focus changed, Object: %p, Paragraph: %d, Last paragraph: %d",
607 : this, aSelection.nEndPara, maLastSelection.nEndPara);
608 : }
609 : }
610 :
611 : // #100530# no caret events if not focused.
612 0 : if( mbGroupHasFocus )
613 : {
614 0 : uno::Any aOldCursor;
615 :
616 : // #i13705# The old cursor can only contain valid
617 : // values if it's the same paragraph!
618 0 : if( maLastSelection.nStartPara != EE_PARA_NOT_FOUND &&
619 0 : maLastSelection.nEndPara == aSelection.nEndPara )
620 : {
621 0 : aOldCursor <<= static_cast<sal_Int32>(maLastSelection.nEndPos);
622 : }
623 : else
624 : {
625 0 : aOldCursor <<= static_cast<sal_Int32>(-1);
626 : }
627 :
628 : maParaManager.FireEvent( aSelection.nEndPara,
629 : aSelection.nEndPara+1,
630 : AccessibleEventId::CARET_CHANGED,
631 : uno::makeAny(static_cast<sal_Int32>(aSelection.nEndPos)),
632 0 : aOldCursor );
633 : }
634 :
635 : OSL_TRACE("AccessibleTextHelper_Impl::UpdateSelection(): caret changed, Object: %p, New pos: %d, Old pos: %d, New para: %d, Old para: %d",
636 : this, aSelection.nEndPos, maLastSelection.nEndPos, aSelection.nEndPara, maLastSelection.nEndPara);
637 :
638 : // #108947# Sort new range before calling FireEvent
639 : ::std::pair<sal_Int32, sal_Int32> sortedSelection(
640 0 : makeSortedPair(::std::min( aSelection.nStartPara, nMaxValidParaIndex ),
641 0 : ::std::min( aSelection.nEndPara, nMaxValidParaIndex ) ) );
642 :
643 : // #108947# Sort last range before calling FireEvent
644 : ::std::pair<sal_Int32, sal_Int32> sortedLastSelection(
645 0 : makeSortedPair(::std::min( maLastSelection.nStartPara, nMaxValidParaIndex ),
646 0 : ::std::min( maLastSelection.nEndPara, nMaxValidParaIndex ) ) );
647 :
648 : // event TEXT_SELECTION_CHANGED has to be submitted. (#i27299#)
649 : const sal_Int16 nTextSelChgEventId =
650 0 : AccessibleEventId::TEXT_SELECTION_CHANGED;
651 : // #107037# notify selection change
652 0 : if( maLastSelection.nStartPara == EE_PARA_NOT_FOUND )
653 : {
654 : // last selection is undefined
655 : // use method <ESelection::HasRange()> (#i27299#)
656 0 : if ( aSelection.HasRange() )
657 : {
658 : // selection was undefined, now is on
659 : maParaManager.FireEvent( sortedSelection.first,
660 : sortedSelection.second+1,
661 0 : nTextSelChgEventId );
662 : }
663 : }
664 : else
665 : {
666 : // last selection is valid
667 : // use method <ESelection::HasRange()> (#i27299#)
668 0 : if ( maLastSelection.HasRange() &&
669 0 : !aSelection.HasRange() )
670 : {
671 : // selection was on, now is empty
672 : maParaManager.FireEvent( sortedLastSelection.first,
673 : sortedLastSelection.second+1,
674 0 : nTextSelChgEventId );
675 : }
676 : // use method <ESelection::HasRange()> (#i27299#)
677 0 : else if( !maLastSelection.HasRange() &&
678 0 : aSelection.HasRange() )
679 : {
680 : // selection was empty, now is on
681 : maParaManager.FireEvent( sortedSelection.first,
682 : sortedSelection.second+1,
683 0 : nTextSelChgEventId );
684 : }
685 : // no event TEXT_SELECTION_CHANGED event, if new and
686 : // last selection are empty. (#i27299#)
687 0 : else if ( maLastSelection.HasRange() &&
688 0 : aSelection.HasRange() )
689 : {
690 : // use sorted last and new selection
691 0 : ESelection aTmpLastSel( maLastSelection );
692 0 : aTmpLastSel.Adjust();
693 0 : ESelection aTmpSel( aSelection );
694 0 : aTmpSel.Adjust();
695 : // first submit event for new and changed selection
696 0 : sal_Int32 nPara = aTmpSel.nStartPara;
697 0 : for ( ; nPara <= aTmpSel.nEndPara; ++nPara )
698 : {
699 0 : if ( nPara < aTmpLastSel.nStartPara ||
700 0 : nPara > aTmpLastSel.nEndPara )
701 : {
702 : // new selection on paragraph <nPara>
703 : maParaManager.FireEvent( nPara,
704 0 : nTextSelChgEventId );
705 : }
706 : else
707 : {
708 : // check for changed selection on paragraph <nPara>
709 : const sal_Int32 nParaStartPos =
710 0 : nPara == aTmpSel.nStartPara
711 0 : ? aTmpSel.nStartPos : 0;
712 : const sal_Int32 nParaEndPos =
713 0 : nPara == aTmpSel.nEndPara
714 0 : ? aTmpSel.nEndPos : -1;
715 : const sal_Int32 nLastParaStartPos =
716 0 : nPara == aTmpLastSel.nStartPara
717 0 : ? aTmpLastSel.nStartPos : 0;
718 : const sal_Int32 nLastParaEndPos =
719 0 : nPara == aTmpLastSel.nEndPara
720 0 : ? aTmpLastSel.nEndPos : -1;
721 0 : if ( nParaStartPos != nLastParaStartPos ||
722 : nParaEndPos != nLastParaEndPos )
723 : {
724 : maParaManager.FireEvent(
725 0 : nPara, nTextSelChgEventId );
726 : }
727 : }
728 : }
729 : // second submit event for 'old' selections
730 0 : nPara = aTmpLastSel.nStartPara;
731 0 : for ( ; nPara <= aTmpLastSel.nEndPara; ++nPara )
732 : {
733 0 : if ( nPara < aTmpSel.nStartPara ||
734 0 : nPara > aTmpSel.nEndPara )
735 : {
736 : maParaManager.FireEvent( nPara,
737 0 : nTextSelChgEventId );
738 : }
739 : }
740 : }
741 : }
742 :
743 0 : maLastSelection = aSelection;
744 : }
745 : }
746 : }
747 : // no selection? no update actions
748 0 : catch( const uno::RuntimeException& ) {}
749 0 : }
750 :
751 0 : void AccessibleTextHelper_Impl::ShutdownEditSource() SAL_THROW((uno::RuntimeException))
752 : {
753 :
754 : // This should only be called with solar mutex locked, i.e. from the main office thread
755 :
756 : // This here is somewhat clumsy: As soon as our children have
757 : // a NULL EditSource (maParaManager.SetEditSource()), they
758 : // enter the disposed state and cannot be reanimated. Thus, it
759 : // is unavoidable and a hard requirement to let go and create
760 : // from scratch each and every child.
761 :
762 : // invalidate children
763 0 : maParaManager.Dispose();
764 0 : maParaManager.SetNum(0);
765 :
766 : // lost all children
767 0 : if( mxFrontEnd.is() )
768 0 : FireEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN);
769 :
770 : // quit listen on stale edit source
771 0 : if( maEditSource.IsValid() )
772 0 : EndListening( maEditSource.GetBroadcaster() );
773 :
774 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
775 0 : maEditSource.SetEditSource( ::std::auto_ptr< SvxEditSource >(NULL) );
776 : SAL_WNODEPRECATED_DECLARATIONS_POP
777 0 : }
778 :
779 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
780 0 : void AccessibleTextHelper_Impl::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException))
781 : {
782 :
783 : // This should only be called with solar mutex locked, i.e. from the main office thread
784 :
785 : // shutdown old edit source
786 0 : ShutdownEditSource();
787 :
788 : // set new edit source
789 0 : maEditSource.SetEditSource( pEditSource );
790 :
791 : // init child vector to the current child count
792 0 : if( maEditSource.IsValid() )
793 : {
794 0 : maParaManager.SetNum( GetTextForwarder().GetParagraphCount() );
795 :
796 : // listen on new edit source
797 0 : StartListening( maEditSource.GetBroadcaster() );
798 :
799 0 : UpdateVisibleChildren();
800 : }
801 0 : }
802 : SAL_WNODEPRECATED_DECLARATIONS_POP
803 :
804 0 : void AccessibleTextHelper_Impl::SetOffset( const Point& rPoint )
805 : {
806 :
807 : // guard against non-atomic access to maOffset data structure
808 : {
809 0 : ::osl::MutexGuard aGuard( maMutex );
810 0 : maOffset = rPoint;
811 : }
812 :
813 0 : maParaManager.SetEEOffset( rPoint );
814 :
815 : // in all cases, check visibility afterwards.
816 0 : UpdateVisibleChildren();
817 0 : UpdateBoundRect();
818 0 : }
819 :
820 0 : void AccessibleTextHelper_Impl::UpdateVisibleChildren( bool bBroadcastEvents )
821 : {
822 :
823 : try
824 : {
825 0 : SvxTextForwarder& rCacheTF = GetTextForwarder();
826 0 : SvxViewForwarder& rCacheVF = GetViewForwarder();
827 :
828 0 : Rectangle aViewArea = rCacheVF.GetVisArea();
829 :
830 0 : if( IsActive() )
831 : {
832 : // maybe the edit view scrolls, adapt aViewArea
833 0 : Rectangle aEditViewArea = GetEditViewForwarder().GetVisArea();
834 0 : aViewArea += aEditViewArea.TopLeft();
835 :
836 : // now determine intersection
837 0 : aViewArea.Intersection( aEditViewArea );
838 : }
839 :
840 0 : Rectangle aTmpBB, aParaBB;
841 0 : sal_Bool bFirstChild = sal_True;
842 : sal_Int32 nCurrPara;
843 0 : sal_Int32 nParas=rCacheTF.GetParagraphCount();
844 :
845 0 : mnFirstVisibleChild = -1;
846 0 : mnLastVisibleChild = -2;
847 :
848 0 : for( nCurrPara=0; nCurrPara<nParas; ++nCurrPara )
849 : {
850 : DBG_ASSERT(nCurrPara >= 0 && nCurrPara <= USHRT_MAX,
851 : "AccessibleTextHelper_Impl::UpdateVisibleChildren: index value overflow");
852 :
853 0 : aTmpBB = rCacheTF.GetParaBounds( nCurrPara );
854 :
855 : // convert to screen coordinates
856 0 : aParaBB = ::accessibility::AccessibleEditableTextPara::LogicToPixel( aTmpBB, rCacheTF.GetMapMode(), rCacheVF );
857 : // at least partially visible
858 0 : if( bFirstChild )
859 : {
860 0 : bFirstChild = sal_False;
861 0 : mnFirstVisibleChild = nCurrPara;
862 : }
863 :
864 0 : mnLastVisibleChild = nCurrPara;
865 :
866 : // child not yet created?
867 0 : ::accessibility::AccessibleParaManager::WeakChild aChild( maParaManager.GetChild(nCurrPara) );
868 0 : if( aChild.second.Width == 0 &&
869 0 : aChild.second.Height == 0 &&
870 0 : mxFrontEnd.is() &&
871 : bBroadcastEvents )
872 : {
873 : GotPropertyEvent( uno::makeAny( maParaManager.CreateChild( nCurrPara - mnFirstVisibleChild,
874 0 : mxFrontEnd, GetEditSource(), nCurrPara ).first ),
875 0 : AccessibleEventId::CHILD );
876 : }
877 0 : }
878 : }
879 0 : catch( const uno::Exception& )
880 : {
881 : OSL_FAIL("AccessibleTextHelper_Impl::UpdateVisibleChildren error while determining visible children");
882 :
883 : // something failed - currently no children
884 0 : mnFirstVisibleChild = -1;
885 0 : mnLastVisibleChild = -2;
886 0 : maParaManager.SetNum(0);
887 :
888 : // lost all children
889 0 : if( bBroadcastEvents )
890 0 : FireEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN);
891 : }
892 0 : }
893 :
894 : // functor for checking changes in paragraph bounding boxes (no stand-alone function, maybe not inlined)
895 : class AccessibleTextHelper_UpdateChildBounds : public ::std::unary_function< const ::accessibility::AccessibleParaManager::WeakChild&,
896 : ::accessibility::AccessibleParaManager::WeakChild >
897 : {
898 : public:
899 0 : AccessibleTextHelper_UpdateChildBounds( AccessibleTextHelper_Impl& rImpl ) : mrImpl(rImpl) {}
900 0 : ::accessibility::AccessibleParaManager::WeakChild operator()( const ::accessibility::AccessibleParaManager::WeakChild& rChild )
901 : {
902 : // retrieve hard reference from weak one
903 0 : ::accessibility::AccessibleParaManager::WeakPara::HardRefType aHardRef( rChild.first.get() );
904 :
905 0 : if( aHardRef.is() )
906 : {
907 0 : awt::Rectangle aNewRect = aHardRef->getBounds();
908 0 : const awt::Rectangle& aOldRect = rChild.second;
909 :
910 0 : if( aNewRect.X != aOldRect.X ||
911 0 : aNewRect.Y != aOldRect.Y ||
912 0 : aNewRect.Width != aOldRect.Width ||
913 0 : aNewRect.Height != aOldRect.Height )
914 : {
915 : // visible data changed
916 0 : aHardRef->FireEvent( AccessibleEventId::BOUNDRECT_CHANGED );
917 :
918 : // update internal bounds
919 0 : return ::accessibility::AccessibleParaManager::WeakChild( rChild.first, aNewRect );
920 : }
921 : }
922 :
923 : // identity transform
924 0 : return rChild;
925 : }
926 :
927 : private:
928 : AccessibleTextHelper_Impl& mrImpl;
929 : };
930 :
931 0 : void AccessibleTextHelper_Impl::UpdateBoundRect()
932 : {
933 :
934 : // send BOUNDRECT_CHANGED to affected children
935 0 : AccessibleTextHelper_UpdateChildBounds aFunctor( *this );
936 0 : ::std::transform( maParaManager.begin(), maParaManager.end(), maParaManager.begin(), aFunctor );
937 0 : }
938 :
939 : #ifdef DBG_UTIL
940 : void AccessibleTextHelper_Impl::CheckInvariants() const
941 : {
942 : if( mnFirstVisibleChild >= 0 &&
943 : mnFirstVisibleChild > mnLastVisibleChild )
944 : {
945 : OSL_FAIL( "AccessibleTextHelper: range invalid" );
946 : }
947 : }
948 : #endif
949 :
950 : // functor for sending child events (no stand-alone function, they are maybe not inlined)
951 : class AccessibleTextHelper_LostChildEvent : public ::std::unary_function< const ::accessibility::AccessibleParaManager::WeakChild&, void >
952 : {
953 : public:
954 0 : AccessibleTextHelper_LostChildEvent( AccessibleTextHelper_Impl& rImpl ) : mrImpl(rImpl) {}
955 0 : void operator()( const ::accessibility::AccessibleParaManager::WeakChild& rPara )
956 : {
957 : // retrieve hard reference from weak one
958 0 : ::accessibility::AccessibleParaManager::WeakPara::HardRefType aHardRef( rPara.first.get() );
959 :
960 0 : if( aHardRef.is() )
961 0 : mrImpl.FireEvent(AccessibleEventId::CHILD, uno::Any(), uno::makeAny( aHardRef.getRef() ) );
962 0 : }
963 :
964 : private:
965 : AccessibleTextHelper_Impl& mrImpl;
966 : };
967 :
968 0 : void AccessibleTextHelper_Impl::ParagraphsMoved( sal_Int32 nFirst, sal_Int32 nMiddle, sal_Int32 nLast )
969 : {
970 :
971 0 : const sal_Int32 nParas = GetTextForwarder().GetParagraphCount();
972 :
973 : /* rotate paragraphs
974 : * =================
975 : *
976 : * Three cases:
977 : *
978 : * 1.
979 : * ... nParagraph ... nParam1 ... nParam2 ...
980 : * |______________[xxxxxxxxxxx]
981 : * becomes
982 : * [xxxxxxxxxxx]|______________
983 : *
984 : * tail is 0
985 : *
986 : * 2.
987 : * ... nParam1 ... nParagraph ... nParam2 ...
988 : * [xxxxxxxxxxx|xxxxxxxxxxxxxx]____________
989 : * becomes
990 : * ____________[xxxxxxxxxxx|xxxxxxxxxxxxxx]
991 : *
992 : * tail is nParagraph - nParam1
993 : *
994 : * 3.
995 : * ... nParam1 ... nParam2 ... nParagraph ...
996 : * [xxxxxxxxxxx]___________|____________
997 : * becomes
998 : * ___________|____________[xxxxxxxxxxx]
999 : *
1000 : * tail is nParam2 - nParam1
1001 : */
1002 :
1003 : // sort nParagraph, nParam1 and nParam2 in ascending order, calc range
1004 0 : if( nMiddle < nFirst )
1005 : {
1006 0 : ::std::swap(nFirst, nMiddle);
1007 : }
1008 0 : else if( nMiddle < nLast )
1009 : {
1010 0 : nLast = nLast + nMiddle - nFirst;
1011 : }
1012 : else
1013 : {
1014 0 : ::std::swap(nMiddle, nLast);
1015 0 : nLast = nLast + nMiddle - nFirst;
1016 : }
1017 :
1018 0 : if( nFirst < nParas && nMiddle < nParas && nLast < nParas )
1019 : {
1020 : // since we have no "paragraph index
1021 : // changed" event on UAA, remove
1022 : // [first,last] and insert again later (in
1023 : // UpdateVisibleChildren)
1024 :
1025 : // maParaManager.Rotate( nFirst, nMiddle, nLast );
1026 :
1027 : // send CHILD_EVENT to affected children
1028 0 : ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator begin = maParaManager.begin();
1029 0 : ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator end = begin;
1030 :
1031 0 : ::std::advance( begin, nFirst );
1032 0 : ::std::advance( end, nLast+1 );
1033 :
1034 : // TODO: maybe optimize here in the following way. If the
1035 : // number of removed children exceeds a certain threshold,
1036 : // use INVALIDATE_CHILDREN
1037 0 : AccessibleTextHelper_LostChildEvent aFunctor( *this );
1038 :
1039 0 : ::std::for_each( begin, end, aFunctor );
1040 :
1041 0 : maParaManager.Release(nFirst, nLast+1);
1042 : // should be no need for UpdateBoundRect, since all affected children are cleared.
1043 : }
1044 0 : }
1045 :
1046 : // functor for sending child events (no stand-alone function, they are maybe not inlined)
1047 : class AccessibleTextHelper_ChildrenTextChanged : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void >
1048 : {
1049 : public:
1050 0 : void operator()( ::accessibility::AccessibleEditableTextPara& rPara )
1051 : {
1052 0 : rPara.TextChanged();
1053 0 : }
1054 : };
1055 :
1056 : /** functor processing queue events
1057 :
1058 : Reacts on TEXT_HINT_PARAINSERTED/REMOVED events and stores
1059 : their content
1060 : */
1061 : class AccessibleTextHelper_QueueFunctor : public ::std::unary_function< const SfxHint*, void >
1062 : {
1063 : public:
1064 0 : AccessibleTextHelper_QueueFunctor() :
1065 : mnParasChanged( 0 ),
1066 : mnParaIndex(-1),
1067 0 : mnHintId(-1)
1068 0 : {}
1069 0 : void operator()( const SfxHint* pEvent )
1070 : {
1071 0 : if( pEvent &&
1072 0 : mnParasChanged != -1 )
1073 : {
1074 : // determine hint type
1075 0 : const TextHint* pTextHint = PTR_CAST( TextHint, pEvent );
1076 0 : const SvxEditSourceHint* pEditSourceHint = PTR_CAST( SvxEditSourceHint, pEvent );
1077 :
1078 0 : if( !pEditSourceHint && pTextHint &&
1079 0 : (pTextHint->GetId() == TEXT_HINT_PARAINSERTED ||
1080 0 : pTextHint->GetId() == TEXT_HINT_PARAREMOVED ) )
1081 : {
1082 0 : if( pTextHint->GetValue() == EE_PARA_ALL )
1083 : {
1084 0 : mnParasChanged = -1;
1085 : }
1086 : else
1087 : {
1088 0 : mnHintId = pTextHint->GetId();
1089 0 : mnParaIndex = pTextHint->GetValue();
1090 0 : ++mnParasChanged;
1091 : }
1092 : }
1093 : }
1094 0 : }
1095 :
1096 : /** Query number of paragraphs changed during queue processing.
1097 :
1098 : @return number of changed paragraphs, -1 for
1099 : "every paragraph changed"
1100 : */
1101 0 : sal_Int32 GetNumberOfParasChanged() { return mnParasChanged; }
1102 : /** Query index of last added/removed paragraph
1103 :
1104 : @return index of lastly added paragraphs, -1 for none
1105 : added so far.
1106 : */
1107 0 : sal_Int32 GetParaIndex() { return mnParaIndex; }
1108 : /** Query hint id of last interesting event
1109 :
1110 : @return hint id of last interesting event (REMOVED/INSERTED).
1111 : */
1112 0 : int GetHintId() { return mnHintId; }
1113 :
1114 : private:
1115 : /** number of paragraphs changed during queue processing. -1 for
1116 : "every paragraph changed"
1117 : */
1118 : sal_Int32 mnParasChanged;
1119 : /// index of paragraph added/removed last
1120 : sal_Int32 mnParaIndex;
1121 : /// TextHint ID (removed/inserted) of last interesting event
1122 : int mnHintId;
1123 : };
1124 :
1125 0 : void AccessibleTextHelper_Impl::ProcessQueue()
1126 : {
1127 :
1128 : // inspect queue for paragraph insert/remove events. If there
1129 : // is exactly _one_ of those in the queue, and the number of
1130 : // paragraphs has changed by exactly one, use that event to
1131 : // determine a priori which paragraph was added/removed. This
1132 : // is necessary, since I must sync right here with the
1133 : // EditEngine state (number of paragraphs etc.), since I'm
1134 : // potentially sending listener events right away.
1135 0 : AccessibleTextHelper_QueueFunctor aFunctor;
1136 0 : maEventQueue.ForEach( aFunctor );
1137 :
1138 0 : const sal_Int32 nNewParas( GetTextForwarder().GetParagraphCount() );
1139 0 : const sal_Int32 nCurrParas( maParaManager.GetNum() );
1140 :
1141 : // whether every paragraph already is updated (no need to
1142 : // repeat that later on, e.g. for PARA_MOVED events)
1143 0 : bool bEverythingUpdated( false );
1144 :
1145 0 : if( labs( nNewParas - nCurrParas ) == 1 &&
1146 0 : aFunctor.GetNumberOfParasChanged() == 1 )
1147 : {
1148 : // #103483# Exactly one paragraph added/removed. This is
1149 : // the normal case, optimize event handling here.
1150 :
1151 0 : if( aFunctor.GetHintId() == TEXT_HINT_PARAINSERTED )
1152 : {
1153 : // update num of paras
1154 0 : maParaManager.SetNum( nNewParas );
1155 :
1156 : // release everything from the insertion position until the end
1157 0 : maParaManager.Release(aFunctor.GetParaIndex(), nCurrParas);
1158 :
1159 : // TODO: Clarify whether this behaviour _really_ saves
1160 : // anybody anything!
1161 : // update children, _don't_ broadcast
1162 0 : UpdateVisibleChildren( false );
1163 0 : UpdateBoundRect();
1164 :
1165 : // send insert event
1166 : // #109864# Enforce creation of this paragraph
1167 : try
1168 : {
1169 0 : GotPropertyEvent( uno::makeAny( getAccessibleChild( aFunctor.GetParaIndex() -
1170 0 : mnFirstVisibleChild + GetStartIndex() ) ),
1171 0 : AccessibleEventId::CHILD );
1172 : }
1173 0 : catch( const uno::Exception& )
1174 : {
1175 : OSL_FAIL("AccessibleTextHelper_Impl::ProcessQueue: could not create new paragraph");
1176 : }
1177 : }
1178 0 : else if( aFunctor.GetHintId() == TEXT_HINT_PARAREMOVED )
1179 : {
1180 0 : ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator begin = maParaManager.begin();
1181 0 : ::std::advance( begin, aFunctor.GetParaIndex() );
1182 0 : ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator end = begin;
1183 0 : ::std::advance( end, 1 );
1184 :
1185 : // #i61812# remember para to be removed for later notification
1186 : // AFTER the new state is applied (that after the para got removed)
1187 0 : ::uno::Reference< XAccessible > xPara;
1188 0 : ::accessibility::AccessibleParaManager::WeakPara::HardRefType aHardRef( begin->first.get() );
1189 0 : if( aHardRef.is() )
1190 0 : xPara = ::uno::Reference< XAccessible >( aHardRef.getRef(), ::uno::UNO_QUERY );
1191 :
1192 : // release everything from the remove position until the end
1193 0 : maParaManager.Release(aFunctor.GetParaIndex(), nCurrParas);
1194 :
1195 : // update num of paras
1196 0 : maParaManager.SetNum( nNewParas );
1197 :
1198 : // TODO: Clarify whether this behaviour _really_ saves
1199 : // anybody anything!
1200 : // update children, _don't_ broadcast
1201 0 : UpdateVisibleChildren( false );
1202 0 : UpdateBoundRect();
1203 :
1204 : // #i61812# notification for removed para
1205 0 : if (xPara.is())
1206 0 : FireEvent(AccessibleEventId::CHILD, uno::Any(), uno::makeAny( xPara) );
1207 : }
1208 : #ifdef DBG_UTIL
1209 : else
1210 : OSL_FAIL("AccessibleTextHelper_Impl::ProcessQueue() invalid hint id");
1211 : #endif
1212 : }
1213 0 : else if( nNewParas != nCurrParas )
1214 : {
1215 : // release all paras
1216 0 : maParaManager.Release(0, nCurrParas);
1217 :
1218 : // update num of paras
1219 0 : maParaManager.SetNum( nNewParas );
1220 :
1221 : // #109864# create from scratch, don't broadcast
1222 0 : UpdateVisibleChildren( false );
1223 0 : UpdateBoundRect();
1224 :
1225 : // number of paragraphs somehow changed - but we have no
1226 : // chance determining how. Thus, throw away everything and
1227 : // create from scratch.
1228 : // (child events should be broadcast after the changes are done...)
1229 0 : FireEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN);
1230 :
1231 : // no need for further updates later on
1232 0 : bEverythingUpdated = true;
1233 : }
1234 :
1235 0 : while( !maEventQueue.IsEmpty() )
1236 : {
1237 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
1238 0 : ::std::auto_ptr< SfxHint > pHint( maEventQueue.PopFront() );
1239 : SAL_WNODEPRECATED_DECLARATIONS_POP
1240 0 : if( pHint.get() )
1241 : {
1242 0 : const SfxHint& rHint = *(pHint.get());
1243 :
1244 : // determine hint type
1245 0 : const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
1246 0 : const SfxSimpleHint* pSimpleHint = PTR_CAST( SfxSimpleHint, &rHint );
1247 0 : const TextHint* pTextHint = PTR_CAST( TextHint, &rHint );
1248 0 : const SvxViewHint* pViewHint = PTR_CAST( SvxViewHint, &rHint );
1249 0 : const SvxEditSourceHint* pEditSourceHint = PTR_CAST( SvxEditSourceHint, &rHint );
1250 :
1251 : try
1252 : {
1253 0 : const sal_Int32 nParas = GetTextForwarder().GetParagraphCount();
1254 :
1255 0 : if( pEditSourceHint )
1256 : {
1257 0 : switch( pEditSourceHint->GetId() )
1258 : {
1259 : case EDITSOURCE_HINT_PARASMOVED:
1260 : {
1261 : DBG_ASSERT( pEditSourceHint->GetStartValue() < GetTextForwarder().GetParagraphCount() &&
1262 : pEditSourceHint->GetEndValue() < GetTextForwarder().GetParagraphCount(),
1263 : "AccessibleTextHelper_Impl::NotifyHdl: Invalid notification");
1264 :
1265 0 : if( !bEverythingUpdated )
1266 : {
1267 : ParagraphsMoved(pEditSourceHint->GetStartValue(),
1268 0 : pEditSourceHint->GetValue(),
1269 0 : pEditSourceHint->GetEndValue());
1270 :
1271 : // in all cases, check visibility afterwards.
1272 0 : UpdateVisibleChildren();
1273 : }
1274 0 : break;
1275 : }
1276 :
1277 : case EDITSOURCE_HINT_SELECTIONCHANGED:
1278 : // notify listeners
1279 : try
1280 : {
1281 0 : UpdateSelection();
1282 : }
1283 : // maybe we're not in edit mode (this is not an error)
1284 0 : catch( const uno::Exception& ) {}
1285 0 : break;
1286 : }
1287 : }
1288 0 : else if( pTextHint )
1289 : {
1290 0 : switch( pTextHint->GetId() )
1291 : {
1292 : case TEXT_HINT_MODIFIED:
1293 : {
1294 : // notify listeners
1295 0 : sal_Int32 nPara( pTextHint->GetValue() );
1296 :
1297 : // #108900# Delegate change event to children
1298 : AccessibleTextHelper_ChildrenTextChanged aNotifyChildrenFunctor;
1299 :
1300 0 : if( nPara == EE_PARA_ALL )
1301 : {
1302 : // #108900# Call every child
1303 : ::std::for_each( maParaManager.begin(), maParaManager.end(),
1304 0 : AccessibleParaManager::WeakChildAdapter< AccessibleTextHelper_ChildrenTextChanged > (aNotifyChildrenFunctor) );
1305 : }
1306 : else
1307 0 : if( nPara < nParas )
1308 : {
1309 : // #108900# Call child at index nPara
1310 0 : ::std::for_each( maParaManager.begin()+nPara, maParaManager.begin()+nPara+1,
1311 0 : AccessibleParaManager::WeakChildAdapter< AccessibleTextHelper_ChildrenTextChanged > (aNotifyChildrenFunctor) );
1312 : }
1313 0 : break;
1314 : }
1315 :
1316 : case TEXT_HINT_PARAINSERTED:
1317 : // already happened above
1318 0 : break;
1319 :
1320 : case TEXT_HINT_PARAREMOVED:
1321 : // already happened above
1322 0 : break;
1323 :
1324 : case TEXT_HINT_TEXTHEIGHTCHANGED:
1325 : // visibility changed, done below
1326 0 : break;
1327 :
1328 : case TEXT_HINT_VIEWSCROLLED:
1329 : // visibility changed, done below
1330 0 : break;
1331 : }
1332 :
1333 : // in all cases, check visibility afterwards.
1334 0 : UpdateVisibleChildren();
1335 0 : UpdateBoundRect();
1336 : }
1337 0 : else if( pViewHint )
1338 : {
1339 0 : switch( pViewHint->GetHintType() )
1340 : {
1341 : case SvxViewHint::SVX_HINT_VIEWCHANGED:
1342 : // just check visibility
1343 0 : UpdateVisibleChildren();
1344 0 : UpdateBoundRect();
1345 0 : break;
1346 : }
1347 : }
1348 0 : else if( pSdrHint )
1349 : {
1350 0 : switch( pSdrHint->GetKind() )
1351 : {
1352 : case HINT_BEGEDIT:
1353 : {
1354 0 : if(!IsActive())
1355 : {
1356 0 : break;
1357 : }
1358 : // change children state
1359 0 : maParaManager.SetActive();
1360 :
1361 : // per definition, edit mode text has the focus
1362 0 : SetFocus( sal_True );
1363 0 : break;
1364 : }
1365 :
1366 : case HINT_ENDEDIT:
1367 : {
1368 : // focused child now looses focus
1369 0 : ESelection aSelection;
1370 0 : if( GetEditViewForwarder().GetSelection( aSelection ) )
1371 0 : SetChildFocus( aSelection.nEndPara, sal_False );
1372 :
1373 : // change children state
1374 0 : maParaManager.SetActive( false );
1375 :
1376 : maLastSelection = ESelection( EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND,
1377 0 : EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND);
1378 0 : break;
1379 : }
1380 : default:
1381 0 : break;
1382 : }
1383 : }
1384 : // it's VITAL to keep the SfxSimpleHint last! It's the base of some classes above!
1385 0 : else if( pSimpleHint )
1386 : {
1387 0 : switch( pSimpleHint->GetId() )
1388 : {
1389 : case SFX_HINT_DYING:
1390 : // edit source is dying under us, become defunc then
1391 : try
1392 : {
1393 : // make edit source inaccessible
1394 : // Note: cannot destroy it here, since we're called from there!
1395 0 : ShutdownEditSource();
1396 : }
1397 0 : catch( const uno::Exception& ) {}
1398 :
1399 0 : break;
1400 : }
1401 : }
1402 : }
1403 0 : catch( const uno::Exception& )
1404 : {
1405 : #ifdef DBG_UTIL
1406 : OSL_TRACE("AccessibleTextHelper_Impl::ProcessQueue: Unhandled exception.");
1407 : #endif
1408 : }
1409 : }
1410 0 : }
1411 0 : }
1412 :
1413 0 : void AccessibleTextHelper_Impl::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
1414 : {
1415 :
1416 : // precondition: solar mutex locked
1417 : DBG_TESTSOLARMUTEX();
1418 :
1419 : // precondition: not in a recursion
1420 0 : if( mbInNotify )
1421 0 : return;
1422 :
1423 0 : mbInNotify = true;
1424 :
1425 : // determine hint type
1426 0 : const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
1427 0 : const SfxSimpleHint* pSimpleHint = PTR_CAST( SfxSimpleHint, &rHint );
1428 0 : const TextHint* pTextHint = PTR_CAST( TextHint, &rHint );
1429 0 : const SvxViewHint* pViewHint = PTR_CAST( SvxViewHint, &rHint );
1430 0 : const SvxEditSourceHint* pEditSourceHint = PTR_CAST( SvxEditSourceHint, &rHint );
1431 :
1432 : try
1433 : {
1434 : // Process notification event
1435 0 : if( pEditSourceHint )
1436 : {
1437 0 : maEventQueue.Append( *pEditSourceHint );
1438 : // EditEngine should emit TEXT_SELECTION_CHANGED events (#i27299#)
1439 0 : if( maEventOpenFrames == 0 )
1440 0 : ProcessQueue();
1441 : }
1442 0 : else if( pTextHint )
1443 : {
1444 0 : switch( pTextHint->GetId() )
1445 : {
1446 : case TEXT_HINT_BLOCKNOTIFICATION_END:
1447 : case TEXT_HINT_INPUT_END:
1448 0 : --maEventOpenFrames;
1449 :
1450 0 : if( maEventOpenFrames == 0 )
1451 : {
1452 : // #103483#
1453 : /* All information should have arrived
1454 : * now, process queue. As stated in the
1455 : * above bug, we can often avoid throwing
1456 : * away all paragraphs by looking forward
1457 : * in the event queue (searching for
1458 : * PARAINSERT/REMOVE events). Furthermore,
1459 : * processing the event queue only at the
1460 : * end of an interaction cycle, ensures
1461 : * that the EditEngine state and the
1462 : * AccessibleText state are the same
1463 : * (well, mostly. If there are _multiple_
1464 : * interaction cycles in the EE queues, it
1465 : * can still happen that EE state is
1466 : * different. That's so to say broken by
1467 : * design with that delayed EE event
1468 : * concept).
1469 : */
1470 0 : ProcessQueue();
1471 : }
1472 0 : break;
1473 :
1474 : case TEXT_HINT_BLOCKNOTIFICATION_START:
1475 : case TEXT_HINT_INPUT_START:
1476 0 : ++maEventOpenFrames;
1477 : // no FALLTHROUGH reason: event will not be processed,
1478 : // thus appending the event isn't necessary. (#i27299#)
1479 0 : break;
1480 : default:
1481 0 : maEventQueue.Append( *pTextHint );
1482 : // EditEngine should emit TEXT_SELECTION_CHANGED events (#i27299#)
1483 0 : if( maEventOpenFrames == 0 )
1484 0 : ProcessQueue();
1485 0 : break;
1486 : }
1487 : }
1488 0 : else if( pViewHint )
1489 : {
1490 0 : maEventQueue.Append( *pViewHint );
1491 :
1492 : // process visibility right away, if not within an
1493 : // open EE notification frame. Otherwise, event
1494 : // processing would be delayed until next EE
1495 : // notification sequence.
1496 0 : if( maEventOpenFrames == 0 )
1497 0 : ProcessQueue();
1498 : }
1499 0 : else if( pSdrHint )
1500 : {
1501 0 : maEventQueue.Append( *pSdrHint );
1502 :
1503 : // process drawing layer events right away, if not
1504 : // within an open EE notification frame. Otherwise,
1505 : // event processing would be delayed until next EE
1506 : // notification sequence.
1507 0 : if( maEventOpenFrames == 0 )
1508 0 : ProcessQueue();
1509 : }
1510 : // it's VITAL to keep the SfxSimpleHint last! It's the base of some classes above!
1511 0 : else if( pSimpleHint )
1512 : {
1513 : // handle this event _at once_, because after that, objects are invalid
1514 0 : switch( pSimpleHint->GetId() )
1515 : {
1516 : case SFX_HINT_DYING:
1517 : // edit source is dying under us, become defunc then
1518 0 : maEventQueue.Clear();
1519 : try
1520 : {
1521 : // make edit source inaccessible
1522 : // Note: cannot destroy it here, since we're called from there!
1523 0 : ShutdownEditSource();
1524 : }
1525 0 : catch( const uno::Exception& ) {}
1526 :
1527 0 : break;
1528 : }
1529 : }
1530 : }
1531 0 : catch( const uno::Exception& )
1532 : {
1533 : #ifdef DBG_UTIL
1534 : OSL_TRACE("AccessibleTextHelper_Impl::Notify: Unhandled exception.");
1535 : #endif
1536 0 : mbInNotify = false;
1537 : }
1538 :
1539 0 : mbInNotify = false;
1540 : }
1541 :
1542 0 : void AccessibleTextHelper_Impl::Dispose()
1543 : {
1544 :
1545 0 : if( getNotifierClientId() != -1 )
1546 : {
1547 : try
1548 : {
1549 : // #106234# Unregister from EventNotifier
1550 0 : ::comphelper::AccessibleEventNotifier::revokeClient( getNotifierClientId() );
1551 : #ifdef DBG_UTIL
1552 : OSL_TRACE( "AccessibleTextHelper_Impl disposed ID: %d", mnNotifierClientId );
1553 : #endif
1554 : }
1555 0 : catch( const uno::Exception& ) {}
1556 :
1557 0 : mnNotifierClientId = -1;
1558 : }
1559 :
1560 : try
1561 : {
1562 : // dispose children
1563 0 : maParaManager.Dispose();
1564 : }
1565 0 : catch( const uno::Exception& ) {}
1566 :
1567 : // quit listen on stale edit source
1568 0 : if( maEditSource.IsValid() )
1569 0 : EndListening( maEditSource.GetBroadcaster() );
1570 :
1571 : // clear references
1572 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
1573 0 : maEditSource.SetEditSource( ::std::auto_ptr< SvxEditSource >(NULL) );
1574 : SAL_WNODEPRECATED_DECLARATIONS_POP
1575 0 : mxFrontEnd = NULL;
1576 0 : }
1577 :
1578 0 : void AccessibleTextHelper_Impl::FireEvent( const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue ) const
1579 : {
1580 :
1581 : // -- object locked --
1582 0 : ::osl::ClearableMutexGuard aGuard( maMutex );
1583 :
1584 0 : AccessibleEventObject aEvent;
1585 :
1586 : DBG_ASSERT(mxFrontEnd.is(), "AccessibleTextHelper::FireEvent: no event source set" );
1587 :
1588 0 : if( mxFrontEnd.is() )
1589 0 : aEvent = AccessibleEventObject(mxFrontEnd->getAccessibleContext(), nEventId, rNewValue, rOldValue);
1590 : else
1591 0 : aEvent = AccessibleEventObject(uno::Reference< uno::XInterface >(), nEventId, rNewValue, rOldValue);
1592 :
1593 : // no locking necessary, FireEvent internally copies listeners
1594 : // if someone removes/adds in between Further locking,
1595 : // actually, might lead to deadlocks, since we're calling out
1596 : // of this object
1597 0 : aGuard.clear();
1598 : // -- until here --
1599 :
1600 0 : FireEvent(aEvent);
1601 0 : }
1602 :
1603 0 : void AccessibleTextHelper_Impl::FireEvent( const AccessibleEventObject& rEvent ) const
1604 : {
1605 :
1606 : // #102261# Call global queue for focus events
1607 0 : if( rEvent.EventId == AccessibleStateType::FOCUSED )
1608 0 : vcl::unohelper::NotifyAccessibleStateEventGlobally( rEvent );
1609 :
1610 : // #106234# Delegate to EventNotifier
1611 0 : ::comphelper::AccessibleEventNotifier::addEvent( getNotifierClientId(),
1612 0 : rEvent );
1613 0 : }
1614 :
1615 : // XAccessibleContext
1616 0 : sal_Int32 SAL_CALL AccessibleTextHelper_Impl::getAccessibleChildCount() SAL_THROW((uno::RuntimeException))
1617 : {
1618 :
1619 0 : return mnLastVisibleChild - mnFirstVisibleChild + 1;
1620 : }
1621 :
1622 0 : uno::Reference< XAccessible > SAL_CALL AccessibleTextHelper_Impl::getAccessibleChild( sal_Int32 i ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException))
1623 : {
1624 :
1625 0 : i -= GetStartIndex();
1626 :
1627 0 : if( 0 > i || i >= getAccessibleChildCount() ||
1628 0 : GetTextForwarder().GetParagraphCount() <= i )
1629 : {
1630 0 : throw lang::IndexOutOfBoundsException("Invalid child index", mxFrontEnd);
1631 : }
1632 :
1633 : DBG_ASSERT(mxFrontEnd.is(), "AccessibleTextHelper_Impl::UpdateVisibleChildren: no frontend set");
1634 :
1635 0 : if( mxFrontEnd.is() )
1636 0 : return maParaManager.CreateChild( i, mxFrontEnd, GetEditSource(), mnFirstVisibleChild + i ).first;
1637 : else
1638 0 : return NULL;
1639 : }
1640 :
1641 0 : void SAL_CALL AccessibleTextHelper_Impl::addAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException))
1642 : {
1643 :
1644 0 : if( getNotifierClientId() != -1 )
1645 0 : ::comphelper::AccessibleEventNotifier::addEventListener( getNotifierClientId(), xListener );
1646 0 : }
1647 :
1648 0 : void SAL_CALL AccessibleTextHelper_Impl::removeAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException))
1649 : {
1650 :
1651 0 : if( getNotifierClientId() != -1 )
1652 0 : ::comphelper::AccessibleEventNotifier::removeEventListener( getNotifierClientId(), xListener );
1653 0 : }
1654 :
1655 0 : uno::Reference< XAccessible > SAL_CALL AccessibleTextHelper_Impl::getAccessibleAtPoint( const awt::Point& _aPoint ) SAL_THROW((uno::RuntimeException))
1656 : {
1657 :
1658 : // make given position relative
1659 0 : if( !mxFrontEnd.is() )
1660 0 : throw uno::RuntimeException("AccessibleTextHelper_Impl::getAccessibleAt: frontend invalid", mxFrontEnd );
1661 :
1662 0 : uno::Reference< XAccessibleContext > xFrontEndContext = mxFrontEnd->getAccessibleContext();
1663 :
1664 0 : if( !xFrontEndContext.is() )
1665 0 : throw uno::RuntimeException("AccessibleTextHelper_Impl::getAccessibleAt: frontend invalid", mxFrontEnd );
1666 :
1667 0 : uno::Reference< XAccessibleComponent > xFrontEndComponent( xFrontEndContext, uno::UNO_QUERY );
1668 :
1669 0 : if( !xFrontEndComponent.is() )
1670 0 : throw uno::RuntimeException("AccessibleTextHelper_Impl::getAccessibleAt: frontend is no XAccessibleComponent", mxFrontEnd );
1671 :
1672 : // #103862# No longer need to make given position relative
1673 0 : Point aPoint( _aPoint.X, _aPoint.Y );
1674 :
1675 : // respect EditEngine offset to surrounding shape/cell
1676 0 : aPoint -= GetOffset();
1677 :
1678 : // convert to EditEngine coordinate system
1679 0 : SvxTextForwarder& rCacheTF = GetTextForwarder();
1680 0 : Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) );
1681 :
1682 : // iterate over all visible children (including those not yet created)
1683 : sal_Int32 nChild;
1684 0 : for( nChild=mnFirstVisibleChild; nChild <= mnLastVisibleChild; ++nChild )
1685 : {
1686 : DBG_ASSERT(nChild >= 0 && nChild <= USHRT_MAX,
1687 : "AccessibleTextHelper_Impl::getAccessibleAt: index value overflow");
1688 :
1689 0 : Rectangle aParaBounds( rCacheTF.GetParaBounds( nChild ) );
1690 :
1691 0 : if( aParaBounds.IsInside( aLogPoint ) )
1692 0 : return getAccessibleChild( nChild - mnFirstVisibleChild + GetStartIndex() );
1693 : }
1694 :
1695 : // found none
1696 0 : return NULL;
1697 : }
1698 :
1699 :
1700 :
1701 : // AccessibleTextHelper implementation (simply forwards to impl)
1702 :
1703 :
1704 :
1705 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
1706 0 : AccessibleTextHelper::AccessibleTextHelper( ::std::auto_ptr< SvxEditSource > pEditSource ) :
1707 0 : mpImpl( new AccessibleTextHelper_Impl() )
1708 : {
1709 0 : SolarMutexGuard aGuard;
1710 :
1711 0 : SetEditSource( pEditSource );
1712 0 : }
1713 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
1714 :
1715 0 : AccessibleTextHelper::~AccessibleTextHelper()
1716 : {
1717 0 : }
1718 :
1719 0 : const SvxEditSource& AccessibleTextHelper::GetEditSource() const SAL_THROW((uno::RuntimeException))
1720 : {
1721 : #ifdef DBG_UTIL
1722 : mpImpl->CheckInvariants();
1723 :
1724 : const SvxEditSource& aEditSource = mpImpl->GetEditSource();
1725 :
1726 : mpImpl->CheckInvariants();
1727 :
1728 : return aEditSource;
1729 : #else
1730 0 : return mpImpl->GetEditSource();
1731 : #endif
1732 : }
1733 :
1734 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
1735 0 : void AccessibleTextHelper::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException))
1736 : {
1737 : #ifdef DBG_UTIL
1738 : // precondition: solar mutex locked
1739 : DBG_TESTSOLARMUTEX();
1740 :
1741 : mpImpl->CheckInvariants();
1742 : #endif
1743 :
1744 0 : mpImpl->SetEditSource( pEditSource );
1745 :
1746 : #ifdef DBG_UTIL
1747 : mpImpl->CheckInvariants();
1748 : #endif
1749 0 : }
1750 : SAL_WNODEPRECATED_DECLARATIONS_POP
1751 :
1752 0 : void AccessibleTextHelper::SetEventSource( const uno::Reference< XAccessible >& rInterface )
1753 : {
1754 : #ifdef DBG_UTIL
1755 : mpImpl->CheckInvariants();
1756 : #endif
1757 :
1758 0 : mpImpl->SetEventSource( rInterface );
1759 :
1760 : #ifdef DBG_UTIL
1761 : mpImpl->CheckInvariants();
1762 : #endif
1763 0 : }
1764 :
1765 0 : uno::Reference< XAccessible > AccessibleTextHelper::GetEventSource() const
1766 : {
1767 : #ifdef DBG_UTIL
1768 : mpImpl->CheckInvariants();
1769 :
1770 : uno::Reference< XAccessible > xRet( mpImpl->GetEventSource() );
1771 :
1772 : mpImpl->CheckInvariants();
1773 :
1774 : return xRet;
1775 : #else
1776 0 : return mpImpl->GetEventSource();
1777 : #endif
1778 : }
1779 :
1780 0 : void AccessibleTextHelper::SetFocus( bool bHaveFocus ) SAL_THROW((::com::sun::star::uno::RuntimeException))
1781 : {
1782 : #ifdef DBG_UTIL
1783 : // precondition: solar mutex locked
1784 : DBG_TESTSOLARMUTEX();
1785 :
1786 : mpImpl->CheckInvariants();
1787 : #endif
1788 :
1789 0 : mpImpl->SetFocus( bHaveFocus );
1790 :
1791 : #ifdef DBG_UTIL
1792 : mpImpl->CheckInvariants();
1793 : #endif
1794 0 : }
1795 :
1796 0 : bool AccessibleTextHelper::HaveFocus() SAL_THROW((::com::sun::star::uno::RuntimeException))
1797 : {
1798 : #ifdef DBG_UTIL
1799 : mpImpl->CheckInvariants();
1800 :
1801 : bool bRet( mpImpl->HaveFocus() );
1802 :
1803 : mpImpl->CheckInvariants();
1804 :
1805 : return bRet;
1806 : #else
1807 0 : return mpImpl->HaveFocus();
1808 : #endif
1809 : }
1810 :
1811 0 : void AccessibleTextHelper::FireEvent( const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue ) const
1812 : {
1813 : #ifdef DBG_UTIL
1814 : mpImpl->CheckInvariants();
1815 : #endif
1816 :
1817 0 : mpImpl->FireEvent( nEventId, rNewValue, rOldValue );
1818 :
1819 : #ifdef DBG_UTIL
1820 : mpImpl->CheckInvariants();
1821 : #endif
1822 0 : }
1823 :
1824 0 : void AccessibleTextHelper::FireEvent( const AccessibleEventObject& rEvent ) const
1825 : {
1826 : #ifdef DBG_UTIL
1827 : mpImpl->CheckInvariants();
1828 : #endif
1829 :
1830 0 : mpImpl->FireEvent( rEvent );
1831 :
1832 : #ifdef DBG_UTIL
1833 : mpImpl->CheckInvariants();
1834 : #endif
1835 0 : }
1836 :
1837 0 : void AccessibleTextHelper::SetOffset( const Point& rPoint )
1838 : {
1839 : #ifdef DBG_UTIL
1840 : // precondition: solar mutex locked
1841 : DBG_TESTSOLARMUTEX();
1842 :
1843 : mpImpl->CheckInvariants();
1844 : #endif
1845 :
1846 0 : mpImpl->SetOffset( rPoint );
1847 :
1848 : #ifdef DBG_UTIL
1849 : mpImpl->CheckInvariants();
1850 : #endif
1851 0 : }
1852 :
1853 0 : Point AccessibleTextHelper::GetOffset() const
1854 : {
1855 : #ifdef DBG_UTIL
1856 : mpImpl->CheckInvariants();
1857 :
1858 : Point aPoint( mpImpl->GetOffset() );
1859 :
1860 : mpImpl->CheckInvariants();
1861 :
1862 : return aPoint;
1863 : #else
1864 0 : return mpImpl->GetOffset();
1865 : #endif
1866 : }
1867 :
1868 0 : void AccessibleTextHelper::SetStartIndex( sal_Int32 nOffset )
1869 : {
1870 : #ifdef DBG_UTIL
1871 : // precondition: solar mutex locked
1872 : DBG_TESTSOLARMUTEX();
1873 :
1874 : mpImpl->CheckInvariants();
1875 : #endif
1876 :
1877 0 : mpImpl->SetStartIndex( nOffset );
1878 :
1879 : #ifdef DBG_UTIL
1880 : mpImpl->CheckInvariants();
1881 : #endif
1882 0 : }
1883 :
1884 0 : sal_Int32 AccessibleTextHelper::GetStartIndex() const
1885 : {
1886 : #ifdef DBG_UTIL
1887 : mpImpl->CheckInvariants();
1888 :
1889 : sal_Int32 nOffset = mpImpl->GetStartIndex();
1890 :
1891 : mpImpl->CheckInvariants();
1892 :
1893 : return nOffset;
1894 : #else
1895 0 : return mpImpl->GetStartIndex();
1896 : #endif
1897 : }
1898 :
1899 0 : void AccessibleTextHelper::SetAdditionalChildStates( const VectorOfStates& rChildStates )
1900 : {
1901 0 : mpImpl->SetAdditionalChildStates( rChildStates );
1902 0 : }
1903 :
1904 0 : void AccessibleTextHelper::UpdateChildren() SAL_THROW((::com::sun::star::uno::RuntimeException))
1905 : {
1906 : #ifdef DBG_UTIL
1907 : // precondition: solar mutex locked
1908 : DBG_TESTSOLARMUTEX();
1909 :
1910 : mpImpl->CheckInvariants();
1911 : #endif
1912 :
1913 0 : mpImpl->UpdateVisibleChildren();
1914 0 : mpImpl->UpdateBoundRect();
1915 :
1916 0 : mpImpl->UpdateSelection();
1917 :
1918 : #ifdef DBG_UTIL
1919 : mpImpl->CheckInvariants();
1920 : #endif
1921 0 : }
1922 :
1923 0 : void AccessibleTextHelper::Dispose()
1924 : {
1925 : // As Dispose calls ShutdownEditSource, which in turn
1926 : // deregisters as listener on the edit source, have to lock
1927 : // here
1928 0 : SolarMutexGuard aGuard;
1929 :
1930 : #ifdef DBG_UTIL
1931 : mpImpl->CheckInvariants();
1932 : #endif
1933 :
1934 0 : mpImpl->Dispose();
1935 :
1936 : #ifdef DBG_UTIL
1937 : mpImpl->CheckInvariants();
1938 : #endif
1939 0 : }
1940 :
1941 0 : bool AccessibleTextHelper::IsSelected() const
1942 : {
1943 0 : SolarMutexGuard aGuard;
1944 :
1945 : #ifdef DBG_UTIL
1946 : mpImpl->CheckInvariants();
1947 :
1948 : bool aRet = mpImpl->IsSelected();
1949 :
1950 : mpImpl->CheckInvariants();
1951 :
1952 : return aRet;
1953 : #else
1954 0 : return mpImpl->IsSelected();
1955 : #endif
1956 : }
1957 :
1958 : // XAccessibleContext
1959 0 : sal_Int32 AccessibleTextHelper::GetChildCount() SAL_THROW((uno::RuntimeException))
1960 : {
1961 0 : SolarMutexGuard aGuard;
1962 :
1963 : #ifdef DBG_UTIL
1964 : mpImpl->CheckInvariants();
1965 :
1966 : sal_Int32 nRet = mpImpl->getAccessibleChildCount();
1967 :
1968 : mpImpl->CheckInvariants();
1969 :
1970 : return nRet;
1971 : #else
1972 0 : return mpImpl->getAccessibleChildCount();
1973 : #endif
1974 : }
1975 :
1976 0 : uno::Reference< XAccessible > AccessibleTextHelper::GetChild( sal_Int32 i ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException))
1977 : {
1978 0 : SolarMutexGuard aGuard;
1979 :
1980 : #ifdef DBG_UTIL
1981 : mpImpl->CheckInvariants();
1982 :
1983 : uno::Reference< XAccessible > xRet = mpImpl->getAccessibleChild( i );
1984 :
1985 : mpImpl->CheckInvariants();
1986 :
1987 : return xRet;
1988 : #else
1989 0 : return mpImpl->getAccessibleChild( i );
1990 : #endif
1991 : }
1992 :
1993 0 : void AccessibleTextHelper::AddEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException))
1994 : {
1995 : #ifdef DBG_UTIL
1996 : mpImpl->CheckInvariants();
1997 :
1998 : mpImpl->addAccessibleEventListener( xListener );
1999 :
2000 : mpImpl->CheckInvariants();
2001 : #else
2002 0 : mpImpl->addAccessibleEventListener( xListener );
2003 : #endif
2004 0 : }
2005 :
2006 0 : void AccessibleTextHelper::RemoveEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) SAL_THROW((uno::RuntimeException))
2007 : {
2008 : #ifdef DBG_UTIL
2009 : mpImpl->CheckInvariants();
2010 :
2011 : mpImpl->removeAccessibleEventListener( xListener );
2012 :
2013 : mpImpl->CheckInvariants();
2014 : #else
2015 0 : mpImpl->removeAccessibleEventListener( xListener );
2016 : #endif
2017 0 : }
2018 :
2019 : // XAccessibleComponent
2020 0 : uno::Reference< XAccessible > AccessibleTextHelper::GetAt( const awt::Point& aPoint ) SAL_THROW((uno::RuntimeException))
2021 : {
2022 0 : SolarMutexGuard aGuard;
2023 :
2024 : #ifdef DBG_UTIL
2025 : mpImpl->CheckInvariants();
2026 :
2027 : uno::Reference< XAccessible > xChild = mpImpl->getAccessibleAtPoint( aPoint );
2028 :
2029 : mpImpl->CheckInvariants();
2030 :
2031 : return xChild;
2032 : #else
2033 0 : return mpImpl->getAccessibleAtPoint( aPoint );
2034 : #endif
2035 : }
2036 :
2037 : } // end of namespace accessibility
2038 :
2039 :
2040 :
2041 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|