1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxMenu, wxMenuBar, wxMenuItem 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:       wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  13 #pragma implementation "menu.h" 
  14 #pragma implementation "menuitem.h" 
  17 // ============================================================================ 
  18 // headers & declarations 
  19 // ============================================================================ 
  24 #include "wx/wxprec.h" 
  28 #include "wx/menuitem.h" 
  29 #include "wx/window.h" 
  34 #include "wx/mac/uma.h" 
  36 // other standard headers 
  37 // ---------------------- 
  40 #if !USE_SHARED_LIBRARY 
  41 IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
) 
  42 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
) 
  45 // the (popup) menu title has this special id 
  46 static const int idMenuTitle 
= -3; 
  47 static MenuItemIndex firstUserHelpMenuItem 
= 0 ; 
  49 const short kwxMacMenuBarResource 
= 1 ; 
  50 const short kwxMacAppleMenuId 
= 1 ; 
  53 // Find an item given the Macintosh Menu Reference 
  55 #if KEY_wxList_DEPRECATED 
  56 wxList 
wxWinMacMenuList(wxKEY_INTEGER
); 
  57 wxMenu 
*wxFindMenuFromMacMenu(MenuRef inMenuRef
) 
  59     wxNode 
*node 
= wxWinMacMenuList
.Find((long)inMenuRef
); 
  62     return (wxMenu 
*)node
->GetData(); 
  65 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu 
*menu
) ; 
  66 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu 
*menu
) 
  68     // adding NULL MenuRef is (first) surely a result of an error and 
  69     // (secondly) breaks menu command processing 
  70     wxCHECK_RET( inMenuRef 
!= (MenuRef
) NULL
, wxT("attempt to add a NULL MenuRef to menu list") ); 
  72     if ( !wxWinMacMenuList
.Find((long)inMenuRef
) ) 
  73         wxWinMacMenuList
.Append((long)inMenuRef
, menu
); 
  76 void wxRemoveMacMenuAssociation(wxMenu 
*menu
) ; 
  77 void wxRemoveMacMenuAssociation(wxMenu 
*menu
) 
  79     wxWinMacMenuList
.DeleteObject(menu
); 
  83 WX_DECLARE_HASH_MAP(MenuRef
, wxMenu
*, wxPointerHash
, wxPointerEqual
, MacMenuMap
); 
  85 static MacMenuMap wxWinMacMenuList
; 
  87 wxMenu 
*wxFindMenuFromMacMenu(MenuRef inMenuRef
) 
  89     MacMenuMap::iterator node 
= wxWinMacMenuList
.find(inMenuRef
); 
  91     return (node 
== wxWinMacMenuList
.end()) ? NULL 
: node
->second
; 
  94 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu 
*menu
) ; 
  95 void wxAssociateMenuWithMacMenu(MenuRef inMenuRef
, wxMenu 
*menu
) 
  97     // adding NULL MenuRef is (first) surely a result of an error and 
  98     // (secondly) breaks menu command processing 
  99     wxCHECK_RET( inMenuRef 
!= (MenuRef
) NULL
, wxT("attempt to add a NULL MenuRef to menu list") ); 
 101     wxWinMacMenuList
[inMenuRef
] = menu
; 
 104 void wxRemoveMacMenuAssociation(wxMenu 
*menu
) ; 
 105 void wxRemoveMacMenuAssociation(wxMenu 
*menu
) 
 107    // iterate over all the elements in the class 
 108     MacMenuMap::iterator it
; 
 109     for ( it 
= wxWinMacMenuList
.begin(); it 
!= wxWinMacMenuList
.end(); ++it 
) 
 111         if ( it
->second 
== menu 
) 
 113             wxWinMacMenuList
.erase(it
); 
 118 #endif // deprecated wxList 
 120 // ============================================================================ 
 122 // ============================================================================ 
 123 static void wxMenubarUnsetInvokingWindow( wxMenu 
*menu 
) ; 
 124 static void wxMenubarSetInvokingWindow( wxMenu 
*menu
, wxWindow 
*win 
); 
 128 // Construct a menu with optional title (then use append) 
 131 short wxMenu::s_macNextMenuId 
= 3 ; 
 133 short wxMenu::s_macNextMenuId 
= 2 ; 
 138 _wxMenuAt(const wxMenuList 
&menuList
, size_t pos
) 
 140     wxMenuList::compatibility_iterator menuIter 
= menuList
.GetFirst(); 
 142     while (pos
-- > 0) menuIter 
= menuIter
->GetNext(); 
 144     return menuIter
->GetData() ; 
 150     m_startRadioGroup 
= -1; 
 153     m_macMenuId 
= s_macNextMenuId
++; 
 154     m_hMenu 
= UMANewMenu(m_macMenuId
, m_title
, wxFont::GetDefaultEncoding() ); 
 158         wxLogLastError(wxT("UMANewMenu failed")); 
 161     wxAssociateMenuWithMacMenu( (MenuRef
)m_hMenu 
, this ) ; 
 163     // if we have a title, insert it in the beginning of the menu 
 166         Append(idMenuTitle
, m_title
) ; 
 173     wxRemoveMacMenuAssociation( this ) ; 
 174     if (MAC_WXHMENU(m_hMenu
)) 
 175         ::DisposeMenu(MAC_WXHMENU(m_hMenu
)); 
 180     // not available on the mac platform 
 183 void wxMenu::Attach(wxMenuBarBase 
*menubar
) 
 185     wxMenuBase::Attach(menubar
); 
 190 // function appends a new item or submenu to the menu 
 191 // append a new item or submenu to the menu 
 192 bool wxMenu::DoInsertOrAppend(wxMenuItem 
*pItem
, size_t pos
) 
 194     wxASSERT_MSG( pItem 
!= NULL
, wxT("can't append NULL item to the menu") ); 
 196     if ( pItem
->IsSeparator() ) 
 198         if ( pos 
== (size_t)-1 ) 
 199             MacAppendMenu(MAC_WXHMENU(m_hMenu
), "\p-"); 
 201             MacInsertMenuItem(MAC_WXHMENU(m_hMenu
), "\p-" , pos
); 
 205         wxMenu 
*pSubMenu 
= pItem
->GetSubMenu() ; 
 206         if ( pSubMenu 
!= NULL 
) 
 208                wxASSERT_MSG( pSubMenu
->m_hMenu 
!= NULL 
, wxT("invalid submenu added")); 
 209             pSubMenu
->m_menuParent 
= this ; 
 211             if (wxMenuBar::MacGetInstalledMenuBar() == GetMenuBar()) 
 213                 pSubMenu
->MacBeforeDisplay( true ) ; 
 216             if ( pos 
== (size_t)-1 ) 
 217                 UMAAppendSubMenuItem(MAC_WXHMENU(m_hMenu
), pItem
->GetText(), wxFont::GetDefaultEncoding() , pSubMenu
->m_macMenuId
); 
 219                 UMAInsertSubMenuItem(MAC_WXHMENU(m_hMenu
), pItem
->GetText(), wxFont::GetDefaultEncoding()  , pos
, pSubMenu
->m_macMenuId
); 
 220             pItem
->UpdateItemBitmap() ; 
 221             pItem
->UpdateItemStatus() ; 
 225             if ( pos 
== (size_t)-1 ) 
 227                 UMAAppendMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a") , wxFont::GetDefaultEncoding() ); 
 228                 pos 
= CountMenuItems(MAC_WXHMENU(m_hMenu
)) ; 
 232                 // MacOS counts menu items from 1 and inserts after, therefore having the 
 233                 // same effect as wx 0 based and inserting before, we must correct pos 
 234                 // after however for updates to be correct 
 235                 UMAInsertMenuItem(MAC_WXHMENU(m_hMenu
), wxT("a"), wxFont::GetDefaultEncoding(), pos
); 
 239             SetMenuItemCommandID( MAC_WXHMENU(m_hMenu
) , pos 
, pItem
->GetId() ) ; 
 240             SetMenuItemRefCon( MAC_WXHMENU(m_hMenu
) , pos 
, (UInt32
) pItem 
) ; 
 241             pItem
->UpdateItemText() ; 
 242             pItem
->UpdateItemBitmap() ; 
 243             pItem
->UpdateItemStatus() ; 
 245               if ( pItem
->GetId() == idMenuTitle 
) 
 247                 UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , pos 
, false ) ; 
 251     // if we're already attached to the menubar, we must update it 
 254         GetMenuBar()->Refresh(); 
 259 void wxMenu::EndRadioGroup() 
 261     // we're not inside a radio group any longer 
 262     m_startRadioGroup 
= -1; 
 265 wxMenuItem
* wxMenu::DoAppend(wxMenuItem 
*item
) 
 267     wxCHECK_MSG( item
, NULL
, _T("NULL item in wxMenu::DoAppend") ); 
 271     if ( item
->GetKind() == wxITEM_RADIO 
) 
 273         int count 
= GetMenuItemCount(); 
 275         if ( m_startRadioGroup 
== -1 ) 
 277             // start a new radio group 
 278             m_startRadioGroup 
= count
; 
 280             // for now it has just one element 
 281             item
->SetAsRadioGroupStart(); 
 282             item
->SetRadioGroupEnd(m_startRadioGroup
); 
 284             // ensure that we have a checked item in the radio group 
 287         else // extend the current radio group 
 289             // we need to update its end item 
 290             item
->SetRadioGroupStart(m_startRadioGroup
); 
 291             wxMenuItemList::compatibility_iterator node 
= GetMenuItems().Item(m_startRadioGroup
); 
 295                 node
->GetData()->SetRadioGroupEnd(count
); 
 299                 wxFAIL_MSG( _T("where is the radio group start item?") ); 
 303     else // not a radio item 
 308     if ( !wxMenuBase::DoAppend(item
) || !DoInsertOrAppend(item
) ) 
 315         // check the item initially 
 322 wxMenuItem
* wxMenu::DoInsert(size_t pos
, wxMenuItem 
*item
) 
 324     if (wxMenuBase::DoInsert(pos
, item
) && DoInsertOrAppend(item
, pos
)) 
 330 wxMenuItem 
*wxMenu::DoRemove(wxMenuItem 
*item
) 
 332     // we need to find the items position in the child list 
 334     wxMenuItemList::compatibility_iterator node 
= GetMenuItems().GetFirst(); 
 335     for ( pos 
= 0; node
; pos
++ ) 
 337         if ( node
->GetData() == item 
) 
 340         node 
= node
->GetNext(); 
 343     // DoRemove() (unlike Remove) can only be called for existing item! 
 344     wxCHECK_MSG( node
, NULL
, wxT("bug in wxMenu::Remove logic") ); 
 346     ::DeleteMenuItem(MAC_WXHMENU(m_hMenu
) , pos 
+ 1); 
 350         // otherwise, the change won't be visible 
 351         GetMenuBar()->Refresh(); 
 354     // and from internal data structures 
 355     return wxMenuBase::DoRemove(item
); 
 358 void wxMenu::SetTitle(const wxString
& label
) 
 361     UMASetMenuTitle(MAC_WXHMENU(m_hMenu
) , label 
, wxFont::GetDefaultEncoding() ) ; 
 363 bool wxMenu::ProcessCommand(wxCommandEvent 
& event
) 
 365     bool processed 
= FALSE
; 
 367     // Try the menu's event handler 
 368     if ( !processed 
&& GetEventHandler()) 
 370         processed 
= GetEventHandler()->ProcessEvent(event
); 
 373     // Try the window the menu was popped up from (and up through the 
 375     wxWindow 
*win 
= GetInvokingWindow(); 
 376     if ( !processed 
&& win 
) 
 377         processed 
= win
->GetEventHandler()->ProcessEvent(event
); 
 383 // --------------------------------------------------------------------------- 
 385 // --------------------------------------------------------------------------- 
 387 wxWindow 
*wxMenu::GetWindow() const 
 389     if ( m_invokingWindow 
!= NULL 
) 
 390         return m_invokingWindow
; 
 391     else if ( GetMenuBar() != NULL
) 
 392         return (wxWindow 
*) GetMenuBar()->GetFrame(); 
 397 // helper functions returning the mac menu position for a certain item, note that this is 
 398 // mac-wise 1 - based, i.e. the first item has index 1 whereas on MSWin it has pos 0 
 400 int wxMenu::MacGetIndexFromId( int id 
) 
 403     wxMenuItemList::compatibility_iterator node 
= GetMenuItems().GetFirst(); 
 404     for ( pos 
= 0; node
; pos
++ ) 
 406         if ( node
->GetData()->GetId() == id 
) 
 409         node 
= node
->GetNext(); 
 418 int wxMenu::MacGetIndexFromItem( wxMenuItem 
*pItem 
) 
 421     wxMenuItemList::compatibility_iterator node 
= GetMenuItems().GetFirst(); 
 422     for ( pos 
= 0; node
; pos
++ ) 
 424         if ( node
->GetData() == pItem 
) 
 427         node 
= node
->GetNext(); 
 436 void wxMenu::MacEnableMenu( bool bDoEnable 
) 
 438     UMAEnableMenuItem(MAC_WXHMENU(m_hMenu
) , 0 , bDoEnable 
) ; 
 443 // MacOS needs to know about submenus somewhere within this menu 
 444 // before it can be displayed , also hide special menu items like preferences 
 445 // that are handled by the OS 
 446 void wxMenu::MacBeforeDisplay( bool isSubMenu 
) 
 448     wxMenuItem
* previousItem 
= NULL 
; 
 450     wxMenuItemList::compatibility_iterator node
; 
 452     for (pos 
= 0, node 
= GetMenuItems().GetFirst(); node
; node 
= node
->GetNext(), pos
++) 
 454         item 
= (wxMenuItem 
*)node
->GetData(); 
 455         wxMenu
* subMenu 
= item
->GetSubMenu() ; 
 458             subMenu
->MacBeforeDisplay( true ) ; 
 463             if ( UMAGetSystemVersion() >= 0x1000 ) 
 465                 // what we do here is to hide the special items which are 
 466                 // shown in the application menu anyhow -- it doesn't make 
 467                 // sense to show them in their normal place as well 
 468                 if ( item
->GetId() == wxApp::s_macPreferencesMenuItemId 
|| 
 469                         item
->GetId() == wxApp::s_macExitMenuItemId 
) 
 471                     ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ), 
 472                                               pos 
+ 1, kMenuItemAttrHidden
, 0 ); 
 474                     // also check for a separator which was used just to 
 475                     // separate this item from the others, so don't leave 
 476                     // separator at the menu start or end nor 2 consecutive 
 478                     wxMenuItemList::compatibility_iterator nextNode 
= node
->GetNext(); 
 479                     wxMenuItem 
*next 
= nextNode 
? nextNode
->GetData() : NULL
; 
 482                     if ( !previousItem 
&& next 
&& next
->IsSeparator() ) 
 484                         // next (i.e. second as we must be first) item is 
 485                         // the separator to hide 
 486                         wxASSERT_MSG( pos 
== 0, _T("should be the menu start") ); 
 489                     else if ( GetMenuItems().GetCount() == pos 
+ 1 && 
 490                                 previousItem 
!= NULL 
&& 
 491                                     previousItem
->IsSeparator() ) 
 493                         // prev item is a trailing separator we want to hide 
 496                     else if ( previousItem 
&& previousItem
->IsSeparator() && 
 497                                 next 
&& next
->IsSeparator() ) 
 499                         // two consecutive separators, this is one too many 
 502                     else // no separators to hide 
 509                         // hide the separator as well 
 510                         ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ), 
 517             #endif // TARGET_CARBON 
 519         previousItem 
= item 
; 
 523         ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1); 
 526 // undo all changes from the MacBeforeDisplay call 
 527 void wxMenu::MacAfterDisplay( bool isSubMenu 
) 
 530         ::DeleteMenu(MacGetMenuId()); 
 532     wxMenuItem
* previousItem 
= NULL 
; 
 534     wxMenuItemList::compatibility_iterator node
