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