]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/menu.cpp
GetLabelTop should return the stripped label, for compatibility.
[wxWidgets.git] / src / gtk / menu.cpp
index 65006103ee5ef64565f7b0a18bc5cf98b4027fe4..002d5f5668b3f7ba091c7bff6135cae4da6347d9 100644 (file)
@@ -1,6 +1,6 @@
 /////////////////////////////////////////////////////////////////////////////
 // Name:        src/gtk/menu.cpp
-// Purpose:
+// Purpose:     implementation of wxMenuBar and wxMenu classes for wxGTK
 // Author:      Robert Roebling
 // Id:          $Id$
 // Copyright:   (c) 1998 Robert Roebling
@@ -10,6 +10,8 @@
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
+#if wxUSE_MENUS
+
 #include "wx/menu.h"
 
 #ifndef WX_PRECOMP
@@ -55,14 +57,12 @@ static wxString GetGtkHotKey( const wxMenuItem& item );
 
 static wxString wxReplaceUnderscore( const wxString& title )
 {
-    const wxChar *pc;
-
     // GTK 1.2 wants to have "_" instead of "&" for accelerators
     wxString str;
-    pc = title;
-    while (*pc != wxT('\0'))
+
+    for ( wxString::const_iterator pc = title.begin(); pc != title.end(); ++pc )
     {
-        if ((*pc == wxT('&')) && (*(pc+1) == wxT('&')))
+        if ((*pc == wxT('&')) && (pc+1 != title.end()) && (*(pc+1) == wxT('&')))
         {
             // "&" is doubled to indicate "&" instead of accelerator
             ++pc;
@@ -83,7 +83,6 @@ static wxString wxReplaceUnderscore( const wxString& title )
 
             str << *pc;
         }
-        ++pc;
     }
 
     // wxPrintf( wxT("before %s after %s\n"), title.c_str(), str.c_str() );
@@ -91,6 +90,40 @@ 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
 //-----------------------------------------------------------------------------
@@ -140,13 +173,11 @@ IMPLEMENT_DYNAMIC_CLASS(wxMenuBar,wxWindow)
 
 void wxMenuBar::Init(size_t n, wxMenu *menus[], const wxString titles[], long style)
 {
-    // the parent window is known after wxFrame::SetMenu()
-    m_needParent = false;
     m_style = style;
-    m_invokingWindow = (wxWindow*) NULL;
+    m_invokingWindow = NULL;
 
-    if (!PreCreation( (wxWindow*) NULL, wxDefaultPosition, wxDefaultSize ) ||
-        !CreateBase( (wxWindow*) NULL, -1, wxDefaultPosition, wxDefaultSize, style, wxDefaultValidator, wxT("menubar") ))
+    if (!PreCreation( NULL, wxDefaultPosition, wxDefaultSize ) ||
+        !CreateBase( NULL, -1, wxDefaultPosition, wxDefaultSize, style, wxDefaultValidator, wxT("menubar") ))
     {
         wxFAIL_MSG( wxT("wxMenuBar creation failed") );
         return;
@@ -422,7 +453,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)
@@ -507,7 +538,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 );
 
@@ -515,26 +546,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 );
 
@@ -731,8 +746,15 @@ wxMenuItem::~wxMenuItem()
 
 // return the menu item text without any menu accels
 /* static */
-wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
+
+wxString wxMenuItemBase::GetLabelText(const wxString& text)
 {
+    // The argument to this function will now always be in wxWidgets standard label
+    // format, not GTK+ format, so we do what the other ports do.
+
+    return wxStripMenuCodes(text);
+
+#if 0
     wxString label;
 
     for ( const wxChar *pc = text.c_str(); *pc; pc++ )
@@ -766,12 +788,21 @@ wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
         label += *pc;
     }
 
-    // wxPrintf( wxT("GetLabelFromText(): text %s label %s\n"), text.c_str(), label.c_str() );
+    // wxPrintf( wxT("GetLabelText(): text %s label %s\n"), text.c_str(), label.c_str() );
 
     return label;
