X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/092f753690cec1f4ee3a7ad2df53afc70caaa2f3..28ff8c8f9e230d148123c1c18b1f9eabcc6e6c66:/src/gtk1/menu.cpp diff --git a/src/gtk1/menu.cpp b/src/gtk1/menu.cpp index e6789d180b..66cb098d1f 100644 --- a/src/gtk1/menu.cpp +++ b/src/gtk1/menu.cpp @@ -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__ @@ -230,14 +241,12 @@ static void wxMenubarUnsetInvokingWindow( wxMenu *menu, wxWindow *win ) { menu->SetInvokingWindow( (wxWindow*) NULL ); -#if GTK_CHECK_VERSION(1, 2, 0) wxWindow *top_frame = win; while (top_frame->GetParent() && !(top_frame->IsTopLevel())) top_frame = top_frame->GetParent(); - /* support for native hot keys */ + /* support for native hot keys */ gtk_accel_group_detach( menu->m_accel, ACCEL_OBJ_CAST(top_frame->m_widget) ); -#endif wxMenuItemList::Node *node = menu->GetMenuItems().GetFirst(); while (node) @@ -336,12 +345,12 @@ bool wxMenuBar::GtkAppend(wxMenu *menu, const wxString& title) /* GTK 1.2.0 doesn't have gtk_item_factory_get_item(), but GTK 1.2.1 has. */ #if GTK_CHECK_VERSION(1, 2, 1) - /* local buffer in multibyte form */ wxString buf; buf << wxT('/') << str.c_str(); - char *cbuf = new char[buf.Length()+1]; - strcpy(cbuf, buf.mbc_str()); + /* local buffer in multibyte form */ + char cbuf[400]; + strcpy(cbuf, wxGTK_CONV(buf) ); GtkItemFactoryEntry entry; entry.path = (gchar *)cbuf; // const_cast @@ -363,12 +372,11 @@ bool wxMenuBar::GtkAppend(wxMenu *menu, const wxString& title) pc++; tmp << *pc; } - menu->m_owner = gtk_item_factory_get_item( m_factory, tmp.mb_str() ); + menu->m_owner = gtk_item_factory_get_item( m_factory, wxGTK_CONV( tmp ) ); gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu->m_owner), menu->m_menu ); - delete [] cbuf; #else - menu->m_owner = gtk_menu_item_new_with_label( str.mb_str() ); + menu->m_owner = gtk_menu_item_new_with_label( wxGTK_CONV( str ) ); gtk_widget_show( menu->m_owner ); gtk_menu_item_set_submenu( GTK_MENU_ITEM(menu->m_owner), menu->m_menu ); @@ -389,7 +397,6 @@ bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title) if ( !wxMenuBarBase::Insert(pos, menu, title) ) return FALSE; -#if __WXGTK12__ // GTK+ doesn't have a function to insert a menu using GtkItemFactory (as // of version 1.2.6), so we first append the item and then change its // index @@ -405,14 +412,6 @@ bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title) menu_shell->children = g_list_insert(menu_shell->children, data, pos); return TRUE; -#else // GTK < 1.2 - // this should be easy to do with GTK 1.0 - can use standard functions for - // this and don't need any hacks like above, but as I don't have GTK 1.0 - // any more I can't do it - wxFAIL_MSG( wxT("TODO") ); - - return FALSE; -#endif // GTK 1.2/1.0 } wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title) @@ -553,7 +552,6 @@ wxString wxMenuBar::GetLabelTop( size_t pos ) const wxString label; wxString text( menu->GetTitle() ); -#if GTK_CHECK_VERSION(1, 2, 0) for ( const wxChar *pc = text.c_str(); *pc; pc++ ) { if ( *pc == wxT('_') || *pc == wxT('&') ) @@ -565,9 +563,6 @@ wxString wxMenuBar::GetLabelTop( size_t pos ) const label += *pc; } -#else // GTK+ 1.0 - label = text; -#endif // GTK+ 1.2/1.0 return label; } @@ -589,10 +584,10 @@ void wxMenuBar::SetLabelTop( size_t pos, const wxString& label ) GtkLabel *label = GTK_LABEL( GTK_BIN(menu->m_owner)->child ); /* set new text */ - gtk_label_set( label, str.mb_str()); + gtk_label_set( label, wxGTK_CONV( str ) ); /* reparse key accel */ - (void)gtk_label_parse_uline (GTK_LABEL(label), str.mb_str() ); + (void)gtk_label_parse_uline (GTK_LABEL(label), wxGTK_CONV( str ) ); gtk_accel_label_refetch( GTK_ACCEL_LABEL(label) ); } @@ -621,21 +616,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); } //----------------------------------------------------------------------------- @@ -771,6 +770,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) @@ -782,10 +789,10 @@ void wxMenuItem::SetText( const wxString& str ) label = GTK_LABEL( GTK_BIN(m_menuItem)->child ); /* set new text */ - gtk_label_set( label, m_text.mb_str()); + gtk_label_set( label, wxGTK_CONV( m_text ) ); /* reparse key accel */ - (void)gtk_label_parse_uline (GTK_LABEL(label), m_text.mb_str() ); + (void)gtk_label_parse_uline (GTK_LABEL(label), wxGTK_CONV( m_text ) ); gtk_accel_label_refetch( GTK_ACCEL_LABEL(label) ); } } @@ -798,34 +805,46 @@ 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; } - /* only GTK 1.2 knows about hot keys */ m_hotKey = wxT(""); -#if GTK_CHECK_VERSION(1, 2, 0) if(*pc == wxT('\t')) { pc++; m_hotKey = pc; } -#endif // GTK+ 1.2.0+ } #if wxUSE_ACCEL @@ -851,17 +870,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") ); } } @@ -911,17 +933,12 @@ IMPLEMENT_DYNAMIC_CLASS(wxMenu,wxEvtHandler) void wxMenu::Init() { -#if GTK_CHECK_VERSION(1, 2, 0) m_accel = gtk_accel_group_new(); m_factory = gtk_item_factory_new( GTK_TYPE_MENU, "
", m_accel ); m_menu = gtk_item_factory_get_widget( m_factory, "
" ); -#else - m_menu = gtk_menu_new(); // Do not show! -#endif m_owner = (GtkWidget*) NULL; -#if GTK_CHECK_VERSION(1, 2, 0) /* Tearoffs are entries, just like separators. So if we want this menu to be a tear-off one, we just append a tearoff entry immediately. */ @@ -936,7 +953,6 @@ void wxMenu::Init() gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */ //GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "
/tearoff" ); } -#endif // GTK+ 1.2.0+ // append the title as the very first entry if we have it if ( !!m_title ) @@ -963,14 +979,11 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) bool appended = FALSE; #endif -#if GTK_CHECK_VERSION(1, 2, 0) - // is this a radio item? - bool isRadio = FALSE; -#endif // GTK+ >= 1.2 + // does this item terminate the current radio group? + bool endOfRadioGroup = TRUE; if ( mitem->IsSeparator() ) { -#if GTK_CHECK_VERSION(1, 2, 0) GtkItemFactoryEntry entry; entry.path = (char *)"/sep"; entry.callback = (GtkItemFactoryCallback) NULL; @@ -982,20 +995,19 @@ 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" ); -#else // GTK+ 1.0 - menuItem = gtk_menu_item_new(); -#endif // GTK 1.2/1.0 + + // we might have a separator inside a radio group + endOfRadioGroup = FALSE; } else if ( mitem->IsSubMenu() ) { -#if GTK_CHECK_VERSION(1, 2, 0) /* text has "_" instead of "&" after mitem->SetText() */ wxString text( mitem->GetText() ); /* local buffer in multibyte form */ char buf[200]; strcpy( buf, "/" ); - strcat( buf, text.mb_str() ); + strcat( buf, wxGTK_CONV( text ) ); GtkItemFactoryEntry entry; entry.path = buf; @@ -1007,10 +1019,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */ wxString path( mitem->GetFactoryPath() ); - menuItem = gtk_item_factory_get_item( m_factory, path.mb_str() ); -#else // GTK+ 1.0 - menuItem = gtk_menu_item_new_with_label(mitem->GetText().mbc_str()); -#endif // GTK 1.2/1.0 + menuItem = gtk_item_factory_get_item( m_factory, wxGTK_CONV( path ) ); gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), mitem->GetSubMenu()->m_menu ); @@ -1027,10 +1036,10 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) const wxBitmap *bitmap = &mitem->GetBitmap(); menuItem = gtk_pixmap_menu_item_new (); - GtkWidget *label = gtk_accel_label_new (text.mb_str()); + GtkWidget *label = gtk_accel_label_new ( wxGTK_CONV( text ) ); 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() ); + guint accel_key = gtk_label_parse_uline (GTK_LABEL(label), wxGTK_CONV( text ) ); gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), menuItem); if (accel_key != GDK_VoidSymbol) { @@ -1059,14 +1068,13 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) #endif // USE_MENU_BITMAPS else // a normal item { -#if GTK_CHECK_VERSION(1, 2, 0) - /* text has "_" instead of "&" after mitem->SetText() */ + // text has "_" instead of "&" after mitem->SetText() so don't use it wxString text( mitem->GetText() ); - /* local buffer in multibyte form */ + // buffer containing the menu text in multibyte form char buf[200]; strcpy( buf, "/" ); - strncat( buf, text.mb_str(), WXSIZEOF(buf) - 2 ); + strncat( buf, wxGTK_CONV(text), WXSIZEOF(buf) - 2 ); buf[WXSIZEOF(buf) - 1] = '\0'; GtkItemFactoryEntry entry; @@ -1092,14 +1100,17 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) else // continue the radio group { pathRadio = m_pathLastRadio; - pathRadio.Replace("_", ""); - pathRadio.Prepend("
/"); - item_type = pathRadio; + pathRadio.Replace(wxT("_"), wxT("")); + pathRadio.Prepend(wxT("
/")); + + char buf2[200]; + strncpy(buf2, wxGTK_CONV(pathRadio), WXSIZEOF(buf2)); + buf2[WXSIZEOF(buf2) - 1] = '\0'; + item_type = buf2; } - // 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: @@ -1118,9 +1129,10 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) // due to an apparent bug in GTK+, we have to use a static buffer here - // otherwise GTK+ 1.2.2 manages to override the memory we pass to it // somehow! (VZ) - static char s_accel[50]; // must be big enougg + char s_accel[50]; // should be big enough, we check for overruns wxString tmp( GetHotKey(*mitem) ); - strncpy(s_accel, tmp.mb_str(), WXSIZEOF(s_accel)); + strncpy(s_accel, wxGTK_CONV( tmp ), WXSIZEOF(s_accel)); + s_accel[WXSIZEOF(s_accel) - 1] = '\0'; entry.accelerator = s_accel; #else // !wxUSE_ACCEL entry.accelerator = (char*) NULL; @@ -1129,15 +1141,7 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */ wxString path( mitem->GetFactoryPath() ); - menuItem = gtk_item_factory_get_widget( m_factory, path.mb_str() ); -#else // GTK+ 1.0 - menuItem = checkable ? gtk_check_menu_item_new_with_label( mitem->GetText().mb_str() ) - : gtk_menu_item_new_with_label( mitem->GetText().mb_str() ); - - gtk_signal_connect( GTK_OBJECT(menuItem), "activate", - GTK_SIGNAL_FUNC(gtk_menu_clicked_callback), - (gpointer)this ); -#endif // GTK+ 1.2/1.0 + menuItem = gtk_item_factory_get_widget( m_factory, wxGTK_CONV( path ) ); } if ( !mitem->IsSeparator() ) @@ -1151,22 +1155,12 @@ bool wxMenu::GtkAppend(wxMenuItem *mitem) (gpointer)this ); } -#if !GTK_CHECK_VERSION(1, 2, 0) - if (!appended) - { - gtk_menu_append( GTK_MENU(m_menu), menuItem ); - gtk_widget_show( menuItem ); - } -#endif // GTK+ 1.0 - mitem->SetMenuItem(menuItem); -#if GTK_CHECK_VERSION(1, 2, 0) - if ( !isRadio ) + if ( endOfRadioGroup ) { m_pathLastRadio.clear(); } -#endif // GTK+ >= 1.2 return TRUE; }