merge the formfield patch from ooo-build
[ooovba.git] / accessibility / source / standard / vclxaccessibleedit.cxx
blobcf5040efdd7f728511b14b34281082d0591f7cd9
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 $
10 * $Revision: 1.4 $
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>
56 #include <algorithm>
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 // -----------------------------------------------------------------------------
67 // VCLXAccessibleEdit
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() );
108 break;
109 case VCLEVENT_EDIT_SELECTIONCHANGED:
111 Window* pWindow = GetWindow();
112 if ( pWindow && pWindow->HasChildPathFocus() )
114 NotifyAccessibleEvent( AccessibleEventId::TEXT_SELECTION_CHANGED, Any(), Any() );
115 UpdateCaretPosition();
118 break;
119 default:
120 VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
124 // -----------------------------------------------------------------------------
126 void VCLXAccessibleEdit::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
128 VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
130 VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
131 if ( pVCLXEdit )
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() );
149 if ( pEdit )
151 aText = OutputDevice::GetNonMnemonicString( pEdit->GetText() );
153 if ( getAccessibleRole() == AccessibleRole::PASSWORD_TEXT )
155 xub_Unicode cEchoChar = pEdit->GetEchoChar();
156 if ( !cEchoChar )
157 cEchoChar = '*';
158 XubString sTmp;
159 aText = sTmp.Fill( (USHORT)aText.getLength(), cEchoChar );
163 return aText;
166 // -----------------------------------------------------------------------------
168 void VCLXAccessibleEdit::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
170 awt::Selection aSelection;
171 VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
172 if ( pVCLXEdit )
173 aSelection = pVCLXEdit->getSelection();
175 nStartIndex = aSelection.Min;
176 nEndIndex = aSelection.Max;
179 // -----------------------------------------------------------------------------
180 // XInterface
181 // -----------------------------------------------------------------------------
183 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleEdit, VCLXAccessibleTextComponent, VCLXAccessibleEdit_BASE )
185 // -----------------------------------------------------------------------------
186 // XTypeProvider
187 // -----------------------------------------------------------------------------
189 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleEdit, VCLXAccessibleTextComponent, VCLXAccessibleEdit_BASE )
191 // -----------------------------------------------------------------------------
192 // XServiceInfo
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" );
206 return aNames;
209 // -----------------------------------------------------------------------------
210 // XAccessibleContext
211 // -----------------------------------------------------------------------------
213 sal_Int32 VCLXAccessibleEdit::getAccessibleChildCount() throw (RuntimeException)
215 OExternalLockGuard aGuard( this );
217 return 0;
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 );
238 sal_Int16 nRole;
239 Edit* pEdit = static_cast< Edit* >( GetWindow() );
240 if ( pEdit && ( ( pEdit->GetStyle() & WB_PASSWORD ) || pEdit->GetEchoChar() ) )
241 nRole = AccessibleRole::PASSWORD_TEXT;
242 else
243 nRole = AccessibleRole::TEXT;
245 return nRole;
248 // -----------------------------------------------------------------------------
249 // XAccessibleAction
250 // -----------------------------------------------------------------------------
252 sal_Int32 VCLXAccessibleEdit::getAccessibleActionCount( ) throw (RuntimeException)
254 OExternalLockGuard aGuard( this );
256 // There is one action: activate
257 return 1;
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();
271 if ( pWindow )
273 pWindow->GrabFocus();
274 bDoAction = sal_True;
277 return bDoAction;
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" ) );
290 return sAction;
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 // -----------------------------------------------------------------------------
306 // XAccessibleText
307 // -----------------------------------------------------------------------------
309 sal_Int32 VCLXAccessibleEdit::getCaretPosition( ) throw (RuntimeException)
311 OExternalLockGuard aGuard( this );
313 awt::Selection aSelection;
314 VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
315 if ( pVCLXEdit )
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() );
361 if ( pControl )
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;
378 aBounds.Width = 1;
382 else
384 aBounds = AWTRectangle( pControl->GetCharacterBounds( nIndex ) );
388 return aBounds;
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 ) );
453 bReturn = sal_True;
456 return bReturn;
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;
532 if ( GetWindow() )
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 );
540 if ( xDataObj.is() )
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;
548 aData >>= sText;
549 bReturn = replaceText( nIndex, nIndex, sText );
555 return bReturn;
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 );
597 bReturn = sal_True;
600 return bReturn;
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!" );
630 return bSuccess;
633 // -----------------------------------------------------------------------------