merged tag ooo/DEV300_m102
[LibreOffice.git] / accessibility / source / standard / vclxaccessibleedit.cxx
blobb806e308bc28984831952427081b3f0c74ea71d9
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>
53 #include <algorithm>
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 // -----------------------------------------------------------------------------
64 // VCLXAccessibleEdit
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() );
90 break;
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() );
120 break;
121 default:
122 VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
126 // -----------------------------------------------------------------------------
128 void VCLXAccessibleEdit::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
130 VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
132 VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
133 if ( pVCLXEdit )
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() );
151 if ( pEdit )
153 aText = OutputDevice::GetNonMnemonicString( pEdit->GetText() );
155 if ( getAccessibleRole() == AccessibleRole::PASSWORD_TEXT )
157 xub_Unicode cEchoChar = pEdit->GetEchoChar();
158 if ( !cEchoChar )
159 cEchoChar = '*';
160 XubString sTmp;
161 aText = sTmp.Fill( (sal_uInt16)aText.getLength(), cEchoChar );
165 return aText;
168 // -----------------------------------------------------------------------------
170 void VCLXAccessibleEdit::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
172 awt::Selection aSelection;
173 VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
174 if ( pVCLXEdit )
175 aSelection = pVCLXEdit->getSelection();
177 nStartIndex = aSelection.Min;
178 nEndIndex = aSelection.Max;
181 // -----------------------------------------------------------------------------
182 // XInterface
183 // -----------------------------------------------------------------------------
185 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleEdit, VCLXAccessibleTextComponent, VCLXAccessibleEdit_BASE )
187 // -----------------------------------------------------------------------------
188 // XTypeProvider
189 // -----------------------------------------------------------------------------
191 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleEdit, VCLXAccessibleTextComponent, VCLXAccessibleEdit_BASE )
193 // -----------------------------------------------------------------------------
194 // XServiceInfo
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" );
208 return aNames;
211 // -----------------------------------------------------------------------------
212 // XAccessibleContext
213 // -----------------------------------------------------------------------------
215 sal_Int32 VCLXAccessibleEdit::getAccessibleChildCount() throw (RuntimeException)
217 OExternalLockGuard aGuard( this );
219 return 0;
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 );
240 sal_Int16 nRole;
241 Edit* pEdit = static_cast< Edit* >( GetWindow() );
242 if ( pEdit && ( ( pEdit->GetStyle() & WB_PASSWORD ) || pEdit->GetEchoChar() ) )
243 nRole = AccessibleRole::PASSWORD_TEXT;
244 else
245 nRole = AccessibleRole::TEXT;
247 return nRole;
250 // -----------------------------------------------------------------------------
251 // XAccessibleAction
252 // -----------------------------------------------------------------------------
254 sal_Int32 VCLXAccessibleEdit::getAccessibleActionCount( ) throw (RuntimeException)
256 OExternalLockGuard aGuard( this );
258 // There is one action: activate
259 return 1;
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();
273 if ( pWindow )
275 pWindow->GrabFocus();
276 bDoAction = sal_True;
279 return bDoAction;
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" ) );
292 return sAction;
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 // -----------------------------------------------------------------------------
308 // XAccessibleText
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() );
354 if ( pControl )
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;
371 aBounds.Width = 1;
375 else
377 aBounds = AWTRectangle( pControl->GetCharacterBounds( nIndex ) );
381 return aBounds;
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 ) );
446 bReturn = sal_True;
449 return bReturn;
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;
525 if ( GetWindow() )
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 );
533 if ( xDataObj.is() )
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;
541 aData >>= sText;
542 bReturn = replaceText( nIndex, nIndex, sText );
548 return bReturn;
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 );
590 bReturn = sal_True;
593 return bReturn;
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!" );
623 return bSuccess;
626 // -----------------------------------------------------------------------------