Icons in menus: GtkAccelLabel woes




	I am writing a Gtk+ application.  It will have a standard-looking
menu bar with File, Edit, etc.

	I want to have icons in my menus, so that they look cool like the
Gnome standard menuitems.  I.e., many of the GtkMenuItems will have a
small graphical icon to the left of the text label.

	I also want the hotkeys (Accelerator Key Combitions) to show up on
the right, right-aligned.  Again, this is how the Gnome menus look.  (I do
not want to require the Gnome libs for my application).

	So, my idea was this: I'll create menus manually (because the
GtkItemFactory only allows you to create menus with lables, not pixmaps),
and for each GtkMenuItem in my menus I'll have two things: on the left,
the XPM icon, and on the right, the GtkAccelLabel that you'd normally
expect in a menu.

	Here is a diagram of what I had in mind for my "File" menu:

--------
| File |
-----------------------------
XPM   New              Ctrl+N
XPM   Open...          Ctrl+O
XPM   Save             Ctrl+S
XPM   Exit
-----------------------------

	I was planning to have each GtkMenuItem layed out like this:

GtkMenuItem---------------------------------
|  hbox----------------------------------- |                  
|  |  pixmap_widget    |   GtkAccelLabel | |
|  |-------------------------------------- |
-------------------------------------------|

	...but it does not work.  The GtkAccelLabel will show the regular
text label (the first argument to the gtk_accel_label_new() function) but
it will NOT show any accelerators which have been attached to that
GtkMenuItem.

	So my questions are:

1) Am I doing things correctly, or is there a mistake in my code?

2) If I'm doing things correctly, why aren't the Accel keys showing up?

3) If this is not something that can be made to work, how else would you
handle it?  One idea I've had is writing in the hotkey combinations
manually in a 3-field hbox, using a regular "label", but I'd prefer to
have the accelerators created automatically.

4)  Below is my test program.  It has a "File" menu with "New" and "Open"
menuitems.  The "New" menuitem is created normally with
gtk_menu_item_new_with_label() and works fine, but the "Open" is a test
case for the problem I'm having.

	There is a strange side-effect I don't understand in my test
program. If I place the mouse pointer of the "New" menuitem in my test
program, pressing CTRL+<any letter> changes what the hotkey combination
reads in the "New" GtkAccelLabel.  Why is that?

	As a possible hint of what's going wrong with "Open", I think the
same thing is happening to the "Open" menuitem.  Although I cannot see any
"Ctrl-X" types of string changing, I *can* see the the menu flicker and
expand slightly as I hit Ctrl-C followed by Ctrl-Z (indicating that there 
is a label there that is changing, as is the case with the "New"
menuitem).

	Below is the source code to my test program, called test.c.  It
can be compiled with the command 

cc -o test test.c `gtk-config --cflags --libs`

	...and it shows what I'm talking about.  It is also attached as a
MIME attachment.

	Please take a look (the code is VERY simple) and let me know what
you think.

Thank You,
Derek Simkowiak
dereks@kd-dev.com

-------------- Begin test.c --------------

#include <gtk/gtk.h>

gint Delete (GtkWindow *widget, gpointer data) {
	gtk_main_quit();
	return FALSE;
}


int main(int argc, char *argv[]) {

	GtkWidget *window;	/* Top-level window */
	GtkWidget *menubar;	/* To hold our sample "File" menu */
	GtkWidget *menuitem;	/* Used for the "File","New","Open" MenuItems */
	GtkWidget *submenu;	/* The actual "menu" holding "New", "Open" */

	GtkWidget *hbox;	/* hbox to hold multiple widgets in menuitem */
	GtkWidget *label;	/* text item to put into hbox  */
	GtkAccelGroup *accel;	/* Our accel group */
	GtkWidget *accel_label; /* Our GtkAccelLabel (appears broken?!)*/

	gtk_init(&argc, &argv);

	/* Create top-level window */
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_signal_connect(GTK_OBJECT(window), "delete_event",
		 GTK_SIGNAL_FUNC(Delete), NULL);

	/* Create our accel group, attach it to our top-level window */
	accel = gtk_accel_group_new();
	gtk_accel_group_attach(accel, GTK_OBJECT(window));
	/* The accels are added down below... */

	/* create the menu bar as the only widget in our "window" */
	menubar = gtk_menu_bar_new();
	gtk_container_add(GTK_CONTAINER(window), menubar);
	gtk_widget_show(menubar);

	/* Create the "File" GtkMenuItem */
	menuitem = gtk_menu_item_new_with_label("File");
	gtk_menu_bar_append(GTK_MENU_BAR(menubar), menuitem);
	gtk_widget_show(menuitem);

	/* Create the actual drop-down menu (called "submenu") */
	submenu = gtk_menu_new();
	/* set it to be the submenu of "File" */
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);

	/* Create "New" entry in our submenu: */
	menuitem = gtk_menu_item_new_with_label("New");
	gtk_menu_append(GTK_MENU(submenu), menuitem);

	/* Finally, add an accelerator for "New" of CTRL-N */
	gtk_widget_add_accelerator(menuitem, 
	"activate", accel, 'N', GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);

	/* Wrap up the "New" GtkMenuItem by showing it: */
	gtk_widget_show(menuitem);


	/* Create a second GtkMenuItem ("Open") that contains an hbox */
	/* The plan is to have a pixmap AND a GtkAccelLabel, to look like 
	   the Gnome built-in menus... */
	menuitem = gtk_menu_item_new();

	/* Create the hbox, fill it with two things, put it into the menuitem */
	hbox = gtk_hbox_new(FALSE, 0);

	/* Our first (leftmost) hbox item: */
	/* In a real app, this label would be replaced with an icon */
	label = gtk_label_new("_XPM_");
	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
	gtk_widget_show(label);

	/* Our second hbox item, an accel_label which does not show 
	   accelerators!  The "Open" is visible, but "Ctrl-P" is not.

	Why doesn't this show the accelerators? */

	accel_label = gtk_accel_label_new("Open");

	/* We attach it to 'menuitem', which is the GtkMenuItem holding
	   the hbox which is holding the accel_label */

	/* I've tried to make these next 4 lines of code look just like
	   the function gtk_menu_item_new_with_label() in gtkmenuitem.c */

	gtk_misc_set_alignment(GTK_MISC(accel_label), 0.0, 0.5);
	gtk_box_pack_start(GTK_BOX(hbox), accel_label, FALSE, TRUE, 0);
	gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(accel_label), menuitem);
	gtk_widget_show(accel_label);
		
	gtk_container_add(GTK_CONTAINER(menuitem), hbox);
	gtk_widget_show(hbox);

	/* All done--add this menuitem to the submenu and show it... */
	gtk_menu_append(GTK_MENU(submenu), menuitem);	
	gtk_widget_show(menuitem);

	/* Now, add an accelerator to the hbox-holding menuitem */
	gtk_widget_add_accelerator(menuitem, 
	"activate", accel, 'P', GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);


	gtk_widget_show(window);

	gtk_main();

	return 0;
}
#include <gtk/gtk.h>

