From defc0789c198fe5af4d60fb4804d146807dd48e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Mon, 9 Aug 2004 16:08:20 +0000 Subject: [PATCH] really fixed wxMenuBar::Remove (bug 610850): reverted incorrect patch 649599 and fixed data corruption and leaks in GTK+ structures git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@28725 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/gtk/menu.cpp | 48 +++++++++-------------------------------------- src/gtk1/menu.cpp | 48 +++++++++-------------------------------------- 2 files changed, 18 insertions(+), 78 deletions(-) diff --git a/src/gtk/menu.cpp b/src/gtk/menu.cpp index ed7a91f67f..5b29ede177 100644 --- a/src/gtk/menu.cpp +++ b/src/gtk/menu.cpp @@ -421,53 +421,17 @@ wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title) return menuOld; } -static wxMenu *CopyMenu (wxMenu *menu) -{ - wxMenu *menucopy = new wxMenu (); - wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst(); - while (node) - { - wxMenuItem *item = node->GetData(); - int itemid = item->GetId(); - wxString text = item->GetText(); - text.Replace(wxT("_"), wxT("&")); - wxMenu *submenu = item->GetSubMenu(); - if (!submenu) - { - wxMenuItem* itemcopy = new wxMenuItem(menucopy, - itemid, text, - menu->GetHelpString(itemid)); - itemcopy->SetBitmap(item->GetBitmap()); - itemcopy->SetCheckable(item->IsCheckable()); - menucopy->Append(itemcopy); - } - else - menucopy->Append (itemid, text, CopyMenu(submenu), - menu->GetHelpString(itemid)); - - node = node->GetNext(); - } - - return menucopy; -} - wxMenu *wxMenuBar::Remove(size_t pos) { wxMenu *menu = wxMenuBarBase::Remove(pos); if ( !menu ) return (wxMenu*) NULL; - wxMenu *menucopy = CopyMenu( menu ); - - // unparent calls unref() and that would delete the widget so we raise - // the ref count to 2 artificially before invoking unparent. - gtk_widget_ref( menu->m_menu ); - gtk_widget_unparent( menu->m_menu ); + gtk_menu_item_remove_submenu( GTK_MENU_ITEM(menu->m_owner) ); + gtk_container_remove(GTK_CONTAINER(m_menubar), menu->m_owner); gtk_widget_destroy( menu->m_owner ); - delete menu; - - menu = menucopy; + menu->m_owner = NULL; if (m_invokingWindow) { @@ -986,6 +950,9 @@ void wxMenu::Init() { m_accel = gtk_accel_group_new(); m_menu = gtk_menu_new(); + // NB: keep reference to the menu so that it is not destroyed behind + // our back by GTK+ e.g. when it is removed from menubar: + gtk_widget_ref(m_menu); m_owner = (GtkWidget*) NULL; @@ -1014,7 +981,10 @@ wxMenu::~wxMenu() WX_CLEAR_LIST(wxMenuItemList, m_items); if ( GTK_IS_WIDGET( m_menu )) + { + gtk_widget_unref( m_menu ); // see wxMenu::Init gtk_widget_destroy( m_menu ); + } } bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos) diff --git a/src/gtk1/menu.cpp b/src/gtk1/menu.cpp index ed7a91f67f..5b29ede177 100644 --- a/src/gtk1/menu.cpp +++ b/src/gtk1/menu.cpp @@ -421,53 +421,17 @@ wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title) return menuOld; } -static wxMenu *CopyMenu (wxMenu *menu) -{ - wxMenu *menucopy = new wxMenu (); - wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst(); - while (node) - { - wxMenuItem *item = node->GetData(); - int itemid = item->GetId(); - wxString text = item->GetText(); - text.Replace(wxT("_"), wxT("&")); - wxMenu *submenu = item->GetSubMenu(); - if (!submenu) - { - wxMenuItem* itemcopy = new wxMenuItem(menucopy, - itemid, text, - menu->GetHelpString(itemid)); - itemcopy->SetBitmap(item->GetBitmap()); - itemcopy->SetCheckable(item->IsCheckable()); - menucopy->Append(itemcopy); - } - else - menucopy->Append (itemid, text, CopyMenu(submenu), - menu->GetHelpString(itemid)); - - node = node->GetNext(); - } - - return menucopy; -} - wxMenu *wxMenuBar::Remove(size_t pos) { wxMenu *menu = wxMenuBarBase::Remove(pos); if ( !menu ) return (wxMenu*) NULL; - wxMenu *menucopy = CopyMenu( menu ); - - // unparent calls unref() and that would delete the widget so we raise - // the ref count to 2 artificially before invoking unparent. - gtk_widget_ref( menu->m_menu ); - gtk_widget_unparent( menu->m_menu ); + gtk_menu_item_remove_submenu( GTK_MENU_ITEM(menu->m_owner) ); + gtk_container_remove(GTK_CONTAINER(m_menubar), menu->m_owner); gtk_widget_destroy( menu->m_owner ); - delete menu; - - menu = menucopy; + menu->m_owner = NULL; if (m_invokingWindow) { @@ -986,6 +950,9 @@ void wxMenu::Init() { m_accel = gtk_accel_group_new(); m_menu = gtk_menu_new(); + // NB: keep reference to the menu so that it is not destroyed behind + // our back by GTK+ e.g. when it is removed from menubar: + gtk_widget_ref(m_menu); m_owner = (GtkWidget*) NULL; @@ -1014,7 +981,10 @@ wxMenu::~wxMenu() WX_CLEAR_LIST(wxMenuItemList, m_items); if ( GTK_IS_WIDGET( m_menu )) + { + gtk_widget_unref( m_menu ); // see wxMenu::Init gtk_widget_destroy( m_menu ); + } } bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)