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 
31 // includes --------------------------------------------------------------
32 #include <accessibility/standard/accessiblemenubasecomponent.hxx>
33 #include <accessibility/standard/vclxaccessiblemenu.hxx>
34 #include <accessibility/standard/vclxaccessiblemenuitem.hxx>
35 #include <accessibility/standard/vclxaccessiblemenuseparator.hxx>
36 #include <toolkit/helper/externallock.hxx>
37 #include <toolkit/helper/convert.hxx>
38 
39 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
40 #include <com/sun/star/accessibility/AccessibleRole.hpp>
41 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
42 
43 #include <unotools/accessiblestatesethelper.hxx>
44 #include <vcl/svapp.hxx>
45 #include <vcl/window.hxx>
46 #include <vcl/menu.hxx>
47 #include <tools/debug.hxx>
48 
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::lang;
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::accessibility;
53 using namespace ::comphelper;
54 
55 
56 // -----------------------------------------------------------------------------
57 // OAccessibleMenuBaseComponent
58 // -----------------------------------------------------------------------------
59 
60 OAccessibleMenuBaseComponent::OAccessibleMenuBaseComponent( Menu* pMenu )
61 	:AccessibleExtendedComponentHelper_BASE( new VCLExternalSolarLock() )
62 	,m_pMenu( pMenu )
63 	,m_bEnabled( sal_False )
64 	,m_bFocused( sal_False )
65     ,m_bVisible( sal_False )
66 	,m_bSelected( sal_False )
67 	,m_bChecked( sal_False )
68 {
69 	m_pExternalLock = static_cast< VCLExternalSolarLock* >( getExternalLock() );
70 
71 	if ( m_pMenu )
72 	{
73 		m_aAccessibleChildren.assign( m_pMenu->GetItemCount(), Reference< XAccessible >() );
74 		m_pMenu->AddEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
75 	}
76 }
77 
78 // -----------------------------------------------------------------------------
79 
80 OAccessibleMenuBaseComponent::~OAccessibleMenuBaseComponent()
81 {
82 	if ( m_pMenu )
83 		m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
84 
85 	delete m_pExternalLock;
86 	m_pExternalLock = NULL;
87 }
88 
89 // -----------------------------------------------------------------------------
90 
91 sal_Bool OAccessibleMenuBaseComponent::IsEnabled()
92 {
93 	return sal_False;
94 }
95 
96 // -----------------------------------------------------------------------------
97 
98 sal_Bool OAccessibleMenuBaseComponent::IsFocused()
99 {
100 	return sal_False;
101 }
102 
103 // -----------------------------------------------------------------------------
104 
105 sal_Bool OAccessibleMenuBaseComponent::IsVisible()
106 {
107 	return sal_False;
108 }
109 
110 // -----------------------------------------------------------------------------
111 
112 sal_Bool OAccessibleMenuBaseComponent::IsSelected()
113 {
114 	return sal_False;
115 }
116 
117 // -----------------------------------------------------------------------------
118 
119 sal_Bool OAccessibleMenuBaseComponent::IsChecked()
120 {
121 	return sal_False;
122 }
123 
124 // -----------------------------------------------------------------------------
125 
126 void OAccessibleMenuBaseComponent::SetStates()
127 {
128 	m_bEnabled = IsEnabled();
129 	m_bFocused = IsFocused();
130     m_bVisible = IsVisible();
131 	m_bSelected = IsSelected();
132 	m_bChecked = IsChecked();
133 }
134 
135 // -----------------------------------------------------------------------------
136 
137 void OAccessibleMenuBaseComponent::SetEnabled( sal_Bool bEnabled )
138 {
139 	if ( m_bEnabled != bEnabled )
140 	{
141         Any aOldValue[2], aNewValue[2];
142 		if ( m_bEnabled )
143         {
144             aOldValue[0] <<= AccessibleStateType::SENSITIVE;
145             aOldValue[1] <<= AccessibleStateType::ENABLED;
146         }
147 		else
148         {
149             aNewValue[0] <<= AccessibleStateType::ENABLED;
150             aNewValue[1] <<= AccessibleStateType::SENSITIVE;
151         }
152 		m_bEnabled = bEnabled;
153         NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[0], aNewValue[0] );
154         NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue[1], aNewValue[1] );
155 	}
156 }
157 
158 // -----------------------------------------------------------------------------
159 
160 void OAccessibleMenuBaseComponent::SetFocused( sal_Bool bFocused )
161 {
162 	if ( m_bFocused != bFocused )
163 	{
164 		Any aOldValue, aNewValue;
165 		if ( m_bFocused )
166 			aOldValue <<= AccessibleStateType::FOCUSED;
167 		else
168 			aNewValue <<= AccessibleStateType::FOCUSED;
169 		m_bFocused = bFocused;
170 		NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
171 	}
172 }
173 
174 // -----------------------------------------------------------------------------
175 
176 void OAccessibleMenuBaseComponent::SetVisible( sal_Bool bVisible )
177 {
178     if ( m_bVisible != bVisible )
179 	{
180 		Any aOldValue, aNewValue;
181         if ( m_bVisible )
182 			aOldValue <<= AccessibleStateType::VISIBLE;
183 		else
184 			aNewValue <<= AccessibleStateType::VISIBLE;
185         m_bVisible = bVisible;
186 		NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
187 	}
188 }
189 
190 // -----------------------------------------------------------------------------
191 
192 void OAccessibleMenuBaseComponent::SetSelected( sal_Bool bSelected )
193 {
194     if ( m_bSelected != bSelected )
195     {
196         Any aOldValue, aNewValue;
197         if ( m_bSelected )
198             aOldValue <<= AccessibleStateType::SELECTED;
199         else
200             aNewValue <<= AccessibleStateType::SELECTED;
201         m_bSelected = bSelected;
202         NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
203     }
204 }
205 
206 // -----------------------------------------------------------------------------
207 
208 void OAccessibleMenuBaseComponent::SetChecked( sal_Bool bChecked )
209 {
210 	if ( m_bChecked != bChecked )
211 	{
212 		Any aOldValue, aNewValue;
213 		if ( m_bChecked )
214 			aOldValue <<= AccessibleStateType::CHECKED;
215 		else
216 			aNewValue <<= AccessibleStateType::CHECKED;
217 		m_bChecked = bChecked;
218 		NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
219 	}
220 }
221 
222 // -----------------------------------------------------------------------------
223 
224 void OAccessibleMenuBaseComponent::UpdateEnabled( sal_Int32 i, sal_Bool bEnabled )
225 {
226 	if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
227 	{
228 		Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
229 		if ( xChild.is() )
230 		{
231 			OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
232 			if ( pComp )
233 				pComp->SetEnabled( bEnabled );
234 		}
235 	}
236 }
237 
238 // -----------------------------------------------------------------------------
239 
240 void OAccessibleMenuBaseComponent::UpdateFocused( sal_Int32 i, sal_Bool bFocused )
241 {
242     if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
243     {
244         Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
245         if ( xChild.is() )
246         {
247             OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
248             if ( pComp )
249                 pComp->SetFocused( bFocused );
250         }
251     }
252 }
253 
254 // -----------------------------------------------------------------------------
255 
256 void OAccessibleMenuBaseComponent::UpdateVisible()
257 {
258     SetVisible( IsVisible() );
259 	for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
260 	{
261 		Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
262 		if ( xChild.is() )
263 		{
264 			OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
265 			if ( pComp )
266                 pComp->SetVisible( pComp->IsVisible() );
267 		}
268 	}
269 }
270 
271 // -----------------------------------------------------------------------------
272 
273 void OAccessibleMenuBaseComponent::UpdateSelected( sal_Int32 i, sal_Bool bSelected )
274 {
275 	NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
276 
277 	if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
278 	{
279 		Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
280 		if ( xChild.is() )
281 		{
282 			OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
283 			if ( pComp )
284 				pComp->SetSelected( bSelected );
285 		}
286 	}
287 }
288 
289 // -----------------------------------------------------------------------------
290 
291 void OAccessibleMenuBaseComponent::UpdateChecked( sal_Int32 i, sal_Bool bChecked )
292 {
293 	if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
294 	{
295 		Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
296 		if ( xChild.is() )
297 		{
298 			OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
299 			if ( pComp )
300 				pComp->SetChecked( bChecked );
301 		}
302 	}
303 }
304 
305 // -----------------------------------------------------------------------------
306 
307 void OAccessibleMenuBaseComponent::UpdateAccessibleName( sal_Int32 i )
308 {
309 	if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
310 	{
311 		Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
312 		if ( xChild.is() )
313 		{
314 			OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xChild.get() );
315 			if ( pComp )
316 				pComp->SetAccessibleName( pComp->GetAccessibleName() );
317 		}
318 	}
319 }
320 
321 // -----------------------------------------------------------------------------
322 
323 void OAccessibleMenuBaseComponent::UpdateItemText( sal_Int32 i )
324 {
325 	if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
326 	{
327 		Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
328 		if ( xChild.is() )
329 		{
330 			OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xChild.get() );
331 			if ( pComp )
332 				pComp->SetItemText( pComp->GetItemText() );
333 		}
334 	}
335 }
336 
337 // -----------------------------------------------------------------------------
338 
339 sal_Int32 OAccessibleMenuBaseComponent::GetChildCount()
340 {
341 	return m_aAccessibleChildren.size();
342 }
343 
344 // -----------------------------------------------------------------------------
345 
346 Reference< XAccessible > OAccessibleMenuBaseComponent::GetChild( sal_Int32 i )
347 {
348 	Reference< XAccessible > xChild = m_aAccessibleChildren[i];
349 	if ( !xChild.is() )
350 	{
351 		if ( m_pMenu )
352 		{
353 			// create a new child
354 			OAccessibleMenuBaseComponent* pChild;
355 
356 			if ( m_pMenu->GetItemType( (sal_uInt16)i ) == MENUITEM_SEPARATOR )
357 			{
358 				pChild = new VCLXAccessibleMenuSeparator( m_pMenu, (sal_uInt16)i );
359 			}
360 			else
361 			{
362 				PopupMenu* pPopupMenu = m_pMenu->GetPopupMenu( m_pMenu->GetItemId( (sal_uInt16)i ) );
363 				if ( pPopupMenu )
364 				{
365 					pChild = new VCLXAccessibleMenu( m_pMenu, (sal_uInt16)i, pPopupMenu );
366 					pPopupMenu->SetAccessible( pChild );
367 				}
368 				else
369 				{
370 					pChild = new VCLXAccessibleMenuItem( m_pMenu, (sal_uInt16)i );
371 				}
372 			}
373 
374 			// set states
375 			pChild->SetStates();
376 
377 			xChild = pChild;
378 
379 			// insert into menu item list
380 			m_aAccessibleChildren[i] = xChild;
381 		}
382 	}
383 
384     return xChild;
385 }
386 
387 // -----------------------------------------------------------------------------
388 
389 Reference< XAccessible > OAccessibleMenuBaseComponent::GetChildAt( const awt::Point& rPoint )
390 {
391 	Reference< XAccessible > xChild;
392 	for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
393 	{
394 		Reference< XAccessible > xAcc = getAccessibleChild( i );
395 		if ( xAcc.is() )
396 		{
397 			Reference< XAccessibleComponent > xComp( xAcc->getAccessibleContext(), UNO_QUERY );
398 			if ( xComp.is() )
399 			{
400 				Rectangle aRect = VCLRectangle( xComp->getBounds() );
401 				Point aPos = VCLPoint( rPoint );
402 				if ( aRect.IsInside( aPos ) )
403 				{
404 					xChild = xAcc;
405 					break;
406 				}
407 			}
408 		}
409 	}
410 
411 	return xChild;
412 }
413 
414 // -----------------------------------------------------------------------------
415 
416 void OAccessibleMenuBaseComponent::InsertChild( sal_Int32 i )
417 {
418 	if ( i > (sal_Int32)m_aAccessibleChildren.size() )
419 		i = m_aAccessibleChildren.size();
420 
421 	if ( i >= 0 )
422 	{
423 		// insert entry in child list
424 		m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() );
425 
426 		// update item position of accessible children
427 		for ( sal_uInt32 j = i, nCount = m_aAccessibleChildren.size(); j < nCount; ++j )
428 		{
429 			Reference< XAccessible > xAcc( m_aAccessibleChildren[j] );
430 			if ( xAcc.is() )
431 			{
432 				OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xAcc.get() );
433 				if ( pComp )
434 					pComp->SetItemPos( (sal_uInt16)j );
435 			}
436 		}
437 
438 		// send accessible child event
439 		Reference< XAccessible > xChild( GetChild( i ) );
440 		if ( xChild.is() )
441 		{
442 			Any aOldValue, aNewValue;
443 			aNewValue <<= xChild;
444 			NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
445 		}
446 	}
447 }
448 
449 // -----------------------------------------------------------------------------
450 
451 void OAccessibleMenuBaseComponent::RemoveChild( sal_Int32 i )
452 {
453 	if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() )
454 	{
455 		// keep the accessible of the removed item
456 		Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
457 
458 		// remove entry in child list
459 		m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i );
460 
461 		// update item position of accessible children
462 		for ( sal_uInt32 j = i, nCount = m_aAccessibleChildren.size(); j < nCount; ++j )
463 		{
464 			Reference< XAccessible > xAcc( m_aAccessibleChildren[j] );
465 			if ( xAcc.is() )
466 			{
467 				OAccessibleMenuItemComponent* pComp = static_cast< OAccessibleMenuItemComponent* >( xAcc.get() );
468 				if ( pComp )
469 					pComp->SetItemPos( (sal_uInt16)j );
470 			}
471 		}
472 
473 		// send accessible child event
474 		if ( xChild.is() )
475 		{
476 			Any aOldValue, aNewValue;
477 			aOldValue <<= xChild;
478 			NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue );
479 
480 			Reference< XComponent > xComponent( xChild, UNO_QUERY );
481 			if ( xComponent.is() )
482 				xComponent->dispose();
483 		}
484 	}
485 }
486 
487 // -----------------------------------------------------------------------------
488 
489 sal_Bool OAccessibleMenuBaseComponent::IsHighlighted()
490 {
491 	return sal_False;
492 }
493 
494 // -----------------------------------------------------------------------------
495 
496 sal_Bool OAccessibleMenuBaseComponent::IsChildHighlighted()
497 {
498     sal_Bool bChildHighlighted = sal_False;
499 
500     for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
501     {
502         Reference< XAccessible > xChild( m_aAccessibleChildren[i] );
503         if ( xChild.is() )
504         {
505             OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xChild.get() );
506             if ( pComp && pComp->IsHighlighted() )
507             {
508                 bChildHighlighted = sal_True;
509                 break;
510             }
511         }
512     }
513 
514     return bChildHighlighted;
515 }
516 
517 // -----------------------------------------------------------------------------
518 
519 void OAccessibleMenuBaseComponent::SelectChild( sal_Int32 i )
520 {
521 	// open the menu
522 	if ( getAccessibleRole() == AccessibleRole::MENU && !IsPopupMenuOpen() )
523 		Click();
524 
525 	// highlight the child
526 	if ( m_pMenu )
527         m_pMenu->HighlightItem( (sal_uInt16)i );
528 }
529 
530 // -----------------------------------------------------------------------------
531 
532 void OAccessibleMenuBaseComponent::DeSelectAll()
533 {
534 	if ( m_pMenu )
535 		m_pMenu->DeHighlight();
536 }
537 
538 // -----------------------------------------------------------------------------
539 
540 sal_Bool OAccessibleMenuBaseComponent::IsChildSelected( sal_Int32 i )
541 {
542     sal_Bool bSelected = sal_False;
543 
544     if ( m_pMenu && m_pMenu->IsHighlighted( (sal_uInt16)i ) )
545         bSelected = sal_True;
546 
547     return bSelected;
548 }
549 
550 // -----------------------------------------------------------------------------
551 
552 void OAccessibleMenuBaseComponent::Select()
553 {
554 }
555 
556 // -----------------------------------------------------------------------------
557 
558 void OAccessibleMenuBaseComponent::DeSelect()
559 {
560 }
561 
562 // -----------------------------------------------------------------------------
563 
564 void OAccessibleMenuBaseComponent::Click()
565 {
566 }
567 
568 // -----------------------------------------------------------------------------
569 
570 sal_Bool OAccessibleMenuBaseComponent::IsPopupMenuOpen()
571 {
572     return sal_False;
573 }
574 
575 // -----------------------------------------------------------------------------
576 
577 IMPL_LINK( OAccessibleMenuBaseComponent, MenuEventListener, VclSimpleEvent*, pEvent )
578 {
579 	DBG_ASSERT( pEvent && pEvent->ISA( VclMenuEvent ), "OAccessibleMenuBaseComponent - Unknown MenuEvent!" );
580 	if ( pEvent && pEvent->ISA( VclMenuEvent ) )
581 	{
582 		DBG_ASSERT( ((VclMenuEvent*)pEvent)->GetMenu(), "OAccessibleMenuBaseComponent - Menu?" );
583 		ProcessMenuEvent( *(VclMenuEvent*)pEvent );
584 	}
585 	return 0;
586 }
587 
588 // -----------------------------------------------------------------------------
589 
590 void OAccessibleMenuBaseComponent::ProcessMenuEvent( const VclMenuEvent& rVclMenuEvent )
591 {
592 	sal_uInt16 nItemPos = rVclMenuEvent.GetItemPos();
593 
594 	switch ( rVclMenuEvent.GetId() )
595 	{
596         case VCLEVENT_MENU_SHOW:
597         case VCLEVENT_MENU_HIDE:
598         {
599             UpdateVisible();
600         }
601         break;
602 		case VCLEVENT_MENU_HIGHLIGHT:
603 		{
604             SetFocused( sal_False );
605             UpdateFocused( nItemPos, sal_True );
606             UpdateSelected( nItemPos, sal_True );
607         }
608 		break;
609 		case VCLEVENT_MENU_DEHIGHLIGHT:
610 		{
611             UpdateFocused( nItemPos, sal_False );
612             UpdateSelected( nItemPos, sal_False );
613         }
614 		break;
615 		case VCLEVENT_MENU_SUBMENUACTIVATE:
616 		{
617 		}
618 		break;
619 		case VCLEVENT_MENU_SUBMENUDEACTIVATE:
620 		{
621             UpdateFocused( nItemPos, sal_True );
622 		}
623 		break;
624 		case VCLEVENT_MENU_ENABLE:
625 		{
626 			UpdateEnabled( nItemPos, sal_True );
627 		}
628 		break;
629 		case VCLEVENT_MENU_DISABLE:
630 		{
631 			UpdateEnabled( nItemPos, sal_False );
632 		}
633 		break;
634 		case VCLEVENT_MENU_SUBMENUCHANGED:
635 		{
636 			RemoveChild( nItemPos );
637 			InsertChild( nItemPos );
638 		}
639 		break;
640 		case VCLEVENT_MENU_INSERTITEM:
641 		{
642 			InsertChild( nItemPos );
643 		}
644 		break;
645 		case VCLEVENT_MENU_REMOVEITEM:
646 		{
647 			RemoveChild( nItemPos );
648 		}
649 		break;
650 		case VCLEVENT_MENU_ACCESSIBLENAMECHANGED:
651 		{
652 			UpdateAccessibleName( nItemPos );
653 		}
654 		break;
655 		case VCLEVENT_MENU_ITEMTEXTCHANGED:
656 		{
657 			UpdateAccessibleName( nItemPos );
658 			UpdateItemText( nItemPos );
659 		}
660 		break;
661 		case VCLEVENT_MENU_ITEMCHECKED:
662 		{
663 			UpdateChecked( nItemPos, sal_True );
664 		}
665 		break;
666 		case VCLEVENT_MENU_ITEMUNCHECKED:
667 		{
668 			UpdateChecked( nItemPos, sal_False );
669 		}
670 		break;
671         case VCLEVENT_OBJECT_DYING:
672         {
673 			if ( m_pMenu )
674 			{
675 				m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
676 
677 				m_pMenu = NULL;
678 
679 				// dispose all menu items
680 				for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
681 				{
682 					Reference< XComponent > xComponent( m_aAccessibleChildren[i], UNO_QUERY );
683 					if ( xComponent.is() )
684 						xComponent->dispose();
685 				}
686 				m_aAccessibleChildren.clear();
687 			}
688         }
689         break;
690 		default:
691 		{
692 		}
693 		break;
694 	}
695 }
696 
697 // -----------------------------------------------------------------------------
698 // XInterface
699 // -----------------------------------------------------------------------------
700 
701 IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleMenuBaseComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleMenuBaseComponent_BASE )
702 
703 // -----------------------------------------------------------------------------
704 // XTypeProvider
705 // -----------------------------------------------------------------------------
706 
707 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleMenuBaseComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleMenuBaseComponent_BASE )
708 
709 // -----------------------------------------------------------------------------
710 // XComponent
711 // -----------------------------------------------------------------------------
712 
713 void OAccessibleMenuBaseComponent::disposing()
714 {
715 	AccessibleExtendedComponentHelper_BASE::disposing();
716 
717 	if ( m_pMenu )
718 	{
719 		m_pMenu->RemoveEventListener( LINK( this, OAccessibleMenuBaseComponent, MenuEventListener ) );
720 
721 		m_pMenu = NULL;
722 
723 		// dispose all menu items
724 		for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i )
725 		{
726 			Reference< XComponent > xComponent( m_aAccessibleChildren[i], UNO_QUERY );
727 			if ( xComponent.is() )
728 				xComponent->dispose();
729 		}
730 		m_aAccessibleChildren.clear();
731 	}
732 }
733 
734 // -----------------------------------------------------------------------------
735 // XServiceInfo
736 // -----------------------------------------------------------------------------
737 
738 sal_Bool OAccessibleMenuBaseComponent::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException)
739 {
740 	Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
741 	const ::rtl::OUString* pNames = aNames.getConstArray();
742 	const ::rtl::OUString* pEnd = pNames + aNames.getLength();
743 	for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
744 		;
745 
746 	return pNames != pEnd;
747 }
748 
749 // -----------------------------------------------------------------------------
750 // XAccessible
751 // -----------------------------------------------------------------------------
752 
753 Reference< XAccessibleContext > OAccessibleMenuBaseComponent::getAccessibleContext(  ) throw (RuntimeException)
754 {
755 	OExternalLockGuard aGuard( this );
756 
757 	return this;
758 }
759 
760 // -----------------------------------------------------------------------------
761 // XAccessibleContext
762 // -----------------------------------------------------------------------------
763 
764 Reference< XAccessibleStateSet > OAccessibleMenuBaseComponent::getAccessibleStateSet(  ) throw (RuntimeException)
765 {
766 	OExternalLockGuard aGuard( this );
767 
768 	utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
769 	Reference< XAccessibleStateSet > xSet = pStateSetHelper;
770 
771 	if ( !rBHelper.bDisposed && !rBHelper.bInDispose )
772 	{
773 		FillAccessibleStateSet( *pStateSetHelper );
774 	}
775 	else
776 	{
777         pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
778 	}
779 
780 	return xSet;
781 }
782 
783 // -----------------------------------------------------------------------------
784