<title>GTK v1.2 Tutorial
<author>
Tony Gale <tt><htmlurl url="mailto:gale@gtk.org"
- name="<gale@gtk.org>"></tt>
+ name="<gale@gtk.org>"></tt>,
Ian Main <tt><htmlurl url="mailto:imain@gtk.org"
- name="<imain@gtk.org>"></tt>,
-<date>February 7th, 1999
+ name="<imain@gtk.org>"></tt>
+<date>February 23rd, 2000
<abstract>
-This is a tutorial on how to use GTK (the GIMP Toolkit) through its C
+This is a tutorial on how to use GTK (the GTK+ Toolkit) through its C
interface.
</abstract>
<sect>Introduction
<!-- ***************************************************************** -->
<p>
-GTK (GIMP Toolkit) is a library for creating graphical user
+GTK (GTK+ Toolkit) is a library for creating graphical user
interfaces. It is licensed using the LGPL license, so you can develop
open software, free software, or even commercial non-free software
using GTK without having to spend anything for licenses or royalties.
It's called the GIMP toolkit because it was originally written for
-developing the General Image Manipulation Program (GIMP), but GTK has
+developing the GNU Image Manipulation Program (GIMP), but GTK has
now been used in a large number of software projects, including the
GNU Network Object Model Environment (GNOME) project. GTK is built on
-top of GDK (GIMP Drawing Kit) which is basically a wrapper around the
+top of GDK (GTK+ Drawing Kit) which is basically a wrapper around the
low-level functions for accessing the underlying windowing functions
-(Xlib in the case of X windows). The primary authors of GTK are:
+(Xlib in the case of the X windows system). The primary authors of GTK
+are:
<itemize>
<item> Peter Mattis <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
using the idea of classes and callback functions (pointers to
functions).
-There is also a third component called glib which contains a few
+There is also a third component called GLib which contains a few
replacements for some standard calls, as well as some additional
-functions for handling linked lists etc. The replacement functions are
-used to increase GTK's portability, as some of the functions
+functions for handling linked lists, etc. The replacement functions
+are used to increase GTK's portability, as some of the functions
implemented here are not available or are nonstandard on other unixes
such as g_strerror(). Some also contain enhancements to the libc
versions, such as g_malloc that has enhanced debugging utilities.
benefit for the reader to have previous X programming experience, but
it shouldn't be necessary. If you are learning GTK as your first
widget set, please comment on how you found this tutorial, and what
-you had trouble with. Note that there is also a C++ API for GTK
-(GTK--) in the works, so if you prefer to use C++, you should look
-into this instead. There are also Objective C, ADA, Guile and other
-language bindings available, but I don't follow these.
+you had trouble with. There are also C++, Objective C, ADA, Guile and
+other language bindings available, but I don't follow these.
-This document is a 'work in progress'. Please look for updates on
-http://www.gtk.org/ <htmlurl url="http://www.gtk.org/"
-name="http://www.gtk.org/">.
+This document is a "work in progress". Please look for updates on
+<htmlurl url="http://www.gtk.org/" name="http://www.gtk.org/">.
I would very much like to hear of any problems you have learning GTK
from this document, and would appreciate input as to how it may be
<!-- ***************************************************************** -->
<p>
-The first thing to do of course, is download the GTK source and
+The first thing to do, of course, is download the GTK source and
install it. You can always get the latest version from ftp.gtk.org in
/pub/gtk. You can also view other sources of GTK information on
-http://www.gtk.org/ <htmlurl url="http://www.gtk.org/"
-name="http://www.gtk.org/">. GTK uses GNU autoconf for configuration.
-Once untar'd, type ./configure --help to see a list of options.
+<htmlurl url="http://www.gtk.org/" name="http://www.gtk.org/">. GTK
+uses GNU autoconf for configuration. Once untar'd, type ./configure
+--help to see a list of options.
-Th GTK source distribution also contains the complete source to all of
-the examples used in this tutorial, along with Makefiles to aid
+The GTK source distribution also contains the complete source to all
+of the examples used in this tutorial, along with Makefiles to aid
compilation.
To begin our introduction to GTK, we'll start with the simplest
program possible. This program will create a 200x200 pixel window and
-has no way of exiting except to be killed using the shell.
+has no way of exiting except to be killed by using the shell.
<tscreen><verb>
/* example-start base base.c */
gcc base.c -o base `gtk-config --cflags --libs`
</verb></tscreen>
-The meaning of the unusual compilation options is explained below.
+The meaning of the unusual compilation options is explained below in
+<ref id="sec_compiling" name="Compiling Hello World">.
All programs will of course include gtk/gtk.h which declares the
-variables, functions, structures etc. that will be used in your GTK
+variables, functions, structures, etc. that will be used in your GTK
application.
The next line:
gtk_widget_show (window);
</verb></tscreen>
-The GTK_WINDOW_TOPLEVEL argument specifies that we want the window to
-undergo window manager decoration and placement. Rather than create a
-window of 0x0 size, a window without children is set to 200x200 by
-default so you can still manipulate it.
+The <tt/GTK_WINDOW_TOPLEVEL/ argument specifies that we want the
+window to undergo window manager decoration and placement. Rather than
+create a window of 0x0 size, a window without children is set to
+200x200 by default so you can still manipulate it.
The gtk_widget_show() function lets GTK know that we are done setting
the attributes of this widget, and that it can display it.
gtk_main() is another call you will see in every GTK application.
When control reaches this point, GTK will sleep waiting for X events
(such as button or key presses), timeouts, or file IO notifications to
-occur. In our simple example however, events are ignored.
+occur. In our simple example, however, events are ignored.
<!-- ----------------------------------------------------------------- -->
<sect1>Hello World in GTK
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
/* When the window is given the "delete_event" signal (this is given
- * by the window manager, usually by the 'close' option, or on the
+ * by the window manager, usually by the "close" option, or on the
* titlebar), we ask it to call the delete_event () function
* as defined above. The data passed to the callback
* function is NULL and is ignored in the callback function. */
/* Here we connect the "destroy" event to a signal handler.
* This event occurs when we call gtk_widget_destroy() on the window,
- * or if we return 'FALSE' in the "delete_event" callback. */
+ * or if we return FALSE in the "delete_event" callback. */
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC (destroy), NULL);
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
-<sect1>Compiling Hello World
+<sect1>Compiling Hello World <label id="sec_compiling">
<p>
To compile use:
`gtk-config --libs`
</verb></tscreen>
-This uses the program <tt>gtk-config</>, which comes with gtk. This
-program 'knows' what compiler switches are needed to compile programs
-that use gtk. <tt>gtk-config --cflags</> will output a list of include
+This uses the program <tt/gtk-config/, which comes with GTK. This
+program "knows" what compiler switches are needed to compile programs
+that use GTK. <tt/gtk-config --cflags/ will output a list of include
directories for the compiler to look in, and <tt>gtk-config --libs</>
will output the list of libraries for the compiler to link with and
-the directories to find them in. In the aboce example they could have
+the directories to find them in. In the above example they could have
been combined into a single instance, such as
-`gtk-config --cflags --libs`.
+<tt/`gtk-config --cflags --libs`/.
Note that the type of single quote used in the compile command above
is significant.
<item>The GDK library (-lgdk), the Xlib wrapper.
<item>The gmodule library (-lgmodule), which is used to load run time
extensions.
-<item>The glib library (-lglib), containing miscellaneous functions, only
-g_print() is used in this particular example. GTK is built on top
-of glib so you will always require this library. See the section on
-<ref id="sec_glib" name="glib"> for details.
+<item>The GLib library (-lglib), containing miscellaneous functions;
+only g_print() is used in this particular example. GTK is built on top
+of glib so you will always require this library. See the section on
+<ref id="sec_glib" name="GLib"> for details.
<item>The Xlib library (-lX11) which is used by GDK.
<item>The Xext library (-lXext). This contains code for shared memory
pixmaps and other X extensions.
sleep in gtk_main until an event occurs and control is passed to the
appropriate function.
-This passing of control is done using the idea of "signals". When an
-event occurs, such as the press of a mouse button, the appropriate
-signal will be "emitted" by the widget that was pressed. This is how
-GTK does most of its useful work. There are a set of signals that all
-widgets inherit, such as "destroy", and there are signals that are
-widget specific, such as "toggled" on a toggle button.
+This passing of control is done using the idea of "signals". (Note
+that these signals are not the same as the Unix system signals, and
+are not implemented using them, although the terminology is almost
+identical.) When an event occurs, such as the press of a mouse button,
+the appropriate signal will be "emitted" by the widget that was
+pressed. This is how GTK does most of its useful work. There are
+signals that all widgets inherit, such as "destroy", and there are
+signals that are widget specific, such as "toggled" on a toggle
+button.
To make a button perform an action, we set up a signal handler to
catch these signals and call the appropriate function. This is done by
gpointer func_data );
</verb></tscreen>
-Where the first argument is the widget which will be emitting the
-signal, and the second, the name of the signal you wish to catch. The
+where the first argument is the widget which will be emitting the
+signal, and the second the name of the signal you wish to catch. The
third is the function you wish to be called when it is caught, and the
fourth, the data you wish to have passed to this function.
The function specified in the third argument is called a "callback
-function", and should generally be of the form:
+function", and should generally be of the form
<tscreen><verb>
void callback_func( GtkWidget *widget,
gpointer callback_data );
</verb></tscreen>
-Where the first argument will be a pointer to the widget that emitted
-the signal, and the second, a pointer to the data given as the last
+where the first argument will be a pointer to the widget that emitted
+the signal, and the second a pointer to the data given as the last
argument to the gtk_signal_connect() function as shown above.
Note that the above form for a signal callback function declaration is
only a general guide, as some widget specific signals generate
-different calling parameters. For example, the GtkCList "select_row"
+different calling parameters. For example, the CList "select_row"
signal provides both row and column parameters.
Another call used in the <em>helloworld</em> example, is:
gtk_signal_connect_object() is the same as gtk_signal_connect() except
that the callback function only uses one argument, a pointer to a GTK
object. So when using this function to connect signals, the callback
-should be of the form:
+should be of the form
<tscreen><verb>
void callback_func( GtkObject *object );
</verb></tscreen>
-Where the object is usually a widget. We usually don't setup callbacks
+where the object is usually a widget. We usually don't setup callbacks
for gtk_signal_connect_object however. They are usually used to call a
GTK function that accepts a single widget or object as an argument, as
is the case in our <em>helloworld</em> example.
<!-- ----------------------------------------------------------------- -->
<sect1>Events
<p>
-In addition to the signal mechanism described above, there are a set
+In addition to the signal mechanism described above, there is a set
of <em>events</em> that reflect the X event mechanism. Callbacks may
also be attached to these events. These events are:
<tscreen><verb>
gtk_signal_connect( GTK_OBJECT(button), "button_press_event",
GTK_SIGNAL_FUNC(button_press_callback),
- NULL);
+ NULL);
</verb></tscreen>
-This assumes that <tt/button/ is a GtkButton widget. Now, when the
+This assumes that <tt/button/ is a Button widget. Now, when the
mouse is over the button and a mouse button is pressed, the function
<tt/button_press_callback/ will be called. This function may be
declared as:
<tscreen><verb>
-static gint button_press_event (GtkWidget *widget,
- GdkEventButton *event,
- gpointer data);
+static gint button_press_callback( GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data );
</verb></tscreen>
Note that we can declare the second argument as type
<!-- ----------------------------------------------------------------- -->
<sect1>Stepping Through Hello World
<p>
-Now that we know the theory behind this, lets clarify by walking through
-the example <em>helloworld</em> program.
+Now that we know the theory behind this, let's clarify by walking
+through the example <em>helloworld</em> program.
Here is the callback function that will be called when the button is
"clicked". We ignore both the widget and the data in this example, but
The value you return in this callback lets GTK know what action to
take. By returning TRUE, we let it know that we don't want to have
the "destroy" signal emitted, keeping our application running. By
-returning FALSE, we ask that "destroy" is emitted, which in turn will
+returning FALSE, we ask that "destroy" be emitted, which in turn will
call our "destroy" signal handler.
<tscreen><verb>
{
</verb></tscreen>
-This next part, declares a pointer to a structure of type
+This next part declares pointers to a structure of type
GtkWidget. These are used below to create a window and a button.
<tscreen><verb>
gtk_init (&argc, &argv);
</verb></tscreen>
-Create a new window. This is fairly straight forward. Memory is
+Create a new window. This is fairly straightforward. Memory is
allocated for the GtkWidget *window structure so it now points to a
valid structure. It sets up a new window, but it is not displayed
until we call gtk_widget_show(window) near the end of our program.
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
</verb></tscreen>
-Here is an example of connecting a signal handler to an object, in
-this case, the window. Here, the "destroy" signal is caught. This is
-emitted when we use the window manager to kill the window (and we
-return FALSE in the "delete_event" handler), or when we use the
-gtk_widget_destroy() call passing in the window widget as the object
-to destroy. By setting this up, we handle both cases with a single
-call. Here, it just calls the destroy() function defined above with a
-NULL argument, which quits GTK for us.
-
-The GTK_OBJECT and GTK_SIGNAL_FUNC are macros that perform type
-casting and checking for us, as well as aid the readability of the
-code.
+Here are two examples of connecting a signal handler to an object, in
+this case, the window. Here, the "delete_event" and "destroy" signals
+are caught. The first is emitted when we use the window manager to
+kill the window, or when we use the gtk_widget_destroy() call passing
+in the window widget as the object to destroy. The second is emitted
+when, in the "delete_event" handler, we return FALSE.
+
+The <tt/GTK_OBJECT/ and <tt/GTK_SIGNAL_FUNC/ are macros that perform
+type casting and checking for us, as well as aid the readability of
+the code.
<tscreen><verb>
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ GTK_SIGNAL_FUNC (delete_event), NULL);
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC (destroy), NULL);
</verb></tscreen>
functions which we will look at in the section on
<ref id="sec_setting_widget_attributes" name="Setting Widget Attributes">
-And again, GTK_CONTAINER is a macro to perform type casting.
+And again, <tt/GTK_CONTAINER/ is a macro to perform type casting.
<tscreen><verb>
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
GTK_OBJECT (window));
</verb></tscreen>
-This is a packing call, which will be explained in depth later on. But
-it is fairly easy to understand. It simply tells GTK that the button
-is to be placed in the window where it will be displayed. Note that a
-GTK container can only contain one widget. There are other widgets,
-that are described later, which are designed to layout multiple
-widgets in various ways.
+This is a packing call, which will be explained in depth later on in
+<ref id="sec_packing_widgets" name="Packing Widgets">. But it is
+fairly easy to understand. It simply tells GTK that the button is to
+be placed in the window where it will be displayed. Note that a GTK
+container can only contain one widget. There are other widgets, that
+are described later, which are designed to layout multiple widgets in
+various ways.
<tscreen><verb>
gtk_container_add (GTK_CONTAINER (window), button);
And the final return. Control returns here after gtk_quit() is called.
<tscreen><verb>
- return 0;
+ return (0);
</verb></tscreen>
Now, when we click the mouse button on a GTK button, the widget emits
to emit the "destroy" signal, which is caught, and calls our destroy()
callback function, which simply exits GTK.
-Another course of events, is to use the window manager to kill the
-window. This will cause the "delete_event" to be emitted. This will
+Another course of events is to use the window manager to kill the
+window, which will cause the "delete_event" to be emitted. This will
call our "delete_event" handler. If we return TRUE here, the window
will be left as is and nothing will happen. Returning FALSE will cause
-GTK to emit the "destroy" signal which of course, calls the "destroy"
+GTK to emit the "destroy" signal which of course calls the "destroy"
callback, exiting GTK.
-Note that these signals are not the same as the Unix system signals,
-and are not implemented using them, although the terminology is almost
-identical.
-
<!-- ***************************************************************** -->
<sect>Moving On
<!-- ***************************************************************** -->
<sect1>Data Types
<p>
There are a few things you probably noticed in the previous examples
-that need explaining. The gint, gchar etc. that you see are typedefs
-to int and char respectively. This is done to get around that nasty
-dependency on the size of simple data types when doing calculations.
+that need explaining. The gint, gchar, etc. that you see are typedefs
+to int and char, respectively, that are part of the GLlib system. This
+is done to get around that nasty dependency on the size of simple data
+types when doing calculations.
A good example is "gint32" which will be typedef'd to a 32 bit integer
for any given platform, whether it be the 64 bit alpha, or the 32 bit
-i386. The typedefs are very straight forward and intuitive. They are
+i386. The typedefs are very straightforward and intuitive. They are
all defined in glib/glib.h (which gets included from gtk.h).
-You'll also notice the ability to use GtkWidget when the function
-calls for a GtkObject. GTK is an object oriented design, and a widget
+You'll also notice GTK's ability to use GtkWidget when the function
+calls for an Object. GTK is an object oriented design, and a widget
is an object.
<!-- ----------------------------------------------------------------- -->
the tag returned by one of the signal_connect functions, you can
disconnect a signal handler.
-Another function to remove all the signal handers from an object is:
+You can also temporarily disable signal handlers with the
+gtk_signal_handler_block() and gtk_signal_handler_unblock() family of
+functions.
<tscreen><verb>
-void gtk_signal_handlers_destroy( GtkObject *object );
-</verb></tscreen>
+void gtk_signal_handler_block( GtkObject *object,
+ guint handler_id );
-This call is fairly self explanatory. It simply removes all the
-current signal handlers from the object passed in as the first
-argument.
+void gtk_signal_handler_block_by_func( GtkObject *object,
+ GtkSignalFunc func,
+ gpointer data );
+
+void gtk_signal_handler_block_by_data( GtkObject *object,
+ gpointer data );
+
+void gtk_signal_handler_unblock( GtkObject *object,
+ guint handler_id );
+
+void gtk_signal_handler_unblock_by_func( GtkObject *object,
+ GtkSignalFunc func,
+ gpointer data );
+
+void gtk_signal_handler_unblock_by_data( GtkObject *object,
+ gpointer data);
+</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
<sect1>An Upgraded Hello World
}
/* another callback */
-void delete_event( GtkWidget *widget,
+gint delete_event( GtkWidget *widget,
GdkEvent *event,
- gpointer data )
+ gpointer data )
{
- gtk_main_quit ();
+ gtk_main_quit();
+ return(FALSE);
}
int main( int argc,
/* Create a new window */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- /* This is a new call, this just sets the title of our
+ /* This is a new call, which just sets the title of our
* new window to "Hello Buttons!" */
gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
resizing the window, and observe the behavior.
Just as a side note, there is another useful define for
-gtk_window_new() - GTK_WINDOW_DIALOG. This interacts with the window
-manager a little differently and should be used for transient windows.
+gtk_window_new() - <tt/GTK_WINDOW_DIALOG/. This interacts with the
+window manager a little differently and should be used for transient
+windows.
<!-- ***************************************************************** -->
-<sect>Packing Widgets
+<sect>Packing Widgets <label id="sec_packing_widgets">
<!-- ***************************************************************** -->
<p>
When creating an application, you'll want to put more than one widget
boxes to create the desired effect.
To create a new horizontal box, we use a call to gtk_hbox_new(), and
-for vertical boxes, gtk_vbox_new().The gtk_box_pack_start() and
+for vertical boxes, gtk_vbox_new(). The gtk_box_pack_start() and
gtk_box_pack_end() functions are used to place objects inside of these
containers. The gtk_box_pack_start() function will start at the top
and work its way down in a vbox, and pack left to right in an hbox.
gtk_box_pack_end() will do the opposite, packing from bottom to top in
-a vbox, and right to left in an hbox. Using these functions allow us
+a vbox, and right to left in an hbox. Using these functions allows us
to right justify or left justify our widgets and may be mixed in any
way to achieve the desired effect. We will use gtk_box_pack_start() in
most of our examples. An object may be another container or a
including the button, but we usually only use a label inside a button.
By using these calls, GTK knows where you want to place your widgets
-so it can do automatic resizing and other nifty things. There's also a
-number of options as to how your widgets should be packed. As you can
-imagine, this method gives us a quite a bit of flexibility when
+so it can do automatic resizing and other nifty things. There are also
+a number of options as to how your widgets should be packed. As you
+can imagine, this method gives us a quite a bit of flexibility when
placing and creating widgets.
<!-- ----------------------------------------------------------------- -->
<p>
Because of this flexibility, packing boxes in GTK can be confusing at
first. There are a lot of options, and it's not immediately obvious how
-they all fit together. In the end however, there are basically five
+they all fit together. In the end, however, there are basically five
different styles.
<? <CENTER> >
Each line contains one horizontal box (hbox) with several buttons. The
call to gtk_box_pack is shorthand for the call to pack each of the
buttons into the hbox. Each of the buttons is packed into the hbox the
-same way (i.e. same arguments to the gtk_box_pack_start() function).
+same way (i.e., same arguments to the gtk_box_pack_start() function).
This is the declaration of the gtk_box_pack_start function.
The expand argument to gtk_box_pack_start() and gtk_box_pack_end()
controls whether the widgets are laid out in the box to fill in all
the extra space in the box so the box is expanded to fill the area
-alloted to it (TRUE). Or the box is shrunk to just fit the widgets
+allotted to it (TRUE); or the box is shrunk to just fit the widgets
(FALSE). Setting expand to FALSE will allow you to do right and left
justification of your widgets. Otherwise, they will all expand to fit
into the box, and the same effect could be achieved by using only one
The homogeneous argument to gtk_hbox_new (and the same for
gtk_vbox_new) controls whether each object in the box has the same
-size (i.e. the same width in an hbox, or the same height in a
-vbox). If it is set, the expand argument to the gtk_box_pack routines
-is always turned on.
+size (i.e., the same width in an hbox, or the same height in a
+vbox). If it is set, the gtk_box_pack routines function essentially
+as if the <tt/expand/ argument was always turned on.
What's the difference between spacing (set when the box is created)
and padding (set when elements are packed)? Spacing is added between
<? </CENTER> >
Here is the code used to create the above images. I've commented it
-fairly heavily so hopefully you won't have any problems following
+fairly heavily so I hope you won't have any problems following
it. Compile it yourself and play with it.
<!-- ----------------------------------------------------------------- -->
/* example-start packbox packbox.c */
#include <stdio.h>
+#include <stdlib.h>
#include "gtk/gtk.h"
-void delete_event( GtkWidget *widget,
+gint delete_event( GtkWidget *widget,
GdkEvent *event,
- gpointer data )
+ gpointer data )
{
- gtk_main_quit ();
+ gtk_main_quit();
+ return(FALSE);
}
/* Make a new hbox filled with button-labels. Arguments for the
/* Create our window */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- /* You should always remember to connect the destroy signal to the
- * main window. This is very important for proper intuitive
+ /* You should always remember to connect the delete_event signal
+ * to the main window. This is very important for proper intuitive
* behavior */
gtk_signal_connect (GTK_OBJECT (window), "delete_event",
GTK_SIGNAL_FUNC (delete_event), NULL);
gtk_widget_show (box2);
/* Call our make box function - homogeneous = FALSE, spacing = 0,
- * expand = FALSE, fill = FALSE, padding = 0 */
+ * expand = TRUE, fill = FALSE, padding = 0 */
box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
gtk_widget_show (box2);
* but they are quite simple. */
separator = gtk_hseparator_new ();
- /* Cack the separator into the vbox. Remember each of these
- * widgets are being packed into a vbox, so they'll be stacked
+ /* Pack the separator into the vbox. Remember each of these
+ * widgets is being packed into a vbox, so they'll be stacked
* vertically. */
gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
gtk_widget_show (separator);
/* Our quit button. */
button = gtk_button_new_with_label ("Quit");
- /* Setup the signal to destroy the window. Remember that this will send
- * the "destroy" signal to the window which will be caught by our signal
- * handler as defined above. */
+ /* Setup the signal to terminate the program when the button is clicked */
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (gtk_main_quit),
GTK_OBJECT (window));
Using tables, we create a grid that we can place widgets in. The
widgets may take up as many spaces as we specify.
-The first thing to look at of course, is the gtk_table_new function:
+The first thing to look at, of course, is the gtk_table_new function:
<tscreen><verb>
GtkWidget *gtk_table_new( gint rows,
gint ypadding );
</verb></tscreen>
-Where the first argument ("table") is the table you've created and the
+The first argument ("table") is the table you've created and the
second ("child") the widget you wish to place in the table.
The left and right attach arguments specify where to place the widget,
These options are:
<itemize>
-<item>GTK_FILL - If the table box is larger than the widget, and
-GTK_FILL is specified, the widget will expand to use all the room
+<item><tt/GTK_FILL/ - If the table box is larger than the widget, and
+<tt/GTK_FILL/ is specified, the widget will expand to use all the room
available.
-<item>GTK_SHRINK - If the table widget was allocated less space then
-was requested (usually by the user resizing the window), then the
+<item><tt/GTK_SHRINK/ - If the table widget was allocated less space
+then was requested (usually by the user resizing the window), then the
widgets would normally just be pushed off the bottom of the window and
-disappear. If GTK_SHRINK is specified, the widgets will shrink with
-the table.
+disappear. If <tt/GTK_SHRINK/ is specified, the widgets will shrink
+with the table.
-<item>GTK_EXPAND - This will cause the table to expand to use up any
-remaining space in the window.
+<item><tt/GTK_EXPAND/ - This will cause the table to expand to use up
+any remaining space in the window.
</itemize>
Padding is just like in boxes, creating a clear area around the widget
gint bottom_attach );
</verb></tscreen>
-The X and Y options default to GTK_FILL | GTK_EXPAND, and X and Y
+The X and Y options default to <tt/GTK_FILL | GTK_EXPAND/, and X and Y
padding are set to 0. The rest of the arguments are identical to the
previous function.
We also have gtk_table_set_row_spacing() and
-gtk_table_set_col_spacing(). This places spacing between the rows at
+gtk_table_set_col_spacing(). These places spacing between the rows at
the specified row or column.
<tscreen><verb>
}
/* This callback quits the program */
-void delete_event( GtkWidget *widget,
+gint delete_event( GtkWidget *widget,
GdkEvent *event,
- gpointer data )
+ gpointer data )
{
gtk_main_quit ();
+ return(FALSE);
}
int main( int argc,
<!-- ----------------------------------------------------------------- -->
<sect1> Casting
<p>
-You'll notice as you go on, that GTK uses a type casting system. This
+You'll notice as you go on that GTK uses a type casting system. This
is always done using macros that both test the ability to cast the
given item, and perform the cast. Some common ones you will see are:
-<itemize>
-<item> GTK_WIDGET(widget)
-<item> GTK_OBJECT(object)
-<item> GTK_SIGNAL_FUNC(function)
-<item> GTK_CONTAINER(container)
-<item> GTK_WINDOW(window)
-<item> GTK_BOX(box)
-</itemize>
+<tscreen><verb>
+ GTK_WIDGET(widget)
+ GTK_OBJECT(object)
+ GTK_SIGNAL_FUNC(function)
+ GTK_CONTAINER(container)
+ GTK_WINDOW(window)
+ GTK_BOX(box)
+</verb></tscreen>
These are all used to cast arguments in functions. You'll see them in the
examples, and can usually tell when to use them simply by looking at the
function's declaration.
As you can see below in the class hierarchy, all GtkWidgets are
-derived from the GtkObject base class. This means you can use a widget
+derived from the Object base class. This means you can use a widget
in any place the function asks for an object - simply use the
-GTK_OBJECT() macro.
+<tt/GTK_OBJECT()/ macro.
For example:
function pointer to the callback.
Many widgets are also containers. If you look in the class hierarchy
-below, you'll notice that many widgets derive from the GtkContainer
-class. Any one of these widgets may be used with the GTK_CONTAINER
-macro to pass them to functions that ask for containers.
+below, you'll notice that many widgets derive from the Container
+class. Any one of these widgets may be used with the
+<tt/GTK_CONTAINER/ macro to pass them to functions that ask for
+containers.
Unfortunately, these macros are not extensively covered in the
tutorial, but I recommend taking a look through the GTK header
<sect1>Widgets Without Windows
<p>
The following widgets do not have an associated window. If you want to
-capture events, you'll have to use the GtkEventBox. See the section on
+capture events, you'll have to use the EventBox. See the section on
the <ref id="sec_EventBox" name="EventBox"> widget.
<tscreen><verb>
gtk_signal_connect (GTK_OBJECT (window), "delete_event",
GTK_SIGNAL_FUNC (gtk_exit), NULL);
-
/* Sets the border width of the window. */
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
gtk_widget_realize(window);
The xpm_label_box function could be used to pack xpm's and labels into
any widget that can be a container.
+Notice in <tt/xpm_label_box/ how there is a call to
+<tt/gtk_widget_get_style/. Every widget has a "style", consisting of
+foreground and background colors for a variety of situations, font
+selection, and other graphics data relevant to a widget. These style
+values are defaulted in each widget, and are required by many GDK
+function calls, such as <tt/gdk_pixmap_create_from_xpm/, which here is
+given the "normal" background color. The style data of widgets may
+be customized, using <ref id="sec_gtkrc_files" name="GTK's rc files">.
+
+Also notice the call to <tt/gtk_widget_realize/ after setting the
+window's border width. This function uses GDK to create the X
+windows related to the widget. The function is automatically called
+when you invoke <tt/gtk_widget_show/ for a widget, and so has not been
+shown in earlier examples. But the call to
+<tt/gdk_pixmap_create_from_xpm/ requires that its <tt/window/ argument
+refer to a real X window, so it is necessary to realize the widget
+before this GDK call.
+
The Button widget has the following signals:
<itemize>
-<item> pressed
-<item> released
-<item> clicked
-<item> enter
-<item> leave
+<item><tt/pressed/ - emitted when pointer button is pressed within
+Button widget
+<item><tt/released/ - emitted when pointer button is released within
+Button widget
+<item><tt/clicked/ - emitted when pointer button is pressed and then
+released within Button widget
+<item><tt/enter/ - emitted when pointer enters Button widget
+<item><tt/leave/ - emitted when pointer leaves Button widget
</itemize>
<!-- ----------------------------------------------------------------- -->
button with a label widget already packed into it.
To retrieve the state of the toggle widget, including radio and check
-buttons, we use a GTK macro as shown in our example below. This tests
-the state of the toggle in a callback. The signal of interest emitted
-to us by toggle buttons (the toggle button, check button, and radio
-button widgets), is the "toggled" signal. To check the state of these
-buttons, set up a signal handler to catch the toggled signal, and use
-the macro to determine its state. The callback will look something
-like:
+buttons, we use a construct as shown in our example below. This tests
+the state of the toggle, by accessing the <tt/active/ field of the
+toggle widget's structure, after first using the
+<tt/GTK_TOGGLE_BUTTON/ macro to cast the widget pointer into a toggle
+widget pointer. The signal of interest to us emitted by toggle
+buttons (the toggle button, check button, and radio button widgets) is
+the "toggled" signal. To check the state of these buttons, set up a
+signal handler to catch the toggled signal, and access the structure
+to determine its state. The callback will look something like:
<tscreen><verb>
void toggle_button_callback (GtkWidget *widget, gpointer data)
}
</verb></tscreen>
+To force the state of a toggle button, and its children, the radio and
+check buttons, use this function:
+
<tscreen><verb>
void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
gint state );
<!-- ----------------------------------------------------------------- -->
<sect1> Check Buttons
<p>
-Check buttons inherent many properties and functions from the the
+Check buttons inherit many properties and functions from the the
toggle buttons above, but look a little different. Rather than being
buttons with text inside them, they are small squares with the text to
the right of them. These are often used for toggling options on and
The important thing to remember is that gtk_radio_button_group must be
called for each new button added to the group, with the previous
button passed in as an argument. The result is then passed into the
-call to gtk_radio_button_new or gtk_radio_button_new_with_label. This
-allows a chain of buttons to be established. The example below should
-make this clear.
+next call to gtk_radio_button_new or
+gtk_radio_button_new_with_label. This allows a chain of buttons to be
+established. The example below should make this clear.
You can shorten this slightly by using the following syntax, which
removes the need for a variable to hold the list of buttons. This form
</verb></tscreen>
This is described in the section on toggle buttons, and works in
-exactly the same way.
+exactly the same way. Once the radio buttons are grouped together,
+only one of the group may be active at a time. If the user clicks on
+one radio button, and then on another, the first radio button will
+first emit a "toggled" signal (to report becoming inactive), and then
+the second will emit its "toggled" signal (to report becoming active).
The following example creates a radio button group with three buttons.
#include <gtk/gtk.h>
#include <glib.h>
-void close_application( GtkWidget *widget,
+gint close_application( GtkWidget *widget,
GdkEvent *event,
- gpointer data )
+ gpointer data )
{
gtk_main_quit();
+ return(FALSE);
}
int main( int argc,
<sect> Adjustments <label id="sec_Adjustment">
<!-- ***************************************************************** -->
<p>
-GTK+ has various widgets that can be visually adjusted by the user
+GTK has various widgets that can be visually adjusted by the user
using the mouse or the keyboard, such as the range widgets, described
in the <ref id="sec_Range_Widgets" name="Range Widgets">
section. There are also a few widgets that display some adjustable
widget's signal and the "input" of another's adjustment setting
function.
-GTK+ solves this problem using the GtkAdjustment object, which is a
-way for widgets to store and pass adjustment information in an
-abstract and flexible form. The most obvious use of GtkAdjustment is
-to store the configuration parameters and values of range widgets,
-such as scrollbars and scale controls. However, since GtkAdjustments
-are derived from GtkObject, they have some special powers beyond those
-of normal data structures. Most importantly, they can emit signals,
-just like widgets, and these signals can be used not only to allow
-your program to react to user input on adjustable widgets, but also to
+GTK solves this problem using the Adjustment object, which is not a
+widget but a way for widgets to store and pass adjustment information
+in an abstract and flexible form. The most obvious use of Adjustment
+is to store the configuration parameters and values of range widgets,
+such as scrollbars and scale controls. However, since Adjustments are
+derived from Object, they have some special powers beyond those of
+normal data structures. Most importantly, they can emit signals, just
+like widgets, and these signals can be used not only to allow your
+program to react to user input on adjustable widgets, but also to
propagate adjustment values transparently between adjustable widgets.
+You will see how adjustments fit in when you see the other widgets
+that incorporate them:
+<ref id="sec_ProgressBar" name="Progress Bars">,
+<ref id="sec_Viewports" name="Viewports">,
+<ref id="sec_ScrolledWindow" name="Scrolled Windows">, and others.
+
<sect1> Creating an Adjustment
<p>
-You create an adjustment using:
+Many of the widgets which use adjustment objects do so automatically,
+but some cases will be shown in later examples where you may need to
+create one yourself. You create an adjustment using:
<tscreen><verb>
GtkObject *gtk_adjustment_new( gfloat value,
</verb></tscreen>
The first thing you should know is that there aren't any handy-dandy
-macros or accessor functions for getting the <tt/value/ out of a
-GtkAdjustment, so you'll have to (horror of horrors) do it like a
+macros or accessor functions for getting the <tt/value/ out of an
+Adjustment, so you'll have to (horror of horrors) do it like a
<em/real/ C programmer. Don't worry - the <tt>GTK_ADJUSTMENT
-(Object)</tt> macro does run-time type checking (as do all the GTK+
+(Object)</tt> macro does run-time type checking (as do all the GTK
type-casting macros, actually).
Since, when you set the <tt/value/ of an adjustment, you generally
want the change to be reflected by every widget that uses this
-adjustment, GTK+ provides this convenience function to do this:
+adjustment, GTK provides this convenience function to do this:
<tscreen><verb>
void gtk_adjustment_set_value( GtkAdjustment *adjustment,
gfloat value );
</verb></tscreen>
-As mentioned earlier, GtkAdjustment is a subclass of GtkObject just
+As mentioned earlier, Adjustment is a subclass of Object just
like all the various widgets, and thus it is able to emit signals.
This is, of course, why updates happen automagically when you share an
adjustment object between a scrollbar and another adjustable widget;
void (* value_changed) (GtkAdjustment *adjustment);
</verb></tscreen>
-The various widgets that use the GtkAdjustment object will emit this
+The various widgets that use the Adjustment object will emit this
signal on an adjustment whenever they change its value. This happens
both when user input causes the slider to move on a range widget, as
well as when the program explicitly changes the value with
You probably won't ever need to attach a handler to this signal,
unless you're writing a new type of range widget. However, if you
-change any of the values in a GtkAdjustment directly, you should emit
+change any of the values in a Adjustment directly, you should emit
this signal on it to reconfigure whatever widgets are using it, like
this:
and that's about it (if you don't believe me, look in the header
files!). The <tt/adjustment/ argument can either be a pointer to an
-existing GtkAdjustment, or NULL, in which case one will be created for
+existing Adjustment, or NULL, in which case one will be created for
you. Specifying NULL might actually be useful in this case, if you
wish to pass the newly-created adjustment to the constructor function
of some other widget which will configure it for you, such as a text
Scale widgets are used to allow the user to visually select and
manipulate a value within a specific range. You might want to use a
scale widget, for example, to adjust the magnification level on a
-zoomed preview of a picture, or to control the brightness of a colour,
+zoomed preview of a picture, or to control the brightness of a color,
or to specify the number of minutes of inactivity before a screensaver
takes over the screen.
<p>
As with scrollbars, there are separate widget types for horizontal and
vertical scale widgets. (Most programmers seem to favour horizontal
-scale widgets). Since they work essentially the same way, there's no
+scale widgets.) Since they work essentially the same way, there's no
need to treat them separately here. The following functions, defined
in <tt><gtk/gtkvscale.h></tt> and
<tt><gtk/gtkhscale.h></tt>, create vertical and horizontal scale
The <tt/adjustment/ argument can either be an adjustment which has
already been created with <tt/gtk_adjustment_new()/, or <tt/NULL/, in
-which case, an anonymous GtkAdjustment is created with all of its
+which case, an anonymous Adjustment is created with all of its
values set to <tt/0.0/ (which isn't very useful in this case). In
order to avoid confusing yourself, you probably want to create your
adjustment with a <tt/page_size/ of <tt/0.0/ so that its <tt/upper/
value actually corresponds to the highest value the user can select.
(If you're <em/already/ thoroughly confused, read the section on <ref
id="sec_Adjustment" name="Adjustments"> again for an explanation of
-what exactly adjustments do and how to create and manipulate them).
+what exactly adjustments do and how to create and manipulate them.)
<!-- ----------------------------------------------------------------- -->
<sect2> Functions and Signals (well, functions, at least)
defined in <tt><gtk/gtkenums.h></tt>, and can take one of the
following values:
-<itemize>
-<item> GTK_POS_LEFT
-<item> GTK_POS_RIGHT
-<item> GTK_POS_TOP
-<item> GTK_POS_BOTTOM
-</itemize>
+<tscreen><verb>
+ GTK_POS_LEFT
+ GTK_POS_RIGHT
+ GTK_POS_TOP
+ GTK_POS_BOTTOM
+</verb></tscreen>
-If you position the value on the "side" of the trough (e.g. on the top
-or bottom of a horizontal scale widget), then it will follow the
+If you position the value on the "side" of the trough (e.g., on the
+top or bottom of a horizontal scale widget), then it will follow the
slider up and down the trough.
All the preceding functions are defined in
-<tt><gtk/gtkscale.h></tt>.
+<tt><gtk/gtkscale.h></tt>. The header files for all GTK widgets
+are automatically included when you include
+<tt><gtk/gtk.h></tt>. But you should look over the header files
+of all widgets that interest you,
+
</sect2>
</sect1>
<!-- ----------------------------------------------------------------- -->
-<sect1> Common Functions <label id="sec_Range_Functions">
+<sect1> Common Range Functions <label id="sec_Range_Functions">
<p>
-The GtkRange widget class is fairly complicated internally, but, like
+The Range widget class is fairly complicated internally, but, like
all the "base class" widgets, most of its complexity is only
interesting if you want to hack on it. Also, almost all of the
functions and signals it defines are only really used in writing
<p>
The "update policy" of a range widget defines at what points during
user interaction it will change the <tt/value/ field of its
-GtkAdjustment and emit the "value_changed" signal on this
-GtkAdjustment. The update policies, defined in
+Adjustment and emit the "value_changed" signal on this
+Adjustment. The update policies, defined in
<tt><gtk/gtkenums.h></tt> as type <tt>enum GtkUpdateType</tt>,
are:
<itemize>
<item>GTK_UPDATE_POLICY_CONTINUOUS - This is the default. The
-"value_changed" signal is emitted continuously, i.e. whenever the
+"value_changed" signal is emitted continuously, i.e., whenever the
slider is moved by even the tiniest amount.
</item>
<item>GTK_UPDATE_POLICY_DISCONTINUOUS - The "value_changed" signal is
only emitted once the slider has stopped moving and the user has
released the mouse button.
</item>
-<item>GTK_UPDATE_POLICY_DELAYED - The "value_change" signal is emitted
+<item>GTK_UPDATE_POLICY_DELAYED - The "value_changed" signal is emitted
when the user releases the mouse button, or if the slider stops moving
for a short period of time.
</item>
<tt/gtk_range_set_adjustment()/ does absolutely nothing if you pass it
the adjustment that <tt/range/ is already using, regardless of whether
you changed any of its fields or not. If you pass it a new
-GtkAdjustment, it will unreference the old one if it exists (possibly
+Adjustment, it will unreference the old one if it exists (possibly
destroying it), connect the appropriate signals to the new one, and
call the private function <tt/gtk_range_adjustment_changed()/, which
will (or at least, is supposed to...) recalculate the size and/or
position of the slider and redraw if necessary. As mentioned in the
-section on adjustments, if you wish to reuse the same GtkAdjustment,
+section on adjustments, if you wish to reuse the same Adjustment,
when you modify its values directly, you should emit the "changed"
signal on it, like this:
<!-- ----------------------------------------------------------------- -->
<sect1> Key and Mouse bindings
<p>
-All of the GTK+ range widgets react to mouse clicks in more or less
+All of the GTK range widgets react to mouse clicks in more or less
the same way. Clicking button-1 in the trough will cause its
adjustment's <tt/page_increment/ to be added or subtracted from its
<tt/value/, and the slider to be moved accordingly. Clicking mouse
cause its adjustment's value to change <tt/step_increment/ at a time.
It may take a little while to get used to, but by default, scrollbars
-as well as scale widgets can take the keyboard focus in GTK+. If you
+as well as scale widgets can take the keyboard focus in GTK. If you
think your users will find this too confusing, you can always disable
-this by unsetting the GTK_CAN_FOCUS flag on the scrollbar, like this:
+this by unsetting the <tt/GTK_CAN_FOCUS/ flag on the scrollbar, like
+this:
<tscreen><verb>
GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS);
<tt/Page Up/ and <tt/Page Down/ move it by <tt/page_increment/.
The user can also move the slider all the way to one end or the other
-of the trough using the keyboard. With the GtkVScale widget, this is
+of the trough using the keyboard. With the VScale widget, this is
done with the <tt/Home/ and <tt/End/ keys, whereas with the
-GtkVScrollbar widget, this is done by typing <tt>Control-Page Up</tt>
+VScrollbar widget, this is done by typing <tt>Control-Page Up</tt>
and <tt>Control-Page Down</tt>.
<!-- ----------------------------------------------------------------- -->
The left and right arrow keys work as you might expect in these
widgets, moving the slider back and forth by <tt/step_increment/. The
<tt/Home/ and <tt/End/ keys move the slider to the ends of the trough.
-For the GtkHScale widget, moving the slider by <tt/page_increment/ is
+For the HScale widget, moving the slider by <tt/page_increment/ is
accomplished with <tt>Control-Left</tt> and <tt>Control-Right</tt>,
-while for GtkHScrollbar, it's done with <tt>Control-Home</tt> and
+while for HScrollbar, it's done with <tt>Control-Home</tt> and
<tt>Control-End</tt>.
</sect2>
</sect1>
test from <tt/testgtk.c/. It basically puts up a window with three
range widgets all connected to the same adjustment, and a couple of
controls for adjusting some of the parameters mentioned above and in
-the seciton on adjustments, so you can see how they affect the way
+the section on adjustments, so you can see how they affect the way
these widgets work for the user.
<tscreen><verb>
gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
gtk_widget_show (box2);
- /* calue, lower, upper, step_increment, page_increment, page_size */
+ /* value, lower, upper, step_increment, page_increment, page_size */
/* Note that the page_size value only makes a difference for
* scrollbar widgets, and the highest value you'll get is actually
* (upper - page_size). */
box2 = gtk_hbox_new (FALSE, 10);
gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
- /* A GtkHScale widget for adjusting the number of digits on the
+ /* An HScale widget for adjusting the number of digits on the
* sample scales. */
label = gtk_label_new ("Scale Digits:");
gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
box2 = gtk_hbox_new (FALSE, 10);
gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
- /* And, one last GtkHScale widget for adjusting the page size of the
+ /* And, one last HScale widget for adjusting the page size of the
* scrollbar. */
label = gtk_label_new ("Scrollbar Page Size:");
gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
/* example-end */
</verb></tscreen>
+
+You will notice that the program does not call <tt/gtk_signal_connect/
+for the "delete_event", but only for the "destroy" signal. This will
+still perform the desired function, because an unhandled
+"delete_event" will result in a "destroy" signal being given to the
+window.
+
</sect1>
</sect>
<p>
Labels are used a lot in GTK, and are relatively simple. Labels emit
no signals as they do not have an associated X window. If you need to
-catch signals, or do clipping, use the <ref id="sec_EventBox"
-name="EventBox"> widget.
+catch signals, or do clipping, place it inside a <ref id="sec_EventBox"
+name="EventBox"> widget or a Button widget.
To create a new label, use:
GtkWidget *gtk_label_new( char *str );
</verb></tscreen>
-Where the sole argument is the string you wish the label to display.
+The sole argument is the string you wish the label to display.
To change the label's text after creation, use the function:
char *str );
</verb></tscreen>
-Where the first argument is the label you created previously (cast
-using the GTK_LABEL() macro), and the second is the new string.
+The first argument is the label you created previously (cast
+using the <tt/GTK_LABEL()/ macro), and the second is the new string.
The space needed for the new string will be automatically adjusted if
needed. You can produce multi-line labels by putting line breaks in
char **str );
</verb></tscreen>
-Where the first argument is the label you've created, and the second,
+The first argument is the label you've created, and the second,
the return for the string. Do not free the return string, as it is
used internally by GTK.
</verb></tscreen>
Values for <tt/jtype/ are:
-<itemize>
-<item> GTK_JUSTIFY_LEFT
-<item> GTK_JUSTIFY_RIGHT
-<item> GTK_JUSTIFY_CENTER (the default)
-<item> GTK_JUSTIFY_FILL
-</itemize>
+<tscreen><verb>
+ GTK_JUSTIFY_LEFT
+ GTK_JUSTIFY_RIGHT
+ GTK_JUSTIFY_CENTER (the default)
+ GTK_JUSTIFY_FILL
+</verb></tscreen>
The label widget is also capable of line wrapping the text
automatically. This can be activated using:
gboolean wrap);
</verb></tscreen>
-The <//wrap/ argument takes a TRUE or FALSE value.
+The <tt/wrap/ argument takes a TRUE or FALSE value.
If you want your label underlined, then you can set a pattern on the
label:
consists of a string of underscore and space characters. An underscore
indicates that the corresponding character in the label should be
underlined. For example, the string <verb/"__ __"/ would underline the
-first two characters and eigth and ninth characters.
+first two characters and eight and ninth characters.
Below is a short example to illustrate these functions. This example
makes use of the Frame widget to better demonstrate the label
label = gtk_label_new ("This is an example of a line-wrapped, filled label. " \
"It should be taking "\
"up the entire width allocated to it. " \
- "Here is a seneance to prove "\
+ "Here is a sentence to prove "\
"my point. Here is another sentence. "\
"Here comes the sun, do de do de do.\n"\
" This is a new paragraph.\n"\
<p>
The Arrow widget draws an arrowhead, facing in a number of possible
directions and having a number of possible styles. It can be very
-useful when placed on a button in many applications.
+useful when placed on a button in many applications. Like the Label
+widget, it emits no signals.
There are only two functions for manipulating an Arrow widget:
retrospectively. The <tt/arrow_type/ argument may take one of the
following values:
-<itemize>
-<item> GTK_ARROW_UP
-<item> GTK_ARROW_DOWN
-<item> GTK_ARROW_LEFT
-<item> GTK_ARROW_RIGHT
-</itemize>
+<tscreen><verb>
+ GTK_ARROW_UP
+ GTK_ARROW_DOWN
+ GTK_ARROW_LEFT
+ GTK_ARROW_RIGHT
+</verb></tscreen>
These values obviously indicate the direction in which the arrow will
point. The <tt/shadow_type/ argument may take one of these values:
-<itemize>
-<item> GTK_SHADOW_IN
-<item> GTK_SHADOW_OUT (the default)
-<item> GTK_SHADOW_ETCHED_IN
-<item> GTK_SHADOW_ETCHED_OUT
-</itemize>
+<tscreen><verb>
+ GTK_SHADOW_IN
+ GTK_SHADOW_OUT (the default)
+ GTK_SHADOW_ETCHED_IN
+ GTK_SHADOW_ETCHED_OUT
+</verb></tscreen>
Here's a brief example to illustrate their use.
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
-<sect1>The Tooltips Widget
+<sect1>The Tooltips Object
<p>
These are the little text strings that pop up when you leave your
pointer over a button or other widget for a few seconds. They are easy
want to see some code, take a look at the testgtk.c program
distributed with GTK.
-Widgets that do not receieve events (widgets that do not have their
+Widgets that do not receive events (widgets that do not have their
own window) will not work with tooltips.
The first call you will use creates a new tooltip. You only need to do
-this once for a set of tooltips as the <tt/GtkTooltip/ object this
+this once for a set of tooltips as the <tt/GtkTooltips/ object this
function returns can be used to create multiple tooltips.
<tscreen><verb>
lets start out with the calls to create a new progress bar.
There are two ways to create a progress bar, one simple that takes
-no arguments, and one that takes a GtkAdjustment object as an
+no arguments, and one that takes an Adjustment object as an
argument. If the former is used, the progress bar creates its own
adjustment object.
The second method has the advantage that we can use the adjustment
object to specify our own range parameters for the progress bar.
+The adjustment of a progress object can be changed dynamically using:
+
+<tscreen><verb>
+void gtk_progress_set_adjustment( GtkProgress *progress,
+ GtkAdjustment *adjustment );
+</verb></tscreen>
+
Now that the progress bar has been created we can use it.
<tscreen><verb>
</verb></tscreen>
The first argument is the progress bar you wish to operate on, and the
-second argument is the amount 'completed', meaning the amount the
+second argument is the amount "completed", meaning the amount the
progress bar has been filled from 0-100%. This is passed to the
function as a real number ranging from 0 to 1.
GtkProgressBarOrientation orientation );
</verb></tscreen>
-Where the <tt/orientation/ argument may take one of the following
+The <tt/orientation/ argument may take one of the following
values to indicate the direction in which the progress bar moves:
-<itemize>
-<item> GTK_PROGRESS_LEFT_TO_RIGHT
-<item> GTK_PROGRESS_RIGHT_TO_LEFT
-<item> GTK_PROGRESS_BOTTOM_TO_TOP
-<item> GTK_PROGRESS_TOP_TO_BOTTOM
-</itemize>
+<tscreen><verb>
+ GTK_PROGRESS_LEFT_TO_RIGHT
+ GTK_PROGRESS_RIGHT_TO_LEFT
+ GTK_PROGRESS_BOTTOM_TO_TOP
+ GTK_PROGRESS_TOP_TO_BOTTOM
+</verb></tscreen>
When used as a measure of how far a process has progressed, the
-GtkProgressBar can be set to display its value in either a continuous
+ProgressBar can be set to display its value in either a continuous
or discrete mode. In continuous mode, the progress bar is updated for
each value. In discrete mode, the progress bar is updated in a number
of discrete blocks. The number of blocks is also configurable.
The <tt/style/ parameter can take one of two values:
-<itemize>
-<item>GTK_PROGRESS_CONTINUOUS
-<item>GTK_PROGRESS_DISCRETE
-</itemize>
+<tscreen><verb>
+ GTK_PROGRESS_CONTINUOUS
+ GTK_PROGRESS_DISCRETE
+</verb></tscreen>
The number of discrete blocks can be set by calling
As well as indicating the amount of progress that has occured, the
progress bar may be set to just indicate that there is some
activity. This can be useful in situations where progress cannot be
-measured against a value range. Activity mode is not effected by the
-bar style that is described above, and overrides it.This mode is
-selected by the following function.
+measured against a value range. Activity mode is not affected by the
+bar style that is described above, and overrides it. This mode is
+either TRUE or FALSE, and is selected by the following function.
<tscreen><verb>
void gtk_progress_set_activity_mode( GtkProgress *progress,
<item> %l - lower range value
<item> %u - upper range value
</itemize>
-
+
+The displaying of this text string can be toggled using:
+
+<tscreen><verb>
+void gtk_progress_set_show_text( GtkProgress *progress,
+ gint show_text );
+</verb></tscreen>
+
+The <tt/show_text/ argument is a boolean TRUE/FALSE value. The
+appearance of the text can be modified further using:
+
+<tscreen><verb>
+void gtk_progress_set_text_alignment( GtkProgress *progress,
+ gfloat x_align,
+ gfloat y_align );
+</verb></tscreen>
+
+The <tt/x_align/ and <tt/y_align/ arguments take values between 0.0
+and 1.0. Their values indicate the position of the text string within
+the trough. Values of 0.0 for both would place the string in the top
+left hand corner; values of 0.5 (the default) centres the text, and
+values of 1.0 places the text in the lower right hand corner.
+
+The current text setting of a progress object can be retrieved using
+the current or a specified adjustment value using the following two
+functions. The character string returned by these functions should be
+freed by the application (using the g_free() function). These
+functions return the formatted string that would be displayed within
+the trough.
+
+<tscreen><verb>
+gchar *gtk_progress_get_current_text( GtkProgress *progress );
+
+gchar *gtk_progress_get_text_from_value( GtkProgress *progress,
+ gfloat value );
+</verb></tscreen>
+
+There is yet another way to change the range and value of a progress
+object using the following function:
+
+<tscreen><verb>
+void gtk_progress_configure( GtkProgress *progress,
+ gfloat value,
+ gfloat min,
+ gfloat max );
+</verb></tscreen>
+
+This function provides quite a simple interface to the range and value
+of a progress object.
+
+The remaining functions can be used to get and set the current value
+of a progess object in various types and formats:
+
+<tscreen><verb>
+void gtk_progress_set_percentage( GtkProgress *progress,
+ gfloat percentage );
+
+void gtk_progress_set_value( GtkProgress *progress,
+ gfloat value );
+
+gfloat gtk_progress_get_value( GtkProgress *progress );
+
+gfloat gtk_progress_get_current_percentage( GtkProgress *progress );
+
+gfloat gtk_progress_get_percentage_from_value( GtkProgress *progress,
+ gfloat value );
+</verb></tscreen>
+
+These functions are pretty self explanatory. The last function uses
+the the adjustment of the specified progess object to compute the
+percentage value of the given range value.
+
Progress Bars are usually used with timeouts or other such functions
(see section on <ref id="sec_timeouts" name="Timeouts, I/O and Idle
Functions">) to give the illusion of multitasking. All will employ the
gtk_progress_bar_update function in the same manner.
-Here is an example of the progress bar, updated using timeouts. This
+Here is an example of the progress bar, updated using timeouts. This
code also shows you how to reset the Progress Bar.
<tscreen><verb>
gfloat new_val;
GtkAdjustment *adj;
- adj = GTK_PROGRESS (data)->adjustment;
-
/* Calculate the value of the progress bar using the
* value range set in the adjustment object */
- new_val = adj->value + 1;
+
+ new_val = gtk_progress_get_value( GTK_PROGRESS(data) ) + 1;
+
+ adj = GTK_PROGRESS (data)->adjustment;
if (new_val > adj->upper)
new_val = adj->lower;
gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
gtk_widget_show(align);
- /* Create a GtkAdjusment object to hold the range of the
+ /* Create a Adjusment object to hold the range of the
* progress bar */
adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 150, 0, 0, 0);
</verb></tscreen>
So you see, it simply creates a window, and then packs a vbox into the
-top, then a separator, and then an hbox for the "action_area".
+top, which contains a separator and then an hbox called the
+"action_area".
The Dialog widget can be used for pop-up messages to the user, and
other similar tasks. It is really basic, and there is only one
</verb></tscreen>
This will create the dialog box, and it is now up to you to use it.
-you could pack a button in the action_area by doing something like this:
+You could pack a button in the action_area by doing something like this:
<tscreen><verb>
button = ...
the operation the user selects.
If the simple functionality provided by the default vertical and
-horizontal boxes in the two areas does't give you enough control for
+horizontal boxes in the two areas doesn't give you enough control for
your application, then you can simply pack another layout widget into
the boxes provided. For example, you could pack a table into the
vertical box.
<sect1> Pixmaps <label id="sec_Pixmaps">
<p>
Pixmaps are data structures that contain pictures. These pictures can
-be used in various places, but most visibly as icons on the X-Windows
+be used in various places, but most commonly as icons on the X
desktop, or as cursors.
A pixmap which only has 2 colors is called a bitmap, and there are a
few additional routines for handling this common special case.
-To understand pixmaps, it would help to understand how X-windows
-works. Under X-windows, applications do not need to be running on the
+To understand pixmaps, it would help to understand how X window
+system works. Under X, applications do not need to be running on the
same computer that is interacting with the user. Instead, the various
applications, called "clients", all communicate with a program which
displays the graphics and handles the keyboard and mouse. This
Pixmaps, for example, are stored in the memory of the X server. This
means that once pixmap values are set, they don't need to keep getting
transmitted over the network; instead a command is sent to "display
-pixmap number XYZ here." Even if you aren't using X-windows with GTK
+pixmap number XYZ here." Even if you aren't using X with GTK
currently, using constructs such as Pixmaps will make your programs
-work acceptably under X-windows.
+work acceptably under X.
To use pixmaps in GTK, we must first build a GdkPixmap structure using
routines from the GDK layer. Pixmaps can either be created from
This routine is used to create a single-plane pixmap (2 colors) from
data in memory. Each bit of the data represents whether that pixel is
-off or on. Width and height are in pixels. The GdkWindow pointer is
-to the current window, since a pixmap resources are meaningful only in
+off or on. Width and height are in pixels. The GdkWindow pointer is to
+the current window, since a pixmap's resources are meaningful only in
the context of the screen where it is to be displayed.
<tscreen><verb>
When we're done using a pixmap and not likely to reuse it again soon,
it is a good idea to release the resource using
-gdk_pixmap_unref(). Pixmaps should be considered a precious resource.
+gdk_pixmap_unref(). Pixmaps should be considered a precious resource,
+because they take up memory in the end-user's X server process. Even
+though the X client you write may run on a powerful "server" computer,
+the user may be running the X server on a small personal computer.
Once we've created a pixmap, we can display it as a GTK widget. We
must create a GTK pixmap widget to contain the GDK pixmap. This is
/* when invoked (via signal delete_event), terminates the application.
*/
-void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
+gint close_application( GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data )
+{
gtk_main_quit();
+ return(FALSE);
}
/* is invoked when the button is clicked. It just prints a message.
*/
-void button_clicked( GtkWidget *widget, gpointer data ) {
- printf( "button clicked\n" );
+void button_clicked( GtkWidget *widget,
+ gpointer data ) {
+ g_print( "button clicked\n" );
}
-int main( int argc, char *argv[] )
+int main( int argc,
+ char *argv[] )
{
/* GtkWidget is the storage type for widgets */
GtkWidget *window, *pixmapwid, *button;
/* When invoked (via signal delete_event), terminates the application */
-void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
+gint close_application( GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data )
+{
gtk_main_quit();
+ return(FALSE);
}
-int main (int argc, char *argv[])
+int main (int argc,
+ char *argv[] )
{
/* GtkWidget is the storage type for widgets */
GtkWidget *window, *pixmap, *fixed;
</verb></tscreen>
Once a ruler is created, we can define the unit of measurement. Units
-of measure for rulers can be GTK_PIXELS, GTK_INCHES or
-GTK_CENTIMETERS. This is set using
+of measure for rulers can be<tt/GTK_PIXELS/, <tt/GTK_INCHES/ or
+<tt/GTK_CENTIMETERS/. This is set using
<tscreen><verb>
void gtk_ruler_set_metric( GtkRuler *ruler,
GtkMetricType metric );
</verb></tscreen>
-The default measure is GTK_PIXELS.
+The default measure is <tt/GTK_PIXELS/.
<tscreen><verb>
gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
#define YSIZE 400
/* This routine gets control when the close button is clicked */
-void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
+gint close_application( GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data )
+{
gtk_main_quit();
+ return(FALSE);
}
/* The main routine */
-int main( int argc, char *argv[] ) {
+int main( int argc,
+ char *argv[] ) {
GtkWidget *window, *table, *area, *hrule, *vrule;
/* Initialize GTK and create the main window */
In order to allow different parts of an application to use the same
statusbar to display messages, the statusbar widget issues Context
-Identifiers which are used to identify different 'users'. The message
+Identifiers which are used to identify different "users". The message
on top of the stack is the one displayed, no matter what context it is
in. Messages are stacked in last-in-first-out order, not context
identifier order.
GtkWidget *status_bar;
-void push_item (GtkWidget *widget, gpointer data)
+void push_item( GtkWidget *widget,
+ gpointer data )
{
static int count = 1;
char buff[20];
return;
}
-void pop_item (GtkWidget *widget, gpointer data)
+void pop_item( GtkWidget *widget,
+ gpointer data )
{
gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) );
return;
}
-int main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
If we want to catch when the user has entered text, we can connect to
the <tt/activate/ or <tt/changed/ signal. Activate is raised when the
user hits the enter key within the Entry widget. Changed is raised
-when the text changes at all, e.g. for every character entered or
+when the text changes at all, e.g., for every character entered or
removed.
The following code is an example of using an Entry widget.
<tscreen><verb>
/* example-start entry entry.c */
+#include <stdio.h>
#include <gtk/gtk.h>
-void enter_callback(GtkWidget *widget, GtkWidget *entry)
+void enter_callback( GtkWidget *widget,
+ GtkWidget *entry )
{
gchar *entry_text;
entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
printf("Entry contents: %s\n", entry_text);
}
-void entry_toggle_editable (GtkWidget *checkbutton,
- GtkWidget *entry)
+void entry_toggle_editable( GtkWidget *checkbutton,
+ GtkWidget *entry )
{
gtk_entry_set_editable(GTK_ENTRY(entry),
GTK_TOGGLE_BUTTON(checkbutton)->active);
}
-void entry_toggle_visibility (GtkWidget *checkbutton,
- GtkWidget *entry)
+void entry_toggle_visibility( GtkWidget *checkbutton,
+ GtkWidget *entry )
{
gtk_entry_set_visibility(GTK_ENTRY(entry),
GTK_TOGGLE_BUTTON(checkbutton)->active);
}
-int main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
The Spin Button widget is generally used to allow the user to select a
value from a range of numeric values. It consists of a text
entry box with up and down arrow buttons attached to the
-side. Selecting one of the buttons causes the value to 'spin' up and
+side. Selecting one of the buttons causes the value to "spin" up and
down the range of possible values. The entry box may also be edited
directly to enter a specific value.
The Spin Button allows the value to have zero or a number of decimal
places and to be incremented/decremented in configurable steps. The
-action of holding down one of the buttons optionally result in an
+action of holding down one of the buttons optionally results in an
acceleration of change in the value according to how long it is
depressed.
The <tt/direction/ parameter can take one of the following values:
-<itemize>
-<item> GTK_SPIN_STEP_FORWARD
-<item> GTK_SPIN_STEP_BACKWARD
-<item> GTK_SPIN_PAGE_FORWARD
-<item> GTK_SPIN_PAGE_BACKWARD
-<item> GTK_SPIN_HOME
-<item> GTK_SPIN_END
-<item> GTK_SPIN_USER_DEFINED
-</itemize>
+<tscreen><verb>
+ GTK_SPIN_STEP_FORWARD
+ GTK_SPIN_STEP_BACKWARD
+ GTK_SPIN_PAGE_FORWARD
+ GTK_SPIN_PAGE_BACKWARD
+ GTK_SPIN_HOME
+ GTK_SPIN_END
+ GTK_SPIN_USER_DEFINED
+</verb></tscreen>
This function packs in quite a bit of functionality, which I will
attempt to clearly explain. Many of these settings use values from the
Adjustment object that is associated with a Spin Button.
-GTK_SPIN_STEP_FORWARD and GTK_SPIN_STEP_BACKWARD change the value of
-the Spin Button by the amount specified by <tt/increment/, unless
-<tt/increment/ is equal to 0, in which case the value is changed by
-the value of <tt/step_increment/ in theAdjustment.
+<tt/GTK_SPIN_STEP_FORWARD/ and <tt/GTK_SPIN_STEP_BACKWARD/ change the
+value of the Spin Button by the amount specified by <tt/increment/,
+unless <tt/increment/ is equal to 0, in which case the value is
+changed by the value of <tt/step_increment/ in theAdjustment.
-GTK_SPIN_PAGE_FORWARD and GTK_SPIN_PAGE_BACKWARD simply alter the value of
-the Spin Button by <tt/increment/.
+<tt/GTK_SPIN_PAGE_FORWARD/ and <tt/GTK_SPIN_PAGE_BACKWARD/ simply
+alter the value of the Spin Button by <tt/increment/.
-GTK_SPIN_HOME sets the value of the Spin Button to the bottom of the
-Adjustments range.
+<tt/GTK_SPIN_HOME/ sets the value of the Spin Button to the bottom of
+the Adjustments range.
-GTK_SPIN_END sets the value of the Spin Button to the top of the
+<tt/GTK_SPIN_END/ sets the value of the Spin Button to the top of the
Adjustments range.
-GTK_SPIN_USER_DEFINED simply alters the value of the Spin Button by
-the specified amount.
+<tt/GTK_SPIN_USER_DEFINED/ simply alters the value of the Spin Button
+by the specified amount.
We move away from functions for setting and retreving the range attributes
-of the Spin Button now, and move onto functions that effect the
+of the Spin Button now, and move onto functions that affect the
appearance and behaviour of the Spin Button widget itself.
The first of these functions is used to constrain the text box of the
-Spin Button such that it may only contain a numric value. This
+Spin Button such that it may only contain a numeric value. This
prevents a user from typing anything other than numeric values into
the text box of a Spin Button:
<!-- TODO: find out what this does - TRG -->
-The possible values of <tt/policy/ are either GTK_UPDATE_ALWAYS or
-GTK_UPDATE_IF_VALID.
+The possible values of <tt/policy/ are either <tt/GTK_UPDATE_ALWAYS/ or
+<tt/GTK_UPDATE_IF_VALID/.
These policies affect the behavior of a Spin Button when parsing
-inserted text and syncing it's value with the values of the
+inserted text and syncing its value with the values of the
Adjustment.
-In the case of GTK_UPDATE_IF_VALID the Spin Button only value gets
-changed if the text input is a numeric value that
-is within the range specified by the Adjustment. Otherwise
-the text is reset to the current value.
+In the case of <tt/GTK_UPDATE_IF_VALID/ the Spin Button only value
+gets changed if the text input is a numeric value that is within the
+range specified by the Adjustment. Otherwise the text is reset to the
+current value.
-In case of GTK_UPDATE_ALWAYS we ignore errors while converting text
-into a numeric value.
+In case of <tt/GTK_UPDATE_ALWAYS/ we ignore errors while converting
+text into a numeric value.
The appearance of the buttons used in a Spin Button can be changed
using the following function:
As usual, the <tt/shadow_type/ can be one of:
-<itemize>
-<item> GTK_SHADOW_IN
-<item> GTK_SHADOW_OUT
-<item> GTK_SHADOW_ETCHED_IN
-<item> GTK_SHADOW_ETCHED_OUT
-</itemize>
+<tscreen><verb>
+ GTK_SHADOW_IN
+ GTK_SHADOW_OUT
+ GTK_SHADOW_ETCHED_IN
+ GTK_SHADOW_ETCHED_OUT
+</verb></tscreen>
Finally, you can explicitly request that a Spin Button update itself:
<tscreen><verb>
/* example-start spinbutton spinbutton.c */
+#include <stdio.h>
#include <gtk/gtk.h>
static GtkWidget *spinner1;
<sect1>Combo Box
<p>
The combo box is another fairly simple widget that is really just a
-collection of other widgets. From the users point of view, the widget
+collection of other widgets. From the user's point of view, the widget
consists of a text entry box and a pull down menu from which the user
can select one of a set of predefined entries. Alternatively, the user
can type a different option directly into the text box.
... };
</verb></tscreen>
-As you can see, the Combo Box has two principle parts that you really
+As you can see, the Combo Box has two principal parts that you really
care about: an entry and a list.
First off, to create a combo box, use:
Before you can do this, you have to assemble a GList of the strings
that you want. GList is a linked list implementation that is part of
-<ref id="sec_glib" name="glib">, a library supporing GTK. For the
+<ref id="sec_glib" name="GLib">, a library supporing GTK. For the
moment, the quick and dirty explanation is that you need to set up a
GList pointer, set it equal to NULL, then append strings to it with
gtk_combo_set_popdown_strings( GTK_COMBO(combo), glist) ;
</verb></tscreen>
+The combo widget makes a copy of the strings passed to it in the glist
+structure. As a result, you need to make sure you free the memory used
+by the list if that is appropriate for your application.
+
At this point you have a working combo box that has been set up.
There are a few aspects of its behavior that you can change. These
are accomplished with the functions:
disabling the use of the up and down arrow keys for changing focus.
<tt/gtk_combo_set_case_sensitive()/ toggles whether or not GTK
-searches for entries in a case sensitive manner. This is used when
-the Combo widget is asked to find a value from the list using the
-current entry in the text box. This completion can be performed in
-eother a case sensitive or insensitive manner, depending upon the use
-of this function. The Combo widget can also simply complete the
-current entry if the user presses the key combination MOD-1 and
-'Tab'. MOD-1 is often mapped to the 'Alt' key. Note, however that some
-Window managers also use this key combination, which will override
-it's use within GTK.
+searches for entries in a case sensitive manner. This is used when the
+Combo widget is asked to find a value from the list using the current
+entry in the text box. This completion can be performed in either a
+case sensitive or insensitive manner, depending upon the use of this
+function. The Combo widget can also simply complete the current entry
+if the user presses the key combination MOD-1 and "Tab". MOD-1 is
+often mapped to the "Alt" key, by the <tt/xmodmap/ utility. Note,
+however that some window managers also use this key combination, which
+will override its use within GTK.
Now that we have a combo box, tailored to look and act how we want it,
all that remains is being able to get data from the combo box. This is
-relatively straight forward. The majority of the time, all you are
+relatively straightforward. The majority of the time, all you are
going to care about getting data from is the entry. The entry is
-accessed simply by GTK_ENTRY(GTK_COMBO(combo)->entry). The two
-principle things that you are going to want to do with it are attach
-to the activate signal, which indicates that the user has pressed the
-Return or Enter key,and read the text. The first is accomplished
-using something like:
+accessed simply by <tt>GTK_ENTRY(GTK_COMBO(combo)->entry)</tt>. The
+two principal things that you are going to want to do with it are
+attach to the activate signal, which indicates that the user has
+pressed the Return or Enter key, and read the text. The first is
+accomplished using something like:
<tscreen><verb>
gtk_signal_connect(GTK_OBJECT(GTK_COMB(combo)->entry), "activate",
box. Personally, I can't think of why you'd want to use it, but it
does exist.
-<!-- There are also a function to set the string on a particular item, void
+<!-- There is also a function to set the string on a particular item, void
gtk_combo_set_item_string(GtkCombo *combo, GtkItem *item, const gchar
*item_value), but this requires that you have a pointer to the
-appropriate GtkItem. Frankly, I have no idea how to do that.
+appropriate Item. Frankly, I have no idea how to do that.
-->
<!-- ----------------------------------------------------------------- -->
-<sect1> Color Selection
+<sect1> Calendar
<p>
-The color selection widget is, not surprisingly, a widget for
-interactive selection of colors. This composite widget lets the user
-select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
-Saturation, Value) triples. This is done either by adjusting single
-values with sliders or entries, or by picking the desired color from a
-hue-saturation wheel/value bar. Optionally, the opacity of the color
-can also be set.
-
-The color selection widget currently emits only one signal,
-"color_changed", which is emitted whenever the current color in the
-widget changes, either when the user changes it or if it's set
-explicitly through gtk_color_selection_set_color().
+The Calendar widget is an effective way to display and retrieve
+monthly date related information. It is a very simple widget to create
+and work with.
-Lets have a look at what the color selection widget has to offer
-us. The widget comes in two flavours: gtk_color_selection and
-gtk_color_selection_dialog.
+Creating a GtkCalendar widget is a simple as:
<tscreen><verb>
-GtkWidget *gtk_color_selection_new( void );
+GtkWidget *gtk_calendar_new();
</verb></tscreen>
-
-You'll probably not be using this constructor directly. It creates an
-orphan GtkColorSelection widget which you'll have to parent
-yourself. The GtkColorSelection widget inherits from the GtkVBox
-widget.
-<tscreen><verb>
-GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
+There might be times where you need to change a lot of information
+within this widget and the following functions allow you to make
+multiple change to a Calendar widget without the user seeing multiple
+on-screen updates.
+
+<tscreen><verb>
+void gtk_calendar_freeze( GtkCalendar *Calendar );
+
+void gtk_calendar_thaw ( GtkCalendar *Calendar );
</verb></tscreen>
-This is the most common color selection constructor. It creates a
-GtkColorSelectionDialog, which inherits from a GtkDialog. It consists
-of a GtkFrame containing a GtkColorSelection widget, a GtkHSeparator
-and a GtkHBox with three buttons, "Ok", "Cancel" and "Help". You can
-reach these buttons by accessing the "ok_button", "cancel_button" and
-"help_button" widgets in the GtkColorSelectionDialog structure,
-(i.e. GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button).
+They work just like the freeze/thaw functions of every other
+widget.
+
+The Calendar widget has a few options that allow you to change the way
+the widget both looks and operates by using the function
<tscreen><verb>
-void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel,
- GtkUpdateType policy );
+void gtk_calendar_display_options( GtkCalendar *calendar,
+ GtkCalendarDisplayOptions flags );
</verb></tscreen>
-This function sets the update policy. The default policy is
-GTK_UPDATE_CONTINUOUS which means that the current color is updated
-continuously when the user drags the sliders or presses the mouse and
-drags in the hue-saturation wheel or value bar. If you experience
-performance problems, you may want to set the policy to
-GTK_UPDATE_DISCONTINUOUS or GTK_UPDATE_DELAYED.
+The <tt/flags/ argument can be formed by combining either of the
+following five options using the logical bitwise OR (|) operation:
+<itemize>
+<item> GTK_CALENDAR_SHOW_HEADING - this option specifies that
+the month and year should be shown when drawing the calendar.
+<item> GTK_CALENDAR_SHOW_DAY_NAMES - this option specifies that the
+three letter descriptions should be displayed for each day (eg
+MON,TUE...).
+
+<item> GTK_CALENDAR_NO_MONTH_CHANGE - this option states that the user
+should not and can not change the currently displayed month. This can
+be good if you only need to display a particular month such as if you
+are displaying 12 calendar widgets for every month in a particular
+year.
+
+<item> GTK_CALENDAR_SHOW_WEEK_NUMBERS - this option specifies that the
+number for each week should be displayed down the left side of the
+calendar. (eg. Jan 1 = Week 1,Dec 31 = Week 52).
+
+<item> GTK_CALENDAR_WEEK_START_MONDAY - this option states that the
+calander week will start on Monday instead of Sunday which is the
+default. This only affects the order in which days are displayed from
+left to right.
+</itemize>
+The following functions are used to set the the currently displayed
+date:
<tscreen><verb>
-void gtk_color_selection_set_opacity( GtkColorSelection *colorsel,
- gint use_opacity );
+gint gtk_calendar_select_month( GtkCalendar *calendar,
+ guint month,
+ guint year );
+
+void gtk_calendar_select_day( GtkCalendar *calendar,
+ guint day );
</verb></tscreen>
-The color selection widget supports adjusting the opacity of a color
-(also known as the alpha channel). This is disabled by
-default. Calling this function with use_opacity set to TRUE enables
-opacity. Likewise, use_opacity set to FALSE will disable opacity.
+The return value from <tt/gtk_calendar_select_month()/ is a boolean
+value indicating whether the selection was successful.
+
+With <tt/gtk_calendar_select_day()/ the specified day number is
+selected within the current month, if that is possible. A
+<tt/day/ value of 0 will deselect any current selection.
+
+In addition to having a day selected, any number of days in the month
+may be "marked". A marked day is highlighted within the calendar
+display. The following functions are provided to manipulate marked
+days:
<tscreen><verb>
-void gtk_color_selection_set_color( GtkColorSelection *colorsel,
- gdouble *color );
+gint gtk_calendar_mark_day( GtkCalendar *calendar,
+ guint day);
+
+gint gtk_calendar_unmark_day( GtkCalendar *calendar,
+ guint day);
+
+void gtk_calendar_clear_marks( GtkCalendar *calendar);
</verb></tscreen>
-You can set the current color explicitly by calling this function with
-a pointer to an array of colors (gdouble). The length of the array
-depends on whether opacity is enabled or not. Position 0 contains the
-red component, 1 is green, 2 is blue and opacity is at position 3
-(only if opacity is enabled, see
-gtk_color_selection_set_opacity()). All values are between 0.0 and
-1.0.
+The currently marked days are stored within an array within the
+GtkCalendar structure. This array is 31 elements long so to test
+whether a particular day is currently marked, you need to access the
+corresponding element of the array (don't forget in C that array
+elements are numbered 0 to n-1). For example:
<tscreen><verb>
-void gtk_color_selection_get_color( GtkColorSelection *colorsel,
- gdouble *color );
-</verb></tscreen>
+ GtkCalendar *calendar;
+ calendar = gtk_calendar_new();
-When you need to query the current color, typically when you've
-received a "color_changed" signal, you use this function. Color is a
-pointer to the array of colors to fill in. See the
-gtk_color_selection_set_color() function for the description of this
-array.
+ ...
-<!-- Need to do a whole section on DnD - TRG
-Drag and drop
--------------
+ /* Is day 7 marked? */
+ if (calendar->marked_date[7-1])
+ /* day is marked */
+</verb></tscreen>
-The color sample areas (right under the hue-saturation wheel) supports
-drag and drop. The type of drag and drop is "application/x-color". The
-message data consists of an array of 4 (or 5 if opacity is enabled)
-gdouble values, where the value at position 0 is 0.0 (opacity on) or
-1.0 (opacity off) followed by the red, green and blue values at
-positions 1,2 and 3 respectively. If opacity is enabled, the opacity
-is passed in the value at position 4.
--->
+Note that marks are persistent across month and year changes.
-Here's a simple example demonstrating the use of the
-GtkColorSelectionDialog. The program displays a window containing a
-drawing area. Clicking on it opens a color selection dialog, and
-changing the color in the color selection dialog changes the
-background color.
+The final Calendar widget function is used to retrieve the currently
+selected date, month and/or year.
<tscreen><verb>
-/* example-start colorsel colorsel.c */
+void gtk_calendar_get_date( GtkCalendar *calendar,
+ guint *year,
+ guint *month,
+ guint *day );
+</verb></tscreen>
-#include <glib.h>
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
+This function requires you to pass the addresses of <tt/guint/
+variables, into which the result will be placed. Passing <tt/NULL/ as
+a value will result in the corresponding value not being returned.
-GtkWidget *colorseldlg = NULL;
-GtkWidget *drawingarea = NULL;
+The Calendar widget can generate a number of signals indicating date
+selection and change. The names of these signals are self explanatory,
+and are:
-/* Color changed handler */
+<itemize>
+<item> <tt/month_changed/
+<item> <tt/day_selected/
+<item> <tt/day_selected_double_click/
+<item> <tt/prev_month/
+<item> <tt/next_month/
+<item> <tt/prev_year/
+<item> <tt/next_year/
+</itemize>
-void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel)
-{
- gdouble color[3];
- GdkColor gdk_color;
- GdkColormap *colormap;
+That just leaves us with the need to put all of this together into
+example code.
- /* Get drawingarea colormap */
+<tscreen><verb>
+/* example-start calendar calendar.c */
+/*
+ * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson, Mattias Grönlund
+ * Copyright (C) 2000 Tony Gale
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
- colormap = gdk_window_get_colormap (drawingarea->window);
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
- /* Get current color */
+#define DEF_PAD 10
+#define DEF_PAD_SMALL 5
- gtk_color_selection_get_color (colorsel,color);
+#define TM_YEAR_BASE 1900
- /* Fit to a unsigned 16 bit integer (0..65535) and
- * insert into the GdkColor structure */
+typedef struct _CalendarData {
+ GtkWidget *flag_checkboxes[5];
+ gboolean settings[5];
+ gchar *font;
+ GtkWidget *font_dialog;
+ GtkWidget *window;
+ GtkWidget *prev2_sig;
+ GtkWidget *prev_sig;
+ GtkWidget *last_sig;
+ GtkWidget *month;
+} CalendarData;
+
+enum {
+ calendar_show_header,
+ calendar_show_days,
+ calendar_month_change,
+ calendar_show_week,
+ calendar_monday_first
+};
+
+/*
+ * GtkCalendar
+ */
+
+void calendar_date_to_string( CalendarData *data,
+ char *buffer,
+ gint buff_len )
+{
+ struct tm tm;
+ time_t time;
+
+ memset (&tm, 0, sizeof (tm));
+ gtk_calendar_get_date (GTK_CALENDAR(data->window),
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday);
+ tm.tm_year -= TM_YEAR_BASE;
+ time = mktime(&tm);
+ strftime (buffer, buff_len-1, "%x", gmtime(&time));
+}
+
+void calendar_set_signal_strings( char *sig_str,
+ CalendarData *data)
+{
+ gchar *prev_sig;
+
+ gtk_label_get (GTK_LABEL (data->prev_sig), &prev_sig);
+ gtk_label_set (GTK_LABEL (data->prev2_sig), prev_sig);
+
+ gtk_label_get (GTK_LABEL (data->last_sig), &prev_sig);
+ gtk_label_set (GTK_LABEL (data->prev_sig), prev_sig);
+ gtk_label_set (GTK_LABEL (data->last_sig), sig_str);
+}
+
+void calendar_month_changed( GtkWidget *widget,
+ CalendarData *data )
+{
+ char buffer[256] = "month_changed: ";
+
+ calendar_date_to_string (data, buffer+15, 256-15);
+ calendar_set_signal_strings (buffer, data);
+}
+
+void calendar_day_selected( GtkWidget *widget,
+ CalendarData *data )
+{
+ char buffer[256] = "day_selected: ";
+
+ calendar_date_to_string (data, buffer+14, 256-14);
+ calendar_set_signal_strings (buffer, data);
+}
+
+void calendar_day_selected_double_click( GtkWidget *widget,
+ CalendarData *data )
+{
+ struct tm tm;
+ char buffer[256] = "day_selected_double_click: ";
+
+ calendar_date_to_string (data, buffer+27, 256-27);
+ calendar_set_signal_strings (buffer, data);
+
+ memset (&tm, 0, sizeof (tm));
+ gtk_calendar_get_date (GTK_CALENDAR(data->window),
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday);
+ tm.tm_year -= TM_YEAR_BASE;
+
+ if(GTK_CALENDAR(data->window)->marked_date[tm.tm_mday-1] == 0) {
+ gtk_calendar_mark_day(GTK_CALENDAR(data->window),tm.tm_mday);
+ } else {
+ gtk_calendar_unmark_day(GTK_CALENDAR(data->window),tm.tm_mday);
+ }
+}
+
+void calendar_prev_month( GtkWidget *widget,
+ CalendarData *data )
+{
+ char buffer[256] = "prev_month: ";
+
+ calendar_date_to_string (data, buffer+12, 256-12);
+ calendar_set_signal_strings (buffer, data);
+}
+
+void calendar_next_month( GtkWidget *widget,
+ CalendarData *data )
+{
+ char buffer[256] = "next_month: ";
+
+ calendar_date_to_string (data, buffer+12, 256-12);
+ calendar_set_signal_strings (buffer, data);
+}
+
+void calendar_prev_year( GtkWidget *widget,
+ CalendarData *data )
+{
+ char buffer[256] = "prev_year: ";
+
+ calendar_date_to_string (data, buffer+11, 256-11);
+ calendar_set_signal_strings (buffer, data);
+}
+
+void calendar_next_year( GtkWidget *widget,
+ CalendarData *data )
+{
+ char buffer[256] = "next_year: ";
+
+ calendar_date_to_string (data, buffer+11, 256-11);
+ calendar_set_signal_strings (buffer, data);
+}
+
+
+void calendar_set_flags( CalendarData *calendar )
+{
+ gint i;
+ gint options=0;
+ for (i=0;i<5;i++)
+ if (calendar->settings[i])
+ {
+ options=options + (1<<i);
+ }
+ if (calendar->window)
+ gtk_calendar_display_options (GTK_CALENDAR (calendar->window), options);
+}
+
+void calendar_toggle_flag( GtkWidget *toggle,
+ CalendarData *calendar )
+{
+ gint i;
+ gint j;
+ j=0;
+ for (i=0; i<5; i++)
+ if (calendar->flag_checkboxes[i] == toggle)
+ j = i;
+
+ calendar->settings[j]=!calendar->settings[j];
+ calendar_set_flags(calendar);
+
+}
+
+void calendar_font_selection_ok( GtkWidget *button,
+ CalendarData *calendar )
+{
+ GtkStyle *style;
+ GdkFont *font;
+
+ calendar->font = gtk_font_selection_dialog_get_font_name(
+ GTK_FONT_SELECTION_DIALOG (calendar->font_dialog));
+ if (calendar->window)
+ {
+ font = gtk_font_selection_dialog_get_font(GTK_FONT_SELECTION_DIALOG(calendar->font_dialog));
+ if (font)
+ {
+ style = gtk_style_copy (gtk_widget_get_style (calendar->window));
+ gdk_font_unref (style->font);
+ style->font = font;
+ gdk_font_ref (style->font);
+ gtk_widget_set_style (calendar->window, style);
+ }
+ }
+}
+
+void calendar_select_font( GtkWidget *button,
+ CalendarData *calendar )
+{
+ GtkWidget *window;
+
+ if (!calendar->font_dialog) {
+ window = gtk_font_selection_dialog_new ("Font Selection Dialog");
+ g_return_if_fail(GTK_IS_FONT_SELECTION_DIALOG(window));
+ calendar->font_dialog = window;
+
+ gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_widget_destroyed),
+ &calendar->font_dialog);
+
+ gtk_signal_connect (GTK_OBJECT (GTK_FONT_SELECTION_DIALOG (window)->ok_button),
+ "clicked", GTK_SIGNAL_FUNC(calendar_font_selection_ok),
+ calendar);
+ gtk_signal_connect_object (GTK_OBJECT (GTK_FONT_SELECTION_DIALOG (window)->cancel_button),
+ "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ GTK_OBJECT (calendar->font_dialog));
+ }
+ window=calendar->font_dialog;
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show (window);
+ else
+ gtk_widget_destroy (window);
+
+}
+
+void create_calendar()
+{
+ GtkWidget *window;
+ GtkWidget *vbox, *vbox2, *vbox3;
+ GtkWidget *hbox;
+ GtkWidget *hbbox;
+ GtkWidget *calendar;
+ GtkWidget *toggle;
+ GtkWidget *button;
+ GtkWidget *frame;
+ GtkWidget *separator;
+ GtkWidget *label;
+ GtkWidget *bbox;
+ static CalendarData calendar_data;
+ gint i;
+
+ struct {
+ char *label;
+ } flags[] =
+ {
+ { "Show Heading" },
+ { "Show Day Names" },
+ { "No Month Change" },
+ { "Show Week Numbers" },
+ { "Week Start Monday" }
+ };
+
+
+ calendar_data.window = NULL;
+ calendar_data.font = NULL;
+ calendar_data.font_dialog = NULL;
+
+ for (i=0; i<5; i++) {
+ calendar_data.settings[i]=0;
+ }
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window), "GtkCalendar Example");
+ gtk_container_border_width (GTK_CONTAINER (window), 5);
+ gtk_signal_connect(GTK_OBJECT(window), "destroy",
+ GTK_SIGNAL_FUNC(gtk_main_quit),
+ NULL);
+ gtk_signal_connect(GTK_OBJECT(window), "delete-event",
+ GTK_SIGNAL_FUNC(gtk_false),
+ NULL);
+
+ gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, TRUE);
+
+ vbox = gtk_vbox_new(FALSE, DEF_PAD);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+
+ /*
+ * The top part of the window, Calendar, flags and fontsel.
+ */
+
+ hbox = gtk_hbox_new(FALSE, DEF_PAD);
+ gtk_box_pack_start (GTK_BOX(vbox), hbox, TRUE, TRUE, DEF_PAD);
+ hbbox = gtk_hbutton_box_new();
+ gtk_box_pack_start(GTK_BOX(hbox), hbbox, FALSE, FALSE, DEF_PAD);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox), GTK_BUTTONBOX_SPREAD);
+ gtk_button_box_set_spacing(GTK_BUTTON_BOX(hbbox), 5);
+
+ /* Calendar widget */
+ frame = gtk_frame_new("Calendar");
+ gtk_box_pack_start(GTK_BOX(hbbox), frame, FALSE, TRUE, DEF_PAD);
+ calendar=gtk_calendar_new();
+ calendar_data.window = calendar;
+ calendar_set_flags(&calendar_data);
+ gtk_calendar_mark_day ( GTK_CALENDAR(calendar), 19);
+ gtk_container_add( GTK_CONTAINER( frame), calendar);
+ gtk_signal_connect (GTK_OBJECT (calendar), "month_changed",
+ GTK_SIGNAL_FUNC (calendar_month_changed),
+ &calendar_data);
+ gtk_signal_connect (GTK_OBJECT (calendar), "day_selected",
+ GTK_SIGNAL_FUNC (calendar_day_selected),
+ &calendar_data);
+ gtk_signal_connect (GTK_OBJECT (calendar), "day_selected_double_click",
+ GTK_SIGNAL_FUNC (calendar_day_selected_double_click),
+ &calendar_data);
+ gtk_signal_connect (GTK_OBJECT (calendar), "prev_month",
+ GTK_SIGNAL_FUNC (calendar_prev_month),
+ &calendar_data);
+ gtk_signal_connect (GTK_OBJECT (calendar), "next_month",
+ GTK_SIGNAL_FUNC (calendar_next_month),
+ &calendar_data);
+ gtk_signal_connect (GTK_OBJECT (calendar), "prev_year",
+ GTK_SIGNAL_FUNC (calendar_prev_year),
+ &calendar_data);
+ gtk_signal_connect (GTK_OBJECT (calendar), "next_year",
+ GTK_SIGNAL_FUNC (calendar_next_year),
+ &calendar_data);
+
+
+ separator = gtk_vseparator_new ();
+ gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, TRUE, 0);
+
+ vbox2 = gtk_vbox_new(FALSE, DEF_PAD);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox2, FALSE, FALSE, DEF_PAD);
+
+ /* Build the Right frame with the flags in */
+
+ frame = gtk_frame_new("Flags");
+ gtk_box_pack_start(GTK_BOX(vbox2), frame, TRUE, TRUE, DEF_PAD);
+ vbox3 = gtk_vbox_new(TRUE, DEF_PAD_SMALL);
+ gtk_container_add(GTK_CONTAINER(frame), vbox3);
+
+ for (i = 0; i < 5; i++)
+ {
+ toggle = gtk_check_button_new_with_label(flags[i].label);
+ gtk_signal_connect (GTK_OBJECT (toggle),
+ "toggled",
+ GTK_SIGNAL_FUNC(calendar_toggle_flag),
+ &calendar_data);
+ gtk_box_pack_start (GTK_BOX (vbox3), toggle, TRUE, TRUE, 0);
+ calendar_data.flag_checkboxes[i]=toggle;
+ }
+ /* Build the right font-button */
+ button = gtk_button_new_with_label("Font...");
+ gtk_signal_connect (GTK_OBJECT (button),
+ "clicked",
+ GTK_SIGNAL_FUNC(calendar_select_font),
+ &calendar_data);
+ gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
+
+ /*
+ * Build the Signal-event part.
+ */
+
+ frame = gtk_frame_new("Signal events");
+ gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, DEF_PAD);
+
+ vbox2 = gtk_vbox_new(TRUE, DEF_PAD_SMALL);
+ gtk_container_add(GTK_CONTAINER(frame), vbox2);
+
+ hbox = gtk_hbox_new (FALSE, 3);
+ gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
+ label = gtk_label_new ("Signal:");
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+ calendar_data.last_sig = gtk_label_new ("");
+ gtk_box_pack_start (GTK_BOX (hbox), calendar_data.last_sig, FALSE, TRUE, 0);
+
+ hbox = gtk_hbox_new (FALSE, 3);
+ gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
+ label = gtk_label_new ("Previous signal:");
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+ calendar_data.prev_sig = gtk_label_new ("");
+ gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev_sig, FALSE, TRUE, 0);
+
+ hbox = gtk_hbox_new (FALSE, 3);
+ gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
+ label = gtk_label_new ("Second previous signal:");
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
+ calendar_data.prev2_sig = gtk_label_new ("");
+ gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev2_sig, FALSE, TRUE, 0);
+
+ bbox = gtk_hbutton_box_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
+
+ button = gtk_button_new_with_label ("Close");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_main_quit),
+ NULL);
+ gtk_container_add (GTK_CONTAINER (bbox), button);
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_default (button);
+
+ gtk_widget_show_all(window);
+}
+
+
+int main(int argc,
+ char *argv[] )
+{
+ gtk_set_locale ();
+ gtk_init (&argc, &argv);
+
+ create_calendar();
+
+ gtk_main();
+
+ return(0);
+}
+/* example-end */
+</verb></tscreen>
+
+
+
+<!-- ----------------------------------------------------------------- -->
+<sect1> Color Selection
+<p>
+The color selection widget is, not surprisingly, a widget for
+interactive selection of colors. This composite widget lets the user
+select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
+Saturation, Value) triples. This is done either by adjusting single
+values with sliders or entries, or by picking the desired color from a
+hue-saturation wheel/value bar. Optionally, the opacity of the color
+can also be set.
+
+The color selection widget currently emits only one signal,
+"color_changed", which is emitted whenever the current color in the
+widget changes, either when the user changes it or if it's set
+explicitly through gtk_color_selection_set_color().
+
+Lets have a look at what the color selection widget has to offer
+us. The widget comes in two flavours: gtk_color_selection and
+gtk_color_selection_dialog.
+
+<tscreen><verb>
+GtkWidget *gtk_color_selection_new( void );
+</verb></tscreen>
+
+You'll probably not be using this constructor directly. It creates an
+orphan ColorSelection widget which you'll have to parent
+yourself. The ColorSelection widget inherits from the VBox
+widget.
+
+<tscreen><verb>
+GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
+</verb></tscreen>
+
+This is the most common color selection constructor. It creates a
+ColorSelectionDialog. It consists of a Frame containing a
+ColorSelection widget, an HSeparator and an HBox with three buttons,
+"Ok", "Cancel" and "Help". You can reach these buttons by accessing
+the "ok_button", "cancel_button" and "help_button" widgets in the
+ColorSelectionDialog structure,
+(i.e., <tt>GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button</tt>)).
+
+<tscreen><verb>
+void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel,
+ GtkUpdateType policy );
+</verb></tscreen>
+
+This function sets the update policy. The default policy is
+<tt/GTK_UPDATE_CONTINUOUS/ which means that the current color is
+updated continuously when the user drags the sliders or presses the
+mouse and drags in the hue-saturation wheel or value bar. If you
+experience performance problems, you may want to set the policy to
+<tt/GTK_UPDATE_DISCONTINUOUS/ or <tt/GTK_UPDATE_DELAYED/.
+
+<tscreen><verb>
+void gtk_color_selection_set_opacity( GtkColorSelection *colorsel,
+ gint use_opacity );
+</verb></tscreen>
+
+The color selection widget supports adjusting the opacity of a color
+(also known as the alpha channel). This is disabled by
+default. Calling this function with use_opacity set to TRUE enables
+opacity. Likewise, use_opacity set to FALSE will disable opacity.
+
+<tscreen><verb>
+void gtk_color_selection_set_color( GtkColorSelection *colorsel,
+ gdouble *color );
+</verb></tscreen>
+
+You can set the current color explicitly by calling this function with
+a pointer to an array of colors (gdouble). The length of the array
+depends on whether opacity is enabled or not. Position 0 contains the
+red component, 1 is green, 2 is blue and opacity is at position 3
+(only if opacity is enabled, see
+gtk_color_selection_set_opacity()). All values are between 0.0 and
+1.0.
+
+<tscreen><verb>
+void gtk_color_selection_get_color( GtkColorSelection *colorsel,
+ gdouble *color );
+</verb></tscreen>
+
+When you need to query the current color, typically when you've
+received a "color_changed" signal, you use this function. Color is a
+pointer to the array of colors to fill in. See the
+gtk_color_selection_set_color() function for the description of this
+array.
+
+<!-- Need to do a whole section on DnD - TRG
+Drag and drop
+-------------
+
+The color sample areas (right under the hue-saturation wheel) supports
+drag and drop. The type of drag and drop is "application/x-color". The
+message data consists of an array of 4 (or 5 if opacity is enabled)
+gdouble values, where the value at position 0 is 0.0 (opacity on) or
+1.0 (opacity off) followed by the red, green and blue values at
+positions 1,2 and 3 respectively. If opacity is enabled, the opacity
+is passed in the value at position 4.
+-->
+
+Here's a simple example demonstrating the use of the
+ColorSelectionDialog. The program displays a window containing a
+drawing area. Clicking on it opens a color selection dialog, and
+changing the color in the color selection dialog changes the
+background color.
+
+<tscreen><verb>
+/* example-start colorsel colorsel.c */
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+GtkWidget *colorseldlg = NULL;
+GtkWidget *drawingarea = NULL;
+
+/* Color changed handler */
+
+void color_changed_cb( GtkWidget *widget,
+ GtkColorSelection *colorsel )
+{
+ gdouble color[3];
+ GdkColor gdk_color;
+ GdkColormap *colormap;
+
+ /* Get drawingarea colormap */
+
+ colormap = gdk_window_get_colormap (drawingarea->window);
+
+ /* Get current color */
+
+ gtk_color_selection_get_color (colorsel,color);
+
+ /* Fit to a unsigned 16 bit integer (0..65535) and
+ * insert into the GdkColor structure */
gdk_color.red = (guint16)(color[0]*65535.0);
gdk_color.green = (guint16)(color[1]*65535.0);
/* Drawingarea event handler */
-gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data)
+gint area_event( GtkWidget *widget,
+ GdkEvent *event,
+ gpointer client_data )
{
gint handled = FALSE;
GtkWidget *colorsel;
colorseldlg = gtk_color_selection_dialog_new("Select background color");
- /* Get the GtkColorSelection widget */
+ /* Get the ColorSelection widget */
colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;
/* Close down and exit handler */
-void destroy_window (GtkWidget *widget, gpointer client_data)
+gint destroy_window( GtkWidget *widget,
+ GdkEvent *event,
+ gpointer client_data )
{
gtk_main_quit ();
+ return(TRUE);
}
/* Main */
-gint main (gint argc, gchar *argv[])
+gint main( gint argc,
+ gchar *argv[] )
{
GtkWidget *window;
gtk_signal_connect (GTK_OBJECT(window), "delete_event",
(GtkSignalFunc)destroy_window, (gpointer)window);
-
- gtk_signal_connect (GTK_OBJECT(window), "destroy",
- (GtkSignalFunc)destroy_window, (gpointer)window);
/* Create drawingarea, set size and catch button events */
There are also pointers to the widgets contained within the file
selection widget. These are:
-<itemize>
-<item>dir_list
-<item>file_list
-<item>selection_entry
-<item>selection_text
-<item>main_vbox
-<item>ok_button
-<item>cancel_button
-<item>help_button
-</itemize>
-
+<tscreen><verb>
+ dir_list
+ file_list
+ selection_entry
+ selection_text
+ main_vbox
+ ok_button
+ cancel_button
+ help_button
+</verb></tscreen>
+
Most likely you will want to use the ok_button, cancel_button, and
help_button pointers in signaling their use.
#include <gtk/gtk.h>
/* Get the selected filename and print it to the console */
-void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
+void file_ok_sel( GtkWidget *w,
+ GtkFileSelection *fs )
{
g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
}
-void destroy (GtkWidget *widget, gpointer data)
+void destroy( GtkWidget *widget,
+ gpointer data )
{
gtk_main_quit ();
}
-int main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *filew;
Some GTK widgets don't have associated X windows, so they just draw on
their parents. Because of this, they cannot receive events and if they
are incorrectly sized, they don't clip so you can get messy
-overwriting etc. If you require more from these widgets, the EventBox
+overwriting, etc. If you require more from these widgets, the EventBox
is for you.
At first glance, the EventBox widget might appear to be totally
#include <gtk/gtk.h>
-int
-main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
GtkWidget *event_box;
All four alignment parameters are floating point numbers which can
range from 0.0 to 1.0. The <tt/xalign/ and <tt/yalign/ arguments
affect the position of the widget placed within the Alignment
-widget. The <tt/xscale/ and <tt/yscale/ arguments effect the amount of
+widget. The <tt/xscale/ and <tt/yscale/ arguments affect the amount of
space allocated to the widget.
A child widget can be added to this Alignment widget using:
<sect1> Fixed Container
<p>
The Fixed container allows you to place widgets at a fixed position
-within it's window, relative to it's upper left hand corner. The
+within its window, relative to its upper left hand corner. The
position of the widgets can be changed dynamically.
There are only three functions associated with the fixed widget:
button = gtk_button_new_with_label ("Press me");
/* When the button receives the "clicked" signal, it will call the
- * function move_button() passing it the Fixed Containter as its
+ * function move_button() passing it the Fixed Container as its
* argument. */
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC (move_button), fixed);
<p>
The Layout container is similar to the Fixed container except that it
implements an infinite (where infinity is less than 2^32) scrolling
-area. Xwindows has a limitation where windows can be at most 32767
-pixels wide or tall. The Layout container gets around this limitation
-by doing some exotic stuff using window and bit gravities, so that you
-can have smooth scrolling even when you have many child widgets in
-your scrolling area.
+area. The X window system has a limitation where windows can be at
+most 32767 pixels wide or tall. The Layout container gets around this
+limitation by doing some exotic stuff using window and bit gravities,
+so that you can have smooth scrolling even when you have many child
+widgets in your scrolling area.
A Layout container is created using:
</verb></tscreen>
As you can see, you can optionally specify the Adjustment objects that
-the Layout widget will use for it's scrolling.
+the Layout widget will use for its scrolling.
You can add and move widgets in the Layout container using the
following two functions:
</verb></tscreen>
The <tt/type/ argument can take one of the following values:
-<itemize>
-<item> GTK_SHADOW_NONE
-<item> GTK_SHADOW_IN
-<item> GTK_SHADOW_OUT
-<item> GTK_SHADOW_ETCHED_IN (the default)
-<item> GTK_SHADOW_ETCHED_OUT
-</itemize>
+<tscreen><verb>
+ GTK_SHADOW_NONE
+ GTK_SHADOW_IN
+ GTK_SHADOW_OUT
+ GTK_SHADOW_ETCHED_IN (the default)
+ GTK_SHADOW_ETCHED_OUT
+</verb></tscreen>
The following code example illustrates the use of the Frame widget.
frame = gtk_frame_new(NULL);
gtk_container_add(GTK_CONTAINER(window), frame);
- /* Set the frames label */
+ /* Set the frame's label */
gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" );
/* Align the label at the right of the frame */
#include <gtk/gtk.h>
-int
-main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
GtkWidget *aspect_frame;
<tscreen><verb>
/* example-start paned paned.c */
+#include <stdio.h>
#include <gtk/gtk.h>
/* Create the list of "messages" */
-GtkWidget *
-create_list (void)
+GtkWidget *create_list( void )
{
GtkWidget *scrolled_window;
realized with gtk_widget_realize, but it would have to be part of
a hierarchy first */
-void
-realize_text (GtkWidget *text, gpointer data)
+void realize_text( GtkWidget *text,
+ gpointer data )
{
gtk_text_freeze (GTK_TEXT (text));
gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL,
}
/* Create a scrolled text area that displays a "message" */
-GtkWidget *
-create_text (void)
+GtkWidget *create_text( void )
{
GtkWidget *table;
GtkWidget *text;
return table;
}
-int
-main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
GtkWidget *vpaned;
<p>
It is unlikely that you will ever need to use the Viewport widget
directly. You are much more likely to use the
-<ref id="sec_ScrolledWindows" name="Scrolled Windows"> widget which
+<ref id="sec_ScrolledWindow" name="Scrolled Window"> widget which
itself uses the Viewport.
A viewport widget allows you to place a larger widget within it such
As you can see you can specify the horizontal and vertical Adjustments
that the widget is to use when you create the widget. It will create
-it's own if you pass NULL as the value of the arguments.
+its own if you pass NULL as the value of the arguments.
You can get and set the adjustments after the widget has been created
using the following four functions:
</verb></tscreen>
Possible values for the <tt/type/ parameter are:
-<itemize>
-<item> GTK_SHADOW_NONE,
-<item> GTK_SHADOW_IN,
-<item> GTK_SHADOW_OUT,
-<item> GTK_SHADOW_ETCHED_IN,
-<item> GTK_SHADOW_ETCHED_OUT
-</itemize>
-
+<tscreen><verb>
+ GTK_SHADOW_NONE,
+ GTK_SHADOW_IN,
+ GTK_SHADOW_OUT,
+ GTK_SHADOW_ETCHED_IN,
+ GTK_SHADOW_ETCHED_OUT
+</verb></tscreen>
+
<!-- ----------------------------------------------------------------- -->
-<sect1>Scrolled Windows <label id="sec_ScrolledWindows">
+<sect1>Scrolled Windows <label id="sec_ScrolledWindow">
<p>
-Scrolled windows are used to create a scrollable area inside a real
-window. You may insert any type of widget into a scrolled window, and
-it will be accessible regardless of the size by using the scrollbars.
+Scrolled windows are used to create a scrollable area with another
+widget inside it. You may insert any type of widget into a scrolled
+window, and it will be accessible regardless of the size by using the
+scrollbars.
The following function is used to create a new scrolled window.
sets the policy for the horizontal scrollbar, and the third the policy for
the vertical scrollbar.
-The policy may be one of GTK_POLICY_AUTOMATIC, or GTK_POLICY_ALWAYS.
-GTK_POLICY_AUTOMATIC will automatically decide whether you need
-scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
-there.
+The policy may be one of <tt/GTK_POLICY_AUTOMATIC/ or
+<tt/GTK_POLICY_ALWAYS/. <tt/GTK_POLICY_AUTOMATIC/ will automatically
+decide whether you need scrollbars, whereas <tt/GTK_POLICY_ALWAYS/
+will always leave the scrollbars there.
You can then place your object into the scrolled window using the
following function.
GtkWidget *child);
</verb></tscreen>
-Here is a simple example that packs 100 toggle buttons into a scrolled
-window. I've only commented on the parts that may be new to you.
+Here is a simple example that packs a table eith 100 toggle buttons
+into a scrolled window. I've only commented on the parts that may be
+new to you.
<tscreen><verb>
/* example-start scrolledwin scrolledwin.c */
+#include <stdio.h>
#include <gtk/gtk.h>
-void destroy(GtkWidget *widget, gpointer data)
+void destroy( GtkWidget *widget,
+ gpointer data )
{
gtk_main_quit();
}
-int main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
static GtkWidget *window;
GtkWidget *scrolled_window;
gtk_init (&argc, &argv);
/* Create a new dialog window for the scrolled window to be
- * packed into. A dialog is just like a normal window except it has a
- * vbox and a horizontal separator packed into it. It's just a shortcut
- * for creating dialogs */
+ * packed into. */
window = gtk_dialog_new ();
gtk_signal_connect (GTK_OBJECT (window), "destroy",
(GtkSignalFunc) destroy, NULL);
GtkWidget *gtk_vbutton_box_new( void );
</verb></tscreen>
-The only attributes pertaining to button boxes effect how the buttons
-are layed out. You can change the spacing between the buttons with:
+The only attributes pertaining to button boxes affect how the buttons
+are laid out. You can change the spacing between the buttons with:
<tscreen><verb>
void gtk_hbutton_box_set_spacing_default( gint spacing );
gint gtk_vbutton_box_get_spacing_default( void );
</verb></tscreen>
-The second attribute that we can access effects the layour of the
+The second attribute that we can access affects the layout of the
buttons within the box. It is set using one of:
<tscreen><verb>
The <tt/layout/ argument can take one of the following values:
-<itemize>
-<item> GTK_BUTTONBOX_DEFAULT_STYLE
-<item> GTK_BUTTONBOX_SPREAD
-<item> GTK_BUTTONBOX_EDGE
-<item> GTK_BUTTONBOX_START
-<item> GTK_BUTTONBOX_END
-</itemize>
+<tscreen><verb>
+ GTK_BUTTONBOX_DEFAULT_STYLE
+ GTK_BUTTONBOX_SPREAD
+ GTK_BUTTONBOX_EDGE
+ GTK_BUTTONBOX_START
+ GTK_BUTTONBOX_END
+</verb></tscreen>
The current layout setting can be retrieved using:
#include <gtk/gtk.h>
/* Create a Button Box with the specified parameters */
-GtkWidget *create_bbox (gint horizontal,
- char* title,
- gint spacing,
- gint child_w,
- gint child_h,
- gint layout)
+GtkWidget *create_bbox( gint horizontal,
+ char *title,
+ gint spacing,
+ gint child_w,
+ gint child_h,
+ gint layout )
{
GtkWidget *frame;
GtkWidget *bbox;
consists of buttons with icons, labels and tooltips, but any other
widget can also be put inside a toolbar. Finally, items can be
arranged horizontally or vertically and buttons can be displayed with
-icons, labels or both.
+icons, labels, or both.
Creating a toolbar is (as one may already suspect) done with the
following function:
(not to buttons inserted into toolbar as separate widgets).
After creating a toolbar one can append, prepend and insert items
-(that means simple buttons) into the toolbar. To describe an item we
-need a label text, a tooltip text, a private tooltip text, an icon for
-the button and a callback function for it. For example, to append or
-prepend an item you may use the following functions:
+(that means simple text strings) or elements (that means any widget
+types) into the toolbar. To describe an item we need a label text, a
+tooltip text, a private tooltip text, an icon for the button and a
+callback function for it. For example, to append or prepend an item
+you may use the following functions:
<tscreen><verb>
GtkWidget *gtk_toolbar_append_item( GtkToolbar *toolbar,
</verb></tscreen>
If it's required, the orientation of a toolbar and its style can be
-changed `on the fly' using the following functions:
+changed "on the fly" using the following functions:
<tscreen><verb>
void gtk_toolbar_set_orientation( GtkToolbar *toolbar,
gint enable );
</verb></tscreen>
-Where <tt/orientation/ is one of GTK_ORIENTATION_HORIZONTAL or
-GTK_ORIENTATION_VERTICAL. The <tt/style/ is used to set appearance of
-the toolbar items by using one of GTK_TOOLBAR_ICONS, GTK_TOOLBAR_TEXT
-or GTK_TOOLBAR_BOTH.
+Where <tt/orientation/ is one of <tt/GTK_ORIENTATION_HORIZONTAL/ or
+<tt/GTK_ORIENTATION_VERTICAL/. The <tt/style/ is used to set
+appearance of the toolbar items by using one of
+<tt/GTK_TOOLBAR_ICONS/, <tt/GTK_TOOLBAR_TEXT/, or
+<tt/GTK_TOOLBAR_BOTH/.
To show some other things that can be done with a toolbar, let's take
the following program (we'll interrupt the listing with some
/* This function is connected to the Close button or
* closing the window from the WM */
-void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
+gint delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
{
gtk_main_quit ();
+ return(FALSE);
}
</verb></tscreen>
</verb></tscreen>
The above should be similar to any other GTK application. Just
-initialization of GTK, creating the window etc.. There is only one
+initialization of GTK, creating the window, etc. There is only one
thing that probably needs some explanation: a handle box. A handle box
is just another box that can be used to pack widgets in to. The
difference between it and typical boxes is that it can be detached
&dialog->style->white, gtk_xpm );
</verb></tscreen>
-Well, what we do above is just a straight-forward initialization of
+Well, what we do above is just a straightforward initialization of
the toolbar widget and creation of a GDK pixmap with its mask. If you
want to know something more about using pixmaps, refer to GDK
documentation or to the <ref id="sec_Pixmaps" name="Pixmaps"> section
Here we begin creating a radio buttons group. To do this we use
gtk_toolbar_append_element. In fact, using this function one can also
-add simple items or even spaces (type = GTK_TOOLBAR_CHILD_SPACE or
-GTK_TOOLBAR_CHILD_BUTTON). In the above case we start creating a radio
-group. In creating other radio buttons for this group a pointer to the
-previous button in the group is required, so that a list of buttons
-can be easily constructed (see the section on <ref
++add simple items or even spaces (type = <tt/GTK_TOOLBAR_CHILD_SPACE/
+or +<tt/GTK_TOOLBAR_CHILD_BUTTON/). In the above case we start
+creating a radio group. In creating other radio buttons for this group
+a pointer to the previous button in the group is required, so that a
+list of buttons can be easily constructed (see the section on <ref
id="sec_Radio_Buttons" name="Radio Buttons"> earlier in this
tutorial).
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_button),TRUE);
</verb></tscreen>
-In the end we have set the state of one of the buttons manually (otherwise
-they all stay in active state, preventing us from switching between them).
+In the end we have to set the state of one of the buttons manually
+(otherwise they all stay in active state, preventing us from switching
+between them).
<tscreen><verb>
/* here we have just a simple toggle button */
<!-- ----------------------------------------------------------------- -->
<sect1> Notebooks
<p>
-The NoteBook Widget is a collection of 'pages' that overlap each
-other, each page contains different information. This widget has
-become more common lately in GUI programming, and it is a good way to
-show blocks of similar information that warrant separation in their
-display.
+The NoteBook Widget is a collection of "pages" that overlap each
+other, each page contains different information with only one page
+visible at a time. This widget has become more common lately in GUI
+programming, and it is a good way to show blocks of similar
+information that warrant separation in their display.
The first function call you will need to know, as you can probably
guess by now, is used to create a new notebook widget.
that operate on the notebook widget. Let's look at them individually.
The first one we will look at is how to position the page indicators.
-These page indicators or 'tabs' as they are referred to, can be
+These page indicators or "tabs" as they are referred to, can be
positioned in four ways: top, bottom, left, or right.
<tscreen><verb>
GtkPositionType pos );
</verb></tscreen>
-GtkPostionType will be one of the following, which are pretty self
+GtkPositionType will be one of the following, which are pretty self
explanatory:
-<itemize>
-<item> GTK_POS_LEFT
-<item> GTK_POS_RIGHT
-<item> GTK_POS_TOP
-<item> GTK_POS_BOTTOM
-</itemize>
+<tscreen><verb>
+ GTK_POS_LEFT
+ GTK_POS_RIGHT
+ GTK_POS_TOP
+ GTK_POS_BOTTOM
+</verb></tscreen>
-GTK_POS_TOP is the default.
+<tt/GTK_POS_TOP/ is the default.
Next we will look at how to add pages to the notebook. There are three
ways to add pages to the NoteBook. Let's look at the first two
<tt/child/ is the widget that is placed within the notebook page, and
<tt/tab_label/ is the label for the page being added. The <tt/child/
widget must be created separately, and is typically a set of options
-setout witin one of the other container widgets, such as a table.
+setup witin one of the other container widgets, such as a table.
The final function for adding a page to the notebook contains all of
the properties of the previous two, but it allows you to specify what
The parameters are the same as _append_ and _prepend_ except it
contains an extra parameter, <tt/position/. This parameter is used to
-specify what place this page will be inserted into.
+specify what place this page will be inserted into the first page
+having position zero.
Now that we know how to add a page, lets see how we can remove a page
from the notebook.
These next two functions are simple calls to move the notebook page
forward or backward. Simply provide the respective function call with
-the notebook widget you wish to operate on. Note: when the NoteBook is
+the notebook widget you wish to operate on. Note: When the NoteBook is
currently on the last page, and gtk_notebook_next_page is called, the
notebook will wrap back to the first page. Likewise, if the NoteBook
is on the first page, and gtk_notebook_prev_page is called, the
void gtk_notebook_prev_page( GtkNoteBook *notebook );
</verb></tscreen>
-This next function sets the 'active' page. If you wish the notebook to
+This next function sets the "active" page. If you wish the notebook to
be opened to page 5 for example, you would use this function. Without
using this function, the notebook defaults to the first page.
<tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
TRUE or FALSE.
-Now lets look at an example, it is expanded from the testgtk.c code
+Now let's look at an example, it is expanded from the testgtk.c code
that comes with the GTK distribution. This small program creates a
window with a notebook and six buttons. The notebook contains 11
pages, added in three different ways, appended, inserted, and
<tscreen><verb>
/* example-start notebook notebook.c */
+#include <stdio.h>
#include <gtk/gtk.h>
/* This function rotates the position of the tabs */
-void rotate_book (GtkButton *button, GtkNotebook *notebook)
+void rotate_book( GtkButton *button,
+ GtkNotebook *notebook )
{
gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
}
/* Add/Remove the page tabs and the borders */
-void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
+void tabsborder_book( GtkButton *button,
+ GtkNotebook *notebook )
{
gint tval = FALSE;
gint bval = FALSE;
}
/* Remove a page from the notebook */
-void remove_book (GtkButton *button, GtkNotebook *notebook)
+void remove_book( GtkButton *button,
+ GtkNotebook *notebook )
{
gint page;
gtk_widget_draw(GTK_WIDGET(notebook), NULL);
}
-void delete (GtkWidget *widget, GtkWidget *event, gpointer data)
+gint delete( GtkWidget *widget,
+ GtkWidget *event,
+ gpointer data )
{
- gtk_main_quit ();
+ gtk_main_quit();
+ return(FALSE);
}
-int main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
GtkWidget *button;
gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
gtk_widget_show(notebook);
- /* Lets append a bunch of pages to the notebook */
+ /* Let's append a bunch of pages to the notebook */
for (i=0; i < 5; i++) {
sprintf(bufferf, "Append Frame %d", i+1);
sprintf(bufferl, "Page %d", i+1);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
}
- /* Now lets add a page to a specific spot */
+ /* Now let's add a page to a specific spot */
checkbutton = gtk_check_button_new_with_label ("Check me please!");
gtk_widget_set_usize(checkbutton, 100, 75);
gtk_widget_show (checkbutton);
label = gtk_label_new ("Add page");
gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
- /* Now finally lets prepend pages to the notebook */
+ /* Now finally let's prepend pages to the notebook */
for (i=0; i < 5; i++) {
sprintf(bufferf, "Prepend Frame %d", i+1);
sprintf(bufferl, "PPage %d", i+1);
/* example-end */
</verb></tscreen>
-Hopefully this helps you on your way with creating notebooks for your
+I hope this helps you on your way with creating notebooks for your
GTK applications.
<!-- ***************************************************************** -->
<!-- ----------------------------------------------------------------- -->
<p>
-The GtkCList widget has replaced the GtkList widget (which is still
+The CList widget has replaced the List widget (which is still
available).
-The GtkCList widget is a multi-column list widget that is capable of
+The CList widget is a multi-column list widget that is capable of
handling literally thousands of rows of information. Each column can
optionally have a title, which itself is optionally active, allowing
us to bind a function to its selection.
<!-- ----------------------------------------------------------------- -->
-<sect1>Creating a GtkCList widget
+<sect1>Creating a CList widget
<p>
-Creating a GtkCList is quite straightforward, once you have learned
+Creating a CList is quite straightforward, once you have learned
about widgets in general. It provides the almost standard two ways,
that is the hard way, and the easy way. But before we create it, there
is one thing we should figure out beforehand: how many columns should
gchar *titles[] );
</verb></tscreen>
-The first form is very straight forward, the second might require some
+The first form is very straightforward, the second might require some
explanation. Each column can have a title associated with it, and this
title can be a label or a button that reacts when we click on it. If
we use the second form, we must provide pointers to the title texts,
specified. Of course we can always use the first form, and manually
add titles later.
-Note: the GtkCList widget does not have its own scrollbars and should
-be placed within a GtkScrolledWindow widget if your require this
+Note: The CList widget does not have its own scrollbars and should
+be placed within a ScrolledWindow widget if your require this
functionality. This is a change from the GTK 1.0 implementation.
<!-- ----------------------------------------------------------------- -->
<sect1>Modes of operation
<p>
There are several attributes that can be used to alter the behaviour of
-a GtkCList. First there is
+a CList. First there is
<tscreen><verb>
void gtk_clist_set_selection_mode( GtkCList *clist,
</verb></tscreen>
which, as the name implies, sets the selection mode of the
-GtkCList. The first argument is the GtkCList widget, and the second
+CList. The first argument is the CList widget, and the second
specifies the cell selection mode (they are defined in gtkenums.h). At
the time of this writing, the following modes are available to us:
<itemize>
-<item> GTK_SELECTION_SINGLE - The selection is either NULL or contains
+<item> <tt/GTK_SELECTION_SINGLE/ - The selection is either NULL or contains
a GList pointer for a single selected item.
-<item> GTK_SELECTION_BROWSE - The selection is NULL if the list
+<item> <tt/GTK_SELECTION_BROWSE/ - The selection is NULL if the list
contains no widgets or insensitive ones only, otherwise it contains a
GList pointer for one GList structure, and therefore exactly one list
item.
-<item> GTK_SELECTION_MULTIPLE - The selection is NULL if no list items
+<item> <tt/GTK_SELECTION_MULTIPLE/ - The selection is NULL if no list items
are selected or a GList pointer for the first selected item. That in
turn points to a GList structure for the second selected item and so
-on. This is currently the <bf>default</bf> for the GtkCList widget.
+on. This is currently the <bf>default</bf> for the CList widget.
-<item> GTK_SELECTION_EXTENDED - The selection is always NULL.
+<item> <tt/GTK_SELECTION_EXTENDED/ - The selection is always NULL.
</itemize>
Others might be added in later revisions of GTK.
-We can also define what the border of the GtkCList widget should look
+We can also define what the border of the CList widget should look
like. It is done through
<tscreen><verb>
GtkShadowType border );
</verb></tscreen>
-And the possible values for the second argument are
-
-<itemize>
-<item> GTK_SHADOW_NONE
-
-<item> GTK_SHADOW_IN
-
-<item> GTK_SHADOW_OUT
+The possible values for the second argument are
-<item> GTK_SHADOW_ETCHED_IN
-
-<item> GTK_SHADOW_ETCHED_OUT
-</itemize>
+<tscreen><verb>
+ GTK_SHADOW_NONE
+ GTK_SHADOW_IN
+ GTK_SHADOW_OUT
+ GTK_SHADOW_ETCHED_IN
+ GTK_SHADOW_ETCHED_OUT
+</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
<sect1>Working with titles
<p>
-When you create a GtkCList widget, you will also get a set of title
+When you create a CList widget, you will also get a set of title
buttons automatically. They live in the top of the CList window, and
can act either as normal buttons that respond to being pressed, or
they can be passive, in which case they are nothing more than a
Note that only the title of one column can be set at a time, so if all
the titles are known from the beginning, then I really suggest using
-gtk_clist_new_with_titles (as described above) to set them. Saves you
-coding time, and makes your program smaller. There are some cases
+gtk_clist_new_with_titles (as described above) to set them. It saves
+you coding time, and makes your program smaller. There are some cases
where getting the job done the manual way is better, and that's when
-not all titles will be text. GtkCList provides us with title buttons
+not all titles will be text. CList provides us with title buttons
that can in fact incorporate whole widgets, for example a pixmap. It's
all done through
The GtkJustification type can take the following values:
<itemize>
-<item>GTK_JUSTIFY_LEFT - The text in the column will begin from the
+<item><tt/GTK_JUSTIFY_LEFT/ - The text in the column will begin from the
left edge.
-<item>GTK_JUSTIFY_RIGHT - The text in the column will begin from the
+<item><tt/GTK_JUSTIFY_RIGHT/ - The text in the column will begin from the
right edge.
-<item>GTK_JUSTIFY_CENTER - The text is placed in the center of the
+<item><tt/GTK_JUSTIFY_CENTER/ - The text is placed in the center of the
column.
-<item>GTK_JUSTIFY_FILL - The text will use up all available space in
+<item><tt/GTK_JUSTIFY_FILL/ - The text will use up all available space in
the column. It is normally done by inserting extra blank spaces
between words (or between individual letters if it's a single
word). Much in the same way as any ordinary WYSIWYG text editor.
</itemize>
The next function is a very important one, and should be standard in
-the setup of all GtkCList widgets. When the list is created, the width
+the setup of all CList widgets. When the list is created, the width
of the various columns are chosen to match their titles, and since
this is seldom the right width we have to set it using
The return value is is one of the following:
-<itemize>
-<item>GTK_VISIBILITY_NONE
-
-<item>GTK_VISIBILITY_PARTIAL
-
-<item>GTK_VISIBILITY_FULL
-</itemize>
+<tscreen><verb>
+ GTK_VISIBILITY_NONE
+ GTK_VISIBILITY_PARTIAL
+ GTK_VISIBILITY_FULL
+</verb></tscreen>
Note that it will only tell us if a row is visible. Currently there is
no way to determine this for a column. We can get partial information
-though, because if the return is GTK_VISIBILITY_PARTIAL, then some of
-it is hidden, but we don't know if it is the row that is being cut by
-the lower edge of the listbox, or if the row has columns that are
-outside.
+though, because if the return is <tt/GTK_VISIBILITY_PARTIAL/, then
+some of it is hidden, but we don't know if it is the row that is being
+cut by the lower edge of the listbox, or if the row has columns that
+are outside.
We can also change both the foreground and background colors of a
particular row. This is useful for marking the row selected by the
functions are used.
<tscreen><verb>
-void gtk_clist_set_text( GtkCList *clist,
- gint row,
- gint column,
- gchar *text );
+void gtk_clist_set_text( GtkCList *clist,
+ gint row,
+ gint column,
+ const gchar *text );
void gtk_clist_set_pixmap( GtkCList *clist,
gint row,
GdkBitmap *mask );
</verb></tscreen>
-It's quite straightforward. All the calls have the GtkCList as the
-first argument, followed by the row and column of the cell, followed
-by the data to be set. The <tt/spacing/ argument in
-gtk_clist_set_pixtext is the number of pixels between the pixmap and
-the beginning of the text.
+It's quite straightforward. All the calls have the CList as the first
+argument, followed by the row and column of the cell, followed by the
+data to be set. The <tt/spacing/ argument in gtk_clist_set_pixtext is
+the number of pixels between the pixmap and the beginning of the
+text. In all cases the data is copied into the widget.
To read back the data, we instead use
GdkBitmap **mask );
</verb></tscreen>
-It isn't necessary to read it all back in case you aren't
-interested. Any of the pointers that are meant for return values (all
-except the clist) can be NULL. So if we want to read back only the
-text from a cell that is of type pixtext, then we would do the
-following, assuming that clist, row and column already exist:
+The returned pointers are all pointers to the data stored within the
+widget, so the referenced data should not be modified or released. It
+isn't necessary to read it all back in case you aren't interested. Any
+of the pointers that are meant for return values (all except the
+clist) can be NULL. So if we want to read back only the text from a
+cell that is of type pixtext, then we would do the following, assuming
+that clist, row and column already exist:
<tscreen><verb>
gchar *mytext;
which returns the type of data in a cell. The return value is one of
-<itemize>
-<item>GTK_CELL_EMPTY
-
-<item>GTK_CELL_TEXT
-
-<item>GTK_CELL_PIXMAP
-
-<item>GTK_CELL_PIXTEXT
-
-<item>GTK_CELL_WIDGET
-</itemize>
+<tscreen><verb>
+ GTK_CELL_EMPTY
+ GTK_CELL_TEXT
+ GTK_CELL_PIXMAP
+ GTK_CELL_PIXTEXT
+ GTK_CELL_WIDGET
+</verb></tscreen>
There is also a function that will let us set the indentation, both
vertical and horizontal, of a cell. The indentation value is of type
<!-- ----------------------------------------------------------------- -->
<sect1>Storing data pointers
<p>
-With a GtkCList it is possible to set a data pointer for a row. This
+With a CList it is possible to set a data pointer for a row. This
pointer will not be visible for the user, but is merely a convenience
for the programmer to associate a row with a pointer to some
additional data.
-The functions should be fairly self-explanatory by now
+The functions should be fairly self-explanatory by now.
<tscreen><verb>
void gtk_clist_set_row_data( GtkCList *clist,
gint *column );
</verb></tscreen>
-When we detect something of interest, it might be movement of the
-pointer, a click somewhere in the list, we can read the pointer
+When we detect something of interest (it might be movement of the
+pointer, a click somewhere in the list) we can read the pointer
coordinates and find out where in the list the pointer is. Cumbersome?
Luckily, there is a simpler way...
<sect1>The signals that bring it together
<p>
As with all other widgets, there are a few signals that can be used. The
-GtkCList widget is derived from the GtkContainer widget, and so has all the
-same signals, but also the adds following:
+CList widget is derived from the Container widget, and so has all the
+same signals, but also adds the following:
<itemize>
<item>select_row - This signal will send the following information, in
gpointer data);
</verb></tscreen>
-The callback is connected as usual with
+The callback is connected as usual with
+
+<tscreen><verb>
+gtk_signal_connect(GTK_OBJECT( clist),
+ "select_row"
+ GTK_SIGNAL_FUNC(select_row_callback),
+ NULL);
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>A CList example
+<p>
+
+<tscreen><verb>
+/* example-start clist clist.c */
+
+#include <gtk/gtk.h>
+
+/* User clicked the "Add List" button. */
+void button_add_clicked( gpointer data )
+{
+ int indx;
+
+ /* Something silly to add to the list. 4 rows of 2 columns each */
+ gchar *drink[4][2] = { { "Milk", "3 Oz" },
+ { "Water", "6 l" },
+ { "Carrots", "2" },
+ { "Snakes", "55" } };
+
+ /* Here we do the actual adding of the text. It's done once for
+ * each row.
+ */
+ for ( indx=0 ; indx < 4 ; indx++ )
+ gtk_clist_append( (GtkCList *) data, drink[indx]);
+
+ return;
+}
+
+/* User clicked the "Clear List" button. */
+void button_clear_clicked( gpointer data )
+{
+ /* Clear the list using gtk_clist_clear. This is much faster than
+ * calling gtk_clist_remove once for each row.
+ */
+ gtk_clist_clear( (GtkCList *) data);
+
+ return;
+}
-<tscreen><verb>
-gtk_signal_connect(GTK_OBJECT( clist),
- "select_row"
- GTK_SIGNAL_FUNC(select_row_callback),
- NULL);
-</verb></tscreen>
+/* The user clicked the "Hide/Show titles" button. */
+void button_hide_show_clicked( gpointer data )
+{
+ /* Just a flag to remember the status. 0 = currently visible */
+ static short int flag = 0;
-<!-- ----------------------------------------------------------------- -->
-<sect1>A GtkCList example
-<p>
+ if (flag == 0)
+ {
+ /* Hide the titles and set the flag to 1 */
+ gtk_clist_column_titles_hide((GtkCList *) data);
+ flag++;
+ }
+ else
+ {
+ /* Show the titles and reset flag to 0 */
+ gtk_clist_column_titles_show((GtkCList *) data);
+ flag--;
+ }
-<tscreen><verb>
-/* example-start clist clist.c */
+ return;
+}
-#include <gtk/gtk.h>
-#include <glib.h>
+/* If we come here, then the user has selected a row in the list. */
+void selection_made( GtkWidget *clist,
+ gint row,
+ gint column,
+ GdkEventButton *event,
+ gpointer data )
+{
+ gchar *text;
+
+ /* Get the text that is stored in the selected row and column
+ * which was clicked in. We will receive it as a pointer in the
+ * argument text.
+ */
+ gtk_clist_get_text(GTK_CLIST(clist), row, column, &text);
-/* These are just the prototypes of the various callbacks */
-void button_add_clicked( GtkWidget *button, gpointer data);
-void button_clear_clicked( GtkWidget *button, gpointer data);
-void button_hide_show_clicked( GtkWidget *button, gpointer data);
-void selection_made( GtkWidget *clist, gint row, gint column,
- GdkEventButton *event, gpointer data);
+ /* Just prints some information about the selected row */
+ g_print("You selected row %d. More specifically you clicked in "
+ "column %d, and the text in this cell is %s\n\n",
+ row, column, text);
+
+ return;
+}
-gint main (int argc, gchar *argv[])
+int main( int argc,
+ gchar *argv[] )
{
- GtkWidget *window;
- GtkWidget *vbox, *hbox;
- GtkWidget *clist;
- GtkWidget *button_add, *button_clear, *button_hide_show;
- gchar *titles[2] = {"Ingredients","Amount"};
+ GtkWidget *window;
+ GtkWidget *vbox, *hbox;
+ GtkWidget *scrolled_window, *clist;
+ GtkWidget *button_add, *button_clear, *button_hide_show;
+ gchar *titles[2] = { "Ingredients", "Amount" };
gtk_init(&argc, &argv);
-
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show(vbox);
- /* Create the GtkCList. For this example we use 2 columns */
+ /* Create a scrolled window to pack the CList widget into */
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+
+ gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);
+ gtk_widget_show (scrolled_window);
+
+ /* Create the CList. For this example we use 2 columns */
clist = gtk_clist_new_with_titles( 2, titles);
/* When a selection is made, we want to know about it. The callback
*/
gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
- /* Add the GtkCList widget to the vertical box and show it. */
- gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
+ /* Add the CList widget to the vertical box and show it. */
+ gtk_container_add(GTK_CONTAINER(scrolled_window), clist);
gtk_widget_show(clist);
/* Create the buttons and add them to the window. See the button
return(0);
}
-
-/* User clicked the "Add List" button. */
-void button_add_clicked( GtkWidget *button, gpointer data)
-{
- int indx;
-
- /* Something silly to add to the list. 4 rows of 2 columns each */
- gchar *drink[4][2] = {{"Milk", "3 Oz"},
- {"Water", "6 l"},
- {"Carrots", "2"},
- {"Snakes", "55"}};
-
- /* Here we do the actual adding of the text. It's done once for
- * each row.
- */
- for( indx=0; indx < 4; indx++)
- gtk_clist_append( (GtkCList*) data, drink[indx]);
-
- return;
-}
-
-/* User clicked the "Clear List" button. */
-void button_clear_clicked( GtkWidget *button, gpointer data)
-{
- /* Clear the list using gtk_clist_clear. This is much faster than
- * calling gtk_clist_remove once for each row.
- */
- gtk_clist_clear((GtkCList*) data);
-
- return;
-}
-
-/* The user clicked the "Hide/Show titles" button. */
-void button_hide_show_clicked( GtkWidget *button, gpointer data)
-{
- /* Just a flag to remember the status. 0 = currently visible */
- static short int flag = 0;
-
- if (flag == 0)
- {
- /* Hide the titles and set the flag to 1 */
- gtk_clist_column_titles_hide((GtkCList*) data);
- flag++;
- }
- else
- {
- /* Show the titles and reset flag to 0 */
- gtk_clist_column_titles_show((GtkCList*) data);
- flag--;
- }
-
- return;
-}
-
-/* If we come here, then the user has selected a row in the list. */
-void selection_made( GtkWidget *clist, gint row, gint column,
- GdkEventButton *event, gpointer data)
-{
- gchar *text;
-
- /* Get the text that is stored in the selected row and column
- * which was clicked in. We will receive it as a pointer in the
- * argument text.
- */
- gtk_clist_get_text(GTK_CLIST(clist), row, column, &text);
-
- /* Just prints some information about the selected row */
- g_print("You selected row %d. More specifically you clicked in column %d, and the text in this cell is %s\n\n", row, column, text);
-
- return;
-}
/* example-end */
</verb></tscreen>
<!-- ***************************************************************** -->
<p>
The purpose of tree widgets is to display hierarchically-organized
-data. The GtkTree widget itself is a vertical container for widgets of
-type GtkTreeItem. GtkTree itself is not terribly different from
-GtkList - both are derived directly from GtkContainer, and the
-GtkContainer methods work in the same way on GtkTree widgets as on
-GtkList widgets. The difference is that GtkTree widgets can be nested
-within other GtkTree widgets. We'll see how to do this shortly.
-
-The GtkTree widget has its own window, and defaults to a white
-background, as does GtkList. Also, most of the GtkTree methods work in
-the same way as the corresponding GtkList ones. However, GtkTree is
-not derived from GtkList, so you cannot use them interchangeably.
+data. The Tree widget itself is a vertical container for widgets of
+type TreeItem. Tree itself is not terribly different from
+CList - both are derived directly from Container, and the
+Container methods work in the same way on Tree widgets as on
+CList widgets. The difference is that Tree widgets can be nested
+within other Tree widgets. We'll see how to do this shortly.
+
+The Tree widget has its own window, and defaults to a white
+background, as does CList. Also, most of the Tree methods work in
+the same way as the corresponding CList ones. However, Tree is
+not derived from CList, so you cannot use them interchangeably.
+
<sect1> Creating a Tree
<p>
-A GtkTree is created in the usual way, using:
+A Tree is created in the usual way, using:
<tscreen><verb>
-GtkWidget* gtk_tree_new( void );
+GtkWidget *gtk_tree_new( void );
</verb></tscreen>
-Like the GtkList widget, a GtkTree will simply keep growing as more
+Like the CList widget, a Tree will simply keep growing as more
items are added to it, as well as when subtrees are expanded. For
this reason, they are almost always packed into a
-GtkScrolledWindow. You might want to use gtk_widget_set_usize() on the
+ScrolledWindow. You might want to use gtk_widget_set_usize() on the
scrolled window to ensure that it is big enough to see the tree's
-items, as the default size for GtkScrolledWindow is quite small.
+items, as the default size for ScrolledWindow is quite small.
Now that you have a tree, you'll probably want to add some items to
it. <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
-explains the gory details of GtkTreeItem. For now, it'll suffice to
+explains the gory details of TreeItem. For now, it'll suffice to
create one, using:
<tscreen><verb>
-GtkWidget* gtk_tree_item_new_with_label( gchar *label );
+GtkWidget *gtk_tree_item_new_with_label( gchar *label );
</verb></tscreen>
You can then add it to the tree using one of the following (see
-<ref id="sec_GtkTree_Functions" name="Functions and Macros">
+<ref id="sec_Tree_Functions" name="Functions and Macros">
below for more options):
<tscreen><verb>
GtkWidget *tree_item );
</verb></tscreen>
-Note that you must add items to a GtkTree one at a time - there is no
+Note that you must add items to a Tree one at a time - there is no
equivalent to gtk_list_*_items().
<!-- ----------------------------------------------------------------- -->
<sect1> Adding a Subtree
<p>
-A subtree is created like any other GtkTree widget. A subtree is added
+A subtree is created like any other Tree widget. A subtree is added
to another tree beneath a tree item, using:
<tscreen><verb>
</verb></tscreen>
You do not need to call gtk_widget_show() on a subtree before or after
-adding it to a GtkTreeItem. However, you <em>must</em> have added the
-GtkTreeItem in question to a parent tree before calling
+adding it to a TreeItem. However, you <em>must</em> have added the
+TreeItem in question to a parent tree before calling
gtk_tree_item_set_subtree(). This is because, technically, the parent
of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
rather the GtkTree which holds that GtkTreeItem.
-When you add a subtree to a GtkTreeItem, a plus or minus sign appears
+When you add a subtree to a TreeItem, a plus or minus sign appears
beside it, which the user can click on to "expand" or "collapse" it,
-meaning, to show or hide its subtree. GtkTreeItems are collapsed by
-default. Note that when you collapse a GtkTreeItem, any selected
+meaning, to show or hide its subtree. TreeItems are collapsed by
+default. Note that when you collapse a TreeItem, any selected
items in its subtree remain selected, which may not be what the user
expects.
<!-- ----------------------------------------------------------------- -->
<sect1> Handling the Selection List
<p>
-As with GtkList, the GtkTree type has a <tt>selection</tt> field, and
+As with CList, the Tree type has a <tt>selection</tt> field, and
it is possible to control the behaviour of the tree (somewhat) by
setting the selection type using:
</verb></tscreen>
The semantics associated with the various selection modes are
-described in the section on the GtkList widget. As with the GtkList
+described in the section on the CList widget. As with the CList
widget, the "select_child", "unselect_child" (not really - see <ref
-id="sec_GtkTree_Signals" name="Signals"> below for an explanation),
+id="sec_Tree_Signals" name="Signals"> below for an explanation),
and "selection_changed" signals are emitted when list items are
selected or unselected. However, in order to take advantage of these
-signals, you need to know <em>which</em> GtkTree widget they will be
+signals, you need to know <em>which</em> Tree widget they will be
emitted by, and where to find the list of selected items.
This is a source of potential confusion. The best way to explain this
-is that though all GtkTree widgets are created equal, some are more
-equal than others. All GtkTree widgets have their own X window, and
-can therefore receive events such as mouse clicks (if their
-GtkTreeItems or their children don't catch them first!). However, to
-make GTK_SELECTION_SINGLE and GTK_SELECTION_BROWSE selection types
-behave in a sane manner, the list of selected items is specific to the
-topmost GtkTree widget in a hierarchy, known as the "root tree".
-
-Thus, accessing the <tt>selection</tt>field directly in an arbitrary
-GtkTree widget is not a good idea unless you <em>know</em> it's the
-root tree. Instead, use the GTK_TREE_SELECTION (Tree) macro, which
+is that though all Tree widgets are created equal, some are more equal
+than others. All Tree widgets have their own X window, and can
+therefore receive events such as mouse clicks (if their TreeItems or
+their children don't catch them first!). However, to make
+<tt/GTK_SELECTION_SINGLE/ and <tt/GTK_SELECTION_BROWSE/ selection
+types behave in a sane manner, the list of selected items is specific
+to the topmost Tree widget in a hierarchy, known as the "root tree".
+
+Thus, accessing the <tt>selection</tt> field directly in an arbitrary
+Tree widget is not a good idea unless you <em>know</em> it's the root
+tree. Instead, use the <tt/GTK_TREE_SELECTION (Tree)/ macro, which
gives the root tree's selection list as a GList pointer. Of course,
-this list can include items that are not in the subtree in question if
-the selection type is GTK_SELECTION_MULTIPLE.
+this list can include items that are not in the subtree in question if
+the selection type is <tt/GTK_SELECTION_MULTIPLE/.
Finally, the "select_child" (and "unselect_child", in theory) signals
are emitted by all trees, but the "selection_changed" signal is only
<sect1> Tree Widget Internals
<p>
-The GtkTree's struct definition looks like this:
+The Tree's struct definition looks like this:
<tscreen><verb>
struct _GtkTree
The perils associated with accessing the <tt>selection</tt> field
directly have already been mentioned. The other important fields of
the struct can also be accessed with handy macros or class functions.
-GTK_TREE_IS_ROOT_TREE (Tree) returns a boolean value which indicates
-whether a tree is the root tree in a GtkTree hierarchy, while
-GTK_TREE_ROOT_TREE (Tree) returns the root tree, an object of type
-GtkTree (so, remember to cast it using GTK_WIDGET (Tree) if you want
-to use one of the gtk_widget_*() functions on it).
-
-Instead of directly accessing the children field of a GtkTree widget,
-it's probably best to cast it using GTK_CONTAINER (Tree), and pass it
-to the gtk_container_children() function. This creates a duplicate of
-the original list, so it's advisable to free it up using g_list_free()
-after you're done with it, or to iterate on it destructively, like
-this:
+<tt/GTK_IS_ROOT_TREE (Tree)/ returns a boolean value which
+indicates whether a tree is the root tree in a Tree hierarchy, while
+<tt/GTK_TREE_ROOT_TREE (Tree)/ returns the root tree, an object of
+type GtkTree (so, remember to cast it using <tt/GTK_WIDGET (Tree)/ if
+you want to use one of the gtk_widget_*() functions on it).
+
+Instead of directly accessing the children field of a Tree widget,
+it's probably best to cast it using >tt/GTK_CONTAINER (Tree)/, and
+pass it to the gtk_container_children() function. This creates a
+duplicate of the original list, so it's advisable to free it up using
+g_list_free() after you're done with it, or to iterate on it
+destructively, like this:
<tscreen><verb>
children = gtk_container_children (GTK_CONTAINER (tree));
</verb></tscreen>
The <tt>tree_owner</tt> field is defined only in subtrees, where it
-points to the GtkTreeItem widget which holds the tree in question.
+points to the TreeItem widget which holds the tree in question.
The <tt>level</tt> field indicates how deeply nested a particular tree
is; root trees have level 0, and each successive level of subtrees has
a level one greater than the parent level. This field is set only
-after a GtkTree widget is actually mapped (i.e. drawn on the screen).
+after a Tree widget is actually mapped (i.e. drawn on the screen).
-<sect2> Signals<label id="sec_GtkTree_Signals">
+<sect2> Signals<label id="sec_Tree_Signals">
<p>
<tscreen><verb>
void selection_changed( GtkTree *tree );
</verb></tscreen>
This signal will be emitted whenever the <tt>selection</tt> field of a
-GtkTree has changed. This happens when a child of the GtkTree is
+Tree has changed. This happens when a child of the Tree is
selected or deselected.
<tscreen><verb>
GtkWidget *child );
</verb></tscreen>
-This signal is emitted when a child of the GtkTree is about to get
+This signal is emitted when a child of the Tree is about to get
selected. This happens on calls to gtk_tree_select_item(),
gtk_tree_select_child(), on <em>all</em> button presses and calls to
gtk_tree_item_toggle() and gtk_item_toggle(). It may sometimes be
indirectly triggered on other occasions where children get added to or
-removed from the GtkTree.
+removed from the Tree.
<tscreen><verb>
void unselect_child (GtkTree *tree,
GtkWidget *child);
</verb></tscreen>
-This signal is emitted when a child of the GtkTree is about to get
-deselected. As of GTK+ 1.0.4, this seems to only occur on calls to
+This signal is emitted when a child of the Tree is about to get
+deselected. As of GTK 1.0.4, this seems to only occur on calls to
gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
other occasions, but <em>not</em> when a button press deselects a
child, nor on emission of the "toggle" signal by gtk_item_toggle().
-<sect2> Functions and Macros<label id="sec_GtkTree_Functions">
+<sect2> Functions and Macros<label id="sec_Tree_Functions">
<p>
<tscreen><verb>
guint gtk_tree_get_type( void );
</verb></tscreen>
-Returns the `GtkTree' type identifier.
+Returns the "GtkTree" type identifier.
<tscreen><verb>
GtkWidget* gtk_tree_new( void );
</verb></tscreen>
-Create a new GtkTree object. The new widget is returned as a pointer
-to a GtkWidget object. NULL is returned on failure.
+Create a new Tree object. The new widget is returned as a pointer to a
+GtkWidget object. NULL is returned on failure.
<tscreen><verb>
void gtk_tree_append( GtkTree *tree,
GtkWidget *tree_item );
</verb></tscreen>
-Append a tree item to a GtkTree.
+Append a tree item to a Tree.
<tscreen><verb>
void gtk_tree_prepend( GtkTree *tree,
GtkWidget *tree_item );
</verb></tscreen>
-Prepend a tree item to a GtkTree.
+Prepend a tree item to a Tree.
<tscreen><verb>
void gtk_tree_insert( GtkTree *tree,
gint position );
</verb></tscreen>
-Insert a tree item into a GtkTree at the position in the list
+Insert a tree item into a Tree at the position in the list
specified by <tt>position.</tt>
<tscreen><verb>
GList *items );
</verb></tscreen>
-Remove a list of items (in the form of a GList *) from a GtkTree.
+Remove a list of items (in the form of a GList *) from a Tree.
Note that removing an item from a tree dereferences (and thus usually)
destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
-subtrees in that subtree. If you want to remove only one item, you
+subtrees in that subtree. If you want to remove only one item, you
can use gtk_container_remove().
<tscreen><verb>
</verb></tscreen>
Remove the items from position <tt>start</tt> to position <tt>end</tt>
-from a GtkTree. The same warning about dereferencing applies here, as
+from a Tree. The same warning about dereferencing applies here, as
gtk_tree_clear_items() simply constructs a list and passes it to
gtk_tree_remove_items().
GtkSelectionMode mode );
</verb></tscreen>
-Sets the selection mode, which can be one of GTK_SELECTION_SINGLE (the
-default), GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, or
-GTK_SELECTION_EXTENDED. This is only defined for root trees, which
+Sets the selection mode, which can be one of <tt/GTK_SELECTION_SINGLE/ (the
+default), <tt/GTK_SELECTION_BROWSE/, <tt/GTK_SELECTION_MULTIPLE/, or
+<tt/GTK_SELECTION_EXTENDED/. This is only defined for root trees, which
makes sense, since the root tree "owns" the selection. Setting it for
subtrees has no effect at all; the value is simply ignored.
GtkTreeViewMode mode );
</verb></tscreen>
-Sets the "view mode", which can be either GTK_TREE_VIEW_LINE (the
-default) or GTK_TREE_VIEW_ITEM. The view mode propagates from a tree
-to its subtrees, and can't be set exclusively to a subtree (this is
-not exactly true - see the example code comments).
+Sets the "view mode", which can be either <tt/GTK_TREE_VIEW_LINE/ (the
+default) or <tt/GTK_TREE_VIEW_ITEM/. The view mode propagates from a
+tree to its subtrees, and can't be set exclusively to a subtree (this
+is not exactly true - see the example code comments).
The term "view mode" is rather ambiguous - basically, it controls the
way the highlight is drawn when one of a tree's children is selected.
-If it's GTK_TREE_VIEW_LINE, the entire GtkTreeItem widget is
-highlighted, while for GTK_TREE_VIEW_ITEM, only the child widget
-(i.e. usually the label) is highlighted.
+If it's <tt/GTK_TREE_VIEW_LINE/, the entire TreeItem widget is
+highlighted, while for <tt/GTK_TREE_VIEW_ITEM/, only the child widget
+(i.e., usually the label) is highlighted.
<tscreen><verb>
void gtk_tree_set_view_lines( GtkTree *tree,
GtkTree *GTK_TREE (gpointer obj);
</verb></tscreen>
-Cast a generic pointer to `GtkTree *'.
+Cast a generic pointer to "GtkTree *".
<tscreen><verb>
GtkTreeClass *GTK_TREE_CLASS (gpointer class);
</verb></tscreen>
-Cast a generic pointer to `GtkTreeClass*'.
+Cast a generic pointer to "GtkTreeClass *".
<tscreen><verb>
gint GTK_IS_TREE (gpointer obj);
</verb></tscreen>
-Determine if a generic pointer refers to a `GtkTree' object.
+Determine if a generic pointer refers to a "GtkTree" object.
<tscreen><verb>
gint GTK_IS_ROOT_TREE (gpointer obj)
</verb></tscreen>
-Determine if a generic pointer refers to a `GtkTree' object
+Determine if a generic pointer refers to a "GtkTree" object
<em>and</em> is a root tree. Though this will accept any pointer, the
-results of passing it a pointer that does not refer to a GtkTree are
+results of passing it a pointer that does not refer to a Tree are
undefined and possibly harmful.
<tscreen><verb>
GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
</verb></tscreen>
-Return the root tree of a pointer to a `GtkTree' object. The above
+Return the root tree of a pointer to a "GtkTree" object. The above
warning applies.
<tscreen><verb>
GList *GTK_TREE_SELECTION( gpointer obj)
</verb></tscreen>
-Return the selection list of the root tree of a `GtkTree' object. The
+Return the selection list of the root tree of a "GtkTree" object. The
above warning applies here, too.
<sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
<p>
-The GtkTreeItem widget, like GtkListItem, is derived from GtkItem,
-which in turn is derived from GtkBin. Therefore, the item itself is a
+The TreeItem widget, like CListItem, is derived from Item,
+which in turn is derived from Bin. Therefore, the item itself is a
generic container holding exactly one child widget, which can be of
-any type. The GtkTreeItem widget has a number of extra fields, but
+any type. The TreeItem widget has a number of extra fields, but
the only one we need be concerned with is the <tt>subtree</tt> field.
-The definition for the GtkTreeItem struct looks like this:
+The definition for the TreeItem struct looks like this:
<tscreen><verb>
struct _GtkTreeItem
};
</verb></tscreen>
-The <tt>pixmaps_box</tt> field is a GtkEventBox which catches clicks
-on the plus/minus symbol which controls expansion and collapsing. The
-<tt>pixmaps</tt> field points to an internal data structure. Since
-you can always obtain the subtree of a GtkTreeItem in a (relatively)
-type-safe manner with the GTK_TREE_ITEM_SUBTREE (Item) macro, it's
-probably advisable never to touch the insides of a GtkTreeItem unless
-you <em>really</em> know what you're doing.
+The <tt>pixmaps_box</tt> field is an EventBox which catches clicks on
+the plus/minus symbol which controls expansion and collapsing. The
+<tt>pixmaps</tt> field points to an internal data structure. Since
+you can always obtain the subtree of a TreeItem in a (relatively)
+type-safe manner with the <tt/GTK_TREE_ITEM_SUBTREE (Item)/ macro,
+it's probably advisable never to touch the insides of a TreeItem
+unless you <em>really</em> know what you're doing.
-Since it is directly derived from a GtkItem it can be treated as such
-by using the GTK_ITEM (TreeItem) macro. A GtkTreeItem usually holds a
+Since it is directly derived from an Item it can be treated as such by
+using the <tt/GTK_ITEM (TreeItem)/ macro. A TreeItem usually holds a
label, so the convenience function gtk_list_item_new_with_label() is
provided. The same effect can be achieved using code like the
following, which is actually copied verbatim from
gtk_widget_show (label_widget);
</verb></tscreen>
-As one is not forced to add a GtkLabel to a GtkTreeItem, you could
-also add a GtkHBox or a GtkArrow, or even a GtkNotebook (though your
-app will likely be quite unpopular in this case) to the GtkTreeItem.
+As one is not forced to add a Label to a TreeItem, you could
+also add an HBox or an Arrow, or even a Notebook (though your
+app will likely be quite unpopular in this case) to the TreeItem.
If you remove all the items from a subtree, it will be destroyed and
-unparented, unless you reference it beforehand, and the GtkTreeItem
-which owns it will be collapsed. So, if you want it to stick around,
+unparented, unless you reference it beforehand, and the TreeItem
+which owns it will be collapsed. So, if you want it to stick around,
do something like the following:
<tscreen><verb>
gtk_widget_unref (tree);
</verb></tscreen>
-Finally, drag-n-drop <em>does</em> work with GtkTreeItems. You just
-have to make sure that the GtkTreeItem you want to make into a drag
-item or a drop site has not only been added to a GtkTree, but that
+Finally, drag-n-drop <em>does</em> work with TreeItems. You just
+have to make sure that the TreeItem you want to make into a drag
+item or a drop site has not only been added to a Tree, but that
each successive parent widget has a parent itself, all the way back to
a toplevel or dialog window, when you call gtk_widget_dnd_drag_set()
or gtk_widget_dnd_drop_set(). Otherwise, strange things will happen.
<sect2> Signals
<p>
-GtkTreeItem inherits the "select", "deselect", and "toggle" signals
-from GtkItem. In addition, it adds two signals of its own, "expand"
+TreeItem inherits the "select", "deselect", and "toggle" signals
+from Item. In addition, it adds two signals of its own, "expand"
and "collapse".
<tscreen><verb>
This signal is emitted when an item is about to be unselected, either
after it has been clicked on by the user, or when the program calls
gtk_tree_item_deselect() or gtk_item_deselect(). In the case of
-GtkTreeItems, it is also emitted by gtk_tree_unselect_child(), and
+TreeItems, it is also emitted by gtk_tree_unselect_child(), and
sometimes gtk_tree_select_child().
<tscreen><verb>
</verb></tscreen>
This signal is emitted when the program calls gtk_item_toggle(). The
-effect it has when emitted on a GtkTreeItem is to call
+effect it has when emitted on a TreeItem is to call
gtk_tree_select_child() (and never gtk_tree_unselect_child()) on the
item's parent tree, if the item has a parent tree. If it doesn't,
then the highlight is reversed on the item.
guint gtk_tree_item_get_type( void );
</verb></tscreen>
-Returns the `GtkTreeItem' type identifier.
+Returns the "GtkTreeItem" type identifier.
<tscreen><verb>
GtkWidget* gtk_tree_item_new( void );
</verb></tscreen>
-Create a new GtkTreeItem object. The new widget is returned as a
+Create a new TreeItem object. The new widget is returned as a
pointer to a GtkWidget object. NULL is returned on failure.
<tscreen><verb>
GtkWidget* gtk_tree_item_new_with_label (gchar *label);
</verb></tscreen>
-Create a new GtkTreeItem object, having a single GtkLabel as the sole
+Create a new TreeItem object, having a single GtkLabel as the sole
child. The new widget is returned as a pointer to a GtkWidget
object. NULL is returned on failure.
void gtk_tree_item_select( GtkTreeItem *tree_item );
</verb></tscreen>
-This function is basically a wrapper around a call to gtk_item_select
-(GTK_ITEM (tree_item)) which will emit the select signal.
+This function is basically a wrapper around a call to
+<tt>gtk_item_select (GTK_ITEM (tree_item))</tt> which will emit the
+select signal.
<tscreen><verb>
void gtk_tree_item_deselect( GtkTreeItem *tree_item );
GtkWidget *subtree );
</verb></tscreen>
-This function adds subtree to tree_item, showing it if tree_item is
+This function adds a subtree to tree_item, showing it if tree_item is
expanded, or hiding it if tree_item is collapsed. Again, remember that
the tree_item must have already been added to a tree for this to work.
GtkTreeItem *GTK_TREE_ITEM (gpointer obj)
</verb></tscreen>
-Cast a generic pointer to `GtkTreeItem*'.
+Cast a generic pointer to "GtkTreeItem *".
<tscreen><verb>
GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj)
</verb></tscreen>
-Cast a generic pointer to `GtkTreeItemClass'.
+Cast a generic pointer to "GtkTreeItemClass".
<tscreen><verb>
gint GTK_IS_TREE_ITEM (gpointer obj)
</verb></tscreen>
-Determine if a generic pointer refers to a `GtkTreeItem' object.
+Determine if a generic pointer refers to a "GtkTreeItem" object.
<tscreen><verb>
GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj)
</verb></tscreen>
-Returns a tree item's subtree (obj should point to a `GtkTreeItem'
-object).
+Returns a tree item's subtree (<tt/obj/ should point to a
+"GtkTreeItem" object).
<sect1> Tree Example
<p>
#include <gtk/gtk.h>
/* for all the GtkItem:: and GtkTreeItem:: signals */
-static void cb_itemsignal (GtkWidget *item, gchar *signame)
+static void cb_itemsignal( GtkWidget *item,
+ gchar *signame )
{
gchar *name;
GtkLabel *label;
- /* It's a GtkBin, so it has one child, which we know to be a
+ /* It's a Bin, so it has one child, which we know to be a
label, so get that */
label = GTK_LABEL (GTK_BIN (item)->child);
/* Get the text of the label */
}
/* Note that this is never called */
-static void cb_unselect_child (GtkWidget *root_tree, GtkWidget *child,
- GtkWidget *subtree)
+static void cb_unselect_child( GtkWidget *root_tree,
+ GtkWidget *child,
+ GtkWidget *subtree )
{
g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
root_tree, subtree, child);
root_tree, subtree, child);
}
-static void cb_selection_changed (GtkWidget *tree)
+static void cb_selection_changed( GtkWidget *tree )
{
GList *i;
}
}
-int main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window, *scrolled_win, *tree;
static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux",
<sect>Menu Widget
<!-- ***************************************************************** -->
<p>
-There are two ways to create menus, there's the easy way, and there's
+There are two ways to create menus: there's the easy way, and there's
the hard way. Both have their uses, but you can usually use the
-itemfactory (the easy way). The "hard" way is to create all the menus
+Itemfactory (the easy way). The "hard" way is to create all the menus
using the calls directly. The easy way is to use the gtk_item_factory
calls. This is much simpler, but there are advantages and
disadvantages to each approach.
-The itemfactory is much easier to use, and to add new menus to,
+The Itemfactory is much easier to use, and to add new menus to,
although writing a few wrapper functions to create menus using the
manual method could go a long way towards usability. With the
-itemfactory, it is not possible to add images or the character '/' to
+Itemfactory, it is not possible to add images or the character '/' to
the menus.
<!-- ----------------------------------------------------------------- -->
There are three widgets that go into making a menubar and submenus:
<itemize>
-<item>a menu item, which is what the user wants to select, e.g. 'Save'
+<item>a menu item, which is what the user wants to select, e.g.,
+"Save"
<item>a menu, which acts as a container for the menu items, and
<item>a menubar, which is a container for each of the individual
menus.
<tscreen>
<verb>
-GtkWidget* gtk_menu_bar_new (void);
+GtkWidget *gtk_menu_bar_new( void );
</verb>
</tscreen>
functions to pack it into a box - the same as buttons.
<tscreen><verb>
-GtkWidget* gtk_menu_new (void);
+GtkWidget *gtk_menu_new( void );
</verb></tscreen>
-This function returns a pointer to a new menu, it is never actually
+This function returns a pointer to a new menu; it is never actually
shown (with gtk_widget_show), it is just a container for the menu
-items. Hopefully this will become more clear when you look at the
+items. I hope this will become more clear when you look at the
example below.
The next two calls are used to create menu items that are packed into
the menu (and menubar).
<tscreen><verb>
-GtkWidget* gtk_menu_item_new (void);
+GtkWidget *gtk_menu_item_new( void );
</verb></tscreen>
and
<tscreen><verb>
-GtkWidget* gtk_menu_item_new_with_label (const char *label);
+GtkWidget *gtk_menu_item_new_with_label( const char *label );
</verb></tscreen>
These calls are used to create the menu items that are to be
is done using the function gtk_menu_append. In order to capture when
the item is selected by the user, we need to connect to the
<tt/activate/ signal in the usual way. So, if we wanted to create a
-standard <tt/File/ menu, with the options <tt/Open/, <tt/Save/ and
-<tt/Quit/ the code would look something like:
+standard <tt/File/ menu, with the options <tt/Open/, <tt/Save/, and
+<tt/Quit/, the code would look something like:
<tscreen><verb>
file_menu = gtk_menu_new (); /* Don't need to show menus */
with the function
<tscreen>
-void gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
- GtkWidget *submenu);
+void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
+ GtkWidget *submenu );
</tscreen>
So, our example would continue with
accomplished using the function
<tscreen>
-void gtk_menu_bar_append (GtkMenuBar *menu_bar, GtkWidget *menu_item);
+void gtk_menu_bar_append( GtkMenuBar *menu_bar,
+ GtkWidget *menu_item );
</tscreen>
which in our case looks like this:
menubar.
<tscreen><verb>
-void gtk_menu_item_right_justify (GtkMenuItem *menu_item);
+void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
</verb></tscreen>
Here is a summary of the steps needed to create a menu bar with menus
</itemize>
Creating a popup menu is nearly the same. The difference is that the
-menu is not posted `automatically' by a menubar, but explicitly by
+menu is not posted "automatically" by a menubar, but explicitly by
calling the function gtk_menu_popup() from a button-press event, for
example. Take these steps:
<tscreen><verb>
/* example-start menu menu.c */
+#include <stdio.h>
#include <gtk/gtk.h>
static gint button_press (GtkWidget *, GdkEvent *);
static void menuitem_response (gchar *);
-int main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
gtk_main ();
- return 0;
+ return(0);
}
/* Respond to a button-press by posting a menu passed in as widget.
* the button that was pressed.
*/
-static gint button_press (GtkWidget *widget, GdkEvent *event)
+static gint button_press( GtkWidget *widget,
+ GdkEvent *event )
{
if (event->type == GDK_BUTTON_PRESS) {
/* Print a string when a menu item is selected */
-static void menuitem_response (gchar *string)
+static void menuitem_response( gchar *string )
{
printf ("%s\n", string);
}
table, bind keys to menu functions.
<!-- ----------------------------------------------------------------- -->
-<sect1>Using GtkItemFactory
+<sect1>Using ItemFactory
<p>
Now that we've shown you the hard way, here's how you do it using the
gtk_item_factory calls.
#include <strings.h>
/* Obligatory basic callback */
-static void
-print_hello (GtkWidget *w, gpointer data)
+static void print_hello( GtkWidget *w,
+ gpointer data )
{
g_message ("Hello, World!\n");
}
};
-void
-get_main_menu (GtkWidget *window, GtkWidget ** menubar)
+void get_main_menu( GtkWidget *window,
+ GtkWidget **menubar )
{
GtkItemFactory *item_factory;
GtkAccelGroup *accel_group;
gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
/* Attach the new accelerator group to the window. */
- gtk_accel_group_attach (accel_group, GTK_OBJECT (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>");
}
-int
-main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
GtkWidget *main_vbox;
gtk_widget_show (window);
gtk_main ();
- return 0;
+ return(0);
}
/* example-end */
</verb></tscreen>
-For now, there's only this example. An explanation and lots 'o' comments
+For now, there's only this example. An explanation and lots 'o' comments
will follow later.
<!-- ***************************************************************** -->
<!-- ***************************************************************** -->
<p>
The Text widget allows multiple lines of text to be displayed and
-edited. It supports both multi-colored and multi-font text, allowing
+edited. It supports both multi-colored and multi-font text, allowing
them to be mixed in any way we wish. It also has a wide set of key
based text editing commands, which are compatible with Emacs.
it to the vertical adjustment of the text widget, <tt/text/. It then
packs it into a box in the normal way.
-Note, currently the GtkText widget does not support horizontal
+Note, currently the Text widget does not support horizontal
scrollbars.
There are two main ways in which a Text widget can be used: to allow
which returns the current length of the Text widget. The length is the
number of characters that are within the text block of the widget,
-including characters such as carriage-return, which marks the end of
+including characters such as newline, which marks the end of
lines.
In order to insert text at the current insertion point of a Text
</verb></tscreen>
Passing a value of <tt/NULL/ in as the value for the foreground color,
-background colour or font will result in the values set within the
+background color or font will result in the values set within the
widget style to be used. Using a value of <tt/-1/ for the length
parameter will result in the whole of the text string given being
inserted.
GTK_TOGGLE_BUTTON(checkbutton)->active);
}
-void close_application( GtkWidget *widget, gpointer data )
+void close_application( GtkWidget *widget,
+ gpointer data )
{
gtk_main_quit();
}
-int main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
GtkWidget *box1;
GtkWidget *vscrollbar;
GtkWidget *text;
GdkColormap *cmap;
- GdkColor colour;
+ GdkColor color;
GdkFont *fixed_font;
FILE *infile;
GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (vscrollbar);
- /* Get the system colour map and allocate the colour red */
+ /* Get the system color map and allocate the color red */
cmap = gdk_colormap_get_system();
- colour.red = 0xffff;
- colour.green = 0;
- colour.blue = 0;
- if (!gdk_color_alloc(cmap, &colour)) {
- g_error("couldn't allocate colour");
+ color.red = 0xffff;
+ color.green = 0;
+ color.blue = 0;
+ if (!gdk_color_alloc(cmap, &color)) {
+ g_error("couldn't allocate color");
}
/* Load a fixed font */
/* Freeze the text widget, ready for multiple updates */
gtk_text_freeze (GTK_TEXT (text));
- /* Insert some coloured text */
+ /* Insert some colored text */
gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL,
"Supports ", -1);
- gtk_text_insert (GTK_TEXT (text), NULL, &colour, NULL,
+ gtk_text_insert (GTK_TEXT (text), NULL, &color, NULL,
"colored ", -1);
gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL,
"text and different ", -1);
widget, please consider writing a tutorial on it so others may benefit
from your time.
-<!-- ----------------------------------------------------------------- -->
-<sect1> Calendar
-<p>
<!-- ----------------------------------------------------------------- -->
<sect1> CTree
<p>
<tscreen><verb>
Previews serve a number of purposes in GIMP/GTK. The most important one is
-this. High quality images may take up to tens of megabytes of memory - easy!
+this. High quality images may take up to tens of megabytes of memory - easily!
Any operation on an image that big is bound to take a long time. If it takes
-you 5-10 trial-and-errors (i.e. 10-20 steps, since you have to revert after
+you 5-10 trial-and-errors (i.e., 10-20 steps, since you have to revert after
you make an error) to choose the desired modification, it make take you
literally hours to make the right one - if you don't run out of memory
first. People who have spent hours in color darkrooms know the feeling.
..., 1010-back! Previews to the rescue!
But there's more. Previews allow for side-by-side pre-previews. In other
-words, you write a plug-in (e.g. the filterpack simulation) which would have
+words, you write a plug-in (e.g., the filterpack simulation) which would have
a number of here's-what-it-would-look-like-if-you-were-to-do-this previews.
An approach like this acts as a sort of a preview palette and is very
effective for subtle changes. Let's go previews!
When Not to Use Previews
-Don't use previews for graphs, drawing etc. GDK is much faster for that. Use
+Don't use previews for graphs, drawing, etc. GDK is much faster for that. Use
previews only for rendered images!
Let's go previews!
gint Selection)
{
/* This function reduced the image down to the the selected preview size */
- /* The preview size is determine by LongerSize, i.e. the greater of the */
+ /* The preview size is determine by LongerSize, i.e., the greater of the */
/* two dimensions. Works for RGB images only! */
gint RH, RW; /* Reduced height and reduced width */
gint width, height; /* Width and Height of the area being reduced */
<sect>Setting Widget Attributes<label id="sec_setting_widget_attributes">
<!-- ***************************************************************** -->
<p>
-This describes the functions used to operate on widgets. These can be
-used to set style, padding, size etc.
+This describes the functions used to operate on widgets. These can be
+used to set style, padding, size, etc.
(Maybe I should make a whole section on accelerators.)
<sect1>Timeouts
<p>
You may be wondering how you make GTK do useful work when in gtk_main.
-Well, you have several options. Using the following functions you can
+Well, you have several options. Using the following function you can
create a timeout function that will be called every "interval"
milliseconds.
You may also stop the timeout function by returning zero or FALSE from
your callback function. Obviously this means if you want your function
to continue to be called, it should return a non-zero value,
-i.e. TRUE.
+i.e., TRUE.
The declaration of your callback should look something like this:
may be one of:
<itemize>
-<item>GDK_INPUT_READ - Call your function when there is data ready for
-reading on your file descriptor.
+<item><tt/GDK_INPUT_READ/ - Call your function when there is data
+ready for reading on your file descriptor.
-<item>GDK_INPUT_WRITE - Call your function when the file descriptor is
-ready for writing.
+<item>><tt/GDK_INPUT_WRITE/ - Call your function when the file
+descriptor is ready for writing.
</itemize>
As I'm sure you've figured out already, the third argument is the
<sect1>Idle Functions
<p>
<!-- TODO: Need to check on idle priorities - TRG -->
-What if you have a function you want called when nothing else is
-happening ?
+What if you have a function which you want to be called when nothing
+else is happening ?
<tscreen><verb>
gint gtk_idle_add( GtkFunction function,
<!-- ----------------------------------------------------------------- -->
<sect1>Signal Emission and Propagation
<p>
-Signal emission is the process wherby GTK runs all handlers for a
+Signal emission is the process whereby GTK runs all handlers for a
specific object and signal.
First, note that the return value from a signal emission is the return
value of the <em>last</em> handler executed. Since event signals are
-all of type GTK_RUN_LAST, this will be the default (GTK supplied)
-default handler, unless you connect with gtk_signal_connect_after().
+all of type <tt/GTK_RUN_LAST/, this will be the default (GTK supplied)
+handler, unless you connect with gtk_signal_connect_after().
-The way an event (say GTK_BUTTON_PRESS) is handled, is:
+The way an event (say "button_press_event") is handled, is:
<itemize>
<item>Start with the widget where the event occured.
<item>Otherwise, emit a specific, "button_press_event" signal. If that
returns TRUE, stop all processing.
-<item>Otherwise, go to the widget's parent, and repeat the above steps.
+<item>Otherwise, go to the widget's parent, and repeat the above two
+steps.
-<item>Contimue until some signal handler returns TRUE, or until the
+<item>Continue until some signal handler returns TRUE, or until the
top-level widget is reached.
</itemize>
<!-- ----------------------------------------------------------------- -->
<sect1> Overview
<p>
-One type of interprocess communication supported by GTK is
+One type of interprocess communication supported by X and GTK is
<em>selections</em>. A selection identifies a chunk of data, for
instance, a portion of text, selected by the user in some fashion, for
instance, by dragging with the mouse. Only one application on a
-display, (the <em>owner</em>) can own a particular selection at one
+display (the <em>owner</em>) can own a particular selection at one
time, so when a selection is claimed by one application, the previous
owner must indicate to the user that selection has been
relinquished. Other applications can request the contents of a
selections itself. The standard widgets, such as the Entry widget,
already have the capability to claim the selection when appropriate
(e.g., when the user drags over text), and to retrieve the contents of
-the selection owned by another widget, or another application (e.g.,
+the selection owned by another widget or another application (e.g.,
when the user clicks the second mouse button). However, there may be
cases in which you want to give other widgets the ability to supply
the selection, or you wish to retrieve targets not supported by
#include <gtk/gtk.h>
-void selection_received (GtkWidget *widget,
- GtkSelectionData *selection_data,
- gpointer data);
+void selection_received( GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ gpointer data );
/* Signal handler invoked when user clicks on the "Get Targets" button */
-void
-get_targets (GtkWidget *widget, gpointer data)
+void get_targets( GtkWidget *widget,
+ gpointer data )
{
static GdkAtom targets_atom = GDK_NONE;
}
/* Signal handler called when the selections owner returns the data */
-void
-selection_received (GtkWidget *widget, GtkSelectionData *selection_data,
- gpointer data)
+void selection_received( GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ gpointer data )
{
GdkAtom *atoms;
GList *item_list;
return;
}
-int
-main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
GtkWidget *button;
each selection/target pair you will handle, you make a call to:
<tscreen><verb>
-void gtk_selection_add_handler( GtkWidget *widget,
- GdkAtom selection,
- GdkAtom target,
- GtkSelectionFunction function,
- GtkRemoveFunction remove_func,
- gpointer data );
+void gtk_selection_add_target (GtkWidget *widget,
+ GdkAtom selection,
+ GdkAtom target,
+ guint info);
</verb></tscreen>
<tt/widget/, <tt/selection/, and <tt/target/ identify the requests
-this handler will manage. <tt/remove_func/, if not
-NULL, will be called when the signal handler is removed. This is
-useful, for instance, for interpreted languages which need to
-keep track of a reference count for <tt/data/.
+this handler will manage. When a request for a selection is received,
+the "selection_get" signal will be called. <tt/info/ can be used as an
+enumerator to identify the specific target within the callback function.
The callback function has the signature:
<tscreen><verb>
-typedef void (*GtkSelectionFunction)( GtkWidget *widget,
- GtkSelectionData *selection_data,
- gpointer data );
-
+void "selection_get" (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time);
</verb></tscreen>
The GtkSelectionData is the same as above, but this time, we're
#include <time.h>
/* Callback when the user toggles the selection */
-void
-selection_toggled (GtkWidget *widget, gint *have_selection)
+void selection_toggled( GtkWidget *widget,
+ gint *have_selection )
{
if (GTK_TOGGLE_BUTTON(widget)->active)
{
}
/* Called when another application claims the selection */
-gint
-selection_clear (GtkWidget *widget, GdkEventSelection *event,
- gint *have_selection)
+gint selection_clear( GtkWidget *widget,
+ GdkEventSelection *event,
+ gint *have_selection )
{
*have_selection = FALSE;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
}
/* Supplies the current time as the selection. */
-void
-selection_handle (GtkWidget *widget,
- GtkSelectionData *selection_data,
- gpointer data)
+void selection_handle( GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time_stamp,
+ gpointer data )
{
gchar *timestr;
time_t current_time;
- current_time = time (NULL);
+ current_time = time(NULL);
timestr = asctime (localtime(&current_time));
/* When we return a single string, it should not be null terminated.
That will be done for us */
8, timestr, strlen(timestr));
}
-int
-main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
-
GtkWidget *selection_button;
static int have_selection = FALSE;
gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
GTK_SIGNAL_FUNC (selection_clear), &have_selection);
- gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
- GDK_SELECTION_TYPE_STRING,
- selection_handle, NULL);
+ gtk_selection_add_target (selection_button,
+ GDK_SELECTION_PRIMARY,
+ GDK_SELECTION_TYPE_STRING,
+ 1);
+ gtk_signal_connect (GTK_OBJECT(selection_button), "selection_get",
+ GTK_SIGNAL_FUNC (selection_handle), &have_selection);
gtk_widget_show (selection_button);
gtk_widget_show (window);
<!-- ***************************************************************** -->
-<sect>glib<label id="sec_glib">
+<sect>GLib<label id="sec_glib">
<!-- ***************************************************************** -->
<p>
-glib is a lower-level library that provides many useful definitions
+GLib is a lower-level library that provides many useful definitions
and functions available for use when creating GDK and GTK
applications. These include definitions for basic types and their
limits, standard macros, type conversions, byte order, memory
accessible by a string or integer id), relations and tuples (tables of
data which can be indexed on any number of fields), and caches.
-A summary of some of glib's capabilities follows; not every function,
+A summary of some of GLib's capabilities follows; not every function,
data structure, or operation is covered here. For more complete
-information about the glib routines, see the glib documentation. One
-source of glib documentation is http://www.gtk.org/ <htmlurl
-url="http://www.gtk.org/" name="http://www.gtk.org/">.
+information about the GLib routines, see the GLib documentation. One
+source of GLib documentation is <htmlurl url="http://www.gtk.org/"
+name="http://www.gtk.org/">.
If you are using a language other than C, you should consult your
language's binding documentation. In some cases your language may
refer to dynamically-allocated memory, then they should be freed
first.
-There are many other glib functions that support doubly linked lists;
+There are many other GLib functions that support doubly linked lists;
see the glib documentation for more information. Here are a few of
the more useful functions' signatures:
void g_mem_profile( void );
</verb></tscreen>
-Dumps a profile of used memory, but requires that you add #define
-MEM_PROFILE to the top of glib/gmem.c and re-make and make install.
+Dumps a profile of used memory, but requires that you add <tt>#define
+MEM_PROFILE</tt> to the top of glib/gmem.c and re-make and make install.
<tscreen><verb>
void g_mem_check( gpointer mem );
</verb></tscreen>
-Checks that a memory location is valid. Requires you add #define
-MEM_CHECK to the top of gmem.c and re-make and make install.
+Checks that a memory location is valid. Requires you add <tt>#define
+MEM_CHECK</tt> to the top of gmem.c and re-make and make install.
<!-- ----------------------------------------------------------------- -->
<sect1>Timers
<p>
-Timer functions can be used to time operations (e.g. to see how much
+Timer functions can be used to time operations (e.g., to see how much
time has elapsed). First, you create a new timer with g_timer_new().
You can then use g_timer_start() to start timing an operation,
g_timer_stop() to stop timing an operation, and g_timer_elapsed() to
<!-- ----------------------------------------------------------------- -->
<sect1>String Handling
<p>
-glib defines a new type called a GString, which is similar to a
+GLib defines a new type called a GString, which is similar to a
standard C string but one that grows automatically. Its string data
is null-terminated. What this gives you is protection from buffer
overflow programming errors within your program. This is a very
to document any function, just send me an email!
<!-- ***************************************************************** -->
-<sect>GTK's rc Files
+<sect>GTK's rc Files <label id="sec_gtkrc_files">
<!-- ***************************************************************** -->
<p>
GTK has its own way of dealing with application defaults, by using rc
widget "main window.*GtkButton*" style "main_button"
</verb></tscreen>
-Which sets all the GtkButton widgets in the "main window" to the
+Which sets all the Button widgets in the "main window" to the
"main_buttons" style as defined in the rc file.
As you can see, this is a fairly powerful and flexible system. Use your
<p>
The format of the GTK file is illustrated in the example below. This is
the testgtkrc file from the GTK distribution, but I've added a
-few comments and things. You may wish to include this explanation
+few comments and things. You may wish to include this explanation in
your application to allow the user to fine tune his application.
There are several directives to change the attributes of a widget.
<itemize>
<item>NORMAL - The normal state of a widget, without the mouse over top of
-it, and not being pressed etc.
+it, and not being pressed, etc.
<item>PRELIGHT - When the mouse is over top of the widget, colors defined
using this state will be in effect.
<item>ACTIVE - When the widget is pressed or clicked it will be active, and
fg[<STATE>] = { Red, Green, Blue }
</verb></tscreen>
-Where STATE is one of the above states (PRELIGHT, ACTIVE etc), and the Red,
+Where STATE is one of the above states (PRELIGHT, ACTIVE, etc), and the Red,
Green and Blue are values in the range of 0 - 1.0, { 1.0, 1.0, 1.0 } being
white. They must be in float form, or they will register as 0, so a straight
"1" will not work, it must be "1.0". A straight "0" is fine because it
font = "<font name>"
</verb></tscreen>
-Where the only hard part is figuring out the font string. Using xfontsel or
-similar utility should help.
+The only hard part is figuring out the font string. Using xfontsel or
+a similar utility should help.
The "widget_class" sets the style of a class of widgets. These classes are
listed in the widget overview on the class hierarchy.
# certain widgets.
#
# NORMAL - The normal state of a widget, without the mouse over top of
-# it, and not being pressed etc.
+# it, and not being pressed, etc.
#
# PRELIGHT - When the mouse is over top of the widget, colors defined
# using this state will be in effect.
Note that, similar to the class structure, the first field is the
object structure of the parent class, so that this structure can be
-cast to the parent class's object structure as needed.
+cast to the parent class' object structure as needed.
<!-- ----------------------------------------------------------------- -->
<sect1> Creating a Composite widget
class that holds all of the elements of the composite widget. For
example, the parent class of the FileSelection widget is the
Dialog class. Since our buttons will be arranged in a table, it
-might seem natural to make our parent class the GtkTable
+might seem natural to make our parent class the Table
class. Unfortunately, this turns out not to work. The creation of a
widget is divided among two functions - a <tt/WIDGETNAME_new()/
function that the user calls, and a <tt/WIDGETNAME_init()/ function
which does the basic work of initializing the widget which is
independent of the arguments passed to the <tt/_new()/
-function. Descendent widgets only call the <tt/_init/ function of
+function. Descendant widgets only call the <tt/_init/ function of
their parent widget. But this division of labor doesn't work well for
-tables, which when created, need to know the number of rows and
+tables, which when created need to know the number of rows and
columns in the table. Unless we want to duplicate most of the
functionality of <tt/gtk_table_new()/ in our Tictactoe widget, we had
-best avoid deriving it from GtkTable. For that reason, we derive it
-from GtkVBox instead, and stick our table inside the VBox.
+best avoid deriving it from Table. For that reason, we derive it
+from VBox instead, and stick our table inside the VBox.
<!-- ----------------------------------------------------------------- -->
<sect2> The header file
user handlers. Usually this will be <tt/GTK_RUN_FIRST/, or <tt/GTK_RUN_LAST/,
although there are other possibilities.
<item> <tt/object_type/: The ID of the object that this signal applies
-to. (It will also apply to that objects descendents)
+to. (It will also apply to that objects descendants.)
<item> <tt/function_offset/: The offset within the class structure of
a pointer to the default handler.
<item> <tt/marshaller/: A function that is used to invoke the signal
After creating our signals, we need to tell GTK to associate our
signals with the Tictactoe class. We do that by calling
<tt/gtk_object_class_add_signals()/. We then set the pointer which
-points to the default handler for the `tictactoe' signal to NULL,
+points to the default handler for the "tictactoe" signal to NULL,
indicating that there is no default action.
<!-- ----------------------------------------------------------------- -->
<sect2> And the rest...
<p>
There is one more function that every widget (except for base widget
-types like GtkBin that cannot be instantiated) needs to have - the
+types like Bin that cannot be instantiated) needs to have - the
function that the user calls to create an object of that type. This is
conventionally called <tt/WIDGETNAME_new()/. In some
widgets, though not for the Tictactoe widgets, this function takes
the exposed portion on the screen. For container widgets, this
function must generate expose events for its child widgets which don't
have their own windows. (If they have their own windows, then X will
-generate the necessary expose events)
+generate the necessary expose events.)
</itemize>
You might notice that the last two functions are quite similar - each
<sect2> The origins of the Dial Widget
<p>
Just as all land animals are just variants on the first amphibian that
-crawled up out of the mud, Gtk widgets tend to start off as variants
-of some other, previously written widget. Thus, although this section
-is entitled `Creating a Widget from Scratch', the Dial widget really
+crawled up out of the mud, GTK widgets tend to start off as variants
+of some other, previously written widget. Thus, although this section
+is entitled "Creating a Widget from Scratch", the Dial widget really
began with the source code for the Range widget. This was picked as a
starting point because it would be nice if our Dial had the same
-interface as the Scale widgets which are just specialized descendents
+interface as the Scale widgets which are just specialized descendants
of the Range widget. So, though the source code is presented below in
-finished form, it should not be implied that it was written, <em>deus
-ex machina</em> in this fashion. Also, if you aren't yet familiar with
+finished form, it should not be implied that it was written, <em>ab
+initio</em> in this fashion. Also, if you aren't yet familiar with
how scale widgets work from the application writer's point of view, it
would be a good idea to look them over before continuing.
Tictactoe widget. First, we have a header file:
<tscreen><verb>
-/* GTK - The GIMP Toolkit
+/* GTK - The GTK+ Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
#endif /* __GTK_DIAL_H__ */
</verb></tscreen>
-Since there is quite a bit more going on in this widget, than the last
+Since there is quite a bit more going on in this widget than the last
one, we have more fields in the data structure, but otherwise things
are pretty similar.
-Next, after including header files, and declaring a few constants,
+Next, after including header files and declaring a few constants,
we have some functions to provide information about the widget
and initialize it:
widget, since this is not a composite widget, and the <tt/new()/
function does more, since it now has an argument. Also, note that when
we store a pointer to the Adjustment object, we increment its
-reference count, (and correspondingly decrement when we no longer use
-it) so that GTK can keep track of when it can be safely destroyed.
+reference count, (and correspondingly decrement it when we no longer
+use it) so that GTK can keep track of when it can be safely destroyed.
<p>
Also, there are a few function to manipulate the widget's options:
fields will be given default values). Also worth noting is the way the
event mask of the widget is created. We call
<tt/gtk_widget_get_events()/ to retrieve the event mask that the user
-has specified for this widget (with <tt/gtk_widget_set_events()/, and
+has specified for this widget (with <tt/gtk_widget_set_events()/), and
add the events that we are interested in ourselves.
<p>
Before the first time that the window containing a widget is
displayed, and whenever the layout of the window changes, GTK asks
each child widget for its desired size. This request is handled by the
-function, <tt/gtk_dial_size_request()/. Since our widget isn't a
+function <tt/gtk_dial_size_request()/. Since our widget isn't a
container widget, and has no real constraints on its size, we just
return a reasonable default value.
<p>
After all the widgets have requested an ideal size, the layout of the
window is computed and each child widget is notified of its actual
-size. Usually, this will at least as large as the requested size, but
-if for instance, the user has resized the window, it may occasionally
-be smaller than the requested size. The size notification is handled
-by the function <tt/gtk_dial_size_allocate()/. Notice that as well as
-computing the sizes of some component pieces for future use, this
-routine also does the grunt work of moving the widgets X window into
-the new position and size.
+size. Usually, this will be at least as large as the requested size,
+but if for instance the user has resized the window, it may
+occasionally be smaller than the requested size. The size notification
+is handled by the function <tt/gtk_dial_size_allocate()/. Notice that
+as well as computing the sizes of some component pieces for future
+use, this routine also does the grunt work of moving the widget's X
+window into the new position and size.
<tscreen><verb>
static void
circumstance.
When the user clicks on the widget, we check to see if the click was
-appropriately near the pointer, and if so, store then button that the
+appropriately near the pointer, and if so, store the button that the
user clicked with in the <tt/button/ field of the widget
structure, and grab all mouse events with a call to
<tt/gtk_grab_add()/. Subsequent motion of the mouse causes the
</verb></tscreen>
Changes to the Adjustment by external means are communicated to our
-widget by the `changed' and `value_changed' signals. The handlers
+widget by the "changed" and "value_changed" signals. The handlers
for these functions call <tt/gtk_dial_update()/ to validate the
arguments, compute the new pointer angle, and redraw the widget (by
calling <tt/gtk_widget_draw()/).
possible to use embedded Button widgets for this, we would also like
the buttons to auto-repeat when held down, as the arrows on a
scrollbar do. Most of the code to implement this type of behavior can
-be found in the GtkRange widget.
+be found in the Range widget.
<item> The Dial widget could be made into a container widget with a
single child widget positioned at the bottom between the buttons
Only a small part of the many details involved in creating widgets
could be described above. If you want to write your own widgets, the
best source of examples is the GTK source itself. Ask yourself some
-questions about the widget you want to write: is it a Container
-widget? does it have its own window? is it a modification of an
+questions about the widget you want to write: IS it a Container
+widget? Does it have its own window? Is it a modification of an
existing widget? Then find a similar widget, and start making changes.
Good luck!
a key being pressed. There are also GTK signals corresponding to these
low-level <em>events</em>. The handlers for these signals have an
extra parameter which is a pointer to a structure containing
-information about the event. For instance, motion events handlers are
+information about the event. For instance, motion event handlers are
passed a pointer to a GdkEventMotion structure which looks (in part)
like:
<tt/type/ will be set to the event type, in this case
<tt/GDK_MOTION_NOTIFY/, window is the window in which the event
-occurred. <tt/x/ and <tt/y/ give the coordinates of the event,
-and <tt/state/ specifies the modifier state when the event
+occurred. <tt/x/ and <tt/y/ give the coordinates of the event.
+<tt/state/ specifies the modifier state when the event
occurred (that is, it specifies which modifier keys and mouse buttons
-were pressed.) It is the bitwise OR of some of the following:
+were pressed). It is the bitwise OR of some of the following:
<tscreen><verb>
GDK_SHIFT_MASK
We'll save the "expose_event" and "configure_event" handlers for
later. The "motion_notify_event" and "button_press_event" handlers
-pretty simple:
+are pretty simple:
<tscreen><verb>
static gint
<!-- ----------------------------------------------------------------- -->
<sect1> The DrawingArea Widget, And Drawing
<p>
-We know turn to the process of drawing on the screen. The
+We now turn to the process of drawing on the screen. The
widget we use for this is the DrawingArea widget. A drawing area
widget is essentially an X window and nothing more. It is a blank
canvas in which we can draw whatever we like. A drawing area
be overridden if the user manually resizes the the window containing
the drawing area.
-It should be noted that when we create a DrawingArea widget, we are,
+It should be noted that when we create a DrawingArea widget, we are
<em>completely</em> responsible for drawing the contents. If our
window is obscured then uncovered, we get an exposure event and must
redraw what was previously hidden.
GTK_STATE_INSENSITIVE
</verb></tscreen>
-For instance, the for <tt/GTK_STATE_SELECTED/ the default foreground
+For instance, for <tt/GTK_STATE_SELECTED/ the default foreground
color is white and the default background color, dark blue.
Our function <tt>draw_brush()</tt>, which does the actual drawing
to copy the relevant portions to the screen.
We have now covered the entire drawing program except for a few
-mundane details like creating the main window. The complete
-source code is available from the location from which you got
-this tutorial, or from:
-
-<htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
-name="http://www.gtk.org/~otaylor/gtk/tutorial/">
-
+mundane details like creating the main window.
<!-- ----------------------------------------------------------------- -->
<sect1> Adding XInput support
<tt/source/ and <tt/deviceid/ specify the device for which the
event occurred in two different ways. <tt/source/ gives some simple
information about the type of device. It can take the enumeration
-values.
+values:
<tscreen><verb>
GDK_SOURCE_MOUSE
enabled. (In this case, <tt/event->deviceid/ will have the value
<tt/GDK_CORE_POINTER/).
-So the basic structure of our button-press and motion event handlers,
+So the basic structure of our button-press and motion event handlers
doesn't change much - we just need to add code to deal with the
extended information.
GList *gdk_input_list_devices (void);
</verb></tscreen>
-which returns a GList (a linked list type from the glib library)
+which returns a GList (a linked list type from the GLib library)
of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
as:
};
</verb></tscreen>
-Most of these fields are configuration information that you
-can ignore unless you are implemented XInput configuration
-saving. The we are interested in here is <tt/name/ which is
-simply the name that X assigns to the device. The other field
-that isn't configuration information is <tt/has_cursor/. If
-<tt/has_cursor/ is false, then we we need to draw our own
-cursor. But since we've specified <tt/GDK_EXTENSION_EVENTS_CURSOR/,
-we don't have to worry about this.
+Most of these fields are configuration information that you can ignore
+unless you are implementing XInput configuration saving. The fieldwe
+are interested in here is <tt/name/ which is simply the name that X
+assigns to the device. The other field that isn't configuration
+information is <tt/has_cursor/. If <tt/has_cursor/ is false, then we
+we need to draw our own cursor. But since we've specified
+<tt/GDK_EXTENSION_EVENTS_CURSOR/, we don't have to worry about this.
Our <tt/print_button_press()/ function simply iterates through
the returned list until it finds a match, then prints out
}
</verb></tscreen>
-That completes the changes to `XInputize' our program. As with
-the first version, the complete source is available at the location
-from which you got this tutorial, or from:
-
-<htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
-name="http://www.gtk.org/~otaylor/gtk/tutorial/">
-
+That completes the changes to "XInputize" our program.
<sect2> Further sophistications <label id="sec_Further_Sophistications">
<p>
The first is done by searching the device list, as we did
to find out the device name. The second is achieved by selecting
"proximity_out" events. An example of drawing one's own cursor is
-found in the 'testinput' program found in the GTK distribution.
+found in the "testinput" program found in the GTK distribution.
<!-- ***************************************************************** -->
<sect>Tips For Writing GTK Applications
<p>
This section is simply a gathering of wisdom, general style guidelines
and hints to creating good GTK applications. Currently this section
-is very short, but hopefully it will get longer in future editions of
+is very short, but I hope it will get longer in future editions of
this tutorial.
Use GNU autoconf and automake! They are your friends :) Automake
name="gale@gtk.org"></tt>. Also, be aware that the entirety of this
document is free, and any addition by you provide must also be
free. That is, people may use any portion of your examples in their
-programs, and copies of this document may be distributed at will etc.
+programs, and copies of this document may be distributed at will, etc.
Thank you.
<sect>Credits
<!-- ***************************************************************** -->
<p>
-I would like to thank the following for their contributions to this text.
+We would like to thank the following for their contributions to this text.
<itemize>
<item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com"
lot Mark! You've been a great help.
<item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org"
-name="timj@psynet.net"></tt> for his great job on the Lists
+name="timj@gtk.org"></tt> for his great job on the Lists
Widget. His excellent work on automatically extracting the widget tree
and signal information from GTK. Thanks Tim :)
Widget sections.
<item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se"
-name="mars@lysator.liu.se"></tt> for the GtkCList section.
+name="mars@lysator.liu.se"></tt> for the CList section.
<item>David A. Wheeler <tt><htmlurl url="mailto:dwheeler@ida.org"
-name="dwheeler@ida.org"></tt> for portions of the text on glib
+name="dwheeler@ida.org"></tt> for portions of the text on GLib
and various tutorial fixups and improvements.
-The glib text was in turn based on material developed by Damon Chaplin
+The GLib text was in turn based on material developed by Damon Chaplin
<tt><htmlurl url="mailto:DAChaplin@msn.com" name="DAChaplin@msn.com"></tt>
+
+<item>David King for style checking the entire document.
</itemize>
-And to all of you who commented and helped refine this document.
+And to all of you who commented on and helped refine this document.
Thanks.
<sect> GDK Event Types<label id="sec_GDK_Event_Types">
<!-- ***************************************************************** -->
<p>
-The follwing data types are passed into event handlers by GTK+. For
+The following data types are passed into event handlers by GTK+. For
each data type listed, the signals that use this data type are listed.
<itemize>
<tscreen><verb>
/* example-start tictactoe tictactoe.h */
-/* GTK - The GIMP Toolkit
+/* GTK - The GTK+ Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
<tscreen><verb>
/* example-start tictactoe tictactoe.c */
-/* GTK - The GIMP Toolkit
+/* GTK - The GTK+ Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
#include <gtk/gtk.h>
#include "tictactoe.h"
-void
-win (GtkWidget *widget, gpointer data)
+void win( GtkWidget *widget,
+ gpointer data )
{
g_print ("Yay!\n");
tictactoe_clear (TICTACTOE (widget));
}
-int
-main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
GtkWidget *ttt;
<tscreen><verb>
/* example-start gtkdial gtkdial.h */
-/* GTK - The GIMP Toolkit
+/* GTK - The GTK+ Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
/* Current angle */
gfloat angle;
+ gfloat last_angle;
/* Old values from adjustment stored so we know when something changes */
gfloat old_value;
<tscreen><verb>
/* example-start gtkdial gtkdial.c */
-/* GTK - The GIMP Toolkit
+/* GTK - The GTK+ Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
dial = gtk_type_new (gtk_dial_get_type ());
if (!adjustment)
- adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0,
- 0.0, 0.0, 0.0);
+ adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
gtk_dial_set_adjustment (dial, adjustment);
if (dial->adjustment)
{
- gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment),
- (gpointer) dial);
+ gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
gtk_object_unref (GTK_OBJECT (dial->adjustment));
}
attributes.colormap = gtk_widget_get_colormap (widget);
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- widget->window = gdk_window_new (widget->parent->window,
- &attributes,
- attributes_mask);
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
widget->style = gtk_style_attach (widget->style, widget->window);
GdkEventExpose *event)
{
GtkDial *dial;
- GdkPoint points[3];
+ GdkPoint points[6];
gdouble s,c;
- gdouble theta;
+ gdouble theta, last, increment;
+ GtkStyle *blankstyle;
gint xc, yc;
+ gint upper, lower;
gint tick_length;
- gint i;
+ gint i, inc;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
dial = GTK_DIAL (widget);
- gdk_window_clear_area (widget->window,
+/* gdk_window_clear_area (widget->window,
0, 0,
widget->allocation.width,
widget->allocation.height);
-
+*/
xc = widget->allocation.width/2;
yc = widget->allocation.height/2;
+ upper = dial->adjustment->upper;
+ lower = dial->adjustment->lower;
+
+ /* Erase old pointer */
+
+ s = sin(dial->last_angle);
+ c = cos(dial->last_angle);
+ dial->last_angle = dial->angle;
+
+ points[0].x = xc + s*dial->pointer_width/2;
+ points[0].y = yc + c*dial->pointer_width/2;
+ points[1].x = xc + c*dial->radius;
+ points[1].y = yc - s*dial->radius;
+ points[2].x = xc - s*dial->pointer_width/2;
+ points[2].y = yc - c*dial->pointer_width/2;
+ points[3].x = xc - c*dial->radius/10;
+ points[3].y = yc + s*dial->radius/10;
+ points[4].x = points[0].x;
+ points[4].y = points[0].y;
+
+ blankstyle = gtk_style_new ();
+ blankstyle->bg_gc[GTK_STATE_NORMAL] =
+ widget->style->bg_gc[GTK_STATE_NORMAL];
+ blankstyle->dark_gc[GTK_STATE_NORMAL] =
+ widget->style->bg_gc[GTK_STATE_NORMAL];
+ blankstyle->light_gc[GTK_STATE_NORMAL] =
+ widget->style->bg_gc[GTK_STATE_NORMAL];
+ blankstyle->black_gc =
+ widget->style->bg_gc[GTK_STATE_NORMAL];
+
+ gtk_draw_polygon (blankstyle,
+ widget->window,
+ GTK_STATE_NORMAL,
+ GTK_SHADOW_OUT,
+ points, 5,
+ FALSE);
+
+ gtk_style_unref(blankstyle);
+
+
/* Draw ticks */
- for (i=0; i<25; i++)
+ if ((upper - lower) == 0)
+ return;
+
+ increment = (100*M_PI)/(dial->radius*dial->radius);
+
+ inc = (upper - lower);
+
+ while (inc < 100) inc *=10;
+ while (inc >= 1000) inc /=10;
+ last = -1;
+
+ for (i=0; i<=inc; i++)
{
- theta = (i*M_PI/18. - M_PI/6.);
+ theta = ((gfloat)i*M_PI/(18*inc/24.) - M_PI/6.);
+
+ if ((theta - last) < (increment))
+ continue;
+ last = theta;
+
s = sin(theta);
c = cos(theta);
- tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
-
+ tick_length = (i%(inc/10) == 0) ? dial->pointer_width : dial->pointer_width/2;
+
gdk_draw_line (widget->window,
- widget->style->fg_gc[widget->state],
- xc + c*(dial->radius - tick_length),
- yc - s*(dial->radius - tick_length),
- xc + c*dial->radius,
- yc - s*dial->radius);
+ widget->style->fg_gc[widget->state],
+ xc + c*(dial->radius - tick_length),
+ yc - s*(dial->radius - tick_length),
+ xc + c*dial->radius,
+ yc - s*dial->radius);
}
/* Draw pointer */
s = sin(dial->angle);
c = cos(dial->angle);
-
+ dial->last_angle = dial->angle;
points[0].x = xc + s*dial->pointer_width/2;
points[0].y = yc + c*dial->pointer_width/2;
points[1].y = yc - s*dial->radius;
points[2].x = xc - s*dial->pointer_width/2;
points[2].y = yc - c*dial->pointer_width/2;
+ points[3].x = xc - c*dial->radius/10;
+ points[3].y = yc + s*dial->radius/10;
+ points[4].x = points[0].x;
+ points[4].y = points[0].y;
+
gtk_draw_polygon (widget->style,
widget->window,
GTK_STATE_NORMAL,
GTK_SHADOW_OUT,
- points, 3,
+ points, 5,
TRUE);
-
+
return FALSE;
}
if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
(dial->old_value != dial->adjustment->value))
- gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
- "value_changed");
+ gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
}
return FALSE;
g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
if (dial->policy == GTK_UPDATE_DELAYED)
- gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
- "value_changed");
+ gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
return FALSE;
}
{
if (dial->policy == GTK_UPDATE_CONTINUOUS)
{
- gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
- "value_changed");
+ gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
}
else
{
gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
}
- dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) *
- 4.*M_PI/3. /
+ dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
(dial->adjustment->upper - dial->adjustment->lower);
gtk_widget_draw (GTK_WIDGET(dial), NULL);
dial->old_value = adjustment->value;
}
}
-/* example-end */
+/* example-end */
+
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect2> dial_test.c
+<p>
+<tscreen><verb>
+#include <stdio.h>
+#include <gtk/gtk.h>
+#include "gtkdial.h"
+
+void value_changed( GtkAdjustment *adjustment,
+ GtkWidget *label )
+{
+ char buffer[16];
+
+ sprintf(buffer,"%4.2f",adjustment->value);
+ gtk_label_set (GTK_LABEL (label), buffer);
+}
+
+int main( int argc,
+ char *argv[])
+{
+ GtkWidget *window;
+ GtkAdjustment *adjustment;
+ GtkWidget *dial;
+ GtkWidget *frame;
+ GtkWidget *vbox;
+ GtkWidget *label;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Dial");
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_exit), NULL);
+
+ gtk_container_border_width (GTK_CONTAINER (window), 10);
+
+ vbox = gtk_vbox_new (FALSE, 5);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+ gtk_widget_show(vbox);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (vbox), frame);
+ gtk_widget_show (frame);
+
+ adjustment = GTK_ADJUSTMENT(gtk_adjustment_new (0, 0, 100, 0.01, 0.1, 0));
+
+ dial = gtk_dial_new(adjustment);
+ gtk_dial_set_update_policy (GTK_DIAL(dial), GTK_UPDATE_DELAYED);
+ /* gtk_widget_set_usize (dial, 100, 100); */
+
+ gtk_container_add (GTK_CONTAINER (frame), dial);
+ gtk_widget_show (dial);
+
+ label = gtk_label_new("0.00");
+ gtk_box_pack_end (GTK_BOX(vbox), label, 0, 0, 0);
+ gtk_widget_show (label);
+
+ gtk_signal_connect (GTK_OBJECT(adjustment), "value_changed",
+ GTK_SIGNAL_FUNC (value_changed), label);
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+}
+
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
<sect1> Scribble
<p>
+<!-- ----------------------------------------------------------------- -->
+<sect2> scribble-simple.c
+<p>
<tscreen><verb>
/* example-start scribble-simple scribble-simple.c */
-/* GTK - The GIMP Toolkit
+/* GTK - The GTK+ Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
static GdkPixmap *pixmap = NULL;
/* Create a new backing pixmap of the appropriate size */
-static gint
-configure_event (GtkWidget *widget, GdkEventConfigure *event)
+static gint configure_event( GtkWidget *widget,
+ GdkEventConfigure *event )
{
if (pixmap)
gdk_pixmap_unref(pixmap);
}
/* Redraw the screen from the backing pixmap */
-static gint
-expose_event (GtkWidget *widget, GdkEventExpose *event)
+static gint expose_event( GtkWidget *widget,
+ GdkEventExpose *event )
{
gdk_draw_pixmap(widget->window,
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
}
/* Draw a rectangle on the screen */
-static void
-draw_brush (GtkWidget *widget, gdouble x, gdouble y)
+static void draw_brush( GtkWidget *widget,
+ gdouble x,
+ gdouble y)
{
GdkRectangle update_rect;
gtk_widget_draw (widget, &update_rect);
}
-static gint
-button_press_event (GtkWidget *widget, GdkEventButton *event)
+static gint button_press_event( GtkWidget *widget,
+ GdkEventButton *event )
{
if (event->button == 1 && pixmap != NULL)
draw_brush (widget, event->x, event->y);
return TRUE;
}
-static gint
-motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
+static gint motion_notify_event( GtkWidget *widget,
+ GdkEventMotion *event )
{
int x, y;
GdkModifierType state;
return TRUE;
}
-void
-quit ()
+void quit ()
{
gtk_exit (0);
}
-int
-main (int argc, char *argv[])
+int main( int argc,
+ char *argv[] )
{
GtkWidget *window;
GtkWidget *drawing_area;
/* example-end */
</verb></tscreen>
+<!-- ----------------------------------------------------------------- -->
+<sect2> scribble-xinput.c
+<p>
+<tscreen><verb>
+/* example-start scribble-xinput scribble-xinput.c */
+
+/* GTK - The GTK+ Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+
+/* Backing pixmap for drawing area */
+static GdkPixmap *pixmap = NULL;
+
+/* Create a new backing pixmap of the appropriate size */
+static gint
+configure_event (GtkWidget *widget, GdkEventConfigure *event)
+{
+ if (pixmap)
+ gdk_pixmap_unref(pixmap);
+
+ pixmap = gdk_pixmap_new(widget->window,
+ widget->allocation.width,
+ widget->allocation.height,
+ -1);
+ gdk_draw_rectangle (pixmap,
+ widget->style->white_gc,
+ TRUE,
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ return TRUE;
+}
+
+/* Redraw the screen from the backing pixmap */
+static gint
+expose_event (GtkWidget *widget, GdkEventExpose *event)
+{
+ gdk_draw_pixmap(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ pixmap,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ return FALSE;
+}
+
+/* Draw a rectangle on the screen, size depending on pressure,
+ and color on the type of device */
+static void
+draw_brush (GtkWidget *widget, GdkInputSource source,
+ gdouble x, gdouble y, gdouble pressure)
+{
+ GdkGC *gc;
+ GdkRectangle update_rect;
+
+ switch (source)
+ {
+ case GDK_SOURCE_MOUSE:
+ gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
+ break;
+ case GDK_SOURCE_PEN:
+ gc = widget->style->black_gc;
+ break;
+ case GDK_SOURCE_ERASER:
+ gc = widget->style->white_gc;
+ break;
+ default:
+ gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
+ }
+
+ update_rect.x = x - 10 * pressure;
+ update_rect.y = y - 10 * pressure;
+ update_rect.width = 20 * pressure;
+ update_rect.height = 20 * pressure;
+ gdk_draw_rectangle (pixmap, gc, TRUE,
+ update_rect.x, update_rect.y,
+ update_rect.width, update_rect.height);
+ gtk_widget_draw (widget, &update_rect);
+}
+
+static void
+print_button_press (guint32 deviceid)
+{
+ GList *tmp_list;
+
+ /* gdk_input_list_devices returns an internal list, so we shouldn't
+ free it afterwards */
+ tmp_list = gdk_input_list_devices();
+
+ while (tmp_list)
+ {
+ GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
+
+ if (info->deviceid == deviceid)
+ {
+ g_print("Button press on device '%s'\n", info->name);
+ return;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+}
+
+static gint
+button_press_event (GtkWidget *widget, GdkEventButton *event)
+{
+ print_button_press (event->deviceid);
+
+ if (event->button == 1 && pixmap != NULL)
+ draw_brush (widget, event->source, event->x, event->y, event->pressure);
+
+ return TRUE;
+}
+
+static gint
+motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
+{
+ gdouble x, y;
+ gdouble pressure;
+ GdkModifierType state;
+
+ if (event->is_hint)
+ gdk_input_window_get_pointer (event->window, event->deviceid,
+ &x, &y, &pressure,
+ NULL, NULL, &state);
+ else
+ {
+ x = event->x;
+ y = event->y;
+ pressure = event->pressure;
+ state = event->state;
+ }
+
+ if (state & GDK_BUTTON1_MASK && pixmap != NULL)
+ draw_brush (widget, event->source, x, y, pressure);
+
+ return TRUE;
+}
+
+void
+input_dialog_destroy (GtkWidget *w, gpointer data)
+{
+ *((GtkWidget **)data) = NULL;
+}
+
+void
+create_input_dialog ()
+{
+ static GtkWidget *inputd = NULL;
+
+ if (!inputd)
+ {
+ inputd = gtk_input_dialog_new();
+
+ gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
+ (GtkSignalFunc)input_dialog_destroy, &inputd);
+ gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
+ "clicked",
+ (GtkSignalFunc)gtk_widget_hide,
+ GTK_OBJECT(inputd));
+ gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
+
+ gtk_widget_show (inputd);
+ }
+ else
+ {
+ if (!GTK_WIDGET_MAPPED(inputd))
+ gtk_widget_show(inputd);
+ else
+ gdk_window_raise(inputd->window);
+ }
+}
+
+void
+quit ()
+{
+ gtk_exit (0);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *drawing_area;
+ GtkWidget *vbox;
+
+ GtkWidget *button;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_name (window, "Test Input");
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+ gtk_widget_show (vbox);
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (quit), NULL);
+
+ /* Create the drawing area */
+
+ drawing_area = gtk_drawing_area_new ();
+ gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
+ gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
+
+ gtk_widget_show (drawing_area);
+
+ /* Signals used to handle backing pixmap */
+
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
+ (GtkSignalFunc) expose_event, NULL);
+ gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
+ (GtkSignalFunc) configure_event, NULL);
+
+ /* Event signals */
+
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
+ (GtkSignalFunc) motion_notify_event, NULL);
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
+ (GtkSignalFunc) button_press_event, NULL);
+
+ gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
+ | GDK_LEAVE_NOTIFY_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK);
+
+ /* The following call enables tracking and processing of extension
+ events for the drawing area */
+ gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
+
+ /* .. And some buttons */
+ button = gtk_button_new_with_label ("Input Dialog");
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (create_input_dialog), NULL);
+ gtk_widget_show (button);
+
+ button = gtk_button_new_with_label ("Quit");
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ GTK_OBJECT (window));
+ gtk_widget_show (button);
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+}
+/* example-end */
+</verb></tscreen>
+
<!-- ***************************************************************** -->
<sect> List Widget
<!-- ***************************************************************** -->
<p>
-NOTE: The GtkList widget has been superseded by the GtkCList
-widget. It is detailed here just for completeness.
+NOTE: The List widget has been superseded by the CList widget. It is
+detailed here just for completeness.
-The GtkList widget is designed to act as a vertical container for
-widgets that should be of the type GtkListItem.
+The List widget is designed to act as a vertical container for
+widgets that should be of the type ListItem.
-A GtkList widget has its own window to receive events and its own
+A List widget has its own window to receive events and its own
background color which is usually white. As it is directly derived
-from a GtkContainer it can be treated as such by using the
-GTK_CONTAINER(List) macro, see the GtkContainer widget for more on
+from a Container it can be treated as such by using the
+GTK_CONTAINER(List) macro, see the Container widget for more on
this. One should already be familiar with the usage of a GList and
-its related functions g_list_*() to be able to use the GtkList widget
+its related functions g_list_*() to be able to use the List widget
to it full extent.
-There is one field inside the structure definition of the GtkList
+There is one field inside the structure definition of the List
widget that will be of greater interest to us, this is:
<tscreen><verb>
};
</verb></tscreen>
-The selection field of a GtkList points to a linked list of all items
+The selection field of a List points to a linked list of all items
that are currently selected, or NULL if the selection is empty. So to
learn about the current selection we read the GTK_LIST()->selection
field, but do not modify it since the internal fields are maintained
by the gtk_list_*() functions.
-The selection_mode of the GtkList determines the selection facilities
-of a GtkList and therefore the contents of the GTK_LIST()->selection
+The selection_mode of the List determines the selection facilities
+of a List and therefore the contents of the GTK_LIST()->selection
field. The selection_mode may be one of the following:
<itemize>
-<item> GTK_SELECTION_SINGLE - The selection is either NULL
+<item> <tt/GTK_SELECTION_SINGLE/ - The selection is either NULL
or contains a GList pointer
for a single selected item.
-<item> GTK_SELECTION_BROWSE - The selection is NULL if the list
+<item> <tt/GTK_SELECTION_BROWSE/ - The selection is NULL if the list
contains no widgets or insensitive
ones only, otherwise it contains
a GList pointer for one GList
structure, and therefore exactly
one list item.
-<item> GTK_SELECTION_MULTIPLE - The selection is NULL if no list
+<item> <tt/GTK_SELECTION_MULTIPLE/ - The selection is NULL if no list
items are selected or a GList pointer
for the first selected item. That
in turn points to a GList structure
for the second selected item and so
on.
-<item> GTK_SELECTION_EXTENDED - The selection is always NULL.
+<item> <tt/GTK_SELECTION_EXTENDED/ - The selection is always NULL.
</itemize>
-The default is GTK_SELECTION_MULTIPLE.
+The default is <tt/GTK_SELECTION_MULTIPLE/.
<!-- ----------------------------------------------------------------- -->
<sect1> Signals
void selection_changed( GtkList *list );
</verb></tscreen>
-This signal will be invoked whenever the selection field of a GtkList
-has changed. This happens when a child of the GtkList got selected or
+This signal will be invoked whenever the selection field of a List
+has changed. This happens when a child of thekList got selected or
deselected.
<tscreen><verb>
GtkWidget *child);
</verb></tscreen>
-This signal is invoked when a child of the GtkList is about to get
+This signal is invoked when a child of the List is about to get
selected. This happens mainly on calls to gtk_list_select_item(),
gtk_list_select_child(), button presses and sometimes indirectly
triggered on some else occasions where children get added to or
-removed from the GtkList.
+removed from the List.
<tscreen><verb>
void unselect_child( GtkList *list,
GtkWidget *child );
</verb></tscreen>
-This signal is invoked when a child of the GtkList is about to get
+This signal is invoked when a child of the List is about to get
deselected. This happens mainly on calls to gtk_list_unselect_item(),
gtk_list_unselect_child(), button presses and sometimes indirectly
triggered on some else occasions where children get added to or
-removed from the GtkList.
+removed from the List.
<!-- ----------------------------------------------------------------- -->
<sect1> Functions
guint gtk_list_get_type( void );
</verb></tscreen>
-Returns the `GtkList' type identifier.
+Returns the "GtkList" type identifier.
<tscreen><verb>
GtkWidget *gtk_list_new( void );
</verb></tscreen>
-Create a new GtkList object. The new widget is returned as a pointer
+Create a new List object. The new widget is returned as a pointer
to a GtkWidget object. NULL is returned on failure.
<tscreen><verb>
Insert list items into the list, starting at <tt/position/.
<tt/items/ is a doubly linked list where each nodes data pointer is
-expected to point to a newly created GtkListItem. The GList nodes of
+expected to point to a newly created ListItem. The GList nodes of
<tt/items/ are taken over by the list.
<tscreen><verb>
GtkList *GTK_LIST( gpointer obj );
</verb></tscreen>
-Cast a generic pointer to `GtkList *'. *Note Standard Macros::, for
-more info.
+Cast a generic pointer to "GtkList *".
<tscreen><verb>
GtkListClass *GTK_LIST_CLASS( gpointer class);
</verb></tscreen>
-Cast a generic pointer to `GtkListClass*'. *Note Standard Macros::,
-for more info.
+Cast a generic pointer to "GtkListClass *".
<tscreen><verb>
gint GTK_IS_LIST( gpointer obj);
</verb></tscreen>
-Determine if a generic pointer refers to a `GtkList' object. *Note
-Standard Macros::, for more info.
+Determine if a generic pointer refers to a "GtkList" object.
<!-- ----------------------------------------------------------------- -->
<sect1> Example
<p>
Following is an example program that will print out the changes of the
-selection of a GtkList, and lets you "arrest" list items into a prison
+selection of a List, and lets you "arrest" list items into a prison
by selecting them with the rightmost mouse button.
<tscreen><verb>
/* example-start list list.c */
-/* Include the gtk+ header files
+/* Include the GTK header files
* Include stdio.h, we need that for the printf() function
*/
#include <gtk/gtk.h>
/* prototypes for signal handler that we are going to connect
- * to the GtkList widget
+ * to the List widget
*/
static void sigh_print_selection( GtkWidget *gtklist,
gpointer func_data);
/* Main function to set up the user interface */
-gint main (int argc,
- gchar *argv[])
+gint main( int argc,
+ gchar *argv[] )
{
GtkWidget *separator;
GtkWidget *window;
gchar buffer[64];
- /* Initialize gtk+ (and subsequently gdk) */
+ /* Initialize GTK (and subsequently GDK) */
gtk_init(&argc, &argv);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show(vbox);
- /* This is the scrolled window to put the GtkList widget inside */
+ /* This is the scrolled window to put the List widget inside */
scrolled_window=gtk_scrolled_window_new(NULL, NULL);
gtk_widget_set_usize(scrolled_window, 250, 150);
gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
gtk_widget_show(scrolled_window);
- /* Create the GtkList widget.
+ /* Create thekList widget.
* Connect the sigh_print_selection() signal handler
- * function to the "selection_changed" signal of the GtkList
+ * function to the "selection_changed" signal of the List
* to print out the selected items each time the selection
* has changed */
gtklist=gtk_list_new();
gtk_container_add(GTK_CONTAINER(vbox), frame);
gtk_widget_show(frame);
- /* Connect the sigh_button_event() signal handler to the GtkList
+ /* Connect the sigh_button_event() signal handler to the List
* which will handle the "arresting" of list items
*/
gtk_signal_connect(GTK_OBJECT(gtklist),
/* Now we create 5 list items, each having its own
- * label and add them to the GtkList using gtk_container_add()
+ * label and add them to the List using gtk_container_add()
* Also we query the text string from the label and
* associate it with the list_item_data_key for each list item
*/
}
/* This is the signal handler that got connected to button
- * press/release events of the GtkList
+ * press/release events of the List
*/
void sigh_button_event( GtkWidget *gtklist,
GdkEventButton *event,
g_list_free(free_list);
/* If we have a new prisoner, remove him from the
- * GtkList and put him into the frame "Prison".
+ * List and put him into the frame "Prison".
* We need to unselect the item first.
*/
if (new_prisoner) {
}
}
-/* This is the signal handler that gets called if GtkList
+/* This is the signal handler that gets called if List
* emits the "selection_changed" signal
*/
void sigh_print_selection( GtkWidget *gtklist,
- gpointer func_data)
+ gpointer func_data )
{
GList *dlist;
/* Fetch the doubly linked list of selected items
- * of the GtkList, remember to treat this as read-only!
+ * of the List, remember to treat this as read-only!
*/
dlist=GTK_LIST(gtklist)->selection;
<!-- ----------------------------------------------------------------- -->
<sect1> List Item Widget
<p>
-The GtkListItem widget is designed to act as a container holding up to
+The ListItem widget is designed to act as a container holding up to
one child, providing functions for selection/deselection just like the
-GtkList widget requires them for its children.
+List widget requires them for its children.
-A GtkListItem has its own window to receive events and has its own
+A ListItem has its own window to receive events and has its own
background color which is usually white.
-As it is directly derived from a GtkItem it can be treated as such by
-using the GTK_ITEM(ListItem) macro, see the GtkItem widget for more on
-this. Usually a GtkListItem just holds a label to identify e.g. a
-filename within a GtkList -- therefore the convenience function
+As it is directly derived from an Item it can be treated as such by
+using the GTK_ITEM(ListItem) macro, see the Item widget for more on
+this. Usually a ListItem just holds a label to identify, e.g., a
+filename within a List -- therefore the convenience function
gtk_list_item_new_with_label() is provided. The same effect can be
-achieved by creating a GtkLabel on its own, setting its alignment to
+achieved by creating a Label on its own, setting its alignment to
xalign=0 and yalign=0.5 with a subsequent container addition to the
-GtkListItem.
+ListItem.
As one is not forced to add a GtkLabel to a GtkListItem, you could
also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
<!-- ----------------------------------------------------------------- -->
<sect1> Signals
<p>
-A GtkListItem does not create new signals on its own, but inherits
-the signals of a GtkItem. *Note GtkItem::, for more info.
+AkListItem does not create new signals on its own, but inherits
+the signals of a Item.
<!-- ----------------------------------------------------------------- -->
<sect1> Functions
guint gtk_list_item_get_type( void );
</verb></tscreen>
-Returns the `GtkListItem' type identifier.
+Returns the "GtkListItem" type identifier.
<tscreen><verb>
GtkWidget *gtk_list_item_new( void );
</verb></tscreen>
-Create a new GtkListItem object. The new widget is returned as a
+Create a new ListItem object. The new widget is returned as a
pointer to a GtkWidget object. NULL is returned on failure.
<tscreen><verb>
GtkWidget *gtk_list_item_new_with_label( gchar *label );
</verb></tscreen>
-Create a new GtkListItem object, having a single GtkLabel as the sole
+Create a new ListItem object, having a single GtkLabel as the sole
child. The new widget is returned as a pointer to a GtkWidget
object. NULL is returned on failure.
GtkListItem *GTK_LIST_ITEM( gpointer obj );
</verb></tscreen>
-Cast a generic pointer to `GtkListItem*'. *Note Standard Macros::, for
-more info.
+Cast a generic pointer to "GtkListItem *".
<tscreen><verb>
GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
<!-- ----------------------------------------------------------------- -->
<sect1> Example
<p>
-Please see the GtkList example on this, which covers the usage of a
-GtkListItem as well.
+Please see the List example on this, which covers the usage of a
+ListItem as well.
</article>