1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_accessibility.hxx"
31 // includes --------------------------------------------------------------
32 #include <accessibility/standard/vclxaccessibleedit.hxx>
34 #include <toolkit/awt/vclxwindows.hxx>
35 #include <toolkit/helper/convert.hxx>
36 #include <accessibility/helper/accresmgr.hxx>
37 #include <accessibility/helper/accessiblestrings.hrc>
39 #include <unotools/accessiblestatesethelper.hxx>
40 #include <unotools/accessiblerelationsethelper.hxx>
41 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
42 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
43 #include <com/sun/star/accessibility/AccessibleRole.hpp>
44 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
45 #include <cppuhelper/typeprovider.hxx>
46 #include <comphelper/sequence.hxx>
47 #include <vcl/svapp.hxx>
48 #include <vcl/window.hxx>
49 #include <vcl/edit.hxx>
50 #include <sot/exchange.hxx>
51 #include <sot/formats.hxx>
55 using namespace ::com::sun::star
;
56 using namespace ::com::sun::star::uno
;
57 using namespace ::com::sun::star::lang
;
58 using namespace ::com::sun::star::beans
;
59 using namespace ::com::sun::star::accessibility
;
60 using namespace ::comphelper
;
63 // -----------------------------------------------------------------------------
65 // -----------------------------------------------------------------------------
67 VCLXAccessibleEdit::VCLXAccessibleEdit( VCLXWindow
* pVCLWindow
)
68 :VCLXAccessibleTextComponent( pVCLWindow
)
70 m_nSelectionStart
= getSelectionStart();
71 m_nCaretPosition
= getCaretPosition();
74 // -----------------------------------------------------------------------------
76 VCLXAccessibleEdit::~VCLXAccessibleEdit()
80 // -----------------------------------------------------------------------------
82 void VCLXAccessibleEdit::ProcessWindowEvent( const VclWindowEvent
& rVclWindowEvent
)
84 switch ( rVclWindowEvent
.GetId() )
86 case VCLEVENT_EDIT_MODIFY
:
88 SetText( implGetText() );
91 case VCLEVENT_EDIT_SELECTIONCHANGED
:
93 sal_Int32 nOldCaretPosition
= m_nCaretPosition
;
94 sal_Int32 nOldSelectionStart
= m_nSelectionStart
;
96 m_nCaretPosition
= getCaretPosition();
97 m_nSelectionStart
= getSelectionStart();
99 Window
* pWindow
= GetWindow();
100 if ( pWindow
&& pWindow
->HasChildPathFocus() )
102 if ( m_nCaretPosition
!= nOldCaretPosition
)
104 Any aOldValue
, aNewValue
;
105 aOldValue
<<= (sal_Int32
) nOldCaretPosition
;
106 aNewValue
<<= (sal_Int32
) m_nCaretPosition
;
107 NotifyAccessibleEvent( AccessibleEventId::CARET_CHANGED
, aOldValue
, aNewValue
);
110 // #i104470# VCL only has SELECTION_CHANGED, but UAA distinguishes between SELECTION_CHANGED and CARET_CHANGED
111 sal_Bool bHasSelection
= ( m_nSelectionStart
!= m_nCaretPosition
);
112 sal_Bool bHadSelection
= ( nOldSelectionStart
!= nOldCaretPosition
);
113 if ( ( bHasSelection
!= bHadSelection
) || ( bHasSelection
&& ( ( m_nCaretPosition
!= nOldCaretPosition
) || ( m_nSelectionStart
!= nOldSelectionStart
) ) ) )
115 NotifyAccessibleEvent( AccessibleEventId::TEXT_SELECTION_CHANGED
, Any(), Any() );
122 VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent
);
126 // -----------------------------------------------------------------------------
128 void VCLXAccessibleEdit::FillAccessibleStateSet( utl::AccessibleStateSetHelper
& rStateSet
)
130 VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet
);
132 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
135 rStateSet
.AddState( AccessibleStateType::FOCUSABLE
);
136 rStateSet
.AddState( AccessibleStateType::SINGLE_LINE
);
137 if ( pVCLXEdit
->isEditable() )
138 rStateSet
.AddState( AccessibleStateType::EDITABLE
);
142 // -----------------------------------------------------------------------------
143 // OCommonAccessibleText
144 // -----------------------------------------------------------------------------
146 ::rtl::OUString
VCLXAccessibleEdit::implGetText()
148 ::rtl::OUString aText
;
150 Edit
* pEdit
= static_cast< Edit
* >( GetWindow() );
153 aText
= OutputDevice::GetNonMnemonicString( pEdit
->GetText() );
155 if ( getAccessibleRole() == AccessibleRole::PASSWORD_TEXT
)
157 xub_Unicode cEchoChar
= pEdit
->GetEchoChar();
161 aText
= sTmp
.Fill( (sal_uInt16
)aText
.getLength(), cEchoChar
);
168 // -----------------------------------------------------------------------------
170 void VCLXAccessibleEdit::implGetSelection( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
)
172 awt::Selection aSelection
;
173 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
175 aSelection
= pVCLXEdit
->getSelection();
177 nStartIndex
= aSelection
.Min
;
178 nEndIndex
= aSelection
.Max
;
181 // -----------------------------------------------------------------------------
183 // -----------------------------------------------------------------------------
185 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleEdit
, VCLXAccessibleTextComponent
, VCLXAccessibleEdit_BASE
)
187 // -----------------------------------------------------------------------------
189 // -----------------------------------------------------------------------------
191 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleEdit
, VCLXAccessibleTextComponent
, VCLXAccessibleEdit_BASE
)
193 // -----------------------------------------------------------------------------
195 // -----------------------------------------------------------------------------
197 ::rtl::OUString
VCLXAccessibleEdit::getImplementationName() throw (RuntimeException
)
199 return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleEdit" );
202 // -----------------------------------------------------------------------------
204 Sequence
< ::rtl::OUString
> VCLXAccessibleEdit::getSupportedServiceNames() throw (RuntimeException
)
206 Sequence
< ::rtl::OUString
> aNames(1);
207 aNames
[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleEdit" );
211 // -----------------------------------------------------------------------------
212 // XAccessibleContext
213 // -----------------------------------------------------------------------------
215 sal_Int32
VCLXAccessibleEdit::getAccessibleChildCount() throw (RuntimeException
)
217 OExternalLockGuard
aGuard( this );
222 // -----------------------------------------------------------------------------
224 Reference
< XAccessible
> VCLXAccessibleEdit::getAccessibleChild( sal_Int32 i
) throw (IndexOutOfBoundsException
, RuntimeException
)
226 OExternalLockGuard
aGuard( this );
228 if ( i
< 0 || i
>= getAccessibleChildCount() )
229 throw IndexOutOfBoundsException();
231 return Reference
< XAccessible
>();
234 // -----------------------------------------------------------------------------
236 sal_Int16
VCLXAccessibleEdit::getAccessibleRole( ) throw (RuntimeException
)
238 OExternalLockGuard
aGuard( this );
241 Edit
* pEdit
= static_cast< Edit
* >( GetWindow() );
242 if ( pEdit
&& ( ( pEdit
->GetStyle() & WB_PASSWORD
) || pEdit
->GetEchoChar() ) )
243 nRole
= AccessibleRole::PASSWORD_TEXT
;
245 nRole
= AccessibleRole::TEXT
;
250 // -----------------------------------------------------------------------------
252 // -----------------------------------------------------------------------------
254 sal_Int32
VCLXAccessibleEdit::getAccessibleActionCount( ) throw (RuntimeException
)
256 OExternalLockGuard
aGuard( this );
258 // There is one action: activate
262 // -----------------------------------------------------------------------------
264 sal_Bool
VCLXAccessibleEdit::doAccessibleAction ( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
266 OExternalLockGuard
aGuard( this );
268 if ( nIndex
< 0 || nIndex
>= getAccessibleActionCount() )
269 throw IndexOutOfBoundsException();
271 sal_Bool bDoAction
= sal_False
;
272 Window
* pWindow
= GetWindow();
275 pWindow
->GrabFocus();
276 bDoAction
= sal_True
;
282 // -----------------------------------------------------------------------------
284 ::rtl::OUString
VCLXAccessibleEdit::getAccessibleActionDescription ( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
286 OExternalLockGuard
aGuard( this );
288 if ( nIndex
< 0 || nIndex
>= getAccessibleActionCount() )
289 throw IndexOutOfBoundsException();
291 static const ::rtl::OUString
sAction( RTL_CONSTASCII_USTRINGPARAM( "activate" ) );
295 // -----------------------------------------------------------------------------
297 Reference
< XAccessibleKeyBinding
> VCLXAccessibleEdit::getAccessibleActionKeyBinding( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
299 OExternalLockGuard
aGuard( this );
301 if ( nIndex
< 0 || nIndex
>= getAccessibleActionCount() )
302 throw IndexOutOfBoundsException();
304 return Reference
< XAccessibleKeyBinding
>();
307 // -----------------------------------------------------------------------------
309 // -----------------------------------------------------------------------------
311 sal_Int32
VCLXAccessibleEdit::getCaretPosition( ) throw (RuntimeException
)
313 return getSelectionEnd();
316 // -----------------------------------------------------------------------------
318 sal_Bool
VCLXAccessibleEdit::setCaretPosition( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
320 return setSelection( nIndex
, nIndex
);
323 // -----------------------------------------------------------------------------
325 sal_Unicode
VCLXAccessibleEdit::getCharacter( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
327 OExternalLockGuard
aGuard( this );
329 return VCLXAccessibleTextComponent::getCharacter( nIndex
);
332 // -----------------------------------------------------------------------------
334 Sequence
< PropertyValue
> VCLXAccessibleEdit::getCharacterAttributes( sal_Int32 nIndex
, const Sequence
< ::rtl::OUString
>& aRequestedAttributes
) throw (IndexOutOfBoundsException
, RuntimeException
)
336 OExternalLockGuard
aGuard( this );
338 return VCLXAccessibleTextComponent::getCharacterAttributes( nIndex
, aRequestedAttributes
);
341 // -----------------------------------------------------------------------------
343 awt::Rectangle
VCLXAccessibleEdit::getCharacterBounds( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
345 OExternalLockGuard
aGuard( this );
347 awt::Rectangle
aBounds( 0, 0, 0, 0 );
348 sal_Int32 nLength
= implGetText().getLength();
350 if ( !implIsValidRange( nIndex
, nIndex
, nLength
) )
351 throw IndexOutOfBoundsException();
353 Control
* pControl
= static_cast< Control
* >( GetWindow() );
356 if ( nIndex
== nLength
)
358 // #108914# calculate virtual bounding rectangle
359 for ( sal_Int32 i
= 0; i
< nLength
; ++i
)
361 Rectangle aRect
= pControl
->GetCharacterBounds( i
);
362 sal_Int32 nHeight
= aRect
.GetHeight();
363 if ( aBounds
.Height
< nHeight
)
365 aBounds
.Y
= aRect
.Top();
366 aBounds
.Height
= nHeight
;
368 if ( i
== nLength
- 1 )
370 aBounds
.X
= aRect
.Right() + 1;
377 aBounds
= AWTRectangle( pControl
->GetCharacterBounds( nIndex
) );
384 // -----------------------------------------------------------------------------
386 sal_Int32
VCLXAccessibleEdit::getCharacterCount( ) throw (RuntimeException
)
388 OExternalLockGuard
aGuard( this );
390 return VCLXAccessibleTextComponent::getCharacterCount();
393 // -----------------------------------------------------------------------------
395 sal_Int32
VCLXAccessibleEdit::getIndexAtPoint( const awt::Point
& aPoint
) throw (RuntimeException
)
397 OExternalLockGuard
aGuard( this );
399 return VCLXAccessibleTextComponent::getIndexAtPoint( aPoint
);
402 // -----------------------------------------------------------------------------
404 ::rtl::OUString
VCLXAccessibleEdit::getSelectedText( ) throw (RuntimeException
)
406 OExternalLockGuard
aGuard( this );
408 return VCLXAccessibleTextComponent::getSelectedText();
411 // -----------------------------------------------------------------------------
413 sal_Int32
VCLXAccessibleEdit::getSelectionStart( ) throw (RuntimeException
)
415 OExternalLockGuard
aGuard( this );
417 return VCLXAccessibleTextComponent::getSelectionStart();
420 // -----------------------------------------------------------------------------
422 sal_Int32
VCLXAccessibleEdit::getSelectionEnd( ) throw (RuntimeException
)
424 OExternalLockGuard
aGuard( this );
426 return VCLXAccessibleTextComponent::getSelectionEnd();
429 // -----------------------------------------------------------------------------
431 sal_Bool
VCLXAccessibleEdit::setSelection( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
433 OExternalLockGuard
aGuard( this );
435 sal_Bool bReturn
= sal_False
;
436 ::rtl::OUString
sText( implGetText() );
438 if ( !implIsValidRange( nStartIndex
, nEndIndex
, sText
.getLength() ) )
439 throw IndexOutOfBoundsException();
441 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
442 Edit
* pEdit
= static_cast< Edit
* >( GetWindow() );
443 if ( pVCLXEdit
&& pEdit
&& pEdit
->IsEnabled() )
445 pVCLXEdit
->setSelection( awt::Selection( nStartIndex
, nEndIndex
) );
452 // -----------------------------------------------------------------------------
454 ::rtl::OUString
VCLXAccessibleEdit::getText( ) throw (RuntimeException
)
456 OExternalLockGuard
aGuard( this );
458 return VCLXAccessibleTextComponent::getText();
461 // -----------------------------------------------------------------------------
463 ::rtl::OUString
VCLXAccessibleEdit::getTextRange( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
465 OExternalLockGuard
aGuard( this );
467 return VCLXAccessibleTextComponent::getTextRange( nStartIndex
, nEndIndex
);
470 // -----------------------------------------------------------------------------
472 ::com::sun::star::accessibility::TextSegment
VCLXAccessibleEdit::getTextAtIndex( sal_Int32 nIndex
, sal_Int16 aTextType
) throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
)
474 OExternalLockGuard
aGuard( this );
476 return VCLXAccessibleTextComponent::getTextAtIndex( nIndex
, aTextType
);
479 // -----------------------------------------------------------------------------
481 ::com::sun::star::accessibility::TextSegment
VCLXAccessibleEdit::getTextBeforeIndex( sal_Int32 nIndex
, sal_Int16 aTextType
) throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
)
483 OExternalLockGuard
aGuard( this );
485 return VCLXAccessibleTextComponent::getTextBeforeIndex( nIndex
, aTextType
);
488 // -----------------------------------------------------------------------------
490 ::com::sun::star::accessibility::TextSegment
VCLXAccessibleEdit::getTextBehindIndex( sal_Int32 nIndex
, sal_Int16 aTextType
) throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
)
492 OExternalLockGuard
aGuard( this );
494 return VCLXAccessibleTextComponent::getTextBehindIndex( nIndex
, aTextType
);
497 // -----------------------------------------------------------------------------
499 sal_Bool
VCLXAccessibleEdit::copyText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
501 OExternalLockGuard
aGuard( this );
503 return VCLXAccessibleTextComponent::copyText( nStartIndex
, nEndIndex
);
506 // -----------------------------------------------------------------------------
507 // XAccessibleEditableText
508 // -----------------------------------------------------------------------------
510 sal_Bool
VCLXAccessibleEdit::cutText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
512 OExternalLockGuard
aGuard( this );
514 return copyText( nStartIndex
, nEndIndex
) && deleteText( nStartIndex
, nEndIndex
);
517 // -----------------------------------------------------------------------------
519 sal_Bool
VCLXAccessibleEdit::pasteText( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
521 OExternalLockGuard
aGuard( this );
523 sal_Bool bReturn
= sal_False
;
527 Reference
< datatransfer::clipboard::XClipboard
> xClipboard
= GetWindow()->GetClipboard();
528 if ( xClipboard
.is() )
530 const sal_uInt32 nRef
= Application::ReleaseSolarMutex();
531 Reference
< datatransfer::XTransferable
> xDataObj
= xClipboard
->getContents();
532 Application::AcquireSolarMutex( nRef
);
535 datatransfer::DataFlavor aFlavor
;
536 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING
, aFlavor
);
537 if ( xDataObj
->isDataFlavorSupported( aFlavor
) )
539 Any aData
= xDataObj
->getTransferData( aFlavor
);
540 ::rtl::OUString sText
;
542 bReturn
= replaceText( nIndex
, nIndex
, sText
);
551 // -----------------------------------------------------------------------------
553 sal_Bool
VCLXAccessibleEdit::deleteText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
555 OExternalLockGuard
aGuard( this );
557 return replaceText( nStartIndex
, nEndIndex
, ::rtl::OUString() );
560 // -----------------------------------------------------------------------------
562 sal_Bool
VCLXAccessibleEdit::insertText( const ::rtl::OUString
& sText
, sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
564 OExternalLockGuard
aGuard( this );
566 return replaceText( nIndex
, nIndex
, sText
);
569 // -----------------------------------------------------------------------------
571 sal_Bool
VCLXAccessibleEdit::replaceText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
, const ::rtl::OUString
& sReplacement
) throw (IndexOutOfBoundsException
, RuntimeException
)
573 OExternalLockGuard
aGuard( this );
575 sal_Bool bReturn
= sal_False
;
576 ::rtl::OUString
sText( implGetText() );
578 if ( !implIsValidRange( nStartIndex
, nEndIndex
, sText
.getLength() ) )
579 throw IndexOutOfBoundsException();
581 sal_Int32 nMinIndex
= ::std::min( nStartIndex
, nEndIndex
);
582 sal_Int32 nMaxIndex
= ::std::max( nStartIndex
, nEndIndex
);
584 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
585 if ( pVCLXEdit
&& pVCLXEdit
->isEditable() )
587 pVCLXEdit
->setText( sText
.replaceAt( nMinIndex
, nMaxIndex
- nMinIndex
, sReplacement
) );
588 sal_Int32 nIndex
= nMinIndex
+ sReplacement
.getLength();
589 setSelection( nIndex
, nIndex
);
596 // -----------------------------------------------------------------------------
598 sal_Bool
VCLXAccessibleEdit::setAttributes( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
, const Sequence
<PropertyValue
>& ) throw (IndexOutOfBoundsException
, RuntimeException
)
600 OExternalLockGuard
aGuard( this );
602 if ( !implIsValidRange( nStartIndex
, nEndIndex
, implGetText().getLength() ) )
603 throw IndexOutOfBoundsException();
605 return sal_False
; // attributes cannot be set for an edit
608 // -----------------------------------------------------------------------------
610 sal_Bool
VCLXAccessibleEdit::setText( const ::rtl::OUString
& sText
) throw (RuntimeException
)
612 OExternalLockGuard
aGuard( this );
614 sal_Bool bSuccess
= sal_False
;
617 bSuccess
= replaceText( 0, implGetText().getLength(), sText
);
619 catch( const IndexOutOfBoundsException
& )
621 OSL_ENSURE( sal_False
, "VCLXAccessibleText::setText: caught an exception!" );
626 // -----------------------------------------------------------------------------