gint Delete (GtkWindow *widget, gpointer data) {
	gtk_main_quit();
	return FALSE;
}


int main(int argc, char *argv[]) {

	GtkWidget *window;	/* Top-level window */
	GtkWidget *menubar;	/* To hold our sample "File" menu */
	GtkWidget *menuitem;	/* Used for the "File","New","Open" MenuItems */
	GtkWidget *submenu;	/* The actual "menu" holding "New", "Open" */

	GtkWidget *hbox;	/* hbox to hold multiple widgets in menuitem */
	GtkWidget *label;	/* text item to put into hbox  */
	GtkAccelGroup *accel;	/* Our accel group */
	GtkWidget *accel_label; /* Our GtkAccelLabel (appears broken?!)*/

	gtk_init(&argc, &argv);

	/* Create top-level window */
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_signal_connect(GTK_OBJECT(window), "delete_event",
		 GTK_SIGNAL_FUNC(Delete), NULL);

	/* Create our accel group, attach it to our top-level window */
	accel = gtk_accel_group_new();
	gtk_accel_group_attach(accel, GTK_OBJECT(window));
	/* The accels are added down below... */

	/* create the menu bar as the only widget in our "window" */
	menubar = gtk_menu_bar_new();
	gtk_container_add(GTK_CONTAINER(window), menubar);
	gtk_widget_show(menubar);

	/* Create the "File" GtkMenuItem */
	menuitem = gtk_menu_item_new_with_label("File");
	gtk_menu_bar_append(GTK_MENU_BAR(menubar), menuitem);
	gtk_widget_show(menuitem);

	/* Create the actual drop-down menu (called "submenu") */
	submenu = gtk_menu_new();
	/* set it to be the submenu of "File" */
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);

	/* Create "New" entry in our submenu: */
	menuitem = gtk_menu_item_new_with_label("New");
	gtk_menu_append(GTK_MENU(submenu), menuitem);

	/* Finally, add an accelerator for "New" of CTRL-N */
	gtk_widget_add_accelerator(menuitem, 
	"activate", accel, 'N', GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);

	/* Wrap up the "New" GtkMenuItem by showing it: */
	gtk_widget_show(menuitem);


	/* Create a second GtkMenuItem ("Open") that contains an hbox */
	/* The plan is to have a pixmap AND a GtkAccelLabel, to look like 
	   the Gnome built-in menus... */
	menuitem = gtk_menu_item_new();

	/* Create the hbox, fill it with two things, put it into the menuitem */
	hbox = gtk_hbox_new(FALSE, 0);

	/* Our first (leftmost) hbox item: */
	/* In a real app, this label would be replaced with an icon */
	label = gtk_label_new("_XPM_");
	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);
	gtk_widget_show(label);

	/* Our second hbox item, an accel_label which does not show 
	   accelerators!  The "Open" is visible, but "Ctrl-P" is not.

	Why doesn't this show the accelerators? */

	accel_label = gtk_accel_label_new("Open");

	/* We attach it to 'menuitem', which is the GtkMenuItem holding
	   the hbox which is holding the accel_label */

	/* I've tried to make these next 4 lines of code look just like
	   the function gtk_menu_item_new_with_label() in gtkmenuitem.c */

	gtk_misc_set_alignment(GTK_MISC(accel_label), 0.0, 0.5);
	gtk_box_pack_start(GTK_BOX(hbox), accel_label, FALSE, TRUE, 0);
	gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(accel_label), menuitem);
	gtk_widget_show(accel_label);
		
	gtk_container_add(GTK_CONTAINER(menuitem), hbox);
	gtk_widget_show(hbox);

	/* All done--add this menuitem to the submenu and show it... */
	gtk_menu_append(GTK_MENU(submenu), menuitem);	
	gtk_widget_show(menuitem);

	/* Now, add an accelerator to the hbox-holding menuitem */
	gtk_widget_add_accelerator(menuitem, 
	"activate", accel, 'P', GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);


	gtk_widget_show(window);

	gtk_main();

	return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]