/////////////////////////////////////////////////////////////////////////////
// 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
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
+#if wxUSE_MENUS
+
#include "wx/menu.h"
#ifndef WX_PRECOMP
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;
str << *pc;
}
- ++pc;
}
// wxPrintf( wxT("before %s after %s\n"), title.c_str(), str.c_str() );
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
//-----------------------------------------------------------------------------
static void DoCommonMenuCallbackCode(wxMenu *menu, wxMenuEvent& event)
{
- if (g_isIdle)
- wxapp_install_idle_handler();
-
event.SetEventObject( menu );
wxEvtHandler* handler = menu->GetEventHandler();
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;
if (style & wxMB_DOCKABLE)
{
m_widget = gtk_handle_box_new();
- gtk_container_add( GTK_CONTAINER(m_widget), GTK_WIDGET(m_menubar) );
- gtk_widget_show( GTK_WIDGET(m_menubar) );
+ gtk_container_add(GTK_CONTAINER(m_widget), m_menubar);
+ gtk_widget_show(m_menubar);
}
else
{
- m_widget = GTK_WIDGET(m_menubar);
+ m_widget = m_menubar;
}
PostCreation();
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)
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 );
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 );
extern "C" {
static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu )
{
- if (g_isIdle)
- wxapp_install_idle_handler();
-
int id = menu->FindMenuIdByMenuItem(widget);
/* should find it for normal (not popup) menu */
extern "C" {
static void gtk_menu_hilight_callback( GtkWidget *widget, wxMenu *menu )
{
- if (g_isIdle) wxapp_install_idle_handler();
-
int id = menu->FindMenuIdByMenuItem(widget);
wxASSERT( id != -1 ); // should find it!
extern "C" {
static void gtk_menu_nolight_callback( GtkWidget *widget, wxMenu *menu )
{
- if (g_isIdle) wxapp_install_idle_handler();
-
int id = menu->FindMenuIdByMenuItem(widget);
wxASSERT( id != -1 ); // should find it!
// 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++ )
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());
gtk_accelerator_parse( (const char*) oldbuf, &accel_key, &accel_mods);
if (accel_key != 0)
{
- gtk_widget_remove_accelerator( GTK_WIDGET(m_menuItem),
+ gtk_widget_remove_accelerator(m_menuItem,
m_parentMenu->m_accel,
accel_key,
accel_mods );
{
// if the accelerator was taken from a stock ID, just get it back from GTK+ stock
if (wxGetStockGtkAccelerator(stockid, &accel_mods, &accel_key))
- gtk_widget_remove_accelerator( GTK_WIDGET(m_menuItem),
+ gtk_widget_remove_accelerator( m_menuItem,
m_parentMenu->m_accel,
accel_key,
accel_mods );
gtk_accelerator_parse( (const char*) buf, &accel_key, &accel_mods);
if (accel_key != 0)
{
- gtk_widget_add_accelerator( GTK_WIDGET(m_menuItem),
+ gtk_widget_add_accelerator( m_menuItem,
"activate",
m_parentMenu->m_accel,
accel_key,
{
// if the accelerator was taken from a stock ID, just get it back from GTK+ stock
if (wxGetStockGtkAccelerator(stockid, &accel_mods, &accel_key))
- gtk_widget_remove_accelerator( GTK_WIDGET(m_menuItem),
+ gtk_widget_remove_accelerator( m_menuItem,
m_parentMenu->m_accel,
accel_key,
accel_mods );
}
// 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
{
if(*pc == wxT('\t'))
{
pc++;
- *hotKey = pc;
+ hotKey->assign(pc, str.end());
}
}
{
// 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 )
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;
}
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() )
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);
if (accel_key != 0)
{
- gtk_widget_add_accelerator (GTK_WIDGET(menuItem),
+ gtk_widget_add_accelerator (menuItem,
"activate",
m_accel,
accel_key,
{
// if the accelerator was taken from a stock ID, just get it back from GTK+ stock
if (wxGetStockGtkAccelerator(stockid, &accel_mods, &accel_key))
- gtk_widget_add_accelerator( GTK_WIDGET(menuItem),
+ gtk_widget_add_accelerator( menuItem,
"activate",
m_accel,
accel_key,
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" );
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" );
default:
if ( code < 127 )
{
- wxString name = wxGTK_CONV_BACK( gdk_keyval_name((guint)code) );
- if ( name )
+ const wxString
+ name = wxGTK_CONV_BACK_SYS(gdk_keyval_name((guint)code));
+ if ( !name.empty() )
{
hotkey << name;
break;
}
#endif // __WXGTK20__
+
+#endif // wxUSE_MENUS