X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0472ece753aa3c018dd2cc9816d3cd755f28efe8..da00a8bb164dd1f58dd0bb211475538a375867b4:/src/gtk/menu.cpp diff --git a/src/gtk/menu.cpp b/src/gtk/menu.cpp index 8474b6382e..586b2ea034 100644 --- a/src/gtk/menu.cpp +++ b/src/gtk/menu.cpp @@ -110,7 +110,7 @@ void gtk_pixmap_menu_item_set_pixmap (GtkPixmapMenuItem *menu_item, static wxString wxReplaceUnderscore( const wxString& title ) { const wxChar *pc; - + /* GTK 1.2 wants to have "_" instead of "&" for accelerators */ wxString str; for ( pc = title; *pc != wxT('\0'); pc++ ) @@ -621,21 +621,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); } //----------------------------------------------------------------------------- @@ -712,6 +716,23 @@ wxMenuItem::wxMenuItem(wxMenu *parentMenu, wxItemKind kind, wxMenu *subMenu) : wxMenuItemBase(parentMenu, id, text, help, kind, subMenu) +{ + Init(text); +} + +wxMenuItem::wxMenuItem(wxMenu *parentMenu, + int id, + const wxString& text, + const wxString& help, + bool isCheckable, + wxMenu *subMenu) + : wxMenuItemBase(parentMenu, id, text, help, + isCheckable ? wxITEM_CHECK : wxITEM_NORMAL, subMenu) +{ + Init(text); +} + +void wxMenuItem::Init(const wxString& text) { m_labelWidget = (GtkWidget *) NULL; m_menuItem = (GtkWidget *) NULL; @@ -729,7 +750,7 @@ wxMenuItem::~wxMenuItem() wxString wxMenuItemBase::GetLabelFromText(const wxString& text) { wxString label; - + for ( const wxChar *pc = text.c_str(); *pc; pc++ ) { if ( *pc == wxT('_') ) @@ -739,7 +760,7 @@ wxString wxMenuItemBase::GetLabelFromText(const wxString& text) label += *pc; continue; } - + if ( *pc == wxT('&') ) { // wxMSW escapes & @@ -754,6 +775,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) @@ -834,17 +863,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") ); } } @@ -879,10 +911,10 @@ wxString wxMenuItem::GetFactoryPath() const // remove '_' and '&' unconditionally continue; } - + path += *pc; } - + return path; } @@ -947,8 +979,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() ) @@ -965,6 +997,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, "
/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 @@ -1008,7 +1043,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) { 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); @@ -1061,11 +1096,11 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) const char *item_type; switch ( mitem->GetKind() ) { - case wxItem_Check: + case wxITEM_CHECK: item_type = ""; break; - case wxItem_Radio: + case wxITEM_RADIO: if ( m_pathLastRadio.empty() ) { // start of a new radio group @@ -1080,16 +1115,15 @@ 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: wxFAIL_MSG( _T("unexpected menu item kind") ); // fall through - case wxItem_Normal: + case wxITEM_NORMAL: item_type = ""; break; } @@ -1145,7 +1179,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) mitem->SetMenuItem(menuItem); #if GTK_CHECK_VERSION(1, 2, 0) - if ( !isRadio ) + if ( endOfRadioGroup ) { m_pathLastRadio.clear(); } @@ -1255,7 +1289,7 @@ static wxString GetHotKey( const wxMenuItem& item ) case WXK_F12: hotkey << wxT('F') << code - WXK_F1 + 1; break; - + // TODO: we should use gdk_keyval_name() (a.k.a. // XKeysymToString) here as well as hardcoding the keysym // names this might be not portable @@ -1389,7 +1423,7 @@ gtk_pixmap_menu_item_get_type (void) (GtkClassInitFunc) NULL, }; - pixmap_menu_item_type = gtk_type_unique (gtk_menu_item_get_type (), + pixmap_menu_item_type = gtk_type_unique (gtk_menu_item_get_type (), &pixmap_menu_item_info); } @@ -1399,7 +1433,7 @@ gtk_pixmap_menu_item_get_type (void) /** * gtk_pixmap_menu_item_new * - * Creates a new pixmap menu item. Use gtk_pixmap_menu_item_set_pixmap() + * Creates a new pixmap menu item. Use gtk_pixmap_menu_item_set_pixmap() * to set the pixmap wich is displayed at the left side. * * Returns: @@ -1461,7 +1495,7 @@ gtk_pixmap_menu_item_draw (GtkWidget *widget, if (GTK_WIDGET_CLASS (parent_class)->draw) (* GTK_WIDGET_CLASS (parent_class)->draw) (widget, area); - if (GTK_WIDGET_DRAWABLE (widget) && + if (GTK_WIDGET_DRAWABLE (widget) && GTK_PIXMAP_MENU_ITEM(widget)->pixmap) { gtk_widget_draw(GTK_WIDGET(GTK_PIXMAP_MENU_ITEM(widget)->pixmap),NULL); } @@ -1478,7 +1512,7 @@ gtk_pixmap_menu_item_expose (GtkWidget *widget, if (GTK_WIDGET_CLASS (parent_class)->expose_event) (* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event); - if (GTK_WIDGET_DRAWABLE (widget) && + if (GTK_WIDGET_DRAWABLE (widget) && GTK_PIXMAP_MENU_ITEM(widget)->pixmap) { gtk_widget_draw(GTK_WIDGET(GTK_PIXMAP_MENU_ITEM(widget)->pixmap),NULL); } @@ -1511,8 +1545,8 @@ gtk_pixmap_menu_item_set_pixmap (GtkPixmapMenuItem *menu_item, if (GTK_WIDGET_REALIZED (pixmap->parent) && !GTK_WIDGET_REALIZED (pixmap)) gtk_widget_realize (pixmap); - - if (GTK_WIDGET_VISIBLE (pixmap->parent)) { + + if (GTK_WIDGET_VISIBLE (pixmap->parent)) { if (GTK_WIDGET_MAPPED (pixmap->parent) && GTK_WIDGET_VISIBLE(pixmap) && !GTK_WIDGET_MAPPED (pixmap)) @@ -1520,7 +1554,7 @@ gtk_pixmap_menu_item_set_pixmap (GtkPixmapMenuItem *menu_item, } changed_have_pixmap_status(menu_item); - + if (GTK_WIDGET_VISIBLE (pixmap) && GTK_WIDGET_VISIBLE (menu_item)) gtk_widget_queue_resize (pixmap); } @@ -1606,7 +1640,7 @@ gtk_pixmap_menu_item_size_request (GtkWidget *widget, GTK_WIDGET_CLASS(parent_class)->size_request(widget,requisition); menu_item = GTK_PIXMAP_MENU_ITEM (widget); - + if (menu_item->pixmap) gtk_widget_size_request(menu_item->pixmap, &req); @@ -1627,19 +1661,19 @@ gtk_pixmap_menu_item_remove (GtkContainer *container, g_return_if_fail (GTK_IS_WIDGET (child)); bin = GTK_BIN (container); - g_return_if_fail ((bin->child == child || + g_return_if_fail ((bin->child == child || (GTK_PIXMAP_MENU_ITEM(container)->pixmap == child))); widget_was_visible = GTK_WIDGET_VISIBLE (child); - + gtk_widget_unparent (child); if (bin->child == child) - bin->child = NULL; + bin->child = NULL; else { GTK_PIXMAP_MENU_ITEM(container)->pixmap = NULL; changed_have_pixmap_status(GTK_PIXMAP_MENU_ITEM(container)); } - + if (widget_was_visible) gtk_widget_queue_resize (GTK_WIDGET (container)); } @@ -1661,7 +1695,7 @@ changed_have_pixmap_status (GtkPixmapMenuItem *menu_item) if (GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item)->have_pixmap_count == 0) { /* Install normal toggle size */ - GTK_MENU_ITEM_GET_CLASS(menu_item)->toggle_size = GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item)->orig_toggle_size; + GTK_MENU_ITEM_GET_CLASS(menu_item)->toggle_size = GTK_PIXMAP_MENU_ITEM_GET_CLASS(menu_item)->orig_toggle_size; } } @@ -1670,7 +1704,7 @@ changed_have_pixmap_status (GtkPixmapMenuItem *menu_item) this function is called, we get the same effect, just because of how the preferences option to show pixmaps works. Bogus, broken. */ - if (GTK_WIDGET_VISIBLE(GTK_WIDGET(menu_item))) + if (GTK_WIDGET_VISIBLE(GTK_WIDGET(menu_item))) gtk_widget_queue_resize(GTK_WIDGET(menu_item)); }