diff --git a/ChangeLog b/ChangeLog index ed9434e228..74f4cff1e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Mon Aug 26 12:21:16 BST 2002 Tony Gale + + * docs/tutorial/package-db-tutorial.sh: cleanups + + * docs/tutorial/gtk-tut.sgml: new content for the + ItemFactory section. Originally from Robert Cleaver Ancell. + 2002-08-25 Tor Lillqvist * gtk/gtkfilesel.c: Don't include on Cygwin (#91654, diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index ed9434e228..74f4cff1e3 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,10 @@ +Mon Aug 26 12:21:16 BST 2002 Tony Gale + + * docs/tutorial/package-db-tutorial.sh: cleanups + + * docs/tutorial/gtk-tut.sgml: new content for the + ItemFactory section. Originally from Robert Cleaver Ancell. + 2002-08-25 Tor Lillqvist * gtk/gtkfilesel.c: Don't include on Cygwin (#91654, diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index ed9434e228..74f4cff1e3 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,10 @@ +Mon Aug 26 12:21:16 BST 2002 Tony Gale + + * docs/tutorial/package-db-tutorial.sh: cleanups + + * docs/tutorial/gtk-tut.sgml: new content for the + ItemFactory section. Originally from Robert Cleaver Ancell. + 2002-08-25 Tor Lillqvist * gtk/gtkfilesel.c: Don't include on Cygwin (#91654, diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index ed9434e228..74f4cff1e3 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,10 @@ +Mon Aug 26 12:21:16 BST 2002 Tony Gale + + * docs/tutorial/package-db-tutorial.sh: cleanups + + * docs/tutorial/gtk-tut.sgml: new content for the + ItemFactory section. Originally from Robert Cleaver Ancell. + 2002-08-25 Tor Lillqvist * gtk/gtkfilesel.c: Don't include on Cygwin (#91654, diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index ed9434e228..74f4cff1e3 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,10 @@ +Mon Aug 26 12:21:16 BST 2002 Tony Gale + + * docs/tutorial/package-db-tutorial.sh: cleanups + + * docs/tutorial/gtk-tut.sgml: new content for the + ItemFactory section. Originally from Robert Cleaver Ancell. + 2002-08-25 Tor Lillqvist * gtk/gtkfilesel.c: Don't include on Cygwin (#91654, diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index ed9434e228..74f4cff1e3 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,10 @@ +Mon Aug 26 12:21:16 BST 2002 Tony Gale + + * docs/tutorial/package-db-tutorial.sh: cleanups + + * docs/tutorial/gtk-tut.sgml: new content for the + ItemFactory section. Originally from Robert Cleaver Ancell. + 2002-08-25 Tor Lillqvist * gtk/gtkfilesel.c: Don't include on Cygwin (#91654, diff --git a/docs/tutorial/gtk-tut.sgml b/docs/tutorial/gtk-tut.sgml index c4b3d8677b..53325ed438 100755 --- a/docs/tutorial/gtk-tut.sgml +++ b/docs/tutorial/gtk-tut.sgml @@ -5,7 +5,7 @@ - August 24, 2002 + August 26, 2002 GTK+ 2.0 Tutorial @@ -8586,6 +8586,326 @@ table, bind keys to menu functions. Now that we've shown you the hard way, here's how you do it using the gtk_item_factory calls. +ItemFactory creates a menu out of an array of ItemFactory entries. This +means you can define your menu in its simplest form and then create the +menu/menubar widgets with a minimum of function calls. + + + +ItemFactory entries + +At the core of ItemFactory is the ItemFactoryEntry. This structure defines +one menu item, and when an array of these entries is defined a whole +menu is formed. The ItemFactory entry struct definition looks like this: + + +struct _GtkItemFactoryEntry +{ + gchar *path; + gchar *accelerator; + + GtkItemFactoryCallback callback; + guint callback_action; + + gchar *item_type; +}; + + +Each field defines part of the menu item. + +*path is a string which defines both the name and the +path of a menu item, for example, "/File/Open" would be the name of a menu +item which would come under the ItemFactory entry with path "/File". Note however +that "/File/Open" would be displayed in the File menu as "Open". Also note +since the forward slashes are used to define the path of the menu, +they cannot be used as part of the name. A letter preceded by an underscore +indicates an accelerator (shortcut) key once the menu is open. + + +*accelerator is a string that indicates a key combination +that can be used as a shortcut to that menu item. The string can be made up +of either a single character, or a combination of modifier keys with a single +character. It is case insensitive. + + +The available modifier keys are: + + +"<ALT> - alt +"<CTL>" or "<CTRL>" or "<CONTROL>" - control +"<MOD1>" to "<MOD5>" - modn +"<SHFT>" or "<SHIFT>" - shift + + +Examples: + +"<ConTroL>a" +"<SHFT><ALT><CONTROL>X" + + + +callback is the function that is called when the menu item +emits the "activate" signal. The form of the callback is described +in the Callback Description +section. + + +The value of callback_action is passed to the callback +function. It also affects the function prototype, as shown +in the Callback Description +section. + + +item_type is a string that defines what type of widget is +packed into the menu items container. It can be: + + +NULL or "" or "<Item>" - create a simple item +"<Title>" - create a title item +"<CheckItem>" - create a check item +"<ToggleItem>" - create a toggle item +"<RadioItem>" - create a (root) radio item +"Path" - create a sister radio item +"<Tearoff>" - create a tearoff +"<Separator>" - create a separator +"<Branch>" - create an item to hold submenus (optional) +"<LastBranch>" - create a right justified branch + + +Note that <LastBranch> is only useful for one submenu of +a menubar. + + + +Callback Description + + +The callback for an ItemFactory entry can take two forms. If +callback_action is zero, it is of the following +form: + + +void callback(void) + + +otherwise it is of the form: + + +void callback(gpointer callback_data, + guint callback_action, + GtkWidget *widget) + + + +callback_data is a pointer to an arbitrary piece of data and +is set during the call to gtk_item_factory_create_items(). + + +callback_action is the same value as +callback_action in the ItemFactory entry. + + +*widget is a pointer to a menu item widget +(described in Manual Menu Creation). + + + + + +ItemFactory entry examples + +Creating a simple menu item: + + +GtkItemFactoryEntry entry = {"/_File/_Open...", "<CTRL>O", print_hello, + 0, "<Item>"}; + + +This will define a new simple menu entry "/File/Open" (displayed as "Open"), +under the menu entry "/File". It has the accelerator (shortcut) control+'O' +that when clicked calls the function print_hello(). print_hello() is of +the form void print_hello(void) since the callback_action +field is zero. When displayed the 'O' in "Open" will be underlined and if the +menu item is visible on the screen pressing 'O' will activate the item. Note +that "File/_Open" could also have been used as the path instead of +"/_File/_Open". + +Creating an entry with a more complex callback: + + +GtkItemFactoryEntry entry = {"/_View/Display _FPS", NULL, print_state, + 7,"<CheckItem>"}; + + +This defines a new menu item displayed as "Display FPS" which is under +the menu item "View". When clicked the function print_state() will be called. +Since callback_action is not zero print_state() is of the +form: + + +void print_state(gpointer callback_data, + guint callback_action, + GtkWidget *widget) + + +with callback_action equal to 7. + +Creating a radio button set: + + +GtkItemFactoryEntry entry1 = {"/_View/_Low Resolution", NULL, change_resolution, + 1, "<RadioButton>"}; +GtkItemFactoryEntry entry2 = {"/_View/_High Resolution", NULL, change_resolution, + 2, "/View/Low Resolution"}; + + +entry1 defines a lone radio button that when toggled +calls the function change_resolution() with the parameter +callback_action equal to 1. change_resolution() is of +the form: + + +void change_resolution(gpointer callback_data, + guint callback_action, + GtkWidget *widget) + + +entry2 defines a radio button that belongs to the +radio group that entry1 belongs to. It calls the same function when toggled +but with the parameter callback_action equal to 2. Note that +the item_type of entry2 is the path of entry1 +without the accelerators ('_'). If another radio button was +required in the same group then it would be defined in the same way as +entry2 was with its item_type again +equal to "/View/Low Resolution". + + + + +ItemFactoryEntry Arrays + +An ItemFactoryEntry on it's own however isn't useful. An array of +entries is what's required to define a menu. Below is an example of how +you'd declare this array. + + +static GtkItemFactoryEntry entries[] = { + { "/_File", NULL, NULL, 0, "<Branch>" }, + { "/File/tear1", NULL, NULL, 0, "<Tearoff>" }, + { "/File/_New", "<CTRL>N", new_file, 1, "<Item>" }, + { "/File/_Open...", "<CTRL>O", open_file, 1, "<Item>" }, + { "/File/sep1", NULL, NULL, 0, "<Seperator>" }, + { "/File/_Quit", "<CTRL>Q", quit_program, 0, "<Item>"} }; + + + + + + +Creating an ItemFactory + +An array of GtkItemFactoryEntry items defines a menu. Once this +array is defined then the item factory can be created. The function that +does this is: + + +GtkItemFactory* gtk_item_factory_new( GtkType container_type, + const gchar *path, + GtkAccelGroup *accel_group ); + + +container_type can be one of: + + +GTK_TYPE_MENU +GTK_TYPE_MENU_BAR +GTK_TYPE_OPTION_MENU + + +container_type defines what type of menu +you want, so when you extract it later it is either a menu (for pop-ups +for instance), a menu bar, or an option menu (like a combo box but with +a menu of pull downs). + +path defines the path of the root of the menu. +Basically it is a unique name for the root of the menu, it must be +surrounded by "<>". This is important for the naming of the +accelerators and should be unique. It should be unique both for each +menu and between each program. For example in a program named 'foo', the +main menu should be called "<FooMain>", and a pop-up menu +"<FooImagePopUp>", or similar. What's important is that they're unique. + +accel_group is a pointer to a gtk_accel_group. The +item factory sets up the accelerator table while generating menus. New +accelerator groups are generated by gtk_accel_group_new(). + +But this is just the first step. To convert the array of GtkItemFactoryEntry +information into widgets the following function is used: + + +void gtk_item_factory_create_items( GtkItemFactory *ifactory, + guint n_entries, + GtkItemFactoryEntry *entries, + gpointer callback_data ); + + +*ifactory a pointer to the above created item factory. +n_entries is the number of entries in the +GtkItemFactoryEntry array. +*entries is a pointer to the GtkItemFactoryEntry array. +callback_data is what gets passed to all the callback functions +for all the entries with callback_action != 0. + +The accelerator group has now been formed, so you'll probably want +to attach it to the window the menu is in: + + +void gtk_window_add_accel_group( GtkWindow *window, + GtkAccelGroup *accel_group); + + + + + +Making use of the menu and its menu items + +The last thing to do is make use of the menu. The following function +extracts the relevant widgets from the ItemFactory: + + +GtkWidget* gtk_item_factory_get_widget( GtkItemFactory *ifactory, + const gchar *path ); + + +For instance if an ItemFactory has two entries "/File" and "/File/New", +using a path of "/File" would retrieve a menu widget from the +ItemFactory. Using a path of "/File/New" would retrieve a +menu item widget. This makes it possible to set the initial state +of menu items. For example to set the default radio +item to the one with the path "/Shape/Oval" then the following code would +be used: + + +gtk_check_menu_item_set_active( + GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory, "/Shape/Oval")), + TRUE); + + +Finally to retrieve the root of the menu use gtk_item_factory_get_item() +with a path of "<main>" (or whatever path was used in +gtk_item_factory_new()). In the case of the ItemFactory being created with +type GTK_TYPE_MENU_BAR this returns a menu bar widget. With type GTK_TYPE_MENU +a menu widget is returned. With type GTK_TYPE_OPTION_MENU an option menu +widget is returned. + +Remember for an entry defined with path "/_File" +the path here is actually "/File". + +Now you have a menubar or menu which can be manipulated in the same +way as shown in the +Manual Menu Creation +section. + @@ -8595,10 +8915,10 @@ gtk_item_factory calls. Here is an example using the GTK item factory. - +/* example-start menu itemfactory.c */ -#include <gtk/gtk.h> -#include <strings.h> +#include &lt;gtk/gtk.h&gt; +#include &lt;strings.h&gt; /* Obligatory basic callback */ static void print_hello( GtkWidget *w, @@ -8607,63 +8927,58 @@ static void print_hello( GtkWidget *w, g_message ("Hello, World!\n"); } -/* This is the GtkItemFactoryEntry structure used to generate new menus. - Item 1: The menu path. The letter after the underscore indicates an - accelerator key once the menu is open. - Item 2: The accelerator key for the entry - Item 3: The callback function. - Item 4: The callback action. This changes the parameters with - which the function is called. The default is 0. - Item 5: The item type, used to define what kind of an item it is. - Here are the possible values: +/* For the check button */ +static void print_toggle(gpointer callback_data, + guint callback_action, + GtkWidget *menu_item) +{ + g_message ("Check button state - %d\n", + GTK_CHECK_MENU_ITEM(menu_item)-&gt;active); +} - NULL -> "<Item>" - "" -> "<Item>" - "<Title>" -> create a title item - "<Item>" -> create a simple item - "<CheckItem>" -> create a check item - "<ToggleItem>" -> create a toggle item - "<RadioItem>" -> create a radio item - <path> -> path of a radio item to link against - "<Separator>" -> create a separator - "<Branch>" -> create an item to hold sub items (optional) - "<LastBranch>" -> create a right justified branch -*/ +/* For the radio buttons */ +static void print_selected(gpointer callback_data, + guint callback_action, + GtkWidget *menu_item) +{ + if(GTK_CHECK_MENU_ITEM(menu_item)-&gt;active) + g_message("Radio button %d selected\n", callback_action); +} +/* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */ static GtkItemFactoryEntry menu_items[] = { - { "/_File", NULL, NULL, 0, "<Branch>" }, - { "/File/_New", "<control>N", print_hello, 0, NULL }, - { "/File/_Open", "<control>O", print_hello, 0, NULL }, - { "/File/_Save", "<control>S", print_hello, 0, NULL }, - { "/File/Save _As", NULL, NULL, 0, NULL }, - { "/File/sep1", NULL, NULL, 0, "<Separator>" }, - { "/File/Quit", "<control>Q", gtk_main_quit, 0, NULL }, - { "/_Options", NULL, NULL, 0, "<Branch>" }, - { "/Options/Test", NULL, NULL, 0, NULL }, - { "/_Help", NULL, NULL, 0, "<LastBranch>" }, - { "/_Help/About", NULL, NULL, 0, NULL }, + { "/_File", NULL, NULL, 0, "&lt;Branch&gt;" }, + { "/File/_New", "&lt;control&gt;N", print_hello, 0, "<Item>" }, + { "/File/_Open", "&lt;control&gt;O", print_hello, 0, "<Item>" }, + { "/File/_Save", "&lt;control&gt;S", print_hello, 0, "<Item>" }, + { "/File/Save _As", NULL, NULL, 0, "<Item>" }, + { "/File/sep1", NULL, NULL, 0, "&lt;Separator&gt;" }, + { "/File/Quit", "&lt;control&gt;Q", gtk_main_quit, 0, "<Item>" }, + { "/_Options", NULL, NULL, 0, "&lt;Branch&gt;" }, + { "/Options/tear", NULL, NULL, 0, "&lt;Tearoff&gt;" }, + { "/Options/Check", NULL, print_toggle, 1, "&lt;CheckItem&gt;" }, + { "/Options/sep", NULL, NULL, 0, "&lt;Separator&gt;" }, + { "/Options/Rad1", NULL, print_selected, 1, "&lt;RadioItem&gt;" }, + { "/Options/Rad2", NULL, print_selected, 2, "/Options/Rad1" }, + { "/Options/Rad3", NULL, print_selected, 3, "/Options/Rad1" }, + { "/_Help", NULL, NULL, 0, "&lt;LastBranch&gt;" }, + { "/_Help/About", NULL, NULL, 0, "<Item>" }, }; +static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]); -void get_main_menu( GtkWidget *window, - GtkWidget **menubar ) +/* Returns a menubar widget made from the above menu */ +GtkWidget *get_menubar_menu( GtkWidget *window) { GtkItemFactory *item_factory; GtkAccelGroup *accel_group; - gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]); + /* Make an accelerator group (shortcut keys) */ accel_group = gtk_accel_group_new (); - /* This function initializes the item factory. - Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU, - or GTK_TYPE_OPTION_MENU. - Param 2: The path of the menu. - Param 3: A pointer to a gtk_accel_group. The item factory sets up - the accelerator table while generating menus. - */ - - item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", - accel_group); + /* Make an ItemFactory (that makes a menubar) */ + item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "&lt;main&gt;", + accel_group); /* This function generates the menu items. Pass the item factory, the number of items in the array, the array itself, and any @@ -8673,48 +8988,112 @@ void get_main_menu( GtkWidget *window, /* Attach the new accelerator group to the window. */ gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); - if (menubar) - /* Finally, return the actual menu bar created by the item factory. */ - *menubar = gtk_item_factory_get_widget (item_factory, "<main>"); + /* Finally, return the actual menu bar created by the item factory. */ + return gtk_item_factory_get_widget (item_factory, "&lt;main&gt;"); } +/* Popup the menu when the popup button is pressed */ +static gint popup_cb(GtkWidget *widget, GdkEvent *event, GtkWidget *menu) +{ + GdkEventButton *bevent = (GdkEventButton *)event; + + /* Only take button presses */ + if(event-&gt;type != GDK_BUTTON_PRESS) + return FALSE; + + /* Show the menu */ + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, + NULL, NULL, bevent-&gt;button, bevent-&gt;time); + + return TRUE; +} + +/* Same as with get_menubar_menu() but just return a button with a signal to + call a popup menu */ +GtkWidget *get_popup_menu(void) +{ + GtkItemFactory *item_factory; + GtkWidget *button, *menu; + + /* Same as before but don't bother with the accelerators */ + item_factory = gtk_item_factory_new (GTK_TYPE_MENU, "&lt;main&gt;", + NULL); + gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); + menu = gtk_item_factory_get_widget(item_factory, "&lt;main&gt;"); + + /* Make a button to activate the popup menu */ + button = gtk_button_new_with_label("Popup"); + /* Make the menu popup when clicked */ + g_signal_connect(G_OBJECT(button), + "event", + G_CALLBACK(popup_cb), + (gpointer) menu); + + return button; +} + +/* Same again but return an option menu */ +GtkWidget *get_option_menu(void) +{ + GtkItemFactory *item_factory; + GtkWidget *option_menu; + + /* Same again, not bothering with the accelerators */ + item_factory = gtk_item_factory_new (GTK_TYPE_OPTION_MENU, "&lt;main&gt;", + NULL); + gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); + option_menu = gtk_item_factory_get_widget(item_factory, "&lt;main&gt;"); + + return option_menu; +} + +/* You have to start somewhere */ int main( int argc, char *argv[] ) { GtkWidget *window; GtkWidget *main_vbox; - GtkWidget *menubar; - + GtkWidget *menubar, *option_menu, *popup_button; + + /* Initialize GTK */ gtk_init (&argc, &argv); - + + /* Make a window */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - g_signal_connect (G_OBJECT (window), "destroy", - G_CALLBACK (gtk_main_quit), - NULL); - gtk_window_set_title (GTK_WINDOW (window), "Item Factory"); - gtk_widget_set_size_request (GTK_WIDGET (window), 300, 200); - + g_signal_connect (G_OBJECT (window), "destroy", + G_CALLBACK (gtk_main_quit), + NULL); + gtk_window_set_title (GTK_WINDOW(window), "Item Factory"); + gtk_widget_set_size_request (GTK_WIDGET(window), 300, 200); + + /* Make a vbox to put the three menus in */ main_vbox = gtk_vbox_new (FALSE, 1); gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 1); gtk_container_add (GTK_CONTAINER (window), main_vbox); - gtk_widget_show (main_vbox); + + /* Get the three types of menu */ + /* Note: all three menus are separately created, so they are not the + same menu */ + menubar = get_menubar_menu (window); + popup_button = get_popup_menu(); + option_menu = get_option_menu(); - get_main_menu (window, &menubar); + /* Pack it all together */ gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0); - gtk_widget_show (menubar); - - gtk_widget_show (window); + gtk_box_pack_end (GTK_BOX (main_vbox), popup_button, FALSE, TRUE, 0); + gtk_box_pack_end (GTK_BOX (main_vbox), option_menu, FALSE, TRUE, 0); + /* Show the widgets */ + gtk_widget_show_all (window); + + /* Finished! */ gtk_main (); - - return 0; + + return(0); } - +/* example-end */ -For now, there's only this example. An explanation and lots 'o' comments -will follow later. - diff --git a/docs/tutorial/package-db-tutorial.sh b/docs/tutorial/package-db-tutorial.sh index 79249a380e..8d43fb0b4e 100755 --- a/docs/tutorial/package-db-tutorial.sh +++ b/docs/tutorial/package-db-tutorial.sh @@ -10,6 +10,7 @@ TARGET=`pwd`/gtk-tut.sgml IMAGES="`pwd`/images" +IMAGESDIR="images" EXAMPLES=`pwd`/../../examples PATH=`pwd`:$PATH @@ -46,7 +47,7 @@ if [ ! -d sgml ]; then mkdir sgml fi -(cd sgml ; cp $TARGET . ; cp -R $IMAGES . ; rm -rf images/CVS) +(cd sgml ; cp $TARGET . ; cp -R $IMAGES . ; rm -rf $IMAGESDIR/CVS) echo "done" # HTML Format @@ -59,8 +60,8 @@ if [ ! -d html ]; then mkdir html fi -(db2html gtk-tut.sgml ; mv gtk-tut/* html ; cp -R $IMAGES html ; rm -rf gtk-tut) > /dev/null -(cd html ; ln -s book1.html index.html ; rm -rf images/CVS) +(db2html gtk-tut.sgml ; mv gtk-tut/* html ; cp -R $IMAGES html ; rm html/$IMAGESDIR/*.eps ; rm -rf gtk-tut) > /dev/null +(cd html ; ln -s book1.html index.html ; rm -rf $IMAGESDIR/CVS) echo "done" # PS, PDF and DVI Format @@ -81,29 +82,12 @@ if [ ! -d pdf ]; then mkdir pdf fi -#sed 's/gtk_tut_packbox1.jpg/gtk_tut_packbox1.eps/ ; s/gtk_tut_packbox2.jpg/gtk_tut_packbox2.eps/ ; s/gtk_tut_table.jpg/gtk_tut_table.eps/' gtk-tut.sgml > ps/gtk-tut.sgml sed "s/images\/\(.*\)\.png/images\/\1.eps/g" gtk-tut.sgml > ps/gtk-tut.sgml -cp -R ../images ps +cp -R $IMAGES ps (cd ps ; db2dvi gtk-tut.sgml ; dvips gtk-tut.dvi -o gtk-tut.ps ; dvipdf gtk-tut.dvi ../pdf/gtk-tut.pdf) > /dev/null 2>&1 -#sed 's/gtk_tut_packbox1.jpg/gtk_tut_packbox1.eps/ ; s/gtk_tut_packbox2.jpg/gtk_tut_packbox2.eps/ ; s/gtk_tut_table.jpg/gtk_tut_table.eps/' gtk-tut.sgml > ps/gtk-tut.sgml -#sed "s/images\/\(.*\)\.png/images\/\1.eps/g" gtk-tut.sgml > ps/gtk-tut.sgml -#cp -R images ps -(cd ps ; rm gtk-tut.aux gtk-tut.log gtk-tut.sgml gtk-tut.tex ; rm -Rf images) > /dev/null 2>&1 +(cd ps ; rm gtk-tut.aux gtk-tut.log gtk-tut.sgml gtk-tut.tex ; rm -Rf $IMAGESDIR) > /dev/null 2>&1 echo "done" -# PDF Format -#echo -n "Formatting into PDF.... " -#if [ ! -d pdf ]; then -# if [ -e pdf ]; then -# echo "ERROR: pdf is not a directory" -# exit -# fi -# mkdir pdf -#fi - -#(db2pdf gtk-tut.sgml ; mv gtk-tut.pdf pdf) > /dev/null -#echo "done" - # RTF Format echo -n "Formatting into RTF.... " if [ ! -d rtf ]; then @@ -115,7 +99,7 @@ if [ ! -d rtf ]; then fi (db2rtf gtk-tut.sgml ; mv gtk-tut.rtf rtf) > /dev/null -cp -R $IMAGES rtf +(cd rtf ; cp -R $IMAGES . ; rm -f $IMAGESDIR/*.eps ; rm -rf $IMAGESDIR/CVS) echo "done" # Copy examples @@ -125,7 +109,7 @@ cp -R $EXAMPLES . echo "done" rm -f * -rm -rf images +rm -rf $IMAGESDIR # Package it all up echo -n "Creating packages.... " diff --git a/examples/menu/itemfactory.c b/examples/menu/itemfactory.c index 76f566e876..c4559c2275 100644 --- a/examples/menu/itemfactory.c +++ b/examples/menu/itemfactory.c @@ -9,63 +9,58 @@ static void print_hello( GtkWidget *w, g_message ("Hello, World!\n"); } -/* This is the GtkItemFactoryEntry structure used to generate new menus. - Item 1: The menu path. The letter after the underscore indicates an - accelerator key once the menu is open. - Item 2: The accelerator key for the entry - Item 3: The callback function. - Item 4: The callback action. This changes the parameters with - which the function is called. The default is 0. - Item 5: The item type, used to define what kind of an item it is. - Here are the possible values: +/* For the check button */ +static void print_toggle(gpointer callback_data, + guint callback_action, + GtkWidget *menu_item) +{ + g_message ("Check button state - %d\n", + GTK_CHECK_MENU_ITEM(menu_item)->active); +} - NULL -> "" - "" -> "" - "" -> create a title item - "<Item>" -> create a simple item - "<CheckItem>" -> create a check item - "<ToggleItem>" -> create a toggle item - "<RadioItem>" -> create a radio item - <path> -> path of a radio item to link against - "<Separator>" -> create a separator - "<Branch>" -> create an item to hold sub items (optional) - "<LastBranch>" -> create a right justified branch -*/ +/* For the radio buttons */ +static void print_selected(gpointer callback_data, + guint callback_action, + GtkWidget *menu_item) +{ + if(GTK_CHECK_MENU_ITEM(menu_item)->active) + g_message("Radio button %d selected\n", callback_action); +} +/* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */ static GtkItemFactoryEntry menu_items[] = { - { "/_File", NULL, NULL, 0, "<Branch>" }, - { "/File/_New", "<control>N", print_hello, 0, NULL }, - { "/File/_Open", "<control>O", print_hello, 0, NULL }, - { "/File/_Save", "<control>S", print_hello, 0, NULL }, - { "/File/Save _As", NULL, NULL, 0, NULL }, - { "/File/sep1", NULL, NULL, 0, "<Separator>" }, - { "/File/Quit", "<control>Q", gtk_main_quit, 0, NULL }, - { "/_Options", NULL, NULL, 0, "<Branch>" }, - { "/Options/Test", NULL, NULL, 0, NULL }, - { "/_Help", NULL, NULL, 0, "<LastBranch>" }, - { "/_Help/About", NULL, NULL, 0, NULL }, + { "/_File", NULL, NULL, 0, "<Branch>" }, + { "/File/_New", "<control>N", print_hello, 0, "<Item>" }, + { "/File/_Open", "<control>O", print_hello, 0, "<Item>" }, + { "/File/_Save", "<control>S", print_hello, 0, "<Item>" }, + { "/File/Save _As", NULL, NULL, 0, "<Item>" }, + { "/File/sep1", NULL, NULL, 0, "<Separator>" }, + { "/File/Quit", "<control>Q", gtk_main_quit, 0, "<Item>" }, + { "/_Options", NULL, NULL, 0, "<Branch>" }, + { "/Options/tear", NULL, NULL, 0, "<Tearoff>" }, + { "/Options/Check", NULL, print_toggle, 1, "<CheckItem>" }, + { "/Options/sep", NULL, NULL, 0, "<Separator>" }, + { "/Options/Rad1", NULL, print_selected, 1, "<RadioItem>" }, + { "/Options/Rad2", NULL, print_selected, 2, "/Options/Rad1" }, + { "/Options/Rad3", NULL, print_selected, 3, "/Options/Rad1" }, + { "/_Help", NULL, NULL, 0, "<LastBranch>" }, + { "/_Help/About", NULL, NULL, 0, "<Item>" }, }; +static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]); -void get_main_menu( GtkWidget *window, - GtkWidget **menubar ) +/* Returns a menubar widget made from the above menu */ +GtkWidget *get_menubar_menu( GtkWidget *window) { GtkItemFactory *item_factory; GtkAccelGroup *accel_group; - gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]); + /* Make an accelerator group (shortcut keys) */ accel_group = gtk_accel_group_new (); - /* This function initializes the item factory. - Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU, - or GTK_TYPE_OPTION_MENU. - Param 2: The path of the menu. - Param 3: A pointer to a gtk_accel_group. The item factory sets up - the accelerator table while generating menus. - */ - - item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", - accel_group); + /* Make an ItemFactory (that makes a menubar) */ + item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", + accel_group); /* This function generates the menu items. Pass the item factory, the number of items in the array, the array itself, and any @@ -75,39 +70,106 @@ void get_main_menu( GtkWidget *window, /* Attach the new accelerator group to the window. */ gtk_window_add_accel_group (GTK_WINDOW (window), accel_group); - if (menubar) - /* Finally, return the actual menu bar created by the item factory. */ - *menubar = gtk_item_factory_get_widget (item_factory, "<main>"); + /* Finally, return the actual menu bar created by the item factory. */ + return gtk_item_factory_get_widget (item_factory, "<main>"); } +/* Popup the menu when the popup button is pressed */ +static gint popup_cb(GtkWidget *widget, GdkEvent *event, GtkWidget *menu) +{ + GdkEventButton *bevent = (GdkEventButton *)event; + + /* Only take button presses */ + if(event->type != GDK_BUTTON_PRESS) + return FALSE; + + /* Show the menu */ + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, + NULL, NULL, bevent->button, bevent->time); + + return TRUE; +} + +/* Same as with get_menubar_menu() but just return a button with a signal to + call a popup menu */ +GtkWidget *get_popup_menu(void) +{ + GtkItemFactory *item_factory; + GtkWidget *button, *menu; + + /* Same as before but don't bother with the accelerators */ + item_factory = gtk_item_factory_new (GTK_TYPE_MENU, "<main>", + NULL); + gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); + menu = gtk_item_factory_get_widget(item_factory, "<main>"); + + /* Make a button to activate the popup menu */ + button = gtk_button_new_with_label("Popup"); + /* Make the menu popup when clicked */ + g_signal_connect(G_OBJECT(button), + "event", + G_CALLBACK(popup_cb), + (gpointer) menu); + + return button; +} + +/* Same again but return an option menu */ +GtkWidget *get_option_menu(void) +{ + GtkItemFactory *item_factory; + GtkWidget *option_menu; + + /* Same again, not bothering with the accelerators */ + item_factory = gtk_item_factory_new (GTK_TYPE_OPTION_MENU, "<main>", + NULL); + gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL); + option_menu = gtk_item_factory_get_widget(item_factory, "<main>"); + + return option_menu; +} + +/* You have to start somewhere */ int main( int argc, char *argv[] ) { GtkWidget *window; GtkWidget *main_vbox; - GtkWidget *menubar; - + GtkWidget *menubar, *option_menu, *popup_button; + + /* Initialize GTK */ gtk_init (&argc, &argv); - + + /* Make a window */ window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - g_signal_connect (G_OBJECT (window), "destroy", - G_CALLBACK (gtk_main_quit), - NULL); - gtk_window_set_title (GTK_WINDOW (window), "Item Factory"); - gtk_widget_set_size_request (GTK_WIDGET (window), 300, 200); - + g_signal_connect (G_OBJECT (window), "destroy", + G_CALLBACK (gtk_main_quit), + NULL); + gtk_window_set_title (GTK_WINDOW(window), "Item Factory"); + gtk_widget_set_size_request (GTK_WIDGET(window), 300, 200); + + /* Make a vbox to put the three menus in */ main_vbox = gtk_vbox_new (FALSE, 1); gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 1); gtk_container_add (GTK_CONTAINER (window), main_vbox); - gtk_widget_show (main_vbox); + + /* Get the three types of menu */ + /* Note: all three menus are separately created, so they are not the + same menu */ + menubar = get_menubar_menu (window); + popup_button = get_popup_menu(); + option_menu = get_option_menu(); - get_main_menu (window, &menubar); + /* Pack it all together */ gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0); - gtk_widget_show (menubar); - - gtk_widget_show (window); + gtk_box_pack_end (GTK_BOX (main_vbox), popup_button, FALSE, TRUE, 0); + gtk_box_pack_end (GTK_BOX (main_vbox), option_menu, FALSE, TRUE, 0); - gtk_main (); + /* Show the widgets */ + gtk_widget_show_all (window); - return 0; + /* Finished! */ + gtk_main (); + + return(0); }