1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
;
56 VCLXAccessibleEdit::VCLXAccessibleEdit( VCLXWindow
* pVCLWindow
)
57 :VCLXAccessibleTextComponent( pVCLWindow
)
59 m_nSelectionStart
= getSelectionStart();
60 m_nCaretPosition
= getCaretPosition();
65 VCLXAccessibleEdit::~VCLXAccessibleEdit()
71 void VCLXAccessibleEdit::ProcessWindowEvent( const VclWindowEvent
& rVclWindowEvent
)
73 switch ( rVclWindowEvent
.GetId() )
75 case VCLEVENT_EDIT_MODIFY
:
77 SetText( implGetText() );
80 case VCLEVENT_EDIT_CARETCHANGED
:
82 sal_Int32 nOldCaretPosition
= m_nCaretPosition
;
83 m_nCaretPosition
= getCaretPosition();
85 vcl::Window
* pWindow
= GetWindow();
86 if (pWindow
&& pWindow
->HasChildPathFocus())
88 if (m_nCaretPosition
!= nOldCaretPosition
)
90 Any aOldValue
, aNewValue
;
91 aOldValue
<<= nOldCaretPosition
;
92 aNewValue
<<= m_nCaretPosition
;
93 NotifyAccessibleEvent( AccessibleEventId::CARET_CHANGED
, aOldValue
, aNewValue
);
98 case VCLEVENT_EDIT_SELECTIONCHANGED
:
100 vcl::Window
* pWindow
= GetWindow();
101 if (pWindow
&& pWindow
->HasChildPathFocus())
103 NotifyAccessibleEvent( AccessibleEventId::TEXT_SELECTION_CHANGED
, Any(), Any() );
108 VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent
);
114 void VCLXAccessibleEdit::FillAccessibleStateSet( utl::AccessibleStateSetHelper
& rStateSet
)
116 VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet
);
118 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
121 rStateSet
.AddState( AccessibleStateType::FOCUSABLE
);
122 rStateSet
.AddState( AccessibleStateType::SINGLE_LINE
);
123 if ( pVCLXEdit
->isEditable() )
124 rStateSet
.AddState( AccessibleStateType::EDITABLE
);
129 // OCommonAccessibleText
132 OUString
VCLXAccessibleEdit::implGetText()
136 VclPtr
< Edit
> pEdit
= GetAs
< Edit
>();
139 aText
= OutputDevice::GetNonMnemonicString( pEdit
->GetText() );
141 if ( getAccessibleRole() == AccessibleRole::PASSWORD_TEXT
)
143 sal_Unicode cEchoChar
= pEdit
->GetEchoChar();
147 aText
= comphelper::string::padToLength(sTmp
, aText
.getLength(),
148 cEchoChar
).makeStringAndClear();
157 void VCLXAccessibleEdit::implGetSelection( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
)
159 awt::Selection aSelection
;
160 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
162 aSelection
= pVCLXEdit
->getSelection();
164 nStartIndex
= aSelection
.Min
;
165 nEndIndex
= aSelection
.Max
;
172 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleEdit
, VCLXAccessibleTextComponent
, VCLXAccessibleEdit_BASE
)
178 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleEdit
, VCLXAccessibleTextComponent
, VCLXAccessibleEdit_BASE
)
184 OUString
VCLXAccessibleEdit::getImplementationName() throw (RuntimeException
, std::exception
)
186 return OUString( "com.sun.star.comp.toolkit.AccessibleEdit" );
191 Sequence
< OUString
> VCLXAccessibleEdit::getSupportedServiceNames() throw (RuntimeException
, std::exception
)
193 Sequence
< OUString
> aNames(1);
194 aNames
[0] = "com.sun.star.awt.AccessibleEdit";
199 // XAccessibleContext
202 sal_Int32
VCLXAccessibleEdit::getAccessibleChildCount() throw (RuntimeException
, std::exception
)
204 OExternalLockGuard
aGuard( this );
211 Reference
< XAccessible
> VCLXAccessibleEdit::getAccessibleChild( sal_Int32 i
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
213 OExternalLockGuard
aGuard( this );
215 if ( i
< 0 || i
>= getAccessibleChildCount() )
216 throw IndexOutOfBoundsException();
218 return Reference
< XAccessible
>();
223 sal_Int16
VCLXAccessibleEdit::getAccessibleRole( ) throw (RuntimeException
, std::exception
)
225 OExternalLockGuard
aGuard( this );
228 VclPtr
< Edit
> pEdit
= GetAs
< Edit
>();
229 if ( pEdit
&& ( ( pEdit
->GetStyle() & WB_PASSWORD
) || pEdit
->GetEchoChar() ) )
230 nRole
= AccessibleRole::PASSWORD_TEXT
;
232 nRole
= AccessibleRole::TEXT
;
241 sal_Int32
VCLXAccessibleEdit::getAccessibleActionCount( ) throw (RuntimeException
, std::exception
)
243 OExternalLockGuard
aGuard( this );
245 // There is one action: activate
251 sal_Bool
VCLXAccessibleEdit::doAccessibleAction ( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
253 OExternalLockGuard
aGuard( this );
255 if ( nIndex
< 0 || nIndex
>= getAccessibleActionCount() )
256 throw IndexOutOfBoundsException();
258 bool bDoAction
= false;
259 vcl::Window
* pWindow
= GetWindow();
262 pWindow
->GrabFocus();
271 OUString
VCLXAccessibleEdit::getAccessibleActionDescription ( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
273 OExternalLockGuard
aGuard( this );
275 if ( nIndex
< 0 || nIndex
>= getAccessibleActionCount() )
276 throw IndexOutOfBoundsException();
278 return OUString( "activate" );
283 Reference
< XAccessibleKeyBinding
> VCLXAccessibleEdit::getAccessibleActionKeyBinding( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
285 OExternalLockGuard
aGuard( this );
287 if ( nIndex
< 0 || nIndex
>= getAccessibleActionCount() )
288 throw IndexOutOfBoundsException();
290 return Reference
< XAccessibleKeyBinding
>();
297 sal_Int32
VCLXAccessibleEdit::getCaretPosition( ) throw (RuntimeException
, std::exception
)
299 return getSelectionEnd();
304 sal_Bool
VCLXAccessibleEdit::setCaretPosition( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
306 return setSelection( nIndex
, nIndex
);
311 sal_Unicode
VCLXAccessibleEdit::getCharacter( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
313 OExternalLockGuard
aGuard( this );
315 return VCLXAccessibleTextComponent::getCharacter( nIndex
);
320 Sequence
< PropertyValue
> VCLXAccessibleEdit::getCharacterAttributes( sal_Int32 nIndex
, const Sequence
< OUString
>& aRequestedAttributes
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
322 OExternalLockGuard
aGuard( this );
324 return VCLXAccessibleTextComponent::getCharacterAttributes( nIndex
, aRequestedAttributes
);
329 awt::Rectangle
VCLXAccessibleEdit::getCharacterBounds( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
331 OExternalLockGuard
aGuard( this );
333 awt::Rectangle
aBounds( 0, 0, 0, 0 );
334 sal_Int32 nLength
= implGetText().getLength();
336 if ( !implIsValidRange( nIndex
, nIndex
, nLength
) )
337 throw IndexOutOfBoundsException();
339 VclPtr
< Control
> pControl
= GetAs
< Control
>();
342 if ( nIndex
== nLength
)
344 // #108914# calculate virtual bounding rectangle
345 for ( sal_Int32 i
= 0; i
< nLength
; ++i
)
347 Rectangle aRect
= pControl
->GetCharacterBounds( i
);
348 sal_Int32 nHeight
= aRect
.GetHeight();
349 if ( aBounds
.Height
< nHeight
)
351 aBounds
.Y
= aRect
.Top();
352 aBounds
.Height
= nHeight
;
354 if ( i
== nLength
- 1 )
356 aBounds
.X
= aRect
.Right() + 1;
363 aBounds
= AWTRectangle( pControl
->GetCharacterBounds( nIndex
) );
372 sal_Int32
VCLXAccessibleEdit::getCharacterCount( ) throw (RuntimeException
, std::exception
)
374 OExternalLockGuard
aGuard( this );
376 return VCLXAccessibleTextComponent::getCharacterCount();
381 sal_Int32
VCLXAccessibleEdit::getIndexAtPoint( const awt::Point
& aPoint
) throw (RuntimeException
, std::exception
)
383 OExternalLockGuard
aGuard( this );
385 return VCLXAccessibleTextComponent::getIndexAtPoint( aPoint
);
390 OUString
VCLXAccessibleEdit::getSelectedText( ) throw (RuntimeException
, std::exception
)
392 OExternalLockGuard
aGuard( this );
394 return VCLXAccessibleTextComponent::getSelectedText();
399 sal_Int32
VCLXAccessibleEdit::getSelectionStart( ) throw (RuntimeException
, std::exception
)
401 OExternalLockGuard
aGuard( this );
403 return VCLXAccessibleTextComponent::getSelectionStart();
408 sal_Int32
VCLXAccessibleEdit::getSelectionEnd( ) throw (RuntimeException
, std::exception
)
410 OExternalLockGuard
aGuard( this );
412 return VCLXAccessibleTextComponent::getSelectionEnd();
417 sal_Bool
VCLXAccessibleEdit::setSelection( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
419 OExternalLockGuard
aGuard( this );
421 bool bReturn
= false;
422 OUString
sText( implGetText() );
424 if ( !implIsValidRange( nStartIndex
, nEndIndex
, sText
.getLength() ) )
425 throw IndexOutOfBoundsException();
427 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
428 VclPtr
< Edit
> pEdit
= GetAs
< Edit
>();
429 if ( pVCLXEdit
&& pEdit
&& pEdit
->IsEnabled() )
431 pVCLXEdit
->setSelection( awt::Selection( nStartIndex
, nEndIndex
) );
440 OUString
VCLXAccessibleEdit::getText( ) throw (RuntimeException
, std::exception
)
442 OExternalLockGuard
aGuard( this );
444 return VCLXAccessibleTextComponent::getText();
449 OUString
VCLXAccessibleEdit::getTextRange( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
451 OExternalLockGuard
aGuard( this );
453 return VCLXAccessibleTextComponent::getTextRange( nStartIndex
, nEndIndex
);
458 ::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
, std::exception
)
460 OExternalLockGuard
aGuard( this );
462 return VCLXAccessibleTextComponent::getTextAtIndex( nIndex
, aTextType
);
467 ::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
, std::exception
)
469 OExternalLockGuard
aGuard( this );
471 return VCLXAccessibleTextComponent::getTextBeforeIndex( nIndex
, aTextType
);
476 ::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
, std::exception
)
478 OExternalLockGuard
aGuard( this );
480 return VCLXAccessibleTextComponent::getTextBehindIndex( nIndex
, aTextType
);
485 sal_Bool
VCLXAccessibleEdit::copyText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
487 OExternalLockGuard
aGuard( this );
489 return VCLXAccessibleTextComponent::copyText( nStartIndex
, nEndIndex
);
493 // XAccessibleEditableText
496 sal_Bool
VCLXAccessibleEdit::cutText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
498 OExternalLockGuard
aGuard( this );
500 return copyText( nStartIndex
, nEndIndex
) && deleteText( nStartIndex
, nEndIndex
);
505 sal_Bool
VCLXAccessibleEdit::pasteText( sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
507 OExternalLockGuard
aGuard( this );
509 bool bReturn
= false;
513 Reference
< datatransfer::clipboard::XClipboard
> xClipboard
= GetWindow()->GetClipboard();
514 if ( xClipboard
.is() )
516 Reference
< datatransfer::XTransferable
> xDataObj
;
518 SolarMutexReleaser aReleaser
;
519 xDataObj
= xClipboard
->getContents();
523 datatransfer::DataFlavor aFlavor
;
524 SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING
, aFlavor
);
525 if ( xDataObj
->isDataFlavorSupported( aFlavor
) )
527 Any aData
= xDataObj
->getTransferData( aFlavor
);
530 bReturn
= replaceText( nIndex
, nIndex
, sText
);
541 sal_Bool
VCLXAccessibleEdit::deleteText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
543 OExternalLockGuard
aGuard( this );
545 return replaceText( nStartIndex
, nEndIndex
, OUString() );
550 sal_Bool
VCLXAccessibleEdit::insertText( const OUString
& sText
, sal_Int32 nIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
552 OExternalLockGuard
aGuard( this );
554 return replaceText( nIndex
, nIndex
, sText
);
559 sal_Bool
VCLXAccessibleEdit::replaceText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
, const OUString
& sReplacement
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
561 OExternalLockGuard
aGuard( this );
563 bool bReturn
= false;
564 OUString
sText( implGetText() );
566 if ( !implIsValidRange( nStartIndex
, nEndIndex
, sText
.getLength() ) )
567 throw IndexOutOfBoundsException();
569 sal_Int32 nMinIndex
= ::std::min( nStartIndex
, nEndIndex
);
570 sal_Int32 nMaxIndex
= ::std::max( nStartIndex
, nEndIndex
);
572 VCLXEdit
* pVCLXEdit
= static_cast< VCLXEdit
* >( GetVCLXWindow() );
573 if ( pVCLXEdit
&& pVCLXEdit
->isEditable() )
575 pVCLXEdit
->setText( sText
.replaceAt( nMinIndex
, nMaxIndex
- nMinIndex
, sReplacement
) );
576 sal_Int32 nIndex
= nMinIndex
+ sReplacement
.getLength();
577 setSelection( nIndex
, nIndex
);
586 sal_Bool
VCLXAccessibleEdit::setAttributes( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
, const Sequence
<PropertyValue
>& ) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
588 OExternalLockGuard
aGuard( this );
590 if ( !implIsValidRange( nStartIndex
, nEndIndex
, implGetText().getLength() ) )
591 throw IndexOutOfBoundsException();
593 return false; // attributes cannot be set for an edit
598 sal_Bool
VCLXAccessibleEdit::setText( const OUString
& sText
) throw (RuntimeException
, std::exception
)
600 OExternalLockGuard
aGuard( this );
602 bool bSuccess
= false;
605 bSuccess
= replaceText( 0, implGetText().getLength(), sText
);
607 catch( const IndexOutOfBoundsException
& )
609 OSL_FAIL( "VCLXAccessibleText::setText: caught an exception!" );
616 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */