+ wxMenuList::compatibility_iterator node = m_menus.GetFirst();
+ while (node)
+ {
+ wxMenu *menu = node->GetData();
+ int res = FindMenuItemRecursive( menu, menuString, itemString);
+ if (res != -1)
+ return res;
+ node = node->GetNext();
+ }
+
+ return wxNOT_FOUND;
+}
+
+// Find a wxMenuItem using its id. Recurses down into sub-menus
+static wxMenuItem* FindMenuItemByIdRecursive(const wxMenu* menu, int id)
+{
+ wxMenuItem* result = menu->FindChildItem(id);
+
+ wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
+ while ( node && result == NULL )
+ {
+ wxMenuItem *item = node->GetData();
+ if (item->IsSubMenu())
+ {
+ result = FindMenuItemByIdRecursive( item->GetSubMenu(), id );
+ }
+ node = node->GetNext();
+ }
+
+ return result;
+}
+
+wxMenuItem* wxMenuBar::FindItem( int id, wxMenu **menuForItem ) const
+{
+ wxMenuItem* result = 0;
+ wxMenuList::compatibility_iterator node = m_menus.GetFirst();
+ while (node && result == 0)
+ {
+ wxMenu *menu = node->GetData();
+ result = FindMenuItemByIdRecursive( menu, id );
+ node = node->GetNext();
+ }
+
+ if ( menuForItem )
+ {
+ *menuForItem = result ? result->GetMenu() : (wxMenu *)NULL;
+ }
+
+ return result;
+}
+
+void wxMenuBar::EnableTop( size_t pos, bool flag )
+{
+ wxMenuList::compatibility_iterator node = m_menus.Item( pos );
+
+ wxCHECK_RET( node, wxT("menu not found") );
+
+ wxMenu* menu = node->GetData();
+
+ if (menu->m_owner)
+ gtk_widget_set_sensitive( menu->m_owner, flag );
+}
+
+wxString wxMenuBar::GetMenuLabel( size_t pos ) const
+{
+ wxMenuList::compatibility_iterator node = m_menus.Item( pos );
+
+ wxCHECK_MSG( node, wxT("invalid"), wxT("menu not found") );
+
+ wxMenu* menu = node->GetData();
+
+ return wxConvertMnemonicsFromGTK(menu->GetTitle());
+}
+
+void wxMenuBar::SetMenuLabel( size_t pos, const wxString& label )
+{
+ wxMenuList::compatibility_iterator node = m_menus.Item( pos );
+
+ wxCHECK_RET( node, wxT("menu not found") );
+
+ wxMenu* menu = node->GetData();
+
+ const wxString str(wxConvertMnemonicsToGTK(label));
+
+ menu->SetTitle( str );
+
+ if (menu->m_owner)
+ gtk_label_set_text_with_mnemonic( GTK_LABEL( GTK_BIN(menu->m_owner)->child), wxGTK_CONV(str) );
+}
+
+//-----------------------------------------------------------------------------
+// "activate"
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static void menuitem_activate(GtkWidget*, wxMenuItem* item)
+{
+ if (!item->IsEnabled())
+ return;
+
+ int id = item->GetId();
+ if (id == wxGTK_TITLE_ID)
+ {
+ // ignore events from the menu title
+ return;
+ }
+
+ if (item->IsCheckable())
+ {
+ bool isReallyChecked = item->IsChecked(),
+ isInternallyChecked = item->wxMenuItemBase::IsChecked();
+
+ // ensure that the internal state is always consistent with what is
+ // shown on the screen
+ item->wxMenuItemBase::Check(isReallyChecked);
+
+ // we must not report the events for the radio button going up nor the
+ // events resulting from the calls to wxMenuItem::Check()
+ if ( (item->GetKind() == wxITEM_RADIO && !isReallyChecked) ||
+ (isInternallyChecked == isReallyChecked) )
+ {
+ return;
+ }
+ }
+
+
+ // Is this menu on a menubar? (possibly nested)
+ wxMenu* menu = item->GetMenu();
+ wxFrame* frame = NULL;
+ if(menu->IsAttached())
+ frame = menu->GetMenuBar()->GetFrame();
+
+ // FIXME: why do we have to call wxFrame::GetEventHandler() directly here?
+ // normally wxMenu::SendEvent() should be enough, if it doesn't work
+ // in wxGTK then we have a bug in wxMenu::GetInvokingWindow() which
+ // should be fixed instead of working around it here...
+ if (frame)
+ {
+ // If it is attached then let the frame send the event.
+ // Don't call frame->ProcessCommand(id) because it toggles
+ // checkable items and we've already done that above.
+ wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);
+ commandEvent.SetEventObject(frame);
+ if (item->IsCheckable())
+ commandEvent.SetInt(item->IsChecked());
+
+ frame->HandleWindowEvent(commandEvent);
+ }
+ else
+ {
+ // otherwise let the menu have it
+ menu->SendEvent(id, item->IsCheckable() ? item->IsChecked() : -1);
+ }
+}
+}
+
+//-----------------------------------------------------------------------------
+// "select"
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static void menuitem_select(GtkWidget*, wxMenuItem* item)
+{
+ if (!item->IsEnabled())
+ return;
+
+ wxMenu* menu = item->GetMenu();
+ wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item->GetId());
+ event.SetEventObject( menu );
+
+ wxEvtHandler* handler = menu->GetEventHandler();
+ if (handler && handler->SafelyProcessEvent(event))
+ return;
+
+ wxWindow *win = menu->GetInvokingWindow();
+ if (win) win->HandleWindowEvent( event );
+}
+}
+
+//-----------------------------------------------------------------------------
+// "deselect"
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static void menuitem_deselect(GtkWidget*, wxMenuItem* item)
+{
+ if (!item->IsEnabled())
+ return;
+
+ wxMenu* menu = item->GetMenu();
+ wxMenuEvent event( wxEVT_MENU_HIGHLIGHT, -1 );
+ event.SetEventObject( menu );
+
+ wxEvtHandler* handler = menu->GetEventHandler();
+ if (handler && handler->SafelyProcessEvent(event))
+ return;
+
+ wxWindow *win = menu->GetInvokingWindow();
+ if (win)
+ win->HandleWindowEvent( event );
+}
+}
+
+//-----------------------------------------------------------------------------
+// wxMenuItem
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
+
+wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
+ int id,
+ const wxString& name,
+ const wxString& help,
+ wxItemKind kind,
+ wxMenu *subMenu)
+{
+ return new wxMenuItem(parentMenu, id, name, help, kind, subMenu);
+}
+
+wxMenuItem::wxMenuItem(wxMenu *parentMenu,
+ int id,
+ const wxString& text,
+ const wxString& help,
+ wxItemKind kind,
+ wxMenu *subMenu)
+ : wxMenuItemBase(parentMenu, id, text, help, kind, subMenu)
+{
+ m_menuItem = NULL;
+}
+
+#if WXWIN_COMPATIBILITY_2_8
+wxMenuItem::wxMenuItem(wxMenu *parentMenu,
+ int id,
+ const wxString& text,
+ const wxString& help,
+ bool isCheckable,
+ wxMenu *subMenu)
+ : wxMenuItemBase(parentMenu, id, text, help,
+ isCheckable ? wxITEM_CHECK : wxITEM_NORMAL, subMenu)
+{
+ m_menuItem = NULL;
+}
+#endif
+
+wxMenuItem::~wxMenuItem()
+{
+ // don't delete menu items, the menus take care of that
+}
+
+void wxMenuItem::SetItemLabel( const wxString& str )
+{
+#if wxUSE_ACCEL
+ if (m_menuItem)
+ {
+ // remove old accelerator
+ guint accel_key;
+ GdkModifierType accel_mods;
+ wxGetGtkAccel(this, &accel_key, &accel_mods);
+ if (accel_key)
+ {
+ gtk_widget_remove_accelerator(
+ m_menuItem, m_parentMenu->m_accel, accel_key, accel_mods);
+ }
+ }
+#endif // wxUSE_ACCEL
+ wxMenuItemBase::SetItemLabel(str);
+ if (m_menuItem)
+ SetGtkLabel();
+}
+
+void wxMenuItem::SetGtkLabel()
+{
+ const wxString text = wxConvertMnemonicsToGTK(m_text.BeforeFirst('\t'));
+ GtkLabel* label = GTK_LABEL(GTK_BIN(m_menuItem)->child);
+ gtk_label_set_text_with_mnemonic(label, wxGTK_CONV_SYS(text));
+#if wxUSE_ACCEL
+ guint accel_key;
+ GdkModifierType accel_mods;
+ wxGetGtkAccel(this, &accel_key, &accel_mods);
+ if (accel_key)
+ {
+ gtk_widget_add_accelerator(
+ m_menuItem, "activate", m_parentMenu->m_accel,
+ accel_key, accel_mods, GTK_ACCEL_VISIBLE);
+ }
+#endif // wxUSE_ACCEL
+}
+
+void wxMenuItem::SetBitmap(const wxBitmap& bitmap)
+{
+ if (m_kind == wxITEM_NORMAL)
+ m_bitmap = bitmap;
+ else
+ wxFAIL_MSG("only normal menu items can have bitmaps");
+}
+
+void wxMenuItem::Check( bool check )
+{
+ wxCHECK_RET( m_menuItem, wxT("invalid menu item") );
+
+ if (check == m_isChecked)
+ return;
+
+ wxMenuItemBase::Check( check );
+
+ switch ( GetKind() )
+ {
+ case wxITEM_CHECK:
+ case wxITEM_RADIO:
+ gtk_check_menu_item_set_active( (GtkCheckMenuItem*)m_menuItem, (gint)check );
+ break;
+
+ default:
+ wxFAIL_MSG( _T("can't check this item") );
+ }
+}
+
+void wxMenuItem::Enable( bool enable )
+{
+ wxCHECK_RET( m_menuItem, wxT("invalid menu item") );
+
+ gtk_widget_set_sensitive( m_menuItem, enable );
+ wxMenuItemBase::Enable( enable );
+}
+
+bool wxMenuItem::IsChecked() const
+{
+ wxCHECK_MSG( m_menuItem, false, wxT("invalid menu item") );
+
+ wxCHECK_MSG( IsCheckable(), false,
+ wxT("can't get state of uncheckable item!") );
+
+ return ((GtkCheckMenuItem*)m_menuItem)->active != 0;
+}
+