+#endif
 }
 
-void wxMenuItem::SetText( const wxString& str )
+wxString wxMenuItem::GetItemLabel() const
+{
+    wxString label = wxConvertFromGTKToWXLabel(m_text);
+    if (!m_hotKey.IsEmpty())
+        label = label + wxT("\t") + m_hotKey;
+    return label;
+}
+
+void wxMenuItem::SetItemLabel( const wxString& str )
 {
     // cache some data which must be used later
     bool isstock = wxIsStockID(GetId());
@@ -866,25 +897,29 @@ void wxMenuItem::SetText( const wxString& str )
 }
 
 // NOTE: this function is different from the similar functions GTKProcessMnemonics()
-//       implemented in control.cpp and from wxMenuItemBase::GetLabelFromText...
+//       implemented in control.cpp and from wxMenuItemBase::GetLabelText...
 //       so there's no real code duplication
 wxString wxMenuItem::GTKProcessMenuItemLabel(const wxString& str, wxString *hotKey)
 {
     wxString text;
 
     // '\t' is the deliminator indicating a hot key
-    const wxChar *pc = str;
-    while ( (*pc != wxT('\0')) && (*pc != wxT('\t')) )
+    wxString::const_iterator pc = str.begin();
+    while ( pc != str.end() && *pc != wxT('\t') )
     {
-        if ((*pc == wxT('&')) && (*(pc+1) == wxT('&')))
-        {
-            // "&" is doubled to indicate "&" instead of accelerator
-            ++pc;
-            text << wxT('&');
-        }
-        else if (*pc == wxT('&'))
+        if (*pc == wxT('&'))
         {
-            text << wxT('_');
+            wxString::const_iterator next = pc + 1;
+            if (next != str.end() && *next == wxT('&'))
+            {
+                // "&" is doubled to indicate "&" instead of accelerator
+                ++pc;
+                text << wxT('&');
+            }
+            else
+            {
+                text << wxT('_');
+            }
         }
         else if ( *pc == wxT('_') )    // escape underscores
         {
@@ -903,7 +938,7 @@ wxString wxMenuItem::GTKProcessMenuItemLabel(const wxString& str, wxString *hotK
         if(*pc == wxT('\t'))
         {
             pc++;
-            *hotKey = pc;
+            hotKey->assign(pc, str.end());
         }
     }
 
@@ -1020,6 +1055,8 @@ wxMenu::~wxMenu()
    {
        // see wxMenu::Init
        gtk_widget_unref( m_menu );
+       g_object_unref( m_accel );
+
        // if the menu is inserted in another menu at this time, there was
        // one more reference to it:
        if ( m_owner )
@@ -1044,7 +1081,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
     GtkWidget *menuItem;
 
     // cache some data used later
-    wxString text = mitem->GetText();
+    wxString text = mitem->wxMenuItemBase::GetItemLabel();
     int id = mitem->GetId();
     bool isstock = wxIsStockID(id);
     const char *stockid = NULL;
@@ -1110,7 +1147,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
     }
     else // a normal item
     {
-        // NB: 'text' variable has "_" instead of "&" after mitem->SetText()
+        // NB: 'text' variable has "_" instead of "&" after mitem->SetItemLabel()
         //     so don't use it
 
         switch ( mitem->GetKind() )
@@ -1158,7 +1195,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
     GdkModifierType accel_mods;
     wxCharBuffer buf = wxGTK_CONV_SYS( 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() );
     if (buf[(size_t)0] != '\0')
     {
         gtk_accelerator_parse( (const char*) buf, &accel_key, &accel_mods);
@@ -1791,3 +1828,5 @@ bool wxGetStockGtkAccelerator(const char *id, GdkModifierType *mod, guint *key)
 }
 
 #endif // __WXGTK20__
+
+#endif // wxUSE_MENUS