Branch libreoffice-5-0-4
[LibreOffice.git] / accessibility / source / standard / accessiblemenubasecomponent.cxx
blob9ab7b0c6849dd9cdfd3598937c27cb6881982eb9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/accessiblemenubasecomponent.hxx>
21 #include <accessibility/standard/vclxaccessiblemenu.hxx>
22 #include <accessibility/standard/vclxaccessiblemenuitem.hxx>
23 #include <accessibility/standard/vclxaccessiblemenuseparator.hxx>
24 #include <toolkit/helper/externallock.hxx>
25 #include <toolkit/helper/convert.hxx>
27 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
28 #include <com/sun/star/accessibility/AccessibleRole.hpp>
29 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
30 #include <cppuhelper/supportsservice.hxx>
31 #include <unotools/accessiblestatesethelper.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/window.hxx>
34 #include <vcl/menu.hxx>
36 using namespace ::com::sun::star;
37 using namespace ::com::sun::star::lang;
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::accessibility;
40 using namespace ::comphelper;
44 // OAccessibleMenuBaseComponent
47 OAccessibleMenuBaseComponent::OAccessibleMenuBaseComponent( Menu* pMenu )
48 :AccessibleExtendedComponentHelper_BASE( new VCLExternalSolarLock() )
49 ,m_pMenu( pMenu )
50 ,m_bEnabled( false )
51 ,m_bFocused( false )
52 ,m_bVisible( false )
53 ,m_bSelected( false )
54 ,m_bChecked( false )
56 m_pExternalLock = static_cast< VCLExternalSolarLock* >( getExternalLock() );
58 if ( m_pMenu )
60 m_aAccessibleChildren.assign( m_pMenu->GetItemCount(), Reference< XAccessible >() );
61 m_pMenu->AddEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
67 OAccessibleMenuBaseComponent::~OAccessibleMenuBaseComponent()
69 if ( m_pMenu )
70 m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
72 delete m_pExternalLock;
73 m_pExternalLock = NULL;
78 bool OAccessibleMenuBaseComponent::IsEnabled()
80 return false;
85 bool OAccessibleMenuBaseComponent::IsFocused()
87 return false;
92 bool OAccessibleMenuBaseComponent::IsVisible()
94 return false;
99 bool OAccessibleMenuBaseComponent::IsSelected()
101 return false;
106 bool OAccessibleMenuBaseComponent::IsChecked()
108 return false;
113 void OAccessibleMenuBaseComponent::SetStates()
115 m_bEnabled = IsEnabled();
116 m_bFocused = IsFocused();
117 m_bVisible = IsVisible();
118 m_bSelected = IsSelected();
119 m_bChecked = IsChecked();
124 void OAccessibleMenuBaseComponent::SetEnabled( bool bEnabled )
126 if ( m_bEnabled != bEnabled )
128 sal_Int16 nStateType=AccessibleStateType::ENABLED;
129 if (IsMenuHideDisabledEntries())
131 nStateType = AccessibleStateType::VISIBLE;
133 Any aOldValue[2], aNewValue[2];
134 if ( m_bEnabled )
136 aOldValue[0] <<= AccessibleStateType::SENSITIVE;
137 aOldValue[1] <<= nStateType;
139 else
141 aNewValue[0] <<= nStateType;
142 aNewValue[1] <<= AccessibleStateType::SENSITIVE;
144 m_bEnabled = bEnabled;
145 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[0], aNewValue[0] );
146 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[1], aNewValue[1] );
152 void OAccessibleMenuBaseComponent::SetFocused( bool bFocused )
154 if ( m_bFocused != bFocused )
156 Any aOldValue, aNewValue;
157 if ( m_bFocused )
158 aOldValue <<= AccessibleStateType::FOCUSED;
159 else
160 aNewValue <<= AccessibleStateType::FOCUSED;
161 m_bFocused = bFocused;
162 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
168 void OAccessibleMenuBaseComponent::SetVisible( bool bVisible )
170 if ( m_bVisible != bVisible )
172 Any aOldValue, aNewValue;
173 if ( m_bVisible )
174 aOldValue <<= AccessibleStateType::VISIBLE;
175 else
176 aNewValue <<= AccessibleStateType::VISIBLE;
177 m_bVisible = bVisible;
178 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
184 void OAccessibleMenuBaseComponent::SetSelected( bool bSelected )
186 if ( m_bSelected != bSelected )
188 Any aOldValue, aNewValue;
189 if ( m_bSelected )
190 aOldValue <<= AccessibleStateType::SELECTED;
191 else
192 aNewValue <<= AccessibleStateType::SELECTED;
193 m_bSelected = bSelected;
194 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
200 void OAccessibleMenuBaseComponent::SetChecked( bool bChecked )
202 if ( m_bChecked != bChecked )
204 Any aOldValue, aNewValue;
205 if ( m_bChecked )
206 aOldValue <<= AccessibleStateType::CHECKED;
207 else
208 aNewValue <<= AccessibleStateType::CHECKED;
209 m_bChecked = bChecked;
210 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
216 void OAccessibleMenuBaseComponent::UpdateEnabled( sal_Int32 i, bool bEnabled )
218 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
220 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
221 if ( xChild.is() )
223 OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
224 if ( pComp )
225 pComp->SetEnabled( bEnabled );
232 void OAccessibleMenuBaseComponent::UpdateFocused( sal_Int32 i, bool bFocused )
234 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
236 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
237 if ( xChild.is() )
239 OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
240 if ( pComp )
241 pComp->SetFocused( bFocused );
248 void OAccessibleMenuBaseComponent::UpdateVisible()
250 SetVisible( IsVisible() );
251 for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
253 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
254 if ( xChild.is() )
256 OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
257 if ( pComp )
258 pComp->SetVisible( pComp->IsVisible() );
265 void OAccessibleMenuBaseComponent::UpdateSelected( sal_Int32 i, bool bSelected )
267 NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
269 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
271 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
272 if ( xChild.is() )
274 OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
275 if ( pComp )
276 pComp->SetSelected( bSelected );
283 void OAccessibleMenuBaseComponent::UpdateChecked( sal_Int32 i, bool bChecked )
285 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
287 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
288 if ( xChild.is() )
290 OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
291 if ( pComp )
292 pComp->SetChecked( bChecked );
299 void OAccessibleMenuBaseComponent::UpdateAccessibleName( sal_Int32 i )
301 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
303 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
304 if ( xChild.is() )
306 OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xChild.get() );
307 if ( pComp )
308 pComp->SetAccessibleName( pComp->GetAccessibleName() );
315 void OAccessibleMenuBaseComponent::UpdateItemText( sal_Int32 i )
317 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
319 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
320 if ( xChild.is() )
322 OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xChild.get() );
323 if ( pComp )
324 pComp->SetItemText( pComp->GetItemText() );
331 sal_Int32 OAccessibleMenuBaseComponent::GetChildCount()
333 return m_aAccessibleChildren.size();
338 Reference< XAccessible > OAccessibleMenuBaseComponent::GetChild( sal_Int32 i )
340 Reference< XAccessible > xChild = m_aAccessibleChildren[i];
341 if ( !xChild.is() )
343 if ( m_pMenu )
345 // create a new child
346 OAccessibleMenuBaseComponent* pChild;
348 if ( m_pMenu->GetItemType( (sal_uInt16)i ) == MenuItemType::SEPARATOR )
350 pChild = new VCLXAccessibleMenuSeparator( m_pMenu, (sal_uInt16)i );
352 else
354 PopupMenu* pPopupMenu = m_pMenu->GetPopupMenu( m_pMenu->GetItemId( (sal_uInt16)i ) );
355 if ( pPopupMenu )
357 pChild = new VCLXAccessibleMenu( m_pMenu, (sal_uInt16)i, pPopupMenu );
358 pPopupMenu->SetAccessible( pChild );
360 else
362 pChild = new VCLXAccessibleMenuItem( m_pMenu, (sal_uInt16)i );
366 // set states
367 pChild->SetStates();
369 xChild = pChild;
371 // insert into menu item list
372 m_aAccessibleChildren[i] = xChild;
376 return xChild;
381 Reference< XAccessible > OAccessibleMenuBaseComponent::GetChildAt( const awt::Point& rPoint )
383 Reference< XAccessible > xChild;
384 for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
386 Reference< XAccessible > xAcc = getAccessibleChild( i );
387 if ( xAcc.is() )
389 Reference< XAccessibleComponent > xComp( xAcc->getAccessibleContext(), UNO_QUERY );
390 if ( xComp.is() )
392 Rectangle aRect = VCLRectangle( xComp->getBounds() );
393 Point aPos = VCLPoint( rPoint );
394 if ( aRect.IsInside( aPos ) )
396 xChild = xAcc;
397 break;
403 return xChild;
408 void OAccessibleMenuBaseComponent::InsertChild( sal_Int32 i )
410 if ( i > (sal_Int32)m_aAccessibleChildren.size() )
411 i = m_aAccessibleChildren.size();
413 if ( i >= 0 )
415 // insert entry in child list
416 m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() );
418 // update item position of accessible children
419 for ( sal_uInt32 j = i, nCount = m_aAccessibleChildren.size(); j < nCount; ++j )
421 Reference< XAccessible > xAcc( m_aAccessibleChildren[j] );
422 if ( xAcc.is() )
424 OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xAcc.get() );
425 if ( pComp )
426 pComp->SetItemPos( (sal_uInt16)j );
430 // send accessible child event
431 Reference< XAccessible > xChild( GetChild( i ) );
432 if ( xChild.is() )
434 Any aOldValue, aNewValue;
435 aNewValue <<= xChild;
436 NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
443 void OAccessibleMenuBaseComponent::RemoveChild( sal_Int32 i )
445 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
447 // keep the accessible of the removed item
448 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
450 // remove entry in child list
451 m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
453 // update item position of accessible children
454 for ( sal_uInt32 j = i, nCount = m_aAccessibleChildren.size(); j < nCount; ++j )
456 Reference< XAccessible > xAcc( m_aAccessibleChildren[j] );
457 if ( xAcc.is() )
459 OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xAcc.get() );
460 if ( pComp )
461 pComp->SetItemPos( (sal_uInt16)j );
465 // send accessible child event
466 if ( xChild.is() )
468 Any aOldValue, aNewValue;
469 aOldValue <<= xChild;
470 NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
472 Reference< XComponent > xComponent( xChild, UNO_QUERY );
473 if ( xComponent.is() )
474 xComponent->dispose();
481 bool OAccessibleMenuBaseComponent::IsHighlighted()
483 return false;
488 bool OAccessibleMenuBaseComponent::IsChildHighlighted()
490 bool bChildHighlighted = false;
492 for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
494 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
495 if ( xChild.is() )
497 OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
498 if ( pComp && pComp->IsHighlighted() )
500 bChildHighlighted = true;
501 break;
506 return bChildHighlighted;
511 void OAccessibleMenuBaseComponent::SelectChild( sal_Int32 i )
513 // open the menu
514 if ( getAccessibleRole() == AccessibleRole::MENU && !IsPopupMenuOpen() )
515 Click();
517 // highlight the child
518 if ( m_pMenu )
519 m_pMenu->HighlightItem( (sal_uInt16)i );
524 void OAccessibleMenuBaseComponent::DeSelectAll()
526 if ( m_pMenu )
527 m_pMenu->DeHighlight();
532 bool OAccessibleMenuBaseComponent::IsChildSelected( sal_Int32 i )
534 bool bSelected = false;
536 if ( m_pMenu && m_pMenu->IsHighlighted( (sal_uInt16)i ) )
537 bSelected = true;
539 return bSelected;
544 void OAccessibleMenuBaseComponent::Select()
550 void OAccessibleMenuBaseComponent::DeSelect()
556 void OAccessibleMenuBaseComponent::Click()
562 bool OAccessibleMenuBaseComponent::IsPopupMenuOpen()
564 return false;
569 IMPL_LINK( OAccessibleMenuBaseComponent, MenuEventListener, VclSimpleEvent*, pEvent )
571 OSL_ENSURE( pEvent && pEvent->ISA( VclMenuEvent ), "OAccessibleMenuBaseComponent - Unknown MenuEvent!" );
572 if ( pEvent && pEvent->ISA( VclMenuEvent ) )
574 OSL_ENSURE( static_cast<VclMenuEvent*>(pEvent)->GetMenu(), "OAccessibleMenuBaseComponent - Menu?" );
575 ProcessMenuEvent( *static_cast<VclMenuEvent*>(pEvent) );
577 return 0;
582 void OAccessibleMenuBaseComponent::ProcessMenuEvent( const VclMenuEvent& rVclMenuEvent )
584 sal_uInt16 nItemPos = rVclMenuEvent.GetItemPos();
586 switch ( rVclMenuEvent.GetId() )
588 case VCLEVENT_MENU_SHOW:
589 case VCLEVENT_MENU_HIDE:
591 UpdateVisible();
593 break;
594 case VCLEVENT_MENU_HIGHLIGHT:
596 SetFocused( false );
597 UpdateFocused( nItemPos, true );
598 UpdateSelected( nItemPos, true );
600 break;
601 case VCLEVENT_MENU_DEHIGHLIGHT:
603 UpdateFocused( nItemPos, false );
604 UpdateSelected( nItemPos, false );
606 break;
607 case VCLEVENT_MENU_SUBMENUACTIVATE:
610 break;
611 case VCLEVENT_MENU_SUBMENUDEACTIVATE:
613 UpdateFocused( nItemPos, true );
615 break;
616 case VCLEVENT_MENU_ENABLE:
618 UpdateEnabled( nItemPos, true );
620 break;
621 case VCLEVENT_MENU_DISABLE:
623 UpdateEnabled( nItemPos, false );
625 break;
626 case VCLEVENT_MENU_SUBMENUCHANGED:
628 RemoveChild( nItemPos );
629 InsertChild( nItemPos );
631 break;
632 case VCLEVENT_MENU_INSERTITEM:
634 InsertChild( nItemPos );
636 break;
637 case VCLEVENT_MENU_REMOVEITEM:
639 RemoveChild( nItemPos );
641 break;
642 case VCLEVENT_MENU_ACCESSIBLENAMECHANGED:
644 UpdateAccessibleName( nItemPos );
646 break;
647 case VCLEVENT_MENU_ITEMTEXTCHANGED:
649 UpdateAccessibleName( nItemPos );
650 UpdateItemText( nItemPos );
652 break;
653 case VCLEVENT_MENU_ITEMCHECKED:
655 UpdateChecked( nItemPos, true );
657 break;
658 case VCLEVENT_MENU_ITEMUNCHECKED:
660 UpdateChecked( nItemPos, false );
662 break;
663 case VCLEVENT_OBJECT_DYING:
665 if ( m_pMenu )
667 m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
669 m_pMenu = NULL;
671 // dispose all menu items
672 for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
674 Reference< XComponent > xComponent( m_aAccessibleChildren[i], UNO_QUERY );
675 if ( xComponent.is() )
676 xComponent->dispose();
678 m_aAccessibleChildren.clear();
681 break;
682 default:
685 break;
690 // XInterface
693 IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleMenuBaseComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleMenuBaseComponent_BASE )
696 // XTypeProvider
699 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleMenuBaseComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleMenuBaseComponent_BASE )
702 // XComponent
705 void OAccessibleMenuBaseComponent::disposing()
707 AccessibleExtendedComponentHelper_BASE::disposing();
709 if ( m_pMenu )
711 m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
713 m_pMenu = NULL;
715 // dispose all menu items
716 for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
718 Reference< XComponent > xComponent( m_aAccessibleChildren[i], UNO_QUERY );
719 if ( xComponent.is() )
720 xComponent->dispose();
722 m_aAccessibleChildren.clear();
727 // XServiceInfo
730 sal_Bool OAccessibleMenuBaseComponent::supportsService( const OUString& rServiceName ) throw (RuntimeException, std::exception)
732 return cppu::supportsService(this, rServiceName);
736 // XAccessible
739 Reference< XAccessibleContext > OAccessibleMenuBaseComponent::getAccessibleContext( ) throw (RuntimeException, std::exception)
741 OExternalLockGuard aGuard( this );
743 return this;
747 // XAccessibleContext
750 Reference< XAccessibleStateSet > OAccessibleMenuBaseComponent::getAccessibleStateSet( ) throw (RuntimeException, std::exception)
752 OExternalLockGuard aGuard( this );
754 utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
755 Reference< XAccessibleStateSet > xSet = pStateSetHelper;
757 if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
759 FillAccessibleStateSet( *pStateSetHelper );
761 else
763 pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
766 return xSet;
771 bool OAccessibleMenuBaseComponent::IsMenuHideDisabledEntries()
773 return false;
776 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */