|
It's tedious to create large menus, especially if they have
features such as icons and keyboard accelerators. Gnome
provides a simple solution. You assemble a GnomeUIInfo struct as a template for
each menu item, simply listing its characteristics: name,
icon, accelerator, and so on. The Gnome libraries can
automatically create menus from arrays of GnomeUIInfo templates. The same method
works with toolbars.
Here's the declaration of struct
GnomeUIInfo.
typedef struct {
GnomeUIInfoType type;
gchar* label;
gchar* hint;
gpointer moreinfo;
gpointer user_data;
gpointer unused_data;
GnomeUIPixmapType pixmap_type;
gpointer pixmap_info;
guint accelerator_key;
GdkModifierType ac_mods;
GtkWidget* widget;
} GnomeUIInfo;
|
A static initializer is the most convenient way to fill in
the struct (but of course you can create it dynamically if
you prefer). Gnome's routines accept an array of GnomeUIInfo, and macros are
provided to simplify and standardize the most common static
initializers. Here's a typical example, a File menu:
static GnomeUIInfo file_menu[] = {
GNOMEUIINFO_MENU_NEW_ITEM(N_("_New Window"),
N_("Create a new text viewer window"),
new_app_cb, NULL),
GNOMEUIINFO_MENU_OPEN_ITEM(open_cb,NULL),
GNOMEUIINFO_MENU_SAVE_AS_ITEM(save_as_cb,NULL),
GNOMEUIINFO_SEPARATOR,
GNOMEUIINFO_MENU_CLOSE_ITEM(close_cb,NULL),
GNOMEUIINFO_MENU_EXIT_ITEM(exit_cb,NULL),
GNOMEUIINFO_END
};
|
There isn't always a nice macro for the menu item you want,
so sometimes you must manually specify each element of the
struct:
{
GNOME_APP_UI_ITEM, N_("_Select All"),
N_("Select all cells in the spreadsheet"),
select_all_cb, NULL,
NULL, 0, 0, 'a', GDK_CONTROL_MASK
}
|
By now you're probably wondering what the struct members
mean. Simple enough. Here's a breakdown:
-
type is a type marker
from the
GnomeUIInfoType enumeration. See Table
1.
-
label is the text of
the menu or toolbar button. It should be marked for
internationalization with the
N_() macro.
-
hint is a long
description of the item's function. For toolbar
buttons, it will appear in a tooltip; for menus, it can
be made to appear in the statusbar.
-
moreinfo depends on the
type of the item. See
Table
1.
-
user_data will be
passed to your callback function, if this item type has
a callback.
-
unused_data should be
set to NULL, and is not
used yet. It may be used in future versions of
Gnome.
-
pixmap_type is a value
from the
GnomeUIPixmapType enumeration; its purpose is to
specify the type of the next member, pixmap_info.
-
pixmap_info can be raw
pixmap data, a filename, or the name of a Gnome stock
pixmap.
-
accelerator_key is the
key to be used as an accelerator for this item . You
can use a character such as
'a', or a value from
gdk/gdkkeysyms.h.
-
ac_mods is a modifier
mask to be used with the accelerator.
-
widget should be NULL; Gnome fills it in when
it creates the menu item or toolbar button. You can
then retrieve it, if you need to manipulate the widget
in some way.
You might also be wondering why the menu item names contain
an underscore. The underscore is used to mark the key
shortcut for the menu item; translators can move it around
as needed to make it intuitive in their language. Gnome
will parse the menu item name to obtain the accelerator,
then remove the underscore.
Table 1
summarizes the possible values for the type field of a GnomeUIInfo struct. See libgnomeui/gnome-app-helper.h for more
details. There are actually a few more possible values, but
the others are used internally by the library. The values
in Table
1 should be sufficient for application code.
Table 1.
GnomeUIInfoType Values
GnomeUIInfoType
|
Description
|
moreinfo Field
|
GNOME_APP_UI_ENDOFINFO
|
Terminates a table of
GnomeUIInfo
|
None
|
GNOME_APP_UI_ITEM
|
Normal item (or radio item inside radio group)
|
Callback function
|
GNOME_APP_UI_TOGGLEITEM
|
Toggle/check item
|
Callback function
|
GNOME_APP_UI_RADIOITEMS
|
Radio item group
|
Array of radio items in the group
|
GNOME_APP_UI_SUBTREE
|
Submenu
|
Array of GnomeUIInfo
in the subtree
|
GNOME_APP_UI_SEPARATOR
|
Separator
|
None
|
GNOME_APP_UI_HELP
|
Help item
|
Help node to load
|
To create an entire menu tree, you include pointers to
previous menu tables using the
GNOMEUIINFO_SUBTREE() macro:
static GnomeUIInfo main_menu[] = {
GNOMEUIINFO_SUBTREE(N_("_File"), file_menu),
GNOMEUIINFO_END
};
|
In this particular case, there is a better macro to use,
however:
static GnomeUIInfo main_menu[] = {
GNOMEUIINFO_MENU_FILE_TREE(file_menu),
GNOMEUIINFO_END
};
|
The main advantage of this macro is standardization; it
ensures that all Gnome file menus use the same key shortcut
and have the same name. There are quite a few analagous
macros; see
libgnomeui/gnome-app-helper.h for the complete list.
Once you have a menu table, Gnome will process it and
convert it to a widget. The functions are listed in Figure
4
If you are using the GnomeApp
widget,
gnome_app_create_menus() and
gnome_app_create_toolbar() create a menubar or
toolbar from the
GnomeUIInfo table you provide, then attach that to
the GnomeApp. Most of the time
these are the functions you want to use; they do
everything automatically. There is a _with_data() variant of each function
which overrides the
user_data field of
GnomeUIInfo.
If you have more specialized needs, you can manually fill
a menubar or toolbar and then add it to the container of
your choice. The fill
functions require you to specify an accelerator group to
add accelerators to; for
GnomeApp, an accelerator group already exists in the
widget struct (the
accel_group member). The
fill functions for menus take two additional
arguments: you can toggle whether to parse the
underscores in menu item labels to extract accelerators,
and you can specify at which position in the GtkMenuShell the function will begin
inserting menu items.
(GtkMenuShell is simply the
base class for GtkMenuBar and
GtkMenu, i.e. it is a widget
that contains menu items. An accelerator group is just a
collection of accelerators, normally attached to a GtkWindow; use GNOME_APP(widget)->accel_group in
this case.)
When you use a
GnomeUIInfo table to create a menubar or toolbar,
pointers to the individual menu item or toolbar button
widgets are placed in the
widget member of each
GnomeUIInfo struct. You can use these pointers to
access the individual widgets; for example, if you create
a check menu item you might want to set the state of the
check. The pointer is also useful if you want to manually
create some part of the menu; you can create an empty
subtree item, for example, and manually build the
contents of the subtree.
|
|