}
#if wxUSE_ACCEL
-static bool wxGetStockGtkAccelerator(const char *id, GdkModifierType *mod, guint *key);
-static wxString GetGtkHotKey( const wxMenuItem& item );
+static void wxGetGtkAccel(const wxMenuItem*, guint*, GdkModifierType*);
#endif
static void DoCommonMenuCallbackCode(wxMenu *menu, wxMenuEvent& event)
wxMenu *subMenu)
: wxMenuItemBase(parentMenu, id, text, help, kind, subMenu)
{
- Init(text);
+ m_menuItem = NULL;
}
#if WXWIN_COMPATIBILITY_2_8
: wxMenuItemBase(parentMenu, id, text, help,
isCheckable ? wxITEM_CHECK : wxITEM_NORMAL, subMenu)
{
- Init(text);
+ m_menuItem = NULL;
}
#endif
-void wxMenuItem::Init(const wxString& text)
-{
- m_menuItem = (GtkWidget *) NULL;
-
- DoSetText(text);
-}
-
wxMenuItem::~wxMenuItem()
{
// don't delete menu items, the menus take care of that
void wxMenuItem::SetItemLabel( const wxString& str )
{
- // cache some data which must be used later
- bool isstock = wxIsStockID(GetId());
- const char *stockid = NULL;
- if (isstock)
- stockid = wxGetStockGtkID(GetId());
-
- // Some optimization to avoid flicker
- wxString oldLabel = m_text;
- oldLabel = wxStripMenuCodes(oldLabel);
- wxString label1 = wxStripMenuCodes(str);
#if wxUSE_ACCEL
- wxString oldhotkey = m_hotKey; // Store the old hotkey in Ctrl-foo format
- wxCharBuffer oldbuf = wxGTK_CONV_SYS( GetGtkHotKey(*this) ); // and as <control>foo
-#endif // wxUSE_ACCEL
-
- DoSetText(str);
-
-#if wxUSE_ACCEL
- if (oldLabel == label1 &&
- oldhotkey == m_hotKey) // Make sure we can change a hotkey even if the label is unaltered
- return;
-
if (m_menuItem)
{
- // stock menu items can have empty labels:
- wxString text = m_gtkText;
- if (text.IsEmpty() && !IsSeparator())
+ // remove old accelerator
+ guint accel_key;
+ GdkModifierType accel_mods;
+ wxGetGtkAccel(this, &accel_key, &accel_mods);
+ if (accel_key)
{
- wxASSERT_MSG(isstock, wxT("A non-stock menu item with an empty label?"));
- text = wxGetStockLabel(GetId());
-
- // need & => _ conversion
- text = GTKProcessMenuItemLabel(text, NULL);
+ gtk_widget_remove_accelerator(
+ m_menuItem, m_parentMenu->m_accel, accel_key, accel_mods);
}
-
- GtkLabel* label = GTK_LABEL(GTK_BIN(m_menuItem)->child);
- gtk_label_set_text_with_mnemonic(label, wxGTK_CONV_SYS(text));
- }
-
- // remove old accelerator from our parent's accelerator group, if present
- guint accel_key;
- GdkModifierType accel_mods;
- if (oldbuf[(size_t)0] != '\0')
- {
- gtk_accelerator_parse( (const char*) oldbuf, &accel_key, &accel_mods);
- if (accel_key != 0)
- {
- gtk_widget_remove_accelerator(m_menuItem,
- m_parentMenu->m_accel,
- accel_key,
- accel_mods );
- }
- }
- else if (isstock)
- {
- // 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( m_menuItem,
- m_parentMenu->m_accel,
- accel_key,
- accel_mods );
- }
-
- // add new accelerator to our parent's accelerator group
- wxCharBuffer buf = wxGTK_CONV_SYS( GetGtkHotKey(*this) );
- if (buf[(size_t)0] != '\0')
- {
- gtk_accelerator_parse( (const char*) buf, &accel_key, &accel_mods);
- if (accel_key != 0)
- {
- gtk_widget_add_accelerator( m_menuItem,
- "activate",
- m_parentMenu->m_accel,
- accel_key,
- accel_mods,
- GTK_ACCEL_VISIBLE);
- }
- }
- else if (isstock)
- {
- // 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( m_menuItem,
- m_parentMenu->m_accel,
- accel_key,
- accel_mods );
}
#endif // wxUSE_ACCEL
+ wxMenuItemBase::SetItemLabel(str);
+ if (m_menuItem)
+ SetGtkLabel();
}
-// NOTE: this function is different from the similar functions GTKProcessMnemonics()
-// implemented in control.cpp and from wxMenuItemBase::GetLabelText...
-// so there's no real code duplication
-wxString wxMenuItem::GTKProcessMenuItemLabel(const wxString& str, wxString *hotKey)
+void wxMenuItem::SetGtkLabel()
{
- wxString text;
-
- // '\t' is the deliminator indicating a hot key
- wxString::const_iterator pc = str.begin();
- while ( pc != str.end() && *pc != wxT('\t') )
- {
- if (*pc == 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
- {
- text << wxT("__");
- }
- else
- {
- text << *pc;
- }
- ++pc;
- }
-
- if (hotKey)
+ const wxString text = wxConvertMnemonicsToGTK(m_text.BeforeFirst('\t'));
+ GtkLabel* label = GTK_LABEL(GTK_BIN(m_menuItem)->child);
+ gtk_label_set_text_with_mnemonic(label, wxGTK_CONV_SYS(text));
+#if wxUSE_ACCEL
+ guint accel_key;
+ GdkModifierType accel_mods;
+ wxGetGtkAccel(this, &accel_key, &accel_mods);
+ if (accel_key)
{
- hotKey->Empty();
- if(*pc == wxT('\t'))
- {
- ++pc;
- hotKey->assign(pc, str.end());
- }
+ gtk_widget_add_accelerator(
+ m_menuItem, "activate", m_parentMenu->m_accel,
+ accel_key, accel_mods, GTK_ACCEL_VISIBLE);
}
-
- return text;
-}
-
-// it's valid for this function to be called even if m_menuItem == NULL
-void wxMenuItem::DoSetText( const wxString& str )
-{
- m_text = str;
- m_gtkText = GTKProcessMenuItemLabel(str, &m_hotKey);
+#endif // wxUSE_ACCEL
}
-#if wxUSE_ACCEL
-
-wxAcceleratorEntry *wxMenuItem::GetAccel() const
+void wxMenuItem::SetBitmap(const wxBitmap& bitmap)
{
- if (m_hotKey.empty())
- {
- // nothing
- return NULL;
- }
-
- // accelerator parsing code looks for them after a TAB, so insert a dummy
- // one here
- wxString label;
- label << wxT('\t') << m_hotKey;
-
- return wxAcceleratorEntry::Create(label);
+ if (m_kind == wxITEM_NORMAL)
+ m_bitmap = bitmap;
+ else
+ wxFAIL_MSG("only normal menu items can have bitmaps");
}
-#endif // wxUSE_ACCEL
-
void wxMenuItem::Check( bool check )
{
wxCHECK_RET( m_menuItem, wxT("invalid menu item") );
bool wxMenu::GtkAppend(wxMenuItem *mitem, int pos)
{
GtkWidget *menuItem;
-
- // cache some data used later
- wxString text = mitem->GetGtkItemLabel();
- int id = mitem->GetId();
- bool isstock = wxIsStockID(id);
- const char *stockid = NULL;
- if (isstock)
- stockid = wxGetStockGtkID(mitem->GetId());
-
- // stock menu items can have an empty label
- if (text.IsEmpty() && !mitem->IsSeparator())
- {
- wxASSERT_MSG(isstock, wxT("A non-stock menu item with an empty label?"));
- text = wxGetStockLabel(id);
-
- // need & => _ conversion
- text = wxMenuItem::GTKProcessMenuItemLabel(text, NULL);
- }
-
- if ( mitem->IsSeparator() )
- {
- menuItem = gtk_separator_menu_item_new();
- m_prevRadio = NULL;
- }
- else if ( mitem->GetBitmap().IsOk() ||
- (mitem->GetKind() == wxITEM_NORMAL && isstock) )
- {
- wxBitmap bitmap(mitem->GetBitmap());
-
- menuItem = gtk_image_menu_item_new_with_mnemonic( wxGTK_CONV_SYS( text ) );
-
- GtkWidget *image;
- if ( !bitmap.Ok() )
- {
- // use stock bitmap for this item if available on the assumption
- // that it never hurts to follow GTK+ conventions more closely
- image = stockid ? gtk_image_new_from_stock(stockid, GTK_ICON_SIZE_MENU)
- : NULL;
- }
- else // we have a custom bitmap
- {
- wxASSERT_MSG( mitem->GetKind() == wxITEM_NORMAL,
- _T("only normal menu items can have bitmaps") );
-
- if ( bitmap.HasPixbuf() )
- {
- image = gtk_image_new_from_pixbuf(bitmap.GetPixbuf());
- }
- else
- {
- GdkPixmap *gdk_pixmap = bitmap.GetPixmap();
- GdkBitmap *gdk_bitmap = bitmap.GetMask() ?
- bitmap.GetMask()->GetBitmap() :
- (GdkBitmap*) NULL;
- image = gtk_image_new_from_pixmap( gdk_pixmap, gdk_bitmap );
- }
- }
-
- if ( image )
- {
- gtk_widget_show(image);
-
- gtk_image_menu_item_set_image( GTK_IMAGE_MENU_ITEM(menuItem), image );
- }
-
- m_prevRadio = NULL;
- }
- else // a normal item
+ GtkWidget* prevRadio = m_prevRadio;
+ m_prevRadio = NULL;
+ switch (mitem->GetKind())
{
- // NB: 'text' variable has "_" instead of "&" after mitem->SetItemLabel()
- // so don't use it
-
- switch ( mitem->GetKind() )
- {
- case wxITEM_CHECK:
+ case wxITEM_SEPARATOR:
+ menuItem = gtk_separator_menu_item_new();
+ break;
+ case wxITEM_CHECK:
+ menuItem = gtk_check_menu_item_new_with_label("");
+ break;
+ case wxITEM_RADIO:
{
- menuItem = gtk_check_menu_item_new_with_mnemonic( wxGTK_CONV_SYS( text ) );
- m_prevRadio = NULL;
- break;
+ GSList* group = NULL;
+ if (prevRadio)
+ group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(prevRadio));
+ menuItem = gtk_radio_menu_item_new_with_label(group, "");
+ m_prevRadio = menuItem;
}
-
- case wxITEM_RADIO:
+ break;
+ default:
+ wxFAIL_MSG("unexpected menu item kind");
+ // fall through
+ case wxITEM_NORMAL:
+ const wxBitmap& bitmap = mitem->GetBitmap();
+ const char* stockid;
+ if (bitmap.IsOk())
{
- GSList *group = NULL;
- if ( m_prevRadio == NULL )
- {
- // start of a new radio group
- m_prevRadio = menuItem =
- gtk_radio_menu_item_new_with_mnemonic( group, wxGTK_CONV_SYS( text ) );
- }
- else // continue the radio group
+ GtkWidget* image;
+ if (bitmap.HasPixbuf())
+ image = gtk_image_new_from_pixbuf(bitmap.GetPixbuf());
+ else
{
- group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (m_prevRadio));
- m_prevRadio = menuItem =
- gtk_radio_menu_item_new_with_mnemonic( group, wxGTK_CONV_SYS( text ) );
+ GdkPixmap* mask = NULL;
+ if (bitmap.GetMask())
+ mask = bitmap.GetMask()->GetBitmap();
+ image = gtk_image_new_from_pixmap(bitmap.GetPixmap(), mask);
}
- break;
- }
-
- default:
- wxFAIL_MSG( _T("unexpected menu item kind") );
- // fall through
-
- case wxITEM_NORMAL:
- {
- menuItem = gtk_menu_item_new_with_mnemonic( wxGTK_CONV_SYS( text ) );
- m_prevRadio = NULL;
- break;
+ menuItem = gtk_image_menu_item_new_with_label("");
+ gtk_widget_show(image);
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuItem), image);
}
- }
-
- }
-
-#if wxUSE_ACCEL
- guint accel_key;
- GdkModifierType accel_mods;
- wxCharBuffer buf = wxGTK_CONV_SYS( GetGtkHotKey(*mitem) );
-
- if (buf[(size_t)0] != '\0')
- {
- gtk_accelerator_parse( (const char*) buf, &accel_key, &accel_mods);
- if (accel_key != 0)
- {
- gtk_widget_add_accelerator (menuItem,
- "activate",
- m_accel,
- accel_key,
- accel_mods,
- GTK_ACCEL_VISIBLE);
- }
- }
- else if (isstock)
- {
- // 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( menuItem,
- "activate",
- m_accel,
- accel_key,
- accel_mods,
- GTK_ACCEL_VISIBLE);
+ else if ((stockid = wxGetStockGtkID(mitem->GetId())) != NULL)
+ // use stock bitmap for this item if available on the assumption
+ // that it never hurts to follow GTK+ conventions more closely
+ menuItem = gtk_image_menu_item_new_from_stock(stockid, NULL);
+ else
+ menuItem = gtk_menu_item_new_with_label("");
+ break;
}
-#endif // wxUSE_ACCEL
+ mitem->SetMenuItem(menuItem);
- if (pos == -1)
- gtk_menu_shell_append(GTK_MENU_SHELL(m_menu), menuItem);
- else
- gtk_menu_shell_insert(GTK_MENU_SHELL(m_menu), menuItem, pos);
+ gtk_menu_shell_insert(GTK_MENU_SHELL(m_menu), menuItem, pos);
gtk_widget_show( menuItem );
if ( !mitem->IsSeparator() )
{
- wxASSERT_MSG( menuItem, wxT("invalid menuitem") );
-
+ mitem->SetGtkLabel();
g_signal_connect (menuItem, "select",
G_CALLBACK (gtk_menu_hilight_callback), this);
g_signal_connect (menuItem, "deselect",
}
}
- mitem->SetMenuItem(menuItem);
-
- if (ms_locked)
- {
- // This doesn't even exist!
- // gtk_widget_lock_accelerators(mitem->GetMenuItem());
- }
-
return true;
}
return hotkey;
}
+static void
+wxGetGtkAccel(const wxMenuItem* item, guint* accel_key, GdkModifierType* accel_mods)
+{
+ *accel_key = 0;
+ const wxString string = GetGtkHotKey(*item);
+ if (!string.empty())
+ gtk_accelerator_parse(wxGTK_CONV_SYS(string), accel_key, accel_mods);
+ else
+ {
+ GtkStockItem stock_item;
+ const char* stockid = wxGetStockGtkID(item->GetId());
+ if (stockid && gtk_stock_lookup(stockid, &stock_item))
+ {
+ *accel_key = stock_item.keyval;
+ *accel_mods = stock_item.modifier;
+ }
+ }
+}
#endif // wxUSE_ACCEL
const char *wxGetStockGtkID(wxWindowID id)
case wx: \
return gtk;
- #define STOCKITEM_MISSING(wx) \
- case wx: \
- return NULL;
-
- #if GTK_CHECK_VERSION(2,4,0)
- #define STOCKITEM_24(wx,gtk) STOCKITEM(wx,gtk)
- #else
- #define STOCKITEM_24(wx,gtk) STOCKITEM_MISSING(wx)
- #endif
-
#if GTK_CHECK_VERSION(2,6,0)
#define STOCKITEM_26(wx,gtk) STOCKITEM(wx,gtk)
#else
- #define STOCKITEM_26(wx,gtk) STOCKITEM_MISSING(wx)
+ #define STOCKITEM_26(wx,gtk)
#endif
#if GTK_CHECK_VERSION(2,10,0)
#define STOCKITEM_210(wx,gtk) STOCKITEM(wx,gtk)
#else
- #define STOCKITEM_210(wx,gtk) STOCKITEM_MISSING(wx)
+ #define STOCKITEM_210(wx,gtk)
#endif
STOCKITEM(wxID_UP, GTK_STOCK_GO_UP)
STOCKITEM(wxID_HELP, GTK_STOCK_HELP)
STOCKITEM(wxID_HOME, GTK_STOCK_HOME)
- STOCKITEM_24(wxID_INDENT, GTK_STOCK_INDENT)
+ STOCKITEM(wxID_INDENT, GTK_STOCK_INDENT)
STOCKITEM(wxID_INDEX, GTK_STOCK_INDEX)
STOCKITEM(wxID_ITALIC, GTK_STOCK_ITALIC)
STOCKITEM(wxID_JUSTIFY_CENTER, GTK_STOCK_JUSTIFY_CENTER)
STOCKITEM(wxID_UNDELETE, GTK_STOCK_UNDELETE)
STOCKITEM(wxID_UNDERLINE, GTK_STOCK_UNDERLINE)
STOCKITEM(wxID_UNDO, GTK_STOCK_UNDO)
- STOCKITEM_24(wxID_UNINDENT, GTK_STOCK_UNINDENT)
+ STOCKITEM(wxID_UNINDENT, GTK_STOCK_UNINDENT)
STOCKITEM(wxID_YES, GTK_STOCK_YES)
STOCKITEM(wxID_ZOOM_100, GTK_STOCK_ZOOM_100)
STOCKITEM(wxID_ZOOM_FIT, GTK_STOCK_ZOOM_FIT)
STOCKITEM(wxID_ZOOM_OUT, GTK_STOCK_ZOOM_OUT)
default:
- wxFAIL_MSG( _T("invalid stock item ID") );
break;
};
return NULL;
}
-#if wxUSE_ACCEL
-static
-bool wxGetStockGtkAccelerator(const char *id, GdkModifierType *mod, guint *key)
-{
- if (!id)
- return false;
-
- GtkStockItem stock_item;
- if (gtk_stock_lookup (id, &stock_item))
- {
- if (key) *key = stock_item.keyval;
- if (mod) *mod = stock_item.modifier;
-
- // some GTK stock items have zero values for the keyval;
- // it means that they do not have an accelerator...
- if (stock_item.keyval)
- return true;
- }
-
- return false;
-}
-#endif // wxUSE_ACCEL
-
#endif // wxUSE_MENUS