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 <helper/characterattributeshelper.hxx>
22 #include <comphelper/accessiblecontexthelper.hxx>
23 #include <comphelper/accessiblekeybindinghelper.hxx>
24 #include <com/sun/star/awt/KeyModifier.hpp>
26 #include <com/sun/star/accessibility/AccessibleRole.hpp>
27 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
28 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
29 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
30 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
31 #include <comphelper/sequence.hxx>
32 #include <i18nlangtag/languagetag.hxx>
33 #include <toolkit/helper/vclunohelper.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();
69 bool VCLXAccessibleMenuItem::IsCheckable()
74 const sal_uInt16 nItemId
= m_pParent
->GetItemId(m_nItemPos
);
75 return m_pParent
->IsItemCheckable(nItemId
);
78 bool VCLXAccessibleMenuItem::IsChecked()
80 bool bChecked
= false;
84 sal_uInt16 nItemId
= m_pParent
->GetItemId( m_nItemPos
);
85 if ( m_pParent
->IsItemChecked( nItemId
) )
93 bool VCLXAccessibleMenuItem::IsHighlighted()
95 bool bHighlighted
= false;
97 if ( m_pParent
&& m_pParent
->IsHighlighted( m_nItemPos
) )
104 void VCLXAccessibleMenuItem::FillAccessibleStateSet( sal_Int64
& rStateSet
)
106 OAccessibleMenuItemComponent::FillAccessibleStateSet( rStateSet
);
108 rStateSet
|= AccessibleStateType::FOCUSABLE
;
111 rStateSet
|= AccessibleStateType::FOCUSED
;
113 rStateSet
|= AccessibleStateType::SELECTABLE
;
116 rStateSet
|= AccessibleStateType::SELECTED
;
119 rStateSet
|= AccessibleStateType::CHECKABLE
;
121 rStateSet
|= AccessibleStateType::CHECKED
;
125 // OCommonAccessibleText
128 OUString
VCLXAccessibleMenuItem::implGetText()
134 Locale
VCLXAccessibleMenuItem::implGetLocale()
136 return Application::GetSettings().GetLanguageTag().getLocale();
140 void VCLXAccessibleMenuItem::implGetSelection( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
)
150 OUString
VCLXAccessibleMenuItem::getImplementationName()
152 return u
"com.sun.star.comp.toolkit.AccessibleMenuItem"_ustr
;
156 Sequence
< OUString
> VCLXAccessibleMenuItem::getSupportedServiceNames()
158 return { u
"com.sun.star.awt.AccessibleMenuItem"_ustr
};
162 // XAccessibleContext
165 sal_Int16
VCLXAccessibleMenuItem::getAccessibleRole( )
167 OExternalLockGuard
aGuard( this );
168 // IA2 CWS. MT: We had the additional roles in UAA for ever, but never used them anywhere.
169 // Looks reasonable, but need to verify in Orca and VoiceOver.
170 sal_Int16 nRole
= AccessibleRole::MENU_ITEM
;
173 sal_uInt16 nItemId
= m_pParent
->GetItemId( m_nItemPos
);
174 MenuItemBits nItemBits
= m_pParent
->GetItemBits(nItemId
);
175 if( nItemBits
& MenuItemBits::RADIOCHECK
)
176 nRole
= AccessibleRole::RADIO_MENU_ITEM
;
177 else if( nItemBits
& MenuItemBits::CHECKABLE
)
178 nRole
= AccessibleRole::CHECK_MENU_ITEM
;
187 sal_Int32
VCLXAccessibleMenuItem::getCaretPosition()
193 sal_Bool
VCLXAccessibleMenuItem::setCaretPosition( sal_Int32 nIndex
)
196 OExternalLockGuard
aGuard( this );
198 if ( !implIsValidRange( nIndex
, nIndex
, m_sItemText
.getLength() ) )
199 throw IndexOutOfBoundsException();
205 sal_Unicode
VCLXAccessibleMenuItem::getCharacter( sal_Int32 nIndex
)
207 OExternalLockGuard
aGuard( this );
209 return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex
);
213 Sequence
< PropertyValue
> VCLXAccessibleMenuItem::getCharacterAttributes( sal_Int32 nIndex
, const Sequence
< OUString
>& aRequestedAttributes
)
215 OExternalLockGuard
aGuard( this );
217 if ( !implIsValidIndex( nIndex
, m_sItemText
.getLength() ) )
218 throw IndexOutOfBoundsException();
220 vcl::Font aFont
= Application::GetSettings().GetStyleSettings().GetMenuFont();
221 sal_Int32 nBackColor
= getBackground();
222 sal_Int32 nColor
= getForeground();
223 return CharacterAttributesHelper( aFont
, nBackColor
, nColor
)
224 .GetCharacterAttributes( aRequestedAttributes
);
228 awt::Rectangle
VCLXAccessibleMenuItem::getCharacterBounds( sal_Int32 nIndex
)
230 OExternalLockGuard
aGuard( this );
232 if ( !implIsValidIndex( nIndex
, m_sItemText
.getLength() ) )
233 throw IndexOutOfBoundsException();
235 awt::Rectangle
aBounds( 0, 0, 0, 0 );
238 sal_uInt16 nItemId
= m_pParent
->GetItemId( m_nItemPos
);
239 tools::Rectangle aItemRect
= m_pParent
->GetBoundingRectangle( m_nItemPos
);
240 tools::Rectangle aCharRect
= m_pParent
->GetCharacterBounds( nItemId
, nIndex
);
241 aCharRect
.Move( -aItemRect
.Left(), -aItemRect
.Top() );
242 aBounds
= VCLUnoHelper::ConvertToAWTRect(aCharRect
);
249 sal_Int32
VCLXAccessibleMenuItem::getCharacterCount()
251 OExternalLockGuard
aGuard( this );
253 return m_sItemText
.getLength();
257 sal_Int32
VCLXAccessibleMenuItem::getIndexAtPoint( const awt::Point
& aPoint
)
259 OExternalLockGuard
aGuard( this );
261 sal_Int32 nIndex
= -1;
264 sal_uInt16 nItemId
= 0;
265 tools::Rectangle aItemRect
= m_pParent
->GetBoundingRectangle( m_nItemPos
);
266 Point
aPnt(VCLUnoHelper::ConvertToVCLPoint(aPoint
));
267 aPnt
+= aItemRect
.TopLeft();
268 sal_Int32 nI
= m_pParent
->GetIndexForPoint( aPnt
, nItemId
);
269 if ( nI
!= -1 && m_pParent
->GetItemId( m_nItemPos
) == nItemId
)
277 OUString
VCLXAccessibleMenuItem::getSelectedText()
279 OExternalLockGuard
aGuard( this );
285 sal_Int32
VCLXAccessibleMenuItem::getSelectionStart()
287 OExternalLockGuard
aGuard( this );
293 sal_Int32
VCLXAccessibleMenuItem::getSelectionEnd()
295 OExternalLockGuard
aGuard( this );
301 sal_Bool
VCLXAccessibleMenuItem::setSelection( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
303 OExternalLockGuard
aGuard( this );
305 if ( !implIsValidRange( nStartIndex
, nEndIndex
, m_sItemText
.getLength() ) )
306 throw IndexOutOfBoundsException();
312 OUString
VCLXAccessibleMenuItem::getText()
314 OExternalLockGuard
aGuard( this );
320 OUString
VCLXAccessibleMenuItem::getTextRange( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
322 OExternalLockGuard
aGuard( this );
324 return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex
, nEndIndex
);
328 css::accessibility::TextSegment
VCLXAccessibleMenuItem::getTextAtIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
330 OExternalLockGuard
aGuard( this );
332 return OCommonAccessibleText::getTextAtIndex( nIndex
, aTextType
);
336 css::accessibility::TextSegment
VCLXAccessibleMenuItem::getTextBeforeIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
338 OExternalLockGuard
aGuard( this );
340 return OCommonAccessibleText::getTextBeforeIndex( nIndex
, aTextType
);
344 css::accessibility::TextSegment
VCLXAccessibleMenuItem::getTextBehindIndex( sal_Int32 nIndex
, sal_Int16 aTextType
)
346 OExternalLockGuard
aGuard( this );
348 return OCommonAccessibleText::getTextBehindIndex( nIndex
, aTextType
);
352 sal_Bool
VCLXAccessibleMenuItem::copyText( sal_Int32 nStartIndex
, sal_Int32 nEndIndex
)
354 OExternalLockGuard
aGuard( this );
356 bool bReturn
= false;
360 vcl::Window
* pWindow
= m_pParent
->GetWindow();
363 Reference
< datatransfer::clipboard::XClipboard
> xClipboard
= pWindow
->GetClipboard();
364 if ( xClipboard
.is() )
366 OUString
sText( getTextRange( nStartIndex
, nEndIndex
) );
368 rtl::Reference
<vcl::unohelper::TextDataObject
> pDataObj
= new vcl::unohelper::TextDataObject( sText
);
370 SolarMutexReleaser aReleaser
;
371 xClipboard
->setContents( pDataObj
, nullptr );
372 Reference
< datatransfer::clipboard::XFlushableClipboard
> xFlushableClipboard( xClipboard
, uno::UNO_QUERY
);
373 if( xFlushableClipboard
.is() )
374 xFlushableClipboard
->flushClipboard();
384 sal_Bool
VCLXAccessibleMenuItem::scrollSubstringTo( sal_Int32
, sal_Int32
, AccessibleScrollType
)
393 sal_Int32
VCLXAccessibleMenuItem::getAccessibleActionCount( )
399 sal_Bool
VCLXAccessibleMenuItem::doAccessibleAction ( sal_Int32 nIndex
)
401 OExternalLockGuard
aGuard( this );
404 throw IndexOutOfBoundsException();
412 OUString
VCLXAccessibleMenuItem::getAccessibleActionDescription ( sal_Int32 nIndex
)
414 OExternalLockGuard
aGuard( this );
417 throw IndexOutOfBoundsException();
419 return RID_STR_ACC_ACTION_SELECT
;
423 Reference
< XAccessibleKeyBinding
> VCLXAccessibleMenuItem::getAccessibleActionKeyBinding( sal_Int32 nIndex
)
425 OExternalLockGuard
aGuard( this );
428 throw IndexOutOfBoundsException();
430 rtl::Reference
<OAccessibleKeyBindingHelper
> pKeyBindingHelper
= new OAccessibleKeyBindingHelper();
434 // create auto mnemonics
435 if (!(m_pParent
->GetMenuFlags() & MenuFlags::NoAutoMnemonics
))
436 m_pParent
->CreateAutoMnemonics();
439 KeyEvent aKeyEvent
= m_pParent
->GetActivationKey( m_pParent
->GetItemId( m_nItemPos
) );
440 vcl::KeyCode aKeyCode
= aKeyEvent
.GetKeyCode();
441 Sequence
< awt::KeyStroke
> aSeq1
445 static_cast< sal_Int16
>(aKeyCode
.GetCode()),
446 aKeyEvent
.GetCharCode(),
447 static_cast< sal_Int16
>( aKeyCode
.GetFunction())
450 Reference
< XAccessible
> xParent( getAccessibleParent() );
453 Reference
< XAccessibleContext
> xParentContext( xParent
->getAccessibleContext() );
454 if ( xParentContext
.is() && xParentContext
->getAccessibleRole() == AccessibleRole::MENU_BAR
)
455 aSeq1
.getArray()[0].Modifiers
|= awt::KeyModifier::MOD2
;
457 pKeyBindingHelper
->AddKeyBinding( aSeq1
);
459 // complete menu activation key sequence
460 Sequence
< awt::KeyStroke
> aSeq
;
463 Reference
< XAccessibleContext
> xParentContext( xParent
->getAccessibleContext() );
464 if ( xParentContext
.is() && xParentContext
->getAccessibleRole() == AccessibleRole::MENU
)
466 Reference
< XAccessibleAction
> xAction( xParentContext
, UNO_QUERY
);
467 if ( xAction
.is() && xAction
->getAccessibleActionCount() > 0 )
469 Reference
< XAccessibleKeyBinding
> xKeyB( xAction
->getAccessibleActionKeyBinding( 0 ) );
470 if ( xKeyB
.is() && xKeyB
->getAccessibleKeyBindingCount() > 1 )
471 aSeq
= xKeyB
->getAccessibleKeyBinding( 1 );
475 Sequence
< awt::KeyStroke
> aSeq2
= ::comphelper::concatSequences( aSeq
, aSeq1
);
476 pKeyBindingHelper
->AddKeyBinding( aSeq2
);
479 vcl::KeyCode aAccelKeyCode
= m_pParent
->GetAccelKey( m_pParent
->GetItemId( m_nItemPos
) );
480 if ( aAccelKeyCode
.GetCode() != 0 )
482 Sequence
< awt::KeyStroke
> aSeq3
486 static_cast< sal_Int16
>(aAccelKeyCode
.GetCode()),
487 aKeyEvent
.GetCharCode(),
488 static_cast< sal_Int16
>(aAccelKeyCode
.GetFunction())
491 if (aAccelKeyCode
.GetModifier() != 0)
493 auto pSeq3
= aSeq3
.getArray();
494 if ( aAccelKeyCode
.IsShift() )
495 pSeq3
[0].Modifiers
|= awt::KeyModifier::SHIFT
;
496 if ( aAccelKeyCode
.IsMod1() )
497 pSeq3
[0].Modifiers
|= awt::KeyModifier::MOD1
;
498 if ( aAccelKeyCode
.IsMod2() )
499 pSeq3
[0].Modifiers
|= awt::KeyModifier::MOD2
;
500 if ( aAccelKeyCode
.IsMod3() )
501 pSeq3
[0].Modifiers
|= awt::KeyModifier::MOD3
;
503 pKeyBindingHelper
->AddKeyBinding( aSeq3
);
507 return pKeyBindingHelper
;
514 Any
VCLXAccessibleMenuItem::getCurrentValue( )
516 OExternalLockGuard
aGuard( this );
520 aValue
<<= sal_Int32(1);
522 aValue
<<= sal_Int32(0);
528 sal_Bool
VCLXAccessibleMenuItem::setCurrentValue( const Any
& aNumber
)
530 OExternalLockGuard
aGuard( this );
532 bool bReturn
= false;
533 sal_Int32 nValue
= 0;
534 OSL_VERIFY( aNumber
>>= nValue
);
541 else if ( nValue
>= 1 )
551 Any
VCLXAccessibleMenuItem::getMaximumValue( )
554 aValue
<<= sal_Int32(1);
560 Any
VCLXAccessibleMenuItem::getMinimumValue( )
563 aValue
<<= sal_Int32(0);
568 Any
VCLXAccessibleMenuItem::getMinimumIncrement( )
571 aValue
<<= sal_Int32(1);
577 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */