1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        common/menucmn.cpp 
   3 // Purpose:     wxMenu and wxMenuBar methods common to all ports 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) wxWindows team 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "menubase.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  41 // ---------------------------------------------------------------------------- 
  43 // ---------------------------------------------------------------------------- 
  45 #include "wx/listimpl.cpp" 
  47 WX_DEFINE_LIST(wxMenuList
); 
  48 WX_DEFINE_LIST(wxMenuItemList
); 
  50 // ============================================================================ 
  52 // ============================================================================ 
  54 // ---------------------------------------------------------------------------- 
  56 // ---------------------------------------------------------------------------- 
  58 wxMenuItemBase::wxMenuItemBase(wxMenu 
*parentMenu
, 
  67     wxASSERT_MSG( parentMenu 
!= NULL
, wxT("menuitem should have a menu") ); 
  69     m_parentMenu  
= parentMenu
; 
  77     if (m_id 
== wxID_SEPARATOR
) 
  78         m_kind 
= wxITEM_SEPARATOR
; 
  81 wxMenuItemBase::~wxMenuItemBase() 
  88 static inline bool CompareAccelString(const wxString
& str
, const wxChar 
*accel
) 
  91     return str 
== accel 
|| str 
== wxGetTranslation(accel
); 
  97 // return wxAcceleratorEntry for the given menu string or NULL if none 
  99 wxAcceleratorEntry 
*wxGetAccelFromString(const wxString
& label
) 
 101     // check for accelerators: they are given after '\t' 
 102     int posTab 
= label
.Find(wxT('\t')); 
 103     if ( posTab 
!= wxNOT_FOUND 
) { 
 104         // parse the accelerator string 
 106         int accelFlags 
= wxACCEL_NORMAL
; 
 108         for ( size_t n 
= (size_t)posTab 
+ 1; n 
< label
.Len(); n
++ ) { 
 109             if ( (label
[n
] == '+') || (label
[n
] == '-') ) { 
 110                 if ( CompareAccelString(current
, wxTRANSLATE("ctrl")) ) 
 111                     accelFlags 
|= wxACCEL_CTRL
; 
 112                 else if ( CompareAccelString(current
, wxTRANSLATE("alt")) ) 
 113                     accelFlags 
|= wxACCEL_ALT
; 
 114                 else if ( CompareAccelString(current
, wxTRANSLATE("shift")) ) 
 115                     accelFlags 
|= wxACCEL_SHIFT
; 
 117                     // we may have "Ctrl-+", for example, but we still want to 
 118                     // catch typos like "Crtl-A" so only give the warning if we 
 119                     // have something before the current '+' or '-', else take 
 120                     // it as a literal symbol 
 121                     if ( current
.empty() ) 
 125                         // skip clearing it below 
 130                         wxLogDebug(wxT("Unknown accel modifier: '%s'"), 
 138                 current 
+= (wxChar
) wxTolower(label
[n
]); 
 142         if ( current
.IsEmpty() ) { 
 143             wxLogDebug(wxT("No accel key found, accel string ignored.")); 
 146             if ( current
.Len() == 1 ) { 
 148                 keyCode 
= current
[0U]; 
 150                 // Only call wxToupper if control, alt, or shift is held down, 
 151                 // otherwise lower case accelerators won't work. 
 152                 if (accelFlags 
!= wxACCEL_NORMAL
) { 
 153                     keyCode 
= wxToupper(keyCode
); 
 157                 // is it a function key? 
 158                 if ( current
[0U] == 'f' && wxIsdigit(current
[1U]) && 
 159                      (current
.Len() == 2 || 
 160                      (current
.Len() == 3 && wxIsdigit(current
[2U]))) ) { 
 162                     wxSscanf(current
.c_str() + 1, wxT("%d"), &n
); 
 164                     keyCode 
= WXK_F1 
+ n 
- 1; 
 167                     // several special cases 
 169                     if ( current 
== wxT("DEL") ) 
 170                         keyCode 
= WXK_DELETE
; 
 171                     else if ( current 
== wxT("DELETE") ) 
 172                         keyCode 
= WXK_DELETE
; 
 173                     else if ( current 
== wxT("BACK") ) 
 175                     else if ( current 
== wxT("INS") ) 
 176                         keyCode 
= WXK_INSERT
; 
 177                     else if ( current 
== wxT("INSERT") ) 
 178                         keyCode 
= WXK_INSERT
; 
 179                     else if ( current 
== wxT("ENTER") || current 
== wxT("RETURN") ) 
 180                         keyCode 
= WXK_RETURN
; 
 181                     else if ( current 
== wxT("PGUP") ) 
 183                     else if ( current 
== wxT("PGDN") ) 
 185                     else if ( current 
== wxT("LEFT") ) 
 187                     else if ( current 
== wxT("RIGHT") ) 
 189                     else if ( current 
== wxT("UP") ) 
 191                     else if ( current 
== wxT("DOWN") ) 
 193                     else if ( current 
== wxT("HOME") ) 
 195                     else if ( current 
== wxT("END") ) 
 197                     else if ( current 
== wxT("SPACE") ) 
 199                     else if ( current 
== wxT("TAB") ) 
 201                     else if ( current 
== wxT("ESC") || current 
== wxT("ESCAPE") ) 
 202                         keyCode 
= WXK_ESCAPE
; 
 205                         wxLogDebug(wxT("Unrecognized accel key '%s', accel string ignored."), 
 213             // we do have something 
 214             return new wxAcceleratorEntry(accelFlags
, keyCode
); 
 218     return (wxAcceleratorEntry 
*)NULL
; 
 221 wxAcceleratorEntry 
*wxMenuItemBase::GetAccel() const 
 223     return wxGetAccelFromString(GetText()); 
 226 void wxMenuItemBase::SetAccel(wxAcceleratorEntry 
*accel
) 
 228     wxString text 
= m_text
.BeforeFirst(wxT('\t')); 
 233         int flags 
= accel
->GetFlags(); 
 234         if ( flags 
& wxACCEL_ALT 
) 
 236         if ( flags 
& wxACCEL_CTRL 
) 
 237             text 
+= wxT("Ctrl-"); 
 238         if ( flags 
& wxACCEL_SHIFT 
) 
 239             text 
+= wxT("Shift-"); 
 241         int code 
= accel
->GetKeyCode(); 
 256                 text 
<< wxT('F') << code 
- WXK_F1 
+ 1; 
 259             // if there are any other keys wxGetAccelFromString() may return, 
 260             // we should process them here 
 263                 if ( wxIsalnum(code
) ) 
 265                     text 
<< (wxChar
)code
; 
 270                 wxFAIL_MSG( wxT("unknown keyboard accel") ); 
 277 #endif // wxUSE_ACCEL 
 279 // ---------------------------------------------------------------------------- 
 280 // wxMenu ctor and dtor 
 281 // ---------------------------------------------------------------------------- 
 283 void wxMenuBase::Init(long style
) 
 285     m_menuBar 
= (wxMenuBar 
*)NULL
; 
 286     m_menuParent 
= (wxMenu 
*)NULL
; 
 288     m_invokingWindow 
= (wxWindow 
*)NULL
; 
 290     m_clientData 
= (void *)NULL
; 
 291     m_eventHandler 
= this; 
 294 wxMenuBase::~wxMenuBase() 
 296     WX_CLEAR_LIST(wxMenuItemList
, m_items
); 
 298     // Actually, in GTK, the submenus have to get deleted first. 
 301 // ---------------------------------------------------------------------------- 
 302 // wxMenu item adding/removing 
 303 // ---------------------------------------------------------------------------- 
 305 void wxMenuBase::AddSubMenu(wxMenu 
*submenu
) 
 307     wxCHECK_RET( submenu
, _T("can't add a NULL submenu") ); 
 311         submenu
->Attach(m_menuBar
); 
 314     submenu
->SetParent((wxMenu 
*)this); 
 317 wxMenuItem
* wxMenuBase::DoAppend(wxMenuItem 
*item
) 
 319     wxCHECK_MSG( item
, NULL
, wxT("invalid item in wxMenu::Append()") ); 
 321     m_items
.Append(item
); 
 322     item
->SetMenu((wxMenu
*)this); 
 323     if ( item
->IsSubMenu() ) 
 325         AddSubMenu(item
->GetSubMenu()); 
 331 wxMenuItem
* wxMenuBase::Insert(size_t pos
, wxMenuItem 
*item
) 
 333     wxCHECK_MSG( item
, NULL
, wxT("invalid item in wxMenu::Insert") ); 
 335     if ( pos 
== GetMenuItemCount() ) 
 337         return DoAppend(item
); 
 341         wxCHECK_MSG( pos 
< GetMenuItemCount(), FALSE
, 
 342                      wxT("invalid index in wxMenu::Insert") ); 
 344         return DoInsert(pos
, item
); 
 348 wxMenuItem
* wxMenuBase::DoInsert(size_t pos
, wxMenuItem 
*item
) 
 350     wxCHECK_MSG( item
, NULL
, wxT("invalid item in wxMenu::Insert()") ); 
 352     wxMenuItemList::compatibility_iterator node 
= m_items
.Item(pos
); 
 353     wxCHECK_MSG( node
, FALSE
, wxT("invalid index in wxMenu::Insert()") ); 
 355     m_items
.Insert(node
, item
); 
 356     item
->SetMenu((wxMenu
*)this); 
 357     if ( item
->IsSubMenu() ) 
 359         AddSubMenu(item
->GetSubMenu()); 
 365 wxMenuItem 
*wxMenuBase::Remove(wxMenuItem 
*item
) 
 367     wxCHECK_MSG( item
, NULL
, wxT("invalid item in wxMenu::Remove") ); 
 369     return DoRemove(item
); 
 372 wxMenuItem 
*wxMenuBase::DoRemove(wxMenuItem 
*item
) 
 374     wxMenuItemList::compatibility_iterator node 
= m_items
.Find(item
); 
 376     // if we get here, the item is valid or one of Remove() functions is broken 
 377     wxCHECK_MSG( node
, NULL
, wxT("bug in wxMenu::Remove logic") ); 
 379     // we detach the item, but we do delete the list node (i.e. don't call 
 380     // DetachNode() here!) 
 383     // item isn't attached to anything any more 
 384     item
->SetMenu((wxMenu 
*)NULL
); 
 385     wxMenu 
*submenu 
= item
->GetSubMenu(); 
 388         submenu
->SetParent((wxMenu 
*)NULL
); 
 394 bool wxMenuBase::Delete(wxMenuItem 
*item
) 
 396     wxCHECK_MSG( item
, FALSE
, wxT("invalid item in wxMenu::Delete") ); 
 398     return DoDelete(item
); 
 401 bool wxMenuBase::DoDelete(wxMenuItem 
*item
) 
 403     wxMenuItem 
*item2 
= DoRemove(item
); 
 404     wxCHECK_MSG( item2
, FALSE
, wxT("failed to delete menu item") ); 
 406     // don't delete the submenu 
 407     item2
->SetSubMenu((wxMenu 
*)NULL
); 
 414 bool wxMenuBase::Destroy(wxMenuItem 
*item
) 
 416     wxCHECK_MSG( item
, FALSE
, wxT("invalid item in wxMenu::Destroy") ); 
 418     return DoDestroy(item
); 
 421 bool wxMenuBase::DoDestroy(wxMenuItem 
*item
) 
 423     wxMenuItem 
*item2 
= DoRemove(item
); 
 424     wxCHECK_MSG( item2
, FALSE
, wxT("failed to delete menu item") ); 
 431 // ---------------------------------------------------------------------------- 
 432 // wxMenu searching for items 
 433 // ---------------------------------------------------------------------------- 
 435 // Finds the item id matching the given string, -1 if not found. 
 436 int wxMenuBase::FindItem(const wxString
& text
) const 
 438     wxString label 
= wxMenuItem::GetLabelFromText(text
); 
 439     for ( wxMenuItemList::compatibility_iterator node 
= m_items
.GetFirst(); 
 441           node 
= node
->GetNext() ) 
 443         wxMenuItem 
*item 
= node
->GetData(); 
 444         if ( item
->IsSubMenu() ) 
 446             int rc 
= item
->GetSubMenu()->FindItem(label
); 
 447             if ( rc 
!= wxNOT_FOUND 
) 
 451         // we execute this code for submenus as well to alllow finding them by 
 452         // name just like the ordinary items 
 453         if ( !item
->IsSeparator() ) 
 455             if ( item
->GetLabel() == label 
) 
 456                 return item
->GetId(); 
 463 // recursive search for item by id 
 464 wxMenuItem 
*wxMenuBase::FindItem(int itemId
, wxMenu 
**itemMenu
) const 
 469     wxMenuItem 
*item 
= NULL
; 
 470     for ( wxMenuItemList::compatibility_iterator node 
= m_items
.GetFirst(); 
 472           node 
= node
->GetNext() ) 
 474         item 
= node
->GetData(); 
 476         if ( item
->GetId() == itemId 
) 
 479                 *itemMenu 
= (wxMenu 
*)this; 
 481         else if ( item
->IsSubMenu() ) 
 483             item 
= item
->GetSubMenu()->FindItem(itemId
, itemMenu
); 
 487             // don't exit the loop 
 495 // non recursive search 
 496 wxMenuItem 
*wxMenuBase::FindChildItem(int id
, size_t *ppos
) const 
 498     wxMenuItem 
*item 
= (wxMenuItem 
*)NULL
; 
 499     wxMenuItemList::compatibility_iterator node 
= GetMenuItems().GetFirst(); 
 502     for ( pos 
= 0; node
; pos
++ ) 
 504         if ( node
->GetData()->GetId() == id 
) 
 506             item 
= node
->GetData(); 
 511         node 
= node
->GetNext(); 
 516         *ppos 
= item 
? pos 
: (size_t)wxNOT_FOUND
; 
 523 wxMenuItem
* wxMenuBase::FindItemByPosition(size_t position
) const 
 525     wxCHECK_MSG( position 
< m_items
.GetCount(), NULL
, 
 526                  _T("wxMenu::FindItemByPosition(): invalid menu index") ); 
 528     return m_items
.Item( position 
)->GetData(); 
 531 // ---------------------------------------------------------------------------- 
 532 // wxMenu helpers used by derived classes 
 533 // ---------------------------------------------------------------------------- 
 535 // Update a menu and all submenus recursively. source is the object that has 
 536 // the update event handlers defined for it. If NULL, the menu or associated 
 537 // window will be used. 
 538 void wxMenuBase::UpdateUI(wxEvtHandler
* source
) 
 540     if (GetInvokingWindow()) 
 542         // Don't update menus if the parent 
 543         // frame is about to get deleted 
 544         wxWindow 
*tlw 
= wxGetTopLevelParent( GetInvokingWindow() ); 
 545         if (tlw 
&& wxPendingDelete
.Member(tlw
)) 
 549     if ( !source 
&& GetInvokingWindow() ) 
 550         source 
= GetInvokingWindow()->GetEventHandler(); 
 552         source 
= GetEventHandler(); 
 556     wxMenuItemList::compatibility_iterator  node 
= GetMenuItems().GetFirst(); 
 559         wxMenuItem
* item 
= node
->GetData(); 
 560         if ( !item
->IsSeparator() ) 
 562             wxWindowID id 
= item
->GetId(); 
 563             wxUpdateUIEvent 
event(id
); 
 564             event
.SetEventObject( source 
); 
 566             if ( source
->ProcessEvent(event
) ) 
 568                 // if anything changed, update the changed attribute 
 569                 if (event
.GetSetText()) 
 570                     SetLabel(id
, event
.GetText()); 
 571                 if (event
.GetSetChecked()) 
 572                     Check(id
, event
.GetChecked()); 
 573                 if (event
.GetSetEnabled()) 
 574                     Enable(id
, event
.GetEnabled()); 
 577             // recurse to the submenus 
 578             if ( item
->GetSubMenu() ) 
 579                 item
->GetSubMenu()->UpdateUI(source
); 
 581         //else: item is a separator (which doesn't process update UI events) 
 583         node 
= node
->GetNext(); 
 587 bool wxMenuBase::SendEvent(int id
, int checked
) 
 589     wxCommandEvent 
event(wxEVT_COMMAND_MENU_SELECTED
, id
); 
 590     event
.SetEventObject(this); 
 591     event
.SetInt(checked
); 
 593     bool processed 
= FALSE
; 
 595     // Try the menu's event handler 
 598         wxEvtHandler 
*handler 
= GetEventHandler(); 
 600             processed 
= handler
->ProcessEvent(event
); 
 603     // Try the window the menu was popped up from (and up through the 
 607         const wxMenuBase 
*menu 
= this; 
 610             wxWindow 
*win 
= menu
->GetInvokingWindow(); 
 613                 processed 
= win
->GetEventHandler()->ProcessEvent(event
); 
 617             menu 
= menu
->GetParent(); 
 624 // ---------------------------------------------------------------------------- 
 625 // wxMenu attaching/detaching to/from menu bar 
 626 // ---------------------------------------------------------------------------- 
 628 void wxMenuBase::Attach(wxMenuBarBase 
*menubar
) 
 630     // use Detach() instead! 
 631     wxASSERT_MSG( menubar
, _T("menu can't be attached to NULL menubar") ); 
 633     // use IsAttached() to prevent this from happening 
 634     wxASSERT_MSG( !m_menuBar
, _T("attaching menu twice?") ); 
 636     m_menuBar 
= (wxMenuBar 
*)menubar
; 
 639 void wxMenuBase::Detach() 
 641     // use IsAttached() to prevent this from happening 
 642     wxASSERT_MSG( m_menuBar
, _T("detaching unattached menu?") ); 
 647 // ---------------------------------------------------------------------------- 
 648 // wxMenu functions forwarded to wxMenuItem 
 649 // ---------------------------------------------------------------------------- 
 651 void wxMenuBase::Enable( int id
, bool enable 
) 
 653     wxMenuItem 
*item 
= FindItem(id
); 
 655     wxCHECK_RET( item
, wxT("wxMenu::Enable: no such item") ); 
 657     item
->Enable(enable
); 
 660 bool wxMenuBase::IsEnabled( int id 
) const 
 662     wxMenuItem 
*item 
= FindItem(id
); 
 664     wxCHECK_MSG( item
, FALSE
, wxT("wxMenu::IsEnabled: no such item") ); 
 666     return item
->IsEnabled(); 
 669 void wxMenuBase::Check( int id
, bool enable 
) 
 671     wxMenuItem 
*item 
= FindItem(id
); 
 673     wxCHECK_RET( item
, wxT("wxMenu::Check: no such item") ); 
 678 bool wxMenuBase::IsChecked( int id 
) const 
 680     wxMenuItem 
*item 
= FindItem(id
); 
 682     wxCHECK_MSG( item
, FALSE
, wxT("wxMenu::IsChecked: no such item") ); 
 684     return item
->IsChecked(); 
 687 void wxMenuBase::SetLabel( int id
, const wxString 
&label 
) 
 689     wxMenuItem 
*item 
= FindItem(id
); 
 691     wxCHECK_RET( item
, wxT("wxMenu::SetLabel: no such item") ); 
 693     item
->SetText(label
); 
 696 wxString 
wxMenuBase::GetLabel( int id 
) const 
 698     wxMenuItem 
*item 
= FindItem(id
); 
 700     wxCHECK_MSG( item
, wxT(""), wxT("wxMenu::GetLabel: no such item") ); 
 702     return item
->GetText(); 
 705 void wxMenuBase::SetHelpString( int id
, const wxString
& helpString 
) 
 707     wxMenuItem 
*item 
= FindItem(id
); 
 709     wxCHECK_RET( item
, wxT("wxMenu::SetHelpString: no such item") ); 
 711     item
->SetHelp( helpString 
); 
 714 wxString 
wxMenuBase::GetHelpString( int id 
) const 
 716     wxMenuItem 
*item 
= FindItem(id
); 
 718     wxCHECK_MSG( item
, wxT(""), wxT("wxMenu::GetHelpString: no such item") ); 
 720     return item
->GetHelp(); 
 723 // ---------------------------------------------------------------------------- 
 724 // wxMenuBarBase ctor and dtor 
 725 // ---------------------------------------------------------------------------- 
 727 wxMenuBarBase::wxMenuBarBase() 
 730     m_menuBarFrame 
= NULL
; 
 733 wxMenuBarBase::~wxMenuBarBase() 
 735     WX_CLEAR_LIST(wxMenuList
, m_menus
); 
 738 // ---------------------------------------------------------------------------- 
 739 // wxMenuBar item access: the base class versions manage m_menus list, the 
 740 // derived class should reflect the changes in the real menubar 
 741 // ---------------------------------------------------------------------------- 
 743 wxMenu 
*wxMenuBarBase::GetMenu(size_t pos
) const 
 745     wxMenuList::compatibility_iterator node 
= m_menus
.Item(pos
); 
 746     wxCHECK_MSG( node
, NULL
, wxT("bad index in wxMenuBar::GetMenu()") ); 
 748     return node
->GetData(); 
 751 bool wxMenuBarBase::Append(wxMenu 
*menu
, const wxString
& WXUNUSED(title
)) 
 753     wxCHECK_MSG( menu
, FALSE
, wxT("can't append NULL menu") ); 
 755     m_menus
.Append(menu
); 
 761 bool wxMenuBarBase::Insert(size_t pos
, wxMenu 
*menu
, 
 762                            const wxString
& title
) 
 764     if ( pos 
== m_menus
.GetCount() ) 
 766         return wxMenuBarBase::Append(menu
, title
); 
 768     else // not at the end 
 770         wxCHECK_MSG( menu
, FALSE
, wxT("can't insert NULL menu") ); 
 772         wxMenuList::compatibility_iterator node 
= m_menus
.Item(pos
); 
 773         wxCHECK_MSG( node
, FALSE
, wxT("bad index in wxMenuBar::Insert()") ); 
 775         m_menus
.Insert(node
, menu
); 
 782 wxMenu 
*wxMenuBarBase::Replace(size_t pos
, wxMenu 
*menu
, 
 783                                const wxString
& WXUNUSED(title
)) 
 785     wxCHECK_MSG( menu
, NULL
, wxT("can't insert NULL menu") ); 
 787     wxMenuList::compatibility_iterator node 
= m_menus
.Item(pos
); 
 788     wxCHECK_MSG( node
, NULL
, wxT("bad index in wxMenuBar::Replace()") ); 
 790     wxMenu 
*menuOld 
= node
->GetData(); 
 799 wxMenu 
*wxMenuBarBase::Remove(size_t pos
) 
 801     wxMenuList::compatibility_iterator node 
= m_menus
.Item(pos
); 
 802     wxCHECK_MSG( node
, NULL
, wxT("bad index in wxMenuBar::Remove()") ); 
 804     wxMenu 
*menu 
= node
->GetData(); 
 811 int wxMenuBarBase::FindMenu(const wxString
& title
) const 
 813     wxString label 
= wxMenuItem::GetLabelFromText(title
); 
 815     size_t count 
= GetMenuCount(); 
 816     for ( size_t i 
= 0; i 
< count
; i
++ ) 
 818         wxString title2 
= GetLabelTop(i
); 
 819         if ( (title2 
== title
) || 
 820              (wxMenuItem::GetLabelFromText(title2
) == label
) ) 
 831 // ---------------------------------------------------------------------------- 
 832 // wxMenuBar attaching/detaching to/from the frame 
 833 // ---------------------------------------------------------------------------- 
 835 void wxMenuBarBase::Attach(wxFrame 
*frame
) 
 837     wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") ); 
 839     m_menuBarFrame 
= frame
; 
 842 void wxMenuBarBase::Detach() 
 844     wxASSERT_MSG( IsAttached(), wxT("detaching unattached menubar") ); 
 846     m_menuBarFrame 
= NULL
; 
 849 // ---------------------------------------------------------------------------- 
 850 // wxMenuBar searching for items 
 851 // ---------------------------------------------------------------------------- 
 853 wxMenuItem 
*wxMenuBarBase::FindItem(int id
, wxMenu 
**menu
) const 
 858     wxMenuItem 
*item 
= NULL
; 
 859     size_t count 
= GetMenuCount(), i
; 
 860     wxMenuList::const_iterator it
; 
 861     for ( i 
= 0, it 
= m_menus
.begin(); !item 
&& (i 
< count
); i
++, it
++ ) 
 863         item 
= (*it
)->FindItem(id
, menu
); 
 869 int wxMenuBarBase::FindMenuItem(const wxString
& menu
, const wxString
& item
) const 
 871     wxString label 
= wxMenuItem::GetLabelFromText(menu
); 
 874     wxMenuList::compatibility_iterator node
; 
 875     for ( node 
= m_menus
.GetFirst(); node
; node 
= node
->GetNext(), i
++ ) 
 877         if ( label 
== wxMenuItem::GetLabelFromText(GetLabelTop(i
)) ) 
 878             return node
->GetData()->FindItem(item
); 
 884 // --------------------------------------------------------------------------- 
 885 // wxMenuBar functions forwarded to wxMenuItem 
 886 // --------------------------------------------------------------------------- 
 888 void wxMenuBarBase::Enable(int id
, bool enable
) 
 890     wxMenuItem 
*item 
= FindItem(id
); 
 892     wxCHECK_RET( item
, wxT("attempt to enable an item which doesn't exist") ); 
 894     item
->Enable(enable
); 
 897 void wxMenuBarBase::Check(int id
, bool check
) 
 899     wxMenuItem 
*item 
= FindItem(id
); 
 901     wxCHECK_RET( item
, wxT("attempt to check an item which doesn't exist") ); 
 902     wxCHECK_RET( item
->IsCheckable(), wxT("attempt to check an uncheckable item") ); 
 907 bool wxMenuBarBase::IsChecked(int id
) const 
 909     wxMenuItem 
*item 
= FindItem(id
); 
 911     wxCHECK_MSG( item
, FALSE
, wxT("wxMenuBar::IsChecked(): no such item") ); 
 913     return item
->IsChecked(); 
 916 bool wxMenuBarBase::IsEnabled(int id
) const 
 918     wxMenuItem 
*item 
= FindItem(id
); 
 920     wxCHECK_MSG( item
, FALSE
, wxT("wxMenuBar::IsEnabled(): no such item") ); 
 922     return item
->IsEnabled(); 
 925 void wxMenuBarBase::SetLabel(int id
, const wxString
& label
) 
 927     wxMenuItem 
*item 
= FindItem(id
); 
 929     wxCHECK_RET( item
, wxT("wxMenuBar::SetLabel(): no such item") ); 
 931     item
->SetText(label
); 
 934 wxString 
wxMenuBarBase::GetLabel(int id
) const 
 936     wxMenuItem 
*item 
= FindItem(id
); 
 938     wxCHECK_MSG( item
, wxEmptyString
, 
 939                  wxT("wxMenuBar::GetLabel(): no such item") ); 
 941     return item
->GetText(); 
 944 void wxMenuBarBase::SetHelpString(int id
, const wxString
& helpString
) 
 946     wxMenuItem 
*item 
= FindItem(id
); 
 948     wxCHECK_RET( item
, wxT("wxMenuBar::SetHelpString(): no such item") ); 
 950     item
->SetHelp(helpString
); 
 953 wxString 
wxMenuBarBase::GetHelpString(int id
) const 
 955     wxMenuItem 
*item 
= FindItem(id
); 
 957     wxCHECK_MSG( item
, wxEmptyString
, 
 958                  wxT("wxMenuBar::GetHelpString(): no such item") ); 
 960     return item
->GetHelp(); 
 963 #endif // wxUSE_MENUS