Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / accessibility / source / standard / accessiblemenubasecomponent.cxx
blob48118edfc48ef87aa63f83ff8975bb29d82381d8
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;
43 // -----------------------------------------------------------------------------
44 // OAccessibleMenuBaseComponent
45 // -----------------------------------------------------------------------------
47 OAccessibleMenuBaseComponent::OAccessibleMenuBaseComponent( Menu* pMenu )
48 :AccessibleExtendedComponentHelper_BASE( new VCLExternalSolarLock() )
49 ,m_pMenu( pMenu )
50 ,m_bEnabled( sal_False )
51 ,m_bFocused( sal_False )
52 ,m_bVisible( sal_False )
53 ,m_bSelected( sal_False )
54 ,m_bChecked( sal_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 ) );
65 // -----------------------------------------------------------------------------
67 OAccessibleMenuBaseComponent::~OAccessibleMenuBaseComponent()
69 if ( m_pMenu )
70 m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
72 delete m_pExternalLock;
73 m_pExternalLock = NULL;
76 // -----------------------------------------------------------------------------
78 sal_Bool OAccessibleMenuBaseComponent::IsEnabled()
80 return sal_False;
83 // -----------------------------------------------------------------------------
85 sal_Bool OAccessibleMenuBaseComponent::IsFocused()
87 return sal_False;
90 // -----------------------------------------------------------------------------
92 sal_Bool OAccessibleMenuBaseComponent::IsVisible()
94 return sal_False;
97 // -----------------------------------------------------------------------------
99 sal_Bool OAccessibleMenuBaseComponent::IsSelected()
101 return sal_False;
104 // -----------------------------------------------------------------------------
106 sal_Bool OAccessibleMenuBaseComponent::IsChecked()
108 return sal_False;
111 // -----------------------------------------------------------------------------
113 void OAccessibleMenuBaseComponent::SetStates()
115 m_bEnabled = IsEnabled();
116 m_bFocused = IsFocused();
117 m_bVisible = IsVisible();
118 m_bSelected = IsSelected();
119 m_bChecked = IsChecked();
122 // -----------------------------------------------------------------------------
124 void OAccessibleMenuBaseComponent::SetEnabled( sal_Bool bEnabled )
126 if ( m_bEnabled != bEnabled )
128 Any aOldValue[2], aNewValue[2];
129 if ( m_bEnabled )
131 aOldValue[0] <<= AccessibleStateType::SENSITIVE;
132 aOldValue[1] <<= AccessibleStateType::ENABLED;
134 else
136 aNewValue[0] <<= AccessibleStateType::ENABLED;
137 aNewValue[1] <<= AccessibleStateType::SENSITIVE;
139 m_bEnabled = bEnabled;
140 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[0], aNewValue[0] );
141 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[1], aNewValue[1] );
145 // -----------------------------------------------------------------------------
147 void OAccessibleMenuBaseComponent::SetFocused( sal_Bool bFocused )
149 if ( m_bFocused != bFocused )
151 Any aOldValue, aNewValue;
152 if ( m_bFocused )
153 aOldValue <<= AccessibleStateType::FOCUSED;
154 else
155 aNewValue <<= AccessibleStateType::FOCUSED;
156 m_bFocused = bFocused;
157 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
161 // -----------------------------------------------------------------------------
163 void OAccessibleMenuBaseComponent::SetVisible( sal_Bool bVisible )
165 if ( m_bVisible != bVisible )
167 Any aOldValue, aNewValue;
168 if ( m_bVisible )
169 aOldValue <<= AccessibleStateType::VISIBLE;
170 else
171 aNewValue <<= AccessibleStateType::VISIBLE;
172 m_bVisible = bVisible;
173 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
177 // -----------------------------------------------------------------------------
179 void OAccessibleMenuBaseComponent::SetSelected( sal_Bool bSelected )
181 if ( m_bSelected != bSelected )
183 Any aOldValue, aNewValue;
184 if ( m_bSelected )
185 aOldValue <<= AccessibleStateType::SELECTED;
186 else
187 aNewValue <<= AccessibleStateType::SELECTED;
188 m_bSelected = bSelected;
189 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
193 // -----------------------------------------------------------------------------
195 void OAccessibleMenuBaseComponent::SetChecked( sal_Bool bChecked )
197 if ( m_bChecked != bChecked )
199 Any aOldValue, aNewValue;
200 if ( m_bChecked )
201 aOldValue <<= AccessibleStateType::CHECKED;
202 else
203 aNewValue <<= AccessibleStateType::CHECKED;
204 m_bChecked = bChecked;
205 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
209 // -----------------------------------------------------------------------------
211 void OAccessibleMenuBaseComponent::UpdateEnabled( sal_Int32 i, sal_Bool bEnabled )
213 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
215 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
216 if ( xChild.is() )
218 OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
219 if ( pComp )
220 pComp->SetEnabled( bEnabled );
225 // -----------------------------------------------------------------------------
227 void OAccessibleMenuBaseComponent::UpdateFocused( sal_Int32 i, sal_Bool bFocused )
229 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
231 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
232 if ( xChild.is() )
234 OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
235 if ( pComp )
236 pComp->SetFocused( bFocused );
241 // -----------------------------------------------------------------------------
243 void OAccessibleMenuBaseComponent::UpdateVisible()
245 SetVisible( IsVisible() );
246 for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
248 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
249 if ( xChild.is() )
251 OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
252 if ( pComp )
253 pComp->SetVisible( pComp->IsVisible() );
258 // -----------------------------------------------------------------------------
260 void OAccessibleMenuBaseComponent::UpdateSelected( sal_Int32 i, sal_Bool bSelected )
262 NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
264 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
266 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
267 if ( xChild.is() )
269 OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
270 if ( pComp )
271 pComp->SetSelected( bSelected );
276 // -----------------------------------------------------------------------------
278 void OAccessibleMenuBaseComponent::UpdateChecked( sal_Int32 i, sal_Bool bChecked )
280 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
282 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
283 if ( xChild.is() )
285 OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
286 if ( pComp )
287 pComp->SetChecked( bChecked );
292 // -----------------------------------------------------------------------------
294 void OAccessibleMenuBaseComponent::UpdateAccessibleName( sal_Int32 i )
296 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
298 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
299 if ( xChild.is() )
301 OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xChild.get() );
302 if ( pComp )
303 pComp->SetAccessibleName( pComp->GetAccessibleName() );
308 // -----------------------------------------------------------------------------
310 void OAccessibleMenuBaseComponent::UpdateItemText( sal_Int32 i )
312 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
314 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
315 if ( xChild.is() )
317 OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xChild.get() );
318 if ( pComp )
319 pComp->SetItemText( pComp->GetItemText() );
324 // -----------------------------------------------------------------------------
326 sal_Int32 OAccessibleMenuBaseComponent::GetChildCount()
328 return m_aAccessibleChildren.size();
331 // -----------------------------------------------------------------------------
333 Reference< XAccessible > OAccessibleMenuBaseComponent::GetChild( sal_Int32 i )
335 Reference< XAccessible > xChild = m_aAccessibleChildren[i];
336 if ( !xChild.is() )
338 if ( m_pMenu )
340 // create a new child
341 OAccessibleMenuBaseComponent* pChild;
343 if ( m_pMenu->GetItemType( (sal_uInt16)i ) == MENUITEM_SEPARATOR )
345 pChild = new VCLXAccessibleMenuSeparator( m_pMenu, (sal_uInt16)i );
347 else
349 PopupMenu* pPopupMenu = m_pMenu->GetPopupMenu( m_pMenu->GetItemId( (sal_uInt16)i ) );
350 if ( pPopupMenu )
352 pChild = new VCLXAccessibleMenu( m_pMenu, (sal_uInt16)i, pPopupMenu );
353 pPopupMenu->SetAccessible( pChild );
355 else
357 pChild = new VCLXAccessibleMenuItem( m_pMenu, (sal_uInt16)i );
361 // set states
362 pChild->SetStates();
364 xChild = pChild;
366 // insert into menu item list
367 m_aAccessibleChildren[i] = xChild;
371 return xChild;
374 // -----------------------------------------------------------------------------
376 Reference< XAccessible > OAccessibleMenuBaseComponent::GetChildAt( const awt::Point& rPoint )
378 Reference< XAccessible > xChild;
379 for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
381 Reference< XAccessible > xAcc = getAccessibleChild( i );
382 if ( xAcc.is() )
384 Reference< XAccessibleComponent > xComp( xAcc->getAccessibleContext(), UNO_QUERY );
385 if ( xComp.is() )
387 Rectangle aRect = VCLRectangle( xComp->getBounds() );
388 Point aPos = VCLPoint( rPoint );
389 if ( aRect.IsInside( aPos ) )
391 xChild = xAcc;
392 break;
398 return xChild;
401 // -----------------------------------------------------------------------------
403 void OAccessibleMenuBaseComponent::InsertChild( sal_Int32 i )
405 if ( i > (sal_Int32)m_aAccessibleChildren.size() )
406 i = m_aAccessibleChildren.size();
408 if ( i >= 0 )
410 // insert entry in child list
411 m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() );
413 // update item position of accessible children
414 for ( sal_uInt32 j = i, nCount = m_aAccessibleChildren.size(); j < nCount; ++j )
416 Reference< XAccessible > xAcc( m_aAccessibleChildren[j] );
417 if ( xAcc.is() )
419 OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xAcc.get() );
420 if ( pComp )
421 pComp->SetItemPos( (sal_uInt16)j );
425 // send accessible child event
426 Reference< XAccessible > xChild( GetChild( i ) );
427 if ( xChild.is() )
429 Any aOldValue, aNewValue;
430 aNewValue <<= xChild;
431 NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
436 // -----------------------------------------------------------------------------
438 void OAccessibleMenuBaseComponent::RemoveChild( sal_Int32 i )
440 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
442 // keep the accessible of the removed item
443 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
445 // remove entry in child list
446 m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
448 // update item position of accessible children
449 for ( sal_uInt32 j = i, nCount = m_aAccessibleChildren.size(); j < nCount; ++j )
451 Reference< XAccessible > xAcc( m_aAccessibleChildren[j] );
452 if ( xAcc.is() )
454 OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xAcc.get() );
455 if ( pComp )
456 pComp->SetItemPos( (sal_uInt16)j );
460 // send accessible child event
461 if ( xChild.is() )
463 Any aOldValue, aNewValue;
464 aOldValue <<= xChild;
465 NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
467 Reference< XComponent > xComponent( xChild, UNO_QUERY );
468 if ( xComponent.is() )
469 xComponent->dispose();
474 // -----------------------------------------------------------------------------
476 sal_Bool OAccessibleMenuBaseComponent::IsHighlighted()
478 return sal_False;
481 // -----------------------------------------------------------------------------
483 sal_Bool OAccessibleMenuBaseComponent::IsChildHighlighted()
485 sal_Bool bChildHighlighted = sal_False;
487 for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
489 Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
490 if ( xChild.is() )
492 OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
493 if ( pComp && pComp->IsHighlighted() )
495 bChildHighlighted = sal_True;
496 break;
501 return bChildHighlighted;
504 // -----------------------------------------------------------------------------
506 void OAccessibleMenuBaseComponent::SelectChild( sal_Int32 i )
508 // open the menu
509 if ( getAccessibleRole() == AccessibleRole::MENU && !IsPopupMenuOpen() )
510 Click();
512 // highlight the child
513 if ( m_pMenu )
514 m_pMenu->HighlightItem( (sal_uInt16)i );
517 // -----------------------------------------------------------------------------
519 void OAccessibleMenuBaseComponent::DeSelectAll()
521 if ( m_pMenu )
522 m_pMenu->DeHighlight();
525 // -----------------------------------------------------------------------------
527 sal_Bool OAccessibleMenuBaseComponent::IsChildSelected( sal_Int32 i )
529 sal_Bool bSelected = sal_False;
531 if ( m_pMenu && m_pMenu->IsHighlighted( (sal_uInt16)i ) )
532 bSelected = sal_True;
534 return bSelected;
537 // -----------------------------------------------------------------------------
539 void OAccessibleMenuBaseComponent::Select()
543 // -----------------------------------------------------------------------------
545 void OAccessibleMenuBaseComponent::DeSelect()
549 // -----------------------------------------------------------------------------
551 void OAccessibleMenuBaseComponent::Click()
555 // -----------------------------------------------------------------------------
557 sal_Bool OAccessibleMenuBaseComponent::IsPopupMenuOpen()
559 return sal_False;
562 // -----------------------------------------------------------------------------
564 IMPL_LINK( OAccessibleMenuBaseComponent, MenuEventListener, VclSimpleEvent*, pEvent )
566 OSL_ENSURE( pEvent && pEvent->ISA( VclMenuEvent ), "OAccessibleMenuBaseComponent - Unknown MenuEvent!" );
567 if ( pEvent && pEvent->ISA( VclMenuEvent ) )
569 OSL_ENSURE( ((VclMenuEvent*)pEvent)->GetMenu(), "OAccessibleMenuBaseComponent - Menu?" );
570 ProcessMenuEvent( *(VclMenuEvent*)pEvent );
572 return 0;
575 // -----------------------------------------------------------------------------
577 void OAccessibleMenuBaseComponent::ProcessMenuEvent( const VclMenuEvent& rVclMenuEvent )
579 sal_uInt16 nItemPos = rVclMenuEvent.GetItemPos();
581 switch ( rVclMenuEvent.GetId() )
583 case VCLEVENT_MENU_SHOW:
584 case VCLEVENT_MENU_HIDE:
586 UpdateVisible();
588 break;
589 case VCLEVENT_MENU_HIGHLIGHT:
591 SetFocused( sal_False );
592 UpdateFocused( nItemPos, sal_True );
593 UpdateSelected( nItemPos, sal_True );
595 break;
596 case VCLEVENT_MENU_DEHIGHLIGHT:
598 UpdateFocused( nItemPos, sal_False );
599 UpdateSelected( nItemPos, sal_False );
601 break;
602 case VCLEVENT_MENU_SUBMENUACTIVATE:
605 break;
606 case VCLEVENT_MENU_SUBMENUDEACTIVATE:
608 UpdateFocused( nItemPos, sal_True );
610 break;
611 case VCLEVENT_MENU_ENABLE:
613 UpdateEnabled( nItemPos, sal_True );
615 break;
616 case VCLEVENT_MENU_DISABLE:
618 UpdateEnabled( nItemPos, sal_False );
620 break;
621 case VCLEVENT_MENU_SUBMENUCHANGED:
623 RemoveChild( nItemPos );
624 InsertChild( nItemPos );
626 break;
627 case VCLEVENT_MENU_INSERTITEM:
629 InsertChild( nItemPos );
631 break;
632 case VCLEVENT_MENU_REMOVEITEM:
634 RemoveChild( nItemPos );
636 break;
637 case VCLEVENT_MENU_ACCESSIBLENAMECHANGED:
639 UpdateAccessibleName( nItemPos );
641 break;
642 case VCLEVENT_MENU_ITEMTEXTCHANGED:
644 UpdateAccessibleName( nItemPos );
645 UpdateItemText( nItemPos );
647 break;
648 case VCLEVENT_MENU_ITEMCHECKED:
650 UpdateChecked( nItemPos, sal_True );
652 break;
653 case VCLEVENT_MENU_ITEMUNCHECKED:
655 UpdateChecked( nItemPos, sal_False );
657 break;
658 case VCLEVENT_OBJECT_DYING:
660 if ( m_pMenu )
662 m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
664 m_pMenu = NULL;
666 // dispose all menu items
667 for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
669 Reference< XComponent > xComponent( m_aAccessibleChildren[i], UNO_QUERY );
670 if ( xComponent.is() )
671 xComponent->dispose();
673 m_aAccessibleChildren.clear();
676 break;
677 default:
680 break;
684 // -----------------------------------------------------------------------------
685 // XInterface
686 // -----------------------------------------------------------------------------
688 IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleMenuBaseComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleMenuBaseComponent_BASE )
690 // -----------------------------------------------------------------------------
691 // XTypeProvider
692 // -----------------------------------------------------------------------------
694 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleMenuBaseComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleMenuBaseComponent_BASE )
696 // -----------------------------------------------------------------------------
697 // XComponent
698 // -----------------------------------------------------------------------------
700 void OAccessibleMenuBaseComponent::disposing()
702 AccessibleExtendedComponentHelper_BASE::disposing();
704 if ( m_pMenu )
706 m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
708 m_pMenu = NULL;
710 // dispose all menu items
711 for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
713 Reference< XComponent > xComponent( m_aAccessibleChildren[i], UNO_QUERY );
714 if ( xComponent.is() )
715 xComponent->dispose();
717 m_aAccessibleChildren.clear();
721 // -----------------------------------------------------------------------------
722 // XServiceInfo
723 // -----------------------------------------------------------------------------
725 sal_Bool OAccessibleMenuBaseComponent::supportsService( const OUString& rServiceName ) throw (RuntimeException)
727 return cppu::supportsService(this, rServiceName);
730 // -----------------------------------------------------------------------------
731 // XAccessible
732 // -----------------------------------------------------------------------------
734 Reference< XAccessibleContext > OAccessibleMenuBaseComponent::getAccessibleContext( ) throw (RuntimeException)
736 OExternalLockGuard aGuard( this );
738 return this;
741 // -----------------------------------------------------------------------------
742 // XAccessibleContext
743 // -----------------------------------------------------------------------------
745 Reference< XAccessibleStateSet > OAccessibleMenuBaseComponent::getAccessibleStateSet( ) throw (RuntimeException)
747 OExternalLockGuard aGuard( this );
749 utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
750 Reference< XAccessibleStateSet > xSet = pStateSetHelper;
752 if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
754 FillAccessibleStateSet( *pStateSetHelper );
756 else
758 pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
761 return xSet;
764 // -----------------------------------------------------------------------------
766 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */