]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/menu.cpp
fixed bug due to which all items in a virtual control stayed sometimes selected even...
[wxWidgets.git] / src / gtk1 / menu.cpp
index b2098039c68e09bf1f5f1c8acecc1c5fdfbb54b9..d74c9b2ca6211f0f7df9ac2ff81baffdb2c3d4ad 100644 (file)
@@ -117,14 +117,25 @@ static wxString wxReplaceUnderscore( const wxString& title )
     {
         if (*pc == wxT('&'))
         {
-#if GTK_CHECK_VERSION(1, 2, 1)
+#if GTK_CHECK_VERSION(1, 2, 0)
             str << wxT('_');
+#endif
+        }
+#if GTK_CHECK_VERSION(2, 0, 0)
+        else if (*pc == wxT('/'))
+        {
+            str << wxT("\\/");
+        }
+        else if (*pc == wxT('\\'))
+        {
+            str << wxT("\\\\");
         }
+#elif GTK_CHECK_VERSION(1, 2, 0)
         else if (*pc == wxT('/'))
         {
             str << wxT('\\');
-#endif
         }
+#endif
         else
         {
 #if __WXGTK12__
@@ -621,21 +632,25 @@ static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu )
 
     if (item->IsCheckable())
     {
-        bool isReallyChecked = item->IsChecked();
-        if ( item->wxMenuItemBase::IsChecked() == isReallyChecked )
+        bool isReallyChecked = item->IsChecked(),
+             isInternallyChecked = item->wxMenuItemBase::IsChecked();
+
+        // ensure that the internal state is always consistent with what is
+        // shown on the screen
+        item->wxMenuItemBase::Check(isReallyChecked);
+
+        // we must not report the events for the radio button going up nor the
+        // events resulting from the calls to wxMenuItem::Check()
+        if ( (item->GetKind() == wxITEM_RADIO && !isReallyChecked) ||
+             (isInternallyChecked == isReallyChecked) )
         {
-            /* the menu item has been checked by calling wxMenuItem->Check() */
             return;
         }
-        else
-        {
-            /* the user pressed on the menu item -> report and make consistent
-             * again */
-            item->wxMenuItemBase::Check(isReallyChecked);
-        }
+
+        // the user pressed on the menu item: report the event below
     }
 
-    menu->SendEvent(item->GetId(), item->IsCheckable() ? item->IsChecked() : -1);
+    menu->SendEvent(id, item->IsCheckable() ? item->IsChecked() : -1);
 }
 
 //-----------------------------------------------------------------------------
@@ -713,7 +728,7 @@ wxMenuItem::wxMenuItem(wxMenu *parentMenu,
                        wxMenu *subMenu)
           : wxMenuItemBase(parentMenu, id, text, help, kind, subMenu)
 {
-    Init();
+    Init(text);
 }
 
 wxMenuItem::wxMenuItem(wxMenu *parentMenu,
@@ -725,15 +740,15 @@ wxMenuItem::wxMenuItem(wxMenu *parentMenu,
           : wxMenuItemBase(parentMenu, id, text, help,
                            isCheckable ? wxITEM_CHECK : wxITEM_NORMAL, subMenu)
 {
-    Init();
+    Init(text);
 }
 
-void wxMenuItem::Init()
+void wxMenuItem::Init(const wxString& text)
 {
     m_labelWidget = (GtkWidget *) NULL;
     m_menuItem = (GtkWidget *) NULL;
 
-    DoSetText(m_text);
+    DoSetText(text);
 }
 
 wxMenuItem::~wxMenuItem()
@@ -771,6 +786,14 @@ wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
 
 void wxMenuItem::SetText( const wxString& str )
 {
+    // Some optimization to avoid flicker
+    wxString oldLabel = m_text;
+    oldLabel = wxStripMenuCodes(oldLabel.BeforeFirst('\t'));
+    oldLabel.Replace(wxT("_"), wxT(""));
+    wxString label1 = wxStripMenuCodes(str.BeforeFirst('\t'));
+    if (oldLabel == label1)
+        return;
+    
     DoSetText(str);
 
     if (m_menuItem)
@@ -798,20 +821,35 @@ void wxMenuItem::DoSetText( const wxString& str )
     const wxChar *pc = str;
     for (; (*pc != wxT('\0')) && (*pc != wxT('\t')); pc++ )
     {
+#if GTK_CHECK_VERSION(1, 2, 0)
         if (*pc == wxT('&'))
         {
-#if GTK_CHECK_VERSION(1, 2, 0)
             m_text << wxT('_');
         }
         else if ( *pc == wxT('_') )    // escape underscores
         {
             m_text << wxT("__");
         }
+#else // GTK+ < 1.2.0
+        if (*pc == wxT('&'))
+        {
+        }
+#endif
+#if GTK_CHECK_VERSION(2, 0, 0)
+        else if (*pc == wxT('/'))      // we have to escape slashes
+        {
+            m_text << wxT("\\/");
+        }
+        else if (*pc == wxT('\\'))     // we have to double backslashes
+        {
+            m_text << wxT("\\\\");
+        }
+#elif GTK_CHECK_VERSION(1, 2, 0)
         else if (*pc == wxT('/'))      /* we have to filter out slashes ... */
         {
             m_text << wxT('\\');  /* ... and replace them with back slashes */
-#endif // GTK+ 1.2.0+
         }
+#endif
         else
             m_text << *pc;
     }
@@ -851,17 +889,20 @@ void wxMenuItem::Check( bool check )
 {
     wxCHECK_RET( m_menuItem, wxT("invalid menu item") );
 
-    wxCHECK_RET( IsCheckable(), wxT("Can't check uncheckable item!") )
-
     if (check == m_isChecked)
         return;
 
     wxMenuItemBase::Check( check );
 
-    // GTK+ does it itself for the radio item
-    if ( GetKind() == wxITEM_CHECK )
+    switch ( GetKind() )
     {
-        gtk_check_menu_item_set_state( (GtkCheckMenuItem*)m_menuItem, (gint)check );
+        case wxITEM_CHECK:
+        case wxITEM_RADIO:
+            gtk_check_menu_item_set_state( (GtkCheckMenuItem*)m_menuItem, (gint)check );
+            break;
+
+        default:
+            wxFAIL_MSG( _T("can't check this item") );
     }
 }
 
@@ -964,8 +1005,8 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem)
 #endif
 
 #if GTK_CHECK_VERSION(1, 2, 0)
-    // is this a radio item?
-    bool isRadio = FALSE;
+    // does this item terminate the current radio group?
+    bool endOfRadioGroup = TRUE;
 #endif // GTK+ >= 1.2
 
     if ( mitem->IsSeparator() )
@@ -982,6 +1023,9 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem)
 
         /* this will be wrong for more than one separator. do we care? */
         menuItem = gtk_item_factory_get_widget( m_factory, "<main>/sep" );
+
+        // we might have a separator inside a radio group
+        endOfRadioGroup = FALSE;
 #else // GTK+ 1.0
         menuItem = gtk_menu_item_new();
 #endif // GTK 1.2/1.0
@@ -1097,9 +1141,8 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem)
                     item_type = pathRadio;
                 }
 
-                // remember that this one was a radio item to avoid resetting
-                // m_pathLastRadio below
-                isRadio = TRUE;
+                // continue the existing radio group, if any
+                endOfRadioGroup = FALSE;
                 break;
 
             default:
@@ -1162,7 +1205,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem)
     mitem->SetMenuItem(menuItem);
 
 #if GTK_CHECK_VERSION(1, 2, 0)
-    if ( !isRadio )
+    if ( endOfRadioGroup )
     {
         m_pathLastRadio.clear();
     }