; 
 536     for (pos 
= 0, node 
= GetMenuItems().GetFirst(); node
; node 
= node
->GetNext(), pos
++) 
 538         item 
= (wxMenuItem 
*)node
->GetData(); 
 539         wxMenu
* subMenu 
= item
->GetSubMenu() ; 
 542             subMenu
->MacAfterDisplay( true ) ; 
 546             // no need to undo hidings 
 548         previousItem 
= item 
; 
 556 Mac Implementation note : 
 558 The Mac has only one global menubar, so we attempt to install the currently 
 559 active menubar from a frame, we currently don't take into account mdi-frames 
 560 which would ask for menu-merging 
 562 Secondly there is no mac api for changing a menubar that is not the current 
 563 menubar, so we have to wait for preparing the actual menubar until the 
 564 wxMenubar is to be used 
 566 We can in subsequent versions use MacInstallMenuBar to provide some sort of 
 567 auto-merge for MDI in case this will be necessary 
 571 wxMenuBar
* wxMenuBar::s_macInstalledMenuBar 
= NULL 
; 
 572 wxMenuBar
* wxMenuBar::s_macCommonMenuBar 
= NULL 
; 
 574 void wxMenuBar::Init() 
 576     m_eventHandler 
= this; 
 577     m_menuBarFrame 
= NULL
; 
 578     m_invokingWindow 
= (wxWindow
*) NULL
; 
 581 wxMenuBar::wxMenuBar() 
 586 wxMenuBar::wxMenuBar( long WXUNUSED(style
) ) 
 592 wxMenuBar::wxMenuBar(int count
, wxMenu 
*menus
[], const wxString titles
[]) 
 596     m_titles
.Alloc(count
); 
 598     for ( int i 
= 0; i 
< count
; i
++ ) 
 600         m_menus
.Append(menus
[i
]); 
 601         m_titles
.Add(titles
[i
]); 
 603         menus
[i
]->Attach(this); 
 607 wxMenuBar::~wxMenuBar() 
 609     if (s_macCommonMenuBar 
== this) 
 610         s_macCommonMenuBar 
= NULL
; 
 611     if (s_macInstalledMenuBar 
== this) 
 614         s_macInstalledMenuBar 
= NULL
; 
 619 void wxMenuBar::Refresh(bool WXUNUSED(eraseBackground
), const wxRect 
*WXUNUSED(rect
)) 
 621     wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") ); 
 626 void wxMenuBar::MacInstallMenuBar() 
 628     if ( s_macInstalledMenuBar 
== this ) 
 631     MenuBarHandle menubar 
= NULL 
; 
 632 #if TARGET_API_MAC_OSX 
 633     menubar 
= NewHandleClear( 6 /* sizeof( MenuBarHeader ) */ ) ; 
 635     menubar 
= NewHandleClear( 12 ) ; 
 636     (*menubar
)[3] = 0x0a ; 
 638     ::SetMenuBar( menubar 
) ; 
 639     DisposeMenuBar( menubar 
) ; 
 640     MenuHandle appleMenu 
= NULL 
; 
 641     char appleMenuTitle
[3] = { 01 , kMenuAppleLogoFilledGlyph 
, 0 } ; 
 643     verify_noerr( CreateNewMenu( kwxMacAppleMenuId 
, 0 , &appleMenu 
) ) ; 
 644     verify_noerr( SetMenuTitle( appleMenu 
, (ConstStr255Param
) appleMenuTitle 
) ); 
 646     // Add About/Preferences separator only on OS X 
 647     // KH/RN: Separator is always present on 10.3 but not on 10.2 
 648     // However, the change from 10.2 to 10.3 suggests it is preferred 
 649 #if TARGET_API_MAC_OSX 
 650     MacInsertMenuItem( appleMenu 
, "\p-" , 0 ) ; 
 653     MacInsertMenuItem( appleMenu 
, "\pAbout..." , 0 ) ; 
 654     MacInsertMenu( appleMenu 
, 0 ) ; 
 656     // clean-up the help menu before adding new items 
 657     MenuHandle mh 
= NULL 
; 
 658     if ( UMAGetHelpMenu( &mh 
, &firstUserHelpMenuItem
) == noErr 
) 
 660         for ( int i 
= CountMenuItems( mh 
) ; i 
>= firstUserHelpMenuItem 
; --i 
) 
 662             DeleteMenuItem( mh 
, i 
) ; 
 670     if ( UMAGetSystemVersion() >= 0x1000 && wxApp::s_macPreferencesMenuItemId
) 
 672         wxMenuItem 
*item 
= FindItem( wxApp::s_macPreferencesMenuItemId 
, NULL 
) ; 
 673         if ( item 
== NULL 
|| !(item
->IsEnabled()) ) 
 674             DisableMenuCommand( NULL 
, kHICommandPreferences 
) ; 
 676             EnableMenuCommand( NULL 
, kHICommandPreferences 
) ; 
 679        wxMenuList::compatibility_iterator menuIter 
= m_menus
.GetFirst(); 
 681        for (size_t i 
= 0; i 
< m_menus
.GetCount(); i
++, menuIter 
= menuIter
->GetNext()) 
 683         wxMenuItemList::compatibility_iterator node
; 
 686         wxMenu
* menu 
= menuIter
->GetData() , *subMenu 
= NULL 
; 
 688         if( m_titles
[i
] == wxT("?") || m_titles
[i
] == wxT("&?")  || m_titles
[i
] == wxApp::s_macHelpMenuTitleName 
) 
 695               for (pos 
= 0 , node 
= menu
->GetMenuItems().GetFirst(); node
; node 
= node
->GetNext(), pos
++) 
 697                  item 
= (wxMenuItem 
*)node
->GetData(); 
 698                  subMenu 
= item
->GetSubMenu() ; 
 701                     // we don't support hierarchical menus in the help menu yet 
 705                     if ( item
->IsSeparator() ) 
 708                             MacAppendMenu(mh
, "\p-" ); 
 712                         wxAcceleratorEntry
* entry 
= wxGetAccelFromString( item
->GetText() ) ; 
 714                         if ( item
->GetId() == wxApp::s_macAboutMenuItemId 
) 
 716                                 UMASetMenuItemText( GetMenuHandle( kwxMacAppleMenuId 
) , 1 , item
->GetText() , wxFont::GetDefaultEncoding() ); 
 717                                 UMAEnableMenuItem( GetMenuHandle( kwxMacAppleMenuId 
) , 1 , true ); 
 718                                 SetMenuItemCommandID( GetMenuHandle( kwxMacAppleMenuId 
) , 1 , item
->GetId() ) ; 
 719                                 SetMenuItemRefCon(GetMenuHandle( kwxMacAppleMenuId 
) , 1 , (UInt32
)item 
) ; 
 720                                 UMASetMenuItemShortcut( GetMenuHandle( kwxMacAppleMenuId 
) , 1 , entry 
) ; 
 726                                 UMAAppendMenuItem(mh
, item
->GetText()  , wxFont::GetDefaultEncoding(), entry
); 
 727                                 SetMenuItemCommandID( mh 
, CountMenuItems(mh
) , item
->GetId() ) ; 
 728                                 SetMenuItemRefCon( mh 
, CountMenuItems(mh
) , (UInt32
)item 
) ; 
 739             UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , m_titles
[i
], m_font
.GetEncoding()  ) ; 
 740             menu
->MacBeforeDisplay(false) ; 
 741             ::InsertMenu(MAC_WXHMENU(_wxMenuAt(m_menus
, i
)->GetHMenu()), 0); 
 745     s_macInstalledMenuBar 
= this; 
 748 void wxMenuBar::EnableTop(size_t pos
, bool enable
) 
 750     wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") ); 
 751     _wxMenuAt(m_menus
, pos
)->MacEnableMenu( enable 
) ; 
 755 bool wxMenuBar::Enable( bool enable
) 
 757     wxCHECK_MSG( IsAttached(), false, wxT("doesn't work with unattached menubars") ); 
 759     for (i 
= 0; i 
< GetMenuCount(); i
++) 
 761         EnableTop(i
, enable
); 
 766 void wxMenuBar::SetLabelTop(size_t pos
, const wxString
& label
) 
 768     wxCHECK_RET( pos 
< GetMenuCount(), wxT("invalid menu index") ); 
 770     m_titles
