bump product version to 4.1.6.2
[LibreOffice.git] / accessibility / source / standard / vclxaccessibleedit.cxx
blob20e4c862a895a604d588ea9baadb49f626c1d4e4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <accessibility/standard/vclxaccessibleedit.hxx>
22 #include <toolkit/awt/vclxwindows.hxx>
23 #include <toolkit/helper/convert.hxx>
24 #include <accessibility/helper/accresmgr.hxx>
25 #include <accessibility/helper/accessiblestrings.hrc>
27 #include <unotools/accessiblestatesethelper.hxx>
28 #include <unotools/accessiblerelationsethelper.hxx>
29 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
30 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
31 #include <com/sun/star/accessibility/AccessibleRole.hpp>
32 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
33 #include <cppuhelper/typeprovider.hxx>
34 #include <comphelper/sequence.hxx>
35 #include <comphelper/string.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/window.hxx>
38 #include <vcl/edit.hxx>
39 #include <sot/exchange.hxx>
40 #include <sot/formats.hxx>
42 #include <algorithm>
44 using namespace ::com::sun::star;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star::beans;
48 using namespace ::com::sun::star::accessibility;
49 using namespace ::comphelper;
52 // -----------------------------------------------------------------------------
53 // VCLXAccessibleEdit
54 // -----------------------------------------------------------------------------
56 VCLXAccessibleEdit::VCLXAccessibleEdit( VCLXWindow* pVCLWindow )
57 :VCLXAccessibleTextComponent( pVCLWindow )
59 m_nSelectionStart = getSelectionStart();
60 m_nCaretPosition = getCaretPosition();
63 // -----------------------------------------------------------------------------
65 VCLXAccessibleEdit::~VCLXAccessibleEdit()
69 // -----------------------------------------------------------------------------
71 void VCLXAccessibleEdit::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
73 switch ( rVclWindowEvent.GetId() )
75 case VCLEVENT_EDIT_MODIFY:
77 SetText( implGetText() );
79 break;
80 case VCLEVENT_EDIT_SELECTIONCHANGED:
82 sal_Int32 nOldCaretPosition = m_nCaretPosition;
83 sal_Int32 nOldSelectionStart = m_nSelectionStart;
85 m_nCaretPosition = getCaretPosition();
86 m_nSelectionStart = getSelectionStart();
88 Window* pWindow = GetWindow();
89 if ( pWindow && pWindow->HasChildPathFocus() )
91 if ( m_nCaretPosition != nOldCaretPosition )
93 Any aOldValue, aNewValue;
94 aOldValue <<= (sal_Int32) nOldCaretPosition;
95 aNewValue <<= (sal_Int32) m_nCaretPosition;
96 NotifyAccessibleEvent( AccessibleEventId::CARET_CHANGED, aOldValue, aNewValue );
99 // #i104470# VCL only has SELECTION_CHANGED, but UAA distinguishes between SELECTION_CHANGED and CARET_CHANGED
100 sal_Bool bHasSelection = ( m_nSelectionStart != m_nCaretPosition );
101 sal_Bool bHadSelection = ( nOldSelectionStart != nOldCaretPosition );
102 if ( ( bHasSelection != bHadSelection ) || ( bHasSelection && ( ( m_nCaretPosition != nOldCaretPosition ) || ( m_nSelectionStart != nOldSelectionStart ) ) ) )
104 NotifyAccessibleEvent( AccessibleEventId::TEXT_SELECTION_CHANGED, Any(), Any() );
109 break;
110 default:
111 VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
115 // -----------------------------------------------------------------------------
117 void VCLXAccessibleEdit::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
119 VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
121 VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
122 if ( pVCLXEdit )
124 rStateSet.AddState( AccessibleStateType::FOCUSABLE );
125 rStateSet.AddState( AccessibleStateType::SINGLE_LINE );
126 if ( pVCLXEdit->isEditable() )
127 rStateSet.AddState( AccessibleStateType::EDITABLE );
131 // -----------------------------------------------------------------------------
132 // OCommonAccessibleText
133 // -----------------------------------------------------------------------------
135 OUString VCLXAccessibleEdit::implGetText()
137 OUString aText;
139 Edit* pEdit = static_cast< Edit* >( GetWindow() );
140 if ( pEdit )
142 aText = OutputDevice::GetNonMnemonicString( pEdit->GetText() );
144 if ( getAccessibleRole() == AccessibleRole::PASSWORD_TEXT )
146 sal_Unicode cEchoChar = pEdit->GetEchoChar();
147 if ( !cEchoChar )
148 cEchoChar = '*';
149 OUStringBuffer sTmp;
150 aText = comphelper::string::padToLength(sTmp, aText.getLength(),
151 cEchoChar).makeStringAndClear();
155 return aText;
158 // -----------------------------------------------------------------------------
160 void VCLXAccessibleEdit::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
162 awt::Selection aSelection;
163 VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
164 if ( pVCLXEdit )
165 aSelection = pVCLXEdit->getSelection();
167 nStartIndex = aSelection.Min;
168 nEndIndex = aSelection.Max;
171 // -----------------------------------------------------------------------------
172 // XInterface
173 // -----------------------------------------------------------------------------
175 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleEdit, VCLXAccessibleTextComponent, VCLXAccessibleEdit_BASE )
177 // -----------------------------------------------------------------------------
178 // XTypeProvider
179 // -----------------------------------------------------------------------------
181 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleEdit, VCLXAccessibleTextComponent, VCLXAccessibleEdit_BASE )
183 // -----------------------------------------------------------------------------
184 // XServiceInfo
185 // -----------------------------------------------------------------------------
187 OUString VCLXAccessibleEdit::getImplementationName() throw (RuntimeException)
189 return OUString( "com.sun.star.comp.toolkit.AccessibleEdit" );
192 // -----------------------------------------------------------------------------
194 Sequence< OUString > VCLXAccessibleEdit::getSupportedServiceNames() throw (RuntimeException)
196 Sequence< OUString > aNames(1);
197 aNames[0] = "com.sun.star.awt.AccessibleEdit";
198 return aNames;
201 // -----------------------------------------------------------------------------
202 // XAccessibleContext
203 // -----------------------------------------------------------------------------
205 sal_Int32 VCLXAccessibleEdit::getAccessibleChildCount() throw (RuntimeException)
207 OExternalLockGuard aGuard( this );
209 return 0;
212 // -----------------------------------------------------------------------------
214 Reference< XAccessible > VCLXAccessibleEdit::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
216 OExternalLockGuard aGuard( this );
218 if ( i < 0 || i >= getAccessibleChildCount() )
219 throw IndexOutOfBoundsException();
221 return Reference< XAccessible >();
224 // -----------------------------------------------------------------------------
226 sal_Int16 VCLXAccessibleEdit::getAccessibleRole( ) throw (RuntimeException)
228 OExternalLockGuard aGuard( this );
230 sal_Int16 nRole;
231 Edit* pEdit = static_cast< Edit* >( GetWindow() );
232 if ( pEdit && ( ( pEdit->GetStyle() & WB_PASSWORD ) || pEdit->GetEchoChar() ) )
233 nRole = AccessibleRole::PASSWORD_TEXT;
234 else
235 nRole = AccessibleRole::TEXT;
237 return nRole;
240 // -----------------------------------------------------------------------------
241 // XAccessibleAction
242 // -----------------------------------------------------------------------------
244 sal_Int32 VCLXAccessibleEdit::getAccessibleActionCount( ) throw (RuntimeException)
246 OExternalLockGuard aGuard( this );
248 // There is one action: activate
249 return 1;
252 // -----------------------------------------------------------------------------
254 sal_Bool VCLXAccessibleEdit::doAccessibleAction ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
256 OExternalLockGuard aGuard( this );
258 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
259 throw IndexOutOfBoundsException();
261 sal_Bool bDoAction = sal_False;
262 Window* pWindow = GetWindow();
263 if ( pWindow )
265 pWindow->GrabFocus();
266 bDoAction = sal_True;
269 return bDoAction;
272 // -----------------------------------------------------------------------------
274 OUString VCLXAccessibleEdit::getAccessibleActionDescription ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
276 OExternalLockGuard aGuard( this );
278 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
279 throw IndexOutOfBoundsException();
281 static const OUString sAction( "activate" );
282 return sAction;
285 // -----------------------------------------------------------------------------
287 Reference< XAccessibleKeyBinding > VCLXAccessibleEdit::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
289 OExternalLockGuard aGuard( this );
291 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
292 throw IndexOutOfBoundsException();
294 return Reference< XAccessibleKeyBinding >();
297 // -----------------------------------------------------------------------------
298 // XAccessibleText
299 // -----------------------------------------------------------------------------
301 sal_Int32 VCLXAccessibleEdit::getCaretPosition( ) throw (RuntimeException)
303 return getSelectionEnd();
306 // -----------------------------------------------------------------------------
308 sal_Bool VCLXAccessibleEdit::setCaretPosition( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
310 return setSelection( nIndex, nIndex );
313 // -----------------------------------------------------------------------------
315 sal_Unicode VCLXAccessibleEdit::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
317 OExternalLockGuard aGuard( this );
319 return VCLXAccessibleTextComponent::getCharacter( nIndex );
322 // -----------------------------------------------------------------------------
324 Sequence< PropertyValue > VCLXAccessibleEdit::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes ) throw (IndexOutOfBoundsException, RuntimeException)
326 OExternalLockGuard aGuard( this );
328 return VCLXAccessibleTextComponent::getCharacterAttributes( nIndex, aRequestedAttributes );
331 // -----------------------------------------------------------------------------
333 awt::Rectangle VCLXAccessibleEdit::getCharacterBounds( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
335 OExternalLockGuard aGuard( this );
337 awt::Rectangle aBounds( 0, 0, 0, 0 );
338 sal_Int32 nLength = implGetText().getLength();
340 if ( !implIsValidRange( nIndex, nIndex, nLength ) )
341 throw IndexOutOfBoundsException();
343 Control* pControl = static_cast< Control* >( GetWindow() );
344 if ( pControl )
346 if ( nIndex == nLength )
348 // #108914# calculate virtual bounding rectangle
349 for ( sal_Int32 i = 0; i < nLength; ++i )
351 Rectangle aRect = pControl->GetCharacterBounds( i );
352 sal_Int32 nHeight = aRect.GetHeight();
353 if ( aBounds.Height < nHeight )
355 aBounds.Y = aRect.Top();
356 aBounds.Height = nHeight;
358 if ( i == nLength - 1 )
360 aBounds.X = aRect.Right() + 1;
361 aBounds.Width = 1;
365 else
367 aBounds = AWTRectangle( pControl->GetCharacterBounds( nIndex ) );
371 return aBounds;
374 // -----------------------------------------------------------------------------
376 sal_Int32 VCLXAccessibleEdit::getCharacterCount( ) throw (RuntimeException)
378 OExternalLockGuard aGuard( this );
380 return VCLXAccessibleTextComponent::getCharacterCount();
383 // -----------------------------------------------------------------------------
385 sal_Int32 VCLXAccessibleEdit::getIndexAtPoint( const awt::Point& aPoint ) throw (RuntimeException)
387 OExternalLockGuard aGuard( this );
389 return VCLXAccessibleTextComponent::getIndexAtPoint( aPoint );
392 // -----------------------------------------------------------------------------
394 OUString VCLXAccessibleEdit::getSelectedText( ) throw (RuntimeException)
396 OExternalLockGuard aGuard( this );
398 return VCLXAccessibleTextComponent::getSelectedText();
401 // -----------------------------------------------------------------------------
403 sal_Int32 VCLXAccessibleEdit::getSelectionStart( ) throw (RuntimeException)
405 OExternalLockGuard aGuard( this );
407 return VCLXAccessibleTextComponent::getSelectionStart();
410 // -----------------------------------------------------------------------------
412 sal_Int32 VCLXAccessibleEdit::getSelectionEnd( ) throw (RuntimeException)
414 OExternalLockGuard aGuard( this );
416 return VCLXAccessibleTextComponent::getSelectionEnd();
419 // -----------------------------------------------------------------------------
421 sal_Bool VCLXAccessibleEdit::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
423 OExternalLockGuard aGuard( this );
425 sal_Bool bReturn = sal_False;
426 OUString sText( implGetText() );
428 if ( !implIsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
429 throw IndexOutOfBoundsException();
431 VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
432 Edit* pEdit = static_cast< Edit* >( GetWindow() );
433 if ( pVCLXEdit && pEdit && pEdit->IsEnabled() )
435 pVCLXEdit->setSelection( awt::Selection( nStartIndex, nEndIndex ) );
436 bReturn = sal_True;
439 return bReturn;
442 // -----------------------------------------------------------------------------
444 OUString VCLXAccessibleEdit::getText( ) throw (RuntimeException)
446 OExternalLockGuard aGuard( this );
448 return VCLXAccessibleTextComponent::getText();
451 // -----------------------------------------------------------------------------
453 OUString VCLXAccessibleEdit::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
455 OExternalLockGuard aGuard( this );
457 return VCLXAccessibleTextComponent::getTextRange( nStartIndex, nEndIndex );
460 // -----------------------------------------------------------------------------
462 ::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)
464 OExternalLockGuard aGuard( this );
466 return VCLXAccessibleTextComponent::getTextAtIndex( nIndex, aTextType );
469 // -----------------------------------------------------------------------------
471 ::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)
473 OExternalLockGuard aGuard( this );
475 return VCLXAccessibleTextComponent::getTextBeforeIndex( nIndex, aTextType );
478 // -----------------------------------------------------------------------------
480 ::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)
482 OExternalLockGuard aGuard( this );
484 return VCLXAccessibleTextComponent::getTextBehindIndex( nIndex, aTextType );
487 // -----------------------------------------------------------------------------
489 sal_Bool VCLXAccessibleEdit::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
491 OExternalLockGuard aGuard( this );
493 return VCLXAccessibleTextComponent::copyText( nStartIndex, nEndIndex );
496 // -----------------------------------------------------------------------------
497 // XAccessibleEditableText
498 // -----------------------------------------------------------------------------
500 sal_Bool VCLXAccessibleEdit::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
502 OExternalLockGuard aGuard( this );
504 return copyText( nStartIndex, nEndIndex ) && deleteText( nStartIndex, nEndIndex );
507 // -----------------------------------------------------------------------------
509 sal_Bool VCLXAccessibleEdit::pasteText( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
511 OExternalLockGuard aGuard( this );
513 sal_Bool bReturn = sal_False;
515 if ( GetWindow() )
517 Reference< datatransfer::clipboard::XClipboard > xClipboard = GetWindow()->GetClipboard();
518 if ( xClipboard.is() )
520 const sal_uInt32 nRef = Application::ReleaseSolarMutex();
521 Reference< datatransfer::XTransferable > xDataObj = xClipboard->getContents();
522 Application::AcquireSolarMutex( nRef );
523 if ( xDataObj.is() )
525 datatransfer::DataFlavor aFlavor;
526 SotExchange::GetFormatDataFlavor( SOT_FORMAT_STRING, aFlavor );
527 if ( xDataObj->isDataFlavorSupported( aFlavor ) )
529 Any aData = xDataObj->getTransferData( aFlavor );
530 OUString sText;
531 aData >>= sText;
532 bReturn = replaceText( nIndex, nIndex, sText );
538 return bReturn;
541 // -----------------------------------------------------------------------------
543 sal_Bool VCLXAccessibleEdit::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
545 OExternalLockGuard aGuard( this );
547 return replaceText( nStartIndex, nEndIndex, OUString() );
550 // -----------------------------------------------------------------------------
552 sal_Bool VCLXAccessibleEdit::insertText( const OUString& sText, sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
554 OExternalLockGuard aGuard( this );
556 return replaceText( nIndex, nIndex, sText );
559 // -----------------------------------------------------------------------------
561 sal_Bool VCLXAccessibleEdit::replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const OUString& sReplacement ) throw (IndexOutOfBoundsException, RuntimeException)
563 OExternalLockGuard aGuard( this );
565 sal_Bool bReturn = sal_False;
566 OUString sText( implGetText() );
568 if ( !implIsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
569 throw IndexOutOfBoundsException();
571 sal_Int32 nMinIndex = ::std::min( nStartIndex, nEndIndex );
572 sal_Int32 nMaxIndex = ::std::max( nStartIndex, nEndIndex );
574 VCLXEdit* pVCLXEdit = static_cast< VCLXEdit* >( GetVCLXWindow() );
575 if ( pVCLXEdit && pVCLXEdit->isEditable() )
577 pVCLXEdit->setText( sText.replaceAt( nMinIndex, nMaxIndex - nMinIndex, sReplacement ) );
578 sal_Int32 nIndex = nMinIndex + sReplacement.getLength();
579 setSelection( nIndex, nIndex );
580 bReturn = sal_True;
583 return bReturn;
586 // -----------------------------------------------------------------------------
588 sal_Bool VCLXAccessibleEdit::setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const Sequence<PropertyValue>& ) throw (IndexOutOfBoundsException, RuntimeException)
590 OExternalLockGuard aGuard( this );
592 if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
593 throw IndexOutOfBoundsException();
595 return sal_False; // attributes cannot be set for an edit
598 // -----------------------------------------------------------------------------
600 sal_Bool VCLXAccessibleEdit::setText( const OUString& sText ) throw (RuntimeException)
602 OExternalLockGuard aGuard( this );
604 sal_Bool bSuccess = sal_False;
607 bSuccess = replaceText( 0, implGetText().getLength(), sText );
609 catch( const IndexOutOfBoundsException& )
611 OSL_FAIL( "VCLXAccessibleText::setText: caught an exception!" );
613 return bSuccess;
616 // -----------------------------------------------------------------------------
618 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */