Mon Aug 26 12:21:16 BST 2002  Tony Gale <gale@gtk.org>

        * docs/tutorial/package-db-tutorial.sh: cleanups

        * docs/tutorial/gtk-tut.sgml: new content for the
        ItemFactory section. Originally from Robert Cleaver Ancell.
This commit is contained in:
BST 2002 Tony Gale 2002-08-26 11:35:57 +00:00 committed by Tony Gale
parent 7049e0cb59
commit 5abc7156b6
9 changed files with 627 additions and 160 deletions

View File

@ -1,3 +1,10 @@
Mon Aug 26 12:21:16 BST 2002 Tony Gale <gale@gtk.org>
* 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 <tml@iki.fi>
* gtk/gtkfilesel.c: Don't include <winsock.h> on Cygwin (#91654,

View File

@ -1,3 +1,10 @@
Mon Aug 26 12:21:16 BST 2002 Tony Gale <gale@gtk.org>
* 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 <tml@iki.fi>
* gtk/gtkfilesel.c: Don't include <winsock.h> on Cygwin (#91654,

View File

@ -1,3 +1,10 @@
Mon Aug 26 12:21:16 BST 2002 Tony Gale <gale@gtk.org>
* 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 <tml@iki.fi>
* gtk/gtkfilesel.c: Don't include <winsock.h> on Cygwin (#91654,

View File

@ -1,3 +1,10 @@
Mon Aug 26 12:21:16 BST 2002 Tony Gale <gale@gtk.org>
* 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 <tml@iki.fi>
* gtk/gtkfilesel.c: Don't include <winsock.h> on Cygwin (#91654,

View File

@ -1,3 +1,10 @@
Mon Aug 26 12:21:16 BST 2002 Tony Gale <gale@gtk.org>
* 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 <tml@iki.fi>
* gtk/gtkfilesel.c: Don't include <winsock.h> on Cygwin (#91654,

View File

@ -1,3 +1,10 @@
Mon Aug 26 12:21:16 BST 2002 Tony Gale <gale@gtk.org>
* 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 <tml@iki.fi>
* gtk/gtkfilesel.c: Don't include <winsock.h> on Cygwin (#91654,

View File

@ -5,7 +5,7 @@
<book id="gtk-tut">
<bookinfo>
<date>August 24, 2002</date>
<date>August 26, 2002</date>
<title>GTK+ 2.0 Tutorial</title>
<authorgroup>
<author>
@ -8586,6 +8586,326 @@ table, bind keys to menu functions.</para>
<para>Now that we've shown you the hard way, here's how you do it using the
gtk_item_factory calls.</para>
<para>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.</para>
<!-- ----------------------------------------------------------------- -->
<sect2 id="sec-ItemFactoryEntries">
<title>ItemFactory entries</title>
<para>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:</para>
<programlisting role="C">
struct _GtkItemFactoryEntry
{
gchar *path;
gchar *accelerator;
GtkItemFactoryCallback callback;
guint callback_action;
gchar *item_type;
};
</programlisting>
<para>Each field defines part of the menu item.</para>
<para><literal>*path</literal> 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.</para>
<para>
<literal>*accelerator</literal> 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.</para>
<para>The available modifier keys are:</para>
<programlisting role="C">
"&lt;ALT&gt; - alt
"&lt;CTL&gt;" or "&lt;CTRL&gt;" or "&lt;CONTROL&gt;" - control
"&lt;MOD1&gt;" to "&lt;MOD5&gt;" - modn
"&lt;SHFT&gt;" or "&lt;SHIFT&gt;" - shift
</programlisting>
<para>Examples:</para>
<programlisting role="C">
"&lt;ConTroL&gt;a"
"&lt;SHFT&gt;&lt;ALT&gt;&lt;CONTROL&gt;X"
</programlisting>
<para>
<literal>callback</literal> is the function that is called when the menu item
emits the "activate" signal. The form of the callback is described
in the <link linkend="sec-ItemFactoryCallback">Callback Description</link>
section.</para>
<para>
The value of <literal>callback_action</literal> is passed to the callback
function. It also affects the function prototype, as shown
in the <link linkend="sec-ItemFactoryCallback">Callback Description</link>
section.</para>
<para>
<literal>item_type</literal> is a string that defines what type of widget is
packed into the menu items container. It can be:</para>
<programlisting role="C">
NULL or "" or "&lt;Item&gt;" - create a simple item
"&lt;Title&gt;" - create a title item
"&lt;CheckItem&gt;" - create a check item
"&lt;ToggleItem&gt;" - create a toggle item
"&lt;RadioItem&gt;" - create a (root) radio item
"Path" - create a sister radio item
"&lt;Tearoff&gt;" - create a tearoff
"&lt;Separator&gt;" - create a separator
"&lt;Branch&gt;" - create an item to hold submenus (optional)
"&lt;LastBranch&gt;" - create a right justified branch
</programlisting>
<para>Note that &lt;LastBranch&gt; is only useful for one submenu of
a menubar.</para>
<!-- ----------------------------------------------------------------- -->
<sect3 id="sec-ItemFactoryCallback">
<title>Callback Description</title>
<para>
The callback for an ItemFactory entry can take two forms. If
<literal>callback_action</literal> is zero, it is of the following
form:</para>
<programlisting role="C">
void callback(void)
</programlisting>
<para>otherwise it is of the form:</para>
<programlisting role="C">
void callback(gpointer callback_data,
guint callback_action,
GtkWidget *widget)
</programlisting>
<para>
<literal>callback_data</literal> is a pointer to an arbitrary piece of data and
is set during the call to gtk_item_factory_create_items().</para>
<para>
<literal>callback_action</literal> is the same value as
<literal>callback_action</literal> in the ItemFactory entry.</para>
<para>
<literal>*widget</literal> is a pointer to a menu item widget
(described in <link linkend="sec-ManualMenuCreation">Manual Menu Creation</link>).
</para>
</sect3>
<!-- ----------------------------------------------------------------- -->
<sect3 id="sec-ItemFactoryEntryExamples">
<title>ItemFactory entry examples</title>
<para>Creating a simple menu item:</para>
<programlisting role="C">
GtkItemFactoryEntry entry = {"/_File/_Open...", "&lt;CTRL&gt;O", print_hello,
0, "&lt;Item&gt;"};
</programlisting>
<para>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 <literal>void print_hello(void)</literal> 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".</para>
<para>Creating an entry with a more complex callback:</para>
<programlisting role="C">
GtkItemFactoryEntry entry = {"/_View/Display _FPS", NULL, print_state,
7,"&lt;CheckItem&gt;"};
</programlisting>
<para>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 <literal>callback_action</literal> is not zero print_state() is of the
form:</para>
<programlisting role="C">
void print_state(gpointer callback_data,
guint callback_action,
GtkWidget *widget)
</programlisting>
<para>with <literal>callback_action</literal> equal to 7.</para>
<para>Creating a radio button set:</para>
<programlisting role="C">
GtkItemFactoryEntry entry1 = {"/_View/_Low Resolution", NULL, change_resolution,
1, "&lt;RadioButton&gt;"};
GtkItemFactoryEntry entry2 = {"/_View/_High Resolution", NULL, change_resolution,
2, "/View/Low Resolution"};
</programlisting>
<para><literal>entry1</literal> defines a lone radio button that when toggled
calls the function change_resolution() with the parameter
<literal>callback_action</literal> equal to 1. change_resolution() is of
the form:</para>
<programlisting role="C">
void change_resolution(gpointer callback_data,
guint callback_action,
GtkWidget *widget)
</programlisting>
<para><literal>entry2</literal> 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 <literal>callback_action</literal> equal to 2. Note that
the item_type of <literal>entry2</literal> is the path of entry1
<emphasis>without</emphasis> the accelerators ('_'). If another radio button was
required in the same group then it would be defined in the same way as
<literal>entry2</literal> was with its <literal>item_type</literal> again
equal to "/View/Low Resolution".</para>
</sect3>
<!-- ----------------------------------------------------------------- -->
<sect3 id="sec-ItemFactoryEntryArrays">
<title>ItemFactoryEntry Arrays</title>
<para>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.</para>
<programlisting role="C">
static GtkItemFactoryEntry entries[] = {
{ "/_File", NULL, NULL, 0, "&lt;Branch&gt;" },
{ "/File/tear1", NULL, NULL, 0, "&lt;Tearoff&gt;" },
{ "/File/_New", "&lt;CTRL&gt;N", new_file, 1, "&lt;Item&gt;" },
{ "/File/_Open...", "&lt;CTRL&gt;O", open_file, 1, "&lt;Item&gt;" },
{ "/File/sep1", NULL, NULL, 0, "&lt;Seperator&gt;" },
{ "/File/_Quit", "&lt;CTRL&gt;Q", quit_program, 0, "&lt;Item&gt;"} };
</programlisting>
</sect3>
</sect2>
<!-- ----------------------------------------------------------------- -->
<sect2 id="sec-ItemFactoryCreation">
<title>Creating an ItemFactory</title>
<para>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:</para>
<programlisting role="C">
GtkItemFactory* gtk_item_factory_new( GtkType container_type,
const gchar *path,
GtkAccelGroup *accel_group );
</programlisting>
<para><literal>container_type</literal> can be one of:</para>
<programlisting role="C">
GTK_TYPE_MENU
GTK_TYPE_MENU_BAR
GTK_TYPE_OPTION_MENU
</programlisting>
<para><literal>container_type</literal> 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).</para>
<para><literal>path</literal> 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 "&lt;&gt;". 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 "&lt;FooMain&gt;", and a pop-up menu
"&lt;FooImagePopUp&gt;", or similar. What's important is that they're unique.</para>
<para><literal>accel_group</literal> 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().</para>
<para>But this is just the first step. To convert the array of GtkItemFactoryEntry
information into widgets the following function is used:</para>
<programlisting role="C">
void gtk_item_factory_create_items( GtkItemFactory *ifactory,
guint n_entries,
GtkItemFactoryEntry *entries,
gpointer callback_data );
</programlisting>
<para><literal>*ifactory</literal> a pointer to the above created item factory.</para>
<para><literal>n_entries</literal> is the number of entries in the
GtkItemFactoryEntry array.</para>
<para><literal>*entries</literal> is a pointer to the GtkItemFactoryEntry array.</para>
<para><literal>callback_data</literal> is what gets passed to all the callback functions
for all the entries with callback_action != 0.</para>
<para>The accelerator group has now been formed, so you'll probably want
to attach it to the window the menu is in:</para>
<programlisting role="C">
void gtk_window_add_accel_group( GtkWindow *window,
GtkAccelGroup *accel_group);
</programlisting>
</sect2>
<!-- ----------------------------------------------------------------- -->
<sect2 id="sec-UsingMenuandItems">
<title>Making use of the menu and its menu items</title>
<para>The last thing to do is make use of the menu. The following function
extracts the relevant widgets from the ItemFactory:</para>
<programlisting role="C">
GtkWidget* gtk_item_factory_get_widget( GtkItemFactory *ifactory,
const gchar *path );
</programlisting>
<para>For instance if an ItemFactory has two entries "/File" and "/File/New",
using a path of "/File" would retrieve a <emphasis>menu</emphasis> widget from the
ItemFactory. Using a path of "/File/New" would retrieve a
<emphasis>menu item</emphasis> 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:</para>
<programlisting role="C">
gtk_check_menu_item_set_active(
GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory, "/Shape/Oval")),
TRUE);
</programlisting>
<para>Finally to retrieve the root of the menu use gtk_item_factory_get_item()
with a path of "&lt;main&gt;" (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.</para>
<para><emphasis>Remember</emphasis> for an entry defined with path "/_File"
the path here is actually "/File".</para>
<para>Now you have a menubar or menu which can be manipulated in the same
way as shown in the
<link linkend="sec-ManualMenuCreation">Manual Menu Creation</link>
section.</para>
</sect2>
</sect1>
<!-- ----------------------------------------------------------------- -->
@ -8595,10 +8915,10 @@ gtk_item_factory calls.</para>
<para>Here is an example using the GTK item factory.</para>
<programlisting role="C">
<!-- example-start menu itemfactory.c -->
/* example-start menu itemfactory.c */
#include &lt;gtk/gtk.h&gt;
#include &lt;strings.h&gt;
#include &amp;lt;gtk/gtk.h&amp;gt;
#include &amp;lt;strings.h&amp;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)-&amp;gt;active);
}
NULL -&gt; "&lt;Item&gt;"
"" -&gt; "&lt;Item&gt;"
"&lt;Title&gt;" -&gt; create a title item
"&lt;Item&gt;" -&gt; create a simple item
"&lt;CheckItem&gt;" -&gt; create a check item
"&lt;ToggleItem&gt;" -&gt; create a toggle item
"&lt;RadioItem&gt;" -&gt; create a radio item
&lt;path&gt; -&gt; path of a radio item to link against
"&lt;Separator&gt;" -&gt; create a separator
"&lt;Branch&gt;" -&gt; create an item to hold sub items (optional)
"&lt;LastBranch&gt;" -&gt; 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)-&amp;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, "&lt;Branch&gt;" },
{ "/File/_New", "&lt;control&gt;N", print_hello, 0, NULL },
{ "/File/_Open", "&lt;control&gt;O", print_hello, 0, NULL },
{ "/File/_Save", "&lt;control&gt;S", print_hello, 0, NULL },
{ "/File/Save _As", NULL, NULL, 0, NULL },
{ "/File/sep1", NULL, NULL, 0, "&lt;Separator&gt;" },
{ "/File/Quit", "&lt;control&gt;Q", gtk_main_quit, 0, NULL },
{ "/_Options", NULL, NULL, 0, "&lt;Branch&gt;" },
{ "/Options/Test", NULL, NULL, 0, NULL },
{ "/_Help", NULL, NULL, 0, "&lt;LastBranch&gt;" },
{ "/_Help/About", NULL, NULL, 0, NULL },
{ "/_File", NULL, NULL, 0, "&amp;lt;Branch&amp;gt;" },
{ "/File/_New", "&amp;lt;control&amp;gt;N", print_hello, 0, "&lt;Item&gt;" },
{ "/File/_Open", "&amp;lt;control&amp;gt;O", print_hello, 0, "&lt;Item&gt;" },
{ "/File/_Save", "&amp;lt;control&amp;gt;S", print_hello, 0, "&lt;Item&gt;" },
{ "/File/Save _As", NULL, NULL, 0, "&lt;Item&gt;" },
{ "/File/sep1", NULL, NULL, 0, "&amp;lt;Separator&amp;gt;" },
{ "/File/Quit", "&amp;lt;control&amp;gt;Q", gtk_main_quit, 0, "&lt;Item&gt;" },
{ "/_Options", NULL, NULL, 0, "&amp;lt;Branch&amp;gt;" },
{ "/Options/tear", NULL, NULL, 0, "&amp;lt;Tearoff&amp;gt;" },
{ "/Options/Check", NULL, print_toggle, 1, "&amp;lt;CheckItem&amp;gt;" },
{ "/Options/sep", NULL, NULL, 0, "&amp;lt;Separator&amp;gt;" },
{ "/Options/Rad1", NULL, print_selected, 1, "&amp;lt;RadioItem&amp;gt;" },
{ "/Options/Rad2", NULL, print_selected, 2, "/Options/Rad1" },
{ "/Options/Rad3", NULL, print_selected, 3, "/Options/Rad1" },
{ "/_Help", NULL, NULL, 0, "&amp;lt;LastBranch&amp;gt;" },
{ "/_Help/About", NULL, NULL, 0, "&lt;Item&gt;" },
};
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, "&lt;main&gt;",
accel_group);
/* Make an ItemFactory (that makes a menubar) */
item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "&amp;lt;main&amp;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, "&lt;main&gt;");
/* Finally, return the actual menu bar created by the item factory. */
return gtk_item_factory_get_widget (item_factory, "&amp;lt;main&amp;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-&amp;gt;type != GDK_BUTTON_PRESS)
return FALSE;
/* Show the menu */
gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
NULL, NULL, bevent-&amp;gt;button, bevent-&amp;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, "&amp;lt;main&amp;gt;",
NULL);
gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
menu = gtk_item_factory_get_widget(item_factory, "&amp;lt;main&amp;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, "&amp;lt;main&amp;gt;",
NULL);
gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
option_menu = gtk_item_factory_get_widget(item_factory, "&amp;lt;main&amp;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 (&amp;argc, &amp;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, &amp;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 -->
/* example-end */
</programlisting>
<para>For now, there's only this example. An explanation and lots 'o' comments
will follow later.</para>
</sect1>
</chapter>

View File

@ -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.... "

View File

@ -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 -> "<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)->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);
}