[pos
] = label
; 
 777     _wxMenuAt(m_menus
, pos
)->SetTitle( label 
) ; 
 779     if (wxMenuBar::s_macInstalledMenuBar 
== this) // are we currently installed ? 
 781         ::SetMenuBar( GetMenuBar() ) ; 
 786 wxString 
wxMenuBar::GetLabelTop(size_t pos
) const 
 788     wxCHECK_MSG( pos 
< GetMenuCount(), wxEmptyString
, 
 789                  wxT("invalid menu index in wxMenuBar::GetLabelTop") ); 
 791     return m_titles
[pos
]; 
 794 int wxMenuBar::FindMenu(const wxString
& title
) 
 796     wxString menuTitle 
= wxStripMenuCodes(title
); 
 798     size_t count 
= GetMenuCount(); 
 799     for ( size_t i 
= 0; i 
< count
; i
++ ) 
 801         wxString title 
= wxStripMenuCodes(m_titles
[i
]); 
 802         if ( menuTitle 
== title 
) 
 811 // --------------------------------------------------------------------------- 
 812 // wxMenuBar construction 
 813 // --------------------------------------------------------------------------- 
 815 wxMenu 
*wxMenuBar::Replace(size_t pos
, wxMenu 
*menu
, const wxString
& title
) 
 817     wxMenu 
*menuOld 
= wxMenuBarBase::Replace(pos
, menu
, title
); 
 820     m_titles
[pos
] = title
; 
 824         if (s_macInstalledMenuBar 
== this) 
 826             menuOld
->MacAfterDisplay( false ) ; 
 827             ::DeleteMenu( menuOld
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ; 
 829                 menu
->MacBeforeDisplay( false ) ; 
 830                 UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title 
, m_font
.GetEncoding() ) ; 
 831                 if ( pos 
== m_menus
.GetCount() - 1) 
 833                     ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ; 
 837                     ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ; 
 844     if (m_invokingWindow
) 
 845         wxMenubarSetInvokingWindow( menu
, m_invokingWindow 
); 
 850 bool wxMenuBar::Insert(size_t pos
, wxMenu 
*menu
, const wxString
& title
) 
 852     if ( !wxMenuBarBase::Insert(pos
, menu
, title
) ) 
 855     m_titles
.Insert(title
, pos
); 
 857     UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title 
, m_font
.GetEncoding() ) ; 
 859     if ( IsAttached() && s_macInstalledMenuBar 
== this ) 
 861         if (s_macInstalledMenuBar 
== this) 
 863             menu
->MacBeforeDisplay( false ) ; 
 864             if ( pos 
== (size_t) -1  || pos 
+ 1 == m_menus
.GetCount() ) 
 866                 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ; 
 870                 ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , _wxMenuAt(m_menus
, pos
+1)->MacGetMenuId() ) ; 
 875     if (m_invokingWindow
) 
 876         wxMenubarSetInvokingWindow( menu
, m_invokingWindow 
); 
 881 wxMenu 
*wxMenuBar::Remove(size_t pos
) 
 883     wxMenu 
*menu 
= wxMenuBarBase::Remove(pos
); 
 889         if (s_macInstalledMenuBar 
== this) 
 891             ::DeleteMenu( menu
->MacGetMenuId() /* m_menus[pos]->MacGetMenuId() */ ) ; 
 897     m_titles
.RemoveAt(pos
); 
 902 bool wxMenuBar::Append(wxMenu 
*menu
, const wxString
& title
) 
 904     WXHMENU submenu 
= menu 
? menu
->GetHMenu() : 0; 
 905     wxCHECK_MSG( submenu
, FALSE
, wxT("can't append invalid menu to menubar") ); 
 907     if ( !wxMenuBarBase::Append(menu
, title
) ) 
 912     UMASetMenuTitle( MAC_WXHMENU(menu
->GetHMenu()) , title 
, m_font
.GetEncoding() ) ; 
 916         if (s_macInstalledMenuBar 
== this) 
 918             menu
