1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_accessibility.hxx" 30 #include <accessibility/standard/vclxaccessiblemenuitem.hxx> 31 #include <accessibility/helper/accresmgr.hxx> 32 #include <accessibility/helper/accessiblestrings.hrc> 33 #include <toolkit/helper/convert.hxx> 34 #include <accessibility/helper/characterattributeshelper.hxx> 35 #include <comphelper/accessiblekeybindinghelper.hxx> 36 #include <com/sun/star/awt/KeyModifier.hpp> 37 38 #include <com/sun/star/accessibility/AccessibleRole.hpp> 39 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 40 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> 41 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp> 42 #include <unotools/accessiblestatesethelper.hxx> 43 #include <comphelper/sequence.hxx> 44 #include <vcl/svapp.hxx> 45 #include <vcl/window.hxx> 46 #include <vcl/menu.hxx> 47 #include <vcl/unohelp2.hxx> 48 49 #include <memory> 50 51 52 using namespace ::com::sun::star::accessibility; 53 using namespace ::com::sun::star::uno; 54 using namespace ::com::sun::star::beans; 55 using namespace ::com::sun::star::lang; 56 using namespace ::com::sun::star; 57 using namespace ::comphelper; 58 59 60 // ----------------------------------------------------------------------------- 61 // class VCLXAccessibleMenuItem 62 // ----------------------------------------------------------------------------- 63 64 VCLXAccessibleMenuItem::VCLXAccessibleMenuItem( Menu* pParent, sal_uInt16 nItemPos, Menu* pMenu ) 65 :OAccessibleMenuItemComponent( pParent, nItemPos, pMenu ) 66 { 67 } 68 69 // ----------------------------------------------------------------------------- 70 71 VCLXAccessibleMenuItem::~VCLXAccessibleMenuItem() 72 { 73 } 74 75 // ----------------------------------------------------------------------------- 76 77 sal_Bool VCLXAccessibleMenuItem::IsFocused() 78 { 79 return IsHighlighted(); 80 } 81 82 // ----------------------------------------------------------------------------- 83 84 sal_Bool VCLXAccessibleMenuItem::IsSelected() 85 { 86 return IsHighlighted(); 87 } 88 89 // ----------------------------------------------------------------------------- 90 91 sal_Bool VCLXAccessibleMenuItem::IsChecked() 92 { 93 sal_Bool bChecked = sal_False; 94 95 if ( m_pParent ) 96 { 97 sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos ); 98 if ( m_pParent->IsItemChecked( nItemId ) ) 99 bChecked = sal_True; 100 } 101 102 return bChecked; 103 } 104 105 // ----------------------------------------------------------------------------- 106 107 sal_Bool VCLXAccessibleMenuItem::IsHighlighted() 108 { 109 sal_Bool bHighlighted = sal_False; 110 111 if ( m_pParent && m_pParent->IsHighlighted( m_nItemPos ) ) 112 bHighlighted = sal_True; 113 114 return bHighlighted; 115 } 116 117 // ----------------------------------------------------------------------------- 118 119 void VCLXAccessibleMenuItem::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet ) 120 { 121 OAccessibleMenuItemComponent::FillAccessibleStateSet( rStateSet ); 122 123 rStateSet.AddState( AccessibleStateType::FOCUSABLE ); 124 125 if ( IsFocused() ) 126 rStateSet.AddState( AccessibleStateType::FOCUSED ); 127 128 rStateSet.AddState( AccessibleStateType::SELECTABLE ); 129 130 if ( IsSelected() ) 131 rStateSet.AddState( AccessibleStateType::SELECTED ); 132 133 if ( IsChecked() ) 134 rStateSet.AddState( AccessibleStateType::CHECKED ); 135 } 136 137 // ----------------------------------------------------------------------------- 138 // OCommonAccessibleText 139 // ----------------------------------------------------------------------------- 140 141 ::rtl::OUString VCLXAccessibleMenuItem::implGetText() 142 { 143 return m_sItemText; 144 } 145 146 // ----------------------------------------------------------------------------- 147 148 Locale VCLXAccessibleMenuItem::implGetLocale() 149 { 150 return Application::GetSettings().GetLocale(); 151 } 152 153 // ----------------------------------------------------------------------------- 154 155 void VCLXAccessibleMenuItem::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex ) 156 { 157 nStartIndex = 0; 158 nEndIndex = 0; 159 } 160 161 // ----------------------------------------------------------------------------- 162 // XInterface 163 // ----------------------------------------------------------------------------- 164 165 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleMenuItem, OAccessibleMenuItemComponent, VCLXAccessibleMenuItem_BASE ) 166 167 // ----------------------------------------------------------------------------- 168 // XTypeProvider 169 // ----------------------------------------------------------------------------- 170 171 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleMenuItem, OAccessibleMenuItemComponent, VCLXAccessibleMenuItem_BASE ) 172 173 // ----------------------------------------------------------------------------- 174 // XServiceInfo 175 // ----------------------------------------------------------------------------- 176 177 ::rtl::OUString VCLXAccessibleMenuItem::getImplementationName() throw (RuntimeException) 178 { 179 return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleMenuItem" ); 180 } 181 182 // ----------------------------------------------------------------------------- 183 184 Sequence< ::rtl::OUString > VCLXAccessibleMenuItem::getSupportedServiceNames() throw (RuntimeException) 185 { 186 Sequence< ::rtl::OUString > aNames(1); 187 aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleMenuItem" ); 188 return aNames; 189 } 190 191 // ----------------------------------------------------------------------------- 192 // XAccessibleContext 193 // ----------------------------------------------------------------------------- 194 195 sal_Int16 VCLXAccessibleMenuItem::getAccessibleRole( ) throw (RuntimeException) 196 { 197 OExternalLockGuard aGuard( this ); 198 199 return AccessibleRole::MENU_ITEM; 200 } 201 202 // ----------------------------------------------------------------------------- 203 // XAccessibleText 204 // ----------------------------------------------------------------------------- 205 206 sal_Int32 VCLXAccessibleMenuItem::getCaretPosition() throw (RuntimeException) 207 { 208 OExternalLockGuard aGuard( this ); 209 210 return -1; 211 } 212 213 // ----------------------------------------------------------------------------- 214 215 sal_Bool VCLXAccessibleMenuItem::setCaretPosition( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) 216 { 217 218 OExternalLockGuard aGuard( this ); 219 220 if ( !implIsValidRange( nIndex, nIndex, implGetText().getLength() ) ) 221 throw IndexOutOfBoundsException(); 222 223 return sal_False; 224 } 225 226 // ----------------------------------------------------------------------------- 227 228 sal_Unicode VCLXAccessibleMenuItem::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) 229 { 230 OExternalLockGuard aGuard( this ); 231 232 return OCommonAccessibleText::getCharacter( nIndex ); 233 } 234 235 // ----------------------------------------------------------------------------- 236 237 Sequence< PropertyValue > VCLXAccessibleMenuItem::getCharacterAttributes( sal_Int32 nIndex, const Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (IndexOutOfBoundsException, RuntimeException) 238 { 239 OExternalLockGuard aGuard( this ); 240 241 Sequence< PropertyValue > aValues; 242 ::rtl::OUString sText( implGetText() ); 243 244 if ( !implIsValidIndex( nIndex, sText.getLength() ) ) 245 throw IndexOutOfBoundsException(); 246 247 Font aFont = Application::GetSettings().GetStyleSettings().GetMenuFont(); 248 sal_Int32 nBackColor = getBackground(); 249 sal_Int32 nColor = getForeground(); 250 ::std::auto_ptr< CharacterAttributesHelper > pHelper( new CharacterAttributesHelper( aFont, nBackColor, nColor ) ); 251 aValues = pHelper->GetCharacterAttributes( aRequestedAttributes ); 252 253 return aValues; 254 } 255 256 // ----------------------------------------------------------------------------- 257 258 awt::Rectangle VCLXAccessibleMenuItem::getCharacterBounds( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) 259 { 260 OExternalLockGuard aGuard( this ); 261 262 if ( !implIsValidIndex( nIndex, implGetText().getLength() ) ) 263 throw IndexOutOfBoundsException(); 264 265 awt::Rectangle aBounds( 0, 0, 0, 0 ); 266 if ( m_pParent ) 267 { 268 sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos ); 269 Rectangle aItemRect = m_pParent->GetBoundingRectangle( m_nItemPos ); 270 Rectangle aCharRect = m_pParent->GetCharacterBounds( nItemId, nIndex ); 271 aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() ); 272 aBounds = AWTRectangle( aCharRect ); 273 } 274 275 return aBounds; 276 } 277 278 // ----------------------------------------------------------------------------- 279 280 sal_Int32 VCLXAccessibleMenuItem::getCharacterCount() throw (RuntimeException) 281 { 282 OExternalLockGuard aGuard( this ); 283 284 return OCommonAccessibleText::getCharacterCount(); 285 } 286 287 // ----------------------------------------------------------------------------- 288 289 sal_Int32 VCLXAccessibleMenuItem::getIndexAtPoint( const awt::Point& aPoint ) throw (RuntimeException) 290 { 291 OExternalLockGuard aGuard( this ); 292 293 sal_Int32 nIndex = -1; 294 if ( m_pParent ) 295 { 296 sal_uInt16 nItemId = 0; 297 Rectangle aItemRect = m_pParent->GetBoundingRectangle( m_nItemPos ); 298 Point aPnt( VCLPoint( aPoint ) ); 299 aPnt += aItemRect.TopLeft(); 300 sal_Int32 nI = m_pParent->GetIndexForPoint( aPnt, nItemId ); 301 if ( nI != -1 && m_pParent->GetItemId( m_nItemPos ) == nItemId ) 302 nIndex = nI; 303 } 304 305 return nIndex; 306 } 307 308 // ----------------------------------------------------------------------------- 309 310 ::rtl::OUString VCLXAccessibleMenuItem::getSelectedText() throw (RuntimeException) 311 { 312 OExternalLockGuard aGuard( this ); 313 314 return OCommonAccessibleText::getSelectedText(); 315 } 316 317 // ----------------------------------------------------------------------------- 318 319 sal_Int32 VCLXAccessibleMenuItem::getSelectionStart() throw (RuntimeException) 320 { 321 OExternalLockGuard aGuard( this ); 322 323 return OCommonAccessibleText::getSelectionStart(); 324 } 325 326 // ----------------------------------------------------------------------------- 327 328 sal_Int32 VCLXAccessibleMenuItem::getSelectionEnd() throw (RuntimeException) 329 { 330 OExternalLockGuard aGuard( this ); 331 332 return OCommonAccessibleText::getSelectionEnd(); 333 } 334 335 // ----------------------------------------------------------------------------- 336 337 sal_Bool VCLXAccessibleMenuItem::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException) 338 { 339 OExternalLockGuard aGuard( this ); 340 341 if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) ) 342 throw IndexOutOfBoundsException(); 343 344 return sal_False; 345 } 346 347 // ----------------------------------------------------------------------------- 348 349 ::rtl::OUString VCLXAccessibleMenuItem::getText() throw (RuntimeException) 350 { 351 OExternalLockGuard aGuard( this ); 352 353 return OCommonAccessibleText::getText(); 354 } 355 356 // ----------------------------------------------------------------------------- 357 358 ::rtl::OUString VCLXAccessibleMenuItem::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException) 359 { 360 OExternalLockGuard aGuard( this ); 361 362 return OCommonAccessibleText::getTextRange( nStartIndex, nEndIndex ); 363 } 364 365 // ----------------------------------------------------------------------------- 366 367 ::com::sun::star::accessibility::TextSegment VCLXAccessibleMenuItem::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 368 { 369 OExternalLockGuard aGuard( this ); 370 371 return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType ); 372 } 373 374 // ----------------------------------------------------------------------------- 375 376 ::com::sun::star::accessibility::TextSegment VCLXAccessibleMenuItem::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 377 { 378 OExternalLockGuard aGuard( this ); 379 380 return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType ); 381 } 382 383 // ----------------------------------------------------------------------------- 384 385 ::com::sun::star::accessibility::TextSegment VCLXAccessibleMenuItem::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) 386 { 387 OExternalLockGuard aGuard( this ); 388 389 return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType ); 390 } 391 392 // ----------------------------------------------------------------------------- 393 394 sal_Bool VCLXAccessibleMenuItem::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException) 395 { 396 OExternalLockGuard aGuard( this ); 397 398 sal_Bool bReturn = sal_False; 399 400 if ( m_pParent ) 401 { 402 Window* pWindow = m_pParent->GetWindow(); 403 if ( pWindow ) 404 { 405 Reference< datatransfer::clipboard::XClipboard > xClipboard = pWindow->GetClipboard(); 406 if ( xClipboard.is() ) 407 { 408 ::rtl::OUString sText( getTextRange( nStartIndex, nEndIndex ) ); 409 410 ::vcl::unohelper::TextDataObject* pDataObj = new ::vcl::unohelper::TextDataObject( sText ); 411 const sal_uInt32 nRef = Application::ReleaseSolarMutex(); 412 xClipboard->setContents( pDataObj, NULL ); 413 414 Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY ); 415 if( xFlushableClipboard.is() ) 416 xFlushableClipboard->flushClipboard(); 417 418 Application::AcquireSolarMutex( nRef ); 419 420 bReturn = sal_True; 421 } 422 } 423 } 424 425 return bReturn; 426 } 427 428 // ----------------------------------------------------------------------------- 429 // XAccessibleAction 430 // ----------------------------------------------------------------------------- 431 432 sal_Int32 VCLXAccessibleMenuItem::getAccessibleActionCount( ) throw (RuntimeException) 433 { 434 OExternalLockGuard aGuard( this ); 435 436 return 1; 437 } 438 439 // ----------------------------------------------------------------------------- 440 441 sal_Bool VCLXAccessibleMenuItem::doAccessibleAction ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) 442 { 443 OExternalLockGuard aGuard( this ); 444 445 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() ) 446 throw IndexOutOfBoundsException(); 447 448 Click(); 449 450 return sal_True; 451 } 452 453 // ----------------------------------------------------------------------------- 454 455 ::rtl::OUString VCLXAccessibleMenuItem::getAccessibleActionDescription ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) 456 { 457 OExternalLockGuard aGuard( this ); 458 459 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() ) 460 throw IndexOutOfBoundsException(); 461 462 return ::rtl::OUString( TK_RES_STRING( RID_STR_ACC_ACTION_CLICK ) ); 463 } 464 465 // ----------------------------------------------------------------------------- 466 467 Reference< XAccessibleKeyBinding > VCLXAccessibleMenuItem::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException) 468 { 469 OExternalLockGuard aGuard( this ); 470 471 if ( nIndex < 0 || nIndex >= getAccessibleActionCount() ) 472 throw IndexOutOfBoundsException(); 473 474 OAccessibleKeyBindingHelper* pKeyBindingHelper = new OAccessibleKeyBindingHelper(); 475 Reference< XAccessibleKeyBinding > xKeyBinding = pKeyBindingHelper; 476 477 if ( m_pParent ) 478 { 479 // create auto mnemonics 480 if ( Application::GetSettings().GetStyleSettings().GetAutoMnemonic() && !( m_pParent->GetMenuFlags() & MENU_FLAG_NOAUTOMNEMONICS ) ) 481 m_pParent->CreateAutoMnemonics(); 482 483 // activation key 484 KeyEvent aKeyEvent = m_pParent->GetActivationKey( m_pParent->GetItemId( m_nItemPos ) ); 485 KeyCode aKeyCode = aKeyEvent.GetKeyCode(); 486 Sequence< awt::KeyStroke > aSeq1(1); 487 aSeq1[0].Modifiers = 0; 488 Reference< XAccessible > xParent( getAccessibleParent() ); 489 if ( xParent.is() ) 490 { 491 Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); 492 if ( xParentContext.is() && xParentContext->getAccessibleRole() == AccessibleRole::MENU_BAR ) 493 aSeq1[0].Modifiers |= awt::KeyModifier::MOD2; 494 } 495 aSeq1[0].KeyCode = aKeyCode.GetCode(); 496 aSeq1[0].KeyChar = aKeyEvent.GetCharCode(); 497 aSeq1[0].KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() ); 498 pKeyBindingHelper->AddKeyBinding( aSeq1 ); 499 500 // complete menu activation key sequence 501 Sequence< awt::KeyStroke > aSeq; 502 if ( xParent.is() ) 503 { 504 Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); 505 if ( xParentContext.is() && xParentContext->getAccessibleRole() == AccessibleRole::MENU ) 506 { 507 Reference< XAccessibleAction > xAction( xParentContext, UNO_QUERY ); 508 if ( xAction.is() && xAction->getAccessibleActionCount() > 0 ) 509 { 510 Reference< XAccessibleKeyBinding > xKeyB( xAction->getAccessibleActionKeyBinding( 0 ) ); 511 if ( xKeyB.is() && xKeyB->getAccessibleKeyBindingCount() > 1 ) 512 aSeq = xKeyB->getAccessibleKeyBinding( 1 ); 513 } 514 } 515 } 516 Sequence< awt::KeyStroke > aSeq2 = ::comphelper::concatSequences( aSeq, aSeq1 ); 517 pKeyBindingHelper->AddKeyBinding( aSeq2 ); 518 519 // accelerator key 520 KeyCode aAccelKeyCode = m_pParent->GetAccelKey( m_pParent->GetItemId( m_nItemPos ) ); 521 if ( aAccelKeyCode.GetCode() != 0 ) 522 { 523 Sequence< awt::KeyStroke > aSeq3(1); 524 aSeq3[0].Modifiers = 0; 525 if ( aAccelKeyCode.IsShift() ) 526 aSeq3[0].Modifiers |= awt::KeyModifier::SHIFT; 527 if ( aAccelKeyCode.IsMod1() ) 528 aSeq3[0].Modifiers |= awt::KeyModifier::MOD1; 529 if ( aAccelKeyCode.IsMod2() ) 530 aSeq3[0].Modifiers |= awt::KeyModifier::MOD2; 531 if ( aAccelKeyCode.IsMod3() ) 532 aSeq3[0].Modifiers |= awt::KeyModifier::MOD3; 533 aSeq3[0].KeyCode = aAccelKeyCode.GetCode(); 534 aSeq3[0].KeyFunc = static_cast< sal_Int16 >( aAccelKeyCode.GetFunction() ); 535 pKeyBindingHelper->AddKeyBinding( aSeq3 ); 536 } 537 } 538 539 return xKeyBinding; 540 } 541 542 // ----------------------------------------------------------------------------- 543 // XAccessibleValue 544 // ----------------------------------------------------------------------------- 545 546 Any VCLXAccessibleMenuItem::getCurrentValue( ) throw (RuntimeException) 547 { 548 OExternalLockGuard aGuard( this ); 549 550 Any aValue; 551 if ( IsSelected() ) 552 aValue <<= (sal_Int32) 1; 553 else 554 aValue <<= (sal_Int32) 0; 555 556 return aValue; 557 } 558 559 // ----------------------------------------------------------------------------- 560 561 sal_Bool VCLXAccessibleMenuItem::setCurrentValue( const Any& aNumber ) throw (RuntimeException) 562 { 563 OExternalLockGuard aGuard( this ); 564 565 sal_Bool bReturn = sal_False; 566 sal_Int32 nValue = 0; 567 OSL_VERIFY( aNumber >>= nValue ); 568 569 if ( nValue <= 0 ) 570 { 571 DeSelect(); 572 bReturn = sal_True; 573 } 574 else if ( nValue >= 1 ) 575 { 576 Select(); 577 bReturn = sal_True; 578 } 579 580 return bReturn; 581 } 582 583 // ----------------------------------------------------------------------------- 584 585 Any VCLXAccessibleMenuItem::getMaximumValue( ) throw (RuntimeException) 586 { 587 OExternalLockGuard aGuard( this ); 588 589 Any aValue; 590 aValue <<= (sal_Int32) 1; 591 592 return aValue; 593 } 594 595 // ----------------------------------------------------------------------------- 596 597 Any VCLXAccessibleMenuItem::getMinimumValue( ) throw (RuntimeException) 598 { 599 OExternalLockGuard aGuard( this ); 600 601 Any aValue; 602 aValue <<= (sal_Int32) 0; 603 604 return aValue; 605 } 606 607 // ----------------------------------------------------------------------------- 608