]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/menu.cpp
new file added
[wxWidgets.git] / src / gtk / menu.cpp
index 3c99374528c5a1f5b76b05169b3b0960cd5534e9..acd8d29e736e6484194aaf7c91b4e2ceb73d4dd7 100644 (file)
 
 #include "wx/accel.h"
 #include "wx/stockitem.h"
+
+#include <gtk/gtk.h>
 #include "wx/gtk/private.h"
+#include "wx/gtk/private/gtk2-compat.h"
 #include "wx/gtk/private/mnemonics.h"
 
 // we use normal item but with a special id for the menu title
@@ -58,6 +61,18 @@ static void DoCommonMenuCallbackCode(wxMenu *menu, wxMenuEvent& event)
 // wxMenuBar
 //-----------------------------------------------------------------------------
 
+wxMenuBar::~wxMenuBar()
+{
+    if (m_widget)
+    {
+        // Work around a probable bug in Ubuntu 12.04 which causes a warning if
+        // gtk_widget_destroy() is called on a wxMenuBar attached to a frame
+        GtkWidget* widget = m_widget;
+        m_widget = NULL;
+        g_object_unref(widget);
+    }
+}
+
 void wxMenuBar::Init(size_t n, wxMenu *menus[], const wxString titles[], long style)
 {
 #if wxUSE_LIBHILDON || wxUSE_LIBHILDON2
@@ -91,7 +106,7 @@ void wxMenuBar::Init(size_t n, wxMenu *menus[], const wxString titles[], long st
     GTKApplyWidgetStyle();
 #endif // wxUSE_LIBHILDON || wxUSE_LIBHILDON2/!wxUSE_LIBHILDON && !wxUSE_LIBHILDON2
 
-    g_object_ref(m_widget);
+    g_object_ref_sink(m_widget);
 
     for (size_t i = 0; i < n; ++i )
         Append(menus[i], titles[i]);
@@ -126,7 +141,7 @@ DetachFromFrame(wxMenu* menu, wxFrame* frame)
         // Note that wxGetTopLevelParent() is really needed because this frame
         // can be an MDI child frame which is a fake frame and not a TLW at all
         GtkWindow * const tlw = GTK_WINDOW(wxGetTopLevelParent(frame)->m_widget);
-        if (g_slist_find(menu->m_accel->acceleratables, tlw))
+        if (g_slist_find(gtk_accel_groups_from_object(G_OBJECT(tlw)), menu->m_accel))
             gtk_window_remove_accel_group(tlw, menu->m_accel);
     }
 
@@ -147,7 +162,7 @@ AttachToFrame(wxMenu* menu, wxFrame* frame)
     if (menu->m_accel)
     {
         GtkWindow * const tlw = GTK_WINDOW(wxGetTopLevelParent(frame)->m_widget);
-        if (!g_slist_find(menu->m_accel->acceleratables, tlw))
+        if (!g_slist_find(gtk_accel_groups_from_object(G_OBJECT(tlw)), menu->m_accel))
             gtk_window_add_accel_group(tlw, menu->m_accel);
     }
 
@@ -230,13 +245,15 @@ void wxMenuBar::Detach()
 
 bool wxMenuBar::Append( wxMenu *menu, const wxString &title )
 {
-    if ( !wxMenuBarBase::Append( menu, title ) )
-        return false;
-
-    return GtkAppend(menu, title);
+    if (wxMenuBarBase::Append(menu, title))
+    {
+        GtkAppend(menu, title);
+        return true;
+    }
+    return false;
 }
 
-bool wxMenuBar::GtkAppend(wxMenu *menu, const wxString& title, int pos)
+void wxMenuBar::GtkAppend(wxMenu* menu, const wxString& title, int pos)
 {
     menu->SetLayoutDirection(GetLayoutDirection());
 
@@ -251,7 +268,10 @@ bool wxMenuBar::GtkAppend(wxMenu *menu, const wxString& title, int pos)
         const wxString str(wxStripMenuCodes(item->GetItemLabel()));
 
         if ( item->IsSubMenu() )
-            return GtkAppend(item->GetSubMenu(), str, pos);
+        {
+            GtkAppend(item->GetSubMenu(), str, pos);
+            return;
+        }
 
         menu->m_owner = gtk_menu_item_new_with_mnemonic( wxGTK_CONV( str ) );
 
@@ -282,21 +302,16 @@ bool wxMenuBar::GtkAppend(wxMenu *menu, const wxString& title, int pos)
 
     if ( m_menuBarFrame )
         AttachToFrame( menu, m_menuBarFrame );
-
-    return true;
 }
 
 bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
 {
-    if ( !wxMenuBarBase::Insert(pos, menu, title) )
-        return false;
-
-    // TODO
-
-    if ( !GtkAppend(menu, title, (int)pos) )
-        return false;
-
-    return true;
+    if (wxMenuBarBase::Insert(pos, menu, title))
+    {
+        GtkAppend(menu, title, int(pos));
+        return true;
+    }
+    return false;
 }
 
 wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
@@ -416,6 +431,15 @@ void wxMenuBar::EnableTop( size_t pos, bool flag )
         gtk_widget_set_sensitive( menu->m_owner, flag );
 }
 
+bool wxMenuBar::IsEnabledTop(size_t pos) const
+{
+    wxMenuList::compatibility_iterator node = m_menus.Item( pos );
+    wxCHECK_MSG( node, false, wxS("invalid index in IsEnabledTop") );
+    wxMenu* const menu = node->GetData();
+    wxCHECK_MSG( menu->m_owner, true, wxS("no menu owner?") );
+    return gtk_widget_get_sensitive( menu->m_owner ) != 0;
+}
+
 wxString wxMenuBar::GetMenuLabel( size_t pos ) const
 {
     wxMenuList::compatibility_iterator node = m_menus.Item( pos );
@@ -745,7 +769,7 @@ wxString wxMenu::GetTitle() const
     return wxConvertMnemonicsFromGTK(wxMenuBase::GetTitle());
 }
 
-bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
+void wxMenu::GtkAppend(wxMenuItem* mitem, int pos)
 {
     GtkWidget *menuItem;
     switch (mitem->GetKind())
@@ -763,9 +787,9 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
                 wxMenuItem* radioGroupItem = NULL;
 
                 const size_t numItems = GetMenuItemCount();
-                const size_t n = pos == -1 ? numItems
-                                           : static_cast<size_t>(pos);
-                if ( n > 0 )
+                const size_t n = pos == -1 ? numItems - 1 : size_t(pos);
+
+                if (n != 0)
                 {
                     wxMenuItem* const itemPrev = FindItemByPosition(n - 1);
                     if ( itemPrev->GetKind() == wxITEM_RADIO )
@@ -776,9 +800,9 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
                     }
                 }
 
-                if ( n < numItems )
+                if (radioGroupItem == NULL && n != numItems - 1)
                 {
-                    wxMenuItem* const itemNext = FindItemByPosition(n);
+                    wxMenuItem* const itemNext = FindItemByPosition(n + 1);
                     if ( itemNext->GetKind() == wxITEM_RADIO )
                     {
                         // Inserting an item before an existing radio item
@@ -850,24 +874,26 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
                               mitem);
         }
     }
-
-    return true;
 }
 
 wxMenuItem* wxMenu::DoAppend(wxMenuItem *mitem)
 {
-    if (!GtkAppend(mitem))
-        return NULL;
-
-    return wxMenuBase::DoAppend(mitem);
+    if (wxMenuBase::DoAppend(mitem))
+    {
+        GtkAppend(mitem);
+        return mitem;
+    }
+    return NULL;
 }
 
 wxMenuItem* wxMenu::DoInsert(size_t pos, wxMenuItem *item)
 {
-    if ( !GtkAppend(item, (int)pos) )
-        return NULL;
-
-    return wxMenuBase::DoInsert(pos, item);
+    if (wxMenuBase::DoInsert(pos, item))
+    {
+        GtkAppend(item, int(pos));
+        return item;
+    }
+    return NULL;
 }
 
 wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
@@ -876,7 +902,25 @@ wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
         return NULL;
 
     GtkWidget * const mitem = item->GetMenuItem();
+#ifdef __WXGTK3__
     gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), NULL);
+#else
+    if (!gtk_check_version(2,12,0))
+    {
+        // gtk_menu_item_remove_submenu() is deprecated since 2.12, but
+        // gtk_menu_item_set_submenu() can now be used with NULL submenu now so
+        // just do use it.
+        gtk_menu_item_set_submenu(GTK_MENU_ITEM(mitem), NULL);
+    }
+    else // GTK+ < 2.12
+    {
+        // In 2.10 calling gtk_menu_item_set_submenu() with NULL submenu
+        // results in critical GTK+ error messages so use the old function
+        // instead.
+        gtk_menu_item_remove_submenu(GTK_MENU_ITEM(mitem));
+    }
+#endif
+
     gtk_widget_destroy(mitem);
     item->SetMenuItem(NULL);