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 <standard/vclxaccessiblemenuitem.hxx>
21 #include <toolkit/helper/convert.hxx>
22 #include <helper/characterattributeshelper.hxx>
23 #include <comphelper/accessiblecontexthelper.hxx>
24 #include <comphelper/accessiblekeybindinghelper.hxx>
25 #include <com/sun/star/awt/KeyModifier.hpp>
27 #include <com/sun/star/accessibility/AccessibleRole.hpp>
28 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
29 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
30 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
31 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
32 #include <comphelper/sequence.hxx>
33 #include <i18nlangtag/languagetag.hxx>
34 #include <vcl/event.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/window.hxx>
37 #include <vcl/menu.hxx>
38 #include <vcl/unohelp2.hxx>
39 #include <vcl/settings.hxx>
40 #include <strings.hxx>
42 using namespace ::com::sun::star::accessibility
;
43 using namespace ::com::sun::star::uno
;
44 using namespace ::com::sun::star::beans
;
45 using namespace ::com::sun::star::lang
;
46 using namespace ::com::sun::star
;
47 using namespace ::comphelper
;
52 VCLXAccessibleMenuItem::VCLXAccessibleMenuItem( Menu
* pParent
, sal_uInt16 nItemPos
, Menu
* pMenu
)
53 :ImplInheritanceHelper( pParent
, nItemPos
, pMenu
)
58 bool VCLXAccessibleMenuItem::IsFocused()
60 return IsHighlighted();
64 bool VCLXAccessibleMenuItem::IsSelected()
66 return IsHighlighted();
70 bool VCLXAccessibleMenuItem::IsChecked()
72 bool bChecked
= false;
76 sal_uInt16 nItemId
= m_pParent
->GetItemId( m_nItemPos
);
77 if ( m_pParent
->IsItemChecked( nItemId
) )
85 bool VCLXAccessibleMenuItem::IsHighlighted()
87 bool bHighlighted
= false;
89 if ( m_pParent
&& m_pParent
->IsHighlighted( m_nItemPos
) )
96 void VCLXAccessibleMenuItem::FillAccessibleStateSet( sal_Int64
& rStateSet
)
98 OAccessibleMenuItemComponent::FillAccessibleStateSet( rStateSet
);
100 rStateSet
|= AccessibleStateType::FOCUSABLE
;
103 rStateSet
|= AccessibleStateType::FOCUSED
;
105 rStateSet
|= AccessibleStateType::SELECTABLE
;
108 rStateSet
|= AccessibleStateType::SELECTED
;
111 rStateSet
|= AccessibleStateType::CHECKED
;
115 // OCommonAccessibleText
118 OUString
VCLXAccessibleMenuItem::implGetText()
124 Locale
VCLXAccessibleMenuItem::implGetLocale()
126 return Application::GetSettings().GetLanguageTag().getLocale();
130 void VCLXAccessibleMenuItem::implGetSelection( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
)
140 OUString
VCLXAccessibleMenuItem::getImplementationName()
142 return "com.sun.star.comp.toolkit.AccessibleMenuItem";
146 Sequence
< OUString
> VCLXAccessibleMenuItem::getSupportedServiceNames()
148 return { "com.sun.star.awt.AccessibleMenuItem" };
152 // XAccessibleContext
155 sal_Int16
VCLXAccessibleMenuItem::getAccessibleRole( )
157 OExternalLockGuard
aGuard( this );
158 // IA2 CWS. MT: We had the additional roles in UAA for ever, but never used them anywhere.
159 // Looks reasonable, but need to verify in Orca and VoiceOver.
160 sal_Int16 nRole
= AccessibleRole::MENU_ITEM
;
163 sal_uInt16 nItemId
= m_pParent
->GetItemId( m_nItemPos
);
164 MenuItemBits nItemBits
= m_pParent
->GetItemBits(nItemId
);
165 if( nItemBits
& MenuItemBits::RADIOCHECK
)
166 nRole
= AccessibleRole::RADIO_MENU_ITEM
;
167 else if( nItemBits
& MenuItemBits::CHECKABLE
)
168 nRole
= AccessibleRole::CHECK_MENU_ITEM
;
177 sal_Int32
VCLXAccessibleMenuItem::getCaretPosition()
183 sal_Bool
VCLXAccessibleMenuItem::setCaretPosition( sal_Int32 nIndex
)
186 OExternalLockGuard
aGuard( this );
188 if ( !implIsValidRange( nIndex
, nIndex
, m_sItemText
.getLength() ) )
189 throw IndexOutOfBoundsException();
195 sal_Unicode
VCLXAccessibleMenuItem::getCharacter( sal_Int32 nIndex
)
197 OExternalLockGuard
aGuard( this );
199 return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex
);
203 Sequence
< PropertyValue
> VCLXAccessibleMenuItem::getCharacterAttributes( sal_Int32 nIndex
, const Sequence
< OUString
>& aRequestedAttributes
)
205 OExternalLockGuard
aGuard( this );
207 if ( !implIsValidIndex( nIndex
, m_sItemText
.getLength() ) )
208 throw IndexOutOfBoundsException();
210 vcl::Font aFont
= Application::GetSettings().GetStyleSettings().GetMenuFont();
211 sal_Int32 nBackColor
= getBackground();
212 sal_Int32 nColor
= getForeground();
213 return CharacterAttributesHelper( aFont
, nBackColor
, nColor
)
214 .GetCharacterAttributes( aRequestedAttributes
);
218 awt::Rectangle
VCLXAccessibleMenuItem::getCharacterBounds( sal_Int32 nIndex
)
220 OExternalLockGuard
aGuard( this );
222 if ( !implIsValidIndex( nIndex
, m_sItemText
.getLength() ) )
223 throw IndexOutOfBoundsException();
225 awt::Rectangle
aBounds( 0, 0, 0, 0 );
228 sal_uInt16 nItemId
= m_pParent
->GetItemId( m_nItemPos
);
229 tools::Rectangle aItemRect
= m_pParent
->GetBoundingRectangle( m_nItemPos
);
230 tools::Rectangle aCharRect
= m_pParent
->GetCharacterBounds( nItemId
, nIndex
);
231 aCharRect
.Move( -aItemRect
.Left(), -aItemRect
.Top() );
232 aBounds
= AWTRectangle( aCharRect
);
239 sal_Int32
VCLXAccessibleMenuItem::getCharacterCount()
241 OExternalLockGuard
aGuard( this );
243 return m_sItemText
.getLength();
247 sal_Int32
VCLXAccessibleMenuItem::getIndexAtPoint( const awt::Point
& aPoint
)
249 OExternalLockGuard
aGuard( this );
251 sal_Int32 nIndex
= -1;
254 sal_uInt16 nItemId
= 0;
255 tools::Rectangle aItemRect
= m_pParent
->GetBoundingRectangle( m_nItemPos
);
256 Point
aPnt( VCLPoint( aPoint
) );
257 aPnt
+= aItemRect
.TopLeft();
258 sal_Int32 nI
= m_pParent
->GetIndexForPoint( aPnt
, nItemId
);
259 if ( nI
!= -1 && m_pParent
->GetItemId( m_nItemPos
) == nItemId
)
267 OUString
VCLXAccessibleMenuItem::getSelectedText()
269 OExternalLockGuard
aGuard( this );
275 sal_Int32
VCLXAccessibleMenuItem::getSelectionStart()
277 OExternalLockGuard
aGuard( this );
283 sal_Int32
VCLXAccessibleMenuItem::getSelectionEnd()
285 OExternalLockGuard
aGuard( this );
291 sal_Bool
VCLXAccessibleMenuItem::setSelection( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
293 OExternalLockGuard
aGuard( this );
295 if ( !implIsValidRange( nStartIndex
, nEndIndex
, m_sItemText
.getLength() ) )
296 throw IndexOutOfBoundsException();
302 OUString
VCLXAccessibleMenuItem::getText()
304 OExternalLockGuard
aGuard( this );
310 OUString
VCLXAccessibleMenuItem::getTextRange( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
312 OExternalLockGuard
aGuard( this );
314 return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex
, nEndIndex
);
318 css::accessibility::TextSegment
VCLXAccessibleMenuItem::getTextAtIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
320 OExternalLockGuard
aGuard( this );
322 return OCommonAccessibleText::getTextAtIndex( nIndex
, aTextType
);
326 css::accessibility::TextSegment
VCLXAccessibleMenuItem::getTextBeforeIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
328 OExternalLockGuard
aGuard( this );
330 return OCommonAccessibleText::getTextBeforeIndex( nIndex
, aTextType
);
334 css::accessibility::TextSegment
VCLXAccessibleMenuItem::getTextBehindIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
336 OExternalLockGuard
aGuard( this );
338 return OCommonAccessibleText::getTextBehindIndex( nIndex
, aTextType
);
342 sal_Bool
VCLXAccessibleMenuItem::copyText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
344 OExternalLockGuard
aGuard( this );
346 bool bReturn
= false;
350 vcl::Window
* pWindow
= m_pParent
->GetWindow();
353 Reference
< datatransfer::clipboard::XClipboard
> xClipboard
= pWindow
->GetClipboard();
354 if ( xClipboard
.is() )
356 OUString
sText( getTextRange( nStartIndex
, nEndIndex
) );
358 rtl::Reference
<vcl::unohelper::TextDataObject
> pDataObj
= new vcl::unohelper::TextDataObject( sText
);
360 SolarMutexReleaser aReleaser
;
361 xClipboard
->setContents( pDataObj
, nullptr );
362 Reference
< datatransfer::clipboard::XFlushableClipboard
> xFlushableClipboard( xClipboard
, uno::UNO_QUERY
);
363 if( xFlushableClipboard
.is() )
364 xFlushableClipboard
->flushClipboard();
374 sal_Bool
VCLXAccessibleMenuItem::scrollSubstringTo( sal_Int32
, sal_Int32
, AccessibleScrollType
)
383 sal_Int32
VCLXAccessibleMenuItem::getAccessibleActionCount( )
389 sal_Bool
VCLXAccessibleMenuItem::doAccessibleAction ( sal_Int32 nIndex
)
391 OExternalLockGuard
aGuard( this );
394 throw IndexOutOfBoundsException();
402 OUString
VCLXAccessibleMenuItem::getAccessibleActionDescription ( sal_Int32 nIndex
)
404 OExternalLockGuard
aGuard( this );
407 throw IndexOutOfBoundsException();
409 return RID_STR_ACC_ACTION_SELECT
;
413 Reference
< XAccessibleKeyBinding
> VCLXAccessibleMenuItem::getAccessibleActionKeyBinding( sal_Int32 nIndex
)
415 OExternalLockGuard
aGuard( this );
418 throw IndexOutOfBoundsException();
420 rtl::Reference
<OAccessibleKeyBindingHelper
> pKeyBindingHelper
= new OAccessibleKeyBindingHelper();
424 // create auto mnemonics
425 if (!(m_pParent
->GetMenuFlags() & MenuFlags::NoAutoMnemonics
))
426 m_pParent
->CreateAutoMnemonics();
429 KeyEvent aKeyEvent
= m_pParent
->GetActivationKey( m_pParent
->GetItemId( m_nItemPos
) );
430 vcl::KeyCode aKeyCode
= aKeyEvent
.GetKeyCode();
431 Sequence
< awt::KeyStroke
> aSeq1
435 static_cast< sal_Int16
>(aKeyCode
.GetCode()),
436 aKeyEvent
.GetCharCode(),
437 static_cast< sal_Int16
>( aKeyCode
.GetFunction())
440 Reference
< XAccessible
> xParent( getAccessibleParent() );
443 Reference
< XAccessibleContext
> xParentContext( xParent
->getAccessibleContext() );
444 if ( xParentContext
.is() && xParentContext
->getAccessibleRole() == AccessibleRole::MENU_BAR
)
445 aSeq1
.getArray()[0].Modifiers
|= awt::KeyModifier::MOD2
;
447 pKeyBindingHelper
->AddKeyBinding( aSeq1
);
449 // complete menu activation key sequence
450 Sequence
< awt::KeyStroke
> aSeq
;
453 Reference
< XAccessibleContext
> xParentContext( xParent
->getAccessibleContext() );
454 if ( xParentContext
.is() && xParentContext
->getAccessibleRole() == AccessibleRole::MENU
)
456 Reference
< XAccessibleAction
> xAction( xParentContext
, UNO_QUERY
);
457 if ( xAction
.is() && xAction
->getAccessibleActionCount() > 0 )
459 Reference
< XAccessibleKeyBinding
> xKeyB( xAction
->getAccessibleActionKeyBinding( 0 ) );
460 if ( xKeyB
.is() && xKeyB
->getAccessibleKeyBindingCount() > 1 )
461 aSeq
= xKeyB
->getAccessibleKeyBinding( 1 );
465 Sequence
< awt::KeyStroke
> aSeq2
= ::comphelper::concatSequences( aSeq
, aSeq1
);
466 pKeyBindingHelper
->AddKeyBinding( aSeq2
);
469 vcl::KeyCode aAccelKeyCode
= m_pParent
->GetAccelKey( m_pParent
->GetItemId( m_nItemPos
) );
470 if ( aAccelKeyCode
.GetCode() != 0 )
472 Sequence
< awt::KeyStroke
> aSeq3
476 static_cast< sal_Int16
>(aAccelKeyCode
.GetCode()),
477 aKeyEvent
.GetCharCode(),
478 static_cast< sal_Int16
>(aAccelKeyCode
.GetFunction())
481 if (aAccelKeyCode
.GetModifier() != 0)
483 auto pSeq3
= aSeq3
.getArray();
484 if ( aAccelKeyCode
.IsShift() )
485 pSeq3
[0].Modifiers
|= awt::KeyModifier::SHIFT
;
486 if ( aAccelKeyCode
.IsMod1() )
487 pSeq3
[0].Modifiers
|= awt::KeyModifier::MOD1
;
488 if ( aAccelKeyCode
.IsMod2() )
489 pSeq3
[0].Modifiers
|= awt::KeyModifier::MOD2
;
490 if ( aAccelKeyCode
.IsMod3() )
491 pSeq3
[0].Modifiers
|= awt::KeyModifier::MOD3
;
493 pKeyBindingHelper
->AddKeyBinding( aSeq3
);
497 return pKeyBindingHelper
;
504 Any
VCLXAccessibleMenuItem::getCurrentValue( )
506 OExternalLockGuard
aGuard( this );
510 aValue
<<= sal_Int32(1);
512 aValue
<<= sal_Int32(0);
518 sal_Bool
VCLXAccessibleMenuItem::setCurrentValue( const Any
& aNumber
)
520 OExternalLockGuard
aGuard( this );
522 bool bReturn
= false;
523 sal_Int32 nValue
= 0;
524 OSL_VERIFY( aNumber
>>= nValue
);
531 else if ( nValue
>= 1 )
541 Any
VCLXAccessibleMenuItem::getMaximumValue( )
544 aValue
<<= sal_Int32(1);
550 Any
VCLXAccessibleMenuItem::getMinimumValue( )
553 aValue
<<= sal_Int32(0);
558 Any
VCLXAccessibleMenuItem::getMinimumIncrement( )
561 aValue
<<= sal_Int32(1);
567 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */