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: vclxaccessibleedit.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_accessibility.hxx"
34 // includes --------------------------------------------------------------
35 #include <accessibility/standard/vclxaccessibleedit.hxx>
37 #include <toolkit/awt/vclxwindows.hxx>
38 #include <toolkit/helper/convert.hxx>
39 #include <accessibility/helper/accresmgr.hxx>
40 #include <accessibility/helper/accessiblestrings.hrc>
42 #include <unotools/accessiblestatesethelper.hxx>
43 #include <unotools/accessiblerelationsethelper.hxx>
44 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
45 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
46 #include <com/sun/star/accessibility/AccessibleRole.hpp>
47 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
48 #include <cppuhelper/typeprovider.hxx>
49 #include <comphelper/sequence.hxx>
50 #include <vcl/svapp.hxx>
51 #include <vcl/window.hxx>
52 #include <vcl/edit.hxx>
53 #include <sot/exchange.hxx>
54 #include <sot/formats.hxx>
58 using namespace ::com::sun::star
;
59 using namespace ::com::sun::star::uno
;
60 using namespace ::com::sun::star::lang
;
61 using namespace ::com::sun::star::beans
;
62 using namespace ::com::sun::star::accessibility
;
63 using namespace ::comphelper
;
66 // -----------------------------------------------------------------------------
68 // -----------------------------------------------------------------------------
70 VCLXAccessibleEdit::VCLXAccessibleEdit( VCLXWindow
* pVCLWindow
)
71 :VCLXAccessibleTextComponent( pVCLWindow
)
73 m_nCaretPosition
= getCaretPosition();
76 // -----------------------------------------------------------------------------
78 VCLXAccessibleEdit::~VCLXAccessibleEdit()
82 // -----------------------------------------------------------------------------
84 void VCLXAccessibleEdit::UpdateCaretPosition()
86 sal_Int32 nCaretPosition
= getCaretPosition();
88 if ( m_nCaretPosition
!= nCaretPosition
)
90 Any aOldValue
, aNewValue
;
91 aOldValue
<<= (sal_Int32
) m_nCaretPosition
;
92 aNewValue
<<= (sal_Int32
) nCaretPosition
;
93 m_nCaretPosition
= nCaretPosition
;
94 NotifyAccessibleEvent( AccessibleEventId::CARET_CHANGED
, aOldValue
, aNewValue
);
98 // -----------------------------------------------------------------------------
100 void VCLXAccessibleEdit::ProcessWindowEvent( const VclWindowEvent
& rVclWindowEvent
)
102 switch ( rVclWindowEvent
.GetId() )
104 case VCLEVENT_EDIT_MODIFY
:
106 SetText( implGetText() );
109 case VCLEVENT_EDIT_SELECTIONCHANGED
:
111 Window
* pWindow
= GetWindow();
112 if ( pWindow
&& pWindow
->HasChildPathFocus() )
114 NotifyAccessibleEvent( AccessibleEventId::TEXT_SELECTION_CHANGED
, Any(), Any() );
115 UpdateCaretPosition();
120 VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent
);
124 // -----------------------------------------------------------------------------
126 void VCLXAccessibleEdit::FillAccessibleStateSet( utl::AccessibleStateSetHelper
& rStateSet
)
128 VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet
);
130 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
133 rStateSet
.AddState( AccessibleStateType::FOCUSABLE
);
134 rStateSet
.AddState( AccessibleStateType::SINGLE_LINE
);
135 if ( pVCLXEdit
->isEditable() )
136 rStateSet
.AddState( AccessibleStateType::EDITABLE
);
140 // -----------------------------------------------------------------------------
141 // OCommonAccessibleText
142 // -----------------------------------------------------------------------------
144 ::rtl::OUString
VCLXAccessibleEdit::implGetText()
146 ::rtl::OUString aText
;
148 Edit
* pEdit
= static_cast< Edit
* >( GetWindow() );
151 aText
= OutputDevice::GetNonMnemonicString( pEdit
->GetText() );
153 if ( getAccessibleRole() == AccessibleRole::PASSWORD_TEXT
)
155 xub_Unicode cEchoChar
= pEdit
->GetEchoChar();
159 aText
= sTmp
.Fill( (USHORT
)aText
.getLength(), cEchoChar
);
166 // -----------------------------------------------------------------------------
168 void VCLXAccessibleEdit::implGetSelection( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
)
170 awt::Selection aSelection
;
171 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
173 aSelection
= pVCLXEdit
->getSelection();
175 nStartIndex
= aSelection
.Min
;
176 nEndIndex
= aSelection
.Max
;
179 // -----------------------------------------------------------------------------
181 // -----------------------------------------------------------------------------
183 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleEdit
, VCLXAccessibleTextComponent
, VCLXAccessibleEdit_BASE
)
185 // -----------------------------------------------------------------------------
187 // -----------------------------------------------------------------------------
189 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleEdit
, VCLXAccessibleTextComponent
, VCLXAccessibleEdit_BASE
)
191 // -----------------------------------------------------------------------------
193 // -----------------------------------------------------------------------------
195 ::rtl::OUString
VCLXAccessibleEdit::getImplementationName() throw (RuntimeException
)
197 return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleEdit" );
200 // -----------------------------------------------------------------------------
202 Sequence
< ::rtl::OUString
> VCLXAccessibleEdit::getSupportedServiceNames() throw (RuntimeException
)
204 Sequence
< ::rtl::OUString
> aNames(1);
205 aNames
[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleEdit" );
209 // -----------------------------------------------------------------------------
210 // XAccessibleContext
211 // -----------------------------------------------------------------------------
213 sal_Int32
VCLXAccessibleEdit::getAccessibleChildCount() throw (RuntimeException
)
215 OExternalLockGuard
aGuard( this );
220 // -----------------------------------------------------------------------------
222 Reference
< XAccessible
> VCLXAccessibleEdit::getAccessibleChild( sal_Int32 i
) throw (IndexOutOfBoundsException
, RuntimeException
)
224 OExternalLockGuard
aGuard( this );
226 if ( i
< 0 || i
>= getAccessibleChildCount() )
227 throw IndexOutOfBoundsException();
229 return Reference
< XAccessible
>();
232 // -----------------------------------------------------------------------------
234 sal_Int16
VCLXAccessibleEdit::getAccessibleRole( ) throw (RuntimeException
)
236 OExternalLockGuard
aGuard( this );
239 Edit
* pEdit
= static_cast< Edit
* >( GetWindow() );
240 if ( pEdit
&& ( ( pEdit
->GetStyle() & WB_PASSWORD
) || pEdit
->GetEchoChar() ) )
241 nRole
= AccessibleRole::PASSWORD_TEXT
;
243 nRole
= AccessibleRole::TEXT
;
248 // -----------------------------------------------------------------------------
250 // -----------------------------------------------------------------------------
252 sal_Int32
VCLXAccessibleEdit::getAccessibleActionCount( ) throw (RuntimeException
)
254 OExternalLockGuard
aGuard( this );
256 // There is one action: activate
260 // -----------------------------------------------------------------------------
262 sal_Bool
VCLXAccessibleEdit::doAccessibleAction ( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
264 OExternalLockGuard
aGuard( this );
266 if ( nIndex
< 0 || nIndex
>= getAccessibleActionCount() )
267 throw IndexOutOfBoundsException();
269 sal_Bool bDoAction
= sal_False
;
270 Window
* pWindow
= GetWindow();
273 pWindow
->GrabFocus();
274 bDoAction
= sal_True
;
280 // -----------------------------------------------------------------------------
282 ::rtl::OUString
VCLXAccessibleEdit::getAccessibleActionDescription ( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
284 OExternalLockGuard
aGuard( this );
286 if ( nIndex
< 0 || nIndex
>= getAccessibleActionCount() )
287 throw IndexOutOfBoundsException();
289 static const ::rtl::OUString
sAction( RTL_CONSTASCII_USTRINGPARAM( "activate" ) );
293 // -----------------------------------------------------------------------------
295 Reference
< XAccessibleKeyBinding
> VCLXAccessibleEdit::getAccessibleActionKeyBinding( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
297 OExternalLockGuard
aGuard( this );
299 if ( nIndex
< 0 || nIndex
>= getAccessibleActionCount() )
300 throw IndexOutOfBoundsException();
302 return Reference
< XAccessibleKeyBinding
>();
305 // -----------------------------------------------------------------------------
307 // -----------------------------------------------------------------------------
309 sal_Int32
VCLXAccessibleEdit::getCaretPosition( ) throw (RuntimeException
)
311 OExternalLockGuard
aGuard( this );
313 awt::Selection aSelection
;
314 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
316 aSelection
= pVCLXEdit
->getSelection();
318 return aSelection
.Max
;
321 // -----------------------------------------------------------------------------
323 sal_Bool
VCLXAccessibleEdit::setCaretPosition( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
325 OExternalLockGuard
aGuard( this );
327 return setSelection( nIndex
, nIndex
);
330 // -----------------------------------------------------------------------------
332 sal_Unicode
VCLXAccessibleEdit::getCharacter( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
334 OExternalLockGuard
aGuard( this );
336 return VCLXAccessibleTextComponent::getCharacter( nIndex
);
339 // -----------------------------------------------------------------------------
341 Sequence
< PropertyValue
> VCLXAccessibleEdit::getCharacterAttributes( sal_Int32 nIndex
, const Sequence
< ::rtl::OUString
>& aRequestedAttributes
) throw (IndexOutOfBoundsException
, RuntimeException
)
343 OExternalLockGuard
aGuard( this );
345 return VCLXAccessibleTextComponent::getCharacterAttributes( nIndex
, aRequestedAttributes
);
348 // -----------------------------------------------------------------------------
350 awt::Rectangle
VCLXAccessibleEdit::getCharacterBounds( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
352 OExternalLockGuard
aGuard( this );
354 awt::Rectangle
aBounds( 0, 0, 0, 0 );
355 sal_Int32 nLength
= implGetText().getLength();
357 if ( !implIsValidRange( nIndex
, nIndex
, nLength
) )
358 throw IndexOutOfBoundsException();
360 Control
* pControl
= static_cast< Control
* >( GetWindow() );
363 if ( nIndex
== nLength
)
365 // #108914# calculate virtual bounding rectangle
366 for ( sal_Int32 i
= 0; i
< nLength
; ++i
)
368 Rectangle aRect
= pControl
->GetCharacterBounds( i
);
369 sal_Int32 nHeight
= aRect
.GetHeight();
370 if ( aBounds
.Height
< nHeight
)
372 aBounds
.Y
= aRect
.Top();
373 aBounds
.Height
= nHeight
;
375 if ( i
== nLength
- 1 )
377 aBounds
.X
= aRect
.Right() + 1;
384 aBounds
= AWTRectangle( pControl
->GetCharacterBounds( nIndex
) );
391 // -----------------------------------------------------------------------------
393 sal_Int32
VCLXAccessibleEdit::getCharacterCount( ) throw (RuntimeException
)
395 OExternalLockGuard
aGuard( this );
397 return VCLXAccessibleTextComponent::getCharacterCount();
400 // -----------------------------------------------------------------------------
402 sal_Int32
VCLXAccessibleEdit::getIndexAtPoint( const awt::Point
& aPoint
) throw (RuntimeException
)
404 OExternalLockGuard
aGuard( this );
406 return VCLXAccessibleTextComponent::getIndexAtPoint( aPoint
);
409 // -----------------------------------------------------------------------------
411 ::rtl::OUString
VCLXAccessibleEdit::getSelectedText( ) throw (RuntimeException
)
413 OExternalLockGuard
aGuard( this );
415 return VCLXAccessibleTextComponent::getSelectedText();
418 // -----------------------------------------------------------------------------
420 sal_Int32
VCLXAccessibleEdit::getSelectionStart( ) throw (RuntimeException
)
422 OExternalLockGuard
aGuard( this );
424 return VCLXAccessibleTextComponent::getSelectionStart();
427 // -----------------------------------------------------------------------------
429 sal_Int32
VCLXAccessibleEdit::getSelectionEnd( ) throw (RuntimeException
)
431 OExternalLockGuard
aGuard( this );
433 return VCLXAccessibleTextComponent::getSelectionEnd();
436 // -----------------------------------------------------------------------------
438 sal_Bool
VCLXAccessibleEdit::setSelection( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
440 OExternalLockGuard
aGuard( this );
442 sal_Bool bReturn
= sal_False
;
443 ::rtl::OUString
sText( implGetText() );
445 if ( !implIsValidRange( nStartIndex
, nEndIndex
, sText
.getLength() ) )
446 throw IndexOutOfBoundsException();
448 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
449 Edit
* pEdit
= static_cast< Edit
* >( GetWindow() );
450 if ( pVCLXEdit
&& pEdit
&& pEdit
->IsEnabled() )
452 pVCLXEdit
->setSelection( awt::Selection( nStartIndex
, nEndIndex
) );
459 // -----------------------------------------------------------------------------
461 ::rtl::OUString
VCLXAccessibleEdit::getText( ) throw (RuntimeException
)
463 OExternalLockGuard
aGuard( this );
465 return VCLXAccessibleTextComponent::getText();
468 // -----------------------------------------------------------------------------
470 ::rtl::OUString
VCLXAccessibleEdit::getTextRange( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
472 OExternalLockGuard
aGuard( this );
474 return VCLXAccessibleTextComponent::getTextRange( nStartIndex
, nEndIndex
);
477 // -----------------------------------------------------------------------------
479 ::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
)
481 OExternalLockGuard
aGuard( this );
483 return VCLXAccessibleTextComponent::getTextAtIndex( nIndex
, aTextType
);
486 // -----------------------------------------------------------------------------
488 ::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
)
490 OExternalLockGuard
aGuard( this );
492 return VCLXAccessibleTextComponent::getTextBeforeIndex( nIndex
, aTextType
);
495 // -----------------------------------------------------------------------------
497 ::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
)
499 OExternalLockGuard
aGuard( this );
501 return VCLXAccessibleTextComponent::getTextBehindIndex( nIndex
, aTextType
);
504 // -----------------------------------------------------------------------------
506 sal_Bool
VCLXAccessibleEdit::copyText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
508 OExternalLockGuard
aGuard( this );
510 return VCLXAccessibleTextComponent::copyText( nStartIndex
, nEndIndex
);
513 // -----------------------------------------------------------------------------
514 // XAccessibleEditableText
515 // -----------------------------------------------------------------------------
517 sal_Bool
VCLXAccessibleEdit::cutText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
519 OExternalLockGuard
aGuard( this );
521 return copyText( nStartIndex
, nEndIndex
) && deleteText( nStartIndex
, nEndIndex
);
524 // -----------------------------------------------------------------------------
526 sal_Bool
VCLXAccessibleEdit::pasteText( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
528 OExternalLockGuard
aGuard( this );
530 sal_Bool bReturn
= sal_False
;
534 Reference
< datatransfer::clipboard::XClipboard
> xClipboard
= GetWindow()->GetClipboard();
535 if ( xClipboard
.is() )
537 const sal_uInt32 nRef
= Application::ReleaseSolarMutex();
538 Reference
< datatransfer::XTransferable
> xDataObj
= xClipboard
->getContents();
539 Application::AcquireSolarMutex( nRef
);
542 datatransfer::DataFlavor aFlavor
;
543 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING
, aFlavor
);
544 if ( xDataObj
->isDataFlavorSupported( aFlavor
) )
546 Any aData
= xDataObj
->getTransferData( aFlavor
);
547 ::rtl::OUString sText
;
549 bReturn
= replaceText( nIndex
, nIndex
, sText
);
558 // -----------------------------------------------------------------------------
560 sal_Bool
VCLXAccessibleEdit::deleteText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
562 OExternalLockGuard
aGuard( this );
564 return replaceText( nStartIndex
, nEndIndex
, ::rtl::OUString() );
567 // -----------------------------------------------------------------------------
569 sal_Bool
VCLXAccessibleEdit::insertText( const ::rtl::OUString
& sText
, sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
)
571 OExternalLockGuard
aGuard( this );
573 return replaceText( nIndex
, nIndex
, sText
);
576 // -----------------------------------------------------------------------------
578 sal_Bool
VCLXAccessibleEdit::replaceText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
, const ::rtl::OUString
& sReplacement
) throw (IndexOutOfBoundsException
, RuntimeException
)
580 OExternalLockGuard
aGuard( this );
582 sal_Bool bReturn
= sal_False
;
583 ::rtl::OUString
sText( implGetText() );
585 if ( !implIsValidRange( nStartIndex
, nEndIndex
, sText
.getLength() ) )
586 throw IndexOutOfBoundsException();
588 sal_Int32 nMinIndex
= ::std::min( nStartIndex
, nEndIndex
);
589 sal_Int32 nMaxIndex
= ::std::max( nStartIndex
, nEndIndex
);
591 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
592 if ( pVCLXEdit
&& pVCLXEdit
->isEditable() )
594 pVCLXEdit
->setText( sText
.replaceAt( nMinIndex
, nMaxIndex
- nMinIndex
, sReplacement
) );
595 sal_Int32 nIndex
= nMinIndex
+ sReplacement
.getLength();
596 setSelection( nIndex
, nIndex
);
603 // -----------------------------------------------------------------------------
605 sal_Bool
VCLXAccessibleEdit::setAttributes( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
, const Sequence
<PropertyValue
>& ) throw (IndexOutOfBoundsException
, RuntimeException
)
607 OExternalLockGuard
aGuard( this );
609 if ( !implIsValidRange( nStartIndex
, nEndIndex
, implGetText().getLength() ) )
610 throw IndexOutOfBoundsException();
612 return sal_False
; // attributes cannot be set for an edit
615 // -----------------------------------------------------------------------------
617 sal_Bool
VCLXAccessibleEdit::setText( const ::rtl::OUString
& sText
) throw (RuntimeException
)
619 OExternalLockGuard
aGuard( this );
621 sal_Bool bSuccess
= sal_False
;
624 bSuccess
= replaceText( 0, implGetText().getLength(), sText
);
626 catch( const IndexOutOfBoundsException
& )
628 OSL_ENSURE( sal_False
, "VCLXAccessibleText::setText: caught an exception!" );
633 // -----------------------------------------------------------------------------