]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/menu.cpp
implement wxEventLoop::DispatchTimeout() for wxGTK (thanks Paul) and rewrote it to...
[wxWidgets.git] / src / gtk1 / menu.cpp
index f19e78a48110f248d96a55a1ce76189a09d08339..beeab89cd94c0b1fa047d16da81435780384a382 100644 (file)
@@ -11,6 +11,7 @@
 #include "wx/wxprec.h"
 
 #include "wx/menu.h"
+#include "wx/stockitem.h"
 
 #ifndef WX_PRECOMP
     #include "wx/intl.h"
@@ -90,6 +91,41 @@ static wxString wxReplaceUnderscore( const wxString& title )
     return str;
 }
 
+static wxString wxConvertFromGTKToWXLabel(const wxString& gtkLabel)
+{
+    wxString label;
+    for ( const wxChar *pc = gtkLabel.c_str(); *pc; pc++ )
+    {
+        // '_' is the escape character for GTK+.
+
+        if ( *pc == wxT('_') && *(pc+1) == wxT('_'))
+        {
+            // An underscore was escaped.
+            label += wxT('_');
+            pc++;
+        }
+        else if ( *pc == wxT('_') )
+        {
+            // Convert GTK+ hotkey symbol to wxWidgets/Windows standard
+            label += wxT('&');
+        }
+        else if ( *pc == wxT('&') )
+        {
+            // Double the ampersand to escape it as far as wxWidgets is concerned
+            label += wxT("&&");
+        }
+        else
+        {
+            // don't remove ampersands '&' since if we have them in the menu title
+            // it means that they were doubled to indicate "&" instead of accelerator
+            label += *pc;
+        }
+    }
+
+    return label;
+}
+
+
 //-----------------------------------------------------------------------------
 // activate message from GTK
 //-----------------------------------------------------------------------------
@@ -107,19 +143,19 @@ static void DoCommonMenuCallbackCode(wxMenu *menu, wxMenuEvent& event)
 
     wxWindow *win = menu->GetInvokingWindow();
     if (win)
-        win->GetEventHandler()->ProcessEvent( event );
+        win->HandleWindowEvent( event );
 }
 
 extern "C" {
 
-static void gtk_menu_open_callback( GtkWidget *widget, wxMenu *menu )
+static void gtk_menu_open_callback( GtkWidget *WXUNUSED(widget), wxMenu *menu )
 {
     wxMenuEvent event(wxEVT_MENU_OPEN, -1, menu);
 
     DoCommonMenuCallbackCode(menu, event);
 }
 
-static void gtk_menu_close_callback( GtkWidget *widget, wxMenuBar *menubar )
+static void gtk_menu_close_callback( GtkWidget *WXUNUSED(widget), wxMenuBar *menubar )
 {
     if ( !menubar->GetMenuCount() )
     {
@@ -407,7 +443,7 @@ wxMenu *wxMenuBar::Remove(size_t pos)
 
 static int FindMenuItemRecursive( const wxMenu *menu, const wxString &menuString, const wxString &itemString )
 {
-    if (wxMenuItem::GetLabelFromText(menu->GetTitle()) == wxMenuItem::GetLabelFromText(menuString))
+    if (wxMenuItem::GetLabelText(wxConvertFromGTKToWXLabel(menu->GetTitle())) == wxMenuItem::GetLabelText(menuString))
     {
         int res = menu->FindItem( itemString );
         if (res != wxNOT_FOUND)
@@ -492,7 +528,7 @@ void wxMenuBar::EnableTop( size_t pos, bool flag )
         gtk_widget_set_sensitive( menu->m_owner, flag );
 }
 
-wxString wxMenuBar::GetLabelTop( size_t pos ) const
+wxString wxMenuBar::GetMenuLabel( size_t pos ) const
 {
     wxMenuList::compatibility_iterator node = m_menus.Item( pos );
 
@@ -500,26 +536,10 @@ wxString wxMenuBar::GetLabelTop( size_t pos ) const
 
     wxMenu* menu = node->GetData();
 
-    wxString label;
-    wxString text( menu->GetTitle() );
-    for ( const wxChar *pc = text.c_str(); *pc; pc++ )
-    {
-        if ( *pc == wxT('_') )
-        {
-            // '_' is the escape character for GTK+
-            continue;
-        }
-
-        // don't remove ampersands '&' since if we have them in the menu title
-        // it means that they were doubled to indicate "&" instead of accelerator
-
-        label += *pc;
-    }
-
-    return label;
+    return wxConvertFromGTKToWXLabel(menu->GetTitle());
 }
 
-void wxMenuBar::SetLabelTop( size_t pos, const wxString& label )
+void wxMenuBar::SetMenuLabel( size_t pos, const wxString& label )
 {
     wxMenuList::compatibility_iterator node = m_menus.Item( pos );
 
@@ -612,7 +632,7 @@ static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu )
             commandEvent.SetInt(item->IsChecked());
         commandEvent.SetEventObject(menu);
 
-        frame->GetEventHandler()->ProcessEvent(commandEvent);
+        frame->HandleWindowEvent(commandEvent);
     }
     else
     {
@@ -646,7 +666,7 @@ static void gtk_menu_hilight_callback( GtkWidget *widget, wxMenu *menu )
         return;
 
     wxWindow *win = menu->GetInvokingWindow();
-    if (win) win->GetEventHandler()->ProcessEvent( event );
+    if (win) win->HandleWindowEvent( event );
 }
 }
 
@@ -675,7 +695,7 @@ static void gtk_menu_nolight_callback( GtkWidget *widget, wxMenu *menu )
 
     wxWindow *win = menu->GetInvokingWindow();
     if (win)
-        win->GetEventHandler()->ProcessEvent( event );
+        win->HandleWindowEvent( event );
 }
 }
 
@@ -703,7 +723,7 @@ wxMenuItem::wxMenuItem(wxMenu *parentMenu,
                        wxMenu *subMenu)
           : wxMenuItemBase(parentMenu, id, text, help, kind, subMenu)
 {
-    Init(text);
+    Init();
 }
 
 wxMenuItem::wxMenuItem(wxMenu *parentMenu,
@@ -715,15 +735,15 @@ wxMenuItem::wxMenuItem(wxMenu *parentMenu,
           : wxMenuItemBase(parentMenu, id, text, help,
                            isCheckable ? wxITEM_CHECK : wxITEM_NORMAL, subMenu)
 {
-    Init(text);
+    Init();
 }
 
-void wxMenuItem::Init(const wxString& text)
+void wxMenuItem::Init()
 {
     m_labelWidget = (GtkWidget *) NULL;
     m_menuItem = (GtkWidget *) NULL;
 
-    DoSetText(text);
+    DoSetText(m_text);
 }
 
 wxMenuItem::~wxMenuItem()
@@ -731,42 +751,24 @@ wxMenuItem::~wxMenuItem()
    // don't delete menu items, the menus take care of that
 }
 
-// return the menu item text without any menu accels
-/* static */
-wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
+wxString wxMenuItem::GetItemLabel() const
 {
-    wxString label;
-
-    for ( const wxChar *pc = text.c_str(); *pc; pc++ )
-    {
-        if ( *pc == wxT('\t'))
-            break;
-
-        if ( *pc == wxT('_') )
-        {
-            // GTK 1.2 escapes "xxx_xxx" to "xxx__xxx"
-            pc++;
-            label += *pc;
-            continue;
-        }
-
-        if ( (*pc == wxT('&')) && (*(pc+1) != wxT('&')) )
-        {
-            // wxMSW escapes "&"
-            // "&" is doubled to indicate "&" instead of accelerator
-            continue;
-        }
-
-        label += *pc;
-    }
-
-    // wxPrintf( wxT("GetLabelFromText(): text %s label %s\n"), text.c_str(), label.c_str() );
-
+    wxString label = wxConvertFromGTKToWXLabel(m_text);
+    if (!m_hotKey.IsEmpty())
+        label = label + wxT("\t") + m_hotKey;
     return label;
 }
 
-void wxMenuItem::SetText( const wxString& str )
+void wxMenuItem::SetItemLabel( const wxString& string )
 {
+    wxString str = string;
+    if ( str.empty() && !IsSeparator() )
+    {
+        wxASSERT_MSG(wxIsStockID(GetId()), wxT("A non-stock menu item with an empty label?"));
+        str = wxGetStockLabel(GetId(), wxSTOCK_WITH_ACCELERATOR |
+                                       wxSTOCK_WITH_MNEMONIC);
+    }
+
     // Some optimization to avoid flicker
     wxString oldLabel = m_text;
     oldLabel = wxStripMenuCodes(oldLabel);
@@ -825,7 +827,9 @@ void wxMenuItem::SetText( const wxString& str )
 void wxMenuItem::DoSetText( const wxString& str )
 {
     // '\t' is the deliminator indicating a hot key
-    m_text.Empty();
+    wxString text;
+    text.reserve(str.length());
+
     const wxChar *pc = str;
     while ( (*pc != wxT('\0')) && (*pc != wxT('\t')) )
     {
@@ -833,32 +837,32 @@ void wxMenuItem::DoSetText( const wxString& str )
         {
             // "&" is doubled to indicate "&" instead of accelerator
             ++pc;
-            m_text << wxT('&');
+            text << wxT('&');
         }
         else if (*pc == wxT('&'))
         {
-            m_text << wxT('_');
+            text << wxT('_');
         }
         else if ( *pc == wxT('_') )    // escape underscores
         {
-            m_text << wxT("__");
+            text << wxT("__");
         }
         else
         {
-            m_text << *pc;
+            text << *pc;
         }
         ++pc;
     }
 
     m_hotKey = wxEmptyString;
 
-    if(*pc == wxT('\t'))
+    if ( *pc == wxT('\t') )
     {
        pc++;
        m_hotKey = pc;
     }
 
-    // wxPrintf( wxT("DoSetText(): str %s m_text %s hotkey %s\n"), str.c_str(), m_text.c_str(), m_hotKey.c_str() );
+    m_text = text;
 }
 
 #if wxUSE_ACCEL
@@ -871,11 +875,12 @@ wxAcceleratorEntry *wxMenuItem::GetAccel() const
         return (wxAcceleratorEntry *)NULL;
     }
 
-    // as wxGetAccelFromString() looks for TAB, insert a dummy one here
+    // accelerator parsing code looks for them after a TAB, so insert a dummy
+    // one here
     wxString label;
     label << wxT('\t') << GetHotKey();
 
-    return wxGetAccelFromString(label);
+    return wxAcceleratorEntry::Create(label);
 }
 
 #endif // wxUSE_ACCEL
@@ -984,7 +989,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
     }
     else if (mitem->GetBitmap().Ok())
     {
-        text = mitem->GetText();
+        text = mitem->wxMenuItemBase::GetItemLabel();
         const wxBitmap *bitmap = &mitem->GetBitmap();
 
         // TODO
@@ -996,8 +1001,8 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
     }
     else // a normal item
     {
-        // text has "_" instead of "&" after mitem->SetText() so don't use it
-        text =  mitem->GetText() ;
+        // text has "_" instead of "&" after mitem->SetItemLabel() so don't use it
+        text =  mitem->wxMenuItemBase::GetItemLabel() ;
 
         switch ( mitem->GetKind() )
         {
@@ -1050,7 +1055,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
     GdkModifierType accel_mods;
     wxCharBuffer buf = wxGTK_CONV( GetGtkHotKey(*mitem) );
 
-    // wxPrintf( wxT("item: %s hotkey %s\n"), mitem->GetText().c_str(), GetGtkHotKey(*mitem).c_str() );
+    // wxPrintf( wxT("item: %s hotkey %s\n"), mitem->GetItemLabel().c_str(), GetGtkHotKey(*mitem).c_str() );
     gtk_accelerator_parse( (const char*) buf, &accel_key, &accel_mods);
     if (accel_key != 0)
     {
@@ -1236,10 +1241,10 @@ static wxString GetGtkHotKey( const wxMenuItem& item )
                 hotkey << wxT("Down" );
                 break;
             case WXK_PAGEUP:
-                hotkey << wxT("PgUp" );
+                hotkey << wxT("Page_Up" );
                 break;
             case WXK_PAGEDOWN:
-                hotkey << wxT("PgDn" );
+                hotkey << wxT("Page_Down" );
                 break;
             case WXK_LEFT:
                 hotkey << wxT("Left" );
@@ -1357,10 +1362,10 @@ static wxString GetGtkHotKey( const wxMenuItem& item )
                 hotkey << wxT("KP_Down" );
                 break;
             case WXK_NUMPAD_PAGEUP:
-                hotkey << wxT("KP_PgUp" );
+                hotkey << wxT("KP_Page_Up" );
                 break;
             case WXK_NUMPAD_PAGEDOWN:
-                hotkey << wxT("KP_PgDn" );
+                hotkey << wxT("KP_Page_Down" );
                 break;
             case WXK_NUMPAD_END:
                 hotkey << wxT("KP_End" );
@@ -1415,14 +1420,14 @@ static wxString GetGtkHotKey( const wxMenuItem& item )
                 hotkey += wxString::Format(wxT("Special%d"), code - WXK_SPECIAL1 + 1);
                 break;
           */
-                // if there are any other keys wxGetAccelFromString() may
+                // if there are any other keys wxAcceleratorEntry::Create() may
                 // return, we should process them here
 
             default:
                 if ( code < 127 )
                 {
                     wxString name = wxGTK_CONV_BACK( gdk_keyval_name((guint)code) );
-                    if ( name )
+                    if ( !name.empty() )
                     {
                         hotkey << name;
                         break;