->MacBeforeDisplay( false ) ; 
 919             ::InsertMenu( MAC_WXHMENU(menu
->GetHMenu()) , 0 ) ; 
 925     // m_invokingWindow is set after wxFrame::SetMenuBar(). This call enables 
 926     // adding menu later on. 
 927     if (m_invokingWindow
) 
 928         wxMenubarSetInvokingWindow( menu
, m_invokingWindow 
); 
 933 static void wxMenubarUnsetInvokingWindow( wxMenu 
*menu 
) 
 935     menu
->SetInvokingWindow( (wxWindow
*) NULL 
); 
 937     wxMenuItemList::compatibility_iterator node 
= menu
->GetMenuItems().GetFirst(); 
 940         wxMenuItem 
*menuitem 
= node
->GetData(); 
 941         if (menuitem
->IsSubMenu()) 
 942             wxMenubarUnsetInvokingWindow( menuitem
->GetSubMenu() ); 
 943         node 
= node
->GetNext(); 
 947 static void wxMenubarSetInvokingWindow( wxMenu 
*menu
, wxWindow 
*win 
) 
 949     menu
->SetInvokingWindow( win 
); 
 951     wxMenuItemList::compatibility_iterator node 
= menu
->GetMenuItems().GetFirst(); 
 954         wxMenuItem 
*menuitem 
= node
->GetData(); 
 955         if (menuitem
->IsSubMenu()) 
 956             wxMenubarSetInvokingWindow( menuitem
->GetSubMenu() , win 
); 
 957         node 
= node
->GetNext(); 
 961 void wxMenuBar::UnsetInvokingWindow() 
 963     m_invokingWindow 
= (wxWindow
*) NULL
; 
 964     wxMenuList::compatibility_iterator node 
= m_menus
.GetFirst(); 
 967         wxMenu 
*menu 
= node
->GetData(); 
 968         wxMenubarUnsetInvokingWindow( menu 
); 
 969         node 
= node
->GetNext(); 
 973 void wxMenuBar::SetInvokingWindow(wxFrame 
*frame
) 
 975     m_invokingWindow 
= frame
; 
 976     wxMenuList::compatibility_iterator node 
= m_menus
.GetFirst(); 
 979         wxMenu 
*menu 
= node
->GetData(); 
 980         wxMenubarSetInvokingWindow( menu
, frame 
); 
 981         node 
= node
->GetNext(); 
 985 void wxMenuBar::Detach() 
 987     wxMenuBarBase::Detach() ; 
 990 void wxMenuBar::Attach(wxFrame 
*frame
) 
 992     wxMenuBarBase::Attach( frame 
) ; 
 994 // --------------------------------------------------------------------------- 
 995 // wxMenuBar searching for menu items 
 996 // --------------------------------------------------------------------------- 
 998 // Find the itemString in menuString, and return the item id or wxNOT_FOUND 
 999 int wxMenuBar::FindMenuItem(const wxString
& menuString
, 
1000                             const wxString
& itemString
) const 
1002     wxString menuLabel 
= wxStripMenuCodes(menuString
); 
1003     size_t count 
= GetMenuCount(); 
1004     for ( size_t i 
= 0; i 
< count
; i
++ ) 
1006         wxString title 
= wxStripMenuCodes(m_titles
[i
]); 
1007         if ( menuLabel 
== title 
) 
1008             return _wxMenuAt(m_menus
, i
)->FindItem(itemString
); 
1014 wxMenuItem 
*wxMenuBar::FindItem(int id
, wxMenu 
**itemMenu
) const 
1019     wxMenuItem 
*item 
= NULL
; 
1020     size_t count 
= GetMenuCount(); 
1021     for ( size_t i 
= 0; !item 
&& (i 
< count
); i
++ ) 
1023         item 
= _wxMenuAt(m_menus
, i
)->FindItem(id
, itemMenu
);