]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/menu.cpp
Updates for Y positioning
[wxWidgets.git] / src / gtk1 / menu.cpp
index 89b3623f27f25d18c50a93897b6439ef4fa69f0f..fd598295af0abbe999c7c72300b31b9279b1c374 100644 (file)
@@ -23,6 +23,7 @@
 #endif // wxUSE_ACCEL
 
 #include <gdk/gdk.h>
+#include <gdk/gdkkeysyms.h>
 #include <gtk/gtk.h>
 
 //-----------------------------------------------------------------------------
@@ -36,15 +37,17 @@ extern bool g_isIdle;
 static wxString GetHotKey( const wxMenuItem& item );
 #endif
 
-////// BEGIN CODE ADAPTED FROM GTKPIXMAPMENUITEM.C IN LIBGNOMEUI //////
+//-----------------------------------------------------------------------------
+// substitute for missing GtkPixmapMenuItem
+//-----------------------------------------------------------------------------
 
-#define GTK_TYPE_PIXMAP_MENU_ITEM           (gtk_pixmap_menu_item_get_type ())
-#define GTK_PIXMAP_MENU_ITEM(obj)           (GTK_CHECK_CAST ((obj), GTK_TYPE_PIXMAP_MENU_ITEM, GtkPixmapMenuItem))
+#define GTK_TYPE_PIXMAP_MENU_ITEM            (gtk_pixmap_menu_item_get_type ())
+#define GTK_PIXMAP_MENU_ITEM(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_PIXMAP_MENU_ITEM, GtkPixmapMenuItem))
 #define GTK_PIXMAP_MENU_ITEM_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_PIXMAP_MENU_ITEM, GtkPixmapMenuItemClass))
-#define GTK_IS_PIXMAP_MENU_ITEM(obj)        (GTK_CHECK_TYPE ((obj), GTK_TYPE_PIXMAP_MENU_ITEM))
+#define GTK_IS_PIXMAP_MENU_ITEM(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_PIXMAP_MENU_ITEM))
 #define GTK_IS_PIXMAP_MENU_ITEM_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PIXMAP_MENU_ITEM))
 //#define GTK_PIXMAP_MENU_ITEM_GET_CLASS(obj)  (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_PIXMAP_MENU_ITEM))
-#define GTK_PIXMAP_MENU_ITEM_GET_CLASS(obj) (GTK_PIXMAP_MENU_ITEM_CLASS( GTK_OBJECT_GET_CLASS(obj)))
+#define GTK_PIXMAP_MENU_ITEM_GET_CLASS(obj)  (GTK_PIXMAP_MENU_ITEM_CLASS( GTK_OBJECT_GET_CLASS(obj)))
 
 #ifndef GTK_MENU_ITEM_GET_CLASS
 #define GTK_MENU_ITEM_GET_CLASS(obj) (GTK_MENU_ITEM_CLASS( GTK_OBJECT_GET_CLASS(obj)))
@@ -55,29 +58,24 @@ typedef struct _GtkPixmapMenuItemClass  GtkPixmapMenuItemClass;
 
 struct _GtkPixmapMenuItem
 {
-  GtkMenuItem menu_item;
+    GtkMenuItem menu_item;
 
-  GtkWidget *pixmap;
+    GtkWidget *pixmap;
 };
 
 struct _GtkPixmapMenuItemClass
 {
-  GtkMenuItemClass parent_class;
+    GtkMenuItemClass parent_class;
 
-  guint orig_toggle_size;
-  guint have_pixmap_count;
+    guint orig_toggle_size;
+    guint have_pixmap_count;
 };
 
 
-GtkType           gtk_pixmap_menu_item_get_type      (void);
-GtkWidget* gtk_pixmap_menu_item_new          (void);
-void       gtk_pixmap_menu_item_set_pixmap    (GtkPixmapMenuItem *menu_item,
-                                              GtkWidget *pixmap);
-/* Added by JACS */
-
-GtkWidget* gtk_pixmap_menu_item_new_with_label (const gchar *label, GtkWidget** labelWidget);
-
-////// END CODE ADAPTED FROM GTKPIXMAPMENUITEM.C IN LIBGNOMEUI //////
+GtkType           gtk_pixmap_menu_item_get_type       (void);
+GtkWidget* gtk_pixmap_menu_item_new            (void);
+void       gtk_pixmap_menu_item_set_pixmap     (GtkPixmapMenuItem *menu_item,
+                                                                   GtkWidget *pixmap);
 
 //-----------------------------------------------------------------------------
 // idle system
@@ -324,7 +322,7 @@ bool wxMenuBar::GtkAppend(wxMenu *menu, const wxString& title)
     entry.accelerator = (gchar*) NULL;
     entry.callback = (GtkItemFactoryCallback) NULL;
     entry.callback_action = 0;
-    entry.item_type = "<Branch>";
+    entry.item_type = (char *)"<Branch>";
 
     gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 );  /* what is 2 ? */
     /* in order to get the pointer to the item we need the item text _without_ underscores */
@@ -580,12 +578,14 @@ void wxMenuBar::SetLabelTop( size_t pos, const wxString& label )
 
 static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu )
 {
-    if (g_isIdle) wxapp_install_idle_handler();
+    if (g_isIdle)
+        wxapp_install_idle_handler();
 
     int id = menu->FindMenuIdByMenuItem(widget);
 
     /* should find it for normal (not popup) menu */
-    wxASSERT( (id != -1) || (menu->GetInvokingWindow() != NULL) );
+    wxASSERT_MSG( (id != -1) || (menu->GetInvokingWindow() != NULL),
+                  _T("menu item not found in gtk_menu_clicked_callback") );
 
     if (!menu->IsEnabled(id))
         return;
@@ -609,25 +609,7 @@ static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu )
         }
     }
 
-    wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, id );
-    event.SetEventObject( menu );
-    if (item->IsCheckable())
-        event.SetInt( item->IsChecked() );
-
-#if wxUSE_MENU_CALLBACK
-    if (menu->GetCallback())
-    {
-        (void) (*(menu->GetCallback())) (*menu, event);
-        return;
-    }
-#endif // wxUSE_MENU_CALLBACK
-
-    if (menu->GetEventHandler()->ProcessEvent(event))
-        return;
-
-    wxWindow *win = menu->GetInvokingWindow();
-    if (win)
-        win->GetEventHandler()->ProcessEvent( event );
+    menu->SendEvent(item->GetId(), item->IsCheckable() ? item->IsChecked() : -1);
 }
 
 //-----------------------------------------------------------------------------
@@ -685,7 +667,7 @@ static void gtk_menu_nolight_callback( GtkWidget *widget, wxMenu *menu )
 // wxMenuItem
 //-----------------------------------------------------------------------------
 
-IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxMenuItemBase)
+IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
 
 wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
                                 int id,
@@ -728,21 +710,25 @@ wxMenuItem::~wxMenuItem()
 wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
 {
     wxString label;
-#if (GTK_MINOR_VERSION > 0)
+    
     for ( const wxChar *pc = text.c_str(); *pc; pc++ )
     {
-        if ( *pc == wxT('_') || *pc == wxT('&') )
+        if ( *pc == wxT('_')  )
         {
-            // '_' is the escape character for GTK+ and '&' is the one for
-            // wxWindows - skip both of them
+            // wxGTK escapes "xxx_xxx" to "xxx__xxx"
+            pc++;
+            label += *pc;
+            continue;
+        }
+        
+        if ( *pc == wxT('&') )
+        {
+            // wxMSW escapes &
             continue;
         }
 
         label += *pc;
     }
-#else // GTK+ 1.0
-    label = text;
-#endif // GTK+ 1.2/1.0
 
     return label;
 }
