1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: AccessibleStaticTextBase.cxx,v $
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 //------------------------------------------------------------------------
38 //------------------------------------------------------------------------
43 #include <boost/bind.hpp>
44 #include <vos/mutex.hxx>
45 #include <vcl/window.hxx>
46 #include <vcl/svapp.hxx>
47 #include <comphelper/sequenceasvector.hxx>
48 #include <com/sun/star/uno/Any.hxx>
49 #include <com/sun/star/uno/Reference.hxx>
50 #include <com/sun/star/awt/Point.hpp>
51 #include <com/sun/star/awt/Rectangle.hpp>
52 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
54 //------------------------------------------------------------------------
56 // Project-local header
58 //------------------------------------------------------------------------
60 #include <svx/editdata.hxx>
61 #include "unopracc.hxx"
62 #include "unoedprx.hxx"
63 #include "AccessibleStaticTextBase.hxx"
64 #include "AccessibleEditableTextPara.hxx"
67 using namespace ::com::sun::star
;
68 using namespace ::com::sun::star::accessibility
;
73 - separate adapter functionality from AccessibleStaticText class
75 - refactor common loops into templates, using mem_fun
79 namespace accessibility
81 typedef ::comphelper::SequenceAsVector
< beans::PropertyValue
> PropertyValueVector
;
83 class PropertyValueEqualFunctor
: public ::std::binary_function
< beans::PropertyValue
, beans::PropertyValue
, bool >
86 PropertyValueEqualFunctor()
88 bool operator() ( const beans::PropertyValue
& lhs
, const beans::PropertyValue
& rhs
) const
90 return ( lhs
.Name
== rhs
.Name
&& lhs
.Value
== rhs
.Value
);
94 //------------------------------------------------------------------------
98 //------------------------------------------------------------------------
99 ESelection
MakeSelection( sal_Int32 nStartPara
, sal_Int32 nStartIndex
,
100 sal_Int32 nEndPara
, sal_Int32 nEndIndex
)
102 DBG_ASSERT(nStartPara
>= 0 && nStartPara
<= USHRT_MAX
&&
103 nStartIndex
>= 0 && nStartIndex
<= USHRT_MAX
&&
104 nEndPara
>= 0 && nEndPara
<= USHRT_MAX
&&
105 nEndIndex
>= 0 && nEndIndex
<= USHRT_MAX
,
106 "AccessibleStaticTextBase_Impl::MakeSelection: index value overflow");
108 return ESelection( static_cast< USHORT
>(nStartPara
), static_cast< USHORT
>(nStartIndex
),
109 static_cast< USHORT
>(nEndPara
), static_cast< USHORT
>(nEndIndex
) );
112 //------------------------------------------------------------------------
114 // AccessibleStaticTextBase_Impl declaration
116 //------------------------------------------------------------------------
118 DBG_NAME( AccessibleStaticTextBase_Impl
);
120 /** AccessibleStaticTextBase_Impl
122 This class implements the AccessibleStaticTextBase
123 functionality, mainly by forwarding the calls to an aggregated
124 AccessibleEditableTextPara. As this is a therefore non-trivial
125 adapter, factoring out the common functionality from
126 AccessibleEditableTextPara might be a profitable future task.
128 class AccessibleStaticTextBase_Impl
133 // receive pointer to our frontend class and view window
134 AccessibleStaticTextBase_Impl();
135 ~AccessibleStaticTextBase_Impl();
137 SvxEditSourceAdapter
& GetEditSource() const SAL_THROW((uno::RuntimeException
))
139 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
143 void SetEditSource( ::std::auto_ptr
< SvxEditSource
> pEditSource
) SAL_THROW((uno::RuntimeException
));
145 void SetEventSource( const uno::Reference
< XAccessible
>& rInterface
)
147 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
151 uno::Reference
< XAccessible
> GetEventSource() const
153 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
158 void SetOffset( const Point
& );
159 Point
GetOffset() const
161 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
163 ::osl::MutexGuard
aGuard( maMutex
); Point
aPoint( maOffset
);
167 void UpdateChildren();
171 void CheckInvariants() const;
174 AccessibleEditableTextPara
& GetParagraph( sal_Int32 nPara
) const;
175 sal_Int32
GetParagraphCount() const;
176 sal_Int32
GetParagraphIndex() const;
177 sal_Int32
GetLineCount( sal_Int32 nParagraph
) const;
179 EPosition
Index2Internal( sal_Int32 nFlatIndex
) const
181 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
183 return ImpCalcInternal( nFlatIndex
, false );
186 EPosition
Range2Internal( sal_Int32 nFlatIndex
) const
188 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
190 return ImpCalcInternal( nFlatIndex
, true );
193 sal_Int32
Internal2Index( EPosition nEEIndex
) const;
195 void CorrectTextSegment( TextSegment
& aTextSegment
,
198 sal_Bool
SetSelection( sal_Int32 nStartPara
, sal_Int32 nStartIndex
,
199 sal_Int32 nEndPara
, sal_Int32 nEndIndex
);
200 sal_Bool
CopyText( sal_Int32 nStartPara
, sal_Int32 nStartIndex
,
201 sal_Int32 nEndPara
, sal_Int32 nEndIndex
);
203 Rectangle
GetParagraphBoundingBox() const;
207 EPosition
ImpCalcInternal( sal_Int32 nFlatIndex
, bool bExclusive
) const;
209 // our frontend class (the one implementing the actual
210 // interface). That's not necessarily the one containing the impl
212 uno::Reference
< XAccessible
> mxThis
;
214 // implements our functionality, we're just an adapter (guarded by solar mutex)
215 mutable AccessibleEditableTextPara
* mpTextParagraph
;
217 uno::Reference
< XAccessible
> mxParagraph
;
219 // a wrapper for the text forwarders (guarded by solar mutex)
220 mutable SvxEditSourceAdapter maEditSource
;
222 // guard for maOffset
223 mutable ::osl::Mutex maMutex
;
225 /// our current offset to the containing shape/cell (guarded by maMutex)
230 //------------------------------------------------------------------------
232 // AccessibleStaticTextBase_Impl implementation
234 //------------------------------------------------------------------------
236 AccessibleStaticTextBase_Impl::AccessibleStaticTextBase_Impl() :
238 mpTextParagraph( new AccessibleEditableTextPara(NULL
) ),
239 mxParagraph( mpTextParagraph
),
244 DBG_CTOR( AccessibleStaticTextBase_Impl
, NULL
);
246 // TODO: this is still somewhat of a hack, all the more since
247 // now the maTextParagraph has an empty parent reference set
250 AccessibleStaticTextBase_Impl::~AccessibleStaticTextBase_Impl()
252 DBG_DTOR( AccessibleStaticTextBase_Impl
, NULL
);
255 void AccessibleStaticTextBase_Impl::SetEditSource( ::std::auto_ptr
< SvxEditSource
> pEditSource
) SAL_THROW((uno::RuntimeException
))
257 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
259 maEditSource
.SetEditSource( pEditSource
);
260 if( mpTextParagraph
)
261 mpTextParagraph
->SetEditSource( &maEditSource
);
264 void AccessibleStaticTextBase_Impl::SetOffset( const Point
& rPoint
)
266 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
268 // guard against non-atomic access to maOffset data structure
270 ::osl::MutexGuard
aGuard( maMutex
);
274 if( mpTextParagraph
)
275 mpTextParagraph
->SetEEOffset( rPoint
);
277 // in all cases, check visibility afterwards.
281 void AccessibleStaticTextBase_Impl::UpdateChildren()
283 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
285 // currently no children
288 void AccessibleStaticTextBase_Impl::Dispose()
290 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
292 // we're the owner of the paragraph, so destroy it, too
293 if( mpTextParagraph
)
294 mpTextParagraph
->Dispose();
299 mpTextParagraph
= NULL
;
303 void AccessibleStaticTextBase_Impl::CheckInvariants() const
309 AccessibleEditableTextPara
& AccessibleStaticTextBase_Impl::GetParagraph( sal_Int32 nPara
) const
311 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
313 if( !mpTextParagraph
)
314 throw lang::DisposedException (
315 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), mxThis
);
317 // TODO: Have a differnt method on AccessibleEditableTextPara
318 // that does not care about state changes
319 mpTextParagraph
->SetParagraphIndex( nPara
);
321 return *mpTextParagraph
;
324 sal_Int32
AccessibleStaticTextBase_Impl::GetParagraphCount() const
326 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
328 if( !mpTextParagraph
)
331 return mpTextParagraph
->GetTextForwarder().GetParagraphCount();
334 sal_Int32
AccessibleStaticTextBase_Impl::GetParagraphIndex() const
336 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
338 sal_Int32 nIndex
= -1;
339 if( mpTextParagraph
)
340 nIndex
= mpTextParagraph
->GetParagraphIndex();
344 sal_Int32
AccessibleStaticTextBase_Impl::GetLineCount( sal_Int32 nParagraph
) const
346 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
348 sal_Int32 nIndex
= 0;
349 if( mpTextParagraph
)
350 nIndex
= mpTextParagraph
->GetTextForwarder().GetLineCount( static_cast< USHORT
>(nParagraph
) );
354 sal_Int32
AccessibleStaticTextBase_Impl::Internal2Index( EPosition nEEIndex
) const
358 for(i
=0; i
<nEEIndex
.nPara
; ++i
)
359 aRes
+= GetParagraph(i
).getCharacterCount();
361 return aRes
+ nEEIndex
.nIndex
;
364 void AccessibleStaticTextBase_Impl::CorrectTextSegment( TextSegment
& aTextSegment
,
367 // Keep 'invalid' values at the TextSegment
368 if( aTextSegment
.SegmentStart
!= -1 &&
369 aTextSegment
.SegmentStart
!= -1 )
371 // #112814# Correct TextSegment by paragraph offset
372 sal_Int32
nOffset(0);
374 for(i
=0; i
<nPara
; ++i
)
375 nOffset
+= GetParagraph(i
).getCharacterCount();
377 aTextSegment
.SegmentStart
+= nOffset
;
378 aTextSegment
.SegmentEnd
+= nOffset
;
382 EPosition
AccessibleStaticTextBase_Impl::ImpCalcInternal( sal_Int32 nFlatIndex
, bool bExclusive
) const
384 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
387 throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleStaticTextBase_Impl::Index2Internal: character index out of bounds")),
389 // gratuitously accepting larger indices here, AccessibleEditableTextPara will throw eventually
391 sal_Int32 nCurrPara
, nCurrIndex
, nParas
, nCurrCount
;
392 for( nCurrPara
=0, nParas
=GetParagraphCount(), nCurrCount
=0, nCurrIndex
=0; nCurrPara
<nParas
; ++nCurrPara
)
394 nCurrCount
= GetParagraph( nCurrPara
).getCharacterCount();
395 nCurrIndex
+= nCurrCount
;
397 if( nCurrIndex
> nFlatIndex
)
400 DBG_ASSERT(nCurrPara
>= 0 && nCurrPara
<= USHRT_MAX
&&
401 nFlatIndex
- nCurrIndex
+ nCurrCount
>= 0 && nFlatIndex
- nCurrIndex
+ nCurrCount
<= USHRT_MAX
,
402 "AccessibleStaticTextBase_Impl::Index2Internal: index value overflow");
404 return EPosition( static_cast< USHORT
>(nCurrPara
), static_cast< USHORT
>(nFlatIndex
- nCurrIndex
+ nCurrCount
) );
408 // #102170# Allow one-past the end for ranges
409 if( bExclusive
&& nCurrIndex
== nFlatIndex
)
412 DBG_ASSERT(nCurrPara
>= 0 && nCurrPara
<= USHRT_MAX
&&
413 nFlatIndex
- nCurrIndex
+ nCurrCount
>= 0 && nFlatIndex
- nCurrIndex
+ nCurrCount
<= USHRT_MAX
,
414 "AccessibleStaticTextBase_Impl::Index2Internal: index value overflow");
416 return EPosition( static_cast< USHORT
>(nCurrPara
-1), static_cast< USHORT
>(nFlatIndex
- nCurrIndex
+ nCurrCount
) );
419 // not found? Out of bounds
420 throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleStaticTextBase_Impl::Index2Internal: character index out of bounds")),
424 sal_Bool
AccessibleStaticTextBase_Impl::SetSelection( sal_Int32 nStartPara
, sal_Int32 nStartIndex
,
425 sal_Int32 nEndPara
, sal_Int32 nEndIndex
)
427 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
429 if( !mpTextParagraph
)
434 SvxEditViewForwarder
& rCacheVF
= mpTextParagraph
->GetEditViewForwarder( sal_True
);
435 return rCacheVF
.SetSelection( MakeSelection(nStartPara
, nStartIndex
, nEndPara
, nEndIndex
) );
437 catch( const uno::RuntimeException
& )
443 sal_Bool
AccessibleStaticTextBase_Impl::CopyText( sal_Int32 nStartPara
, sal_Int32 nStartIndex
,
444 sal_Int32 nEndPara
, sal_Int32 nEndIndex
)
446 DBG_CHKTHIS( AccessibleStaticTextBase_Impl
, NULL
);
448 if( !mpTextParagraph
)
453 SvxEditViewForwarder
& rCacheVF
= mpTextParagraph
->GetEditViewForwarder( sal_True
);
454 mpTextParagraph
->GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs
457 // save current selection
458 ESelection aOldSelection
;
460 rCacheVF
.GetSelection( aOldSelection
);
461 rCacheVF
.SetSelection( MakeSelection(nStartPara
, nStartIndex
, nEndPara
, nEndIndex
) );
462 aRetVal
= rCacheVF
.Copy();
463 rCacheVF
.SetSelection( aOldSelection
); // restore
467 catch( const uno::RuntimeException
& )
473 Rectangle
AccessibleStaticTextBase_Impl::GetParagraphBoundingBox() const
476 if( mpTextParagraph
)
478 awt::Rectangle aAwtRect
= mpTextParagraph
->getBounds();
479 aRect
= Rectangle( Point( aAwtRect
.X
, aAwtRect
.Y
), Size( aAwtRect
.Width
, aAwtRect
.Height
) );
488 //------------------------------------------------------------------------
490 // AccessibleStaticTextBase implementation
492 //------------------------------------------------------------------------
494 AccessibleStaticTextBase::AccessibleStaticTextBase( ::std::auto_ptr
< SvxEditSource
> pEditSource
) :
495 mpImpl( new AccessibleStaticTextBase_Impl() )
497 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
499 SetEditSource( pEditSource
);
502 AccessibleStaticTextBase::~AccessibleStaticTextBase()
506 const SvxEditSource
& AccessibleStaticTextBase::GetEditSource() const SAL_THROW((::com::sun::star::uno::RuntimeException
))
509 mpImpl
->CheckInvariants();
511 const SvxEditSource
& aEditSource
= mpImpl
->GetEditSource();
513 mpImpl
->CheckInvariants();
517 return mpImpl
->GetEditSource();
521 void AccessibleStaticTextBase::SetEditSource( ::std::auto_ptr
< SvxEditSource
> pEditSource
) SAL_THROW((::com::sun::star::uno::RuntimeException
))
524 // precondition: solar mutex locked
525 DBG_TESTSOLARMUTEX();
527 mpImpl
->CheckInvariants();
529 mpImpl
->SetEditSource( pEditSource
);
531 mpImpl
->CheckInvariants();
533 mpImpl
->SetEditSource( pEditSource
);
537 void AccessibleStaticTextBase::SetEventSource( const uno::Reference
< XAccessible
>& rInterface
)
540 mpImpl
->CheckInvariants();
543 mpImpl
->SetEventSource( rInterface
);
546 mpImpl
->CheckInvariants();
550 uno::Reference
< XAccessible
> AccessibleStaticTextBase::GetEventSource() const
553 mpImpl
->CheckInvariants();
555 uno::Reference
< XAccessible
> xRet( mpImpl
->GetEventSource() );
557 mpImpl
->CheckInvariants();
561 return mpImpl
->GetEventSource();
565 void AccessibleStaticTextBase::SetOffset( const Point
& rPoint
)
568 // precondition: solar mutex locked
569 DBG_TESTSOLARMUTEX();
571 mpImpl
->CheckInvariants();
573 mpImpl
->SetOffset( rPoint
);
575 mpImpl
->CheckInvariants();
577 mpImpl
->SetOffset( rPoint
);
581 Point
AccessibleStaticTextBase::GetOffset() const
584 mpImpl
->CheckInvariants();
586 Point
aPoint( mpImpl
->GetOffset() );
588 mpImpl
->CheckInvariants();
592 return mpImpl
->GetOffset();
596 void AccessibleStaticTextBase::UpdateChildren() SAL_THROW((::com::sun::star::uno::RuntimeException
))
599 // precondition: solar mutex locked
600 DBG_TESTSOLARMUTEX();
602 mpImpl
->CheckInvariants();
604 mpImpl
->UpdateChildren();
606 mpImpl
->CheckInvariants();
608 mpImpl
->UpdateChildren();
612 void AccessibleStaticTextBase::Dispose()
615 mpImpl
->CheckInvariants();
621 mpImpl
->CheckInvariants();
625 // XAccessibleContext
626 sal_Int32 SAL_CALL
AccessibleStaticTextBase::getAccessibleChildCount() throw (uno::RuntimeException
)
628 // no children at all
632 uno::Reference
< XAccessible
> SAL_CALL
AccessibleStaticTextBase::getAccessibleChild( sal_Int32
/*i*/ ) throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
634 // no children at all
635 return uno::Reference
< XAccessible
>();
638 uno::Reference
< XAccessible
> SAL_CALL
AccessibleStaticTextBase::getAccessibleAtPoint( const awt::Point
& /*_aPoint*/ ) throw (uno::RuntimeException
)
640 // no children at all
641 return uno::Reference
< XAccessible
>();
645 sal_Int32 SAL_CALL
AccessibleStaticTextBase::getCaretPosition() throw (uno::RuntimeException
)
647 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
649 sal_Int32 i
, nPos
, nParas
;
650 for( i
=0, nPos
=-1, nParas
=mpImpl
->GetParagraphCount(); i
<nParas
; ++i
)
652 if( (nPos
=mpImpl
->GetParagraph(i
).getCaretPosition()) != -1 )
659 sal_Bool SAL_CALL
AccessibleStaticTextBase::setCaretPosition( sal_Int32 nIndex
) throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
661 return setSelection(nIndex
, nIndex
);
664 sal_Unicode SAL_CALL
AccessibleStaticTextBase::getCharacter( sal_Int32 nIndex
) throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
666 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
668 EPosition
aPos( mpImpl
->Index2Internal(nIndex
) );
670 return mpImpl
->GetParagraph( aPos
.nPara
).getCharacter( aPos
.nIndex
);
673 uno::Sequence
< beans::PropertyValue
> SAL_CALL
AccessibleStaticTextBase::getCharacterAttributes( sal_Int32 nIndex
, const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& aRequestedAttributes
) throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
675 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
677 EPosition
aPos( mpImpl
->Index2Internal(nIndex
) );
679 return mpImpl
->GetParagraph( aPos
.nPara
).getCharacterAttributes( aPos
.nIndex
, aRequestedAttributes
);
682 awt::Rectangle SAL_CALL
AccessibleStaticTextBase::getCharacterBounds( sal_Int32 nIndex
) throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
684 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
686 // #108900# Allow ranges for nIndex, as one-past-the-end
687 // values are now legal, too.
688 EPosition
aPos( mpImpl
->Range2Internal(nIndex
) );
690 // #i70916# Text in spread sheet cells return the wrong extents
691 AccessibleEditableTextPara
& rPara
= mpImpl
->GetParagraph( aPos
.nPara
);
692 awt::Rectangle
aParaBounds( rPara
.getBounds() );
693 awt::Rectangle
aBounds( rPara
.getCharacterBounds( aPos
.nIndex
) );
694 aBounds
.X
+= aParaBounds
.X
;
695 aBounds
.Y
+= aParaBounds
.Y
;
700 sal_Int32 SAL_CALL
AccessibleStaticTextBase::getCharacterCount() throw (uno::RuntimeException
)
702 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
704 sal_Int32 i
, nCount
, nParas
;
705 for( i
=0, nCount
=0, nParas
=mpImpl
->GetParagraphCount(); i
<nParas
; ++i
)
706 nCount
+= mpImpl
->GetParagraph(i
).getCharacterCount();
711 sal_Int32 SAL_CALL
AccessibleStaticTextBase::getIndexAtPoint( const awt::Point
& rPoint
) throw (uno::RuntimeException
)
713 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
715 const sal_Int32
nParas( mpImpl
->GetParagraphCount() );
718 for( i
=0; i
<nParas
; ++i
)
720 // TODO: maybe exploit the fact that paragraphs are
721 // ordered vertically for early exit
723 // #i70916# Text in spread sheet cells return the wrong extents
724 AccessibleEditableTextPara
& rPara
= mpImpl
->GetParagraph( i
);
725 awt::Rectangle
aParaBounds( rPara
.getBounds() );
726 awt::Point
aPoint( rPoint
);
727 aPoint
.X
-= aParaBounds
.X
;
728 aPoint
.Y
-= aParaBounds
.Y
;
730 // #112814# Use correct index offset
731 if ( ( nIndex
= rPara
.getIndexAtPoint( aPoint
) ) != -1 )
732 return mpImpl
->Internal2Index( EPosition(sal::static_int_cast
<USHORT
>(i
),
733 sal::static_int_cast
<USHORT
>(nIndex
)) );
739 ::rtl::OUString SAL_CALL
AccessibleStaticTextBase::getSelectedText() throw (uno::RuntimeException
)
741 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
743 sal_Int32
nStart( getSelectionStart() );
744 sal_Int32
nEnd( getSelectionEnd() );
746 // #104481# Return the empty string for 'no selection'
747 if( nStart
< 0 || nEnd
< 0 )
748 return ::rtl::OUString();
750 return getTextRange( nStart
, nEnd
);
753 sal_Int32 SAL_CALL
AccessibleStaticTextBase::getSelectionStart() throw (uno::RuntimeException
)
755 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
757 sal_Int32 i
, nPos
, nParas
;
758 for( i
=0, nPos
=-1, nParas
=mpImpl
->GetParagraphCount(); i
<nParas
; ++i
)
760 if( (nPos
=mpImpl
->GetParagraph(i
).getSelectionStart()) != -1 )
767 sal_Int32 SAL_CALL
AccessibleStaticTextBase::getSelectionEnd() throw (uno::RuntimeException
)
769 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
771 sal_Int32 i
, nPos
, nParas
;
772 for( i
=0, nPos
=-1, nParas
=mpImpl
->GetParagraphCount(); i
<nParas
; ++i
)
774 if( (nPos
=mpImpl
->GetParagraph(i
).getSelectionEnd()) != -1 )
781 sal_Bool SAL_CALL
AccessibleStaticTextBase::setSelection( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
783 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
785 EPosition
aStartIndex( mpImpl
->Range2Internal(nStartIndex
) );
786 EPosition
aEndIndex( mpImpl
->Range2Internal(nEndIndex
) );
788 return mpImpl
->SetSelection( aStartIndex
.nPara
, aStartIndex
.nIndex
,
789 aEndIndex
.nPara
, aEndIndex
.nIndex
);
792 ::rtl::OUString SAL_CALL
AccessibleStaticTextBase::getText() throw (uno::RuntimeException
)
794 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
797 ::rtl::OUString aRes
;
798 for( i
=0, nParas
=mpImpl
->GetParagraphCount(); i
<nParas
; ++i
)
799 aRes
+= mpImpl
->GetParagraph(i
).getText();
804 ::rtl::OUString SAL_CALL
AccessibleStaticTextBase::getTextRange( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
806 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
808 if( nStartIndex
> nEndIndex
)
809 ::std::swap(nStartIndex
, nEndIndex
);
811 EPosition
aStartIndex( mpImpl
->Range2Internal(nStartIndex
) );
812 EPosition
aEndIndex( mpImpl
->Range2Internal(nEndIndex
) );
814 // #102170# Special case: start and end paragraph are identical
815 if( aStartIndex
.nPara
== aEndIndex
.nPara
)
817 return mpImpl
->GetParagraph( aStartIndex
.nPara
).getTextRange( aStartIndex
.nIndex
, aEndIndex
.nIndex
);
821 sal_Int32
i( aStartIndex
.nPara
);
822 ::rtl::OUString
aRes( mpImpl
->GetParagraph(i
).getTextRange( aStartIndex
.nIndex
,
823 mpImpl
->GetParagraph(i
).getCharacterCount()-1) );
826 // paragraphs inbetween are fully included
827 for( ; i
<aEndIndex
.nPara
; ++i
)
828 aRes
+= mpImpl
->GetParagraph(i
).getText();
830 if( i
<=aEndIndex
.nPara
)
831 aRes
+= mpImpl
->GetParagraph(i
).getTextRange( 0, aEndIndex
.nIndex
);
837 ::com::sun::star::accessibility::TextSegment SAL_CALL
AccessibleStaticTextBase::getTextAtIndex( sal_Int32 nIndex
, sal_Int16 aTextType
) throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
)
839 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
841 EPosition
aPos( mpImpl
->Range2Internal(nIndex
) );
843 ::com::sun::star::accessibility::TextSegment aResult
;
845 if( AccessibleTextType::PARAGRAPH
== aTextType
)
847 // #106393# Special casing one behind last paragraph is
848 // not necessary, since then, we return the content and
849 // boundary of that last paragraph. Range2Internal is
850 // tolerant against that, and returns the last paragraph
853 // retrieve full text of the paragraph
854 aResult
.SegmentText
= mpImpl
->GetParagraph( aPos
.nPara
).getText();
856 // #112814# Adapt the start index with the paragraph offset
857 aResult
.SegmentStart
= mpImpl
->Internal2Index( EPosition( aPos
.nPara
, 0 ) );
858 aResult
.SegmentEnd
= aResult
.SegmentStart
+ aResult
.SegmentText
.getLength();
862 // No special handling required, forward to wrapped class
863 aResult
= mpImpl
->GetParagraph( aPos
.nPara
).getTextAtIndex( aPos
.nIndex
, aTextType
);
865 // #112814# Adapt the start index with the paragraph offset
866 mpImpl
->CorrectTextSegment( aResult
, aPos
.nPara
);
872 ::com::sun::star::accessibility::TextSegment SAL_CALL
AccessibleStaticTextBase::getTextBeforeIndex( sal_Int32 nIndex
, sal_Int16 aTextType
) throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
)
874 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
876 EPosition
aPos( mpImpl
->Range2Internal(nIndex
) );
878 ::com::sun::star::accessibility::TextSegment aResult
;
880 if( AccessibleTextType::PARAGRAPH
== aTextType
)
882 if( aPos
.nIndex
== mpImpl
->GetParagraph( aPos
.nPara
).getCharacterCount() )
884 // #103589# Special casing one behind the last paragraph
885 aResult
.SegmentText
= mpImpl
->GetParagraph( aPos
.nPara
).getText();
887 // #112814# Adapt the start index with the paragraph offset
888 aResult
.SegmentStart
= mpImpl
->Internal2Index( EPosition( aPos
.nPara
, 0 ) );
890 else if( aPos
.nPara
> 0 )
892 aResult
.SegmentText
= mpImpl
->GetParagraph( aPos
.nPara
- 1 ).getText();
894 // #112814# Adapt the start index with the paragraph offset
895 aResult
.SegmentStart
= mpImpl
->Internal2Index( EPosition( aPos
.nPara
- 1, 0 ) );
898 aResult
.SegmentEnd
= aResult
.SegmentStart
+ aResult
.SegmentText
.getLength();
902 // No special handling required, forward to wrapped class
903 aResult
= mpImpl
->GetParagraph( aPos
.nPara
).getTextBeforeIndex( aPos
.nIndex
, aTextType
);
905 // #112814# Adapt the start index with the paragraph offset
906 mpImpl
->CorrectTextSegment( aResult
, aPos
.nPara
);
912 ::com::sun::star::accessibility::TextSegment SAL_CALL
AccessibleStaticTextBase::getTextBehindIndex( sal_Int32 nIndex
, sal_Int16 aTextType
) throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
)
914 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
916 EPosition
aPos( mpImpl
->Range2Internal(nIndex
) );
918 ::com::sun::star::accessibility::TextSegment aResult
;
920 if( AccessibleTextType::PARAGRAPH
== aTextType
)
922 // Special casing one behind the last paragraph is not
923 // necessary, this case is invalid here for
924 // getTextBehindIndex
925 if( aPos
.nPara
+ 1 < mpImpl
->GetParagraphCount() )
927 aResult
.SegmentText
= mpImpl
->GetParagraph( aPos
.nPara
+ 1 ).getText();
929 // #112814# Adapt the start index with the paragraph offset
930 aResult
.SegmentStart
= mpImpl
->Internal2Index( EPosition( aPos
.nPara
+ 1, 0 ) );
931 aResult
.SegmentEnd
= aResult
.SegmentStart
+ aResult
.SegmentText
.getLength();
936 // No special handling required, forward to wrapped class
937 aResult
= mpImpl
->GetParagraph( aPos
.nPara
).getTextBehindIndex( aPos
.nIndex
, aTextType
);
939 // #112814# Adapt the start index with the paragraph offset
940 mpImpl
->CorrectTextSegment( aResult
, aPos
.nPara
);
946 sal_Bool SAL_CALL
AccessibleStaticTextBase::copyText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
948 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
950 if( nStartIndex
> nEndIndex
)
951 ::std::swap(nStartIndex
, nEndIndex
);
953 EPosition
aStartIndex( mpImpl
->Range2Internal(nStartIndex
) );
954 EPosition
aEndIndex( mpImpl
->Range2Internal(nEndIndex
) );
956 return mpImpl
->CopyText( aStartIndex
.nPara
, aStartIndex
.nIndex
,
957 aEndIndex
.nPara
, aEndIndex
.nIndex
);
960 // XAccessibleTextAttributes
961 uno::Sequence
< beans::PropertyValue
> AccessibleStaticTextBase::getDefaultAttributes( const uno::Sequence
< ::rtl::OUString
>& RequestedAttributes
) throw (uno::RuntimeException
)
963 // get the intersection of the default attributes of all paragraphs
965 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
967 PropertyValueVector
aDefAttrVec( mpImpl
->GetParagraph( 0 ).getDefaultAttributes( RequestedAttributes
) );
969 const sal_Int32 nParaCount
= mpImpl
->GetParagraphCount();
970 for ( sal_Int32 nPara
= 1; nPara
< nParaCount
; ++nPara
)
972 uno::Sequence
< beans::PropertyValue
> aSeq
= mpImpl
->GetParagraph( nPara
).getDefaultAttributes( RequestedAttributes
);
973 PropertyValueVector aIntersectionVec
;
975 PropertyValueVector::const_iterator aEnd
= aDefAttrVec
.end();
976 for ( PropertyValueVector::const_iterator aItr
= aDefAttrVec
.begin(); aItr
!= aEnd
; ++aItr
)
978 const beans::PropertyValue
* pItr
= aSeq
.getConstArray();
979 const beans::PropertyValue
* pEnd
= pItr
+ aSeq
.getLength();
980 const beans::PropertyValue
* pFind
= ::std::find_if( pItr
, pEnd
, ::std::bind2nd( PropertyValueEqualFunctor(), boost::cref( *aItr
) ) );
983 aIntersectionVec
.push_back( *pFind
);
987 aDefAttrVec
.swap( aIntersectionVec
);
989 if ( aDefAttrVec
.empty() )
995 return aDefAttrVec
.getAsConstList();
998 uno::Sequence
< beans::PropertyValue
> SAL_CALL
AccessibleStaticTextBase::getRunAttributes( sal_Int32 nIndex
, const uno::Sequence
< ::rtl::OUString
>& RequestedAttributes
) throw (lang::IndexOutOfBoundsException
, uno::RuntimeException
)
1000 // get those default attributes of the paragraph, which are not part
1001 // of the intersection of all paragraphs and add them to the run attributes
1003 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
1005 EPosition
aPos( mpImpl
->Index2Internal( nIndex
) );
1006 AccessibleEditableTextPara
& rPara
= mpImpl
->GetParagraph( aPos
.nPara
);
1007 uno::Sequence
< beans::PropertyValue
> aDefAttrSeq
= rPara
.getDefaultAttributes( RequestedAttributes
);
1008 uno::Sequence
< beans::PropertyValue
> aRunAttrSeq
= rPara
.getRunAttributes( aPos
.nIndex
, RequestedAttributes
);
1009 uno::Sequence
< beans::PropertyValue
> aIntersectionSeq
= getDefaultAttributes( RequestedAttributes
);
1010 PropertyValueVector aDiffVec
;
1012 const beans::PropertyValue
* pDefAttr
= aDefAttrSeq
.getConstArray();
1013 const sal_Int32 nLength
= aDefAttrSeq
.getLength();
1014 for ( sal_Int32 i
= 0; i
< nLength
; ++i
)
1016 const beans::PropertyValue
* pItr
= aIntersectionSeq
.getConstArray();
1017 const beans::PropertyValue
* pEnd
= pItr
+ aIntersectionSeq
.getLength();
1018 const beans::PropertyValue
* pFind
= ::std::find_if( pItr
, pEnd
, ::std::bind2nd( PropertyValueEqualFunctor(), boost::cref( pDefAttr
[i
] ) ) );
1019 if ( pFind
== pEnd
&& pFind
->Handle
!= 0)
1021 aDiffVec
.push_back( *pFind
);
1025 return ::comphelper::concatSequences( aRunAttrSeq
, aDiffVec
.getAsConstList() );
1028 Rectangle
AccessibleStaticTextBase::GetParagraphBoundingBox() const
1030 return mpImpl
->GetParagraphBoundingBox();
1033 sal_Int32
AccessibleStaticTextBase::GetParagraphIndex() const
1035 return mpImpl
->GetParagraphIndex();
1038 sal_Int32
AccessibleStaticTextBase::GetParagraphCount() const
1040 return mpImpl
->GetParagraphCount();
1043 sal_Int32
AccessibleStaticTextBase::GetLineCount( sal_Int32 nParagraph
) const
1045 return mpImpl
->GetLineCount( nParagraph
);
1048 } // end of namespace accessibility
1050 //------------------------------------------------------------------------