LibreOffice Module accessibility (master) 1
vclxaccessiblemenuitem.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
25#include <com/sun/star/awt/KeyModifier.hpp>
26
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>
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>
41
42using namespace ::com::sun::star::accessibility;
43using namespace ::com::sun::star::uno;
44using namespace ::com::sun::star::beans;
45using namespace ::com::sun::star::lang;
46using namespace ::com::sun::star;
47using namespace ::comphelper;
48
49
50
51
52VCLXAccessibleMenuItem::VCLXAccessibleMenuItem( Menu* pParent, sal_uInt16 nItemPos, Menu* pMenu )
53 :ImplInheritanceHelper( pParent, nItemPos, pMenu )
54{
55}
56
57
59{
60 return IsHighlighted();
61}
62
63
65{
66 return IsHighlighted();
67}
68
69
71{
72 bool bChecked = false;
73
74 if ( m_pParent )
75 {
76 sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos );
77 if ( m_pParent->IsItemChecked( nItemId ) )
78 bChecked = true;
79 }
80
81 return bChecked;
82}
83
84
86{
87 bool bHighlighted = false;
88
89 if ( m_pParent && m_pParent->IsHighlighted( m_nItemPos ) )
90 bHighlighted = true;
91
92 return bHighlighted;
93}
94
95
97{
99
100 rStateSet |= AccessibleStateType::FOCUSABLE;
101
102 if ( IsFocused() )
103 rStateSet |= AccessibleStateType::FOCUSED;
104
105 rStateSet |= AccessibleStateType::SELECTABLE;
106
107 if ( IsSelected() )
108 rStateSet |= AccessibleStateType::SELECTED;
109
110 if ( IsChecked() )
111 rStateSet |= AccessibleStateType::CHECKED;
112}
113
114
115// OCommonAccessibleText
116
117
119{
120 return m_sItemText;
121}
122
123
125{
127}
128
129
130void VCLXAccessibleMenuItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
131{
132 nStartIndex = 0;
133 nEndIndex = 0;
134}
135
136
137// XServiceInfo
138
139
141{
142 return "com.sun.star.comp.toolkit.AccessibleMenuItem";
143}
144
145
147{
148 return { "com.sun.star.awt.AccessibleMenuItem" };
149}
150
151
152// XAccessibleContext
153
154
156{
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;
161 if ( m_pParent )
162 {
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;
169 }
170 return nRole;
171}
172
173
174// XAccessibleText
175
176
178{
179 return -1;
180}
181
182
184{
185
186 OExternalLockGuard aGuard( this );
187
188 if ( !implIsValidRange( nIndex, nIndex, m_sItemText.getLength() ) )
189 throw IndexOutOfBoundsException();
190
191 return false;
192}
193
194
196{
197 OExternalLockGuard aGuard( this );
198
199 return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex );
200}
201
202
203Sequence< PropertyValue > VCLXAccessibleMenuItem::getCharacterAttributes( sal_Int32 nIndex, const Sequence< OUString >& aRequestedAttributes )
204{
205 OExternalLockGuard aGuard( this );
206
207 if ( !implIsValidIndex( nIndex, m_sItemText.getLength() ) )
208 throw IndexOutOfBoundsException();
209
211 sal_Int32 nBackColor = getBackground();
212 sal_Int32 nColor = getForeground();
213 return CharacterAttributesHelper( aFont, nBackColor, nColor )
214 .GetCharacterAttributes( aRequestedAttributes );
215}
216
217
218awt::Rectangle VCLXAccessibleMenuItem::getCharacterBounds( sal_Int32 nIndex )
219{
220 OExternalLockGuard aGuard( this );
221
222 if ( !implIsValidIndex( nIndex, m_sItemText.getLength() ) )
223 throw IndexOutOfBoundsException();
224
225 awt::Rectangle aBounds( 0, 0, 0, 0 );
226 if ( m_pParent )
227 {
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 );
233 }
234
235 return aBounds;
236}
237
238
240{
241 OExternalLockGuard aGuard( this );
242
243 return m_sItemText.getLength();
244}
245
246
247sal_Int32 VCLXAccessibleMenuItem::getIndexAtPoint( const awt::Point& aPoint )
248{
249 OExternalLockGuard aGuard( this );
250
251 sal_Int32 nIndex = -1;
252 if ( m_pParent )
253 {
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 )
260 nIndex = nI;
261 }
262
263 return nIndex;
264}
265
266
268{
269 OExternalLockGuard aGuard( this );
270
271 return OUString();
272}
273
274
276{
277 OExternalLockGuard aGuard( this );
278
279 return 0;
280}
281
282
284{
285 OExternalLockGuard aGuard( this );
286
287 return 0;
288}
289
290
291sal_Bool VCLXAccessibleMenuItem::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
292{
293 OExternalLockGuard aGuard( this );
294
295 if ( !implIsValidRange( nStartIndex, nEndIndex, m_sItemText.getLength() ) )
296 throw IndexOutOfBoundsException();
297
298 return false;
299}
300
301
303{
304 OExternalLockGuard aGuard( this );
305
306 return m_sItemText;
307}
308
309
310OUString VCLXAccessibleMenuItem::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
311{
312 OExternalLockGuard aGuard( this );
313
314 return OCommonAccessibleText::implGetTextRange( implGetText(), nStartIndex, nEndIndex );
315}
316
317
318css::accessibility::TextSegment VCLXAccessibleMenuItem::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
319{
320 OExternalLockGuard aGuard( this );
321
322 return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
323}
324
325
326css::accessibility::TextSegment VCLXAccessibleMenuItem::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
327{
328 OExternalLockGuard aGuard( this );
329
330 return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
331}
332
333
334css::accessibility::TextSegment VCLXAccessibleMenuItem::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
335{
336 OExternalLockGuard aGuard( this );
337
338 return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
339}
340
341
342sal_Bool VCLXAccessibleMenuItem::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
343{
344 OExternalLockGuard aGuard( this );
345
346 bool bReturn = false;
347
348 if ( m_pParent )
349 {
350 vcl::Window* pWindow = m_pParent->GetWindow();
351 if ( pWindow )
352 {
353 Reference< datatransfer::clipboard::XClipboard > xClipboard = pWindow->GetClipboard();
354 if ( xClipboard.is() )
355 {
356 OUString sText( getTextRange( nStartIndex, nEndIndex ) );
357
359
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();
365
366 bReturn = true;
367 }
368 }
369 }
370
371 return bReturn;
372}
373
374sal_Bool VCLXAccessibleMenuItem::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
375{
376 return false;
377}
378
379
380// XAccessibleAction
381
382
384{
385 return 1;
386}
387
388
390{
391 OExternalLockGuard aGuard( this );
392
393 if ( nIndex != 0 )
394 throw IndexOutOfBoundsException();
395
396 Click();
397
398 return true;
399}
400
401
403{
404 OExternalLockGuard aGuard( this );
405
406 if ( nIndex != 0 )
407 throw IndexOutOfBoundsException();
408
410}
411
412
413Reference< XAccessibleKeyBinding > VCLXAccessibleMenuItem::getAccessibleActionKeyBinding( sal_Int32 nIndex )
414{
415 OExternalLockGuard aGuard( this );
416
417 if ( nIndex != 0 )
418 throw IndexOutOfBoundsException();
419
420 rtl::Reference<OAccessibleKeyBindingHelper> pKeyBindingHelper = new OAccessibleKeyBindingHelper();
421
422 if ( m_pParent )
423 {
424 // create auto mnemonics
425 if (!(m_pParent->GetMenuFlags() & MenuFlags::NoAutoMnemonics))
426 m_pParent->CreateAutoMnemonics();
427
428 // activation key
429 KeyEvent aKeyEvent = m_pParent->GetActivationKey( m_pParent->GetItemId( m_nItemPos ) );
430 vcl::KeyCode aKeyCode = aKeyEvent.GetKeyCode();
431 Sequence< awt::KeyStroke > aSeq1
432 {
433 {
434 0, // Modifiers
435 static_cast< sal_Int16 >(aKeyCode.GetCode()),
436 aKeyEvent.GetCharCode(),
437 static_cast< sal_Int16 >( aKeyCode.GetFunction())
438 }
439 };
440 Reference< XAccessible > xParent( getAccessibleParent() );
441 if ( xParent.is() )
442 {
443 Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
444 if ( xParentContext.is() && xParentContext->getAccessibleRole() == AccessibleRole::MENU_BAR )
445 aSeq1.getArray()[0].Modifiers |= awt::KeyModifier::MOD2;
446 }
447 pKeyBindingHelper->AddKeyBinding( aSeq1 );
448
449 // complete menu activation key sequence
450 Sequence< awt::KeyStroke > aSeq;
451 if ( xParent.is() )
452 {
453 Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
454 if ( xParentContext.is() && xParentContext->getAccessibleRole() == AccessibleRole::MENU )
455 {
456 Reference< XAccessibleAction > xAction( xParentContext, UNO_QUERY );
457 if ( xAction.is() && xAction->getAccessibleActionCount() > 0 )
458 {
459 Reference< XAccessibleKeyBinding > xKeyB( xAction->getAccessibleActionKeyBinding( 0 ) );
460 if ( xKeyB.is() && xKeyB->getAccessibleKeyBindingCount() > 1 )
461 aSeq = xKeyB->getAccessibleKeyBinding( 1 );
462 }
463 }
464 }
465 Sequence< awt::KeyStroke > aSeq2 = ::comphelper::concatSequences( aSeq, aSeq1 );
466 pKeyBindingHelper->AddKeyBinding( aSeq2 );
467
468 // accelerator key
469 vcl::KeyCode aAccelKeyCode = m_pParent->GetAccelKey( m_pParent->GetItemId( m_nItemPos ) );
470 if ( aAccelKeyCode.GetCode() != 0 )
471 {
472 Sequence< awt::KeyStroke > aSeq3
473 {
474 {
475 0, // Modifiers
476 static_cast< sal_Int16 >(aAccelKeyCode.GetCode()),
477 aKeyEvent.GetCharCode(),
478 static_cast< sal_Int16 >(aAccelKeyCode.GetFunction())
479 }
480 };
481 if (aAccelKeyCode.GetModifier() != 0)
482 {
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;
492 }
493 pKeyBindingHelper->AddKeyBinding( aSeq3 );
494 }
495 }
496
497 return pKeyBindingHelper;
498}
499
500
501// XAccessibleValue
502
503
505{
506 OExternalLockGuard aGuard( this );
507
508 Any aValue;
509 if ( IsSelected() )
510 aValue <<= sal_Int32(1);
511 else
512 aValue <<= sal_Int32(0);
513
514 return aValue;
515}
516
517
519{
520 OExternalLockGuard aGuard( this );
521
522 bool bReturn = false;
523 sal_Int32 nValue = 0;
524 OSL_VERIFY( aNumber >>= nValue );
525
526 if ( nValue <= 0 )
527 {
528 DeSelect();
529 bReturn = true;
530 }
531 else if ( nValue >= 1 )
532 {
533 Select();
534 bReturn = true;
535 }
536
537 return bReturn;
538}
539
540
542{
543 Any aValue;
544 aValue <<= sal_Int32(1);
545
546 return aValue;
547}
548
549
551{
552 Any aValue;
553 aValue <<= sal_Int32(0);
554
555 return aValue;
556}
557
559{
560 Any aValue;
561 aValue <<= sal_Int32(1);
562
563 return aValue;
564}
565
566
567/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const LanguageTag & GetLanguageTag() const
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
std::vector< css::beans::PropertyValue > GetCharacterAttributes()
sal_Unicode GetCharCode() const
const vcl::KeyCode & GetKeyCode() const
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
virtual void FillAccessibleStateSet(sal_Int64 &rStateSet) override
const vcl::Font & GetMenuFont() const
virtual OUString SAL_CALL getAccessibleActionDescription(sal_Int32 nIndex) override
virtual css::uno::Any SAL_CALL getMinimumValue() override
virtual sal_Bool SAL_CALL doAccessibleAction(sal_Int32 nIndex) override
virtual css::uno::Any SAL_CALL getMinimumIncrement() override
virtual css::uno::Reference< css::accessibility::XAccessibleKeyBinding > SAL_CALL getAccessibleActionKeyBinding(sal_Int32 nIndex) override
virtual sal_Bool SAL_CALL setCurrentValue(const css::uno::Any &aNumber) override
virtual sal_Int32 SAL_CALL getCaretPosition() override
virtual OUString implGetText() final override
virtual sal_Int32 SAL_CALL getSelectionStart() override final
virtual OUString SAL_CALL getSelectedText() override final
virtual bool IsHighlighted() override
virtual sal_Int32 SAL_CALL getAccessibleActionCount() final override
virtual sal_Int32 SAL_CALL getCharacterCount() final override
virtual sal_Bool SAL_CALL setSelection(sal_Int32 nStartIndex, sal_Int32 nEndIndex) override
VCLXAccessibleMenuItem(Menu *pParent, sal_uInt16 nItemPos, Menu *pMenu=nullptr)
virtual css::uno::Any SAL_CALL getCurrentValue() override
virtual sal_Int32 SAL_CALL getSelectionEnd() override final
virtual css::accessibility::TextSegment SAL_CALL getTextBeforeIndex(sal_Int32 nIndex, sal_Int16 aTextType) override
virtual css::lang::Locale implGetLocale() override
virtual void FillAccessibleStateSet(sal_Int64 &rStateSet) override
virtual sal_Unicode SAL_CALL getCharacter(sal_Int32 nIndex) final override
virtual css::accessibility::TextSegment SAL_CALL getTextAtIndex(sal_Int32 nIndex, sal_Int16 aTextType) override
virtual bool IsSelected() override
virtual css::accessibility::TextSegment SAL_CALL getTextBehindIndex(sal_Int32 nIndex, sal_Int16 aTextType) override
virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getCharacterAttributes(sal_Int32 nIndex, const css::uno::Sequence< OUString > &aRequestedAttributes) override
virtual sal_Bool SAL_CALL scrollSubstringTo(sal_Int32 nStartIndex, sal_Int32 nEndIndex, css::accessibility::AccessibleScrollType aScrollType) override
virtual sal_Int32 SAL_CALL getIndexAtPoint(const css::awt::Point &aPoint) override
virtual sal_Int16 SAL_CALL getAccessibleRole() override
virtual OUString SAL_CALL getImplementationName() override
virtual void implGetSelection(sal_Int32 &nStartIndex, sal_Int32 &nEndIndex) override final
virtual OUString SAL_CALL getTextRange(sal_Int32 nStartIndex, sal_Int32 nEndIndex) override
virtual css::uno::Any SAL_CALL getMaximumValue() override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual bool IsChecked() override
virtual bool IsFocused() override
virtual OUString SAL_CALL getText() final override
virtual sal_Bool SAL_CALL copyText(sal_Int32 nStartIndex, sal_Int32 nEndIndex) override
virtual sal_Bool SAL_CALL setCaretPosition(sal_Int32 nIndex) override
virtual css::awt::Rectangle SAL_CALL getCharacterBounds(sal_Int32 nIndex) override
static bool implIsValidIndex(sal_Int32 nIndex, sal_Int32 nLength)
static bool implIsValidRange(sal_Int32 nStartIndex, sal_Int32 nEndIndex, sal_Int32 nLength)
constexpr tools::Long Top() const
constexpr Point TopLeft() const
void Move(tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta)
constexpr tools::Long Left() const
bool IsMod1() const
sal_uInt16 GetCode() const
sal_uInt16 GetModifier() const
KeyFuncType GetFunction() const
bool IsShift() const
bool IsMod2() const
bool IsMod3() const
css::uno::Reference< css::datatransfer::clipboard::XClipboard > GetClipboard()
css::awt::Rectangle AWTRectangle(const ::tools::Rectangle &rVCLRect)
inline ::Point VCLPoint(const css::awt::Point &rAWTPoint)
sal_Int16 nValue
sal_Int32 nIndex
Sequence< sal_Int8 > aSeq
constexpr OUStringLiteral RID_STR_ACC_ACTION_SELECT
Definition: strings.hxx:16
unsigned char sal_Bool
sal_uInt16 sal_Unicode
MenuItemBits