@@ -857,11 +843,21 @@ bool wxMenuItem::IsChecked() const
 
 wxString wxMenuItem::GetFactoryPath() const
 {
-    /* in order to get the pointer to the item we need the item text _without_
-       underscores */
+    /* in order to get the pointer to the item we need the item text
+       _without_ underscores */
     wxString path( wxT("<main>/") );
-    path += GetLabel();
 
+    for ( const wxChar *pc = m_text.c_str(); *pc; pc++ )
+    {
+        if ( *pc == wxT('_') || *pc == wxT('&') )
+        {
+            // remove '_' and '&' unconditionally
+            continue;
+        }
+        
+        path += *pc;
+    }
+    
     return path;
 }
 
@@ -890,10 +886,10 @@ void wxMenu::Init()
     if(m_style & wxMENU_TEAROFF)
     {
        GtkItemFactoryEntry entry;
-       entry.path = "/tearoff";
+       entry.path = (char *)"/tearoff";
        entry.callback = (GtkItemFactoryCallback) NULL;
        entry.callback_action = 0;
-       entry.item_type = "<Tearoff>";
+       entry.item_type = (char *)"<Tearoff>";
        entry.accelerator = (gchar*) NULL;
        gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 );  /* what is 2 ? */
        //GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/tearoff" );
@@ -927,10 +923,10 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem)
     {
 #if (GTK_MINOR_VERSION > 0)
         GtkItemFactoryEntry entry;
-        entry.path = "/sep";
+        entry.path = (char *)"/sep";
         entry.callback = (GtkItemFactoryCallback) NULL;
         entry.callback_action = 0;
-        entry.item_type = "<Separator>";
+        entry.item_type = (char *)"<Separator>";
         entry.accelerator = (gchar*) NULL;
 
         gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 );  /* what is 2 ? */
@@ -956,7 +952,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem)
         entry.path = buf;
         entry.callback = (GtkItemFactoryCallback) 0;
         entry.callback_action = 0;
-        entry.item_type = "<Branch>";
+        entry.item_type = (char *)"<Branch>";
         entry.accelerator = (gchar*) NULL;
 
         gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 );  /* what is 2 ? */
@@ -977,18 +973,30 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem)
     }
     else if (mitem->GetBitmap().Ok()) // An item with bitmap
     {
-        //// UNFINISHED, because I don't know how to handle hotkeys and
-        //// accelerators :-(
+        wxString text( mitem->GetText() );
+        const wxBitmap *bitmap = &mitem->GetBitmap();
+    
+        menuItem = gtk_pixmap_menu_item_new ();
+        GtkWidget *label = gtk_accel_label_new (text.mb_str());
+        gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+        gtk_container_add (GTK_CONTAINER (menuItem), label);
+        guint accel_key = gtk_label_parse_uline (GTK_LABEL(label), text.mb_str() );
+        gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), menuItem);
+        if (accel_key != GDK_VoidSymbol)
+           {
+            gtk_widget_add_accelerator (menuItem,
+                                       "activate_item",
+                                       gtk_menu_ensure_uline_accel_group (GTK_MENU (m_menu)),
+                                       accel_key, 0,
+                                       GTK_ACCEL_LOCKED);
+        }
+        gtk_widget_show (label);
 
-        GtkWidget* labelWidget;
-        menuItem = gtk_pixmap_menu_item_new_with_label(mitem->GetText().mb_str(), &labelWidget);
-        //menuItem = gtk_pixmap_menu_item_new_with_label("", &labelWidget);
-        mitem->SetLabelWidget(labelWidget);
+        mitem->SetLabelWidget(label);
 
-        //// TODO: should we store the widget somewhere to avoid a memory leak?
-        GtkWidget* w = gtk_pixmap_new(mitem->GetBitmap().GetPixmap(), mitem->GetBitmap().GetMask() ? mitem->GetBitmap().GetMask()->GetBitmap() : (GdkBitmap* )NULL);
-        gtk_widget_show(w);
-        gtk_pixmap_menu_item_set_pixmap(GTK_PIXMAP_MENU_ITEM( menuItem ), w);
+        GtkWidget* pixmap = gtk_pixmap_new( bitmap->GetPixmap(), bitmap->GetMask() ? bitmap->GetMask()->GetBitmap() : (GdkBitmap* )NULL);
+        gtk_widget_show(pixmap);
+        gtk_pixmap_menu_item_set_pixmap(GTK_PIXMAP_MENU_ITEM( menuItem ), pixmap);
 
         gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
                             GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
@@ -996,9 +1004,6 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem)
         gtk_menu_append( GTK_MENU(m_menu), menuItem );
         gtk_widget_show( menuItem );
 
-        //mitem->SetMenuItem(menuItem);
-        //mitem->SetText(mitem->GetText());
-
         appended = TRUE; // We've done this, don't do it again
     }
     else // a normal item
@@ -1017,9 +1022,9 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem)
         entry.callback = (GtkItemFactoryCallback) gtk_menu_clicked_callback;
         entry.callback_action = 0;
         if ( mitem->IsCheckable() )
-            entry.item_type = "<CheckItem>";
+            entry.item_type = (char *)"<CheckItem>";
         else
-            entry.item_type = "<Item>";
+            entry.item_type = (char *)"<Item>";
         entry.accelerator = (gchar*) NULL;
 
 #if wxUSE_ACCEL
@@ -1209,7 +1214,9 @@ static wxString GetHotKey( const wxMenuItem& item )
 #endif // wxUSE_ACCEL
 
 
-////// BEGIN CODE ADAPTED FROM GTKPIXMAPMENUITEM.C IN LIBGNOMEUI //////
+//-----------------------------------------------------------------------------
+// substitute for missing GtkPixmapMenuItem
+//-----------------------------------------------------------------------------
 
 /*
  * Copyright (C) 1998, 1999, 2000 Free Software Foundation
@@ -1238,13 +1245,15 @@ static wxString GetHotKey( const wxMenuItem& item )
 
 /* Author: Dietmar Maurer <dm@vlsivie.tuwien.ac.at> */
 
-//#include "gtkpixmapmenuitem.h"
 #include <gtk/gtkaccellabel.h>
 #include <gtk/gtksignal.h>
 #include <gtk/gtkmenuitem.h>
 #include <gtk/gtkmenu.h>
 #include <gtk/gtkcontainer.h>
 
+extern "C"
+{
+
 static void gtk_pixmap_menu_item_class_init    (GtkPixmapMenuItemClass *klass);
 static void gtk_pixmap_menu_item_init          (GtkPixmapMenuItem      *menu_item);
 static void gtk_pixmap_menu_item_draw          (GtkWidget              *widget,
@@ -1270,6 +1279,8 @@ static void changed_have_pixmap_status         (GtkPixmapMenuItem *menu_item);
 
 static GtkMenuItemClass *parent_class = NULL;
 
+}
+
 #define BORDER_SPACING  3
 #define PMAP_WIDTH 20
 
@@ -1282,7 +1293,7 @@ gtk_pixmap_menu_item_get_type (void)
     {
       GtkTypeInfo pixmap_menu_item_info =
       {
-        "GtkPixmapMenuItem",
+        (char *)"GtkPixmapMenuItem",
         sizeof (GtkPixmapMenuItem),
         sizeof (GtkPixmapMenuItemClass),
         (GtkClassInitFunc) gtk_pixmap_menu_item_class_init,
@@ -1577,26 +1588,4 @@ changed_have_pixmap_status (GtkPixmapMenuItem *menu_item)
     gtk_widget_queue_resize(GTK_WIDGET(menu_item));
 }
 
-/* Added by JACS */
-
-GtkWidget*
-gtk_pixmap_menu_item_new_with_label (const gchar *label, GtkWidget** labelWidget)
-{
-  GtkWidget *menu_item;
-  GtkWidget *accel_label;
-
-  menu_item = gtk_pixmap_menu_item_new ();
-  accel_label = gtk_accel_label_new (label);
-  if (labelWidget)
-      *labelWidget = accel_label;
-  gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
-
-  gtk_container_add (GTK_CONTAINER (menu_item), accel_label);
-  gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label), menu_item);
-  gtk_widget_show (accel_label);
-
-  return menu_item;
-}
-
-////// END CODE ADAPTED FROM GTKPIXMAPMENUITEM.C IN LIBGNOMEUI //////