]> Pileus Git - ~andy/gtk/blob - docs/tutorial/gtk-tut.sgml
Don't include strings.h, it's not needed anymore. (#112388)
[~andy/gtk] / docs / tutorial / gtk-tut.sgml
1 <!doctype book PUBLIC "-//OASIS//DTD DocBook V3.1//EN" [
2 <!notation PNG system "PNG">
3 <!entity % local.notation.class "| PNG">
4 ]>
5 <book id="gtk-tut">
6
7 <bookinfo>
8     <date>January 24th, 2003</date>
9     <title>GTK+ 2.0 Tutorial</title>
10     <authorgroup>
11       <author>
12         <firstname>Tony</firstname>
13         <surname>Gale</surname>
14       </author>
15       <author>
16         <firstname>Ian</firstname>
17         <surname>Main</surname>
18       </author>
19       <author>
20         <firstname>&amp; the GTK team</firstname>
21       </author>
22     </authorgroup>
23     <abstract>
24       <para>This is a tutorial on how to use GTK (the GIMP Toolkit) through its C
25             interface.</para>
26     </abstract>
27   </bookinfo>
28
29 <toc></toc>
30
31 <!-- ***************************************************************** -->
32 <chapter id="ch-TutorialDownload">
33 <title>Tutorial Availability</title>
34
35 <para>A copy of this tutorial in SGML and HTML is distributed with each
36 source code release of GTK+. For binary distributions, please check with
37 your vendor.</para>
38
39 <para>A copy is available online for reference at <ulink 
40 url="http://www.gtk.org/tutorial/">http://www.gtk.org/tutorial</ulink>.</para>
41
42 <para>A packaged verion of this tutorial is available from
43 <ulink url="ftp://ftp.gtk.org/pub/gtk/tutorial/">
44 ftp://ftp.gtk.org/pub/gtk/tutorial</ulink> which contains the tutorial in
45 various different formats. This
46 package is primary for those people wanting to have the tutorial
47 available for offline reference and for printing.</para>
48
49 </chapter>
50
51 <!-- ***************************************************************** -->
52 <chapter id="ch-Introduction">
53 <title>Introduction</title>
54
55 <para>GTK (GIMP Toolkit) is a library for creating graphical user
56 interfaces. It is licensed using the LGPL license, so you can develop
57 open software, free software, or even commercial non-free software
58 using GTK without having to spend anything for licenses or royalties.</para>
59
60 <para>It's called the GIMP toolkit because it was originally written for
61 developing the GNU Image Manipulation Program (GIMP), but GTK has
62 now been used in a large number of software projects, including the
63 GNU Network Object Model Environment (GNOME) project. GTK is built on
64 top of GDK (GIMP Drawing Kit) which is basically a wrapper around the
65 low-level functions for accessing the underlying windowing functions
66 (Xlib in the case of the X windows system), and gdk-pixbuf, a library for
67 client-side image manipulation.
68 </para>
69 <para>The primary authors of GTK are:</para>
70
71 <itemizedlist>
72 <listitem><simpara> Peter Mattis <ulink url="mailto:petm@xcf.berkeley.edu">
73 petm@xcf.berkeley.edu</ulink></simpara>
74 </listitem>
75 <listitem><simpara> Spencer Kimball <ulink url="mailto:spencer@xcf.berkeley.edu">
76 spencer@xcf.berkeley.edu</ulink></simpara>
77 </listitem>
78 <listitem><simpara> Josh MacDonald <ulink url="mailto:jmacd@xcf.berkeley.edu">
79 jmacd@xcf.berkeley.edu</ulink></simpara>
80 </listitem>
81 </itemizedlist>
82
83 <para>GTK is currently maintained by:</para>
84
85 <itemizedlist>
86 <listitem><simpara> Owen Taylor <ulink url="mailto:otaylor@redhat.com">
87 otaylor@redhat.com</ulink></simpara>
88 </listitem>
89 <listitem><simpara> Tim Janik <ulink url="mailto:timj@gtk.org">
90 timj@gtk.org</ulink></simpara>
91 </listitem>
92 </itemizedlist>
93
94 <para>GTK is essentially an object oriented application programmers
95 interface (API). Although written completely in C, it is implemented
96 using the idea of classes and callback functions (pointers to
97 functions).</para>
98
99 <para>There is also a third component called GLib which contains a few
100 replacements for some standard calls, as well as some additional
101 functions for handling linked lists, etc. The replacement functions
102 are used to increase GTK's portability, as some of the functions
103 implemented here are not available or are nonstandard on other Unixes
104 such as g_strerror(). Some also contain enhancements to the libc
105 versions, such as g_malloc() that has enhanced debugging utilities.</para>
106
107 <para>In version 2.0, GLib has picked up the type system which forms the
108 foundation for GTK's class hierarchy, the signal system which is used
109 throughout GTK, a thread API which abstracts the different native thread APIs 
110 of the various platforms and a facility for loading modules.
111 </para>
112
113 <para>As the last component, GTK uses the Pango library for internationalized
114 text output.
115 </para>
116
117 <para>This tutorial describes the C interface to GTK. There are GTK
118 bindings for many other languages including C++, Guile, Perl, Python,
119 TOM, Ada95, Objective C, Free Pascal, Eiffel, Java and C#. If you intend to
120 use another language's bindings to GTK, look at that binding's
121 documentation first. In some cases that documentation may describe
122 some important conventions (which you should know first) and then
123 refer you back to this tutorial. There are also some cross-platform
124 APIs (such as wxWindows and V) which use GTK as one of their target
125 platforms; again, consult their documentation first.</para>
126
127 <para>If you're developing your GTK application in C++, a few extra notes
128 are in order. There's a C++ binding to GTK called GTK--, which
129 provides a more C++-like interface to GTK; you should probably look
130 into this instead. If you don't like that approach for whatever
131 reason, there are two alternatives for using GTK. First, you can use
132 only the C subset of C++ when interfacing with GTK and then use the C
133 interface as described in this tutorial. Second, you can use GTK and
134 C++ together by declaring all callbacks as static functions in C++
135 classes, and again calling GTK using its C interface. If you choose
136 this last approach, you can include as the callback's data value a
137 pointer to the object to be manipulated (the so-called "this" value).
138 Selecting between these options is simply a matter of preference,
139 since in all three approaches you get C++ and GTK. None of these
140 approaches requires the use of a specialized preprocessor, so no
141 matter what you choose you can use standard C++ with GTK.</para>
142
143 <para>This tutorial is an attempt to document as much as possible of GTK,
144 but it is by no means complete. This tutorial assumes a good
145 understanding of C, and how to create C programs. It would be a great
146 benefit for the reader to have previous X programming experience, but
147 it shouldn't be necessary. If you are learning GTK as your first
148 widget set, please comment on how you found this tutorial, and what
149 you had trouble with. There are also C++, Objective C, ADA, Guile and
150 other language bindings available, but I don't follow these.</para>
151
152 <para>This document is a "work in progress". Please look for updates on
153 <ulink url="http://www.gtk.org/">http://www.gtk.org/</ulink>.</para>
154
155 <para>I would very much like to hear of any problems you have learning GTK
156 from this document, and would appreciate input as to how it may be
157 improved. Please see the section on <link linkend="ch-Contributing">Contributing
158 </link> for further information.</para>
159
160 </chapter>
161
162 <!-- ***************************************************************** -->
163 <chapter id="ch-GettingStarted">
164 <title>Getting Started</title>
165
166 <para>The first thing to do, of course, is download the GTK source and
167 install it. You can always get the latest version from <ulink 
168 url="ftp://ftp.gtk.org/pub/gtk">ftp.gtk.org</ulink>. You can also view 
169 other sources of GTK information on
170 <ulink url="http://www.gtk.org/">http://www.gtk.org/</ulink>. GTK
171 uses GNU autoconf for configuration. Once untar'd, type 
172 <literal>./configure --help</literal> to see a list of options.</para>
173
174 <para>The GTK source distribution also contains the complete source to all
175 of the examples used in this tutorial, along with Makefiles to aid
176 compilation.</para>
177
178 <para>To begin our introduction to GTK, we'll start with the simplest
179 program possible. This program will create a 200x200 pixel window and
180 has no way of exiting except to be killed by using the shell.</para>
181
182 <para>
183 <inlinemediaobject>
184 <imageobject>
185 <imagedata fileref="images/base.png" format="png">
186 </imageobject>
187 </inlinemediaobject>
188 </para>
189
190 <programlisting role="C">
191 <!-- example-start base base.c -->
192
193 #include &lt;gtk/gtk.h&gt;
194
195 int main( int   argc,
196           char *argv[] )
197 {
198     GtkWidget *window;
199     
200     gtk_init (&amp;argc, &amp;argv);
201     
202     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
203     gtk_widget_show  (window);
204     
205     gtk_main ();
206     
207     return 0;
208 }
209 <!-- example-end -->
210 </programlisting>
211
212 <para>You can compile the above program with gcc using:</para>
213 <para><literallayout>
214 <literal>gcc base.c -o base `pkg-config --cflags --libs gtk+-2.0`</literal>
215 </literallayout></para>
216
217 <para>The meaning of the unusual compilation options is explained below in
218 <link linkend="sec-Compiling">Compiling Hello World</link>.</para>
219
220 <para>All programs will of course include <filename>gtk/gtk.h</filename> which 
221 declares the variables, functions, structures, etc. that will be used in your GTK
222 application.</para>
223
224 <para>The next line:</para>
225
226 <programlisting role="C">
227 gtk_init (&amp;argc, &amp;argv);
228 </programlisting>
229
230 <para>calls the function gtk_init(gint *argc, gchar ***argv) which will be called 
231 in all GTK applications. This sets up a few things for us such as the default visual 
232 and color map and then proceeds to call gdk_init(gint *argc, gchar ***argv). 
233 This function initializes the library for use, sets up default signal handlers, and 
234 checks the arguments passed to your application on the command line, looking for
235 one of the following:</para>
236
237 <itemizedlist spacing=Compact>
238 <listitem><simpara> <literal>--gtk-module</literal></simpara>
239 </listitem>
240 <listitem><simpara> <literal>--g-fatal-warnings</literal></simpara>
241 </listitem>
242 <listitem><simpara> <literal>--gtk-debug</literal></simpara>
243 </listitem>
244 <listitem><simpara> <literal>--gtk-no-debug</literal></simpara>
245 </listitem>
246 <listitem><simpara> <literal>--gdk-debug</literal></simpara>
247 </listitem>
248 <listitem><simpara> <literal>--gdk-no-debug</literal></simpara>
249 </listitem>
250 <listitem><simpara> <literal>--display</literal></simpara>
251 </listitem>
252 <listitem><simpara> <literal>--sync</literal></simpara>
253 </listitem>
254 <listitem><simpara> <literal>--name</literal></simpara>
255 </listitem>
256 <listitem><simpara> <literal>--class</literal></simpara>
257 </listitem>
258 </itemizedlist>
259
260 <para>It removes these from the argument list, leaving anything it does not
261 recognize for your application to parse or ignore. This creates a set
262 of standard arguments accepted by all GTK applications.</para>
263
264 <para>The next two lines of code create and display a window.</para>
265
266 <programlisting role="C">
267   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
268   gtk_widget_show (window);
269 </programlisting>
270
271 <para>The <literal>GTK_WINDOW_TOPLEVEL</literal> argument specifies that we want the
272 window to undergo window manager decoration and placement. Rather than
273 create a window of 0x0 size, a window without children is set to
274 200x200 by default so you can still manipulate it.</para>
275
276 <para>The gtk_widget_show() function lets GTK know that we are done setting
277 the attributes of this widget, and that it can display it.</para>
278
279 <para>The last line enters the GTK main processing loop.</para>
280
281 <programlisting role="C">
282   gtk_main ();
283 </programlisting>
284
285 <para>gtk_main() is another call you will see in every GTK application.
286 When control reaches this point, GTK will sleep waiting for X events
287 (such as button or key presses), timeouts, or file IO notifications to
288 occur. In our simple example, however, events are ignored.</para>
289
290 <!-- ----------------------------------------------------------------- -->
291 <sect1 id="sec-HelloWorld">
292 <title>Hello World in GTK</title>
293
294 <para>Now for a program with a widget (a button). It's the classic
295 hello world a la GTK.</para>
296
297 <para>
298 <inlinemediaobject>
299 <imageobject>
300 <imagedata fileref="images/helloworld.png" format="png">
301 </imageobject>
302 </inlinemediaobject>
303 </para>
304
305 <programlisting role="C">
306 <!-- example-start helloworld helloworld.c -->
307
308 #include &lt;gtk/gtk.h&gt;
309
310 /* This is a callback function. The data arguments are ignored
311  * in this example. More on callbacks below. */
312 static void hello( GtkWidget *widget,
313                    gpointer   data )
314 {
315     g_print ("Hello World\n");
316 }
317
318 static gboolean delete_event( GtkWidget *widget,
319                               GdkEvent  *event,
320                               gpointer   data )
321 {
322     /* If you return FALSE in the "delete_event" signal handler,
323      * GTK will emit the "destroy" signal. Returning TRUE means
324      * you don't want the window to be destroyed.
325      * This is useful for popping up 'are you sure you want to quit?'
326      * type dialogs. */
327
328     g_print ("delete event occurred\n");
329
330     /* Change TRUE to FALSE and the main window will be destroyed with
331      * a "delete_event". */
332
333     return TRUE;
334 }
335
336 /* Another callback */
337 static void destroy( GtkWidget *widget,
338                      gpointer   data )
339 {
340     gtk_main_quit ();
341 }
342
343 int main( int   argc,
344           char *argv[] )
345 {
346     /* GtkWidget is the storage type for widgets */
347     GtkWidget *window;
348     GtkWidget *button;
349     
350     /* This is called in all GTK applications. Arguments are parsed
351      * from the command line and are returned to the application. */
352     gtk_init (&amp;argc, &amp;argv);
353     
354     /* create a new window */
355     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
356     
357     /* When the window is given the "delete_event" signal (this is given
358      * by the window manager, usually by the "close" option, or on the
359      * titlebar), we ask it to call the delete_event () function
360      * as defined above. The data passed to the callback
361      * function is NULL and is ignored in the callback function. */
362     g_signal_connect (G_OBJECT (window), "delete_event",
363                       G_CALLBACK (delete_event), NULL);
364     
365     /* Here we connect the "destroy" event to a signal handler.  
366      * This event occurs when we call gtk_widget_destroy() on the window,
367      * or if we return FALSE in the "delete_event" callback. */
368     g_signal_connect (G_OBJECT (window), "destroy",
369                       G_CALLBACK (destroy), NULL);
370     
371     /* Sets the border width of the window. */
372     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
373     
374     /* Creates a new button with the label "Hello World". */
375     button = gtk_button_new_with_label ("Hello World");
376     
377     /* When the button receives the "clicked" signal, it will call the
378      * function hello() passing it NULL as its argument.  The hello()
379      * function is defined above. */
380     g_signal_connect (G_OBJECT (button), "clicked",
381                       G_CALLBACK (hello), NULL);
382     
383     /* This will cause the window to be destroyed by calling
384      * gtk_widget_destroy(window) when "clicked".  Again, the destroy
385      * signal could come from here, or the window manager. */
386     g_signal_connect_swapped (G_OBJECT (button), "clicked",
387                               G_CALLBACK (gtk_widget_destroy),
388                               G_OBJECT (window));
389     
390     /* This packs the button into the window (a gtk container). */
391     gtk_container_add (GTK_CONTAINER (window), button);
392     
393     /* The final step is to display this newly created widget. */
394     gtk_widget_show (button);
395     
396     /* and the window */
397     gtk_widget_show (window);
398     
399     /* All GTK applications must have a gtk_main(). Control ends here
400      * and waits for an event to occur (like a key press or
401      * mouse event). */
402     gtk_main ();
403     
404     return 0;
405 }
406 <!-- example-end -->
407 </programlisting>
408
409 </sect1>
410
411 <!-- ----------------------------------------------------------------- -->
412 <sect1 id="sec-Compiling">
413 <title>Compiling Hello World</title>
414
415 <para>To compile use:</para>
416
417 <para><literallayout>
418 <literal>gcc -Wall -g helloworld.c -o helloworld `pkg-config --cflags gtk+-2.0` \</literal>
419 <literal>    `pkg-config --libs gtk+-2.0`</literal>
420 </literallayout></para>
421
422 <para>This uses the program <literal>pkg-config</literal>, which can be obtained from
423 <ulink url="http://www.freedesktop.org">www.freedesktop.org</ulink>. This program 
424 reads the <filename>.pc</filename> which comes with GTK to determine what 
425 compiler switches are needed to compile programs that use GTK. 
426 <literal>pkg-config --cflags gtk+-2.0</literal> will output a list of include
427 directories for the compiler to look in, and 
428 <literal>pkg-config --libs gtk+-2.0</literal>
429 will output the list of libraries for the compiler to link with and
430 the directories to find them in. In the above example they could have
431 been combined into a single instance, such as
432 <literal>pkg-config --cflags --libs gtk+-2.0</literal>.</para>
433
434 <para>Note that the type of single quote used in the compile command above
435 is significant.</para>
436
437 <para>The libraries that are usually linked in are:</para>
438
439 <itemizedlist>
440 <listitem><simpara>The GTK library (<literal>-lgtk</literal>), the widget library, 
441 based on top of GDK.</simpara>
442 </listitem>
443
444 <listitem><simpara>The GDK library (<literal>-lgdk</literal>), the Xlib wrapper.</simpara>
445 </listitem>
446
447 <listitem><simpara>The gdk-pixbuf library (<literal>-lgdk_pixbuf</literal>), the image 
448 manipulation library.</simpara>
449 </listitem>
450
451 <listitem><simpara>The Pango library (<literal>-lpango</literal>) for internationalized 
452 text.</simpara>
453 </listitem>
454
455 <listitem><simpara>The gobject library (<literal>-lgobject</literal>), containing the
456 type system on which GTK is based.</simpara>
457 </listitem>
458
459 <listitem><simpara>The gmodule library (<literal>-lgmodule</literal>), which is used 
460 to load run time extensions.</simpara>
461 </listitem>
462
463 <listitem><simpara>The GLib library (<literal>-lglib</literal>), containing miscellaneous
464 functions; only g_print() is used in this particular example. GTK is built on top
465 of GLib so you will always require this library. See the section on
466 <link linkend="ch-glib">GLib</link> for details.</simpara>
467 </listitem>
468
469 <listitem><simpara>The Xlib library (<literal>-lX11</literal>) which is used by GDK.</simpara>
470 </listitem>
471
472 <listitem><simpara>The Xext library (<literal>-lXext</literal>). This contains code 
473 for shared memory pixmaps and other X extensions.</simpara>
474 </listitem>
475
476 <listitem><simpara>The math library (<literal>-lm</literal>). This is used by GTK 
477 for various purposes.</simpara>
478 </listitem>
479 </itemizedlist>
480
481 </sect1>
482
483 <!-- ----------------------------------------------------------------- -->
484 <sect1 id="sec-TheoryOfSignalsAndCallbacks">
485 <title>Theory of Signals and Callbacks</title>
486
487 <note>
488 <para>In version 2.0, the signal system has been moved from GTK to GLib, therefore the
489 functions and types explained in this section have a "g_" prefix rather than a "gtk_" 
490 prefix. We won't go into details about the extensions which the GLib 2.0 signal system
491 has relative to the GTK 1.2 signal system.</para>
492 </note>
493
494 <para>Before we look in detail at <emphasis>helloworld</emphasis>, we'll discuss signals
495 and callbacks. GTK is an event driven toolkit, which means it will
496 sleep in gtk_main() until an event occurs and control is passed to the
497 appropriate function.</para>
498
499 <para>This passing of control is done using the idea of "signals". (Note
500 that these signals are not the same as the Unix system signals, and
501 are not implemented using them, although the terminology is almost
502 identical.) When an event occurs, such as the press of a mouse button,
503 the appropriate signal will be "emitted" by the widget that was
504 pressed.  This is how GTK does most of its useful work. There are
505 signals that all widgets inherit, such as "destroy", and there are
506 signals that are widget specific, such as "toggled" on a toggle
507 button.</para>
508
509 <para>To make a button perform an action, we set up a signal handler to
510 catch these signals and call the appropriate function. This is done by
511 using a function such as:</para>
512
513 <programlisting role="C">
514 gulong g_signal_connect( gpointer      *object,
515                          const gchar   *name,
516                          GCallback     func,
517                          gpointer      func_data );
518 </programlisting>
519
520 <para>where the first argument is the widget which will be emitting the
521 signal, and the second the name of the signal you wish to catch. The
522 third is the function you wish to be called when it is caught, and the
523 fourth, the data you wish to have passed to this function.</para>
524
525 <para>The function specified in the third argument is called a "callback
526 function", and should generally be of the form</para>
527
528 <programlisting role="C">
529 void callback_func( GtkWidget *widget,
530                     gpointer   callback_data );
531 </programlisting>
532
533 <para>where the first argument will be a pointer to the widget that emitted
534 the signal, and the second a pointer to the data given as the last
535 argument to the g_signal_connect() function as shown above.</para>
536
537 <para>Note that the above form for a signal callback function declaration is
538 only a general guide, as some widget specific signals generate
539 different calling parameters.</para>
540
541 <para>Another call used in the <emphasis>helloworld</emphasis> example, is:</para>
542
543 <programlisting role="C">
544 gulong g_signal_connect_swapped( gpointer     *object,
545                                  const gchar  *name,
546                                  GCallback    func,
547                                  gpointer     *slot_object );
548 </programlisting>
549
550 <para>g_signal_connect_swapped() is the same as g_signal_connect() except
551 that the callback function only uses one argument, a pointer to a GTK
552 object. So when using this function to connect signals, the callback
553 should be of the form</para>
554
555 <programlisting role="C">
556 void callback_func( GtkObject *object );
557 </programlisting>
558
559 <para>where the object is usually a widget. We usually don't setup callbacks
560 for g_signal_connect_swapped() however. They are usually used to call a
561 GTK function that accepts a single widget or object as an argument, as
562 is the case in our <emphasis>helloworld</emphasis> example.</para>
563
564 <para>The purpose of having two functions to connect signals is simply to
565 allow the callbacks to have a different number of arguments. Many
566 functions in the GTK library accept only a single GtkWidget pointer as
567 an argument, so you want to use the g_signal_connect_swapped() for
568 these, whereas for your functions, you may need to have additional
569 data supplied to the callbacks.</para>
570
571 </sect1>
572
573 <!-- ----------------------------------------------------------------- -->
574 <sect1 id="sec-Events">
575 <title>Events</title>
576
577 <para>In addition to the signal mechanism described above, there is a set
578 of <emphasis>events</emphasis> that reflect the X event mechanism. Callbacks may
579 also be attached to these events. These events are:</para>
580
581 <itemizedlist spacing=Compact>
582 <listitem><simpara> event</simpara>
583 </listitem>
584 <listitem><simpara> button_press_event</simpara>
585 </listitem>
586 <listitem><simpara> button_release_event</simpara>
587 </listitem>
588 <listitem><simpara> scroll_event</simpara>
589 </listitem>
590 <listitem><simpara> motion_notify_event</simpara>
591 </listitem>
592 <listitem><simpara> delete_event</simpara>
593 </listitem>
594 <listitem><simpara> destroy_event</simpara>
595 </listitem>
596 <listitem><simpara> expose_event</simpara>
597 </listitem>
598 <listitem><simpara> key_press_event</simpara>
599 </listitem>
600 <listitem><simpara> key_release_event</simpara>
601 </listitem>
602 <listitem><simpara> enter_notify_event</simpara>
603 </listitem>
604 <listitem><simpara> leave_notify_event</simpara>
605 </listitem>
606 <listitem><simpara> configure_event</simpara>
607 </listitem>
608 <listitem><simpara> focus_in_event</simpara>
609 </listitem>
610 <listitem><simpara> focus_out_event</simpara>
611 </listitem>
612 <listitem><simpara> map_event</simpara>
613 </listitem>
614 <listitem><simpara> unmap_event</simpara>
615 </listitem>
616 <listitem><simpara> property_notify_event</simpara>
617 </listitem>
618 <listitem><simpara> selection_clear_event</simpara>
619 </listitem>
620 <listitem><simpara> selection_request_event</simpara>
621 </listitem>
622 <listitem><simpara> selection_notify_event</simpara>
623 </listitem>
624 <listitem><simpara> proximity_in_event</simpara>
625 </listitem>
626 <listitem><simpara> proximity_out_event</simpara>
627 </listitem>
628 <listitem><simpara> visibility_notify_event</simpara>
629 </listitem>
630 <listitem><simpara> client_event</simpara>
631 </listitem>
632 <listitem><simpara> no_expose_event</simpara>
633 </listitem>
634 <listitem><simpara> window_state_event</simpara>
635 </listitem>
636 </itemizedlist>
637
638 <para>In order to connect a callback function to one of these events you
639 use the function g_signal_connect(), as described above, using one of
640 the above event names as the <literal>name</literal> parameter. The callback
641 function for events has a slightly different form than that for
642 signals:</para>
643
644 <programlisting role="C">
645 gint callback_func( GtkWidget *widget,
646                     GdkEvent  *event,
647                     gpointer   callback_data );
648 </programlisting>
649
650 <para>GdkEvent is a C <literal>union</literal> structure whose type will depend upon 
651 which of the above events has occurred. In order for us to tell which event
652 has been issued each of the possible alternatives has a <literal>type</literal>
653 member that reflects the event being issued. The other components
654 of the event structure will depend upon the type of the
655 event. Possible values for the type are:</para>
656
657 <programlisting role="C">
658   GDK_NOTHING
659   GDK_DELETE
660   GDK_DESTROY
661   GDK_EXPOSE
662   GDK_MOTION_NOTIFY
663   GDK_BUTTON_PRESS
664   GDK_2BUTTON_PRESS
665   GDK_3BUTTON_PRESS
666   GDK_BUTTON_RELEASE
667   GDK_KEY_PRESS
668   GDK_KEY_RELEASE
669   GDK_ENTER_NOTIFY
670   GDK_LEAVE_NOTIFY
671   GDK_FOCUS_CHANGE
672   GDK_CONFIGURE
673   GDK_MAP
674   GDK_UNMAP
675   GDK_PROPERTY_NOTIFY
676   GDK_SELECTION_CLEAR
677   GDK_SELECTION_REQUEST
678   GDK_SELECTION_NOTIFY
679   GDK_PROXIMITY_IN
680   GDK_PROXIMITY_OUT
681   GDK_DRAG_ENTER
682   GDK_DRAG_LEAVE
683   GDK_DRAG_MOTION
684   GDK_DRAG_STATUS
685   GDK_DROP_START
686   GDK_DROP_FINISHED
687   GDK_CLIENT_EVENT
688   GDK_VISIBILITY_NOTIFY
689   GDK_NO_EXPOSE
690   GDK_SCROLL
691   GDK_WINDOW_STATE
692   GDK_SETTING
693 </programlisting>
694
695 <para>So, to connect a callback function to one of these events we would use
696 something like:</para>
697
698 <programlisting role="C">
699 g_signal_connect (G_OBJECT (button), "button_press_event",
700                   G_CALLBACK (button_press_callback), NULL);
701 </programlisting>
702
703 <para>This assumes that <literal>button</literal> is a Button widget. Now, when the
704 mouse is over the button and a mouse button is pressed, the function
705 button_press_callback() will be called. This function may be declared as:</para>
706
707 <programlisting role="C">
708 static gboolean button_press_callback( GtkWidget      *widget, 
709                                        GdkEventButton *event,
710                                        gpointer        data );
711 </programlisting>
712
713 <para>Note that we can declare the second argument as type
714 <literal>GdkEventButton</literal> as we know what type of event will occur for this
715 function to be called.</para>
716
717 <para>The value returned from this function indicates whether the event
718 should be propagated further by the GTK event handling
719 mechanism. Returning TRUE indicates that the event has been handled,
720 and that it should not propagate further. Returning FALSE continues
721 the normal event handling.  See the section on
722 <link linkend="ch-AdvancedEventsAndSignals">Advanced Event and Signal Handling</link> 
723 for more details on this propagation process.</para>
724
725 <para>For details on the GdkEvent data types, see the appendix entitled
726 <link linkend="app-GDKEventTypes">GDK Event Types</link>.</para>
727
728 <para>The GDK selection and drag-and-drop APIs also emit a number of events which
729 are reflected in GTK by the signals. See <link 
730 linkend="sec-SignalsOnSourceWidgets">Signals on the source widget</link> and <link 
731 linkend="sec-SignalsOnDestWidgets">Signals on the destination widget</link>
732 for details on the signatures of the callback functions for these signals:</para>
733
734 <itemizedlist spacing=Compact>
735 <listitem><simpara> selection_received</simpara>
736 </listitem>
737 <listitem><simpara> selection_get</simpara>
738 </listitem>
739 <listitem><simpara> drag_begin_event</simpara>
740 </listitem>
741 <listitem><simpara> drag_end_event</simpara>
742 </listitem>
743 <listitem><simpara> drag_data_delete</simpara>
744 </listitem>
745 <listitem><simpara> drag_motion</simpara>
746 </listitem>
747 <listitem><simpara> drag_drop</simpara>
748 </listitem>
749 <listitem><simpara> drag_data_get</simpara>
750 </listitem>
751 <listitem><simpara> drag_data_received</simpara>
752 </listitem>
753 </itemizedlist>
754
755 </sect1>
756
757 <!-- ----------------------------------------------------------------- -->
758 <sect1 id="sec-SteppingThroughHelloWorld">
759 <title>Stepping Through Hello World</title>
760
761 <para>Now that we know the theory behind this, let's clarify by walking
762 through the example <emphasis>helloworld</emphasis> program.</para>
763
764 <para>Here is the callback function that will be called when the button is
765 "clicked". We ignore both the widget and the data in this example, but
766 it is not hard to do things with them. The next example will use the
767 data argument to tell us which button was pressed.</para>
768
769 <programlisting role="C">
770 static void hello( GtkWidget *widget,
771                    gpointer   data )
772 {
773     g_print ("Hello World\n");
774 }
775 </programlisting>
776
777 <para>The next callback is a bit special. The "delete_event" occurs when the
778 window manager sends this event to the application. We have a choice
779 here as to what to do about these events. We can ignore them, make
780 some sort of response, or simply quit the application.</para>
781
782 <para>The value you return in this callback lets GTK know what action to
783 take.  By returning TRUE, we let it know that we don't want to have
784 the "destroy" signal emitted, keeping our application running. By
785 returning FALSE, we ask that "destroy" be emitted, which in turn will
786 call our "destroy" signal handler.</para>
787
788
789 <programlisting role="C">
790 static gboolean delete_event( GtkWidget *widget,
791                               GdkEvent  *event,
792                               gpointer   data )
793 {
794     g_print ("delete event occurred\n");
795
796     return TRUE; 
797 }
798 </programlisting>
799
800 <para>Here is another callback function which causes the program to quit by
801 calling gtk_main_quit(). This function tells GTK that it is to exit
802 from gtk_main when control is returned to it.</para>
803
804 <programlisting role="C">
805 static void destroy( GtkWidget *widget,
806                      gpointer   data )
807 {
808     gtk_main_quit ();
809 }
810 </programlisting>
811
812 <para>I assume you know about the main() function... yes, as with other
813 applications, all GTK applications will also have one of these.</para>
814
815 <programlisting role="C">
816 int main( int   argc,
817           char *argv[] )
818 {
819 </programlisting>
820
821 <para>This next part declares pointers to a structure of type
822 GtkWidget. These are used below to create a window and a button.</para>
823
824 <programlisting role="C">
825     GtkWidget *window;
826     GtkWidget *button;
827 </programlisting>
828
829 <para>Here is our gtk_init() again. As before, this initializes the toolkit,
830 and parses the arguments found on the command line. Any argument it
831 recognizes from the command line, it removes from the list, and
832 modifies argc and argv to make it look like they never existed,
833 allowing your application to parse the remaining arguments.</para>
834
835 <programlisting role="C">
836     gtk_init (&amp;argc, &amp;argv);
837 </programlisting>
838
839 <para>Create a new window. This is fairly straightforward. Memory is
840 allocated for the GtkWidget *window structure so it now points to a
841 valid structure. It sets up a new window, but it is not displayed
842 until we call gtk_widget_show(window) near the end of our program.</para>
843
844 <programlisting role="C">
845     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
846 </programlisting>
847
848 <para>Here are two examples of connecting a signal handler to an object, in
849 this case, the window. Here, the "delete_event" and "destroy" signals
850 are caught. The first is emitted when we use the window manager to
851 kill the window, or when we use the gtk_widget_destroy() call passing
852 in the window widget as the object to destroy. The second is emitted
853 when, in the "delete_event" handler, we return FALSE.
854  
855 The <literal>G_OBJECT</literal> and <literal>G_CALLBACK</literal> are macros 
856 that perform type casting and checking for us, as well as aid the readability of
857 the code.</para>
858
859 <programlisting role="C">
860     g_signal_connect (G_OBJECT (window), "delete_event",
861                       G_CALLBACK (delete_event), NULL);
862     g_signal_connect (G_OBJECT (window), "destroy",
863                       G_CALLBACK (destroy), NULL);
864 </programlisting>
865
866 <para>This next function is used to set an attribute of a container object.
867 This just sets the window so it has a blank area along the inside of
868 it 10 pixels wide where no widgets will go. There are other similar
869 functions which we will look at in the section on
870 <link linkend="ch-SettingWidgetAttributes">Setting Widget Attributes</link></para>
871
872 <para>And again, <literal>GTK_CONTAINER</literal> is a macro to perform type casting.</para>
873
874 <programlisting role="C">
875     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
876 </programlisting>
877
878 <para>This call creates a new button. It allocates space for a new GtkWidget
879 structure in memory, initializes it, and makes the button pointer
880 point to it. It will have the label "Hello World" on it when
881 displayed.</para>
882
883 <programlisting role="C">
884     button = gtk_button_new_with_label ("Hello World");
885 </programlisting>
886
887 <para>Here, we take this button, and make it do something useful. We attach
888 a signal handler to it so when it emits the "clicked" signal, our
889 hello() function is called. The data is ignored, so we simply pass in
890 NULL to the hello() callback function. Obviously, the "clicked" signal
891 is emitted when we click the button with our mouse pointer.</para>
892
893 <programlisting role="C">
894     g_signal_connect (G_OBJECT (button), "clicked",
895                       G_CALLBACK (hello), NULL);
896 </programlisting>
897
898 <para>We are also going to use this button to exit our program. This will
899 illustrate how the "destroy" signal may come from either the window
900 manager, or our program. When the button is "clicked", same as above,
901 it calls the first hello() callback function, and then this one in the
902 order they are set up. You may have as many callback functions as you
903 need, and all will be executed in the order you connected
904 them. Because the gtk_widget_destroy() function accepts only a
905 GtkWidget *widget as an argument, we use the g_signal_connect_swapped() 
906 function here instead of straight g_signal_connect().</para>
907
908 <programlisting role="C">
909     g_signal_connect_swapped (G_OBJECT (button), "clicked",
910                               G_CALLBACK (gtk_widget_destroy),
911                               G_OBJECT (window));
912 </programlisting>
913
914 <para>This is a packing call, which will be explained in depth later on in
915 <link linkend="ch-PackingWidgets">Packing Widgets</link>. But it is
916 fairly easy to understand. It simply tells GTK that the button is to
917 be placed in the window where it will be displayed. Note that a GTK
918 container can only contain one widget. There are other widgets, that
919 are described later, which are designed to layout multiple widgets in
920 various ways.
921  </para>
922
923 <programlisting role="C">
924     gtk_container_add (GTK_CONTAINER (window), button);
925 </programlisting>
926
927 <para>Now we have everything set up the way we want it to be. With all the
928 signal handlers in place, and the button placed in the window where it
929 should be, we ask GTK to "show" the widgets on the screen. The window
930 widget is shown last so the whole window will pop up at once rather
931 than seeing the window pop up, and then the button form inside of
932 it. Although with such a simple example, you'd never notice.</para>
933
934 <programlisting role="C">
935     gtk_widget_show (button);
936
937     gtk_widget_show (window);
938 </programlisting>
939
940 <para>And of course, we call gtk_main() which waits for events to come from
941 the X server and will call on the widgets to emit signals when these
942 events come.</para>
943
944 <programlisting role="C">
945     gtk_main ();
946 </programlisting>
947
948 <para>And the final return. Control returns here after gtk_quit() is called.</para>
949
950 <programlisting role="C">
951     return 0;
952 </programlisting>
953
954 <para>Now, when we click the mouse button on a GTK button, the widget emits
955 a "clicked" signal. In order for us to use this information, our
956 program sets up a signal handler to catch that signal, which
957 dispatches the function of our choice. In our example, when the button
958 we created is "clicked", the hello() function is called with a NULL
959 argument, and then the next handler for this signal is called. This
960 calls the gtk_widget_destroy() function, passing it the window widget
961 as its argument, destroying the window widget. This causes the window
962 to emit the "destroy" signal, which is caught, and calls our destroy()
963 callback function, which simply exits GTK.</para>
964
965 <para>Another course of events is to use the window manager to kill the
966 window, which will cause the "delete_event" to be emitted. This will
967 call our "delete_event" handler. If we return TRUE here, the window
968 will be left as is and nothing will happen. Returning FALSE will cause
969 GTK to emit the "destroy" signal which of course calls the "destroy"
970 callback, exiting GTK.</para>
971
972 </sect1>
973 </chapter>
974
975 <!-- ***************************************************************** -->
976 <chapter id="ch-MovingOn">
977 <title>Moving On</title>
978
979 <!-- ----------------------------------------------------------------- -->
980 <sect1 id="sec-DataTypes">
981 <title>Data Types</title>
982
983 <para>There are a few things you probably noticed in the previous examples
984 that need explaining. The gint, gchar, etc. that you see are typedefs
985 to int and char, respectively, that are part of the GLib system. This
986 is done to get around that nasty dependency on the size of simple data
987 types when doing calculations.</para>
988
989 <para>A good example is "gint32" which will be typedef'd to a 32 bit integer
990 for any given platform, whether it be the 64 bit alpha, or the 32 bit
991 i386. The typedefs are very straightforward and intuitive. They are
992 all defined in <filename>glib/glib.h</filename> (which gets included from 
993 <filename>gtk.h</filename>).</para>
994
995 <para>You'll also notice GTK's ability to use GtkWidget when the function
996 calls for a GtkObject. GTK is an object oriented design, and a widget
997 is an object.</para>
998
999 </sect1>
1000
1001 <!-- ----------------------------------------------------------------- -->
1002 <sect1 id="sec-MoreOnSignalHandlers">
1003 <title>More on Signal Handlers</title>
1004
1005 <para>Lets take another look at the g_signal_connect() declaration.</para>
1006
1007 <programlisting role="C">
1008 gulong g_signal_connect( gpointer object,
1009                          const gchar *name,
1010                          GCallback func,
1011                          gpointer func_data );
1012 </programlisting>
1013
1014 <para>Notice the gulong return value? This is a tag that identifies your
1015 callback function. As stated above, you may have as many callbacks per
1016 signal and per object as you need, and each will be executed in turn,
1017 in the order they were attached.</para>
1018
1019 <para>This tag allows you to remove this callback from the list by using:</para>
1020
1021 <programlisting role="C">
1022 void g_signal_handler_disconnect( gpointer object,
1023                                   gulong   id );
1024 </programlisting>
1025
1026 <para>So, by passing in the widget you wish to remove the handler from, and
1027 the tag returned by one of the signal_connect functions, you can
1028 disconnect a signal handler.</para>
1029
1030 <para>You can also temporarily disable signal handlers with the
1031 g_signal_handler_block() and g_signal_handler_unblock() family of
1032 functions.</para>
1033
1034 <programlisting role="C">
1035 void g_signal_handler_block( gpointer object,
1036                              gulong   id );
1037
1038 void g_signal_handlers_block_by_func( gpointer  object,
1039                                       GCallback func,
1040                                       gpointer  data );
1041
1042 void g_signal_handler_unblock( gpointer object,
1043                                gulong   id );
1044
1045 void g_signal_handlers_unblock_by_func( gpointer  object,
1046                                         GCallback func,
1047                                         gpointer  data );
1048 </programlisting>
1049
1050 </sect1>
1051
1052 <!-- ----------------------------------------------------------------- -->
1053 <sect1 id="sec-AnUpgradedHelloWorld">
1054 <title>An Upgraded Hello World</title>
1055
1056 <para>Let's take a look at a slightly improved <emphasis>helloworld</emphasis> with
1057 better examples of callbacks. This will also introduce us to our next
1058 topic, packing widgets.</para>
1059
1060 <para>
1061 <inlinemediaobject>
1062 <imageobject>
1063 <imagedata fileref="images/helloworld2.png" format="png">
1064 </imageobject>
1065 </inlinemediaobject>
1066 </para>
1067
1068 <programlisting role="C">
1069 <!-- example-start helloworld2 helloworld2.c -->
1070
1071 #include &lt;gtk/gtk.h&gt;
1072
1073 /* Our new improved callback.  The data passed to this function
1074  * is printed to stdout. */
1075 static void callback( GtkWidget *widget,
1076                       gpointer   data )
1077 {
1078     g_print ("Hello again - %s was pressed\n", (gchar *) data);
1079 }
1080
1081 /* another callback */
1082 static gboolean delete_event( GtkWidget *widget,
1083                               GdkEvent  *event,
1084                               gpointer   data )
1085 {
1086     gtk_main_quit ();
1087     return FALSE;
1088 }
1089
1090 int main( int   argc,
1091           char *argv[] )
1092 {
1093     /* GtkWidget is the storage type for widgets */
1094     GtkWidget *window;
1095     GtkWidget *button;
1096     GtkWidget *box1;
1097
1098     /* This is called in all GTK applications. Arguments are parsed
1099      * from the command line and are returned to the application. */
1100     gtk_init (&amp;argc, &amp;argv);
1101
1102     /* Create a new window */
1103     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1104
1105     /* This is a new call, which just sets the title of our
1106      * new window to "Hello Buttons!" */
1107     gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
1108
1109     /* Here we just set a handler for delete_event that immediately
1110      * exits GTK. */
1111     g_signal_connect (G_OBJECT (window), "delete_event",
1112                       G_CALLBACK (delete_event), NULL);
1113
1114     /* Sets the border width of the window. */
1115     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1116
1117     /* We create a box to pack widgets into.  This is described in detail
1118      * in the "packing" section. The box is not really visible, it
1119      * is just used as a tool to arrange widgets. */
1120     box1 = gtk_hbox_new (FALSE, 0);
1121
1122     /* Put the box into the main window. */
1123     gtk_container_add (GTK_CONTAINER (window), box1);
1124
1125     /* Creates a new button with the label "Button 1". */
1126     button = gtk_button_new_with_label ("Button 1");
1127     
1128     /* Now when the button is clicked, we call the "callback" function
1129      * with a pointer to "button 1" as its argument */
1130     g_signal_connect (G_OBJECT (button), "clicked",
1131                       G_CALLBACK (callback), (gpointer) "button 1");
1132
1133     /* Instead of gtk_container_add, we pack this button into the invisible
1134      * box, which has been packed into the window. */
1135     gtk_box_pack_start (GTK_BOX(box1), button, TRUE, TRUE, 0);
1136
1137     /* Always remember this step, this tells GTK that our preparation for
1138      * this button is complete, and it can now be displayed. */
1139     gtk_widget_show (button);
1140
1141     /* Do these same steps again to create a second button */
1142     button = gtk_button_new_with_label ("Button 2");
1143
1144     /* Call the same callback function with a different argument,
1145      * passing a pointer to "button 2" instead. */
1146     g_signal_connect (G_OBJECT (button), "clicked",
1147                       G_CALLBACK (callback), (gpointer) "button 2");
1148
1149     gtk_box_pack_start(GTK_BOX (box1), button, TRUE, TRUE, 0);
1150
1151     /* The order in which we show the buttons is not really important, but I
1152      * recommend showing the window last, so it all pops up at once. */
1153     gtk_widget_show (button);
1154
1155     gtk_widget_show (box1);
1156
1157     gtk_widget_show (window);
1158     
1159     /* Rest in gtk_main and wait for the fun to begin! */
1160     gtk_main ();
1161
1162     return 0;
1163 }
1164 <!-- example-end -->
1165 </programlisting>
1166
1167 <para>Compile this program using the same linking arguments as our first
1168 example.  You'll notice this time there is no easy way to exit the
1169 program, you have to use your window manager or command line to kill
1170 it. A good exercise for the reader would be to insert a third "Quit"
1171 button that will exit the program. You may also wish to play with the
1172 options to gtk_box_pack_start() while reading the next section.  Try
1173 resizing the window, and observe the behavior.</para>
1174
1175 </sect1>
1176 </chapter>
1177
1178 <!-- ***************************************************************** -->
1179 <chapter id="ch-PackingWidgets">
1180 <title>Packing Widgets</title>
1181
1182 <para>When creating an application, you'll want to put more than one widget
1183 inside a window. Our first <emphasis>helloworld</emphasis> example only used one
1184 widget so we could simply use a gtk_container_add() call to "pack" the
1185 widget into the window. But when you want to put more than one widget
1186 into a window, how do you control where that widget is positioned?
1187 This is where packing comes in.</para>
1188
1189 <!-- ----------------------------------------------------------------- -->
1190 <sect1 id="sec-TheoryOfPackingBoxes">
1191 <title>Theory of Packing Boxes</title>
1192
1193 <para>Most packing is done by creating boxes. These
1194 are invisible widget containers that we can pack our widgets into
1195 which come in two forms, a horizontal box, and a vertical box. When
1196 packing widgets into a horizontal box, the objects are inserted
1197 horizontally from left to right or right to left depending on the call
1198 used. In a vertical box, widgets are packed from top to bottom or vice
1199 versa. You may use any combination of boxes inside or beside other
1200 boxes to create the desired effect.</para>
1201
1202 <para>To create a new horizontal box, we use a call to gtk_hbox_new(), and
1203 for vertical boxes, gtk_vbox_new(). The gtk_box_pack_start() and
1204 gtk_box_pack_end() functions are used to place objects inside of these
1205 containers. The gtk_box_pack_start() function will start at the top
1206 and work its way down in a vbox, and pack left to right in an hbox.
1207 gtk_box_pack_end() will do the opposite, packing from bottom to top in
1208 a vbox, and right to left in an hbox. Using these functions allows us
1209 to right justify or left justify our widgets and may be mixed in any
1210 way to achieve the desired effect. We will use gtk_box_pack_start() in
1211 most of our examples. An object may be another container or a
1212 widget. In fact, many widgets are actually containers themselves,
1213 including the button, but we usually only use a label inside a button.</para>
1214
1215 <para>By using these calls, GTK knows where you want to place your widgets
1216 so it can do automatic resizing and other nifty things. There are also
1217 a number of options as to how your widgets should be packed. As you
1218 can imagine, this method gives us a quite a bit of flexibility when
1219 placing and creating widgets.</para>
1220
1221 </sect1>
1222
1223 <!-- ----------------------------------------------------------------- -->
1224 <sect1 id="sec-DetailsOfBoxes">
1225 <title>Details of Boxes</title>
1226
1227 <para>Because of this flexibility, packing boxes in GTK can be confusing at
1228 first. There are a lot of options, and it's not immediately obvious how
1229 they all fit together. In the end, however, there are basically five
1230 different styles.</para>
1231
1232 <para>
1233 <inlinemediaobject>
1234 <imageobject>
1235 <imagedata fileref="images/packbox1.png" format="png">
1236 </imageobject>
1237 </inlinemediaobject>
1238 </para>
1239
1240 <para>Each line contains one horizontal box (hbox) with several buttons. The
1241 call to gtk_box_pack is shorthand for the call to pack each of the
1242 buttons into the hbox. Each of the buttons is packed into the hbox the
1243 same way (i.e., same arguments to the gtk_box_pack_start() function).</para>
1244
1245 <para>This is the declaration of the gtk_box_pack_start() function.</para>
1246
1247 <programlisting role="C">
1248 void gtk_box_pack_start( GtkBox    *box,
1249                          GtkWidget *child,
1250                          gboolean   expand,
1251                          gboolean   fill,
1252                          guint      padding );
1253 </programlisting>
1254
1255 <para>The first argument is the box you are packing the object into, the
1256 second is the object. The objects will all be buttons for now, so
1257 we'll be packing buttons into boxes.</para>
1258
1259 <para>The expand argument to gtk_box_pack_start() and gtk_box_pack_end()
1260 controls whether the widgets are laid out in the box to fill in all
1261 the extra space in the box so the box is expanded to fill the area
1262 allotted to it (TRUE); or the box is shrunk to just fit the widgets
1263 (FALSE). Setting expand to FALSE will allow you to do right and left
1264 justification of your widgets.  Otherwise, they will all expand to fit
1265 into the box, and the same effect could be achieved by using only one
1266 of gtk_box_pack_start() or gtk_box_pack_end().</para>
1267
1268 <para>The fill argument to the gtk_box_pack functions control whether the
1269 extra space is allocated to the objects themselves (TRUE), or as extra
1270 padding in the box around these objects (FALSE). It only has an effect
1271 if the expand argument is also TRUE.</para>
1272
1273 <para>When creating a new box, the function looks like this:</para>
1274
1275 <programlisting role="C">
1276 GtkWidget *gtk_hbox_new ( gboolean homogeneous,
1277                           gint     spacing );
1278 </programlisting>
1279
1280 <para>The homogeneous argument to gtk_hbox_new() (and the same for
1281 gtk_vbox_new()) controls whether each object in the box has the same
1282 size (i.e., the same width in an hbox, or the same height in a
1283 vbox). If it is set, the gtk_box_pack() routines function essentially
1284 as if the <literal>expand</literal> argument was always turned on.</para>
1285
1286 <para>What's the difference between spacing (set when the box is created)
1287 and padding (set when elements are packed)? Spacing is added between
1288 objects, and padding is added on either side of an object. The
1289 following figure should make it clearer:</para>
1290
1291 <para>
1292 <inlinemediaobject>
1293 <imageobject>
1294 <imagedata fileref="images/packbox2.png" format="png">
1295 </imageobject>
1296 </inlinemediaobject>
1297 </para>
1298
1299 <para>Here is the code used to create the above images. I've commented it
1300 fairly heavily so I hope you won't have any problems following
1301 it. Compile it yourself and play with it.</para>
1302
1303 </sect1>
1304
1305 <!-- ----------------------------------------------------------------- -->
1306 <sect1 id="sec-PackingDemonstrationProgram">
1307 <title>Packing Demonstration Program</title>
1308
1309 <programlisting role="C">
1310 /* example-start packbox packbox.c */
1311
1312 #include &lt;stdio.h&gt;
1313 #include &lt;stdlib.h&gt;
1314 #include "gtk/gtk.h"
1315
1316 static gboolean delete_event( GtkWidget *widget,
1317                               GdkEvent  *event,
1318                               gpointer   data )
1319 {
1320     gtk_main_quit ();
1321     return FALSE;
1322 }
1323
1324 /* Make a new hbox filled with button-labels. Arguments for the 
1325  * variables we're interested are passed in to this function. 
1326  * We do not show the box, but do show everything inside. */
1327 static GtkWidget *make_box( gboolean homogeneous,
1328                             gint     spacing,
1329                             gboolean expand,
1330                             gboolean fill,
1331                             guint    padding ) 
1332 {
1333     GtkWidget *box;
1334     GtkWidget *button;
1335     char padstr[80];
1336     
1337     /* Create a new hbox with the appropriate homogeneous
1338      * and spacing settings */
1339     box = gtk_hbox_new (homogeneous, spacing);
1340     
1341     /* Create a series of buttons with the appropriate settings */
1342     button = gtk_button_new_with_label ("gtk_box_pack");
1343     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1344     gtk_widget_show (button);
1345     
1346     button = gtk_button_new_with_label ("(box,");
1347     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1348     gtk_widget_show (button);
1349     
1350     button = gtk_button_new_with_label ("button,");
1351     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1352     gtk_widget_show (button);
1353     
1354     /* Create a button with the label depending on the value of
1355      * expand. */
1356     if (expand == TRUE)
1357             button = gtk_button_new_with_label ("TRUE,");
1358     else
1359             button = gtk_button_new_with_label ("FALSE,");
1360     
1361     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1362     gtk_widget_show (button);
1363     
1364     /* This is the same as the button creation for "expand"
1365      * above, but uses the shorthand form. */
1366     button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
1367     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1368     gtk_widget_show (button);
1369     
1370     sprintf (padstr, "%d);", padding);
1371     
1372     button = gtk_button_new_with_label (padstr);
1373     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1374     gtk_widget_show (button);
1375     
1376     return box;
1377 }
1378
1379 int main( int   argc,
1380           char *argv[]) 
1381 {
1382     GtkWidget *window;
1383     GtkWidget *button;
1384     GtkWidget *box1;
1385     GtkWidget *box2;
1386     GtkWidget *separator;
1387     GtkWidget *label;
1388     GtkWidget *quitbox;
1389     int which;
1390     
1391     /* Our init, don't forget this! :) */
1392     gtk_init (&amp;argc, &amp;argv);
1393     
1394     if (argc != 2) {
1395         fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n");
1396         /* This just does cleanup in GTK and exits with an exit status of 1. */
1397         exit (1);
1398     }
1399     
1400     which = atoi (argv[1]);
1401
1402     /* Create our window */
1403     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1404
1405     /* You should always remember to connect the delete_event signal
1406      * to the main window. This is very important for proper intuitive
1407      * behavior */
1408     g_signal_connect (G_OBJECT (window), "delete_event",
1409                       G_CALLBACK (delete_event), NULL);
1410     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1411     
1412     /* We create a vertical box (vbox) to pack the horizontal boxes into.
1413      * This allows us to stack the horizontal boxes filled with buttons one
1414      * on top of the other in this vbox. */
1415     box1 = gtk_vbox_new (FALSE, 0);
1416     
1417     /* which example to show. These correspond to the pictures above. */
1418     switch (which) {
1419     case 1:
1420         /* create a new label. */
1421         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1422         
1423         /* Align the label to the left side.  We'll discuss this function and 
1424          * others in the section on Widget Attributes. */
1425         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1426
1427         /* Pack the label into the vertical box (vbox box1).  Remember that 
1428          * widgets added to a vbox will be packed one on top of the other in
1429          * order. */
1430         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1431         
1432         /* Show the label */
1433         gtk_widget_show (label);
1434         
1435         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1436          * expand = FALSE, fill = FALSE, padding = 0 */
1437         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1438         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1439         gtk_widget_show (box2);
1440
1441         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1442          * expand = TRUE, fill = FALSE, padding = 0 */
1443         box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
1444         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1445         gtk_widget_show (box2);
1446         
1447         /* Args are: homogeneous, spacing, expand, fill, padding */
1448         box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
1449         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1450         gtk_widget_show (box2);
1451         
1452         /* Creates a separator, we'll learn more about these later, 
1453          * but they are quite simple. */
1454         separator = gtk_hseparator_new ();
1455         
1456         /* Pack the separator into the vbox. Remember each of these
1457          * widgets is being packed into a vbox, so they'll be stacked
1458          * vertically. */
1459         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1460         gtk_widget_show (separator);
1461         
1462         /* Create another new label, and show it. */
1463         label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
1464         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1465         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1466         gtk_widget_show (label);
1467         
1468         /* Args are: homogeneous, spacing, expand, fill, padding */
1469         box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
1470         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1471         gtk_widget_show (box2);
1472         
1473         /* Args are: homogeneous, spacing, expand, fill, padding */
1474         box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
1475         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1476         gtk_widget_show (box2);
1477         
1478         /* Another new separator. */
1479         separator = gtk_hseparator_new ();
1480         /* The last 3 arguments to gtk_box_pack_start are:
1481          * expand, fill, padding. */
1482         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1483         gtk_widget_show (separator);
1484         
1485         break;
1486
1487     case 2:
1488
1489         /* Create a new label, remember box1 is a vbox as created 
1490          * near the beginning of main() */
1491         label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
1492         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1493         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1494         gtk_widget_show (label);
1495         
1496         /* Args are: homogeneous, spacing, expand, fill, padding */
1497         box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
1498         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1499         gtk_widget_show (box2);
1500         
1501         /* Args are: homogeneous, spacing, expand, fill, padding */
1502         box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
1503         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1504         gtk_widget_show (box2);
1505         
1506         separator = gtk_hseparator_new ();
1507         /* The last 3 arguments to gtk_box_pack_start are:
1508          * expand, fill, padding. */
1509         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1510         gtk_widget_show (separator);
1511         
1512         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1513         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1514         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1515         gtk_widget_show (label);
1516         
1517         /* Args are: homogeneous, spacing, expand, fill, padding */
1518         box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
1519         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1520         gtk_widget_show (box2);
1521         
1522         /* Args are: homogeneous, spacing, expand, fill, padding */
1523         box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
1524         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1525         gtk_widget_show (box2);
1526         
1527         separator = gtk_hseparator_new ();
1528         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1529         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1530         gtk_widget_show (separator);
1531         break;
1532     
1533     case 3:
1534
1535         /* This demonstrates the ability to use gtk_box_pack_end() to
1536          * right justify widgets. First, we create a new box as before. */
1537         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1538
1539         /* Create the label that will be put at the end. */
1540         label = gtk_label_new ("end");
1541         /* Pack it using gtk_box_pack_end(), so it is put on the right
1542          * side of the hbox created in the make_box() call. */
1543         gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
1544         /* Show the label. */
1545         gtk_widget_show (label);
1546         
1547         /* Pack box2 into box1 (the vbox remember ? :) */
1548         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1549         gtk_widget_show (box2);
1550         
1551         /* A separator for the bottom. */
1552         separator = gtk_hseparator_new ();
1553         /* This explicitly sets the separator to 400 pixels wide by 5 pixels
1554          * high. This is so the hbox we created will also be 400 pixels wide,
1555          * and the "end" label will be separated from the other labels in the
1556          * hbox. Otherwise, all the widgets in the hbox would be packed as
1557          * close together as possible. */
1558         gtk_widget_set_size_request (separator, 400, 5);
1559         /* pack the separator into the vbox (box1) created near the start 
1560          * of main() */
1561         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1562         gtk_widget_show (separator);    
1563     }
1564     
1565     /* Create another new hbox.. remember we can use as many as we need! */
1566     quitbox = gtk_hbox_new (FALSE, 0);
1567     
1568     /* Our quit button. */
1569     button = gtk_button_new_with_label ("Quit");
1570     
1571     /* Setup the signal to terminate the program when the button is clicked */
1572     g_signal_connect_swapped (G_OBJECT (button), "clicked",
1573                               G_CALLBACK (gtk_main_quit),
1574                               G_OBJECT (window));
1575     /* Pack the button into the quitbox.
1576      * The last 3 arguments to gtk_box_pack_start are:
1577      * expand, fill, padding. */
1578     gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
1579     /* pack the quitbox into the vbox (box1) */
1580     gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
1581     
1582     /* Pack the vbox (box1) which now contains all our widgets, into the
1583      * main window. */
1584     gtk_container_add (GTK_CONTAINER (window), box1);
1585     
1586     /* And show everything left */
1587     gtk_widget_show (button);
1588     gtk_widget_show (quitbox);
1589     
1590     gtk_widget_show (box1);
1591     /* Showing the window last so everything pops up at once. */
1592     gtk_widget_show (window);
1593     
1594     /* And of course, our main function. */
1595     gtk_main ();
1596
1597     /* Control returns here when gtk_main_quit() is called, but not when 
1598      * exit() is used. */
1599     
1600     return 0;
1601 }
1602 <!-- example-end -->
1603 </programlisting>
1604
1605 </sect1>
1606
1607 <!-- ----------------------------------------------------------------- -->
1608 <sect1 id="sec-PackingUsingTables">
1609 <title>Packing Using Tables</title>
1610
1611 <para>Let's take a look at another way of packing - Tables. These can be
1612 extremely useful in certain situations.</para>
1613
1614 <para>Using tables, we create a grid that we can place widgets in. The
1615 widgets may take up as many spaces as we specify.</para>
1616
1617 <para>The first thing to look at, of course, is the gtk_table_new() function:</para>
1618
1619 <programlisting role="C">
1620 GtkWidget *gtk_table_new( guint    rows,
1621                           guint    columns,
1622                           gboolean homogeneous );
1623 </programlisting>
1624
1625 <para>The first argument is the number of rows to make in the table, while
1626 the second, obviously, is the number of columns.</para>
1627
1628 <para>The homogeneous argument has to do with how the table's boxes are
1629 sized. If homogeneous is TRUE, the table boxes are resized to the size
1630 of the largest widget in the table. If homogeneous is FALSE, the size
1631 of a table boxes is dictated by the tallest widget in its same row,
1632 and the widest widget in its column.</para>
1633
1634 <para>The rows and columns are laid out from 0 to n, where n was the number
1635 specified in the call to gtk_table_new. So, if you specify rows = 2
1636 and columns = 2, the layout would look something like this:</para>
1637
1638 <programlisting role="C">
1639  0          1          2
1640 0+----------+----------+
1641  |          |          |
1642 1+----------+----------+
1643  |          |          |
1644 2+----------+----------+
1645 </programlisting>
1646
1647 <para>Note that the coordinate system starts in the upper left hand corner.
1648 To place a widget into a box, use the following function:</para>
1649
1650 <programlisting role="C">
1651 void gtk_table_attach( GtkTable         *table,
1652                        GtkWidget        *child,
1653                        guint            left_attach,
1654                        guint            right_attach,
1655                        guint            top_attach,
1656                        guint            bottom_attach,
1657                        GtkAttachOptions xoptions,
1658                        GtkAttachOptions yoptions,
1659                        guint            xpadding,
1660                        guint            ypadding );
1661 </programlisting>
1662
1663 <para>The first argument ("table") is the table you've created and the
1664 second ("child") the widget you wish to place in the table.</para>
1665
1666 <para>The left and right attach arguments specify where to place the widget,
1667 and how many boxes to use. If you want a button in the lower right
1668 table entry of our 2x2 table, and want it to fill that entry <emphasis>only</emphasis>,
1669 left_attach would be = 1, right_attach = 2, top_attach = 1,
1670 bottom_attach = 2.</para>
1671
1672 <para>Now, if you wanted a widget to take up the whole top row of our 2x2
1673 table, you'd use left_attach = 0, right_attach = 2, top_attach = 0,
1674 bottom_attach = 1.</para>
1675
1676 <para>The xoptions and yoptions are used to specify packing options and may
1677 be bitwise OR'ed together to allow multiple options.</para>
1678
1679 <para>These options are:</para>
1680
1681 <variablelist>
1682 <varlistentry>
1683 <term><literal>GTK_FILL</literal></term>
1684 <listitem><para>If the table box is larger than the widget, and
1685 <literal>GTK_FILL</literal> is specified, the widget will expand to use all the room
1686 available.</para>
1687 </listitem>
1688 </varlistentry>
1689
1690 <varlistentry>
1691 <term><literal>GTK_SHRINK</literal></term>
1692 <listitem><para>If the table widget was allocated less space
1693 then was requested (usually by the user resizing the window), then the
1694 widgets would normally just be pushed off the bottom of the window and
1695 disappear. If <literal>GTK_SHRINK</literal> is specified, the widgets will shrink
1696 with the table.</para>
1697 </listitem>
1698 </varlistentry>
1699
1700 <varlistentry>
1701 <term><literal>GTK_EXPAND</literal></term>
1702 <listitem><para>This will cause the table to expand to use up
1703 any remaining space in the window.</para>
1704 </listitem>
1705 </varlistentry>
1706 </variablelist>
1707
1708 <para>Padding is just like in boxes, creating a clear area around the widget
1709 specified in pixels.</para>
1710
1711 <para>gtk_table_attach() has a <emphasis>lot</emphasis> of options.  
1712 So, there's a shortcut:</para>
1713
1714 <programlisting role="C">
1715 void gtk_table_attach_defaults( GtkTable  *table,
1716                                 GtkWidget *widget,
1717                                 guint      left_attach,
1718                                 guint      right_attach,
1719                                 guint      top_attach,
1720                                 guint      bottom_attach );
1721 </programlisting>
1722
1723 <para>The X and Y options default to <literal>GTK_FILL | GTK_EXPAND</literal>, 
1724 and X and Y padding are set to 0. The rest of the arguments are identical to the
1725 previous function.</para>
1726
1727 <para>We also have gtk_table_set_row_spacing() and
1728 gtk_table_set_col_spacing(). These places spacing between the rows at
1729 the specified row or column.</para>
1730
1731 <programlisting role="C">
1732 void gtk_table_set_row_spacing( GtkTable *table,
1733                                 guint     row,
1734                                 guint     spacing );
1735 </programlisting>
1736
1737 <para>and</para>
1738
1739 <programlisting role="C">
1740 void gtk_table_set_col_spacing ( GtkTable *table,
1741                                  guint     column,
1742                                  guint     spacing );
1743 </programlisting>
1744
1745 <para>Note that for columns, the space goes to the right of the column, and
1746 for rows, the space goes below the row.</para>
1747
1748 <para>You can also set a consistent spacing of all rows and/or columns with:</para>
1749
1750 <programlisting role="C">
1751 void gtk_table_set_row_spacings( GtkTable *table,
1752                                  guint    spacing );
1753 </programlisting>
1754
1755 <para>And,</para>
1756
1757 <programlisting role="C">
1758 void gtk_table_set_col_spacings( GtkTable *table,
1759                                  guint     spacing );
1760 </programlisting>
1761
1762 <para>Note that with these calls, the last row and last column do not get
1763 any spacing.</para>
1764
1765 </sect1>
1766
1767 <!-- ----------------------------------------------------------------- -->
1768 <sect1 id="sec-TablePackingExamples">
1769 <title>Table Packing Example</title>
1770
1771 <para>Here we make a window with three buttons in a 2x2 table.
1772 The first two buttons will be placed in the upper row.
1773 A third, quit button, is placed in the lower row, spanning both columns.
1774 Which means it should look something like this:</para>
1775
1776 <para>
1777 <inlinemediaobject>
1778 <imageobject>
1779 <imagedata fileref="images/table.png" format="png">
1780 </imageobject>
1781 </inlinemediaobject>
1782 </para>
1783
1784 <para>Here's the source code:</para>
1785
1786 <programlisting role="C">
1787 <!-- example-start table table.c -->
1788
1789 #include &lt;gtk/gtk.h&gt;
1790
1791 /* Our callback.
1792  * The data passed to this function is printed to stdout */
1793 static void callback( GtkWidget *widget,
1794                       gpointer   data )
1795 {
1796     g_print ("Hello again - %s was pressed\n", (char *) data);
1797 }
1798
1799 /* This callback quits the program */
1800 static gboolean delete_event( GtkWidget *widget,
1801                               GdkEvent  *event,
1802                               gpointer   data )
1803 {
1804     gtk_main_quit ();
1805     return FALSE;
1806 }
1807
1808 int main( int   argc,
1809           char *argv[] )
1810 {
1811     GtkWidget *window;
1812     GtkWidget *button;
1813     GtkWidget *table;
1814
1815     gtk_init (&amp;argc, &amp;argv);
1816
1817     /* Create a new window */
1818     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1819
1820     /* Set the window title */
1821     gtk_window_set_title (GTK_WINDOW (window), "Table");
1822
1823     /* Set a handler for delete_event that immediately
1824      * exits GTK. */
1825     g_signal_connect (G_OBJECT (window), "delete_event",
1826                       G_CALLBACK (delete_event), NULL);
1827
1828     /* Sets the border width of the window. */
1829     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
1830
1831     /* Create a 2x2 table */
1832     table = gtk_table_new (2, 2, TRUE);
1833
1834     /* Put the table in the main window */
1835     gtk_container_add (GTK_CONTAINER (window), table);
1836
1837     /* Create first button */
1838     button = gtk_button_new_with_label ("button 1");
1839
1840     /* When the button is clicked, we call the "callback" function
1841      * with a pointer to "button 1" as its argument */
1842     g_signal_connect (G_OBJECT (button), "clicked",
1843                       G_CALLBACK (callback), (gpointer) "button 1");
1844
1845
1846     /* Insert button 1 into the upper left quadrant of the table */
1847     gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 1, 0, 1);
1848
1849     gtk_widget_show (button);
1850
1851     /* Create second button */
1852
1853     button = gtk_button_new_with_label ("button 2");
1854
1855     /* When the button is clicked, we call the "callback" function
1856      * with a pointer to "button 2" as its argument */
1857     g_signal_connect (G_OBJECT (button), "clicked",
1858                       G_CALLBACK (callback), (gpointer) "button 2");
1859     /* Insert button 2 into the upper right quadrant of the table */
1860     gtk_table_attach_defaults (GTK_TABLE (table), button, 1, 2, 0, 1);
1861
1862     gtk_widget_show (button);
1863
1864     /* Create "Quit" button */
1865     button = gtk_button_new_with_label ("Quit");
1866
1867     /* When the button is clicked, we call the "delete_event" function
1868      * and the program exits */
1869     g_signal_connect (G_OBJECT (button), "clicked",
1870                       G_CALLBACK (delete_event), NULL);
1871
1872     /* Insert the quit button into the both 
1873      * lower quadrants of the table */
1874     gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 2, 1, 2);
1875
1876     gtk_widget_show (button);
1877
1878     gtk_widget_show (table);
1879     gtk_widget_show (window);
1880
1881     gtk_main ();
1882
1883     return 0;
1884 }
1885 <!-- example-end -->
1886 </programlisting>
1887
1888 </sect1>
1889 </chapter>
1890
1891 <!-- ***************************************************************** -->
1892 <chapter id="ch-WidgetOverview">
1893 <title>Widget Overview</title>
1894
1895 <para>The general steps to creating a widget in GTK are:</para>
1896 <orderedlist>
1897 <listitem><simpara> gtk_*_new() - one of various functions to create a new widget.
1898 These are all detailed in this section.</simpara>
1899 </listitem>
1900
1901 <listitem><simpara> Connect all signals and events we wish to use to the
1902 appropriate handlers.</simpara>
1903 </listitem>
1904
1905 <listitem><simpara> Set the attributes of the widget.</simpara>
1906 </listitem>
1907
1908 <listitem><simpara> Pack the widget into a container using the appropriate call
1909 such as gtk_container_add() or gtk_box_pack_start().</simpara>
1910 </listitem>
1911
1912 <listitem><simpara> gtk_widget_show() the widget.</simpara>
1913 </listitem>
1914 </orderedlist>
1915
1916 <para>gtk_widget_show() lets GTK know that we are done setting the
1917 attributes of the widget, and it is ready to be displayed. You may
1918 also use gtk_widget_hide to make it disappear again. The order in
1919 which you show the widgets is not important, but I suggest showing the
1920 window last so the whole window pops up at once rather than seeing the
1921 individual widgets come up on the screen as they're formed. The
1922 children of a widget (a window is a widget too) will not be displayed
1923 until the window itself is shown using the gtk_widget_show() function.</para>
1924
1925 <!-- ----------------------------------------------------------------- -->
1926 <sect1 id="sec-Casting">
1927 <title>Casting</title>
1928
1929 <para>You'll notice as you go on that GTK uses a type casting system. This
1930 is always done using macros that both test the ability to cast the
1931 given item, and perform the cast. Some common ones you will see are:</para>
1932
1933 <programlisting role="C">
1934   G_OBJECT (object)
1935   GTK_WIDGET (widget)
1936   GTK_OBJECT (object)
1937   GTK_SIGNAL_FUNC (function)
1938   GTK_CONTAINER (container)
1939   GTK_WINDOW (window)
1940   GTK_BOX (box)
1941 </programlisting>
1942
1943 <para>These are all used to cast arguments in functions. You'll see them in the
1944 examples, and can usually tell when to use them simply by looking at the
1945 function's declaration.</para>
1946
1947 <para>As you can see below in the class hierarchy, all GtkWidgets are
1948 derived from the GObject base class. This means you can use a widget
1949 in any place the function asks for an object - simply use the
1950 <literal>G_OBJECT()</literal> macro.</para>
1951
1952 <para>For example:</para>
1953
1954 <programlisting role="C">
1955 g_signal_connect( G_OBJECT (button), "clicked",
1956                   G_CALLBACK (callback_function), callback_data);
1957 </programlisting>
1958
1959 <para>This casts the button into an object, and provides a cast for the
1960 function pointer to the callback.</para>
1961
1962 <para>Many widgets are also containers. If you look in the class hierarchy
1963 below, you'll notice that many widgets derive from the Container
1964 class. Any one of these widgets may be used with the
1965 <literal>GTK_CONTAINER</literal> macro to pass them to functions that ask for
1966 containers.</para>
1967
1968 <para>Unfortunately, these macros are not extensively covered in the
1969 tutorial, but I recommend taking a look through the GTK header
1970 files or the GTK API reference manual. It can be very educational. In fact, 
1971 it's not difficult to learn how a widget works just by looking at the 
1972 function declarations.</para>
1973
1974 </sect1>
1975
1976 <!-- ----------------------------------------------------------------- -->
1977 <sect1 id="sec-WidgetHierarchy">
1978 <title>Widget Hierarchy</title>
1979
1980 <para>For your reference, here is the class hierarchy tree used to implement 
1981 widgets. (Deprecated widgets and auxiliary classes have been omitted.)</para>
1982
1983 <programlisting role="C">
1984 GObject
1985  |  
1986  GtkObject
1987   +GtkWidget
1988   | +GtkMisc
1989   | | +GtkLabel
1990   | | | `GtkAccelLabel
1991   | | +GtkArrow
1992   | | `GtkImage
1993   | +GtkContainer
1994   | | +GtkBin
1995   | | | +GtkAlignment
1996   | | | +GtkFrame
1997   | | | | `GtkAspectFrame
1998   | | | +GtkButton
1999   | | | | +GtkToggleButton
2000   | | | | | `GtkCheckButton
2001   | | | | |   `GtkRadioButton
2002   | | | | `GtkOptionMenu
2003   | | | +GtkItem
2004   | | | | +GtkMenuItem
2005   | | | |   +GtkCheckMenuItem
2006   | | | |   | `GtkRadioMenuItem
2007   | | | |   +GtkImageMenuItem
2008   | | | |   +GtkSeparatorMenuItem
2009   | | | |   `GtkTearoffMenuItem
2010   | | | +GtkWindow
2011   | | | | +GtkDialog
2012   | | | | | +GtkColorSelectionDialog
2013   | | | | | +GtkFileSelection
2014   | | | | | +GtkFontSelectionDialog
2015   | | | | | +GtkInputDialog
2016   | | | | | `GtkMessageDialog
2017   | | | | `GtkPlug
2018   | | | +GtkEventBox
2019   | | | +GtkHandleBox
2020   | | | +GtkScrolledWindow
2021   | | | `GtkViewport
2022   | | +GtkBox
2023   | | | +GtkButtonBox
2024   | | | | +GtkHButtonBox
2025   | | | | `GtkVButtonBox
2026   | | | +GtkVBox
2027   | | | | +GtkColorSelection
2028   | | | | +GtkFontSelection
2029   | | | | `GtkGammaCurve
2030   | | | `GtkHBox
2031   | | |   +GtkCombo
2032   | | |   `GtkStatusbar
2033   | | +GtkFixed
2034   | | +GtkPaned
2035   | | | +GtkHPaned
2036   | | | `GtkVPaned
2037   | | +GtkLayout
2038   | | +GtkMenuShell
2039   | | | +GtkMenuBar
2040   | | | `GtkMenu
2041   | | +GtkNotebook
2042   | | +GtkSocket
2043   | | +GtkTable
2044   | | +GtkTextView
2045   | | +GtkToolbar
2046   | | `GtkTreeView
2047   | +GtkCalendar
2048   | +GtkDrawingArea
2049   | | `GtkCurve
2050   | +GtkEditable
2051   | | +GtkEntry
2052   | |   `GtkSpinButton
2053   | +GtkRuler
2054   | | +GtkHRuler
2055   | | `GtkVRuler
2056   | +GtkRange
2057   | | +GtkScale
2058   | | | +GtkHScale
2059   | | | `GtkVScale
2060   | | `GtkScrollbar
2061   | |   +GtkHScrollbar
2062   | |   `GtkVScrollbar
2063   | +GtkSeparator
2064   | | +GtkHSeparator
2065   | | `GtkVSeparator
2066   | +GtkInvisible
2067   | +GtkPreview
2068   | `GtkProgressBar
2069   +GtkAdjustment
2070   +GtkCellRenderer
2071   | +GtkCellRendererPixbuf
2072   | +GtkCellRendererText
2073   | +GtkCellRendererToggle
2074   +GtkItemFactory
2075   +GtkTooltips
2076   `GtkTreeViewColumn
2077 </programlisting>
2078
2079 </sect1>
2080
2081 <!-- ----------------------------------------------------------------- -->
2082 <sect1 id="sec-WidgetsWithoutWindows">
2083 <title>Widgets Without Windows</title>
2084
2085 <para>The following widgets do not have an associated window. If you want to
2086 capture events, you'll have to use the EventBox. See the section on
2087 the <link linkend="sec-EventBox">EventBox</link> widget.</para>
2088
2089 <programlisting role="C">
2090 GtkAlignment
2091 GtkArrow
2092 GtkBin
2093 GtkBox
2094 GtkButton
2095 GtkCheckButton
2096 GtkFixed
2097 GtkImage
2098 GtkLabel
2099 GtkMenuItem
2100 GtkNotebook
2101 GtkPaned
2102 GtkRadioButton
2103 GtkRange
2104 GtkScrolledWindow
2105 GtkSeparator
2106 GtkTable
2107 GtkToolbar
2108 GtkAspectFrame
2109 GtkFrame
2110 GtkVBox
2111 GtkHBox
2112 GtkVSeparator
2113 GtkHSeparator
2114 </programlisting>
2115
2116 <para>We'll further our exploration of GTK by examining each widget in turn,
2117 creating a few simple functions to display them. Another good source
2118 is the <literal>testgtk</literal> program that comes with GTK. It can be found in
2119 <filename>tests/testgtk.c</filename>.</para>
2120
2121 </sect1>
2122 </chapter>
2123
2124 <!-- ***************************************************************** -->
2125 <chapter id="ch-ButtonWidget">
2126 <title>The Button Widget</title>
2127
2128 <!-- ----------------------------------------------------------------- -->
2129 <sect1 id="sec-NormalButtons">
2130 <title>Normal Buttons</title>
2131
2132 <para>We've almost seen all there is to see of the button widget. It's
2133 pretty simple. There is however more than one way to create a button. You can
2134 use the gtk_button_new_with_label() or gtk_button_new_with_mnemonic() to create 
2135 a button with a label, use gtk_button_new_from_stock() to create a button
2136 containing the image and text from a stock item or use gtk_button_new() to
2137 create a blank button. It's then up to you to pack a label or pixmap into 
2138 this new button. To do this, create a new box, and then pack your objects into 
2139 this box using the usual gtk_box_pack_start(), and then use gtk_container_add() 
2140 to pack the box into the button.</para>
2141
2142 <para>Here's an example of using gtk_button_new() to create a button with a
2143 image and a label in it. I've broken up the code to create a box from the rest 
2144 so you can use it in your programs. There are further examples of using images 
2145 later in the tutorial.</para>
2146
2147 <para>
2148 <inlinemediaobject>
2149 <imageobject>
2150 <imagedata fileref="images/buttons.png" format="png">
2151 </imageobject>
2152 </inlinemediaobject>
2153 </para>
2154
2155 <programlisting role="C">
2156 <!-- example-start buttons buttons.c -->
2157
2158 #include &lt;stdlib.h&gt;
2159 #include &lt;gtk/gtk.h&gt;
2160
2161 /* Create a new hbox with an image and a label packed into it
2162  * and return the box. */
2163
2164 static GtkWidget *xpm_label_box( gchar     *xpm_filename,
2165                                  gchar     *label_text )
2166 {
2167     GtkWidget *box;
2168     GtkWidget *label;
2169     GtkWidget *image;
2170
2171     /* Create box for image and label */
2172     box = gtk_hbox_new (FALSE, 0);
2173     gtk_container_set_border_width (GTK_CONTAINER (box), 2);
2174
2175     /* Now on to the image stuff */
2176     image = gtk_image_new_from_file (xpm_filename);
2177
2178     /* Create a label for the button */
2179     label = gtk_label_new (label_text);
2180
2181     /* Pack the image and label into the box */
2182     gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 3);
2183     gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 3);
2184
2185     gtk_widget_show (image);
2186     gtk_widget_show (label);
2187
2188     return box;
2189 }
2190
2191 /* Our usual callback function */
2192 static void callback( GtkWidget *widget,
2193                       gpointer   data )
2194 {
2195     g_print ("Hello again - %s was pressed\n", (char *) data);
2196 }
2197
2198 int main( int   argc,
2199           char *argv[] )
2200 {
2201     /* GtkWidget is the storage type for widgets */
2202     GtkWidget *window;
2203     GtkWidget *button;
2204     GtkWidget *box;
2205
2206     gtk_init (&amp;argc, &amp;argv);
2207
2208     /* Create a new window */
2209     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2210
2211     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
2212
2213     /* It's a good idea to do this for all windows. */
2214     g_signal_connect (G_OBJECT (window), "destroy",
2215                       G_CALLBACK (gtk_main_quit), NULL);
2216
2217     g_signal_connect (G_OBJECT (window), "delete_event",
2218                       G_CALLBACK (gtk_main_quit), NULL);
2219
2220     /* Sets the border width of the window. */
2221     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
2222
2223     /* Create a new button */
2224     button = gtk_button_new ();
2225
2226     /* Connect the "clicked" signal of the button to our callback */
2227     g_signal_connect (G_OBJECT (button), "clicked",
2228                       G_CALLBACK (callback), (gpointer) "cool button");
2229
2230     /* This calls our box creating function */
2231     box = xpm_label_box ("info.xpm", "cool button");
2232
2233     /* Pack and show all our widgets */
2234     gtk_widget_show (box);
2235
2236     gtk_container_add (GTK_CONTAINER (button), box);
2237
2238     gtk_widget_show (button);
2239
2240     gtk_container_add (GTK_CONTAINER (window), button);
2241
2242     gtk_widget_show (window);
2243
2244     /* Rest in gtk_main and wait for the fun to begin! */
2245     gtk_main ();
2246
2247     return 0;
2248 }
2249 <!-- example-end -->
2250 </programlisting>
2251
2252 <para>The xpm_label_box() function could be used to pack images and labels into
2253 any widget that can be a container.</para>
2254
2255 <para>The Button widget has the following signals:</para>
2256
2257 <itemizedlist>
2258 <listitem><simpara><literal>pressed</literal> - emitted when pointer button is pressed within
2259 Button widget</simpara>
2260 </listitem>
2261 <listitem><simpara><literal>released</literal> - emitted when pointer button is released within
2262 Button widget</simpara>
2263 </listitem>
2264 <listitem><simpara><literal>clicked</literal> - emitted when pointer button is pressed and then
2265 released within Button widget</simpara>
2266 </listitem>
2267 <listitem><simpara><literal>enter</literal> - emitted when pointer enters Button widget</simpara>
2268 </listitem>
2269 <listitem><simpara><literal>leave</literal> - emitted when pointer leaves Button widget</simpara>
2270 </listitem>
2271 </itemizedlist>
2272
2273 </sect1>
2274
2275 <!-- ----------------------------------------------------------------- -->
2276 <sect1 id="sec-ToggleButtons">
2277 <title>Toggle Buttons</title>
2278
2279 <para>Toggle buttons are derived from normal buttons and are very similar,
2280 except they will always be in one of two states, alternated by a
2281 click. They may be depressed, and when you click again, they will pop
2282 back up. Click again, and they will pop back down.</para>
2283
2284 <para>Toggle buttons are the basis for check buttons and radio buttons, as
2285 such, many of the calls used for toggle buttons are inherited by radio
2286 and check buttons. I will point these out when we come to them.</para>
2287
2288 <para>Creating a new toggle button:</para>
2289
2290 <programlisting role="C">
2291 GtkWidget *gtk_toggle_button_new( void );
2292
2293 GtkWidget *gtk_toggle_button_new_with_label( const gchar *label );
2294
2295 GtkWidget *gtk_toggle_button_new_with_mnemonic( const gchar *label );
2296 </programlisting>
2297
2298 <para>As you can imagine, these work identically to the normal button widget
2299 calls. The first creates a blank toggle button, and the last two, a
2300 button with a label widget already packed into it. The _mnemonic() variant
2301 additionally parses the label for '_'-prefixed mnemonic characters.</para>
2302
2303 <para>To retrieve the state of the toggle widget, including radio and check
2304 buttons, we use a construct as shown in our example below. This tests
2305 the state of the toggle button, by accessing the <literal>active</literal> field of the
2306 toggle widget's structure, after first using the
2307 <literal>GTK_TOGGLE_BUTTON</literal> macro to cast the widget pointer into a toggle
2308 widget pointer. The signal of interest to us emitted by toggle
2309 buttons (the toggle button, check button, and radio button widgets) is
2310 the "toggled" signal. To check the state of these buttons, set up a
2311 signal handler to catch the toggled signal, and access the structure
2312 to determine its state. The callback will look something like:</para>
2313
2314 <programlisting role="C">
2315 void toggle_button_callback (GtkWidget *widget, gpointer data)
2316 {
2317     if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) 
2318     {
2319         /* If control reaches here, the toggle button is down */
2320     
2321     } else {
2322     
2323         /* If control reaches here, the toggle button is up */
2324     }
2325 }
2326 </programlisting>
2327
2328 <para>To force the state of a toggle button, and its children, the radio and
2329 check buttons, use this function:</para>
2330
2331 <programlisting role="C">
2332 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2333                                    gboolean        is_active );
2334 </programlisting>
2335
2336 <para>The above call can be used to set the state of the toggle button, and
2337 its children the radio and check buttons. Passing in your created
2338 button as the first argument, and a TRUE or FALSE for the second state
2339 argument to specify whether it should be down (depressed) or up
2340 (released). Default is up, or FALSE.</para>
2341
2342 <para>Note that when you use the gtk_toggle_button_set_active() function, and
2343 the state is actually changed, it causes the "clicked" and "toggled"
2344 signals to be emitted from the button.</para>
2345
2346 <programlisting role="C">
2347 gboolean gtk_toggle_button_get_active   (GtkToggleButton *toggle_button);
2348 </programlisting>
2349
2350 <para>This returns the current state of the toggle button as a boolean
2351 TRUE/FALSE value.</para>
2352
2353 </sect1>
2354
2355 <!-- ----------------------------------------------------------------- -->
2356 <sect1 id="sec-CheckButtons">
2357 <title>Check Buttons</title>
2358
2359 <para>Check buttons inherit many properties and functions from the the
2360 toggle buttons above, but look a little different. Rather than being
2361 buttons with text inside them, they are small squares with the text to
2362 the right of them. These are often used for toggling options on and
2363 off in applications.</para>
2364
2365 <para>The creation functions are similar to those of the normal button.</para>
2366
2367 <programlisting role="C">
2368 GtkWidget *gtk_check_button_new( void );
2369
2370 GtkWidget *gtk_check_button_new_with_label ( const gchar *label );
2371
2372 GtkWidget *gtk_check_button_new_with_mnemonic ( const gchar *label );
2373 </programlisting>
2374
2375 <para>The gtk_check_button_new_with_label() function creates a check button 
2376 with a label beside it.</para>
2377
2378 <para>Checking the state of the check button is identical to that of the
2379 toggle button.</para>
2380
2381 </sect1>
2382
2383 <!-- ----------------------------------------------------------------- -->
2384 <sect1 id="sec-RadioButtons">
2385 <title>Radio Buttons</title>
2386
2387 <para>Radio buttons are similar to check buttons except they are grouped so
2388 that only one may be selected/depressed at a time. This is good for
2389 places in your application where you need to select from a short list
2390 of options.</para>
2391
2392 <para>Creating a new radio button is done with one of these calls:</para>
2393
2394 <programlisting role="C">
2395 GtkWidget *gtk_radio_button_new( GSList *group );
2396
2397 GtkWidget *gtk_radio_button_new_from_widget( GtkRadioButton *group );
2398
2399 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
2400                                             const gchar  *label );
2401
2402 GtkWidget* gtk_radio_button_new_with_label_from_widget( GtkRadioButton *group,
2403                                                         const gchar    *label );
2404
2405 GtkWidget *gtk_radio_button_new_with_mnemonic( GSList *group,
2406                                                const gchar  *label );
2407
2408 GtkWidget *gtk_radio_button_new_with_mnemonic_from_widget( GtkRadioButton *group,
2409                                                            const gchar  *label );
2410
2411 </programlisting>
2412
2413 <para>You'll notice the extra argument to these calls. They require a group
2414 to perform their duty properly. The first call to gtk_radio_button_new() or 
2415 gtk_radio_button_new_with_label() should pass NULL as the first argument. 
2416 Then create a group using:</para>
2417
2418 <programlisting role="C">
2419 GSList *gtk_radio_button_get_group( GtkRadioButton *radio_button );
2420 </programlisting>
2421
2422 <para>The important thing to remember is that gtk_radio_button_get_group() must be
2423 called for each new button added to the group, with the previous button passed 
2424 in as an argument. The result is then passed into the next call to 
2425 gtk_radio_button_new() or gtk_radio_button_new_with_label(). This allows a
2426 chain of buttons to be established. The example below should make this clear.</para>
2427
2428 <para>You can shorten this slightly by using the following syntax, which
2429 removes the need for a variable to hold the list of buttons:</para>
2430
2431 <programlisting role="C">
2432      button2 = gtk_radio_button_new_with_label(
2433                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button1)),
2434                  "button2");
2435 </programlisting>
2436
2437 <para>
2438 The _from_widget() variants of the creation functions allow you to shorten this
2439 further, by omitting the gtk_radio_button_get_group() call. This form is used 
2440 in the example to create the third button:
2441 </para>
2442
2443 <programlisting role="C">
2444      button2 = gtk_radio_button_new_with_label_from_widget(
2445                  GTK_RADIO_BUTTON (button1), 
2446                  "button2");
2447 </programlisting>
2448
2449 <para>It is also a good idea to explicitly set which button should be the
2450 default depressed button with:</para>
2451
2452 <programlisting role="C">
2453 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2454                                    gboolean        state );
2455 </programlisting>
2456
2457 <para>This is described in the section on toggle buttons, and works in
2458 exactly the same way.  Once the radio buttons are grouped together,
2459 only one of the group may be active at a time. If the user clicks on
2460 one radio button, and then on another, the first radio button will
2461 first emit a "toggled" signal (to report becoming inactive), and then
2462 the second will emit its "toggled" signal (to report becoming active).</para>
2463
2464 <para>The following example creates a radio button group with three buttons.</para>
2465
2466 <para>
2467 <inlinemediaobject>
2468 <imageobject>
2469 <imagedata fileref="images/radiobuttons.png" format="png">
2470 </imageobject>
2471 </inlinemediaobject>
2472 </para>
2473
2474 <programlisting role="C">
2475 <!-- example-start radiobuttons radiobuttons.c -->
2476
2477 #include &lt;glib.h&gt;
2478 #include &lt;gtk/gtk.h&gt;
2479
2480 static gboolean close_application( GtkWidget *widget,
2481                                    GdkEvent  *event,
2482                                    gpointer   data )
2483 {
2484   gtk_main_quit ();
2485   return FALSE;
2486 }
2487
2488 int main( int   argc,
2489           char *argv[] )
2490 {
2491     GtkWidget *window = NULL;
2492     GtkWidget *box1;
2493     GtkWidget *box2;
2494     GtkWidget *button;
2495     GtkWidget *separator;
2496     GSList *group;
2497   
2498     gtk_init (&amp;argc, &amp;argv);    
2499       
2500     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2501   
2502     g_signal_connect (G_OBJECT (window), "delete_event",
2503                       G_CALLBACK (close_application),
2504                       NULL);
2505
2506     gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
2507     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2508
2509     box1 = gtk_vbox_new (FALSE, 0);
2510     gtk_container_add (GTK_CONTAINER (window), box1);
2511     gtk_widget_show (box1);
2512
2513     box2 = gtk_vbox_new (FALSE, 10);
2514     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2515     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2516     gtk_widget_show (box2);
2517
2518     button = gtk_radio_button_new_with_label (NULL, "button1");
2519     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2520     gtk_widget_show (button);
2521
2522     group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
2523     button = gtk_radio_button_new_with_label (group, "button2");
2524     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2525     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2526     gtk_widget_show (button);
2527
2528     button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (button),
2529                                                           "button3");
2530     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2531     gtk_widget_show (button);
2532
2533     separator = gtk_hseparator_new ();
2534     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2535     gtk_widget_show (separator);
2536
2537     box2 = gtk_vbox_new (FALSE, 10);
2538     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2539     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2540     gtk_widget_show (box2);
2541
2542     button = gtk_button_new_with_label ("close");
2543     g_signal_connect_swapped (G_OBJECT (button), "clicked",
2544                               G_CALLBACK (close_application),
2545                               G_OBJECT (window));
2546     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2547     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2548     gtk_widget_grab_default (button);
2549     gtk_widget_show (button);
2550     gtk_widget_show (window);
2551      
2552     gtk_main ();
2553
2554     return 0;
2555 }
2556 <!-- example-end -->
2557 </programlisting>
2558
2559 </sect1>
2560 </chapter>
2561
2562 <!-- ***************************************************************** -->
2563 <chapter id="ch-Adjustments">
2564 <title>Adjustments</title>
2565
2566 <para>GTK has various widgets that can be visually adjusted by the user
2567 using the mouse or the keyboard, such as the range widgets, described
2568 in the <link linkend="ch-RangeWidgets">Range Widgets</link>
2569 section. There are also a few widgets that display some adjustable
2570 portion of a larger area of data, such as the text widget and the
2571 viewport widget.</para>
2572
2573 <para>Obviously, an application needs to be able to react to changes the
2574 user makes in range widgets. One way to do this would be to have each
2575 widget emit its own type of signal when its adjustment changes, and
2576 either pass the new value to the signal handler, or require it to look
2577 inside the widget's data structure in order to ascertain the value.
2578 But you may also want to connect the adjustments of several widgets
2579 together, so that adjusting one adjusts the others. The most obvious
2580 example of this is connecting a scrollbar to a panning viewport or a
2581 scrolling text area. If each widget has its own way of setting or
2582 getting the adjustment value, then the programmer may have to write
2583 their own signal handlers to translate between the output of one
2584 widget's signal and the "input" of another's adjustment setting
2585 function.</para>
2586
2587 <para>GTK solves this problem using the Adjustment object, which is not a
2588 widget but a way for widgets to store and pass adjustment information
2589 in an abstract and flexible form. The most obvious use of Adjustment
2590 is to store the configuration parameters and values of range widgets,
2591 such as scrollbars and scale controls. However, since Adjustments are
2592 derived from Object, they have some special powers beyond those of
2593 normal data structures. Most importantly, they can emit signals, just
2594 like widgets, and these signals can be used not only to allow your
2595 program to react to user input on adjustable widgets, but also to
2596 propagate adjustment values transparently between adjustable widgets.</para>
2597
2598 <para>You will see how adjustments fit in when you see the other widgets
2599 that incorporate them:
2600 <link linkend="sec-ProgressBars">Progress Bars</link>,
2601 <link linkend="sec-Viewports">Viewports</link>,
2602 <link linkend="sec-ScrolledWindows">Scrolled Windows</link>, and others.</para>
2603
2604 <!-- ----------------------------------------------------------------- -->
2605 <sect1 id="sec-CreatingAnAdjustment">
2606 <title>Creating an Adjustment</title>
2607
2608 <para>Many of the widgets which use adjustment objects do so automatically,
2609 but some cases will be shown in later examples where you may need to
2610 create one yourself. You create an adjustment using:</para>
2611
2612 <programlisting role="C">
2613 GtkObject *gtk_adjustment_new( gdouble value,
2614                                gdouble lower,
2615                                gdouble upper,
2616                                gdouble step_increment,
2617                                gdouble page_increment,
2618                                gdouble page_size );
2619 </programlisting>
2620
2621 <para>The <literal>value</literal> argument is the initial value you want to give to the
2622 adjustment, usually corresponding to the topmost or leftmost position
2623 of an adjustable widget. The <literal>lower</literal> argument specifies the lowest
2624 value which the adjustment can hold. The <literal>step_increment</literal> argument
2625 specifies the "smaller" of the two increments by which the user can
2626 change the value, while the <literal>page_increment</literal> is the "larger" one.
2627 The <literal>page_size</literal> argument usually corresponds somehow to the visible
2628 area of a panning widget. The <literal>upper</literal> argument is used to represent
2629 the bottom most or right most coordinate in a panning widget's
2630 child. Therefore it is <emphasis>not</emphasis> always the largest number that
2631 <literal>value</literal> can take, since the <literal>page_size</literal> of such widgets is
2632 usually non-zero.</para>
2633
2634 </sect1>
2635
2636 <!-- ----------------------------------------------------------------- -->
2637 <sect1 id="sec-UsingAdjustments">
2638 <title>Using Adjustments the Easy Way</title>
2639
2640 <para>The adjustable widgets can be roughly divided into those which use and
2641 require specific units for these values and those which treat them as
2642 arbitrary numbers. The group which treats the values as arbitrary
2643 numbers includes the range widgets (scrollbars and scales, the
2644 progress bar widget, and the spin button widget). These widgets are
2645 all the widgets which are typically "adjusted" directly by the user
2646 with the mouse or keyboard. They will treat the <literal>lower</literal> and
2647 <literal>upper</literal> values of an adjustment as a range within which the user
2648 can manipulate the adjustment's <literal>value</literal>. By default, they will only
2649 modify the <literal>value</literal> of an adjustment.</para>
2650
2651 <para>The other group includes the text widget, the viewport widget, the
2652 compound list widget, and the scrolled window widget. All of these
2653 widgets use pixel values for their adjustments. These are also all
2654 widgets which are typically "adjusted" indirectly using scrollbars.
2655 While all widgets which use adjustments can either create their own
2656 adjustments or use ones you supply, you'll generally want to let this
2657 particular category of widgets create its own adjustments. Usually,
2658 they will eventually override all the values except the <literal>value</literal>
2659 itself in whatever adjustments you give them, but the results are, in
2660 general, undefined (meaning, you'll have to read the source code to
2661 find out, and it may be different from widget to widget).</para>
2662
2663 <para>Now, you're probably thinking, since text widgets and viewports insist
2664 on setting everything except the <literal>value</literal> of their adjustments,
2665 while scrollbars will <emphasis>only</emphasis> touch the adjustment's 
2666 <literal>value</literal>, if you <emphasis>share</emphasis> an adjustment
2667 object between a scrollbar and a text widget, manipulating the scrollbar will 
2668 automagically adjust the viewport widget?  Of course it will! Just like this:</para>
2669
2670 <programlisting role="C">
2671   /* creates its own adjustments */
2672   viewport = gtk_viewport_new (NULL, NULL);
2673   /* uses the newly-created adjustment for the scrollbar as well */
2674   vscrollbar = gtk_vscrollbar_new (gtk_viewport_get_vadjustment (viewport));
2675 </programlisting>
2676
2677 </sect1>
2678
2679 <!-- ----------------------------------------------------------------- -->
2680 <sect1 id="sec-AdjustmentInternals">
2681 <title>Adjustment Internals</title>
2682
2683 <para>Ok, you say, that's nice, but what if I want to create my own handlers
2684 to respond when the user adjusts a range widget or a spin button, and
2685 how do I get at the value of the adjustment in these handlers?  To
2686 answer these questions and more, let's start by taking a look at
2687 <literal>struct _GtkAdjustment</literal> itself:</para>
2688
2689 <programlisting role="C">
2690 struct _GtkAdjustment
2691 {
2692   GtkObject parent_instance;
2693   
2694   gdouble lower;
2695   gdouble upper;
2696   gdouble value;
2697   gdouble step_increment;
2698   gdouble page_increment;
2699   gdouble page_size;
2700 };
2701 </programlisting>
2702
2703 <para>If you don't like to poke directly at struct internals like a 
2704 <emphasis>real</emphasis> C programmer, you can use the following accessor to
2705 inspect the <literal>value</literal> of an adjustment:</para>
2706
2707 <programlisting role="C">
2708 gdouble gtk_adjustment_get_value( GtkAdjustment *adjustment);
2709 </programlisting>
2710
2711 <para>Since, when you set the <literal>value</literal> of an Adjustment, you generally
2712 want the change to be reflected by every widget that uses this
2713 adjustment, GTK provides this convenience function to do this:</para>
2714
2715 <programlisting role="C">
2716 void gtk_adjustment_set_value( GtkAdjustment *adjustment,
2717                                gdouble       value );
2718 </programlisting>
2719
2720 <para>As mentioned earlier, Adjustment is a subclass of Object just
2721 like all the various widgets, and thus it is able to emit signals.
2722 This is, of course, why updates happen automagically when you share an
2723 adjustment object between a scrollbar and another adjustable widget;
2724 all adjustable widgets connect signal handlers to their adjustment's
2725 <literal>value_changed</literal> signal, as can your program. Here's the definition
2726 of this signal in <literal>struct _GtkAdjustmentClass</literal>:</para>
2727
2728 <programlisting role="C">
2729   void (* value_changed) (GtkAdjustment *adjustment);
2730 </programlisting>
2731
2732 <para>The various widgets that use the Adjustment object will emit this
2733 signal on an adjustment whenever they change its value. This happens
2734 both when user input causes the slider to move on a range widget, as
2735 well as when the program explicitly changes the value with
2736 gtk_adjustment_set_value(). So, for example, if you have a scale
2737 widget, and you want to change the rotation of a picture whenever its
2738 value changes, you would create a callback like this:</para>
2739
2740 <programlisting role="C">
2741 void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
2742 {
2743   set_picture_rotation (picture, gtk_adjustment_get_value (adj));
2744 ...
2745 </programlisting>
2746
2747 <para>and connect it to the scale widget's adjustment like this:</para>
2748
2749 <programlisting role="C">
2750 g_signal_connect (G_OBJECT (adj), "value_changed",
2751                   G_CALLBACK (cb_rotate_picture), (gpointer) picture);
2752 </programlisting>
2753
2754 <para>What about when a widget reconfigures the <literal>upper</literal> or <literal>lower</literal>
2755 fields of its adjustment, such as when a user adds more text to a text
2756 widget?  In this case, it emits the <literal>changed</literal> signal, which looks
2757 like this:</para>
2758
2759 <programlisting role="C">
2760   void (* changed) (GtkAdjustment *adjustment);
2761 </programlisting>
2762
2763 <para>Range widgets typically connect a handler to this signal, which
2764 changes their appearance to reflect the change - for example, the size
2765 of the slider in a scrollbar will grow or shrink in inverse proportion
2766 to the difference between the <literal>lower</literal> and <literal>upper</literal> values of its
2767 adjustment.</para>
2768
2769 <para>You probably won't ever need to attach a handler to this signal,
2770 unless you're writing a new type of range widget.  However, if you
2771 change any of the values in a Adjustment directly, you should emit
2772 this signal on it to reconfigure whatever widgets are using it, like
2773 this:</para>
2774
2775 <programlisting role="C">
2776 g_signal_emit_by_name (G_OBJECT (adjustment), "changed");
2777 </programlisting>
2778
2779 <para>Now go forth and adjust!</para>
2780
2781 </sect1>
2782 </chapter>
2783
2784 <!-- ***************************************************************** -->
2785 <chapter id="ch-RangeWidgets">
2786 <title>Range Widgets</title>
2787
2788 <para>The category of range widgets includes the ubiquitous scrollbar widget
2789 and the less common scale widget. Though these two types of widgets
2790 are generally used for different purposes, they are quite similar in
2791 function and implementation. All range widgets share a set of common
2792 graphic elements, each of which has its own X window and receives
2793 events. They all contain a "trough" and a "slider" (what is sometimes
2794 called a "thumbwheel" in other GUI environments). Dragging the slider
2795 with the pointer moves it back and forth within the trough, while
2796 clicking in the trough advances the slider towards the location of the
2797 click, either completely, or by a designated amount, depending on
2798 which mouse button is used.</para>
2799
2800 <para>As mentioned in <link linkend="ch-Adjustments">Adjustments</link> above,
2801 all range widgets are associated with an adjustment object, from which
2802 they calculate the length of the slider and its position within the
2803 trough. When the user manipulates the slider, the range widget will
2804 change the value of the adjustment.</para>
2805
2806 <!-- ----------------------------------------------------------------- -->
2807 <sect1 id="sec-ScrollbarWidgets">
2808 <title>Scrollbar Widgets</title>
2809
2810 <para>These are your standard, run-of-the-mill scrollbars. These should be
2811 used only for scrolling some other widget, such as a list, a text box,
2812 or a viewport (and it's generally easier to use the scrolled window
2813 widget in most cases).  For other purposes, you should use scale
2814 widgets, as they are friendlier and more featureful.</para>
2815
2816 <para>There are separate types for horizontal and vertical scrollbars.
2817 There really isn't much to say about these. You create them with the
2818 following functions:</para>
2819
2820 <programlisting role="C">
2821 GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );
2822
2823 GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );
2824 </programlisting>
2825
2826 <para>and that's about it (if you don't believe me, look in the header
2827 files!).  The <literal>adjustment</literal> argument can either be a pointer to an
2828 existing Adjustment, or NULL, in which case one will be created for
2829 you. Specifying NULL might actually be useful in this case, if you
2830 wish to pass the newly-created adjustment to the constructor function
2831 of some other widget which will configure it for you, such as a text
2832 widget.</para>
2833
2834 </sect1>
2835
2836 <!-- ----------------------------------------------------------------- -->
2837 <sect1 id="sec-ScaleWidgets">
2838 <title>Scale Widgets</title>
2839
2840 <para>Scale widgets are used to allow the user to visually select and
2841 manipulate a value within a specific range. You might want to use a
2842 scale widget, for example, to adjust the magnification level on a
2843 zoomed preview of a picture, or to control the brightness of a color,
2844 or to specify the number of minutes of inactivity before a screensaver
2845 takes over the screen.</para>
2846
2847 <!-- ----------------------------------------------------------------- -->
2848 <sect2>
2849 <title>Creating a Scale Widget</title>
2850
2851 <para>As with scrollbars, there are separate widget types for horizontal and
2852 vertical scale widgets. (Most programmers seem to favour horizontal
2853 scale widgets.) Since they work essentially the same way, there's no
2854 need to treat them separately here. The following functions create vertical and 
2855 horizontal scale widgets, respectively:</para>
2856
2857 <programlisting role="C">
2858 GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );
2859
2860 GtkWidget *gtk_vscale_new_with_range( gdouble min,
2861                                       gdouble max,
2862                                       gdouble step );
2863
2864 GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );
2865
2866 GtkWidget *gtk_hscale_new_with_range( gdouble min,
2867                                       gdouble max,
2868                                       gdouble step );
2869 </programlisting>
2870
2871 <para>The <literal>adjustment</literal> argument can either be an adjustment which has
2872 already been created with gtk_adjustment_new(), or NULL, in
2873 which case, an anonymous Adjustment is created with all of its
2874 values set to <literal>0.0</literal> (which isn't very useful in this case). 
2875 In order to avoid confusing yourself, you probably want to create your
2876 adjustment with a <literal>page_size</literal> of <literal>0.0</literal> so 
2877 that its <literal>upper</literal> value actually corresponds to the highest 
2878 value the user can select. The _new_with_range() variants take care of creating
2879 a suitable adjustment. (If you're <emphasis>already</emphasis> thoroughly
2880 confused, read the section on <link linkend="ch-Adjustments">Adjustments</link> 
2881 again for an explanation of what exactly adjustments do and how to create and 
2882 manipulate them.)</para>
2883
2884 </sect2>
2885
2886 <!-- ----------------------------------------------------------------- -->
2887 <sect2>
2888 <title>Functions and Signals (well, functions, at least)</title>
2889
2890 <para>Scale widgets can display their current value as a number beside the
2891 trough. The default behaviour is to show the value, but you can change
2892 this with this function:</para>
2893
2894 <programlisting role="C">
2895 void gtk_scale_set_draw_value( GtkScale *scale,
2896                                gboolean draw_value );
2897 </programlisting>
2898
2899 <para>As you might have guessed, <literal>draw_value</literal> is either <literal>TRUE</literal> or
2900 <literal>FALSE</literal>, with predictable consequences for either one.</para>
2901
2902 <para>The value displayed by a scale widget is rounded to one decimal point
2903 by default, as is the <literal>value</literal> field in its Adjustment. You can
2904 change this with:</para>
2905
2906 <programlisting role="C">
2907 void gtk_scale_set_digits( GtkScale *scale,
2908                             gint     digits );
2909 </programlisting>
2910
2911 <para>where <literal>digits</literal> is the number of decimal places you want. You can
2912 set <literal>digits</literal> to anything you like, but no more than 13 decimal
2913 places will actually be drawn on screen.</para>
2914
2915 <para>Finally, the value can be drawn in different positions
2916 relative to the trough:</para>
2917
2918 <programlisting role="C">
2919 void gtk_scale_set_value_pos( GtkScale        *scale,
2920                               GtkPositionType  pos );
2921 </programlisting>
2922
2923 <para>The argument <literal>pos</literal> is of type <literal>GtkPositionType</literal>,
2924 which can take one of the following values:</para>
2925
2926 <programlisting role="C">
2927   GTK_POS_LEFT
2928   GTK_POS_RIGHT
2929   GTK_POS_TOP
2930   GTK_POS_BOTTOM
2931 </programlisting>
2932
2933 <para>If you position the value on the "side" of the trough (e.g., on the
2934 top or bottom of a horizontal scale widget), then it will follow the
2935 slider up and down the trough.</para>
2936
2937 <para>All the preceding functions are defined in
2938 <literal>&lt;gtk/gtkscale.h&gt;</literal>. The header files for all GTK widgets
2939 are automatically included when you include
2940 <literal>&lt;gtk/gtk.h&gt;</literal>. But you should look over the header files
2941 of all widgets that interest you, in order to learn more about their functions
2942 and features.</para>
2943
2944 </sect2>
2945 </sect1>
2946
2947 <!-- ----------------------------------------------------------------- -->
2948 <sect1 id="sec-CommonRangeFunctions">
2949 <title>Common Range Functions</title>
2950
2951 <para>The Range widget class is fairly complicated internally, but, like
2952 all the "base class" widgets, most of its complexity is only
2953 interesting if you want to hack on it. Also, almost all of the
2954 functions and signals it defines are only really used in writing
2955 derived widgets. There are, however, a few useful functions that are
2956 defined in <literal>&lt;gtk/gtkrange.h&gt;</literal> and will work on all range
2957 widgets.</para>
2958
2959 <!-- ----------------------------------------------------------------- -->
2960 <sect2>
2961 <title>Setting the Update Policy</title>
2962
2963 <para>The "update policy" of a range widget defines at what points during
2964 user interaction it will change the <literal>value</literal> field of its
2965 Adjustment and emit the "value_changed" signal on this
2966 Adjustment. The update policies, defined in
2967 <literal>&lt;gtk/gtkenums.h&gt;</literal> as type <literal>enum GtkUpdateType</literal>,
2968 are:</para>
2969
2970 <variablelist>
2971 <varlistentry>
2972 <term><literal>GTK_UPDATE_CONTINUOUS</literal></term>
2973 <listitem><para>This is the default. The
2974 "value_changed" signal is emitted continuously, i.e., whenever the
2975 slider is moved by even the tiniest amount.</para>
2976 </listitem>
2977 </varlistentry>
2978 <varlistentry>
2979 <term><literal>GTK_UPDATE_DISCONTINUOUS</literal></term>
2980 <listitem><para>The "value_changed" signal is
2981 only emitted once the slider has stopped moving and the user has
2982 released the mouse button.</para>
2983 </listitem>
2984 </varlistentry>
2985 <varlistentry>
2986 <term><literal>GTK_UPDATE_DELAYED</literal></term>
2987 <listitem><para>The "value_changed" signal is emitted
2988 when the user releases the mouse button, or if the slider stops moving
2989 for a short period of time.</para>
2990 </listitem>
2991 </varlistentry>
2992 </variablelist>
2993
2994 <para>The update policy of a range widget can be set by casting it using the
2995 <literal>GTK_RANGE(widget)</literal> macro and passing it to this function:</para>
2996
2997 <programlisting role="C">
2998 void gtk_range_set_update_policy( GtkRange      *range,
2999                                   GtkUpdateType  policy);
3000 </programlisting>
3001
3002 </sect2>
3003
3004 <!-- ----------------------------------------------------------------- -->
3005 <sect2>
3006 <title>Getting and Setting Adjustments</title>
3007
3008 <para>Getting and setting the adjustment for a range widget "on the fly" is
3009 done, predictably, with:</para>
3010
3011 <programlisting role="C">
3012 GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );
3013
3014 void gtk_range_set_adjustment( GtkRange      *range,
3015                                GtkAdjustment *adjustment );
3016 </programlisting>
3017
3018 <para><literal>gtk_range_get_adjustment()</literal> returns a pointer to the adjustment to
3019 which <literal>range</literal> is connected.</para>
3020
3021 <para><literal>gtk_range_set_adjustment()</literal> does absolutely nothing if you pass it
3022 the adjustment that <literal>range</literal> is already using, regardless of whether
3023 you changed any of its fields or not. If you pass it a new
3024 Adjustment, it will unreference the old one if it exists (possibly
3025 destroying it), connect the appropriate signals to the new one, and
3026 call the private function <literal>gtk_range_adjustment_changed()</literal>, which
3027 will (or at least, is supposed to...) recalculate the size and/or
3028 position of the slider and redraw if necessary. As mentioned in the
3029 section on adjustments, if you wish to reuse the same Adjustment,
3030 when you modify its values directly, you should emit the "changed"
3031 signal on it, like this:</para>
3032
3033 <programlisting role="C">
3034 g_signal_emit_by_name (G_OBJECT (adjustment), "changed");
3035 </programlisting>
3036
3037 </sect2>
3038 </sect1>
3039
3040 <!-- ----------------------------------------------------------------- -->
3041 <sect1 id="sec-KeyAndMouseBindings">
3042 <title>Key and Mouse bindings</title>
3043
3044 <para>All of the GTK range widgets react to mouse clicks in more or less
3045 the same way. Clicking button-1 in the trough will cause its
3046 adjustment's <literal>page_increment</literal> to be added or subtracted from its
3047 <literal>value</literal>, and the slider to be moved accordingly. Clicking mouse
3048 button-2 in the trough will jump the slider to the point at which the
3049 button was clicked. Clicking button-3 in the trough of a range or any button on 
3050 a scrollbar's arrows will cause its adjustment's value to change by
3051 <literal>step_increment</literal> at a time.</para>
3052
3053 <para>Scrollbars are not focusable, thus have no key bindings. The key bindings
3054 for the other range widgets (which are, of course, only active when the widget 
3055 has focus) are do <emphasis>not</emphasis> differentiate between horizontal and 
3056 vertical range widgets.</para>
3057
3058 <para>All range widgets can be operated with the left, right, up and down arrow
3059 keys, as well as with the <literal>Page Up</literal> and <literal>Page Down</literal> 
3060 keys. The arrows move the slider up and down by <literal>step_increment</literal>, while
3061 <literal>Page Up</literal> and <literal>Page Down</literal> move it by 
3062 <literal>page_increment</literal>.</para>
3063
3064 <para>The user can also move the slider all the way to one end or the other
3065 of the trough using the keyboard. This is done with the <literal>Home</literal> 
3066 and <literal>End</literal> keys.</para>
3067
3068 </sect1>
3069
3070 <!-- ----------------------------------------------------------------- -->
3071 <sect1 id="sec-RangeWidgetsExample">
3072 <title>Example</title>
3073
3074 <para>This example is a somewhat modified version of the "range controls"
3075 test from <filename>testgtk.c</filename>. It basically puts up a window with three
3076 range widgets all connected to the same adjustment, and a couple of
3077 controls for adjusting some of the parameters mentioned above and in
3078 the section on adjustments, so you can see how they affect the way
3079 these widgets work for the user.</para>
3080
3081 <para>
3082 <inlinemediaobject>
3083 <imageobject>
3084 <imagedata fileref="images/rangewidgets.png" format="png">
3085 </imageobject>
3086 </inlinemediaobject>
3087 </para>
3088
3089 <programlisting role="C">
3090 <!-- example-start rangewidgets rangewidgets.c -->
3091
3092 #include &lt;gtk/gtk.h&gt;
3093
3094 GtkWidget *hscale, *vscale;
3095
3096 static void cb_pos_menu_select( GtkWidget       *item,
3097                                 GtkPositionType  pos )
3098 {
3099     /* Set the value position on both scale widgets */
3100     gtk_scale_set_value_pos (GTK_SCALE (hscale), pos);
3101     gtk_scale_set_value_pos (GTK_SCALE (vscale), pos);
3102 }
3103
3104 static void cb_update_menu_select( GtkWidget     *item,
3105                                    GtkUpdateType  policy )
3106 {
3107     /* Set the update policy for both scale widgets */
3108     gtk_range_set_update_policy (GTK_RANGE (hscale), policy);
3109     gtk_range_set_update_policy (GTK_RANGE (vscale), policy);
3110 }
3111
3112 static void cb_digits_scale( GtkAdjustment *adj )
3113 {
3114     /* Set the number of decimal places to which adj->value is rounded */
3115     gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
3116     gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
3117 }
3118
3119 static void cb_page_size( GtkAdjustment *get,
3120                           GtkAdjustment *set )
3121 {
3122     /* Set the page size and page increment size of the sample
3123      * adjustment to the value specified by the "Page Size" scale */
3124     set->page_size = get->value;
3125     set->page_increment = get->value;
3126
3127     /* This sets the adjustment and makes it emit the "changed" signal to 
3128        reconfigure all the widgets that are attached to this signal.  */
3129     gtk_adjustment_set_value (set, CLAMP (set->value,
3130                                           set->lower,
3131                                           (set->upper - set->page_size)));
3132     g_signal_emit_by_name(G_OBJECT(set), "changed");
3133 }
3134
3135 static void cb_draw_value( GtkToggleButton *button )
3136 {
3137     /* Turn the value display on the scale widgets off or on depending
3138      *  on the state of the checkbutton */
3139     gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active);
3140     gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active);  
3141 }
3142
3143 /* Convenience functions */
3144
3145 static GtkWidget *make_menu_item ( gchar     *name,
3146                                    GCallback  callback,
3147                                    gpointer   data )
3148 {
3149     GtkWidget *item;
3150   
3151     item = gtk_menu_item_new_with_label (name);
3152     g_signal_connect (G_OBJECT (item), "activate",
3153                       callback, (gpointer) data);
3154     gtk_widget_show (item);
3155
3156     return item;
3157 }
3158
3159 static void scale_set_default_values( GtkScale *scale )
3160 {
3161     gtk_range_set_update_policy (GTK_RANGE (scale),
3162                                  GTK_UPDATE_CONTINUOUS);
3163     gtk_scale_set_digits (scale, 1);
3164     gtk_scale_set_value_pos (scale, GTK_POS_TOP);
3165     gtk_scale_set_draw_value (scale, TRUE);
3166 }
3167
3168 /* makes the sample window */
3169
3170 static void create_range_controls( void )
3171 {
3172     GtkWidget *window;
3173     GtkWidget *box1, *box2, *box3;
3174     GtkWidget *button;
3175     GtkWidget *scrollbar;
3176     GtkWidget *separator;
3177     GtkWidget *opt, *menu, *item;
3178     GtkWidget *label;
3179     GtkWidget *scale;
3180     GtkObject *adj1, *adj2;
3181
3182     /* Standard window-creating stuff */
3183     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3184     g_signal_connect (G_OBJECT (window), "destroy",
3185                       G_CALLBACK (gtk_main_quit),
3186                       NULL);
3187     gtk_window_set_title (GTK_WINDOW (window), "range controls");
3188
3189     box1 = gtk_vbox_new (FALSE, 0);
3190     gtk_container_add (GTK_CONTAINER (window), box1);
3191     gtk_widget_show (box1);
3192
3193     box2 = gtk_hbox_new (FALSE, 10);
3194     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3195     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3196     gtk_widget_show (box2);
3197
3198     /* value, lower, upper, step_increment, page_increment, page_size */
3199     /* Note that the page_size value only makes a difference for
3200      * scrollbar widgets, and the highest value you'll get is actually
3201      * (upper - page_size). */
3202     adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
3203   
3204     vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1));
3205     scale_set_default_values (GTK_SCALE (vscale));
3206     gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0);
3207     gtk_widget_show (vscale);
3208
3209     box3 = gtk_vbox_new (FALSE, 10);
3210     gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0);
3211     gtk_widget_show (box3);
3212
3213     /* Reuse the same adjustment */
3214     hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1));
3215     gtk_widget_set_size_request (GTK_WIDGET (hscale), 200, -1);
3216     scale_set_default_values (GTK_SCALE (hscale));
3217     gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0);
3218     gtk_widget_show (hscale);
3219
3220     /* Reuse the same adjustment again */
3221     scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1));
3222     /* Notice how this causes the scales to always be updated
3223      * continuously when the scrollbar is moved */
3224     gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
3225                                  GTK_UPDATE_CONTINUOUS);
3226     gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0);
3227     gtk_widget_show (scrollbar);
3228
3229     box2 = gtk_hbox_new (FALSE, 10);
3230     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3231     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3232     gtk_widget_show (box2);
3233
3234     /* A checkbutton to control whether the value is displayed or not */
3235     button = gtk_check_button_new_with_label("Display value on scale widgets");
3236     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
3237     g_signal_connect (G_OBJECT (button), "toggled",
3238                       G_CALLBACK (cb_draw_value), NULL);
3239     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3240     gtk_widget_show (button);
3241   
3242     box2 = gtk_hbox_new (FALSE, 10);
3243     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3244
3245     /* An option menu to change the position of the value */
3246     label = gtk_label_new ("Scale Value Position:");
3247     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3248     gtk_widget_show (label);
3249   
3250     opt = gtk_option_menu_new ();
3251     menu = gtk_menu_new ();
3252
3253     item = make_menu_item ("Top",
3254                            G_CALLBACK (cb_pos_menu_select),
3255                            GINT_TO_POINTER (GTK_POS_TOP));
3256     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3257   
3258     item = make_menu_item ("Bottom", G_CALLBACK (cb_pos_menu_select), 
3259                            GINT_TO_POINTER (GTK_POS_BOTTOM));
3260     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3261   
3262     item = make_menu_item ("Left", G_CALLBACK (cb_pos_menu_select),
3263                            GINT_TO_POINTER (GTK_POS_LEFT));
3264     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3265   
3266     item = make_menu_item ("Right", G_CALLBACK (cb_pos_menu_select),
3267                            GINT_TO_POINTER (GTK_POS_RIGHT));
3268     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3269   
3270     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
3271     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
3272     gtk_widget_show (opt);
3273
3274     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3275     gtk_widget_show (box2);
3276
3277     box2 = gtk_hbox_new (FALSE, 10);
3278     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3279
3280     /* Yet another option menu, this time for the update policy of the
3281      * scale widgets */
3282     label = gtk_label_new ("Scale Update Policy:");
3283     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3284     gtk_widget_show (label);
3285   
3286     opt = gtk_option_menu_new ();
3287     menu = gtk_menu_new ();
3288   
3289     item = make_menu_item ("Continuous",
3290                            G_CALLBACK (cb_update_menu_select),
3291                            GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS));
3292     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3293   
3294     item = make_menu_item ("Discontinuous",
3295                            G_CALLBACK (cb_update_menu_select),
3296                            GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS));
3297     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3298   
3299     item = make_menu_item ("Delayed",
3300                            G_CALLBACK (cb_update_menu_select),
3301                            GINT_TO_POINTER (GTK_UPDATE_DELAYED));
3302     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3303   
3304     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
3305     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
3306     gtk_widget_show (opt);
3307   
3308     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3309     gtk_widget_show (box2);
3310
3311     box2 = gtk_hbox_new (FALSE, 10);
3312     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3313   
3314     /* An HScale widget for adjusting the number of digits on the
3315      * sample scales. */
3316     label = gtk_label_new ("Scale Digits:");
3317     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3318     gtk_widget_show (label);
3319
3320     adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0);
3321     g_signal_connect (G_OBJECT (adj2), "value_changed",
3322                       G_CALLBACK (cb_digits_scale), NULL);
3323     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
3324     gtk_scale_set_digits (GTK_SCALE (scale), 0);
3325     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
3326     gtk_widget_show (scale);
3327
3328     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3329     gtk_widget_show (box2);
3330   
3331     box2 = gtk_hbox_new (FALSE, 10);
3332     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3333   
3334     /* And, one last HScale widget for adjusting the page size of the
3335      * scrollbar. */
3336     label = gtk_label_new ("Scrollbar Page Size:");
3337     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3338     gtk_widget_show (label);
3339
3340     adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0);
3341     g_signal_connect (G_OBJECT (adj2), "value_changed",
3342                       G_CALLBACK (cb_page_size), (gpointer) adj1);
3343     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
3344     gtk_scale_set_digits (GTK_SCALE (scale), 0);
3345     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
3346     gtk_widget_show (scale);
3347
3348     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3349     gtk_widget_show (box2);
3350
3351     separator = gtk_hseparator_new ();
3352     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3353     gtk_widget_show (separator);
3354
3355     box2 = gtk_vbox_new (FALSE, 10);
3356     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3357     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3358     gtk_widget_show (box2);
3359
3360     button = gtk_button_new_with_label ("Quit");
3361     g_signal_connect_swapped (G_OBJECT (button), "clicked",
3362                               G_CALLBACK (gtk_main_quit),
3363                               NULL);
3364     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3365     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3366     gtk_widget_grab_default (button);
3367     gtk_widget_show (button);
3368
3369     gtk_widget_show (window);
3370 }
3371
3372 int main( int   argc,
3373           char *argv[] )
3374 {
3375     gtk_init (&amp;argc, &amp;argv);
3376
3377     create_range_controls ();
3378
3379     gtk_main ();
3380
3381     return 0;
3382 }
3383
3384 <!-- example-end -->
3385 </programlisting>
3386
3387 <para>You will notice that the program does not call g_signal_connect()
3388 for the "delete_event", but only for the "destroy" signal. This will
3389 still perform the desired function, because an unhandled
3390 "delete_event" will result in a "destroy" signal being given to the
3391 window.</para>
3392
3393 </sect1>
3394 </chapter>
3395
3396 <!-- ***************************************************************** -->
3397 <chapter id="ch-MiscWidgets">
3398 <title>Miscellaneous Widgets</title>
3399
3400 <!-- ----------------------------------------------------------------- -->
3401 <sect1 id="sec-Labels">
3402 <title>Labels</title>
3403
3404 <para>Labels are used a lot in GTK, and are relatively simple. Labels emit
3405 no signals as they do not have an associated X window. If you need to
3406 catch signals, or do clipping, place it inside a <link linkend="sec-EventBox">
3407 EventBox</link> widget or a Button widget.</para>
3408
3409 <para>To create a new label, use:</para>
3410
3411 <programlisting role="C">
3412 GtkWidget *gtk_label_new( const char *str );
3413
3414 GtkWidget *gtk_label_new_with_mnemonic( const char *str );
3415 </programlisting>
3416
3417 <para>The sole argument is the string you wish the label to display.</para>
3418
3419 <para>To change the label's text after creation, use the function:</para>
3420
3421 <programlisting role="C">
3422 void gtk_label_set_text( GtkLabel   *label,
3423                          const char *str );
3424 </programlisting>
3425
3426 <para>The first argument is the label you created previously (cast
3427 using the <literal>GTK_LABEL()</literal> macro), and the second is the new string.</para>
3428
3429 <para>The space needed for the new string will be automatically adjusted if
3430 needed. You can produce multi-line labels by putting line breaks in
3431 the label string.</para>
3432
3433 <para>To retrieve the current string, use:</para>
3434
3435 <programlisting role="C">
3436 const gchar* gtk_label_get_text( GtkLabel  *label );                    
3437 </programlisting>
3438
3439 <para>Do not free the returned string, as it is used internally by GTK.</para>
3440
3441 <para>The label text can be justified using:</para>
3442
3443 <programlisting role="C">
3444 void gtk_label_set_justify( GtkLabel         *label,
3445                             GtkJustification  jtype );
3446 </programlisting>
3447
3448 <para>Values for <literal>jtype</literal> are:</para>
3449 <programlisting role="C">
3450   GTK_JUSTIFY_LEFT
3451   GTK_JUSTIFY_RIGHT
3452   GTK_JUSTIFY_CENTER (the default)
3453   GTK_JUSTIFY_FILL
3454 </programlisting>
3455
3456 <para>The label widget is also capable of line wrapping the text
3457 automatically. This can be activated using:</para>
3458
3459 <programlisting role="C">
3460 void gtk_label_set_line_wrap (GtkLabel *label,
3461                               gboolean  wrap);
3462 </programlisting>
3463
3464 <para>The <literal>wrap</literal> argument takes a TRUE or FALSE value.</para>
3465
3466 <para>If you want your label underlined, then you can set a pattern on the
3467 label:</para>
3468
3469 <programlisting role="C">
3470 void       gtk_label_set_pattern   (GtkLabel          *label,
3471                                     const gchar       *pattern);
3472 </programlisting>
3473
3474 <para>The pattern argument indicates how the underlining should look. It
3475 consists of a string of underscore and space characters. An underscore
3476 indicates that the corresponding character in the label should be
3477 underlined. For example, the string <literal>"__     __"</literal> would underline the
3478 first two characters and eight and ninth characters.</para>
3479
3480 <note><para>If you simply want to have an underlined accelerator ("mnemonic") 
3481 in your label, you should use gtk_label_new_with_mnemonic() or 
3482 gtk_label_set_text_with_mnemonic(), not gtk_label_set_pattern().</para>
3483 </note>
3484
3485 <para>Below is a short example to illustrate these functions. This example
3486 makes use of the Frame widget to better demonstrate the label
3487 styles. You can ignore this for now as the <link linkend="sec-Frames">Frame</link> 
3488 widget is explained later on.</para>
3489
3490 <para>In GTK+ 2.0, label texts can contain markup for font and other text attribute 
3491 changes, and labels may be selectable (for copy-and-paste). These advanced features
3492 won't be explained here.</para>
3493
3494 <para>
3495 <inlinemediaobject>
3496 <imageobject>
3497 <imagedata fileref="images/label.png" format="png">
3498 </imageobject>
3499 </inlinemediaobject>
3500 </para>
3501
3502 <programlisting role="C">
3503 <!-- example-start label label.c -->
3504
3505 #include &lt;gtk/gtk.h&gt;
3506
3507 int main( int   argc,
3508           char *argv[] )
3509 {
3510   static GtkWidget *window = NULL;
3511   GtkWidget *hbox;
3512   GtkWidget *vbox;
3513   GtkWidget *frame;
3514   GtkWidget *label;
3515
3516   /* Initialise GTK */
3517   gtk_init (&amp;argc, &amp;argv);
3518
3519   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3520   g_signal_connect (G_OBJECT (window), "destroy",
3521                     G_CALLBACK (gtk_main_quit),
3522                     NULL);
3523
3524   gtk_window_set_title (GTK_WINDOW (window), "Label");
3525   vbox = gtk_vbox_new (FALSE, 5);
3526   hbox = gtk_hbox_new (FALSE, 5);
3527   gtk_container_add (GTK_CONTAINER (window), hbox);
3528   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3529   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3530   
3531   frame = gtk_frame_new ("Normal Label");
3532   label = gtk_label_new ("This is a Normal label");
3533   gtk_container_add (GTK_CONTAINER (frame), label);
3534   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3535   
3536   frame = gtk_frame_new ("Multi-line Label");
3537   label = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \
3538                          "Third line");
3539   gtk_container_add (GTK_CONTAINER (frame), label);
3540   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3541   
3542   frame = gtk_frame_new ("Left Justified Label");
3543   label = gtk_label_new ("This is a Left-Justified\n" \
3544                          "Multi-line label.\nThird      line");
3545   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3546   gtk_container_add (GTK_CONTAINER (frame), label);
3547   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3548   
3549   frame = gtk_frame_new ("Right Justified Label");
3550   label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \
3551                          "Fourth line, (j/k)");
3552   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3553   gtk_container_add (GTK_CONTAINER (frame), label);
3554   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3555
3556   vbox = gtk_vbox_new (FALSE, 5);
3557   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3558   frame = gtk_frame_new ("Line wrapped label");
3559   label = gtk_label_new ("This is an example of a line-wrapped label.  It " \
3560                          "should not be taking up the entire             " /* big space to test spacing */\
3561                          "width allocated to it, but automatically " \
3562                          "wraps the words to fit.  " \
3563                          "The time has come, for all good men, to come to " \
3564                          "the aid of their party.  " \
3565                          "The sixth sheik's six sheep's sick.\n" \
3566                          "     It supports multiple paragraphs correctly, " \
3567                          "and  correctly   adds "\
3568                          "many          extra  spaces. ");
3569   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3570   gtk_container_add (GTK_CONTAINER (frame), label);
3571   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3572   
3573   frame = gtk_frame_new ("Filled, wrapped label");
3574   label = gtk_label_new ("This is an example of a line-wrapped, filled label.  " \
3575                          "It should be taking "\
3576                          "up the entire              width allocated to it.  " \
3577                          "Here is a sentence to prove "\
3578                          "my point.  Here is another sentence. "\
3579                          "Here comes the sun, do de do de do.\n"\
3580                          "    This is a new paragraph.\n"\
3581                          "    This is another newer, longer, better " \
3582                          "paragraph.  It is coming to an end, "\
3583                          "unfortunately.");
3584   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3585   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3586   gtk_container_add (GTK_CONTAINER (frame), label);
3587   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3588   
3589   frame = gtk_frame_new ("Underlined label");
3590   label = gtk_label_new ("This label is underlined!\n"
3591                          "This one is underlined in quite a funky fashion");
3592   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3593   gtk_label_set_pattern (GTK_LABEL (label),
3594                          "_________________________ _ _________ _ ______     __ _______ ___");
3595   gtk_container_add (GTK_CONTAINER (frame), label);
3596   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3597   
3598   gtk_widget_show_all (window);
3599
3600   gtk_main ();
3601   
3602   return 0;
3603 }
3604 <!-- example-end -->
3605 </programlisting>
3606
3607 </sect1>
3608
3609 <!-- ----------------------------------------------------------------- -->
3610 <sect1 id="sec-Arrows">
3611 <title>Arrows</title>
3612
3613 <para>The Arrow widget draws an arrowhead, facing in a number of possible
3614 directions and having a number of possible styles. It can be very
3615 useful when placed on a button in many applications. Like the Label
3616 widget, it emits no signals.</para>
3617
3618 <para>There are only two functions for manipulating an Arrow widget:</para>
3619
3620 <programlisting role="C">
3621 GtkWidget *gtk_arrow_new( GtkArrowType   arrow_type,
3622                           GtkShadowType  shadow_type );
3623
3624 void gtk_arrow_set( GtkArrow      *arrow,
3625                     GtkArrowType   arrow_type,
3626                     GtkShadowType  shadow_type );
3627 </programlisting>
3628
3629 <para>The first creates a new arrow widget with the indicated type and
3630 appearance. The second allows these values to be altered
3631 retrospectively. The <literal>arrow_type</literal> argument may take one of the
3632 following values:</para>
3633
3634 <programlisting role="C">
3635   GTK_ARROW_UP
3636   GTK_ARROW_DOWN
3637   GTK_ARROW_LEFT
3638   GTK_ARROW_RIGHT
3639 </programlisting>
3640
3641 <para>These values obviously indicate the direction in which the arrow will
3642 point. The <literal>shadow_type</literal> argument may take one of these values:</para>
3643
3644 <programlisting role="C">
3645   GTK_SHADOW_IN
3646   GTK_SHADOW_OUT (the default)
3647   GTK_SHADOW_ETCHED_IN
3648   GTK_SHADOW_ETCHED_OUT
3649 </programlisting>
3650
3651 <para>Here's a brief example to illustrate their use.</para>
3652
3653 <para>
3654 <inlinemediaobject>
3655 <imageobject>
3656 <imagedata fileref="images/arrow.png" format="png">
3657 </imageobject>
3658 </inlinemediaobject>
3659 </para>
3660
3661 <programlisting role="C">
3662 <!-- example-start arrow arrow.c -->
3663
3664 #include &lt;gtk/gtk.h&gt;
3665
3666 /* Create an Arrow widget with the specified parameters
3667  * and pack it into a button */
3668 static GtkWidget *create_arrow_button( GtkArrowType  arrow_type,
3669                                        GtkShadowType shadow_type )
3670 {
3671   GtkWidget *button;
3672   GtkWidget *arrow;
3673
3674   button = gtk_button_new ();
3675   arrow = gtk_arrow_new (arrow_type, shadow_type);
3676
3677   gtk_container_add (GTK_CONTAINER (button), arrow);
3678   
3679   gtk_widget_show (button);
3680   gtk_widget_show (arrow);
3681
3682   return button;
3683 }
3684
3685 int main( int   argc,
3686           char *argv[] )
3687 {
3688   /* GtkWidget is the storage type for widgets */
3689   GtkWidget *window;
3690   GtkWidget *button;
3691   GtkWidget *box;
3692
3693   /* Initialize the toolkit */
3694   gtk_init (&amp;argc, &amp;argv);
3695
3696   /* Create a new window */
3697   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3698
3699   gtk_window_set_title (GTK_WINDOW (window), "Arrow Buttons");
3700
3701   /* It's a good idea to do this for all windows. */
3702   g_signal_connect (G_OBJECT (window), "destroy",
3703                     G_CALLBACK (gtk_main_quit), NULL);
3704
3705   /* Sets the border width of the window. */
3706   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
3707
3708   /* Create a box to hold the arrows/buttons */
3709   box = gtk_hbox_new (FALSE, 0);
3710   gtk_container_set_border_width (GTK_CONTAINER (box), 2);
3711   gtk_container_add (GTK_CONTAINER (window), box);
3712
3713   /* Pack and show all our widgets */
3714   gtk_widget_show (box);
3715
3716   button = create_arrow_button (GTK_ARROW_UP, GTK_SHADOW_IN);
3717   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3718
3719   button = create_arrow_button (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
3720   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3721   
3722   button = create_arrow_button (GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN);
3723   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3724   
3725   button = create_arrow_button (GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT);
3726   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3727   
3728   gtk_widget_show (window);
3729   
3730   /* Rest in gtk_main and wait for the fun to begin! */
3731   gtk_main ();
3732   
3733   return 0;
3734 }
3735 <!-- example-end -->
3736 </programlisting>
3737
3738 </sect1>
3739
3740 <!-- ----------------------------------------------------------------- -->
3741 <sect1 id="sec-TheTooltipsObject">
3742 <title>The Tooltips Object</title>
3743
3744 <para>These are the little text strings that pop up when you leave your
3745 pointer over a button or other widget for a few seconds. They are easy
3746 to use, so I will just explain them without giving an example. If you
3747 want to see some code, take a look at the <filename>testgtk.c</filename> program
3748 distributed with GTK.</para>
3749
3750 <para>Widgets that do not receive events (widgets that do not have their
3751 own window) will not work with tooltips.</para>
3752
3753 <para>The first call you will use creates a new tooltip. You only need to do
3754 this once for a set of tooltips as the <literal>GtkTooltips</literal> object this
3755 function returns can be used to create multiple tooltips.</para>
3756
3757 <programlisting role="C">
3758 GtkTooltips *gtk_tooltips_new( void );
3759 </programlisting>
3760
3761 <para>Once you have created a new tooltip, and the widget you wish to use it
3762 on, simply use this call to set it:</para>
3763
3764 <programlisting role="C">
3765 void gtk_tooltips_set_tip( GtkTooltips *tooltips,
3766                            GtkWidget   *widget,
3767                            const gchar *tip_text,
3768                            const gchar *tip_private );
3769 </programlisting>
3770
3771 <para>The first argument is the tooltip you've already created, followed by
3772 the widget you wish to have this tooltip pop up for, and the text you
3773 wish it to say. The last argument is a text string that can be used as
3774 an identifier when using GtkTipsQuery to implement context sensitive
3775 help. For now, you can set it to NULL.</para>
3776
3777 <!-- TODO: sort out what how to do the context sensitive help -->
3778
3779 <para>Here's a short example:</para>
3780
3781 <programlisting role="C">
3782 GtkTooltips *tooltips;
3783 GtkWidget *button;
3784 .
3785 .
3786 .
3787 tooltips = gtk_tooltips_new ();
3788 button = gtk_button_new_with_label ("button 1");
3789 .
3790 .
3791 .
3792 gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);
3793 </programlisting>
3794
3795 <para>There are other calls that can be used with tooltips. I will just list
3796 them with a brief description of what they do.</para>
3797
3798 <programlisting role="C">
3799 void gtk_tooltips_enable( GtkTooltips *tooltips );
3800 </programlisting>
3801
3802 <para>Enable a disabled set of tooltips.</para>
3803
3804 <programlisting role="C">
3805 void gtk_tooltips_disable( GtkTooltips *tooltips );
3806 </programlisting>
3807
3808 <para>Disable an enabled set of tooltips.</para>
3809
3810 <para>And that's all the functions associated with tooltips. More than
3811 you'll ever want to know :-)</para>
3812
3813 </sect1>
3814
3815 <!-- ----------------------------------------------------------------- -->
3816 <sect1 id="sec-ProgressBars">
3817 <title>Progress Bars</title>
3818
3819 <para>Progress bars are used to show the status of an operation. They are
3820 pretty easy to use, as you will see with the code below. But first
3821 lets start out with the calls to create a new progress bar.</para>
3822
3823 <programlisting role="C">
3824 GtkWidget *gtk_progress_bar_new( void );
3825 </programlisting>
3826
3827 <para>Now that the progress bar has been created we can use it.</para>
3828
3829 <programlisting role="C">
3830 void gtk_progress_bar_set_fraction ( GtkProgressBar *pbar,
3831                                      gdouble        fraction );
3832 </programlisting>
3833
3834 <para>The first argument is the progress bar you wish to operate on, and the
3835 second argument is the amount "completed", meaning the amount the
3836 progress bar has been filled from 0-100%. This is passed to the
3837 function as a real number ranging from 0 to 1.</para>
3838
3839 <para>GTK v1.2 has added new functionality to the progress bar that enables
3840 it to display its value in different ways, and to inform the user of
3841 its current value and its range.</para>
3842
3843 <para>A progress bar may be set to one of a number of orientations using the
3844 function</para>
3845
3846 <programlisting role="C">
3847 void gtk_progress_bar_set_orientation( GtkProgressBar *pbar,
3848                                        GtkProgressBarOrientation orientation );
3849 </programlisting>
3850
3851 <para>The <literal>orientation</literal> argument may take one of the following
3852 values to indicate the direction in which the progress bar moves:</para>
3853
3854 <programlisting role="C">
3855   GTK_PROGRESS_LEFT_TO_RIGHT
3856   GTK_PROGRESS_RIGHT_TO_LEFT
3857   GTK_PROGRESS_BOTTOM_TO_TOP
3858   GTK_PROGRESS_TOP_TO_BOTTOM
3859 </programlisting>
3860
3861 <para>As well as indicating the amount of progress that has occured, the
3862 progress bar may be set to just indicate that there is some activity. 
3863 This can be useful in situations where progress cannot be measured against 
3864 a value range. The following function indicates that some progress has been 
3865 made.</para>
3866
3867 <programlisting role="C">
3868 void gtk_progress_bar_pulse ( GtkProgressBar *progress );
3869 </programlisting>
3870
3871 <para>The step size of the activity indicator is set using the following 
3872 function.</para>
3873
3874 <programlisting role="C">
3875 void gtk_progress_bar_set_pulse_step( GtkProgressBar *pbar,
3876                                       gdouble         fraction );
3877 </programlisting>
3878
3879 <para>When not in activity mode, the progress bar can also display a
3880 configurable text string within its trough, using the following
3881 function.</para>
3882
3883 <programlisting role="C">
3884 void gtk_progress_bar_set_text( GtkProgressBar *progress,
3885                                 const gchar    *text );
3886 </programlisting>
3887
3888 <note><para>Note that gtk_progress_set_text() doesn't support the printf()-like formatting
3889 of the GTK+ 1.2 Progressbar.</para></note>
3890
3891 <para>You can turn off the display of the string by calling gtk_progess_bar_set_text()
3892 again with NULL as second argument.</para>
3893
3894 <para>The current text setting of a progressbar can be retrieved with the 
3895 following function. Do not free the returned string.</para>
3896
3897 <programlisting role="C">
3898 const gchar *gtk_progress_bar_get_text( GtkProgressBar *pbar );
3899 </programlisting>
3900
3901 <para>Progress Bars are usually used with timeouts or other such functions
3902 (see section on <link linkend="ch-Timeouts">Timeouts, I/O and Idle Functions</link>) 
3903 to give the illusion of multitasking. All will employ the
3904 gtk_progress_bar_set_fraction() or gtk_progress_bar_pulse() functions in the 
3905 same manner.</para>
3906
3907 <para>Here is an example of the progress bar, updated using timeouts. This
3908 code also shows you how to reset the Progress Bar.</para>
3909
3910 <para>
3911 <inlinemediaobject>
3912 <imageobject>
3913 <imagedata fileref="images/progressbar.png" format="png">
3914 </imageobject>
3915 </inlinemediaobject>
3916 </para>
3917
3918 <programlisting role="C">
3919 <!-- example-start progressbar progressbar.c -->
3920
3921 #include &lt;gtk/gtk.h&gt;
3922
3923 typedef struct _ProgressData {
3924   GtkWidget *window;
3925   GtkWidget *pbar;
3926   int timer;
3927   gboolean activity_mode;
3928 } ProgressData;
3929
3930 /* Update the value of the progress bar so that we get
3931  * some movement */
3932 static gboolean progress_timeout( gpointer data )
3933 {
3934   ProgressData *pdata = (ProgressData *)data;
3935   gdouble new_val;
3936   
3937   if (pdata-&gt;activity_mode) 
3938     gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata-&gt;pbar));
3939   else 
3940     {
3941       /* Calculate the value of the progress bar using the
3942        * value range set in the adjustment object */
3943       
3944       new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata-&gt;pbar)) + 0.01;
3945       
3946       if (new_val &gt; 1.0)
3947         new_val = 0.0;
3948       
3949       /* Set the new value */
3950       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata-&gt;pbar), new_val);
3951     }
3952   
3953   /* As this is a timeout function, return TRUE so that it
3954    * continues to get called */
3955   return TRUE;
3956
3957
3958 /* Callback that toggles the text display within the progress bar trough */
3959 static void toggle_show_text( GtkWidget    *widget,
3960                               ProgressData *pdata )
3961 {
3962   const gchar *text;
3963   
3964   text = gtk_progress_bar_get_text (GTK_PROGRESS_BAR (pdata-&gt;pbar));
3965   if (text &amp;&amp; *text)
3966     gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata-&gt;pbar), "");
3967   else 
3968     gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata-&gt;pbar), "some text");
3969 }
3970
3971 /* Callback that toggles the activity mode of the progress bar */
3972 static void toggle_activity_mode( GtkWidget    *widget,
3973                                   ProgressData *pdata )
3974 {
3975   pdata-&gt;activity_mode = !pdata-&gt;activity_mode;
3976   if (pdata-&gt;activity_mode) 
3977       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata-&gt;pbar));
3978   else
3979       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata-&gt;pbar), 0.0);
3980 }
3981
3982  
3983 /* Callback that toggles the orientation of the progress bar */
3984 static void toggle_orientation( GtkWidget    *widget,
3985                                 ProgressData *pdata )
3986 {
3987   switch (gtk_progress_bar_get_orientation (GTK_PROGRESS_BAR (pdata-&gt;pbar))) {
3988   case GTK_PROGRESS_LEFT_TO_RIGHT:
3989     gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata-&gt;pbar), 
3990                                       GTK_PROGRESS_RIGHT_TO_LEFT);
3991     break;
3992   case GTK_PROGRESS_RIGHT_TO_LEFT:
3993     gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata-&gt;pbar), 
3994                                       GTK_PROGRESS_LEFT_TO_RIGHT);
3995     break;
3996   default:
3997     // do nothing       
3998   }
3999 }
4000
4001  
4002 /* Clean up allocated memory and remove the timer */
4003 static void destroy_progress( GtkWidget    *widget,
4004                               ProgressData *pdata)
4005 {
4006     gtk_timeout_remove (pdata-&gt;timer);
4007     pdata-&gt;timer = 0;
4008     pdata-&gt;window = NULL;
4009     g_free (pdata);
4010     gtk_main_quit ();
4011 }
4012
4013 int main( int   argc,
4014           char *argv[])
4015 {
4016     ProgressData *pdata;
4017     GtkWidget *align;
4018     GtkWidget *separator;
4019     GtkWidget *table;
4020     GtkWidget *button;
4021     GtkWidget *check;
4022     GtkWidget *vbox;
4023
4024     gtk_init (&amp;argc, &amp;argv);
4025
4026     /* Allocate memory for the data that is passed to the callbacks */
4027     pdata = g_malloc (sizeof (ProgressData));
4028   
4029     pdata-&gt;window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4030     gtk_window_set_resizable (GTK_WINDOW (pdata-&gt;window), TRUE);
4031
4032     g_signal_connect (G_OBJECT (pdata-&gt;window), "destroy",
4033                       G_CALLBACK (destroy_progress),
4034                       (gpointer) pdata);
4035     gtk_window_set_title (GTK_WINDOW (pdata-&gt;window), "GtkProgressBar");
4036     gtk_container_set_border_width (GTK_CONTAINER (pdata-&gt;window), 0);
4037
4038     vbox = gtk_vbox_new (FALSE, 5);
4039     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
4040     gtk_container_add (GTK_CONTAINER (pdata-&gt;window), vbox);
4041     gtk_widget_show (vbox);
4042   
4043     /* Create a centering alignment object */
4044     align = gtk_alignment_new (0.5, 0.5, 0, 0);
4045     gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
4046     gtk_widget_show (align);
4047
4048     /* Create the GtkProgressBar */
4049     pdata-&gt;pbar = gtk_progress_bar_new ();
4050
4051     gtk_container_add (GTK_CONTAINER (align), pdata-&gt;pbar);
4052     gtk_widget_show (pdata-&gt;pbar);
4053
4054     /* Add a timer callback to update the value of the progress bar */
4055     pdata-&gt;timer = gtk_timeout_add (100, progress_timeout, pdata);
4056
4057     separator = gtk_hseparator_new ();
4058     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
4059     gtk_widget_show (separator);
4060
4061     /* rows, columns, homogeneous */
4062     table = gtk_table_new (2, 3, FALSE);
4063     gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
4064     gtk_widget_show (table);
4065
4066     /* Add a check button to select displaying of the trough text */
4067     check = gtk_check_button_new_with_label ("Show text");
4068     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
4069                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
4070                       5, 5);
4071     g_signal_connect (G_OBJECT (check), "clicked",
4072                       G_CALLBACK (toggle_show_text),
4073                       (gpointer) pdata);
4074     gtk_widget_show (check);
4075
4076     /* Add a check button to toggle activity mode */
4077     check = gtk_check_button_new_with_label ("Activity mode");
4078     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
4079                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
4080                       5, 5);
4081     g_signal_connect (G_OBJECT (check), "clicked",
4082                       G_CALLBACK (toggle_activity_mode),
4083                       (gpointer) pdata);
4084     gtk_widget_show (check);
4085
4086     /* Add a check button to toggle orientation */
4087     check = gtk_check_button_new_with_label ("Right to Left");
4088     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 2, 3,
4089                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
4090                       5, 5);
4091     g_signal_connect (G_OBJECT (check), "clicked",
4092                       G_CALLBACK (toggle_orientation),
4093                       (gpointer) pdata);
4094     gtk_widget_show (check);
4095
4096     /* Add a button to exit the program */
4097     button = gtk_button_new_with_label ("close");
4098     g_signal_connect_swapped (G_OBJECT (button), "clicked",
4099                               G_CALLBACK (gtk_widget_destroy),
4100                               G_OBJECT (pdata-&gt;window));
4101     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
4102
4103     /* This makes it so the button is the default. */
4104     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4105
4106     /* This grabs this button to be the default button. Simply hitting
4107      * the "Enter" key will cause this button to activate. */
4108     gtk_widget_grab_default (button);
4109     gtk_widget_show (button);
4110
4111     gtk_widget_show (pdata-&gt;window);
4112
4113     gtk_main ();
4114     
4115     return 0;
4116 }
4117 <!-- example-end -->
4118 </programlisting>
4119
4120 </sect1>
4121
4122 <!-- ----------------------------------------------------------------- -->
4123 <sect1 id="sec-Dialogs">
4124 <title>Dialogs</title>
4125
4126 <para>The Dialog widget is very simple, and is actually just a window with a
4127 few things pre-packed into it for you. The structure for a Dialog is:</para>
4128
4129 <programlisting role="C">
4130 struct GtkDialog
4131 {
4132       GtkWindow window;
4133     
4134       GtkWidget *vbox;
4135       GtkWidget *action_area;
4136 };
4137 </programlisting>
4138
4139 <para>So you see, it simply creates a window, and then packs a vbox into the
4140 top, which contains a separator and then an hbox called the
4141 "action_area".</para>
4142
4143 <para>The Dialog widget can be used for pop-up messages to the user, and
4144 other similar tasks. There are two functions to create a new Dialog.</para>
4145
4146 <programlisting role="C">
4147 GtkWidget *gtk_dialog_new( void );
4148
4149 GtkWidget *gtk_dialog_new_with_buttons( const gchar    *title,
4150                                         GtkWindow      *parent,
4151                                         GtkDialogFlags  flags, 
4152                                         const gchar    *first_button_text,
4153                                         ... );
4154 </programlisting>
4155
4156 <para>The first function will create an empty dialog, and it is now up to you to use
4157  it. You could pack a button in the action_area by doing something like this:</para>
4158
4159 <programlisting role="C">
4160     button = ...
4161     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
4162                         button, TRUE, TRUE, 0);
4163     gtk_widget_show (button);
4164 </programlisting>
4165
4166 <para>And you could add to the vbox area by packing, for instance, a label 
4167 in it, try something like this:</para>
4168
4169 <programlisting role="C">
4170     label = gtk_label_new ("Dialogs are groovy");
4171     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
4172                         label, TRUE, TRUE, 0);
4173     gtk_widget_show (label);
4174 </programlisting>
4175
4176 <para>As an example in using the dialog box, you could put two buttons in
4177 the action_area, a Cancel button and an Ok button, and a label in the
4178 vbox area, asking the user a question or giving an error etc. Then
4179 you could attach a different signal to each of the buttons and perform
4180 the operation the user selects.</para>
4181
4182 <para>If the simple functionality provided by the default vertical and
4183 horizontal boxes in the two areas doesn't give you enough control for
4184 your application, then you can simply pack another layout widget into
4185 the boxes provided. For example, you could pack a table into the
4186 vertical box.</para>
4187
4188 <para>The more complicated _new_with_buttons() variant allows to set one or
4189 more of the following flags.</para>
4190
4191 <variablelist>
4192 <varlistentry>
4193 <term><literal>GTK_DIALOG_MODAL</literal></term>
4194 <listitem><para>make the dialog modal.
4195 </para></listitem>
4196 </varlistentry>
4197 <varlistentry>
4198 <term><literal>GTK_DIALOG_DESTROY_WITH_PARENT</literal></term>
4199 <listitem><para>ensures that the dialog window is destroyed together with the specified
4200 parent.</para></listitem>
4201 </varlistentry>
4202 <varlistentry>
4203 <term><literal>GTK_DIALOG_NO_SEPARATOR</literal></term>
4204 <listitem><para>omits the separator between the vbox and the action_area.
4205 </para></listitem>
4206 </varlistentry>
4207 </variablelist>
4208 </sect1>
4209
4210 <!-- ----------------------------------------------------------------- -->
4211 <sect1 id="sec-Rulers">
4212 <title>Rulers</title>
4213
4214 <para>Ruler widgets are used to indicate the location of the mouse pointer
4215 in a given window. A window can have a vertical ruler spanning across
4216 the width and a horizontal ruler spanning down the height. A small
4217 triangular indicator on the ruler shows the exact location of the
4218 pointer relative to the ruler.</para>
4219
4220 <para>A ruler must first be created. Horizontal and vertical rulers are
4221 created using</para>
4222
4223 <programlisting role="C">
4224 GtkWidget *gtk_hruler_new( void );    /* horizontal ruler */
4225
4226 GtkWidget *gtk_vruler_new( void );    /* vertical ruler   */
4227 </programlisting>
4228
4229 <para>Once a ruler is created, we can define the unit of measurement. Units
4230 of measure for rulers can be<literal>GTK_PIXELS</literal>, <literal>GTK_INCHES</literal> or
4231 <literal>GTK_CENTIMETERS</literal>. This is set using</para>
4232
4233 <programlisting role="C">
4234 void gtk_ruler_set_metric( GtkRuler      *ruler,
4235                            GtkMetricType  metric );
4236 </programlisting>
4237
4238 <para>The default measure is <literal>GTK_PIXELS</literal>.</para>
4239
4240 <programlisting role="C">
4241     gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
4242 </programlisting>
4243
4244 <para>Other important characteristics of a ruler are how to mark the units
4245 of scale and where the position indicator is initially placed. These
4246 are set for a ruler using</para>
4247
4248 <programlisting role="C">
4249 void gtk_ruler_set_range( GtkRuler *ruler,
4250                           gdouble   lower,
4251                           gdouble   upper,
4252                           gdouble   position,
4253                           gdouble   max_size );
4254 </programlisting>
4255
4256 <para>The lower and upper arguments define the extent of the ruler, and
4257 max_size is the largest possible number that will be displayed.
4258 Position defines the initial position of the pointer indicator within
4259 the ruler.</para>
4260
4261 <para>A vertical ruler can span an 800 pixel wide window thus</para>
4262
4263 <programlisting role="C">
4264     gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
4265 </programlisting>
4266
4267 <para>The markings displayed on the ruler will be from 0 to 800, with a
4268 number for every 100 pixels. If instead we wanted the ruler to range
4269 from 7 to 16, we would code</para>
4270
4271 <programlisting role="C">
4272     gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
4273 </programlisting>
4274
4275 <para>The indicator on the ruler is a small triangular mark that indicates
4276 the position of the pointer relative to the ruler. If the ruler is
4277 used to follow the mouse pointer, the motion_notify_event signal
4278 should be connected to the motion_notify_event method of the ruler.
4279 To follow all mouse movements within a window area, we would use</para>
4280
4281 <programlisting role="C">
4282 #define EVENT_METHOD(i, x) GTK_WIDGET_GET_CLASS(i)->x
4283
4284     g_signal_connect_swapped (G_OBJECT (area), "motion_notify_event",
4285            G_CALLBACK (EVENT_METHOD (ruler, motion_notify_event)),
4286            G_OBJECT (ruler));
4287 </programlisting>
4288
4289 <para>The following example creates a drawing area with a horizontal ruler
4290 above it and a vertical ruler to the left of it. The size of the
4291 drawing area is 600 pixels wide by 400 pixels high. The horizontal
4292 ruler spans from 7 to 13 with a mark every 100 pixels, while the
4293 vertical ruler spans from 0 to 400 with a mark every 100 pixels.
4294 Placement of the drawing area and the rulers is done using a table.</para>
4295
4296 <para>
4297 <inlinemediaobject>
4298 <imageobject>
4299 <imagedata fileref="images/rulers.png" format="png">
4300 </imageobject>
4301 </inlinemediaobject>
4302 </para>
4303
4304 <programlisting role="C">
4305 <!-- example-start rulers rulers.c -->
4306
4307 #include &lt;gtk/gtk.h&gt;
4308
4309 #define EVENT_METHOD(i, x) GTK_WIDGET_GET_CLASS(i)-&gt;x
4310
4311 #define XSIZE  600
4312 #define YSIZE  400
4313
4314 /* This routine gets control when the close button is clicked */
4315 static gboolean close_application( GtkWidget *widget,
4316                                    GdkEvent  *event,
4317                                    gpointer   data )
4318 {
4319     gtk_main_quit ();
4320     return FALSE;
4321 }
4322
4323 /* The main routine */
4324 int main( int   argc,
4325           char *argv[] ) {
4326     GtkWidget *window, *table, *area, *hrule, *vrule;
4327
4328     /* Initialize GTK and create the main window */
4329     gtk_init (&amp;argc, &amp;argv);
4330
4331     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4332     g_signal_connect (G_OBJECT (window), "delete_event",
4333                       G_CALLBACK (close_application), NULL);
4334     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
4335
4336     /* Create a table for placing the ruler and the drawing area */
4337     table = gtk_table_new (3, 2, FALSE);
4338     gtk_container_add (GTK_CONTAINER (window), table);
4339
4340     area = gtk_drawing_area_new ();
4341     gtk_widget_set_size_request (GTK_WIDGET (area), XSIZE, YSIZE);
4342     gtk_table_attach (GTK_TABLE (table), area, 1, 2, 1, 2,
4343                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0);
4344     gtk_widget_set_events (area, GDK_POINTER_MOTION_MASK |
4345                                  GDK_POINTER_MOTION_HINT_MASK);
4346
4347     /* The horizontal ruler goes on top. As the mouse moves across the
4348      * drawing area, a motion_notify_event is passed to the
4349      * appropriate event handler for the ruler. */
4350     hrule = gtk_hruler_new ();
4351     gtk_ruler_set_metric (GTK_RULER (hrule), GTK_PIXELS);
4352     gtk_ruler_set_range (GTK_RULER (hrule), 7, 13, 0, 20);
4353     g_signal_connect_swapped (G_OBJECT (area), "motion_notify_event",
4354                               G_CALLBACK (EVENT_METHOD (hrule, motion_notify_event)),
4355                               G_OBJECT (hrule));
4356     gtk_table_attach (GTK_TABLE (table), hrule, 1, 2, 0, 1,
4357                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0);
4358     
4359     /* The vertical ruler goes on the left. As the mouse moves across
4360      * the drawing area, a motion_notify_event is passed to the
4361      * appropriate event handler for the ruler. */
4362     vrule = gtk_vruler_new ();
4363     gtk_ruler_set_metric (GTK_RULER (vrule), GTK_PIXELS);
4364     gtk_ruler_set_range (GTK_RULER (vrule), 0, YSIZE, 10, YSIZE );
4365     g_signal_connect_swapped (G_OBJECT (area), "motion_notify_event",
4366                               G_CALLBACK (EVENT_METHOD (vrule, motion_notify_event)),
4367                               G_OBJECT (vrule));
4368     gtk_table_attach (GTK_TABLE (table), vrule, 0, 1, 1, 2,
4369                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0);
4370
4371     /* Now show everything */
4372     gtk_widget_show (area);
4373     gtk_widget_show (hrule);
4374     gtk_widget_show (vrule);
4375     gtk_widget_show (table);
4376     gtk_widget_show (window);
4377     gtk_main ();
4378
4379     return 0;
4380 }
4381 <!-- example-end -->
4382 </programlisting>
4383
4384 </sect1>
4385
4386 <!-- ----------------------------------------------------------------- -->
4387 <sect1 id="sec-Statusbars">
4388 <title>Statusbars</title>
4389
4390 <para>Statusbars are simple widgets used to display a text message. They
4391 keep a stack of the messages pushed onto them, so that popping the
4392 current message will re-display the previous text message.</para>
4393
4394 <para>In order to allow different parts of an application to use the same
4395 statusbar to display messages, the statusbar widget issues Context
4396 Identifiers which are used to identify different "users". The message
4397 on top of the stack is the one displayed, no matter what context it is
4398 in. Messages are stacked in last-in-first-out order, not context
4399 identifier order.</para>
4400
4401 <para>A statusbar is created with a call to:</para>
4402
4403 <programlisting role="C">
4404 GtkWidget *gtk_statusbar_new( void );
4405 </programlisting>
4406
4407 <para>A new Context Identifier is requested using a call to the following 
4408 function with a short textual description of the context:</para>
4409
4410 <programlisting role="C">
4411 guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
4412                                     const gchar  *context_description );
4413 </programlisting>
4414
4415 <para>There are three functions that can operate on statusbars:</para>
4416
4417 <programlisting role="C">
4418 guint gtk_statusbar_push( GtkStatusbar *statusbar,
4419                           guint         context_id,
4420                           const gchar  *text );
4421
4422 void gtk_statusbar_pop( GtkStatusbar *statusbar)
4423                         guint         context_id );
4424
4425 void gtk_statusbar_remove( GtkStatusbar *statusbar,
4426                            guint         context_id,
4427                            guint         message_id ); 
4428 </programlisting>
4429
4430 <para>The first, gtk_statusbar_push(), is used to add a new message to the
4431 statusbar.  It returns a Message Identifier, which can be passed later
4432 to the function gtk_statusbar_remove to remove the message with the
4433 given Message and Context Identifiers from the statusbar's stack.</para>
4434
4435 <para>The function gtk_statusbar_pop() removes the message highest in the
4436 stack with the given Context Identifier.</para>
4437
4438 <para>In addition to messages, statusbars may also display a resize grip, which 
4439 can be dragged with the mouse to resize the toplevel window containing the statusbar,
4440 similar to dragging the window frame. The following functions control the display
4441 of the resize grip.</para>
4442
4443 <programlisting role="C">
4444 void     gtk_statusbar_set_has_resize_grip( GtkStatusbar *statusbar,
4445                                             gboolean      setting );
4446
4447 gboolean gtk_statusbar_get_has_resize_grip( GtkStatusbar *statusbar );
4448 </programlisting>
4449
4450 <para>The following example creates a statusbar and two buttons, one for
4451 pushing items onto the statusbar, and one for popping the last item
4452 back off.</para>
4453
4454 <para>
4455 <inlinemediaobject>
4456 <imageobject>
4457 <imagedata fileref="images/statusbar.png" format="png">
4458 </imageobject>
4459 </inlinemediaobject>
4460 </para>
4461
4462 <programlisting role="C">
4463 <!-- example-start statusbar statusbar.c -->
4464
4465 #include &lt;stdlib.h&gt;
4466 #include &lt;gtk/gtk.h&gt;
4467 #include &lt;glib.h&gt;
4468
4469 GtkWidget *status_bar;
4470
4471 static void push_item( GtkWidget *widget,
4472                        gpointer   data )
4473 {
4474   static int count = 1;
4475   gchar *buff;
4476
4477   buff = g_strdup_printf ("Item %d", count++);
4478   gtk_statusbar_push (GTK_STATUSBAR (status_bar), GPOINTER_TO_INT (data), buff);
4479   g_free (buff);
4480 }
4481
4482 static void pop_item( GtkWidget *widget,
4483                       gpointer   data )
4484 {
4485   gtk_statusbar_pop (GTK_STATUSBAR (status_bar), GPOINTER_TO_INT (data));
4486 }
4487
4488 int main( int   argc,
4489           char *argv[] )
4490 {
4491
4492     GtkWidget *window;
4493     GtkWidget *vbox;
4494     GtkWidget *button;
4495
4496     gint context_id;
4497
4498     gtk_init (&amp;argc, &amp;argv);
4499
4500     /* create a new window */
4501     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4502     gtk_widget_set_size_request (GTK_WIDGET (window), 200, 100);
4503     gtk_window_set_title (GTK_WINDOW (window), "GTK Statusbar Example");
4504     g_signal_connect (G_OBJECT (window), "delete_event",
4505                       G_CALLBACK (exit), NULL);
4506  
4507     vbox = gtk_vbox_new (FALSE, 1);
4508     gtk_container_add (GTK_CONTAINER (window), vbox);
4509     gtk_widget_show (vbox);
4510           
4511     status_bar = gtk_statusbar_new ();      
4512     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
4513     gtk_widget_show (status_bar);
4514
4515     context_id = gtk_statusbar_get_context_id(
4516                           GTK_STATUSBAR (status_bar), "Statusbar example");
4517
4518     button = gtk_button_new_with_label ("push item");
4519     g_signal_connect (G_OBJECT (button), "clicked",
4520                       G_CALLBACK (push_item), GINT_TO_POINTER (context_id));
4521     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 2);
4522     gtk_widget_show (button);              
4523
4524     button = gtk_button_new_with_label ("pop last item");
4525     g_signal_connect (G_OBJECT (button), "clicked",
4526                       G_CALLBACK (pop_item), GINT_TO_POINTER (context_id));
4527     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 2);
4528     gtk_widget_show (button);
4529
4530     /* always display the window as the last step so it all splashes on
4531      * the screen at once. */
4532     gtk_widget_show (window);
4533
4534     gtk_main ();
4535
4536     return 0;
4537 }
4538 <!-- example-end -->
4539 </programlisting>
4540
4541 </sect1>
4542
4543 <!-- ----------------------------------------------------------------- -->
4544 <sect1 id="sec-TextEntries">
4545 <title>Text Entries</title>
4546
4547 <para>The Entry widget allows text to be typed and displayed in a single line
4548 text box. The text may be set with function calls that allow new text
4549 to replace, prepend or append the current contents of the Entry widget.</para>
4550
4551 <para>Create a new Entry widget with the following function.</para>
4552
4553 <programlisting role="C">
4554 GtkWidget *gtk_entry_new( void );
4555 </programlisting>
4556
4557 <para>The next function alters the text which is currently
4558 within the Entry widget.</para>
4559
4560 <programlisting role="C">
4561 void gtk_entry_set_text( GtkEntry    *entry,
4562                          const gchar *text );
4563 </programlisting>
4564
4565 <para>The function gtk_entry_set_text() sets the contents of the Entry widget,
4566 replacing the current contents. Note that the class Entry implements the Editable
4567 interface (yes, gobject supports Java-like interfaces) which contains some more
4568 functions for manipulating the contents.
4569  </para>
4570
4571 <para>The contents of the Entry can be retrieved by using a call to the
4572 following function. This is useful in the callback functions described below.</para>
4573
4574 <programlisting role="C">
4575 const gchar *gtk_entry_get_text( GtkEntry *entry );
4576 </programlisting>
4577
4578 <para>The value returned by this function is used internally, and must not
4579 be freed using either free() or g_free().</para>
4580
4581 <para>If we don't want the contents of the Entry to be changed by someone typing
4582 into it, we can change its editable state.</para>
4583
4584 <programlisting role="C">
4585 void gtk_editable_set_editable( GtkEditable *entry,
4586                                 gboolean     editable );
4587 </programlisting>
4588
4589 <para>The function above allows us to toggle the editable state of the
4590 Entry widget by passing in a TRUE or FALSE value for the <literal>editable</literal>
4591 argument.</para>
4592
4593 <para>If we are using the Entry where we don't want the text entered to be
4594 visible, for example when a password is being entered, we can use the
4595 following function, which also takes a boolean flag.</para>
4596
4597 <programlisting role="C">
4598 void gtk_entry_set_visibility( GtkEntry *entry,
4599                                gboolean  visible );
4600 </programlisting>
4601
4602 <para>A region of the text may be set as selected by using the following
4603 function. This would most often be used after setting some default
4604 text in an Entry, making it easy for the user to remove it.</para>
4605
4606 <programlisting role="C">
4607 void gtk_editable_select_region( GtkEditable *entry,
4608                                  gint         start,
4609                                  gint         end );
4610 </programlisting>
4611
4612 <para>If we want to catch when the user has entered text, we can connect to
4613 the <literal>activate</literal> or <literal>changed</literal> signal. Activate is raised when the
4614 user hits the enter key within the Entry widget. Changed is raised
4615 when the text changes at all, e.g., for every character entered or
4616 removed.</para>
4617
4618 <para>The following code is an example of using an Entry widget.</para>
4619
4620 <para>
4621 <inlinemediaobject>
4622 <imageobject>
4623 <imagedata fileref="images/entry.png" format="png">
4624 </imageobject>
4625 </inlinemediaobject>
4626 </para>
4627
4628 <programlisting role="C">
4629 <!-- example-start entry entry.c -->
4630
4631 #include &lt;stdio.h&gt;
4632 #include &lt;stdlib.h&gt;
4633 #include &lt;gtk/gtk.h&gt;
4634
4635 static void enter_callback( GtkWidget *widget,
4636                             GtkWidget *entry )
4637 {
4638   const gchar *entry_text;
4639   entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
4640   printf ("Entry contents: %s\n", entry_text);
4641 }
4642
4643 static void entry_toggle_editable( GtkWidget *checkbutton,
4644                                    GtkWidget *entry )
4645 {
4646   gtk_editable_set_editable (GTK_EDITABLE (entry),
4647                              GTK_TOGGLE_BUTTON (checkbutton)-&gt;active);
4648 }
4649
4650 static void entry_toggle_visibility( GtkWidget *checkbutton,
4651                                      GtkWidget *entry )
4652 {
4653   gtk_entry_set_visibility (GTK_ENTRY (entry),
4654                             GTK_TOGGLE_BUTTON (checkbutton)-&gt;active);
4655 }
4656
4657 int main( int   argc,
4658           char *argv[] )
4659 {
4660
4661     GtkWidget *window;
4662     GtkWidget *vbox, *hbox;
4663     GtkWidget *entry;
4664     GtkWidget *button;
4665     GtkWidget *check;
4666     gint tmp_pos;
4667
4668     gtk_init (&amp;argc, &amp;argv);
4669
4670     /* create a new window */
4671     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4672     gtk_widget_set_size_request (GTK_WIDGET (window), 200, 100);
4673     gtk_window_set_title (GTK_WINDOW (window), "GTK Entry");
4674     g_signal_connect (G_OBJECT (window), "destroy",
4675                       G_CALLBACK (gtk_main_quit), NULL);
4676     g_signal_connect_swapped (G_OBJECT (window), "delete_event",
4677                               G_CALLBACK (gtk_widget_destroy), 
4678                               G_OBJECT (window));
4679
4680     vbox = gtk_vbox_new (FALSE, 0);
4681     gtk_container_add (GTK_CONTAINER (window), vbox);
4682     gtk_widget_show (vbox);
4683
4684     entry = gtk_entry_new ();
4685     gtk_entry_set_max_length (GTK_ENTRY (entry), 50);
4686     g_signal_connect (G_OBJECT (entry), "activate",
4687                       G_CALLBACK (enter_callback),
4688                       (gpointer) entry);
4689     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
4690     tmp_pos = GTK_ENTRY (entry)-&gt;text_length;
4691     gtk_editable_insert_text (GTK_EDITABLE (entry), " world", -1, &amp;tmp_pos);
4692     gtk_editable_select_region (GTK_EDITABLE (entry),
4693                                 0, GTK_ENTRY (entry)-&gt;text_length);
4694     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4695     gtk_widget_show (entry);
4696
4697     hbox = gtk_hbox_new (FALSE, 0);
4698     gtk_container_add (GTK_CONTAINER (vbox), hbox);
4699     gtk_widget_show (hbox);
4700                                   
4701     check = gtk_check_button_new_with_label ("Editable");
4702     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4703     g_signal_connect (G_OBJECT (check), "toggled",
4704                       G_CALLBACK (entry_toggle_editable), (gpointer) entry);
4705     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
4706     gtk_widget_show (check);
4707     
4708     check = gtk_check_button_new_with_label ("Visible");
4709     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4710     g_signal_connect (G_OBJECT (check), "toggled",
4711                       G_CALLBACK (entry_toggle_visibility), (gpointer) entry);
4712     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
4713     gtk_widget_show (check);
4714                                    
4715     button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
4716     g_signal_connect_swapped (G_OBJECT (button), "clicked",
4717                               G_CALLBACK (gtk_widget_destroy),
4718                               G_OBJECT (window));
4719     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4720     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4721     gtk_widget_grab_default (button);
4722     gtk_widget_show (button);
4723     
4724     gtk_widget_show (window);
4725
4726     gtk_main();
4727
4728     return 0;
4729 }
4730 <!-- example-end -->
4731 </programlisting>
4732
4733 </sect1>
4734
4735 <!-- ----------------------------------------------------------------- -->
4736 <sect1 id="sec-SpinButtons">
4737 <title>Spin Buttons</title>
4738
4739 <para>The Spin Button widget is generally used to allow the user to select a
4740 value from a range of numeric values. It consists of a text
4741 entry box with up and down arrow buttons attached to the
4742 side. Selecting one of the buttons causes the value to "spin" up and
4743 down the range of possible values. The entry box may also be edited
4744 directly to enter a specific value.</para>
4745
4746 <para>The Spin Button allows the value to have zero or a number of decimal
4747 places and to be incremented/decremented in configurable steps. The
4748 action of holding down one of the buttons optionally results in an
4749 acceleration of change in the value according to how long it is
4750 depressed.</para>
4751
4752 <para>The Spin Button uses an <link linkend="ch-Adjustments">Adjustment</link>
4753 object to hold information about the range of values that the spin
4754 button can take. This makes for a powerful Spin Button widget.</para>
4755
4756 <para>Recall that an adjustment widget is created with the following
4757 function, which illustrates the information that it holds:</para>
4758
4759 <programlisting role="C">
4760 GtkObject *gtk_adjustment_new( gdouble value,
4761                                gdouble lower,
4762                                gdouble upper,
4763                                gdouble step_increment,
4764                                gdouble page_increment,
4765                                gdouble page_size );
4766 </programlisting>
4767
4768 <para>These attributes of an Adjustment are used by the Spin Button in the
4769 following way:</para>
4770
4771 <itemizedlist>
4772 <listitem><simpara> <literal>value</literal>: initial value for the Spin Button</simpara>
4773 </listitem>
4774 <listitem><simpara> <literal>lower</literal>: lower range value</simpara>
4775 </listitem>
4776 <listitem><simpara> <literal>upper</literal>: upper range value</simpara>
4777 </listitem>
4778 <listitem><simpara> <literal>step_increment</literal>: value to increment/decrement when pressing
4779 mouse button 1 on a button</simpara>
4780 </listitem>
4781 <listitem><simpara> <literal>page_increment</literal>: value to increment/decrement when pressing
4782 mouse button 2 on a button</simpara>
4783 </listitem>
4784 <listitem><simpara> <literal>page_size</literal>: unused</simpara>
4785 </listitem>
4786 </itemizedlist>
4787
4788 <para>Additionally, mouse button 3 can be used to jump directly to the
4789 <literal>upper</literal> or <literal>lower</literal> values when used to select one of the
4790 buttons. Lets look at how to create a Spin Button:</para>
4791
4792 <programlisting role="C">
4793 GtkWidget *gtk_spin_button_new( GtkAdjustment *adjustment,
4794                                 gdouble         climb_rate,
4795                                 guint          digits );
4796 </programlisting>
4797
4798 <para>The <literal>climb_rate</literal> argument take a value between 0.0 and 1.0 and
4799 indicates the amount of acceleration that the Spin Button has. The
4800 <literal>digits</literal> argument specifies the number of decimal places to which
4801 the value will be displayed.</para>
4802
4803 <para>A Spin Button can be reconfigured after creation using the following
4804 function:</para>
4805
4806 <programlisting role="C">
4807 void gtk_spin_button_configure( GtkSpinButton *spin_button,
4808                                 GtkAdjustment *adjustment,
4809                                 gdouble        climb_rate,
4810                                 guint          digits );
4811 </programlisting>
4812
4813 <para>The <literal>spin_button</literal> argument specifies the Spin Button widget that is
4814 to be reconfigured. The other arguments are as specified above.</para>
4815
4816 <para>The adjustment can be set and retrieved independantly using the
4817 following two functions:</para>
4818
4819 <programlisting role="C">
4820 void gtk_spin_button_set_adjustment( GtkSpinButton  *spin_button,
4821                                      GtkAdjustment  *adjustment );
4822
4823 GtkAdjustment *gtk_spin_button_get_adjustment( GtkSpinButton *spin_button );
4824 </programlisting>
4825
4826 <para>The number of decimal places can also be altered using:</para>
4827
4828 <programlisting role="C">
4829 void gtk_spin_button_set_digits( GtkSpinButton *spin_button,
4830                                  guint          digits) ;
4831 </programlisting>
4832
4833 <para>The value that a Spin Button is currently displaying can be changed
4834 using the following function:</para>
4835
4836 <programlisting role="C">
4837 void gtk_spin_button_set_value( GtkSpinButton *spin_button,
4838                                 gdouble        value );
4839 </programlisting>
4840
4841 <para>The current value of a Spin Button can be retrieved as either a
4842 floating point or integer value with the following functions:</para>
4843
4844 <programlisting role="C">
4845 gdouble gtk_spin_button_get_value ( GtkSpinButton *spin_button );
4846
4847 gint gtk_spin_button_get_value_as_int( GtkSpinButton *spin_button );
4848 </programlisting>
4849
4850 <para>If you want to alter the value of a Spin Button relative to its current
4851 value, then the following function can be used:</para>
4852
4853 <programlisting role="C">
4854 void gtk_spin_button_spin( GtkSpinButton *spin_button,
4855                            GtkSpinType    direction,
4856                            gdouble        increment );
4857 </programlisting>
4858
4859 <para>The <literal>direction</literal> parameter can take one of the following values:</para>
4860
4861 <programlisting role="C">
4862   GTK_SPIN_STEP_FORWARD
4863   GTK_SPIN_STEP_BACKWARD
4864   GTK_SPIN_PAGE_FORWARD
4865   GTK_SPIN_PAGE_BACKWARD
4866   GTK_SPIN_HOME
4867   GTK_SPIN_END
4868   GTK_SPIN_USER_DEFINED
4869 </programlisting>
4870
4871 <para>This function packs in quite a bit of functionality, which I will
4872 attempt to clearly explain. Many of these settings use values from the
4873 Adjustment object that is associated with a Spin Button.</para>
4874
4875 <para><literal>GTK_SPIN_STEP_FORWARD</literal> and <literal>GTK_SPIN_STEP_BACKWARD</literal> change the
4876 value of the Spin Button by the amount specified by <literal>increment</literal>,
4877 unless <literal>increment</literal> is equal to 0, in which case the value is
4878 changed by the value of <literal>step_increment</literal> in theAdjustment.</para>
4879
4880 <para><literal>GTK_SPIN_PAGE_FORWARD</literal> and <literal>GTK_SPIN_PAGE_BACKWARD</literal> simply
4881 alter the value of the Spin Button by <literal>increment</literal>.</para>
4882
4883 <para><literal>GTK_SPIN_HOME</literal> sets the value of the Spin Button to the bottom of
4884 the Adjustments range.</para>
4885
4886 <para><literal>GTK_SPIN_END</literal> sets the value of the Spin Button to the top of the
4887 Adjustments range.</para>
4888
4889 <para><literal>GTK_SPIN_USER_DEFINED</literal> simply alters the value of the Spin Button
4890 by the specified amount.</para>
4891
4892 <para>We move away from functions for setting and retreving the range attributes
4893 of the Spin Button now, and move onto functions that effect the
4894 appearance and behaviour of the Spin Button widget itself.</para>
4895
4896 <para>The first of these functions is used to constrain the text box of the
4897 Spin Button such that it may only contain a numeric value. This
4898 prevents a user from typing anything other than numeric values into
4899 the text box of a Spin Button:</para>
4900
4901 <programlisting role="C">
4902 void gtk_spin_button_set_numeric( GtkSpinButton *spin_button,
4903                                   gboolean       numeric );
4904 </programlisting>
4905
4906 <para>You can set whether a Spin Button will wrap around between the upper
4907 and lower range values with the following function:</para>
4908
4909 <programlisting role="C">
4910 void gtk_spin_button_set_wrap( GtkSpinButton *spin_button,
4911                                gboolean       wrap );
4912 </programlisting>
4913
4914 <para>You can set a Spin Button to round the value to the nearest
4915 <literal>step_increment</literal>, which is set within the Adjustment object used
4916 with the Spin Button. This is accomplished with the following
4917 function:</para>
4918
4919 <programlisting role="C">
4920 void gtk_spin_button_set_snap_to_ticks( GtkSpinButton  *spin_button,
4921                                         gboolean        snap_to_ticks );
4922 </programlisting>
4923
4924 <para>The update policy of a Spin Button can be changed with the following
4925 function:</para>
4926
4927 <programlisting role="C">
4928 void gtk_spin_button_set_update_policy( GtkSpinButton  *spin_button,
4929                                         GtkSpinButtonUpdatePolicy policy );
4930 </programlisting>
4931
4932 <para>The possible values of <literal>policy</literal> are either <literal>GTK_UPDATE_ALWAYS</literal> or
4933 <literal>GTK_UPDATE_IF_VALID</literal>.</para>
4934
4935 <para>These policies affect the behavior of a Spin Button when parsing
4936 inserted text and syncing its value with the values of the
4937 Adjustment.</para>
4938
4939 <para>In the case of <literal>GTK_UPDATE_IF_VALID</literal> the Spin Button only value
4940 gets changed if the text input is a numeric value that is within the
4941 range specified by the Adjustment. Otherwise the text is reset to the
4942 current value.</para>
4943
4944 <para>In case of <literal>GTK_UPDATE_ALWAYS</literal> we ignore errors while converting
4945 text into a numeric value.</para>
4946
4947 <para>Finally, you can explicitly request that a Spin Button update itself:</para>
4948
4949 <programlisting role="C">
4950 void gtk_spin_button_update( GtkSpinButton  *spin_button );
4951 </programlisting>
4952
4953 <para>It's example time again.</para>
4954
4955 <para>
4956 <inlinemediaobject>
4957 <imageobject>
4958 <imagedata fileref="images/spinbutton.png" format="png">
4959 </imageobject>
4960 </inlinemediaobject>
4961 </para>
4962
4963 <programlisting role="C">
4964 <!-- example-start spinbutton spinbutton.c -->
4965
4966 #include &lt;stdio.h&gt;
4967 #include &lt;gtk/gtk.h&gt;
4968
4969 static GtkWidget *spinner1;
4970
4971 static void toggle_snap( GtkWidget     *widget,
4972                          GtkSpinButton *spin )
4973 {
4974   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)-&gt;active);
4975 }
4976
4977 static void toggle_numeric( GtkWidget *widget,
4978                             GtkSpinButton *spin )
4979 {
4980   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)-&gt;active);
4981 }
4982
4983 static void change_digits( GtkWidget *widget,
4984                            GtkSpinButton *spin )
4985 {
4986   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
4987                               gtk_spin_button_get_value_as_int (spin));
4988 }
4989
4990 static void get_value( GtkWidget *widget,
4991                        gpointer data )
4992 {
4993   gchar *buf;
4994   GtkLabel *label;
4995   GtkSpinButton *spin;
4996
4997   spin = GTK_SPIN_BUTTON (spinner1);
4998   label = GTK_LABEL (g_object_get_data (G_OBJECT (widget), "user_data"));
4999   if (GPOINTER_TO_INT (data) == 1)
5000     buf = g_strdup_printf ("%d", gtk_spin_button_get_value_as_int (spin));
5001   else
5002     buf = g_strdup_printf ("%0.*f", spin-&gt;digits,
5003                            gtk_spin_button_get_value (spin));
5004   gtk_label_set_text (label, buf);
5005   g_free (buf);
5006 }
5007
5008
5009 int main( int   argc,
5010           char *argv[] )
5011 {
5012   GtkWidget *window;
5013   GtkWidget *frame;
5014   GtkWidget *hbox;
5015   GtkWidget *main_vbox;
5016   GtkWidget *vbox;
5017   GtkWidget *vbox2;
5018   GtkWidget *spinner2;
5019   GtkWidget *spinner;
5020   GtkWidget *button;
5021   GtkWidget *label;
5022   GtkWidget *val_label;
5023   GtkAdjustment *adj;
5024
5025   /* Initialise GTK */
5026   gtk_init (&amp;argc, &amp;argv);
5027
5028   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5029
5030   g_signal_connect (G_OBJECT (window), "destroy",
5031                     G_CALLBACK (gtk_main_quit),
5032                     NULL);
5033
5034   gtk_window_set_title (GTK_WINDOW (window), "Spin Button");
5035
5036   main_vbox = gtk_vbox_new (FALSE, 5);
5037   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5038   gtk_container_add (GTK_CONTAINER (window), main_vbox);
5039   
5040   frame = gtk_frame_new ("Not accelerated");
5041   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5042   
5043   vbox = gtk_vbox_new (FALSE, 0);
5044   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5045   gtk_container_add (GTK_CONTAINER (frame), vbox);
5046   
5047   /* Day, month, year spinners */
5048   
5049   hbox = gtk_hbox_new (FALSE, 0);
5050   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5051   
5052   vbox2 = gtk_vbox_new (FALSE, 0);
5053   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5054   
5055   label = gtk_label_new ("Day :");
5056   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5057   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5058   
5059   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 31.0, 1.0,
5060                                               5.0, 0.0);
5061   spinner = gtk_spin_button_new (adj, 0, 0);
5062   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5063   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5064   
5065   vbox2 = gtk_vbox_new (FALSE, 0);
5066   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5067   
5068   label = gtk_label_new ("Month :");
5069   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5070   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5071   
5072   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5073                                               5.0, 0.0);
5074   spinner = gtk_spin_button_new (adj, 0, 0);
5075   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5076   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5077   
5078   vbox2 = gtk_vbox_new (FALSE, 0);
5079   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5080   
5081   label = gtk_label_new ("Year :");
5082   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5083   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5084   
5085   adj = (GtkAdjustment *) gtk_adjustment_new (1998.0, 0.0, 2100.0,
5086                                               1.0, 100.0, 0.0);
5087   spinner = gtk_spin_button_new (adj, 0, 0);
5088   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), FALSE);
5089   gtk_widget_set_size_request (spinner, 55, -1);
5090   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5091   
5092   frame = gtk_frame_new ("Accelerated");
5093   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5094   
5095   vbox = gtk_vbox_new (FALSE, 0);
5096   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5097   gtk_container_add (GTK_CONTAINER (frame), vbox);
5098   
5099   hbox = gtk_hbox_new (FALSE, 0);
5100   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5101   
5102   vbox2 = gtk_vbox_new (FALSE, 0);
5103   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5104   
5105   label = gtk_label_new ("Value :");
5106   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5107   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5108   
5109   adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
5110                                               0.5, 100.0, 0.0);
5111   spinner1 = gtk_spin_button_new (adj, 1.0, 2);
5112   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
5113   gtk_widget_set_size_request (spinner1, 100, -1);
5114   gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
5115   
5116   vbox2 = gtk_vbox_new (FALSE, 0);
5117   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5118   
5119   label = gtk_label_new ("Digits :");
5120   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5121   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5122   
5123   adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 5, 1, 1, 0);
5124   spinner2 = gtk_spin_button_new (adj, 0.0, 0);
5125   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner2), TRUE);
5126   g_signal_connect (G_OBJECT (adj), "value_changed",
5127                     G_CALLBACK (change_digits),
5128                     (gpointer) spinner2);
5129   gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
5130   
5131   hbox = gtk_hbox_new (FALSE, 0);
5132   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5133   
5134   button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
5135   g_signal_connect (G_OBJECT (button), "clicked",
5136                     G_CALLBACK (toggle_snap),
5137                     (gpointer) spinner1);
5138   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5139   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5140   
5141   button = gtk_check_button_new_with_label ("Numeric only input mode");
5142   g_signal_connect (G_OBJECT (button), "clicked",
5143                     G_CALLBACK (toggle_numeric),
5144                     (gpointer) spinner1);
5145   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5146   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5147   
5148   val_label = gtk_label_new ("");
5149   
5150   hbox = gtk_hbox_new (FALSE, 0);
5151   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5152   button = gtk_button_new_with_label ("Value as Int");
5153   g_object_set_data (G_OBJECT (button), "user_data", val_label);
5154   g_signal_connect (G_OBJECT (button), "clicked",
5155                     G_CALLBACK (get_value),
5156                     GINT_TO_POINTER (1));
5157   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5158   
5159   button = gtk_button_new_with_label ("Value as Float");
5160   g_object_set_data (G_OBJECT (button), "user_data", val_label);
5161   g_signal_connect (G_OBJECT (button), "clicked",
5162                     G_CALLBACK (get_value),
5163                     GINT_TO_POINTER (2));
5164   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5165   
5166   gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
5167   gtk_label_set_text (GTK_LABEL (val_label), "0");
5168   
5169   hbox = gtk_hbox_new (FALSE, 0);
5170   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5171   
5172   button = gtk_button_new_with_label ("Close");
5173   g_signal_connect_swapped (G_OBJECT (button), "clicked",
5174                             G_CALLBACK (gtk_widget_destroy),
5175                             G_OBJECT (window));
5176   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5177
5178   gtk_widget_show_all (window);
5179
5180   /* Enter the event loop */
5181   gtk_main ();
5182     
5183   return 0;
5184 }
5185
5186 <!-- example-end -->
5187 </programlisting>
5188
5189 </sect1>
5190
5191 <!-- ----------------------------------------------------------------- -->
5192 <sect1 id="sec-ComboBox">
5193 <title>Combo Box</title>
5194
5195 <para>The combo box is another fairly simple widget that is really just a
5196 collection of other widgets. From the user's point of view, the widget
5197 consists of a text entry box and a pull down menu from which the user
5198 can select one of a set of predefined entries. Alternatively, the user
5199 can type a different option directly into the text box.</para>
5200
5201 <para>The following extract from the structure that defines a Combo Box
5202 identifies several of the components:</para>
5203
5204 <programlisting role="C">
5205 struct _GtkCombo { 
5206         GtkHBox hbox; 
5207         GtkWidget *entry; 
5208         GtkWidget *button;
5209         GtkWidget *popup; 
5210         GtkWidget *popwin; 
5211         GtkWidget *list;
5212         ...  };
5213 </programlisting>
5214
5215 <para>As you can see, the Combo Box has two principal parts that you really
5216 care about: an entry and a list.</para>
5217
5218 <para>First off, to create a combo box, use:</para>
5219
5220 <programlisting role="C">
5221 GtkWidget *gtk_combo_new( void );
5222 </programlisting>
5223
5224 <para>Now, if you want to set the string in the entry section of the combo
5225 box, this is done by manipulating the <literal>entry</literal> widget directly:</para>
5226
5227 <programlisting role="C">
5228     gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo)->entry), "My String.");
5229 </programlisting>
5230
5231 <para>To set the values in the popdown list, one uses the function:</para>
5232
5233 <programlisting role="C">
5234 void gtk_combo_set_popdown_strings( GtkCombo *combo,
5235                                     GList    *strings );
5236 </programlisting>
5237
5238 <para>Before you can do this, you have to assemble a GList of the strings
5239 that you want. GList is a linked list implementation that is part of
5240 <link linkend="ch-GLib">GLib</link>, a library supporting GTK. For the
5241 moment, the quick and dirty explanation is that you need to set up a
5242 GList pointer, set it equal to NULL, then append strings to it with</para>
5243
5244 <programlisting role="C">
5245 GList *g_list_append( GList *glist, 
5246                       gpointer data );
5247 </programlisting>
5248
5249 <para>It is important that you set the initial GList pointer to NULL. The
5250 value returned from the g_list_append() function must be used as the new
5251 pointer to the GList.</para>
5252
5253 <para>Here's a typical code segment for creating a set of options:</para>
5254
5255 <programlisting role="C">
5256     GList *glist = NULL;
5257
5258     glist = g_list_append (glist, "String 1");
5259     glist = g_list_append (glist, "String 2");
5260     glist = g_list_append (glist, "String 3"); 
5261     glist = g_list_append (glist, "String 4");
5262
5263     gtk_combo_set_popdown_strings (GTK_COMBO (combo), glist);
5264     
5265     /* can free glist now, combo takes a copy */
5266 </programlisting>
5267
5268 <para>The combo widget makes a copy of the strings passed to it in the glist
5269 structure. As a result, you need to make sure you free the memory used
5270 by the list if that is appropriate for your application.</para>
5271
5272 <para>At this point you have a working combo box that has been set up.
5273 There are a few aspects of its behavior that you can change. These
5274 are accomplished with the functions: </para>
5275
5276 <programlisting role="C">
5277 void gtk_combo_set_use_arrows( GtkCombo *combo,
5278                                gboolean  val );
5279
5280 void gtk_combo_set_use_arrows_always( GtkCombo *combo,
5281                                       gboolean  val );
5282
5283 void gtk_combo_set_case_sensitive( GtkCombo *combo,
5284                                    gboolean  val );
5285 </programlisting>
5286
5287 <para>gtk_combo_set_use_arrows() lets the user change the value in the
5288 entry using the up/down arrow keys. This doesn't bring up the list, but
5289 rather replaces the current text in the entry with the next list entry
5290 (up or down, as your key choice indicates). It does this by searching
5291 in the list for the item corresponding to the current value in the
5292 entry and selecting the previous/next item accordingly. Usually in an
5293 entry the arrow keys are used to change focus (you can do that anyway
5294 using TAB). Note that when the current item is the last of the list
5295 and you press arrow-down it changes the focus (the same applies with
5296 the first item and arrow-up).</para>
5297
5298 <para>If the current value in the entry is not in the list, then the
5299 function of gtk_combo_set_use_arrows() is disabled.</para>
5300
5301 <para>gtk_combo_set_use_arrows_always() similarly allows the use the
5302 the up/down arrow keys to cycle through the choices in the dropdown
5303 list, except that it wraps around the values in the list, completely
5304 disabling the use of the up and down arrow keys for changing focus.</para>
5305
5306 <para>gtk_combo_set_case_sensitive() toggles whether or not GTK
5307 searches for entries in a case sensitive manner. This is used when the
5308 Combo widget is asked to find a value from the list using the current
5309 entry in the text box. This completion can be performed in either a
5310 case sensitive or insensitive manner, depending upon the use of this
5311 function. The Combo widget can also simply complete the current entry
5312 if the user presses the key combination MOD-1 and "Tab". MOD-1 is
5313 often mapped to the "Alt" key, by the <literal>xmodmap</literal> utility. Note,
5314 however that some window managers also use this key combination, which
5315 will override its use within GTK.</para>
5316
5317 <para>Now that we have a combo box, tailored to look and act how we want it,
5318 all that remains is being able to get data from the combo box. This is
5319 relatively straightforward. The majority of the time, all you are
5320 going to care about getting data from is the entry. The entry is
5321 accessed simply by <literal>GTK_ENTRY (GTK_COMBO (combo)->entry)</literal>. The
5322 two principal things that you are going to want to do with it are
5323 connect to the activate signal, which indicates that the user has
5324 pressed the Return or Enter key, and read the text. The first is
5325 accomplished using something like:</para>
5326
5327 <programlisting role="C">
5328     g_signal_connect (G_OBJECT (GTK_COMBO (combo)->entry), "activate",
5329                       G_CALLBACK (my_callback_function), (gpointer) my_data);
5330 </programlisting>
5331
5332 <para>Getting the text at any arbitrary time is accomplished by simply using
5333 the entry function:</para>
5334
5335 <programlisting role="C">
5336 gchar *gtk_entry_get_text( GtkEntry *entry );
5337 </programlisting>
5338
5339 <para>Such as:</para>
5340
5341 <programlisting role="C">
5342     gchar *string;
5343
5344     string = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (combo)->entry));
5345 </programlisting>
5346
5347 <para>That's about all there is to it. There is a function</para>
5348
5349 <programlisting role="C">
5350 void gtk_combo_disable_activate( GtkCombo *combo );
5351 </programlisting>
5352
5353 <para>that will disable the activate signal on the entry widget in the combo
5354 box. Personally, I can't think of why you'd want to use it, but it
5355 does exist.</para>
5356
5357 <!-- There is also a function to set the string on a particular item, void
5358 gtk_combo_set_item_string(GtkCombo *combo, GtkItem *item, const gchar
5359 *item_value), but this requires that you have a pointer to the
5360 appropriate Item. Frankly, I have no idea how to do that.
5361 -->
5362
5363 </sect1>
5364
5365 <!-- ----------------------------------------------------------------- -->
5366 <sect1 id="sec-Calendar">
5367 <title>Calendar</title>
5368
5369 <para>The Calendar widget is an effective way to display and retrieve
5370 monthly date related information. It is a very simple widget to create
5371 and work with.</para>
5372
5373 <para>Creating a GtkCalendar widget is a simple as: </para>
5374
5375 <programlisting role="C">
5376 GtkWidget *gtk_calendar_new( void );
5377 </programlisting>
5378
5379 <para>There might be times where you need to change a lot of information
5380 within this widget and the following functions allow you to make
5381 multiple change to a Calendar widget without the user seeing multiple
5382 on-screen updates.</para>
5383
5384 <programlisting role="C">
5385 void gtk_calendar_freeze( GtkCalendar *Calendar );
5386
5387 void gtk_calendar_thaw( GtkCalendar *Calendar );
5388 </programlisting>
5389
5390 <para>They work just like the freeze/thaw functions of every other
5391 widget.</para>
5392
5393 <para>The Calendar widget has a few options that allow you to change the way
5394 the widget both looks and operates by using the function</para>
5395
5396 <programlisting role="C">
5397 void gtk_calendar_display_options( GtkCalendar               *calendar,
5398                                    GtkCalendarDisplayOptions  flags );
5399 </programlisting>
5400
5401 <para>The <literal>flags</literal> argument can be formed by combining either of the
5402 following five options using the logical bitwise OR (|) operation:</para>
5403
5404 <variablelist>
5405 <varlistentry>
5406 <term><literal>GTK_CALENDAR_SHOW_HEADING</literal></term>
5407 <listitem><para>this option specifies that the month and year should be shown 
5408 when drawing the calendar.</para>
5409 </listitem>
5410 </varlistentry>
5411 <varlistentry>
5412 <term><literal>GTK_CALENDAR_SHOW_DAY_NAMES</literal></term>
5413 <listitem><para>this option specifies that the three letter descriptions should 
5414 be displayed for each day (eg Mon,Tue, etc.).</para>
5415 </listitem>
5416 </varlistentry>
5417 <varlistentry>
5418 <term><literal>GTK_CALENDAR_NO_MONTH_CHANGE</literal></term>
5419 <listitem><para>this option states that the user
5420 should not and can not change the currently displayed month. This can
5421 be good if you only need to display a particular month such as if you
5422 are displaying 12 calendar widgets for every month in a particular
5423 year.</para>
5424 </listitem>
5425 </varlistentry>
5426 <varlistentry>
5427 <term><literal>GTK_CALENDAR_SHOW_WEEK_NUMBERS</literal></term>
5428 <listitem><para>this option specifies that the
5429 number for each week should be displayed down the left side of the
5430 calendar. (eg. Jan 1 = Week 1,Dec 31 = Week 52).</para>
5431 </listitem>
5432 </varlistentry>
5433 <varlistentry>
5434 <term><literal>GTK_CALENDAR_WEEK_START_MONDAY</literal></term>
5435 <listitem><para>this option states that the
5436 calander week will start on Monday instead of Sunday which is the
5437 default. This only affects the order in which days are displayed from
5438 left to right.</para>
5439 </listitem>
5440 </varlistentry>
5441 </variablelist>
5442
5443 <para>The following functions are used to set the the currently displayed
5444 date:</para>
5445
5446 <programlisting role="C">
5447 gint gtk_calendar_select_month( GtkCalendar *calendar, 
5448                                 guint        month,
5449                                 guint        year );
5450
5451 void gtk_calendar_select_day( GtkCalendar *calendar,
5452                               guint        day );
5453 </programlisting>
5454
5455 <para>The return value from <literal>gtk_calendar_select_month()</literal> is a boolean
5456 value indicating whether the selection was successful.</para>
5457
5458 <para>With <literal>gtk_calendar_select_day()</literal> the specified day number is
5459 selected within the current month, if that is possible. A
5460 <literal>day</literal> value of 0 will deselect any current selection.</para>
5461
5462 <para>In addition to having a day selected, any number of days in the month
5463 may be "marked". A marked day is highlighted within the calendar
5464 display. The following functions are provided to manipulate marked
5465 days:</para>
5466
5467 <programlisting role="C">
5468 gint gtk_calendar_mark_day( GtkCalendar *calendar,
5469                             guint        day);
5470
5471 gint gtk_calendar_unmark_day( GtkCalendar *calendar,
5472                               guint        day);
5473
5474 void gtk_calendar_clear_marks( GtkCalendar *calendar);
5475 </programlisting>
5476
5477 <para>The currently marked days are stored within an array within the
5478 GtkCalendar structure. This array is 31 elements long so to test
5479 whether a particular day is currently marked, you need to access the
5480 corresponding element of the array (don't forget in C that array
5481 elements are numbered 0 to n-1). For example:</para>
5482
5483 <programlisting role="C">
5484     GtkCalendar *calendar;
5485     calendar = gtk_calendar_new ();
5486
5487     ...
5488
5489     /* Is day 7 marked? */
5490     if (calendar->marked_date[7-1])
5491        /* day is marked */
5492 </programlisting>
5493
5494 <para>Note that marks are persistent across month and year changes.</para>
5495
5496 <para>The final Calendar widget function is used to retrieve the currently
5497 selected date, month and/or year.</para>
5498
5499 <programlisting role="C">
5500 void gtk_calendar_get_date( GtkCalendar *calendar, 
5501                             guint       *year,
5502                             guint       *month,
5503                             guint       *day );
5504 </programlisting>
5505
5506 <para>This function requires you to pass the addresses of <literal>guint</literal>
5507 variables, into which the result will be placed. Passing <literal>NULL</literal> as
5508 a value will result in the corresponding value not being returned.</para>
5509
5510 <para>The Calendar widget can generate a number of signals indicating date
5511 selection and change. The names of these signals are self explanatory,
5512 and are:</para>
5513
5514 <itemizedlist>
5515 <listitem><simpara> <literal>month_changed</literal></simpara>
5516 </listitem>
5517 <listitem><simpara> <literal>day_selected</literal></simpara>
5518 </listitem>
5519 <listitem><simpara> <literal>day_selected_double_click</literal></simpara>
5520 </listitem>
5521 <listitem><simpara> <literal>prev_month</literal></simpara>
5522 </listitem>
5523 <listitem><simpara> <literal>next_month</literal></simpara>
5524 </listitem>
5525 <listitem><simpara> <literal>prev_year</literal></simpara>
5526 </listitem>
5527 <listitem><simpara> <literal>next_year</literal></simpara>
5528 </listitem>
5529 </itemizedlist>
5530
5531 <para>That just leaves us with the need to put all of this together into
5532 example code.</para>
5533
5534 <para>
5535 <inlinemediaobject>
5536 <imageobject>
5537 <imagedata fileref="images/calendar.png" format="png">
5538 </imageobject>
5539 </inlinemediaobject>
5540 </para>
5541
5542 <programlisting role="C">
5543 <!-- example-start calendar calendar.c -->
5544 /*
5545  * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson, Mattias Grönlund
5546  * Copyright (C) 2000 Tony Gale
5547  *
5548  * This program is free software; you can redistribute it and/or modify
5549  * it under the terms of the GNU General Public License as published by
5550  * the Free Software Foundation; either version 2 of the License, or
5551  * (at your option) any later version.
5552  *
5553  * This program is distributed in the hope that it will be useful,
5554  * but WITHOUT ANY WARRANTY; without even the implied warranty of
5555  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5556  * GNU General Public License for more details.
5557  *
5558  * You should have received a copy of the GNU General Public License
5559  * along with this program; if not, write to the Free Software
5560  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5561  */
5562
5563 #include &lt;stdio.h&gt;
5564 #include &lt;string.h&gt;
5565 #include &lt;gtk/gtk.h&gt;
5566
5567 #define DEF_PAD 10
5568 #define DEF_PAD_SMALL 5
5569
5570 #define TM_YEAR_BASE 1900
5571
5572 typedef struct _CalendarData {
5573   GtkWidget *flag_checkboxes[5];
5574   gboolean  settings[5];
5575   GtkWidget *font_dialog;
5576   GtkWidget *window;
5577   GtkWidget *prev2_sig;
5578   GtkWidget *prev_sig;
5579   GtkWidget *last_sig;
5580   GtkWidget *month;
5581 } CalendarData;
5582
5583 enum {
5584   calendar_show_header,
5585   calendar_show_days,
5586   calendar_month_change, 
5587   calendar_show_week,
5588   calendar_monday_first
5589 };
5590
5591 /*
5592  * GtkCalendar
5593  */
5594
5595 static void calendar_date_to_string( CalendarData *data,
5596                                      char         *buffer,
5597                                      gint          buff_len )
5598 {
5599   GDate date;
5600   guint year, month, day;
5601
5602   gtk_calendar_get_date (GTK_CALENDAR (data-&gt;window),
5603                          &amp;year, &amp;month, &amp;day);
5604   g_date_set_dmy (&date, day, month + 1, year);
5605   g_date_strftime (buffer, buff_len - 1, "%x", &date);
5606
5607 }
5608
5609 static void calendar_set_signal_strings( char         *sig_str,
5610                                          CalendarData *data )
5611 {
5612   const gchar *prev_sig;
5613
5614   prev_sig = gtk_label_get_text (GTK_LABEL (data-&gt;prev_sig));
5615   gtk_label_set_text (GTK_LABEL (data-&gt;prev2_sig), prev_sig);
5616
5617   prev_sig = gtk_label_get_text (GTK_LABEL (data-&gt;last_sig));
5618   gtk_label_set_text (GTK_LABEL (data-&gt;prev_sig), prev_sig);
5619   gtk_label_set_text (GTK_LABEL (data-&gt;last_sig), sig_str);
5620 }
5621
5622 static void calendar_month_changed( GtkWidget    *widget,
5623                                     CalendarData *data )
5624 {
5625   char buffer[256] = "month_changed: ";
5626
5627   calendar_date_to_string (data, buffer + 15, 256 - 15);
5628   calendar_set_signal_strings (buffer, data);
5629 }
5630
5631 static void calendar_day_selected( GtkWidget    *widget,
5632                                    CalendarData *data )
5633 {
5634   char buffer[256] = "day_selected: ";
5635
5636   calendar_date_to_string (data, buffer + 14, 256 - 14);
5637   calendar_set_signal_strings (buffer, data);
5638 }
5639
5640 static void calendar_day_selected_double_click ( GtkWidget    *widget,
5641                                                  CalendarData *data )
5642 {
5643   char buffer[256] = "day_selected_double_click: ";
5644   guint day;
5645
5646   calendar_date_to_string (data, buffer + 27, 256 - 27);
5647   calendar_set_signal_strings (buffer, data);
5648
5649   gtk_calendar_get_date (GTK_CALENDAR (data-&gt;window),
5650                          NULL, NULL, &amp;day);
5651
5652   if (GTK_CALENDAR (data-&gt;window)-&gt;marked_date[day-1] == 0) {
5653     gtk_calendar_mark_day (GTK_CALENDAR (data-&gt;window), day);
5654   } else { 
5655     gtk_calendar_unmark_day (GTK_CALENDAR (data-&gt;window), day);
5656   }
5657 }
5658
5659 static void calendar_prev_month( GtkWidget    *widget,
5660                                  CalendarData *data )
5661 {
5662   char buffer[256] = "prev_month: ";
5663
5664   calendar_date_to_string (data, buffer + 12, 256 - 12);
5665   calendar_set_signal_strings (buffer, data);
5666 }
5667
5668 static void calendar_next_month( GtkWidget    *widget,
5669                                  CalendarData *data )
5670 {
5671   char buffer[256] = "next_month: ";
5672
5673   calendar_date_to_string (data, buffer + 12, 256 - 12);
5674   calendar_set_signal_strings (buffer, data);
5675 }
5676
5677 static void calendar_prev_year( GtkWidget    *widget,
5678                                 CalendarData *data )
5679 {
5680   char buffer[256] = "prev_year: ";
5681
5682   calendar_date_to_string (data, buffer + 11, 256 - 11);
5683   calendar_set_signal_strings (buffer, data);
5684 }
5685
5686 static void calendar_next_year( GtkWidget    *widget,
5687                                 CalendarData *data )
5688 {
5689   char buffer[256] = "next_year: ";
5690
5691   calendar_date_to_string (data, buffer + 11, 256 - 11);
5692   calendar_set_signal_strings (buffer, data);
5693 }
5694
5695
5696 static void calendar_set_flags( CalendarData *calendar )
5697 {
5698   gint i;
5699   gint options = 0;
5700   for (i = 0;i &lt; 5; i++) 
5701     if (calendar-&gt;settings[i])
5702       {
5703         options = options + (1 &lt;&lt; i);
5704       }
5705   if (calendar-&gt;window)
5706     gtk_calendar_display_options (GTK_CALENDAR (calendar-&gt;window), options);
5707 }
5708
5709 static void calendar_toggle_flag( GtkWidget    *toggle,
5710                                   CalendarData *calendar)
5711 {
5712   gint i;
5713   gint j;
5714   j = 0;
5715   for (i = 0; i &lt; 5; i++)
5716     if (calendar-&gt;flag_checkboxes[i] == toggle)
5717       j = i;
5718
5719   calendar-&gt;settings[j] = !calendar-&gt;settings[j];
5720   calendar_set_flags (calendar);
5721   
5722 }
5723
5724 static void calendar_font_selection_ok( GtkWidget    *button,
5725                                         CalendarData *calendar )
5726 {
5727   GtkRcStyle *style;
5728   char *font_name;
5729
5730   if (calendar-&gt;window)
5731     {
5732       font_name = gtk_font_selection_dialog_get_font_name (GTK_FONT_SELECTION_DIALOG (calendar-&gt;font_dialog));
5733       if (font_name) 
5734         {
5735           style = gtk_rc_style_new ();
5736           pango_font_description_free (style-&gt;font_desc);
5737           style-&gt;font_desc = pango_font_description_from_string (font_name);
5738           gtk_widget_modify_style (calendar-&gt;window, style);
5739           g_free (font_name);
5740         }
5741     }
5742
5743   gtk_widget_destroy (calendar-&gt;font_dialog);
5744 }
5745
5746 static void calendar_select_font( GtkWidget    *button,
5747                                   CalendarData *calendar )
5748 {
5749   GtkWidget *window;
5750
5751   if (!calendar-&gt;font_dialog) {
5752     window = gtk_font_selection_dialog_new ("Font Selection Dialog");
5753     g_return_if_fail (GTK_IS_FONT_SELECTION_DIALOG (window));
5754     calendar-&gt;font_dialog = window;
5755     
5756     gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
5757     
5758     g_signal_connect (window, "destroy",
5759                       G_CALLBACK (gtk_widget_destroyed),
5760                       &amp;calendar-&gt;font_dialog);
5761     
5762     g_signal_connect (GTK_FONT_SELECTION_DIALOG (window)-&gt;ok_button,
5763                       "clicked", G_CALLBACK (calendar_font_selection_ok),
5764                       calendar);
5765     g_signal_connect_swapped (GTK_FONT_SELECTION_DIALOG (window)-&gt;cancel_button,
5766                              "clicked", G_CALLBACK (gtk_widget_destroy), 
5767                              calendar-&gt;font_dialog);
5768   }
5769   window = calendar-&gt;font_dialog;
5770   if (!GTK_WIDGET_VISIBLE (window))
5771     gtk_widget_show (window);
5772   else
5773     gtk_widget_destroy (window);
5774
5775 }
5776
5777 static void create_calendar( void )
5778 {
5779   GtkWidget *window;
5780   GtkWidget *vbox, *vbox2, *vbox3;
5781   GtkWidget *hbox;
5782   GtkWidget *hbbox;
5783   GtkWidget *calendar;
5784   GtkWidget *toggle;
5785   GtkWidget *button;
5786   GtkWidget *frame;
5787   GtkWidget *separator;
5788   GtkWidget *label;
5789   GtkWidget *bbox;
5790   static CalendarData calendar_data;
5791   gint i;
5792   
5793   struct {
5794     char *label;
5795   } flags[] =
5796     {
5797       { "Show Heading" },
5798       { "Show Day Names" },
5799       { "No Month Change" },
5800       { "Show Week Numbers" },
5801       { "Week Start Monday" }
5802     };
5803
5804   
5805   calendar_data.window = NULL;
5806   calendar_data.font_dialog = NULL;
5807
5808   for (i = 0; i &lt; 5; i++) {
5809     calendar_data.settings[i] = 0;
5810   }
5811
5812   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5813   gtk_window_set_title (GTK_WINDOW (window), "GtkCalendar Example");
5814   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
5815   g_signal_connect (window, "destroy",
5816                     G_CALLBACK (gtk_main_quit),
5817                     NULL);
5818   g_signal_connect (window, "delete-event",
5819                     G_CALLBACK (gtk_false),
5820                     NULL);
5821   gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
5822
5823   vbox = gtk_vbox_new (FALSE, DEF_PAD);
5824   gtk_container_add (GTK_CONTAINER (window), vbox);
5825
5826   /*
5827    * The top part of the window, Calendar, flags and fontsel.
5828    */
5829
5830   hbox = gtk_hbox_new (FALSE, DEF_PAD);
5831   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, DEF_PAD);
5832   hbbox = gtk_hbutton_box_new ();
5833   gtk_box_pack_start (GTK_BOX (hbox), hbbox, FALSE, FALSE, DEF_PAD);
5834   gtk_button_box_set_layout (GTK_BUTTON_BOX (hbbox), GTK_BUTTONBOX_SPREAD);
5835   gtk_box_set_spacing (GTK_BOX (hbbox), 5);
5836
5837   /* Calendar widget */
5838   frame = gtk_frame_new ("Calendar");
5839   gtk_box_pack_start(GTK_BOX (hbbox), frame, FALSE, TRUE, DEF_PAD);
5840   calendar=gtk_calendar_new ();
5841   calendar_data.window = calendar;
5842   calendar_set_flags (&amp;calendar_data);
5843   gtk_calendar_mark_day (GTK_CALENDAR (calendar), 19);  
5844   gtk_container_add (GTK_CONTAINER (frame), calendar);
5845   g_signal_connect (calendar, "month_changed", 
5846                     G_CALLBACK (calendar_month_changed),
5847                     &amp;calendar_data);
5848   g_signal_connect (calendar, "day_selected", 
5849                     G_CALLBACK (calendar_day_selected),
5850                     &amp;calendar_data);
5851   g_signal_connect (calendar, "day_selected_double_click", 
5852                     G_CALLBACK (calendar_day_selected_double_click),
5853                     &amp;calendar_data);
5854   g_signal_connect (calendar, "prev_month", 
5855                     G_CALLBACK (calendar_prev_month),
5856                     &amp;calendar_data);
5857   g_signal_connect (calendar, "next_month", 
5858                     G_CALLBACK (calendar_next_month),
5859                     &amp;calendar_data);
5860   g_signal_connect (calendar, "prev_year", 
5861                     G_CALLBACK (calendar_prev_year),
5862                     &amp;calendar_data);
5863   g_signal_connect (calendar, "next_year", 
5864                     G_CALLBACK (calendar_next_year),
5865                     &amp;calendar_data);
5866
5867
5868   separator = gtk_vseparator_new ();
5869   gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, TRUE, 0);
5870
5871   vbox2 = gtk_vbox_new (FALSE, DEF_PAD);
5872   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, DEF_PAD);
5873   
5874   /* Build the Right frame with the flags in */ 
5875
5876   frame = gtk_frame_new ("Flags");
5877   gtk_box_pack_start (GTK_BOX (vbox2), frame, TRUE, TRUE, DEF_PAD);
5878   vbox3 = gtk_vbox_new (TRUE, DEF_PAD_SMALL);
5879   gtk_container_add (GTK_CONTAINER (frame), vbox3);
5880
5881   for (i = 0; i &lt; 5; i++)
5882     {
5883       toggle = gtk_check_button_new_with_label (flags[i].label);
5884       g_signal_connect (toggle,
5885                         "toggled",
5886                         G_CALLBACK (calendar_toggle_flag),
5887                         &amp;calendar_data);
5888       gtk_box_pack_start (GTK_BOX (vbox3), toggle, TRUE, TRUE, 0);
5889       calendar_data.flag_checkboxes[i] = toggle;
5890     }
5891   /* Build the right font-button */ 
5892   button = gtk_button_new_with_label ("Font...");
5893   g_signal_connect (button,
5894                     "clicked",
5895                     G_CALLBACK (calendar_select_font),
5896                     &amp;calendar_data);
5897   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
5898
5899   /*
5900    *  Build the Signal-event part.
5901    */
5902
5903   frame = gtk_frame_new ("Signal events");
5904   gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, DEF_PAD);
5905
5906   vbox2 = gtk_vbox_new (TRUE, DEF_PAD_SMALL);
5907   gtk_container_add (GTK_CONTAINER (frame), vbox2);
5908   
5909   hbox = gtk_hbox_new (FALSE, 3);
5910   gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
5911   label = gtk_label_new ("Signal:");
5912   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5913   calendar_data.last_sig = gtk_label_new ("");
5914   gtk_box_pack_start (GTK_BOX (hbox), calendar_data.last_sig, FALSE, TRUE, 0);
5915
5916   hbox = gtk_hbox_new (FALSE, 3);
5917   gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
5918   label = gtk_label_new ("Previous signal:");
5919   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5920   calendar_data.prev_sig = gtk_label_new ("");
5921   gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev_sig, FALSE, TRUE, 0);
5922
5923   hbox = gtk_hbox_new (FALSE, 3);
5924   gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
5925   label = gtk_label_new ("Second previous signal:");
5926   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5927   calendar_data.prev2_sig = gtk_label_new ("");
5928   gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev2_sig, FALSE, TRUE, 0);
5929
5930   bbox = gtk_hbutton_box_new ();
5931   gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
5932   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
5933
5934   button = gtk_button_new_with_label ("Close");
5935   g_signal_connect (button, "clicked", 
5936                     G_CALLBACK (gtk_main_quit), 
5937                     NULL);
5938   gtk_container_add (GTK_CONTAINER (bbox), button);
5939   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
5940   gtk_widget_grab_default (button);
5941
5942   gtk_widget_show_all (window);
5943 }
5944
5945
5946 int main (int   argc,
5947           char *argv[])
5948 {
5949   gtk_init (&amp;argc, &amp;argv);
5950
5951   create_calendar ();
5952
5953   gtk_main ();
5954
5955   return 0;
5956 }
5957 <!-- example-end -->
5958 </programlisting>
5959
5960 </sect1>
5961
5962 <!-- ----------------------------------------------------------------- -->
5963 <sect1 id="sec-ColorSelection">
5964 <title>Color Selection</title>
5965
5966 <para>The color selection widget is, not surprisingly, a widget for
5967 interactive selection of colors. This composite widget lets the user
5968 select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
5969 Saturation, Value) triples.  This is done either by adjusting single
5970 values with sliders or entries, or by picking the desired color from a
5971 hue-saturation wheel/value bar.  Optionally, the opacity of the color
5972 can also be set.</para>
5973
5974 <para>The color selection widget currently emits only one signal,
5975 "color_changed", which is emitted whenever the current color in the
5976 widget changes, either when the user changes it or if it's set
5977 explicitly through gtk_color_selection_set_color().</para>
5978
5979 <para>Lets have a look at what the color selection widget has to offer
5980 us. The widget comes in two flavours: GtkColorSelection and
5981 GtkColorSelectionDialog.</para>
5982
5983 <programlisting role="C">
5984 GtkWidget *gtk_color_selection_new( void );
5985 </programlisting>
5986         
5987 <para>You'll probably not be using this constructor directly. It creates an
5988 orphan ColorSelection widget which you'll have to parent
5989 yourself. The ColorSelection widget inherits from the VBox
5990 widget.</para>
5991
5992 <programlisting role="C">
5993 GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
5994 </programlisting>
5995
5996 <para>This is the most common color selection constructor. It creates a
5997 ColorSelectionDialog. It consists of a Frame containing a
5998 ColorSelection widget, an HSeparator and an HBox with three buttons,
5999 "Ok", "Cancel" and "Help". You can reach these buttons by accessing
6000 the "ok_button", "cancel_button" and "help_button" widgets in the
6001 ColorSelectionDialog structure,
6002 (i.e., <literal>GTK_COLOR_SELECTION_DIALOG (colorseldialog)->ok_button</literal>)).</para>
6003
6004 <programlisting role="C">
6005 void gtk_color_selection_set_has_opacity_control( GtkColorSelection *colorsel,
6006                                                   gboolean           has_opacity );
6007 </programlisting>
6008
6009 <para>The color selection widget supports adjusting the opacity of a color
6010 (also known as the alpha channel). This is disabled by
6011 default. Calling this function with has_opacity set to TRUE enables
6012 opacity. Likewise, has_opacity set to FALSE will disable opacity.</para>
6013
6014 <programlisting role="C">
6015 void gtk_color_selection_set_current_color( GtkColorSelection *colorsel,
6016                                             GdkColor          *color );
6017
6018 void gtk_color_selection_set_current_alpha( GtkColorSelection *colorsel,
6019                                             guint16            alpha );
6020 </programlisting>
6021
6022 <para>You can set the current color explicitly by calling 
6023 gtk_color_selection_set_current_color() with a pointer to a GdkColor. 
6024 Setting the opacity (alpha channel) is done with 
6025 gtk_color_selection_set_current_alpha(). The alpha value should be between
6026 0 (fully transparent) and 65636 (fully opaque).
6027 </para>
6028
6029 <programlisting role="C">
6030 void gtk_color_selection_get_current_color( GtkColorSelection *colorsel,
6031                                             GdkColor *color );
6032
6033 void gtk_color_selection_get_current_alpha( GtkColorSelection *colorsel,
6034                                             guint16           *alpha );
6035 </programlisting>
6036
6037 <para>When you need to query the current color, typically when you've
6038 received a "color_changed" signal, you use these functions.</para>
6039
6040 <para><!-- Need to do a whole section on DnD - TRG
6041 Drag and drop
6042 -------------</para>
6043
6044 <para>The color sample areas (right under the hue-saturation wheel) supports
6045 drag and drop. The type of drag and drop is "application/x-color". The
6046 message data consists of an array of 4 (or 5 if opacity is enabled)
6047 gdouble values, where the value at position 0 is 0.0 (opacity on) or
6048 1.0 (opacity off) followed by the red, green and blue values at
6049 positions 1,2 and 3 respectively.  If opacity is enabled, the opacity
6050 is passed in the value at position 4.
6051 --></para>
6052
6053 <para>Here's a simple example demonstrating the use of the
6054 ColorSelectionDialog. The program displays a window containing a
6055 drawing area. Clicking on it opens a color selection dialog, and
6056 changing the color in the color selection dialog changes the
6057 background color.</para>
6058
6059 <para>
6060 <inlinemediaobject>
6061 <imageobject>
6062 <imagedata fileref="images/colorsel.png" format="png">
6063 </imageobject>
6064 </inlinemediaobject>
6065 </para>
6066
6067 <programlisting role="C">
6068 <!-- example-start colorsel colorsel.c -->
6069
6070 #include &lt;glib.h&gt;
6071 #include &lt;gdk/gdk.h&gt;
6072 #include &lt;gtk/gtk.h&gt;
6073
6074 GtkWidget *colorseldlg = NULL;
6075 GtkWidget *drawingarea = NULL;
6076 GdkColor color;
6077
6078 /* Color changed handler */
6079
6080 static void color_changed_cb( GtkWidget         *widget,
6081                               GtkColorSelection *colorsel )
6082 {
6083   GdkColor ncolor;
6084
6085   gtk_color_selection_get_current_color (colorsel, &amp;ncolor);
6086   gtk_widget_modify_bg (drawingarea, GTK_STATE_NORMAL, &amp;ncolor);       
6087 }
6088
6089 /* Drawingarea event handler */
6090
6091 static gboolean area_event( GtkWidget *widget,
6092                             GdkEvent  *event,
6093                             gpointer   client_data )
6094 {
6095   gint handled = FALSE;
6096   gint response;
6097   GtkColorSelection *colorsel;
6098
6099   /* Check if we've received a button pressed event */
6100
6101   if (event-&gt;type == GDK_BUTTON_PRESS)
6102     {
6103       handled = TRUE;
6104
6105        /* Create color selection dialog */
6106       if (colorseldlg == NULL)
6107         colorseldlg = gtk_color_selection_dialog_new ("Select background color");
6108
6109       /* Get the ColorSelection widget */
6110       colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (colorseldlg)-&gt;colorsel);
6111
6112       gtk_color_selection_set_previous_color (colorsel, &amp;color);
6113       gtk_color_selection_set_current_color (colorsel, &amp;color);
6114       gtk_color_selection_set_has_palette (colorsel, TRUE);
6115
6116       /* Connect to the "color_changed" signal, set the client-data
6117        * to the colorsel widget */
6118       g_signal_connect (G_OBJECT (colorsel), "color_changed",
6119                         G_CALLBACK (color_changed_cb), (gpointer) colorsel);
6120
6121       /* Show the dialog */
6122       response = gtk_dialog_run (GTK_DIALOG (colorseldlg));
6123
6124       if (response == GTK_RESPONSE_OK)
6125         gtk_color_selection_get_current_color (colorsel, &amp;color);
6126       else 
6127         gtk_widget_modify_bg (drawingarea, GTK_STATE_NORMAL, &amp;color);
6128
6129       gtk_widget_hide (colorseldlg);
6130     }
6131
6132   return handled;
6133 }
6134
6135 /* Close down and exit handler */
6136
6137 static gboolean destroy_window( GtkWidget *widget,
6138                                 GdkEvent  *event,
6139                                 gpointer   client_data )
6140 {
6141   gtk_main_quit ();
6142   return TRUE;
6143 }
6144
6145 /* Main */
6146
6147 gint main( gint   argc,
6148            gchar *argv[] )
6149 {
6150   GtkWidget *window;
6151
6152   /* Initialize the toolkit, remove gtk-related commandline stuff */
6153
6154   gtk_init (&amp;argc, &amp;argv);
6155
6156   /* Create toplevel window, set title and policies */
6157
6158   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6159   gtk_window_set_title (GTK_WINDOW (window), "Color selection test");
6160   gtk_window_set_policy (GTK_WINDOW (window), TRUE, TRUE, TRUE);
6161
6162   /* Attach to the "delete" and "destroy" events so we can exit */
6163
6164   g_signal_connect (GTK_OBJECT (window), "delete_event",
6165                     GTK_SIGNAL_FUNC (destroy_window), (gpointer) window);
6166   
6167   /* Create drawingarea, set size and catch button events */
6168
6169   drawingarea = gtk_drawing_area_new ();
6170
6171   color.red = 0;
6172   color.blue = 65535;
6173   color.green = 0;
6174   gtk_widget_modify_bg (drawingarea, GTK_STATE_NORMAL, &amp;color);       
6175
6176   gtk_widget_set_size_request (GTK_WIDGET (drawingarea), 200, 200);
6177
6178   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
6179
6180   g_signal_connect (GTK_OBJECT (drawingarea), "event", 
6181                     GTK_SIGNAL_FUNC (area_event), (gpointer) drawingarea);
6182   
6183   /* Add drawingarea to window, then show them both */
6184
6185   gtk_container_add (GTK_CONTAINER (window), drawingarea);
6186
6187   gtk_widget_show (drawingarea);
6188   gtk_widget_show (window);
6189   
6190   /* Enter the gtk main loop (this never returns) */
6191
6192   gtk_main ();
6193
6194   /* Satisfy grumpy compilers */
6195
6196   return 0;
6197 }
6198 <!-- example-end -->
6199 </programlisting>
6200
6201 </sect1>
6202
6203 <!-- ----------------------------------------------------------------- -->
6204 <sect1 id="sec-FileSelections">
6205 <title>File Selections</title>
6206
6207 <para>The file selection widget is a quick and simple way to display a File
6208 dialog box. It comes complete with Ok, Cancel, and Help buttons, a
6209 great way to cut down on programming time.</para>
6210
6211 <para>To create a new file selection box use:</para>
6212
6213 <programlisting role="C">
6214 GtkWidget *gtk_file_selection_new( const gchar *title );
6215 </programlisting>
6216
6217 <para>To set the filename, for example to bring up a specific directory, or
6218 give a default filename, use this function:</para>
6219
6220 <programlisting role="C">
6221 void gtk_file_selection_set_filename( GtkFileSelection *filesel,
6222                                       const gchar      *filename );
6223 </programlisting>
6224
6225 <para>To grab the text that the user has entered or clicked on, use this 
6226 function:</para>
6227
6228 <programlisting role="C">
6229 gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel );
6230 </programlisting>
6231
6232 <para>There are also pointers to the widgets contained within the file 
6233 selection widget. These are:</para>
6234
6235 <programlisting role="C">
6236   dir_list
6237   file_list
6238   selection_entry
6239   selection_text
6240   main_vbox
6241   ok_button
6242   cancel_button
6243   help_button
6244 </programlisting>
6245  
6246 <para>Most likely you will want to use the ok_button, cancel_button, and
6247 help_button pointers in signaling their use.</para>
6248
6249 <para>Included here is an example stolen from <filename>testgtk.c</filename>,
6250 modified to run on its own. As you will see, there is nothing much to creating a file
6251 selection widget. While in this example the Help button appears on the
6252 screen, it does nothing as there is not a signal attached to it.</para>
6253
6254 <para>
6255 <inlinemediaobject>
6256 <imageobject>
6257 <imagedata fileref="images/filesel.png" format="png">
6258 </imageobject>
6259 </inlinemediaobject>
6260 </para>
6261
6262 <programlisting role="C">
6263 <!-- example-start filesel filesel.c -->
6264
6265 #include &lt;gtk/gtk.h&gt;
6266
6267 /* Get the selected filename and print it to the console */
6268 static void file_ok_sel( GtkWidget        *w,
6269                          GtkFileSelection *fs )
6270 {
6271     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
6272 }
6273
6274 int main( int   argc,
6275           char *argv[] )
6276 {
6277     GtkWidget *filew;
6278     
6279     gtk_init (&amp;argc, &amp;argv);
6280     
6281     /* Create a new file selection widget */
6282     filew = gtk_file_selection_new ("File selection");
6283     
6284     g_signal_connect (G_OBJECT (filew), "destroy",
6285                       G_CALLBACK (gtk_main_quit), NULL);
6286     /* Connect the ok_button to file_ok_sel function */
6287     g_signal_connect (G_OBJECT (GTK_FILE_SELECTION (filew)-&gt;ok_button),
6288                       "clicked", G_CALLBACK (file_ok_sel), (gpointer) filew);
6289     
6290     /* Connect the cancel_button to destroy the widget */
6291     g_signal_connect_swapped (G_OBJECT (GTK_FILE_SELECTION (filew)-&gt;cancel_button),
6292                               "clicked", G_CALLBACK (gtk_widget_destroy),
6293                               G_OBJECT (filew));
6294     
6295     /* Lets set the filename, as if this were a save dialog, and we are giving
6296      a default filename */
6297     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
6298                                      "penguin.png");
6299     
6300     gtk_widget_show (filew);
6301     gtk_main ();
6302     return 0;
6303 }
6304 <!-- example-end -->
6305 </programlisting>
6306
6307 </sect1>
6308 </chapter>
6309
6310 <!-- ***************************************************************** -->
6311 <chapter id="ch-ContainerWidgets">
6312 <title>Container Widgets</title>
6313
6314 <!-- ----------------------------------------------------------------- -->   
6315 <sect1 id="sec-EventBox">
6316 <title>The EventBox</title>
6317
6318 <para>Some GTK widgets don't have associated X windows, so they just draw on
6319 their parents. Because of this, they cannot receive events and if they
6320 are incorrectly sized, they don't clip so you can get messy
6321 overwriting, etc. If you require more from these widgets, the EventBox
6322 is for you.</para>
6323
6324 <para>At first glance, the EventBox widget might appear to be totally
6325 useless. It draws nothing on the screen and responds to no
6326 events. However, it does serve a function - it provides an X window
6327 for its child widget. This is important as many GTK widgets do not
6328 have an associated X window. Not having an X window saves memory and
6329 improves performance, but also has some drawbacks. A widget without an
6330 X window cannot receive events, and does not perform any clipping on
6331 its contents. Although the name <emphasis>EventBox</emphasis> emphasizes the
6332 event-handling function, the widget can also be used for clipping.
6333 (and more, see the example below).</para>
6334
6335 <para>To create a new EventBox widget, use:</para>
6336
6337 <programlisting role="C">
6338 GtkWidget *gtk_event_box_new( void );
6339 </programlisting>
6340
6341 <para>A child widget can then be added to this EventBox:</para>
6342
6343 <programlisting role="C">
6344     gtk_container_add (GTK_CONTAINER (event_box), child_widget);
6345 </programlisting>
6346
6347 <para>The following example demonstrates both uses of an EventBox - a label
6348 is created that is clipped to a small box, and set up so that a
6349 mouse-click on the label causes the program to exit. Resizing the
6350 window reveals varying amounts of the label.</para>
6351
6352 <para>
6353 <inlinemediaobject>
6354 <imageobject>
6355 <imagedata fileref="images/eventbox.png" format="png">
6356 </imageobject>
6357 </inlinemediaobject>
6358 </para>
6359
6360 <programlisting role="C">
6361 <!-- example-start eventbox eventbox.c -->
6362
6363 #include &lt;stdlib.h&gt;
6364 #include &lt;gtk/gtk.h&gt;
6365
6366 int main( int argc,
6367           char *argv[] )
6368 {
6369     GtkWidget *window;
6370     GtkWidget *event_box;
6371     GtkWidget *label;
6372     
6373     gtk_init (&amp;argc, &amp;argv);
6374     
6375     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6376     
6377     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
6378     
6379     g_signal_connect (G_OBJECT (window), "destroy",
6380                       G_CALLBACK (exit), NULL);
6381     
6382     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6383     
6384     /* Create an EventBox and add it to our toplevel window */
6385     
6386     event_box = gtk_event_box_new ();
6387     gtk_container_add (GTK_CONTAINER (window), event_box);
6388     gtk_widget_show (event_box);
6389     
6390     /* Create a long label */
6391     
6392     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
6393     gtk_container_add (GTK_CONTAINER (event_box), label);
6394     gtk_widget_show (label);
6395     
6396     /* Clip it short. */
6397     gtk_widget_set_size_request (label, 110, 20);
6398     
6399     /* And bind an action to it */
6400     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
6401     g_signal_connect (G_OBJECT (event_box), "button_press_event",
6402                       G_CALLBACK (exit), NULL);
6403     
6404     /* Yet one more thing you need an X window for ... */
6405     
6406     gtk_widget_realize (event_box);
6407     gdk_window_set_cursor (event_box-&gt;window, gdk_cursor_new (GDK_HAND1));
6408     
6409     gtk_widget_show (window);
6410     
6411     gtk_main ();
6412     
6413     return 0;
6414 }
6415 <!-- example-end -->
6416 </programlisting>
6417
6418 </sect1>
6419
6420 <!-- ----------------------------------------------------------------- -->   
6421 <sect1 id="sec-TheAlignmentWidget">
6422 <title>The Alignment widget</title>
6423
6424 <para>The alignment widget allows you to place a widget within its window at
6425 a position and size relative to the size of the Alignment widget
6426 itself. For example, it can be very useful for centering a widget
6427 within the window.</para>
6428
6429 <para>There are only two functions associated with the Alignment widget:</para>
6430
6431 <programlisting role="C">
6432 GtkWidget* gtk_alignment_new( gfloat xalign,
6433                               gfloat yalign,
6434                               gfloat xscale,
6435                               gfloat yscale );
6436
6437 void gtk_alignment_set( GtkAlignment *alignment,
6438                         gfloat        xalign,
6439                         gfloat        yalign,
6440                         gfloat        xscale,
6441                         gfloat        yscale );
6442 </programlisting>
6443
6444 <para>The first function creates a new Alignment widget with the specified
6445 parameters. The second function allows the alignment parameters of an
6446 exisiting Alignment widget to be altered.</para>
6447
6448 <para>All four alignment parameters are floating point numbers which can
6449 range from 0.0 to 1.0. The <literal>xalign</literal> and <literal>yalign</literal> arguments
6450 affect the position of the widget placed within the Alignment
6451 widget. The <literal>xscale</literal> and <literal>yscale</literal> arguments effect the amount of
6452 space allocated to the widget.</para>
6453
6454 <para>A child widget can be added to this Alignment widget using:</para>
6455
6456 <programlisting role="C">
6457     gtk_container_add (GTK_CONTAINER (alignment), child_widget);
6458 </programlisting>
6459
6460 <para>For an example of using an Alignment widget, refer to the example for
6461 the <link linkend="sec-ProgressBars">Progress Bar</link> widget.</para>
6462
6463 </sect1>
6464
6465 <!-- ----------------------------------------------------------------- -->
6466 <sect1 id="sec-FixedContainer">
6467 <title>Fixed Container</title>
6468
6469 <para>The Fixed container allows you to place widgets at a fixed position
6470 within it's window, relative to it's upper left hand corner. The
6471 position of the widgets can be changed dynamically.</para>
6472
6473 <para>There are only a few functions associated with the fixed widget:</para>
6474
6475 <programlisting role="C">
6476 GtkWidget* gtk_fixed_new( void );
6477
6478 void gtk_fixed_put( GtkFixed  *fixed,
6479                     GtkWidget *widget,
6480                     gint       x,
6481                     gint       y );
6482
6483 void gtk_fixed_move( GtkFixed  *fixed,
6484                      GtkWidget *widget,
6485                      gint       x,
6486                      gint       y );
6487 </programlisting>
6488
6489 <para>The function gtk_fixed_new() allows you to create a new Fixed
6490 container.</para>
6491
6492 <para>gtk_fixed_put() places <literal>widget</literal> in the container <literal>fixed</literal> at
6493 the position specified by <literal>x</literal> and <literal>y</literal>.</para>
6494
6495 <para>gtk_fixed_move() allows the specified widget to be moved to a new
6496 position.</para>
6497
6498 <programlisting role="C">
6499 void gtk_fixed_set_has_window( GtkFixed  *fixed,
6500                                gboolean   has_window );
6501
6502 gboolean gtk_fixed_get_has_window( GtkFixed *fixed );
6503 </programlisting>
6504
6505 <para>Normally, Fixed widgets don't have their own X window. Since this is
6506 different from the behaviour of Fixed widgets in earlier releases of GTK, 
6507 the function gtk_fixed_set_has_window() allows the creation of Fixed widgets 
6508 <emphasis>with</emphasis> their own window. It has to be called before
6509 realizing the widget.</para>
6510
6511 <para>The following example illustrates how to use the Fixed Container.</para>
6512
6513 <para>
6514 <inlinemediaobject>
6515 <imageobject>
6516 <imagedata fileref="images/fixed.png" format="png">
6517 </imageobject>
6518 </inlinemediaobject>
6519 </para>
6520
6521 <programlisting role="C">
6522 <!-- example-start fixed fixed.c -->
6523
6524 #include &lt;gtk/gtk.h&gt;
6525
6526 /* I'm going to be lazy and use some global variables to
6527  * store the position of the widget within the fixed
6528  * container */
6529 gint x = 50;
6530 gint y = 50;
6531
6532 /* This callback function moves the button to a new position
6533  * in the Fixed container. */
6534 static void move_button( GtkWidget *widget,
6535                          GtkWidget *fixed )
6536 {
6537   x = (x + 30) % 300;
6538   y = (y + 50) % 300;
6539   gtk_fixed_move (GTK_FIXED (fixed), widget, x, y); 
6540 }
6541
6542 int main( int   argc,
6543           char *argv[] )
6544 {
6545   /* GtkWidget is the storage type for widgets */
6546   GtkWidget *window;
6547   GtkWidget *fixed;
6548   GtkWidget *button;
6549   gint i;
6550
6551   /* Initialise GTK */
6552   gtk_init (&amp;argc, &amp;argv);
6553     
6554   /* Create a new window */
6555   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6556   gtk_window_set_title (GTK_WINDOW (window), "Fixed Container");
6557
6558   /* Here we connect the "destroy" event to a signal handler */ 
6559   g_signal_connect (G_OBJECT (window), "destroy",
6560                     G_CALLBACK (gtk_main_quit), NULL);
6561  
6562   /* Sets the border width of the window. */
6563   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6564
6565   /* Create a Fixed Container */
6566   fixed = gtk_fixed_new ();
6567   gtk_container_add (GTK_CONTAINER (window), fixed);
6568   gtk_widget_show (fixed);
6569   
6570   for (i = 1 ; i &lt;= 3 ; i++) {
6571     /* Creates a new button with the label "Press me" */
6572     button = gtk_button_new_with_label ("Press me");
6573   
6574     /* When the button receives the "clicked" signal, it will call the
6575      * function move_button() passing it the Fixed Container as its
6576      * argument. */
6577     g_signal_connect (G_OBJECT (button), "clicked",
6578                       G_CALLBACK (move_button), (gpointer) fixed);
6579   
6580     /* This packs the button into the fixed containers window. */
6581     gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
6582   
6583     /* The final step is to display this newly created widget. */
6584     gtk_widget_show (button);
6585   }
6586
6587   /* Display the window */
6588   gtk_widget_show (window);
6589     
6590   /* Enter the event loop */
6591   gtk_main ();
6592     
6593   return 0;
6594 }
6595 <!-- example-end -->
6596 </programlisting>
6597
6598 </sect1>
6599
6600 <!-- ----------------------------------------------------------------- -->
6601 <sect1 id="sec-LayoutContainer">
6602 <title>Layout Container</title>
6603
6604 <para>The Layout container is similar to the Fixed container except that it
6605 implements an infinite (where infinity is less than 2^32) scrolling
6606 area. The X window system has a limitation where windows can be at
6607 most 32767 pixels wide or tall. The Layout container gets around this
6608 limitation by doing some exotic stuff using window and bit gravities,
6609 so that you can have smooth scrolling even when you have many child
6610 widgets in your scrolling area.</para>
6611
6612 <para>A Layout container is created using:</para>
6613
6614 <programlisting role="C">
6615 GtkWidget *gtk_layout_new( GtkAdjustment *hadjustment,
6616                            GtkAdjustment *vadjustment );
6617 </programlisting>
6618
6619 <para>As you can see, you can optionally specify the Adjustment objects that
6620 the Layout widget will use for its scrolling.</para>
6621
6622 <para>You can add and move widgets in the Layout container using the
6623 following two functions:</para>
6624
6625 <programlisting role="C">
6626 void gtk_layout_put( GtkLayout *layout,
6627                      GtkWidget *widget,
6628                      gint       x,
6629                      gint       y );
6630
6631 void gtk_layout_move( GtkLayout *layout,
6632                       GtkWidget *widget,
6633                       gint       x,
6634                       gint       y );
6635 </programlisting>
6636
6637 <para>The size of the Layout container can be set using the next function:</para>
6638
6639 <programlisting role="C">
6640 void gtk_layout_set_size( GtkLayout *layout,
6641                           guint      width,
6642                           guint      height );
6643 </programlisting>
6644
6645 <para>The final four functions for use with Layout widgets are for
6646 manipulating the horizontal and vertical adjustment widgets:</para>
6647
6648 <programlisting role="C">
6649 GtkAdjustment* gtk_layout_get_hadjustment( GtkLayout *layout );
6650
6651 GtkAdjustment* gtk_layout_get_vadjustment( GtkLayout *layout );
6652
6653 void gtk_layout_set_hadjustment( GtkLayout     *layout,
6654                                  GtkAdjustment *adjustment );
6655
6656 void gtk_layout_set_vadjustment( GtkLayout     *layout,
6657                                  GtkAdjustment *adjustment);
6658 </programlisting>
6659
6660 </sect1>
6661
6662 <!-- ----------------------------------------------------------------- -->
6663 <sect1 id="sec-Frames">
6664 <title>Frames</title>
6665
6666 <para>Frames can be used to enclose one or a group of widgets with a box
6667 which can optionally be labelled. The position of the label and the
6668 style of the box can be altered to suit.</para>
6669
6670 <para>A Frame can be created with the following function:</para>
6671
6672 <programlisting role="C">
6673 GtkWidget *gtk_frame_new( const gchar *label );
6674 </programlisting>
6675
6676 <para>The label is by default placed in the upper left hand corner of the
6677 frame. A value of NULL for the <literal>label</literal> argument will result in no
6678 label being displayed. The text of the label can be changed using the
6679 next function.</para>
6680
6681 <programlisting role="C">
6682 void gtk_frame_set_label( GtkFrame    *frame,
6683                           const gchar *label );
6684 </programlisting>
6685
6686 <para>The position of the label can be changed using this function:</para>
6687
6688 <programlisting role="C">
6689 void gtk_frame_set_label_align( GtkFrame *frame,
6690                                 gfloat    xalign,
6691                                 gfloat    yalign );
6692 </programlisting>
6693
6694 <para><literal>xalign</literal> and <literal>yalign</literal> take values between 0.0 and 1.0. <literal>xalign</literal>
6695 indicates the position of the label along the top horizontal of the
6696 frame. <literal>yalign</literal> is not currently used. The default value of xalign
6697 is 0.0 which places the label at the left hand end of the frame.</para>
6698
6699 <para>The next function alters the style of the box that is used to outline
6700 the frame.</para>
6701
6702 <programlisting role="C">
6703 void gtk_frame_set_shadow_type( GtkFrame      *frame,
6704                                 GtkShadowType  type);
6705 </programlisting>
6706
6707 <para>The <literal>type</literal> argument can take one of the following values:</para>
6708 <programlisting role="C">
6709   GTK_SHADOW_NONE
6710   GTK_SHADOW_IN
6711   GTK_SHADOW_OUT
6712   GTK_SHADOW_ETCHED_IN (the default)
6713   GTK_SHADOW_ETCHED_OUT
6714 </programlisting>
6715
6716 <para>The following code example illustrates the use of the Frame widget.</para>
6717
6718 <para>
6719 <inlinemediaobject>
6720 <imageobject>
6721 <imagedata fileref="images/frame.png" format="png">
6722 </imageobject>
6723 </inlinemediaobject>
6724 </para>
6725
6726 <programlisting role="C">
6727 <!-- example-start frame frame.c -->
6728
6729 #include &lt;gtk/gtk.h&gt;
6730
6731 int main( int   argc,
6732           char *argv[] )
6733 {
6734   /* GtkWidget is the storage type for widgets */
6735   GtkWidget *window;
6736   GtkWidget *frame;
6737
6738   /* Initialise GTK */
6739   gtk_init (&amp;argc, &amp;argv);
6740     
6741   /* Create a new window */
6742   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6743   gtk_window_set_title (GTK_WINDOW (window), "Frame Example");
6744
6745   /* Here we connect the "destroy" event to a signal handler */ 
6746   g_signal_connect (G_OBJECT (window), "destroy",
6747                     G_CALLBACK (gtk_main_quit), NULL);
6748
6749   gtk_widget_set_size_request (window, 300, 300);
6750   /* Sets the border width of the window. */
6751   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6752
6753   /* Create a Frame */
6754   frame = gtk_frame_new (NULL);
6755   gtk_container_add (GTK_CONTAINER (window), frame);
6756
6757   /* Set the frame's label */
6758   gtk_frame_set_label (GTK_FRAME (frame), "GTK Frame Widget");
6759
6760   /* Align the label at the right of the frame */
6761   gtk_frame_set_label_align (GTK_FRAME (frame), 1.0, 0.0);
6762
6763   /* Set the style of the frame */
6764   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);
6765
6766   gtk_widget_show (frame);
6767   
6768   /* Display the window */
6769   gtk_widget_show (window);
6770     
6771   /* Enter the event loop */
6772   gtk_main ();
6773     
6774   return 0;
6775 }
6776 <!-- example-end -->
6777 </programlisting>
6778 </sect1>
6779
6780 <!-- ----------------------------------------------------------------- -->   
6781 <sect1 id="sec-AspectFrames">
6782 <title>Aspect Frames</title>
6783
6784 <para>The aspect frame widget is like a frame widget, except that it also
6785 enforces the aspect ratio (that is, the ratio of the width to the
6786 height) of the child widget to have a certain value, adding extra
6787 space if necessary. This is useful, for instance, if you want to
6788 preview a larger image. The size of the preview should vary when the
6789 user resizes the window, but the aspect ratio needs to always match
6790 the original image.</para>
6791   
6792 <para>To create a new aspect frame use:</para>
6793
6794 <programlisting role="C">
6795 GtkWidget *gtk_aspect_frame_new( const gchar *label,
6796                                  gfloat       xalign,
6797                                  gfloat       yalign,
6798                                  gfloat       ratio,
6799                                  gboolean     obey_child);
6800 </programlisting>
6801    
6802 <para><literal>xalign</literal> and <literal>yalign</literal> specify alignment as with Alignment
6803 widgets. If <literal>obey_child</literal> is TRUE, the aspect ratio of a child
6804 widget will match the aspect ratio of the ideal size it requests.
6805 Otherwise, it is given by <literal>ratio</literal>.</para>
6806    
6807 <para>To change the options of an existing aspect frame, you can use:</para>
6808
6809 <programlisting role="C">
6810 void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
6811                            gfloat          xalign,
6812                            gfloat          yalign,
6813                            gfloat          ratio,
6814                            gboolean        obey_child);
6815 </programlisting>
6816    
6817 <para>As an example, the following program uses an AspectFrame to present a
6818 drawing area whose aspect ratio will always be 2:1, no matter how the
6819 user resizes the top-level window.</para>
6820
6821 <para>
6822 <inlinemediaobject>
6823 <imageobject>
6824 <imagedata fileref="images/aspectframe.png" format="png">
6825 </imageobject>
6826 </inlinemediaobject>
6827 </para>
6828
6829 <programlisting role="C">
6830 <!-- example-start aspectframe aspectframe.c -->
6831
6832 #include &lt;gtk/gtk.h&gt;
6833    
6834 int main( int argc,
6835           char *argv[] )
6836 {
6837     GtkWidget *window;
6838     GtkWidget *aspect_frame;
6839     GtkWidget *drawing_area;
6840     gtk_init (&amp;argc, &amp;argv);
6841    
6842     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6843     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
6844     g_signal_connect (G_OBJECT (window), "destroy",
6845                       G_CALLBACK (gtk_main_quit), NULL);
6846     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6847    
6848     /* Create an aspect_frame and add it to our toplevel window */
6849    
6850     aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
6851                                          0.5, /* center x */
6852                                          0.5, /* center y */
6853                                          2, /* xsize/ysize = 2 */
6854                                          FALSE /* ignore child's aspect */);
6855    
6856     gtk_container_add (GTK_CONTAINER (window), aspect_frame);
6857     gtk_widget_show (aspect_frame);
6858    
6859     /* Now add a child widget to the aspect frame */
6860    
6861     drawing_area = gtk_drawing_area_new ();
6862    
6863     /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
6864      * window since we are forcing a 2x1 aspect ratio */
6865     gtk_widget_set_size_request (drawing_area, 200, 200);
6866     gtk_container_add (GTK_CONTAINER (aspect_frame), drawing_area);
6867     gtk_widget_show (drawing_area);
6868    
6869     gtk_widget_show (window);
6870     gtk_main ();
6871     return 0;
6872 }
6873 <!-- example-end -->
6874 </programlisting>
6875
6876 </sect1>
6877
6878 <!-- ----------------------------------------------------------------- -->   
6879 <sect1 id="sec-PanedWindowWidgets">
6880 <title>Paned Window Widgets</title>
6881
6882 <para>The paned window widgets are useful when you want to divide an area
6883 into two parts, with the relative size of the two parts controlled by
6884 the user. A groove is drawn between the two portions with a handle
6885 that the user can drag to change the ratio. The division can either be
6886 horizontal (HPaned) or vertical (VPaned).</para>
6887    
6888 <para>To create a new paned window, call one of:</para>
6889
6890 <programlisting role="C">
6891 GtkWidget *gtk_hpaned_new (void);
6892
6893 GtkWidget *gtk_vpaned_new (void);
6894 </programlisting>
6895
6896 <para>After creating the paned window widget, you need to add child widgets
6897 to its two halves. To do this, use the functions:</para>
6898
6899 <programlisting role="C">
6900 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
6901
6902 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
6903 </programlisting>
6904
6905 <para><literal>gtk_paned_add1()</literal> adds the child widget to the left or top half of
6906 the paned window. <literal>gtk_paned_add2()</literal> adds the child widget to the
6907 right or bottom half of the paned window.</para>
6908
6909 <para>As an example, we will create part of the user interface of an
6910 imaginary email program. A window is divided into two portions
6911 vertically, with the top portion being a list of email messages and
6912 the bottom portion the text of the email message. Most of the program
6913 is pretty straightforward. A couple of points to note: text can't be
6914 added to a Text widget until it is realized. This could be done by
6915 calling gtk_widget_realize(), but as a demonstration of an
6916 alternate technique, we connect a handler to the "realize" signal to
6917 add the text. Also, we need to add the <literal>GTK_SHRINK</literal> option to some
6918 of the items in the table containing the text window and its
6919 scrollbars, so that when the bottom portion is made smaller, the
6920 correct portions shrink instead of being pushed off the bottom of the
6921 window.</para>
6922
6923 <para>
6924 <inlinemediaobject>
6925 <imageobject>
6926 <imagedata fileref="images/paned.png" format="png">
6927 </imageobject>
6928 </inlinemediaobject>
6929 </para>
6930
6931 <programlisting role="C">
6932 <!-- example-start paned paned.c -->
6933
6934 #include &lt;stdio.h&gt;
6935 #include &lt;gtk/gtk.h&gt;
6936    
6937 /* Create the list of "messages" */
6938 static GtkWidget *create_list( void )
6939 {
6940
6941     GtkWidget *scrolled_window;
6942     GtkWidget *tree_view;
6943     GtkListStore *model;
6944     GtkTreeIter iter;
6945     GtkCellRenderer *cell;
6946     GtkTreeViewColumn *column;
6947
6948     int i;
6949    
6950     /* Create a new scrolled window, with scrollbars only if needed */
6951     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6952     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6953                                     GTK_POLICY_AUTOMATIC, 
6954                                     GTK_POLICY_AUTOMATIC);
6955    
6956     model = gtk_list_store_new (1, G_TYPE_STRING);
6957     tree_view = gtk_tree_view_new ();
6958     gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), 
6959                                            tree_view);
6960     gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (model));
6961     gtk_widget_show (tree_view);
6962    
6963     /* Add some messages to the window */
6964     for (i = 0; i &lt; 10; i++) {
6965         gchar *msg = g_strdup_printf ("Message #%d", i);
6966         gtk_list_store_append (GTK_LIST_STORE (model), &amp;iter);
6967         gtk_list_store_set (GTK_LIST_STORE (model), 
6968                             &amp;iter,
6969                             0, msg,
6970                             -1);
6971         g_free (msg);
6972     }
6973    
6974     cell = gtk_cell_renderer_text_new ();
6975
6976     column = gtk_tree_view_column_new_with_attributes ("Messages",
6977                                                        cell,
6978                                                        "text", 0,
6979                                                        NULL);
6980   
6981     gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
6982                                  GTK_TREE_VIEW_COLUMN (column));
6983
6984     return scrolled_window;
6985 }
6986    
6987 /* Add some text to our text widget - this is a callback that is invoked
6988 when our window is realized. We could also force our window to be
6989 realized with gtk_widget_realize, but it would have to be part of
6990 a hierarchy first */
6991
6992 static void insert_text( GtkTextBuffer *buffer )
6993 {
6994    GtkTextIter iter;
6995  
6996    gtk_text_buffer_get_iter_at_offset (buffer, &amp;iter, 0);
6997
6998    gtk_text_buffer_insert (buffer, &amp;iter,   
6999     "From: pathfinder@nasa.gov\n"
7000     "To: mom@nasa.gov\n"
7001     "Subject: Made it!\n"
7002     "\n"
7003     "We just got in this morning. The weather has been\n"
7004     "great - clear but cold, and there are lots of fun sights.\n"
7005     "Sojourner says hi. See you soon.\n"
7006     " -Path\n", -1);
7007 }
7008    
7009 /* Create a scrolled text area that displays a "message" */
7010 static GtkWidget *create_text( void )
7011 {
7012    GtkWidget *scrolled_window;
7013    GtkWidget *view;
7014    GtkTextBuffer *buffer;
7015
7016    view = gtk_text_view_new ();
7017    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
7018
7019    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
7020    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
7021                                    GTK_POLICY_AUTOMATIC,
7022                                    GTK_POLICY_AUTOMATIC);
7023
7024    gtk_container_add (GTK_CONTAINER (scrolled_window), view);
7025    insert_text (buffer);
7026
7027    gtk_widget_show_all (scrolled_window);
7028
7029    return scrolled_window;
7030 }
7031    
7032 int main( int   argc,
7033           char *argv[] )
7034 {
7035     GtkWidget *window;
7036     GtkWidget *vpaned;
7037     GtkWidget *list;
7038     GtkWidget *text;
7039
7040     gtk_init (&amp;argc, &amp;argv);
7041    
7042     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7043     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
7044     g_signal_connect (G_OBJECT (window), "destroy",
7045                       G_CALLBACK (gtk_main_quit), NULL);
7046     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7047     gtk_widget_set_size_request (GTK_WIDGET (window), 450, 400);
7048
7049     /* create a vpaned widget and add it to our toplevel window */
7050    
7051     vpaned = gtk_vpaned_new ();
7052     gtk_container_add (GTK_CONTAINER (window), vpaned);
7053     gtk_widget_show (vpaned);
7054    
7055     /* Now create the contents of the two halves of the window */
7056    
7057     list = create_list ();
7058     gtk_paned_add1 (GTK_PANED (vpaned), list);
7059     gtk_widget_show (list);
7060    
7061     text = create_text ();
7062     gtk_paned_add2 (GTK_PANED (vpaned), text);
7063     gtk_widget_show (text);
7064     gtk_widget_show (window);
7065
7066     gtk_main ();
7067
7068     return 0;
7069 }
7070 <!-- example-end -->
7071 </programlisting>
7072
7073 </sect1>
7074
7075 <!-- ----------------------------------------------------------------- -->
7076 <sect1 id="sec-Viewports">
7077 <title>Viewports</title>
7078
7079 <para>It is unlikely that you will ever need to use the Viewport widget
7080 directly. You are much more likely to use the
7081 <link linkend="sec-ScrolledWindows">Scrolled Window</link> widget which
7082 itself uses the Viewport.</para>
7083
7084 <para>A viewport widget allows you to place a larger widget within it such
7085 that you can view a part of it at a time. It uses
7086 <link linkend="ch-Adjustments">Adjustments</link> to define the area that
7087 is currently in view.</para>
7088
7089 <para>A Viewport is created with the function</para>
7090
7091 <programlisting role="C">
7092 GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment,
7093                              GtkAdjustment *vadjustment );
7094 </programlisting>
7095
7096 <para>As you can see you can specify the horizontal and vertical Adjustments
7097 that the widget is to use when you create the widget. It will create
7098 its own if you pass NULL as the value of the arguments.</para>
7099
7100 <para>You can get and set the adjustments after the widget has been created
7101 using the following four functions:</para>
7102
7103 <programlisting role="C">
7104 GtkAdjustment *gtk_viewport_get_hadjustment( GtkViewport *viewport );
7105
7106 GtkAdjustment *gtk_viewport_get_vadjustment( GtkViewport *viewport );
7107
7108 void gtk_viewport_set_hadjustment( GtkViewport   *viewport,
7109                                    GtkAdjustment *adjustment );
7110
7111 void gtk_viewport_set_vadjustment( GtkViewport   *viewport,
7112                                    GtkAdjustment *adjustment );
7113 </programlisting>
7114
7115 <para>The only other viewport function is used to alter its appearance:</para>
7116
7117 <programlisting role="C">
7118 void gtk_viewport_set_shadow_type( GtkViewport   *viewport,
7119                                    GtkShadowType  type );
7120 </programlisting>
7121
7122 <para>Possible values for the <literal>type</literal> parameter are:</para>
7123 <programlisting role="C">
7124   GTK_SHADOW_NONE,
7125   GTK_SHADOW_IN,
7126   GTK_SHADOW_OUT,
7127   GTK_SHADOW_ETCHED_IN,
7128   GTK_SHADOW_ETCHED_OUT
7129 </programlisting>
7130  
7131 </sect1>
7132
7133 <!-- ----------------------------------------------------------------- -->
7134 <sect1 id="sec-ScrolledWindows"
7135 <title>Scrolled Windows</title>
7136
7137 <para>Scrolled windows are used to create a scrollable area with another
7138 widget inside it. You may insert any type of widget into a scrolled
7139 window, and it will be accessible regardless of the size by using the
7140 scrollbars.</para>
7141
7142 <para>The following function is used to create a new scrolled window.</para>
7143
7144 <programlisting role="C">
7145 GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
7146                                     GtkAdjustment *vadjustment );
7147 </programlisting>
7148
7149 <para>Where the first argument is the adjustment for the horizontal
7150 direction, and the second, the adjustment for the vertical direction.
7151 These are almost always set to NULL.</para>
7152
7153 <programlisting role="C">
7154 void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
7155                                      GtkPolicyType      hscrollbar_policy,
7156                                      GtkPolicyType      vscrollbar_policy );
7157 </programlisting>
7158
7159 <para>This sets the policy to be used with respect to the scrollbars.
7160 The first argument is the scrolled window you wish to change. The second
7161 sets the policy for the horizontal scrollbar, and the third the policy for 
7162 the vertical scrollbar.</para>
7163
7164 <para>The policy may be one of <literal>GTK_POLICY_AUTOMATIC</literal> or
7165 <literal>GTK_POLICY_ALWAYS</literal>. <literal>GTK_POLICY_AUTOMATIC</literal> will automatically
7166 decide whether you need scrollbars, whereas <literal>GTK_POLICY_ALWAYS</literal>
7167 will always leave the scrollbars there.</para>
7168
7169 <para>You can then place your object into the scrolled window using the
7170 following function.</para>
7171
7172 <programlisting role="C">
7173 void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
7174                                             GtkWidget         *child);
7175 </programlisting>
7176
7177 <para>Here is a simple example that packs a table with 100 toggle buttons
7178 into a scrolled window. I've only commented on the parts that may be
7179 new to you.</para>
7180
7181 <para>
7182 <inlinemediaobject>
7183 <imageobject>
7184 <imagedata fileref="images/scrolledwin.png" format="png">
7185 </imageobject>
7186 </inlinemediaobject>
7187 </para>
7188
7189 <programlisting role="C">
7190 <!-- example-start scrolledwin scrolledwin.c -->
7191
7192 #include &lt;stdio.h&gt;
7193 #include &lt;gtk/gtk.h&gt;
7194
7195 static void destroy( GtkWidget *widget,
7196                      gpointer   data )
7197 {
7198     gtk_main_quit ();
7199 }
7200
7201 int main( int   argc,
7202           char *argv[] )
7203 {
7204     static GtkWidget *window;
7205     GtkWidget *scrolled_window;
7206     GtkWidget *table;
7207     GtkWidget *button;
7208     char buffer[32];
7209     int i, j;
7210     
7211     gtk_init (&amp;argc, &amp;argv);
7212     
7213     /* Create a new dialog window for the scrolled window to be
7214      * packed into.  */
7215     window = gtk_dialog_new ();
7216     g_signal_connect (G_OBJECT (window), "destroy",
7217                       G_CALLBACK (destroy), NULL);
7218     gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
7219     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7220     gtk_widget_set_size_request (window, 300, 300);
7221     
7222     /* create a new scrolled window. */
7223     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
7224     
7225     gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
7226     
7227     /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
7228      * GTK_POLICY_AUTOMATIC will automatically decide whether you need
7229      * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
7230      * there.  The first one is the horizontal scrollbar, the second, 
7231      * the vertical. */
7232     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
7233                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
7234     /* The dialog window is created with a vbox packed into it. */                                                              
7235     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)-&gt;vbox), scrolled_window, 
7236                         TRUE, TRUE, 0);
7237     gtk_widget_show (scrolled_window);
7238     
7239     /* create a table of 10 by 10 squares. */
7240     table = gtk_table_new (10, 10, FALSE);
7241     
7242     /* set the spacing to 10 on x and 10 on y */
7243     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
7244     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
7245     
7246     /* pack the table into the scrolled window */
7247     gtk_scrolled_window_add_with_viewport (
7248                    GTK_SCROLLED_WINDOW (scrolled_window), table);
7249     gtk_widget_show (table);
7250     
7251     /* this simply creates a grid of toggle buttons on the table
7252      * to demonstrate the scrolled window. */
7253     for (i = 0; i &lt; 10; i++)
7254        for (j = 0; j &lt; 10; j++) {
7255           sprintf (buffer, "button (%d,%d)\n", i, j);
7256           button = gtk_toggle_button_new_with_label (buffer);
7257           gtk_table_attach_defaults (GTK_TABLE (table), button,
7258                                      i, i+1, j, j+1);
7259           gtk_widget_show (button);
7260        }
7261     
7262     /* Add a "close" button to the bottom of the dialog */
7263     button = gtk_button_new_with_label ("close");
7264     g_signal_connect_swapped (G_OBJECT (button), "clicked",
7265                               G_CALLBACK (gtk_widget_destroy),
7266                               G_OBJECT (window));
7267     
7268     /* this makes it so the button is the default. */
7269     
7270     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
7271     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)-&gt;action_area), button, TRUE, TRUE, 0);
7272     
7273     /* This grabs this button to be the default button. Simply hitting
7274      * the "Enter" key will cause this button to activate. */
7275     gtk_widget_grab_default (button);
7276     gtk_widget_show (button);
7277     
7278     gtk_widget_show (window);
7279     
7280     gtk_main();
7281     
7282     return 0;
7283 }
7284 <!-- example-end -->
7285 </programlisting>
7286
7287 <para>Try playing with resizing the window. You'll notice how the scrollbars
7288 react. You may also wish to use the gtk_widget_set_size_request() call to set
7289 the default size of the window or other widgets.</para>
7290
7291 </sect1>
7292
7293 <!-- ----------------------------------------------------------------- -->   
7294 <sect1 id="sec-ButtonBoxes">
7295 <title>Button Boxes</title>
7296
7297 <para>Button Boxes are a convenient way to quickly layout a group of
7298 buttons. They come in both horizontal and vertical flavours. You
7299 create a new Button Box with one of the following calls, which create
7300 a horizontal or vertical box, respectively:</para>
7301
7302 <programlisting role="C">
7303 GtkWidget *gtk_hbutton_box_new( void );
7304
7305 GtkWidget *gtk_vbutton_box_new( void );
7306 </programlisting>
7307
7308 <para>Buttons are added to a Button Box using the usual function:</para>
7309
7310 <programlisting role="C">
7311     gtk_container_add (GTK_CONTAINER (button_box), child_widget);
7312 </programlisting>
7313
7314 <para>Here's an example that illustrates all the different layout settings
7315 for Button Boxes.</para>
7316
7317 <para>
7318 <inlinemediaobject>
7319 <imageobject>
7320 <imagedata fileref="images/buttonbox.png" format="png">
7321 </imageobject>
7322 </inlinemediaobject>
7323 </para>
7324
7325 <programlisting role="C">
7326 <!-- example-start buttonbox buttonbox.c -->
7327
7328 #include &lt;gtk/gtk.h&gt;
7329
7330 /* Create a Button Box with the specified parameters */
7331 static GtkWidget *create_bbox( gint  horizontal,
7332                                char *title,
7333                                gint  spacing,
7334                                gint  child_w,
7335                                gint  child_h,
7336                                gint  layout )
7337 {
7338   GtkWidget *frame;
7339   GtkWidget *bbox;
7340   GtkWidget *button;
7341
7342   frame = gtk_frame_new (title);
7343
7344   if (horizontal)
7345     bbox = gtk_hbutton_box_new ();
7346   else
7347     bbox = gtk_vbutton_box_new ();
7348
7349   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
7350   gtk_container_add (GTK_CONTAINER (frame), bbox);
7351
7352   /* Set the appearance of the Button Box */
7353   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
7354   gtk_box_set_spacing (GTK_BOX (bbox), spacing);
7355   /*gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);*/
7356
7357   button = gtk_button_new_from_stock (GTK_STOCK_OK);
7358   gtk_container_add (GTK_CONTAINER (bbox), button);
7359
7360   button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
7361   gtk_container_add (GTK_CONTAINER (bbox), button);
7362
7363   button = gtk_button_new_from_stock (GTK_STOCK_HELP);
7364   gtk_container_add (GTK_CONTAINER (bbox), button);
7365
7366   return frame;
7367 }
7368
7369 int main( int   argc,
7370           char *argv[] )
7371 {
7372   static GtkWidget* window = NULL;
7373   GtkWidget *main_vbox;
7374   GtkWidget *vbox;
7375   GtkWidget *hbox;
7376   GtkWidget *frame_horz;
7377   GtkWidget *frame_vert;
7378
7379   /* Initialize GTK */
7380   gtk_init (&amp;argc, &amp;argv);
7381
7382   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7383   gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
7384
7385   g_signal_connect (G_OBJECT (window), "destroy",
7386                     G_CALLBACK (gtk_main_quit),
7387                     NULL);
7388
7389   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7390
7391   main_vbox = gtk_vbox_new (FALSE, 0);
7392   gtk_container_add (GTK_CONTAINER (window), main_vbox);
7393
7394   frame_horz = gtk_frame_new ("Horizontal Button Boxes");
7395   gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
7396
7397   vbox = gtk_vbox_new (FALSE, 0);
7398   gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
7399   gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
7400
7401   gtk_box_pack_start (GTK_BOX (vbox),
7402            create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
7403                       TRUE, TRUE, 0);
7404
7405   gtk_box_pack_start (GTK_BOX (vbox),
7406            create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
7407                       TRUE, TRUE, 5);
7408
7409   gtk_box_pack_start (GTK_BOX (vbox),
7410            create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
7411                       TRUE, TRUE, 5);
7412
7413   gtk_box_pack_start (GTK_BOX (vbox),
7414            create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END),
7415                       TRUE, TRUE, 5);
7416
7417   frame_vert = gtk_frame_new ("Vertical Button Boxes");
7418   gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
7419
7420   hbox = gtk_hbox_new (FALSE, 0);
7421   gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
7422   gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
7423
7424   gtk_box_pack_start (GTK_BOX (hbox),
7425            create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD),
7426                       TRUE, TRUE, 0);
7427
7428   gtk_box_pack_start (GTK_BOX (hbox),
7429            create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
7430                       TRUE, TRUE, 5);
7431
7432   gtk_box_pack_start (GTK_BOX (hbox),
7433            create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
7434                       TRUE, TRUE, 5);
7435
7436   gtk_box_pack_start (GTK_BOX (hbox),
7437            create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END),
7438                       TRUE, TRUE, 5);
7439
7440   gtk_widget_show_all (window);
7441
7442   /* Enter the event loop */
7443   gtk_main ();
7444     
7445   return 0;
7446 }
7447 <!-- example-end -->
7448 </programlisting>
7449
7450 </sect1>
7451
7452 <!-- ----------------------------------------------------------------- -->   
7453 <sect1 id="sec-Toolbar">
7454 <title>Toolbar</title>
7455
7456 <para>Toolbars are usually used to group some number of widgets in order to
7457 simplify customization of their look and layout. Typically a toolbar
7458 consists of buttons with icons, labels and tooltips, but any other
7459 widget can also be put inside a toolbar. Finally, items can be
7460 arranged horizontally or vertically and buttons can be displayed with
7461 icons, labels, or both.</para>
7462
7463 <para>Creating a toolbar is (as one may already suspect) done with the
7464 following function:</para>
7465
7466 <programlisting role="C">
7467 GtkWidget *gtk_toolbar_new( void );
7468 </programlisting>
7469
7470 <para>After creating a toolbar one can append, prepend and insert items
7471 (that means simple text strings) or elements (that means any widget
7472 types) into the toolbar. To describe an item we need a label text, a
7473 tooltip text, a private tooltip text, an icon for the button and a
7474 callback function for it. For example, to append or prepend an item
7475 you may use the following functions:</para>
7476
7477 <programlisting role="C">
7478 GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
7479                                     const char    *text,
7480                                     const char    *tooltip_text,
7481                                     const char    *tooltip_private_text,
7482                                     GtkWidget     *icon,
7483                                     GtkSignalFunc  callback,
7484                                     gpointer       user_data );
7485
7486 GtkWidget *gtk_toolbar_prepend_item( GtkToolbar    *toolbar,
7487                                      const char    *text,
7488                                      const char    *tooltip_text,
7489                                      const char    *tooltip_private_text,
7490                                      GtkWidget     *icon,
7491                                      GtkSignalFunc  callback,
7492                                      gpointer       user_data );
7493 </programlisting>
7494
7495 <para>If you want to use gtk_toolbar_insert_item(), the only additional
7496 parameter which must be specified is the position in which the item
7497 should be inserted, thus:</para>
7498
7499 <programlisting role="C">
7500 GtkWidget *gtk_toolbar_insert_item( GtkToolbar    *toolbar,
7501                                     const char    *text,
7502                                     const char    *tooltip_text,
7503                                     const char    *tooltip_private_text,
7504                                     GtkWidget     *icon,
7505                                     GtkSignalFunc  callback,
7506                                     gpointer       user_data,
7507                                     gint           position );
7508 </programlisting>
7509
7510 <para>To simplify adding spaces between toolbar items, you may use the
7511 following functions:</para>
7512
7513 <programlisting role="C">
7514 void gtk_toolbar_append_space( GtkToolbar *toolbar );
7515
7516 void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
7517
7518 void gtk_toolbar_insert_space( GtkToolbar *toolbar,
7519                                gint        position );
7520 </programlisting>
7521
7522 <para>If it's required, the orientation of a toolbar and its style can be
7523 changed "on the fly" using the following functions:</para>
7524
7525 <programlisting role="C">
7526 void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
7527                                   GtkOrientation  orientation );
7528
7529 void gtk_toolbar_set_style( GtkToolbar      *toolbar,
7530                             GtkToolbarStyle  style );
7531
7532 void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
7533                                gint        enable );
7534 </programlisting>
7535
7536 <para>Where <literal>orientation</literal> is one of <literal>GTK_ORIENTATION_HORIZONTAL</literal> or
7537 <literal>GTK_ORIENTATION_VERTICAL</literal>. The <literal>style</literal> is used to set
7538 appearance of the toolbar items by using one of
7539 <literal>GTK_TOOLBAR_ICONS</literal>, <literal>GTK_TOOLBAR_TEXT</literal>, or
7540 <literal>GTK_TOOLBAR_BOTH</literal>.</para>
7541
7542 <para>To show some other things that can be done with a toolbar, let's take
7543 the following program (we'll interrupt the listing with some
7544 additional explanations):</para>
7545
7546 <programlisting role="C">
7547 #include &lt;gtk/gtk.h&gt;
7548
7549 /* This function is connected to the Close button or
7550  * closing the window from the WM */
7551 static gboolean delete_event( GtkWidget *widget,
7552                               GdkEvent *event,
7553                               gpointer data )
7554 {
7555   gtk_main_quit ();
7556   return FALSE;
7557 }
7558 </programlisting>
7559
7560 <para>The above beginning seems for sure familiar to you if it's not your first
7561 GTK program. There is one additional thing though, we include a nice XPM
7562 picture to serve as an icon for all of the buttons.</para>
7563
7564 <programlisting role="C">
7565 GtkWidget* close_button; /* This button will emit signal to close
7566                           * application */
7567 GtkWidget* tooltips_button; /* to enable/disable tooltips */
7568 GtkWidget* text_button,
7569          * icon_button,
7570          * both_button; /* radio buttons for toolbar style */
7571 GtkWidget* entry; /* a text entry to show packing any widget into
7572                    * toolbar */
7573 </programlisting>
7574
7575 <para>In fact not all of the above widgets are needed here, but to make things
7576 clearer I put them all together.</para>
7577
7578 <programlisting role="C">
7579 /* that's easy... when one of the buttons is toggled, we just
7580  * check which one is active and set the style of the toolbar
7581  * accordingly
7582  * ATTENTION: our toolbar is passed as data to callback ! */
7583 static void radio_event( GtkWidget *widget,
7584                          gpointer data )
7585 {
7586   if (GTK_TOGGLE_BUTTON (text_button)->active) 
7587     gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_TEXT);
7588   else if (GTK_TOGGLE_BUTTON (icon_button)->active)
7589     gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_ICONS);
7590   else if (GTK_TOGGLE_BUTTON (both_button)->active)
7591     gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH);
7592 }
7593
7594 /* even easier, just check given toggle button and enable/disable 
7595  * tooltips */
7596 static void toggle_event( GtkWidget *widget,
7597                           gpointer   data )
7598 {
7599   gtk_toolbar_set_tooltips (GTK_TOOLBAR (data),
7600                             GTK_TOGGLE_BUTTON (widget)->active );
7601 }
7602 </programlisting>
7603
7604 <para>The above are just two callback functions that will be called when
7605 one of the buttons on a toolbar is pressed. You should already be
7606 familiar with things like this if you've already used toggle buttons (and
7607 radio buttons).</para>
7608
7609 <programlisting role="C">
7610 int main (int argc, char *argv[])
7611 {
7612   /* Here is our main window (a dialog) and a handle for the handlebox */
7613   GtkWidget* dialog;
7614   GtkWidget* handlebox;
7615
7616   /* Ok, we need a toolbar, an icon with a mask (one for all of 
7617      the buttons) and an icon widget to put this icon in (but 
7618      we'll create a separate widget for each button) */
7619   GtkWidget * toolbar;
7620   GtkWidget * iconw;
7621
7622   /* this is called in all GTK application. */
7623   gtk_init (&amp;argc, &amp;argv);
7624   
7625   /* create a new window with a given title, and nice size */
7626   dialog = gtk_dialog_new ();
7627   gtk_window_set_title (GTK_WINDOW (dialog), "GTKToolbar Tutorial");
7628   gtk_widget_set_size_request (GTK_WIDGET (dialog), 600, 300);
7629   GTK_WINDOW (dialog)->allow_shrink = TRUE;
7630
7631   /* typically we quit if someone tries to close us */
7632   g_signal_connect (G_OBJECT (dialog), "delete_event",
7633                     G_CALLBACK (delete_event), NULL);
7634
7635   /* we need to realize the window because we use pixmaps for 
7636    * items on the toolbar in the context of it */
7637   gtk_widget_realize (dialog);
7638
7639   /* to make it nice we'll put the toolbar into the handle box, 
7640    * so that it can be detached from the main window */
7641   handlebox = gtk_handle_box_new ();
7642   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
7643                       handlebox, FALSE, FALSE, 5);
7644 </programlisting>
7645
7646 <para>The above should be similar to any other GTK application. Just
7647 initialization of GTK, creating the window, etc. There is only one
7648 thing that probably needs some explanation: a handle box. A handle box
7649 is just another box that can be used to pack widgets in to. The
7650 difference between it and typical boxes is that it can be detached
7651 from a parent window (or, in fact, the handle box remains in the
7652 parent, but it is reduced to a very small rectangle, while all of its
7653 contents are reparented to a new freely floating window). It is
7654 usually nice to have a detachable toolbar, so these two widgets occur
7655 together quite often.</para>
7656
7657 <programlisting role="C">
7658   /* toolbar will be horizontal, with both icons and text, and
7659    * with 5pxl spaces between items and finally, 
7660    * we'll also put it into our handlebox */
7661   toolbar = gtk_toolbar_new ();
7662   gtk_toolbar_set_orientation (GTK_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
7663   gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH);
7664   gtk_container_set_border_width (GTK_CONTAINER (toolbar), 5);
7665   gtk_toolbar_set_space_size (GTK_TOOLBAR (toolbar), 5);
7666   gtk_container_add (GTK_CONTAINER (handlebox), toolbar);
7667 </programlisting>
7668
7669 <para>Well, what we do above is just a straightforward initialization of
7670 the toolbar widget.</para>
7671
7672 <programlisting role="C">
7673   /* our first item is &lt;close&gt; button */
7674   iconw = gtk_image_new_from_file ("gtk.xpm"); /* icon widget */
7675   close_button = 
7676     gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), /* our toolbar */
7677                              "Close",               /* button label */
7678                              "Closes this app",     /* this button's tooltip */
7679                              "Private",             /* tooltip private info */
7680                              iconw,                 /* icon widget */
7681                              GTK_SIGNAL_FUNC (delete_event), /* a signal */
7682                              NULL);
7683   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar)); /* space after item */
7684 </programlisting>
7685
7686 <para>In the above code you see the simplest case: adding a button to
7687 toolbar.  Just before appending a new item, we have to construct an
7688 image widget to serve as an icon for this item; this step will have
7689 to be repeated for each new item. Just after the item we also add a
7690 space, so the following items will not touch each other. As you see
7691 gtk_toolbar_append_item() returns a pointer to our newly created button
7692 widget, so that we can work with it in the normal way.</para>
7693
7694 <programlisting role="C">
7695   /* now, let's make our radio buttons group... */
7696   iconw = gtk_image_new_from_file ("gtk.xpm");
7697   icon_button = gtk_toolbar_append_element (
7698                     GTK_TOOLBAR (toolbar),
7699                     GTK_TOOLBAR_CHILD_RADIOBUTTON, /* a type of element */
7700                     NULL,                          /* pointer to widget */
7701                     "Icon",                        /* label */
7702                     "Only icons in toolbar",       /* tooltip */
7703                     "Private",                     /* tooltip private string */
7704                     iconw,                         /* icon */
7705                     GTK_SIGNAL_FUNC (radio_event), /* signal */
7706                     toolbar);                      /* data for signal */
7707   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
7708 </programlisting>
7709
7710 <para>Here we begin creating a radio buttons group. To do this we use
7711 gtk_toolbar_append_element.  In fact, using this function one can also
7712 +add simple items or even spaces (type = <literal>GTK_TOOLBAR_CHILD_SPACE</literal>
7713 or +<literal>GTK_TOOLBAR_CHILD_BUTTON</literal>). In the above case we start
7714 creating a radio group. In creating other radio buttons for this group
7715 a pointer to the previous button in the group is required, so that a
7716 list of buttons can be easily constructed (see the section on <link
7717 linkend="sec-RadioButtons">Radio Buttons</link> earlier in this
7718 tutorial).</para>
7719
7720 <programlisting role="C">
7721   /* following radio buttons refer to previous ones */
7722   iconw = gtk_image_new_from_file ("gtk.xpm");
7723   text_button = 
7724     gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
7725                                 GTK_TOOLBAR_CHILD_RADIOBUTTON,
7726                                 icon_button,
7727                                 "Text",
7728                                 "Only texts in toolbar",
7729                                 "Private",
7730                                 iconw,
7731                                 GTK_SIGNAL_FUNC (radio_event),
7732                                 toolbar);
7733   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
7734                                           
7735   iconw = gtk_image_new_from_file ("gtk.xpm");
7736   both_button = 
7737     gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
7738                                 GTK_TOOLBAR_CHILD_RADIOBUTTON,
7739                                 text_button,
7740                                 "Both",
7741                                 "Icons and text in toolbar",
7742                                 "Private",
7743                                 iconw,
7744                                 GTK_SIGNAL_FUNC (radio_event),
7745                                 toolbar);
7746   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
7747   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (both_button), TRUE);
7748 </programlisting>
7749
7750 <para>In the end we have to set the state of one of the buttons manually
7751 (otherwise they all stay in active state, preventing us from switching
7752 between them).</para>
7753
7754 <programlisting role="C">
7755   /* here we have just a simple toggle button */
7756   iconw = gtk_image_new_from_file ("gtk.xpm");
7757   tooltips_button = 
7758     gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
7759                                 GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
7760                                 NULL,
7761                                 "Tooltips",
7762                                 "Toolbar with or without tips",
7763                                 "Private",
7764                                 iconw,
7765                                 GTK_SIGNAL_FUNC (toggle_event),
7766                                 toolbar);
7767   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
7768   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tooltips_button), TRUE);
7769 </programlisting>
7770
7771 <para>A toggle button can be created in the obvious way (if one knows how to create
7772 radio buttons already).</para>
7773
7774 <programlisting role="C">
7775   /* to pack a widget into toolbar, we only have to 
7776    * create it and append it with an appropriate tooltip */
7777   entry = gtk_entry_new ();
7778   gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), 
7779                              entry, 
7780                              "This is just an entry", 
7781                              "Private");
7782
7783   /* well, it isn't created within the toolbar, so we must still show it */
7784   gtk_widget_show (entry);
7785 </programlisting>
7786
7787 <para>As you see, adding any kind of widget to a toolbar is simple. The
7788 one thing you have to remember is that this widget must be shown manually
7789 (contrary to other items which will be shown together with the toolbar).</para>
7790
7791 <programlisting role="C">
7792   /* that's it ! let's show everything. */
7793   gtk_widget_show (toolbar);
7794   gtk_widget_show (handlebox);
7795   gtk_widget_show (dialog);
7796
7797   /* rest in gtk_main and wait for the fun to begin! */
7798   gtk_main ();
7799   
7800   return 0;
7801 }
7802 </programlisting>
7803
7804 <para>So, here we are at the end of toolbar tutorial. Of course, to appreciate
7805 it in full you need also this nice XPM icon, so here it is:</para>
7806
7807 <programlisting role="C">
7808 /* XPM */
7809 static char * gtk_xpm[] = {
7810 "32 39 5 1",
7811 ".      c none",
7812 "+      c black",
7813 "@      c #3070E0",
7814 "#      c #F05050",
7815 "$      c #35E035",
7816 "................+...............",
7817 "..............+++++.............",
7818 "............+++++@@++...........",
7819 "..........+++++@@@@@@++.........",
7820 "........++++@@@@@@@@@@++........",
7821 "......++++@@++++++++@@@++.......",
7822 ".....+++@@@+++++++++++@@@++.....",
7823 "...+++@@@@+++@@@@@@++++@@@@+....",
7824 "..+++@@@@+++@@@@@@@@+++@@@@@++..",
7825 ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
7826 ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
7827 ".+##++@@@@+++@@@+++++@@@@@@@@$@.",
7828 ".+###++@@@@+++@@@+++@@@@@++$$$@.",
7829 ".+####+++@@@+++++++@@@@@+@$$$$@.",
7830 ".+#####+++@@@@+++@@@@++@$$$$$$+.",
7831 ".+######++++@@@@@@@++@$$$$$$$$+.",
7832 ".+#######+##+@@@@+++$$$$$$@@$$+.",
7833 ".+###+++##+##+@@++@$$$$$$++$$$+.",
7834 ".+###++++##+##+@@$$$$$$$@+@$$@+.",
7835 ".+###++++++#+++@$$@+@$$@++$$$@+.",
7836 ".+####+++++++#++$$@+@$$++$$$$+..",
7837 ".++####++++++#++$$@+@$++@$$$$+..",
7838 ".+#####+++++##++$$++@+++$$$$$+..",
7839 ".++####+++##+#++$$+++++@$$$$$+..",
7840 ".++####+++####++$$++++++@$$$@+..",
7841 ".+#####++#####++$$+++@++++@$@+..",
7842 ".+#####++#####++$$++@$$@+++$@@..",
7843 ".++####++#####++$$++$$$$$+@$@++.",
7844 ".++####++#####++$$++$$$$$$$$+++.",
7845 ".+++####+#####++$$++$$$$$$$@+++.",
7846 "..+++#########+@$$+@$$$$$$+++...",
7847 "...+++########+@$$$$$$$$@+++....",
7848 ".....+++######+@$$$$$$$+++......",
7849 "......+++#####+@$$$$$@++........",
7850 ".......+++####+@$$$$+++.........",
7851 ".........++###+$$$@++...........",
7852 "..........++##+$@+++............",
7853 "...........+++++++..............",
7854 ".............++++..............."};
7855 </programlisting>
7856
7857 </sect1>
7858
7859 <!-- ----------------------------------------------------------------- -->
7860 <sect1 id="sec-Notebooks">
7861 <title>Notebooks</title>
7862
7863 <para>The NoteBook Widget is a collection of "pages" that overlap each
7864 other, each page contains different information with only one page
7865 visible at a time. This widget has become more common lately in GUI
7866 programming, and it is a good way to show blocks of similar
7867 information that warrant separation in their display.</para>
7868
7869 <para>The first function call you will need to know, as you can probably
7870 guess by now, is used to create a new notebook widget.</para>
7871
7872 <programlisting role="C">
7873 GtkWidget *gtk_notebook_new( void );
7874 </programlisting>
7875
7876 <para>Once the notebook has been created, there are a number of functions
7877 that operate on the notebook widget. Let's look at them individually.</para>
7878
7879 <para>The first one we will look at is how to position the page indicators.
7880 These page indicators or "tabs" as they are referred to, can be
7881 positioned in four ways: top, bottom, left, or right.</para>
7882
7883 <programlisting role="C">
7884 void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
7885                                GtkPositionType  pos );
7886 </programlisting>
7887
7888 <para>GtkPositionType will be one of the following, which are pretty self
7889 explanatory:</para>
7890 <programlisting role="C">
7891   GTK_POS_LEFT
7892   GTK_POS_RIGHT
7893   GTK_POS_TOP
7894   GTK_POS_BOTTOM
7895 </programlisting>
7896
7897 <para><literal>GTK_POS_TOP</literal> is the default.</para>
7898
7899 <para>Next we will look at how to add pages to the notebook. There are three
7900 ways to add pages to the NoteBook. Let's look at the first two
7901 together as they are quite similar.</para>
7902
7903 <programlisting role="C">
7904 void gtk_notebook_append_page( GtkNotebook *notebook,
7905                                GtkWidget   *child,
7906                                GtkWidget   *tab_label );
7907
7908 void gtk_notebook_prepend_page( GtkNotebook *notebook,
7909                                 GtkWidget   *child,
7910                                 GtkWidget   *tab_label );
7911 </programlisting>
7912
7913 <para>These functions add pages to the notebook by inserting them from the
7914 back of the notebook (append), or the front of the notebook (prepend).
7915 <literal>child</literal> is the widget that is placed within the notebook page, and
7916 <literal>tab_label</literal> is the label for the page being added. The <literal>child</literal>
7917 widget must be created separately, and is typically a set of options
7918 setup witin one of the other container widgets, such as a table.</para>
7919
7920 <para>The final function for adding a page to the notebook contains all of
7921 the properties of the previous two, but it allows you to specify what
7922 position you want the page to be in the notebook.</para>
7923
7924 <programlisting role="C">
7925 void gtk_notebook_insert_page( GtkNotebook *notebook,
7926                                GtkWidget   *child,
7927                                GtkWidget   *tab_label,
7928                                gint         position );
7929 </programlisting>
7930
7931 <para>The parameters are the same as _append_ and _prepend_ except it
7932 contains an extra parameter, <literal>position</literal>.  This parameter is used to
7933 specify what place this page will be inserted into the first page
7934 having position zero.</para>
7935
7936 <para>Now that we know how to add a page, lets see how we can remove a page
7937 from the notebook.</para>
7938
7939 <programlisting role="C">
7940 void gtk_notebook_remove_page( GtkNotebook *notebook,
7941                                gint         page_num );
7942 </programlisting>
7943
7944 <para>This function takes the page specified by <literal>page_num</literal> and removes it
7945 from the widget pointed to by <literal>notebook</literal>.</para>
7946
7947 <para>To find out what the current page is in a notebook use the function:</para>
7948
7949 <programlisting role="C">
7950 gint gtk_notebook_get_current_page( GtkNotebook *notebook );
7951 </programlisting>
7952
7953 <para>These next two functions are simple calls to move the notebook page
7954 forward or backward. Simply provide the respective function call with
7955 the notebook widget you wish to operate on. Note: When the NoteBook is
7956 currently on the last page, and gtk_notebook_next_page() is called, the
7957 notebook will wrap back to the first page. Likewise, if the NoteBook
7958 is on the first page, and gtk_notebook_prev_page() is called, the
7959 notebook will wrap to the last page.</para>
7960
7961 <programlisting role="C">
7962 void gtk_notebook_next_page( GtkNoteBook *notebook );
7963
7964 void gtk_notebook_prev_page( GtkNoteBook *notebook );
7965 </programlisting>
7966
7967 <para>This next function sets the "active" page. If you wish the notebook to
7968 be opened to page 5 for example, you would use this function.  Without
7969 using this function, the notebook defaults to the first page.</para>
7970
7971 <programlisting role="C">
7972 void gtk_notebook_set_current_page( GtkNotebook *notebook,
7973                                     gint         page_num );
7974 </programlisting>
7975
7976 <para>The next two functions add or remove the notebook page tabs and the
7977 notebook border respectively.</para>
7978
7979 <programlisting role="C">
7980 void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
7981                                  gboolean     show_tabs );
7982
7983 void gtk_notebook_set_show_border( GtkNotebook *notebook,
7984                                    gboolean     show_border );
7985 </programlisting>
7986
7987 <para>The next function is useful when the you have a large number of pages,
7988 and the tabs don't fit on the page. It allows the tabs to be scrolled
7989 through using two arrow buttons.</para>
7990
7991 <programlisting role="C">
7992 void gtk_notebook_set_scrollable( GtkNotebook *notebook,
7993                                   gboolean     scrollable );
7994 </programlisting>
7995
7996 <para><literal>show_tabs</literal>, <literal>show_border</literal> and <literal>scrollable</literal> can be either
7997 TRUE or FALSE.</para>
7998
7999 <para>Now let's look at an example, it is expanded from the 
8000 <filename>testgtk.c</filename> code
8001 that comes with the GTK distribution. This small program creates a
8002 window with a notebook and six buttons. The notebook contains 11
8003 pages, added in three different ways, appended, inserted, and
8004 prepended. The buttons allow you rotate the tab positions, add/remove
8005 the tabs and border, remove a page, change pages in both a forward and
8006 backward manner, and exit the program.</para>
8007
8008 <para>
8009 <inlinemediaobject>
8010 <imageobject>
8011 <imagedata fileref="images/notebook.png" format="png">
8012 </imageobject>
8013 </inlinemediaobject>
8014 </para>
8015
8016 <programlisting role="C">
8017 <!-- example-start notebook notebook.c -->
8018
8019 #include &lt;stdio.h&gt;
8020 #include &lt;gtk/gtk.h&gt;
8021
8022 /* This function rotates the position of the tabs */
8023 static void rotate_book( GtkButton   *button,
8024                          GtkNotebook *notebook )
8025 {
8026     gtk_notebook_set_tab_pos (notebook, (notebook-&gt;tab_pos + 1) % 4);
8027 }
8028
8029 /* Add/Remove the page tabs and the borders */
8030 static void tabsborder_book( GtkButton   *button,
8031                              GtkNotebook *notebook )
8032 {
8033     gint tval = FALSE;
8034     gint bval = FALSE;
8035     if (notebook-&gt;show_tabs == 0)
8036             tval = TRUE; 
8037     if (notebook-&gt;show_border == 0)
8038             bval = TRUE;
8039     
8040     gtk_notebook_set_show_tabs (notebook, tval);
8041     gtk_notebook_set_show_border (notebook, bval);
8042 }
8043
8044 /* Remove a page from the notebook */
8045 static void remove_book( GtkButton   *button,
8046                          GtkNotebook *notebook )
8047 {
8048     gint page;
8049     
8050     page = gtk_notebook_get_current_page (notebook);
8051     gtk_notebook_remove_page (notebook, page);
8052     /* Need to refresh the widget -- 
8053      This forces the widget to redraw itself. */
8054     gtk_widget_queue_draw (GTK_WIDGET (notebook));
8055 }
8056
8057 static gboolean delete( GtkWidget *widget,
8058                         GtkWidget *event,
8059                         gpointer   data )
8060 {
8061     gtk_main_quit ();
8062     return FALSE;
8063 }
8064
8065 int main( int argc,
8066           char *argv[] )
8067 {
8068     GtkWidget *window;
8069     GtkWidget *button;
8070     GtkWidget *table;
8071     GtkWidget *notebook;
8072     GtkWidget *frame;
8073     GtkWidget *label;
8074     GtkWidget *checkbutton;
8075     int i;
8076     char bufferf[32];
8077     char bufferl[32];
8078     
8079     gtk_init (&amp;argc, &amp;argv);
8080     
8081     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8082     
8083     g_signal_connect (G_OBJECT (window), "delete_event",
8084                       G_CALLBACK (delete), NULL);
8085     
8086     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8087
8088     table = gtk_table_new (3, 6, FALSE);
8089     gtk_container_add (GTK_CONTAINER (window), table);
8090     
8091     /* Create a new notebook, place the position of the tabs */
8092     notebook = gtk_notebook_new ();
8093     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
8094     gtk_table_attach_defaults (GTK_TABLE (table), notebook, 0, 6, 0, 1);
8095     gtk_widget_show (notebook);
8096     
8097     /* Let's append a bunch of pages to the notebook */
8098     for (i = 0; i &lt; 5; i++) {
8099         sprintf(bufferf, "Append Frame %d", i + 1);
8100         sprintf(bufferl, "Page %d", i + 1);
8101         
8102         frame = gtk_frame_new (bufferf);
8103         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
8104         gtk_widget_set_size_request (frame, 100, 75);
8105         gtk_widget_show (frame);
8106         
8107         label = gtk_label_new (bufferf);
8108         gtk_container_add (GTK_CONTAINER (frame), label);
8109         gtk_widget_show (label);
8110         
8111         label = gtk_label_new (bufferl);
8112         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
8113     }
8114       
8115     /* Now let's add a page to a specific spot */
8116     checkbutton = gtk_check_button_new_with_label ("Check me please!");
8117     gtk_widget_set_size_request (checkbutton, 100, 75);
8118     gtk_widget_show (checkbutton);
8119    
8120     label = gtk_label_new ("Add page");
8121     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
8122     
8123     /* Now finally let's prepend pages to the notebook */
8124     for (i = 0; i &lt; 5; i++) {
8125         sprintf (bufferf, "Prepend Frame %d", i + 1);
8126         sprintf (bufferl, "PPage %d", i + 1);
8127         
8128         frame = gtk_frame_new (bufferf);
8129         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
8130         gtk_widget_set_size_request (frame, 100, 75);
8131         gtk_widget_show (frame);
8132         
8133         label = gtk_label_new (bufferf);
8134         gtk_container_add (GTK_CONTAINER (frame), label);
8135         gtk_widget_show (label);
8136         
8137         label = gtk_label_new (bufferl);
8138         gtk_notebook_prepend_page (GTK_NOTEBOOK (notebook), frame, label);
8139     }
8140     
8141     /* Set what page to start at (page 4) */
8142     gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 3);
8143
8144     /* Create a bunch of buttons */
8145     button = gtk_button_new_with_label ("close");
8146     g_signal_connect_swapped (G_OBJECT (button), "clicked",
8147                               G_CALLBACK (delete), NULL);
8148     gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 1, 1, 2);
8149     gtk_widget_show (button);
8150     
8151     button = gtk_button_new_with_label ("next page");
8152     g_signal_connect_swapped (G_OBJECT (button), "clicked",
8153                               G_CALLBACK (gtk_notebook_next_page),
8154                               G_OBJECT (notebook));
8155     gtk_table_attach_defaults (GTK_TABLE (table), button, 1, 2, 1, 2);
8156     gtk_widget_show (button);
8157     
8158     button = gtk_button_new_with_label ("prev page");
8159     g_signal_connect_swapped (G_OBJECT (button), "clicked",
8160                               G_CALLBACK (gtk_notebook_prev_page),
8161                               G_OBJECT (notebook));
8162     gtk_table_attach_defaults (GTK_TABLE (table), button, 2, 3, 1, 2);
8163     gtk_widget_show (button);
8164     
8165     button = gtk_button_new_with_label ("tab position");
8166     g_signal_connect (G_OBJECT (button), "clicked",
8167                       G_CALLBACK (rotate_book),
8168                       (gpointer) notebook);
8169     gtk_table_attach_defaults (GTK_TABLE (table), button, 3, 4, 1, 2);
8170     gtk_widget_show (button);
8171     
8172     button = gtk_button_new_with_label ("tabs/border on/off");
8173     g_signal_connect (G_OBJECT (button), "clicked",
8174                       G_CALLBACK (tabsborder_book),
8175                       (gpointer) notebook);
8176     gtk_table_attach_defaults (GTK_TABLE (table), button, 4, 5, 1, 2);
8177     gtk_widget_show (button);
8178     
8179     button = gtk_button_new_with_label ("remove page");
8180     g_signal_connect (G_OBJECT (button), "clicked",
8181                       G_CALLBACK (remove_book),
8182                       (gpointer) notebook);
8183     gtk_table_attach_defaults (GTK_TABLE (table), button, 5, 6, 1, 2);
8184     gtk_widget_show (button);
8185     
8186     gtk_widget_show (table);
8187     gtk_widget_show (window);
8188     
8189     gtk_main ();
8190     
8191     return 0;
8192 }
8193 <!-- example-end -->
8194 </programlisting>
8195
8196 <para>I hope this helps you on your way with creating notebooks for your
8197 GTK applications.</para>
8198
8199 </sect1>
8200 </chapter>
8201
8202 <!-- ***************************************************************** -->
8203 <chapter id="ch-MenuWidget">
8204 <title>Menu Widget</title>
8205
8206 <para>There are two ways to create menus: there's the easy way, and there's
8207 the hard way. Both have their uses, but you can usually use the
8208 Itemfactory (the easy way). The "hard" way is to create all the menus
8209 using the calls directly. The easy way is to use the gtk_item_factory
8210 calls. This is much simpler, but there are advantages and
8211 disadvantages to each approach.</para>
8212
8213 <para>The Itemfactory is much easier to use, and to add new menus to,
8214 although writing a few wrapper functions to create menus using the
8215 manual method could go a long way towards usability. With the
8216 Itemfactory, it is not possible to add images or the character '/' to
8217 the menus.</para>
8218
8219 <!-- ----------------------------------------------------------------- -->
8220 <sect1 id="sec-ManualMenuCreation">
8221 <title>Manual Menu Creation</title>
8222
8223 <para>In the true tradition of teaching, we'll show you the hard way
8224 first. <literal>:)</literal></para>
8225
8226 <para>There are three widgets that go into making a menubar and submenus:</para>
8227
8228 <itemizedlist>
8229 <listitem><simpara>a menu item, which is what the user wants to select, e.g.,
8230 "Save"</simpara>
8231 </listitem>
8232 <listitem><simpara>a menu, which acts as a container for the menu items, and</simpara>
8233 </listitem>
8234 <listitem><simpara>a menubar, which is a container for each of the individual
8235 menus.</simpara>
8236 </listitem>
8237 </itemizedlist>
8238
8239 <para>This is slightly complicated by the fact that menu item widgets are
8240 used for two different things. They are both the widgets that are
8241 packed into the menu, and the widget that is packed into the menubar,
8242 which, when selected, activates the menu.</para>
8243
8244 <para>Let's look at the functions that are used to create menus and
8245 menubars.  This first function is used to create a new menubar.</para>
8246
8247 <programlisting role="C">
8248 GtkWidget *gtk_menu_bar_new( void );
8249 </programlisting>
8250
8251 <para>This rather self explanatory function creates a new menubar. You use
8252 gtk_container_add() to pack this into a window, or the box_pack
8253 functions to pack it into a box - the same as buttons.</para>
8254
8255 <programlisting role="C">
8256 GtkWidget *gtk_menu_new( void );
8257 </programlisting>
8258
8259 <para>This function returns a pointer to a new menu; it is never actually
8260 shown (with gtk_widget_show()), it is just a container for the menu
8261 items. I hope this will become more clear when you look at the
8262 example below.</para>
8263
8264 <para>The next three calls are used to create menu items that are packed into
8265 the menu (and menubar).</para>
8266
8267 <programlisting role="C">
8268 GtkWidget *gtk_menu_item_new( void );
8269
8270 GtkWidget *gtk_menu_item_new_with_label( const char *label );
8271
8272 GtkWidget *gtk_menu_item_new_with_mnemnonic( const char *label );
8273 </programlisting>
8274
8275 <para>These calls are used to create the menu items that are to be
8276 displayed.  Remember to differentiate between a "menu" as created with
8277 gtk_menu_new() and a "menu item" as created by the gtk_menu_item_new()
8278 functions. The menu item will be an actual button with an associated
8279 action, whereas a menu will be a container holding menu items.</para>
8280
8281 <para>The gtk_menu_item_new_with_label() and gtk_menu_item_new() functions are just as
8282 you'd expect after reading about the buttons. One creates a new menu
8283 item with a label already packed into it, and the other just creates a
8284 blank menu item.</para>
8285
8286 <para>Once you've created a menu item you have to put it into a menu. This
8287 is done using the function gtk_menu_shelll_append. In order to capture when
8288 the item is selected by the user, we need to connect to the
8289 <literal>activate</literal> signal in the usual way. So, if we wanted to create a
8290 standard <literal>File</literal> menu, with the options <literal>Open</literal>, <literal>Save</literal>, and
8291 <literal>Quit</literal>, the code would look something like:</para>
8292
8293 <programlisting role="C">
8294     file_menu = gtk_menu_new ();    /* Don't need to show menus */
8295
8296     /* Create the menu items */
8297     open_item = gtk_menu_item_new_with_label ("Open");
8298     save_item = gtk_menu_item_new_with_label ("Save");
8299     quit_item = gtk_menu_item_new_with_label ("Quit");
8300
8301     /* Add them to the menu */
8302     gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), open_item);
8303     gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), save_item);
8304     gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), quit_item);
8305
8306     /* Attach the callback functions to the activate signal */
8307     g_signal_connect_swapped (G_OBJECT (open_item), "activate",
8308                               G_CALLBACK (menuitem_response),
8309                               (gpointer) "file.open");
8310     g_signal_connect_swapped (G_OBJECT (save_item), "activate",
8311                               G_CALLBACK (menuitem_response),
8312                               (gpointer) "file.save");
8313
8314     /* We can attach the Quit menu item to our exit function */
8315     g_signal_connect_swapped (G_OBJECT (quit_item), "activate",
8316                               G_CALLBACK (destroy),
8317                               (gpointer) "file.quit");
8318
8319     /* We do need to show menu items */
8320     gtk_widget_show (open_item);
8321     gtk_widget_show (save_item);
8322     gtk_widget_show (quit_item);
8323 </programlisting>
8324
8325 <para>At this point we have our menu. Now we need to create a menubar and a
8326 menu item for the <literal>File</literal> entry, to which we add our menu. The code
8327 looks like this:</para>
8328
8329 <programlisting role="C">
8330     menu_bar = gtk_menu_bar_new ();
8331     gtk_container_add (GTK_CONTAINER (window), menu_bar);
8332     gtk_widget_show (menu_bar);
8333
8334     file_item = gtk_menu_item_new_with_label ("File");
8335     gtk_widget_show (file_item);
8336 </programlisting>
8337
8338 <para>Now we need to associate the menu with <literal>file_item</literal>. This is done
8339 with the function</para>
8340
8341 <programlisting role="C">
8342 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
8343                                 GtkWidget   *submenu );
8344 </programlisting>
8345
8346 <para>So, our example would continue with</para>
8347
8348 <programlisting role="C">
8349     gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_item), file_menu);
8350 </programlisting>
8351
8352 <para>All that is left to do is to add the menu to the menubar, which is
8353 accomplished using the function</para>
8354
8355 <programlisting role="C">
8356 void gtk_menu_bar_append( GtkMenuBar *menu_bar,
8357                           GtkWidget  *menu_item );
8358 </programlisting>
8359
8360 <para>which in our case looks like this:</para>
8361
8362 <programlisting role="C">
8363     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), file_item);
8364 </programlisting>
8365
8366 <para>If we wanted the menu right justified on the menubar, such as help
8367 menus often are, we can use the following function (again on
8368 <literal>file_item</literal> in the current example) before attaching it to the
8369 menubar.</para>
8370
8371 <programlisting role="C">
8372 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
8373 </programlisting>
8374
8375 <para>Here is a summary of the steps needed to create a menu bar with menus
8376 attached:</para>
8377
8378 <itemizedlist>
8379 <listitem><simpara> Create a new menu using gtk_menu_new()</simpara>
8380 </listitem>
8381
8382 <listitem><simpara> Use multiple calls to gtk_menu_item_new() for each item you
8383 wish to have on your menu. And use gtk_menu_shell_append() to put each of
8384 these new items on to the menu.</simpara>
8385 </listitem>
8386
8387 <listitem><simpara> Create a menu item using gtk_menu_item_new(). This will be the
8388 root of the menu, the text appearing here will be on the menubar
8389 itself.</simpara>
8390 </listitem>
8391
8392 <listitem><simpara>Use gtk_menu_item_set_submenu() to attach the menu to the root
8393 menu item (the one created in the above step).</simpara>
8394 </listitem>
8395
8396 <listitem><simpara> Create a new menubar using gtk_menu_bar_new. This step only
8397 needs to be done once when creating a series of menus on one menu bar.</simpara>
8398 </listitem>
8399
8400 <listitem><simpara> Use gtk_menu_bar_append() to put the root menu onto the menubar.</simpara>
8401 </listitem>
8402 </itemizedlist>
8403
8404 <para>Creating a popup menu is nearly the same. The difference is that the
8405 menu is not posted "automatically" by a menubar, but explicitly by
8406 calling the function gtk_menu_popup() from a button-press event, for
8407 example.  Take these steps:</para>
8408
8409 <itemizedlist>
8410 <listitem><simpara>Create an event handling function. It needs to have the
8411 prototype</simpara>
8412 <programlisting role="C">
8413 static gboolean handler( GtkWidget *widget,
8414                          GdkEvent  *event );
8415 </programlisting>
8416 <simpara>and it will use the event to find out where to pop up the menu.</simpara>
8417 </listitem>
8418
8419 <listitem><simpara>In the event handler, if the event is a mouse button press,
8420 treat <literal>event</literal> as a button event (which it is) and use it as
8421 shown in the sample code to pass information to gtk_menu_popup().</simpara>
8422 </listitem>
8423
8424 <listitem><simpara>Bind that event handler to a widget with</simpara>
8425 <programlisting role="C">
8426     g_signal_connect_swapped (G_OBJECT (widget), "event",
8427                               G_CALLBACK (handler),
8428                               G_OBJECT (menu));
8429 </programlisting>
8430 <simpara>where <literal>widget</literal> is the widget you are binding to,
8431 <literal>handler</literal> is the handling function, and <literal>menu</literal> is a menu
8432 created with gtk_menu_new(). This can be a menu which is also posted
8433 by a menu bar, as shown in the sample code.</simpara>
8434 </listitem>
8435 </itemizedlist>
8436
8437 </sect1>
8438
8439 <!-- ----------------------------------------------------------------- -->
8440 <sect1 id="sec-ManualMenuExample">
8441 <title>Manual Menu Example</title>
8442
8443 <para>That should about do it. Let's take a look at an example to help clarify.</para>
8444
8445 <para>
8446 <inlinemediaobject>
8447 <imageobject>
8448 <imagedata fileref="images/menu.png" format="png">
8449 </imageobject>
8450 </inlinemediaobject>
8451 </para>
8452
8453 <programlisting role="C">
8454 <!-- example-start menu menu.c -->
8455
8456 #include &lt;stdio.h&gt;
8457 #include &lt;gtk/gtk.h&gt;
8458
8459 static gboolean button_press (GtkWidget *, GdkEvent *);
8460 static void menuitem_response (gchar *);
8461
8462 int main( int   argc,
8463           char *argv[] )
8464 {
8465
8466     GtkWidget *window;
8467     GtkWidget *menu;
8468     GtkWidget *menu_bar;
8469     GtkWidget *root_menu;
8470     GtkWidget *menu_items;
8471     GtkWidget *vbox;
8472     GtkWidget *button;
8473     char buf[128];
8474     int i;
8475
8476     gtk_init (&amp;argc, &amp;argv);
8477
8478     /* create a new window */
8479     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8480     gtk_widget_set_size_request (GTK_WIDGET (window), 200, 100);
8481     gtk_window_set_title (GTK_WINDOW (window), "GTK Menu Test");
8482     g_signal_connect (G_OBJECT (window), "delete_event",
8483                       G_CALLBACK (gtk_main_quit), NULL);
8484
8485     /* Init the menu-widget, and remember -- never
8486      * gtk_show_widget() the menu widget!! 
8487      * This is the menu that holds the menu items, the one that
8488      * will pop up when you click on the "Root Menu" in the app */
8489     menu = gtk_menu_new ();
8490
8491     /* Next we make a little loop that makes three menu-entries for "test-menu".
8492      * Notice the call to gtk_menu_shell_append.  Here we are adding a list of
8493      * menu items to our menu.  Normally, we'd also catch the "clicked"
8494      * signal on each of the menu items and setup a callback for it,
8495      * but it's omitted here to save space. */
8496
8497     for (i = 0; i &lt; 3; i++)
8498         {
8499             /* Copy the names to the buf. */
8500             sprintf (buf, "Test-undermenu - %d", i);
8501
8502             /* Create a new menu-item with a name... */
8503             menu_items = gtk_menu_item_new_with_label (buf);
8504
8505             /* ...and add it to the menu. */
8506             gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
8507
8508             /* Do something interesting when the menuitem is selected */
8509             g_signal_connect_swapped (G_OBJECT (menu_items), "activate",
8510                                       G_CALLBACK (menuitem_response), 
8511                                       (gpointer) g_strdup (buf));
8512
8513             /* Show the widget */
8514             gtk_widget_show (menu_items);
8515         }
8516
8517     /* This is the root menu, and will be the label
8518      * displayed on the menu bar.  There won't be a signal handler attached,
8519      * as it only pops up the rest of the menu when pressed. */
8520     root_menu = gtk_menu_item_new_with_label ("Root Menu");
8521
8522     gtk_widget_show (root_menu);
8523
8524     /* Now we specify that we want our newly created "menu" to be the menu
8525      * for the "root menu" */
8526     gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu);
8527
8528     /* A vbox to put a menu and a button in: */
8529     vbox = gtk_vbox_new (FALSE, 0);
8530     gtk_container_add (GTK_CONTAINER (window), vbox);
8531     gtk_widget_show (vbox);
8532
8533     /* Create a menu-bar to hold the menus and add it to our main window */
8534     menu_bar = gtk_menu_bar_new ();
8535     gtk_box_pack_start (GTK_BOX (vbox), menu_bar, FALSE, FALSE, 2);
8536     gtk_widget_show (menu_bar);
8537
8538     /* Create a button to which to attach menu as a popup */
8539     button = gtk_button_new_with_label ("press me");
8540     g_signal_connect_swapped (G_OBJECT (button), "event",
8541                               G_CALLBACK (button_press), 
8542                               G_OBJECT (menu));
8543     gtk_box_pack_end (GTK_BOX (vbox), button, TRUE, TRUE, 2);
8544     gtk_widget_show (button);
8545
8546     /* And finally we append the menu-item to the menu-bar -- this is the
8547      * "root" menu-item I have been raving about =) */
8548     gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), root_menu);
8549
8550     /* always display the window as the last step so it all splashes on
8551      * the screen at once. */
8552     gtk_widget_show (window);
8553
8554     gtk_main ();
8555
8556     return 0;
8557 }
8558
8559 /* Respond to a button-press by posting a menu passed in as widget.
8560  *
8561  * Note that the "widget" argument is the menu being posted, NOT
8562  * the button that was pressed.
8563  */
8564
8565 static gboolean button_press( GtkWidget *widget,
8566                               GdkEvent *event )
8567 {
8568
8569     if (event-&gt;type == GDK_BUTTON_PRESS) {
8570         GdkEventButton *bevent = (GdkEventButton *) event; 
8571         gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
8572                         bevent-&gt;button, bevent-&gt;time);
8573         /* Tell calling code that we have handled this event; the buck
8574          * stops here. */
8575         return TRUE;
8576     }
8577
8578     /* Tell calling code that we have not handled this event; pass it on. */
8579     return FALSE;
8580 }
8581
8582
8583 /* Print a string when a menu item is selected */
8584
8585 static void menuitem_response( gchar *string )
8586 {
8587     printf ("%s\n", string);
8588 }
8589 <!-- example-end -->
8590 </programlisting>
8591
8592 <para>You may also set a menu item to be insensitive and, using an accelerator
8593 table, bind keys to menu functions.</para>
8594
8595 </sect1>
8596
8597 <!-- ----------------------------------------------------------------- -->
8598 <sect1 id="sec-UsingItemFactory">
8599 <title>Using ItemFactory</title>
8600
8601 <para>Now that we've shown you the hard way, here's how you do it using the
8602 gtk_item_factory calls.</para>
8603
8604 <para>ItemFactory creates a menu out of an array of ItemFactory entries. This 
8605 means you can define your menu in its simplest form and then create the
8606 menu/menubar widgets with a minimum of function calls.</para>
8607
8608 <!-- ----------------------------------------------------------------- -->
8609 <sect2 id="sec-ItemFactoryEntries">
8610 <title>ItemFactory entries</title>
8611
8612 <para>At the core of ItemFactory is the ItemFactoryEntry. This structure defines
8613 one menu item, and when an array of these entries is defined a whole
8614 menu is formed. The ItemFactory entry struct definition looks like this:</para>
8615
8616 <programlisting role="C">
8617 struct _GtkItemFactoryEntry
8618 {
8619   gchar *path;
8620   gchar *accelerator;
8621
8622   GtkItemFactoryCallback callback;
8623   guint                  callback_action;
8624
8625   gchar          *item_type;
8626 };
8627 </programlisting>
8628
8629 <para>Each field defines part of the menu item.</para>
8630
8631 <para><literal>*path</literal> is a string which defines both the name and the
8632 path of a menu item, for example, "/File/Open" would be the name of a menu
8633 item which would come under the ItemFactory entry with path "/File". Note however
8634 that "/File/Open" would be displayed in the File menu as "Open". Also note
8635 since the forward slashes are used to define the path of the menu,
8636 they cannot be used as part of the name. A letter preceded by an underscore
8637 indicates an accelerator (shortcut) key once the menu is open.</para>
8638
8639 <para>
8640 <literal>*accelerator</literal> is a string that indicates a key combination
8641 that can be used as a shortcut to that menu item. The string can be made up
8642 of either a single character, or a combination of modifier keys with a single
8643 character. It is case insensitive.</para>
8644
8645
8646 <para>The available modifier keys are:</para>
8647
8648 <programlisting role="C">
8649 "&lt;ALT&gt;                             - alt
8650 "&lt;CTL&gt;" or "&lt;CTRL&gt;" or "&lt;CONTROL&gt;" - control
8651 "&lt;MOD1&gt;" to "&lt;MOD5&gt;"               - modn
8652 "&lt;SHFT&gt;" or "&lt;SHIFT&gt;"              - shift
8653 </programlisting>
8654
8655 <para>Examples:</para>
8656 <programlisting role="C">
8657 "&lt;ConTroL&gt;a"
8658 "&lt;SHFT&gt;&lt;ALT&gt;&lt;CONTROL&gt;X"
8659 </programlisting>
8660
8661 <para>
8662 <literal>callback</literal> is the function that is called when the menu item
8663 emits the "activate" signal. The form of the callback is described
8664 in the <link linkend="sec-ItemFactoryCallback">Callback Description</link>
8665 section.</para>
8666
8667 <para>
8668 The value of <literal>callback_action</literal> is passed to the callback
8669 function. It also affects the function prototype, as shown
8670 in the <link linkend="sec-ItemFactoryCallback">Callback Description</link>
8671 section.</para>
8672
8673 <para>
8674 <literal>item_type</literal> is a string that defines what type of widget is
8675 packed into the menu items container. It can be:</para>
8676
8677 <programlisting role="C">
8678 NULL or "" or "&lt;Item&gt;" - create a simple item
8679 "&lt;Title&gt;"              - create a title item
8680 "&lt;CheckItem&gt;"          - create a check item
8681 "&lt;ToggleItem&gt;"         - create a toggle item
8682 "&lt;RadioItem&gt;"          - create a (root) radio item
8683 "Path"                 - create a sister radio item
8684 "&lt;Tearoff&gt;"            - create a tearoff
8685 "&lt;Separator&gt;"          - create a separator
8686 "&lt;Branch&gt;"             - create an item to hold submenus (optional)
8687 "&lt;LastBranch&gt;"         - create a right justified branch
8688 "&lt;StockItem&gt;"          - create a simple item with a stock image. 
8689                                see <filename>gtkstock.h</filename> for builtin stock items
8690  
8691 </programlisting>
8692
8693 <para>Note that &lt;LastBranch&gt; is only useful for one submenu of
8694 a menubar.</para>
8695
8696 <!-- ----------------------------------------------------------------- -->
8697 <sect3 id="sec-ItemFactoryCallback">
8698 <title>Callback Description</title>
8699
8700 <para>
8701 The callback for an ItemFactory entry can take two forms. If
8702 <literal>callback_action</literal> is zero, it is of the following
8703 form:</para>
8704
8705 <programlisting role="C">
8706 void callback( void )
8707 </programlisting>
8708
8709 <para>otherwise it is of the form:</para>
8710
8711 <programlisting role="C">
8712 void callback( gpointer    callback_data,
8713                guint       callback_action,
8714                GtkWidget  *widget )
8715 </programlisting>
8716
8717 <para>
8718 <literal>callback_data</literal> is a pointer to an arbitrary piece of data and
8719 is set during the call to gtk_item_factory_create_items().</para>
8720
8721 <para>
8722 <literal>callback_action</literal> is the same value as
8723 <literal>callback_action</literal> in the ItemFactory entry.</para>
8724
8725 <para>
8726 <literal>*widget</literal> is a pointer to a menu item widget
8727 (described in <link linkend="sec-ManualMenuCreation">Manual Menu Creation</link>).
8728 </para>
8729 </sect3>
8730
8731 <!-- ----------------------------------------------------------------- -->
8732 <sect3 id="sec-ItemFactoryEntryExamples">
8733 <title>ItemFactory entry examples</title>
8734
8735 <para>Creating a simple menu item:</para>
8736
8737 <programlisting role="C">
8738 GtkItemFactoryEntry entry = {"/_File/_Open...", "&lt;CTRL&gt;O", print_hello,
8739                                 0, "&lt;Item&gt;"};
8740 </programlisting>
8741
8742 <para>This will define a new simple menu entry "/File/Open" (displayed as "Open"),
8743 under the menu entry "/File". It has the accelerator (shortcut) control+'O'
8744 that when clicked calls the function print_hello(). print_hello() is of
8745 the form <literal>void print_hello(void)</literal> since the callback_action
8746 field is zero. When displayed the 'O' in "Open" will be underlined and if the
8747 menu item is visible on the screen pressing 'O' will activate the item. Note
8748 that "File/_Open" could also have been used as the path instead of
8749 "/_File/_Open".</para>
8750
8751 <para>Creating an entry with a more complex callback:</para>
8752
8753 <programlisting role="C">
8754 GtkItemFactoryEntry entry = {"/_View/Display _FPS", NULL, print_state,
8755                                 7,"&lt;CheckItem&gt;"};
8756 </programlisting>
8757
8758 <para>This defines a new menu item displayed as "Display FPS" which is under
8759 the menu item "View". When clicked the function print_state() will be called.
8760 Since <literal>callback_action</literal> is not zero print_state() is of the
8761 form:</para>
8762
8763 <programlisting role="C">
8764 void print_state( gpointer    callback_data,
8765                   guint       callback_action,
8766                   GtkWidget  *widget )
8767 </programlisting>
8768
8769 <para>with <literal>callback_action</literal> equal to 7.</para>
8770
8771 <para>Creating a radio button set:</para>
8772
8773 <programlisting role="C">
8774 GtkItemFactoryEntry entry1 = {"/_View/_Low Resolution", NULL, change_resolution,
8775                                 1, "&lt;RadioButton&gt;"};
8776 GtkItemFactoryEntry entry2 = {"/_View/_High Resolution", NULL, change_resolution,
8777                                 2, "/View/Low Resolution"};
8778 </programlisting>
8779
8780 <para><literal>entry1</literal> defines a lone radio button that when toggled
8781 calls the function change_resolution() with the parameter
8782 <literal>callback_action</literal> equal to 1. change_resolution() is of
8783 the form:</para>
8784
8785 <programlisting role="C">
8786 void change_resolution(gpointer    callback_data,
8787                        guint       callback_action,
8788                        GtkWidget  *widget)
8789 </programlisting>
8790
8791 <para><literal>entry2</literal> defines a radio button that belongs to the
8792 radio group that entry1 belongs to. It calls the same function when toggled
8793 but with the parameter <literal>callback_action</literal> equal to 2. Note that
8794 the item_type of <literal>entry2</literal> is the path of entry1
8795 <emphasis>without</emphasis> the accelerators ('_'). If another radio button was
8796 required in the same group then it would be defined in the same way as
8797 <literal>entry2</literal> was with its <literal>item_type</literal> again
8798 equal to "/View/Low Resolution".</para>
8799 </sect3>
8800
8801 <!-- ----------------------------------------------------------------- -->
8802 <sect3 id="sec-ItemFactoryEntryArrays">
8803 <title>ItemFactoryEntry Arrays</title>
8804
8805 <para>An ItemFactoryEntry on it's own however isn't useful. An array of
8806 entries is what's required to define a menu. Below is an example of how
8807 you'd declare this array.</para>
8808
8809 <programlisting role="C">
8810 static GtkItemFactoryEntry entries[] = {
8811   { "/_File",         NULL,      NULL,         0, "&lt;Branch&gt;" },
8812   { "/File/tear1",    NULL,      NULL,         0, "&lt;Tearoff&gt;" },
8813   { "/File/_New",     "&lt;CTRL&gt;N", new_file,     1, "&lt;Item&gt;" },
8814   { "/File/_Open...", "&lt;CTRL&gt;O", open_file,    1, "&lt;Item&gt;" },
8815   { "/File/sep1",     NULL,      NULL,         0, "&lt;Separator&gt;" },
8816   { "/File/_Quit",    "&lt;CTRL&gt;Q", quit_program, 0, "&lt;StockItem&gt;", GTK_STOCK_QUIT } };
8817 </programlisting>
8818 </sect3>
8819 </sect2>
8820
8821 <!-- ----------------------------------------------------------------- -->
8822 <sect2 id="sec-ItemFactoryCreation">
8823 <title>Creating an ItemFactory</title>
8824
8825 <para>An array of GtkItemFactoryEntry items defines a menu. Once this
8826 array is defined then the item factory can be created. The function that
8827 does this is:</para>
8828
8829 <programlisting role="C">
8830 GtkItemFactory* gtk_item_factory_new( GtkType        container_type,
8831                                       const gchar   *path,
8832                                       GtkAccelGroup *accel_group );
8833 </programlisting>
8834
8835 <para><literal>container_type</literal> can be one of:</para>
8836
8837 <programlisting role="C">
8838 GTK_TYPE_MENU
8839 GTK_TYPE_MENU_BAR
8840 GTK_TYPE_OPTION_MENU
8841 </programlisting>
8842
8843 <para><literal>container_type</literal> defines what type of menu
8844 you want, so when you extract it later it is either a menu (for pop-ups
8845 for instance), a menu bar, or an option menu (like a combo box but with
8846 a menu of pull downs).</para>
8847
8848 <para><literal>path</literal> defines the path of the root of the menu.
8849 Basically it is a unique name for the root of the menu, it must be
8850 surrounded by "&lt;&gt;". This is important for the naming of the
8851 accelerators and should be unique. It should be unique both for each
8852 menu and between each program. For example in a program named 'foo', the
8853 main menu should be called "&lt;FooMain&gt;", and a pop-up menu
8854 "&lt;FooImagePopUp&gt;", or similar. What's important is that they're unique.</para>
8855
8856 <para><literal>accel_group</literal> is a pointer to a gtk_accel_group. The
8857 item factory sets up the accelerator table while generating menus. New
8858 accelerator groups are generated by gtk_accel_group_new().</para>
8859
8860 <para>But this is just the first step. To convert the array of GtkItemFactoryEntry
8861 information into widgets the following function is used:</para>
8862
8863 <programlisting role="C">
8864 void gtk_item_factory_create_items( GtkItemFactory      *ifactory,
8865                                     guint                n_entries,
8866                                     GtkItemFactoryEntry *entries,
8867                                     gpointer             callback_data );
8868 </programlisting>
8869
8870 <para><literal>*ifactory</literal> a pointer to the above created item factory.</para>
8871 <para><literal>n_entries</literal> is the number of entries in the
8872 GtkItemFactoryEntry array.</para>
8873 <para><literal>*entries</literal> is a pointer to the GtkItemFactoryEntry array.</para>
8874 <para><literal>callback_data</literal> is what gets passed to all the callback functions
8875 for all the entries with callback_action != 0.</para>
8876
8877 <para>The accelerator group has now been formed, so you'll probably want
8878 to attach it to the window the menu is in:</para>
8879
8880 <programlisting role="C">
8881 void gtk_window_add_accel_group( GtkWindow     *window,
8882                                  GtkAccelGroup *accel_group);
8883 </programlisting>
8884 </sect2>
8885
8886 <!-- ----------------------------------------------------------------- -->
8887 <sect2 id="sec-UsingMenuandItems">
8888 <title>Making use of the menu and its menu items</title>
8889
8890 <para>The last thing to do is make use of the menu. The following function
8891 extracts the relevant widgets from the ItemFactory:</para>
8892
8893 <programlisting role="C">
8894 GtkWidget* gtk_item_factory_get_widget( GtkItemFactory *ifactory,
8895                                         const gchar    *path );
8896 </programlisting>
8897
8898 <para>For instance if an ItemFactory has two entries "/File" and "/File/New",
8899 using a path of "/File" would retrieve a <emphasis>menu</emphasis> widget from the
8900 ItemFactory. Using a path of "/File/New" would retrieve a
8901 <emphasis>menu item</emphasis> widget. This makes it possible to set the initial state
8902 of menu items. For example to set the default radio
8903 item to the one with the path "/Shape/Oval" then the following code would
8904 be used:</para>
8905
8906 <programlisting role="C">
8907 gtk_check_menu_item_set_active(
8908         GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory, "/Shape/Oval")),
8909         TRUE);
8910 </programlisting>
8911
8912 <para>Finally to retrieve the root of the menu use gtk_item_factory_get_item()
8913 with a path of "&lt;main&gt;" (or whatever path was used in
8914 gtk_item_factory_new()). In the case of the ItemFactory being created with
8915 type GTK_TYPE_MENU_BAR this returns a menu bar widget. With type GTK_TYPE_MENU
8916 a menu widget is returned. With type GTK_TYPE_OPTION_MENU an option menu
8917 widget is returned.</para>
8918
8919 <para><emphasis>Remember</emphasis> for an entry defined with path "/_File"
8920 the path here is actually "/File".</para>
8921
8922 <para>Now you have a menubar or menu which can be manipulated in the same
8923 way as shown in the
8924 <link linkend="sec-ManualMenuCreation">Manual Menu Creation</link>
8925 section.</para>
8926 </sect2>
8927 </sect1>
8928
8929 <!-- ----------------------------------------------------------------- -->
8930 <sect1 id="sec-ItemFactoryExample">
8931 <title>Item Factory Example</title>
8932
8933 <para>Here is an example using the GTK item factory.</para>
8934
8935 <programlisting role="C">
8936 <!-- example-start menu itemfactory.c -->
8937
8938 #include &lt;gtk/gtk.h&gt;
8939
8940 /* Obligatory basic callback */
8941 static void print_hello( GtkWidget *w,
8942                          gpointer   data )
8943 {
8944   g_message ("Hello, World!\n");
8945 }
8946
8947 /* For the check button */
8948 static void print_toggle( gpointer   callback_data,
8949                           guint      callback_action,
8950                           GtkWidget *menu_item )
8951 {
8952    g_message ("Check button state - %d\n",
8953               GTK_CHECK_MENU_ITEM (menu_item)-&gt;active);
8954 }
8955
8956 /* For the radio buttons */
8957 static void print_selected( gpointer   callback_data,
8958                             guint      callback_action,
8959                             GtkWidget *menu_item )
8960 {
8961    if(GTK_CHECK_MENU_ITEM(menu_item)-&gt;active)
8962      g_message ("Radio button %d selected\n", callback_action);
8963 }
8964
8965 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
8966 static GtkItemFactoryEntry menu_items[] = {
8967   { "/_File",         NULL,         NULL,           0, "&lt;Branch&gt;" },
8968   { "/File/_New",     "&lt;control&gt;N", print_hello,    0, "&lt;StockItem&gt;", GTK_STOCK_NEW },
8969   { "/File/_Open",    "&lt;control&gt;O", print_hello,    0, "&lt;StockItem&gt;", GTK_STOCK_OPEN },
8970   { "/File/_Save",    "&lt;control&gt;S", print_hello,    0, "&lt;StockItem&gt;", GTK_STOCK_SAVE },
8971   { "/File/Save _As", NULL,         NULL,           0, "&lt;Item&gt;" },
8972   { "/File/sep1",     NULL,         NULL,           0, "&lt;Separator&gt;" },
8973   { "/File/_Quit",    "&lt;CTRL&gt;Q", gtk_main_quit, 0, "&lt;StockItem&gt;", GTK_STOCK_QUIT },
8974   { "/_Options",      NULL,         NULL,           0, "&lt;Branch&gt;" },
8975   { "/Options/tear",  NULL,         NULL,           0, "&lt;Tearoff&gt;" },
8976   { "/Options/Check", NULL,         print_toggle,   1, "&lt;CheckItem&gt;" },
8977   { "/Options/sep",   NULL,         NULL,           0, "&lt;Separator&gt;" },
8978   { "/Options/Rad1",  NULL,         print_selected, 1, "&lt;RadioItem&gt;" },
8979   { "/Options/Rad2",  NULL,         print_selected, 2, "/Options/Rad1" },
8980   { "/Options/Rad3",  NULL,         print_selected, 3, "/Options/Rad1" },
8981   { "/_Help",         NULL,         NULL,           0, "&lt;LastBranch&gt;" },
8982   { "/_Help/About",   NULL,         NULL,           0, "&lt;Item&gt;" },
8983 };
8984
8985 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
8986
8987 /* Returns a menubar widget made from the above menu */
8988 static GtkWidget *get_menubar_menu( GtkWidget  *window )
8989 {
8990   GtkItemFactory *item_factory;
8991   GtkAccelGroup *accel_group;
8992
8993   /* Make an accelerator group (shortcut keys) */
8994   accel_group = gtk_accel_group_new ();
8995
8996   /* Make an ItemFactory (that makes a menubar) */
8997   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "&lt;main&gt;",
8998                                        accel_group);
8999
9000   /* This function generates the menu items. Pass the item factory,
9001      the number of items in the array, the array itself, and any
9002      callback data for the the menu items. */
9003   gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
9004
9005   /* Attach the new accelerator group to the window. */
9006   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
9007
9008   /* Finally, return the actual menu bar created by the item factory. */
9009   return gtk_item_factory_get_widget (item_factory, "&lt;main&gt;");
9010 }
9011
9012 /* Popup the menu when the popup button is pressed */
9013 static gboolean popup_cb( GtkWidget *widget,
9014                           GdkEvent *event,
9015                           GtkWidget *menu )
9016 {
9017    GdkEventButton *bevent = (GdkEventButton *)event;
9018   
9019    /* Only take button presses */
9020    if (event-&gt;type != GDK_BUTTON_PRESS)
9021      return FALSE;
9022   
9023    /* Show the menu */
9024    gtk_menu_popup (GTK_MENU(menu), NULL, NULL,
9025                    NULL, NULL, bevent-&gt;button, bevent-&gt;time);
9026   
9027    return TRUE;
9028 }
9029
9030 /* Same as with get_menubar_menu() but just return a button with a signal to
9031    call a popup menu */
9032 GtkWidget *get_popup_menu( void )
9033 {
9034    GtkItemFactory *item_factory;
9035    GtkWidget *button, *menu;
9036   
9037    /* Same as before but don't bother with the accelerators */
9038    item_factory = gtk_item_factory_new (GTK_TYPE_MENU, "&lt;main&gt;",
9039                                         NULL);
9040    gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
9041    menu = gtk_item_factory_get_widget (item_factory, "&lt;main&gt;");
9042   
9043    /* Make a button to activate the popup menu */
9044    button = gtk_button_new_with_label ("Popup");
9045    /* Make the menu popup when clicked */
9046    g_signal_connect (G_OBJECT(button),
9047                      "event",
9048                      G_CALLBACK(popup_cb),
9049                      (gpointer) menu);
9050
9051    return button;
9052 }
9053
9054 /* Same again but return an option menu */
9055 GtkWidget *get_option_menu( void )
9056 {
9057    GtkItemFactory *item_factory;
9058    GtkWidget *option_menu;
9059   
9060    /* Same again, not bothering with the accelerators */
9061    item_factory = gtk_item_factory_new (GTK_TYPE_OPTION_MENU, "&lt;main&gt;",
9062                                         NULL);
9063    gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
9064    option_menu = gtk_item_factory_get_widget (item_factory, "&lt;main&gt;");
9065
9066    return option_menu;
9067 }
9068
9069 /* You have to start somewhere */
9070 int main( int argc,
9071           char *argv[] )
9072 {
9073   GtkWidget *window;
9074   GtkWidget *main_vbox;
9075   GtkWidget *menubar, *option_menu, *popup_button;
9076  
9077   /* Initialize GTK */
9078   gtk_init (&amp;argc, &amp;argv);
9079  
9080   /* Make a window */
9081   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9082   g_signal_connect (G_OBJECT (window), "destroy",
9083                     G_CALLBACK (gtk_main_quit),
9084                     NULL);
9085   gtk_window_set_title (GTK_WINDOW(window), "Item Factory");
9086   gtk_widget_set_size_request (GTK_WIDGET(window), 300, 200);
9087  
9088   /* Make a vbox to put the three menus in */
9089   main_vbox = gtk_vbox_new (FALSE, 1);
9090   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 1);
9091   gtk_container_add (GTK_CONTAINER (window), main_vbox);
9092  
9093   /* Get the three types of menu */
9094   /* Note: all three menus are separately created, so they are not the
9095      same menu */
9096   menubar = get_menubar_menu (window);
9097   popup_button = get_popup_menu ();
9098   option_menu = get_option_menu ();
9099   
9100   /* Pack it all together */
9101   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
9102   gtk_box_pack_end (GTK_BOX (main_vbox), popup_button, FALSE, TRUE, 0);
9103   gtk_box_pack_end (GTK_BOX (main_vbox), option_menu, FALSE, TRUE, 0);
9104
9105   /* Show the widgets */
9106   gtk_widget_show_all (window);
9107   
9108   /* Finished! */
9109   gtk_main ();
9110  
9111   return 0;
9112 }
9113 <!-- example-end -->
9114 </programlisting>
9115
9116 </sect1>
9117 </chapter>
9118
9119 <!-- ***************************************************************** -->
9120 <chapter id="ch-UndocWidgets">
9121 <title>Undocumented Widgets</title>
9122
9123 <para>These all require authors! :) Please consider contributing to our
9124 tutorial.</para>
9125
9126 <para>If you must use one of these widgets that are undocumented, I strongly
9127 suggest you take a look at their respective header files in the GTK
9128 distribution. GTK's function names are very descriptive. Once you
9129 have an understanding of how things work, it's not difficult to figure
9130 out how to use a widget simply by looking at its function
9131 declarations. This, along with a few examples from others' code, and
9132 it should be no problem.</para>
9133
9134 <para>When you do come to understand all the functions of a new undocumented
9135 widget, please consider writing a tutorial on it so others may benefit
9136 from your time.</para>
9137
9138 <!-- ----------------------------------------------------------------- -->
9139 <sect1 id="sec-AccelLabel">
9140 <title>Accel Label</title>
9141
9142 <para></para>
9143
9144 </sect1>
9145
9146 <!-- ----------------------------------------------------------------- -->
9147 <sect1 id="sec-OptionMenu">
9148 <title>Option Menu</title>
9149
9150 <para></para>
9151
9152 </sect1>
9153
9154 <!-- ----------------------------------------------------------------- -->
9155 <sect1 id="sec-MenuItems">
9156 <title>Menu Items</title>
9157
9158 <para></para>
9159
9160 <sect2 id="sec-CheckMenuItem">
9161 <title>Check Menu Item</title>
9162
9163 <para></para>
9164 </sect2>
9165
9166 <sect2 id="sec-RadioMenuItem">
9167 <title>Radio Menu Item</title>
9168
9169 <para></para>
9170 </sect2>
9171
9172 <sect2 id="sec-SeparatorMenuItem">
9173 <title>Separator Menu Item</title>
9174
9175 <para></para>
9176 </sect2>
9177
9178 <sect2 id="sec-TearoffMenuItem">
9179 <title>Tearoff Menu Item</title>
9180
9181 <para></para>
9182 </sect2>
9183 </sect1>
9184
9185 <!-- ----------------------------------------------------------------- -->
9186 <sect1 id="sec-Curves">
9187 <title>Curves</title>
9188
9189 <para></para>
9190
9191 </sect1>
9192
9193 <!-- ----------------------------------------------------------------- -->
9194 <sect1 id="sec-DrawingArea">
9195 <title>Drawing Area</title>
9196
9197 <para></para>
9198
9199 </sect1>
9200
9201 <!-- ----------------------------------------------------------------- -->
9202 <sect1 id="sec-FontSelectionDialog">
9203 <title>Font Selection Dialog</title>
9204
9205 <para></para>
9206
9207 </sect1>
9208
9209 <!-- ----------------------------------------------------------------- -->
9210 <sect1 id="sec-MessageDialog">
9211 <title>Message Dialog</title>
9212
9213 <para></para>
9214
9215 </sect1>
9216
9217 <!-- ----------------------------------------------------------------- -->
9218 <sect1 id="sec-GammaCurve">
9219 <title>Gamma Curve</title>
9220
9221 <para></para>
9222
9223 </sect1>
9224
9225 <!-- ----------------------------------------------------------------- -->
9226 <sect1 id="sec-Image">
9227 <title>Image</title>
9228
9229 <para></para>
9230
9231 </sect1>
9232
9233 <!-- ----------------------------------------------------------------- -->
9234 <sect1 id="sec-PlugsAndSockets">
9235 <title>Plugs and Sockets</title>
9236
9237 <para></para>
9238
9239 </sect1>
9240
9241 <!-- ----------------------------------------------------------------- -->
9242 <sect1 id="sec-TreeView">
9243 <title>Tree View</title>
9244
9245 <para></para>
9246
9247 </sect1>
9248
9249 <!-- ----------------------------------------------------------------- -->
9250 <sect1 id="sec-TextView">
9251 <title>Text View</title>
9252
9253 <para></para>
9254
9255 </sect1>
9256 </chapter>
9257
9258 <!-- ***************************************************************** -->
9259 <chapter id="ch-SettingWidgetAttributes">
9260 <title>Setting Widget Attributes</title>
9261
9262 <para>This describes the functions used to operate on widgets. These can be
9263 used to set style, padding, size, etc.</para>
9264
9265 <para>(Maybe I should make a whole section on accelerators.)</para>
9266
9267 <programlisting role="C">
9268 void gtk_widget_activate( GtkWidget *widget );
9269
9270 void gtk_widget_set_name( GtkWidget *widget,
9271                           gchar     *name );
9272
9273 gchar *gtk_widget_get_name( GtkWidget *widget );
9274
9275 void gtk_widget_set_sensitive( GtkWidget *widget,
9276                                gboolean   sensitive );
9277
9278 void gtk_widget_set_style( GtkWidget *widget,
9279                            GtkStyle  *style );
9280                                            
9281 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
9282
9283 GtkStyle *gtk_widget_get_default_style( void );
9284
9285 void gtk_widget_set_size_request( GtkWidget *widget,
9286                                   gint       width,
9287                                   gint       height );
9288
9289 void gtk_widget_grab_focus( GtkWidget *widget );
9290
9291 void gtk_widget_show( GtkWidget *widget );
9292
9293 void gtk_widget_hide( GtkWidget *widget );
9294 </programlisting>
9295
9296 </chapter>
9297
9298 <!-- ***************************************************************** -->
9299 <chapter id="ch-Timeouts">
9300 <title>Timeouts, IO and Idle Functions</title>
9301
9302 <!-- ----------------------------------------------------------------- -->
9303 <sect1 id="sec-Timeouts">
9304 <title>Timeouts</title>
9305
9306 <para>You may be wondering how you make GTK do useful work when in gtk_main.
9307 Well, you have several options. Using the following function you can
9308 create a timeout function that will be called every "interval"
9309 milliseconds.</para>
9310
9311 <programlisting role="C">
9312 gint gtk_timeout_add( guint32     interval,
9313                       GtkFunction function,
9314                       gpointer    data );
9315 </programlisting>
9316
9317 <para>The first argument is the number of milliseconds between calls to your
9318 function. The second argument is the function you wish to have called,
9319 and the third, the data passed to this callback function. The return
9320 value is an integer "tag" which may be used to stop the timeout by
9321 calling:</para>
9322
9323 <programlisting role="C">
9324 void gtk_timeout_remove( gint tag );
9325 </programlisting>
9326
9327 <para>You may also stop the timeout function by returning zero or FALSE from
9328 your callback function. Obviously this means if you want your function
9329 to continue to be called, it should return a non-zero value,
9330 i.e., TRUE.</para>
9331
9332 <para>The declaration of your callback should look something like this:</para>
9333
9334 <programlisting role="C">
9335 gint timeout_callback( gpointer data );
9336 </programlisting>
9337
9338 </sect1>
9339
9340 <!-- ----------------------------------------------------------------- -->
9341 <sect1 id="sec-MonitoringIO">
9342 <title>Monitoring IO</title>
9343
9344 <para>A nifty feature of GDK (the library that underlies GTK), is the
9345 ability to have it check for data on a file descriptor for you (as
9346 returned by open(2) or socket(2)). This is especially useful for
9347 networking applications. The function:</para>
9348
9349 <programlisting role="C">
9350 gint gdk_input_add( gint              source,
9351                     GdkInputCondition condition,
9352                     GdkInputFunction  function,
9353                     gpointer          data );
9354 </programlisting>
9355
9356 <para>Where the first argument is the file descriptor you wish to have
9357 watched, and the second specifies what you want GDK to look for. This
9358 may be one of:</para>
9359
9360 <itemizedlist>
9361 <listitem><simpara><literal>GDK_INPUT_READ</literal> - Call your function when there is data
9362 ready for reading on your file descriptor.</simpara>
9363 </listitem>
9364
9365 <listitem><simpara><literal>GDK_INPUT_WRITE</literal> - Call your function when the file
9366 descriptor is ready for writing.</simpara>
9367 </listitem>
9368 </itemizedlist>
9369
9370 <para>As I'm sure you've figured out already, the third argument is the
9371 function you wish to have called when the above conditions are
9372 satisfied, and the fourth is the data to pass to this function.</para>
9373
9374 <para>The return value is a tag that may be used to stop GDK from monitoring
9375 this file descriptor using the following function.</para>
9376
9377 <programlisting role="C">
9378 void gdk_input_remove( gint tag );
9379 </programlisting>
9380
9381 <para>The callback function should be declared as:</para>
9382
9383 <programlisting role="C">
9384 void input_callback( gpointer          data,
9385                      gint              source, 
9386                      GdkInputCondition condition );
9387 </programlisting>
9388
9389 <para>Where <literal>source</literal> and <literal>condition</literal> are as specified above.</para>
9390
9391 </sect1>
9392
9393 <!-- ----------------------------------------------------------------- -->
9394 <sect1 id="sec-IdleFunctions">
9395 <title>Idle Functions</title>
9396
9397 <para><!-- TODO: Need to check on idle priorities - TRG -->
9398 What if you have a function which you want to be called when nothing
9399 else is happening ?</para>
9400
9401 <programlisting role="C">
9402 gint gtk_idle_add( GtkFunction function,
9403                    gpointer    data );
9404 </programlisting>
9405
9406 <para>This causes GTK to call the specified function whenever nothing else
9407 is happening.</para>
9408
9409 <programlisting role="C">
9410 void gtk_idle_remove( gint tag );
9411 </programlisting>
9412
9413 <para>I won't explain the meaning of the arguments as they follow very much
9414 like the ones above. The function pointed to by the first argument to
9415 gtk_idle_add will be called whenever the opportunity arises. As with
9416 the others, returning FALSE will stop the idle function from being
9417 called.</para>
9418
9419 </sect1>
9420 </chapter>
9421
9422 <!-- ***************************************************************** -->
9423 <chapter id="ch-AdvancedEventsAndSignals">
9424 <title>Advanced Event and Signal Handling</title>
9425
9426 <!-- ----------------------------------------------------------------- -->
9427 <sect1 id="sec-SignalFunctions">
9428 <title>Signal Functions</title>
9429
9430 <!-- ----------------------------------------------------------------- -->
9431 <sect2>
9432 <title>Connecting and Disconnecting Signal Handlers</title>
9433
9434 <programlisting role="C">
9435 gulong g_signal_connect( GObject     *object,
9436                          const gchar *name,
9437                          GCallback    func,
9438                          gpointer     func_data );
9439
9440 gulong g_signal_connect_after( GObject       *object,
9441                                const gchar   *name,
9442                                GCallback      func,
9443                                gpointer       func_data );
9444
9445 gulong g_signal_connect_swapped( GObject       *object,
9446                                  const gchar   *name,
9447                                  GCallback      func,
9448                                  GObject       *slot_object );
9449
9450 void g_signal_handler_disconnect( GObject *object,
9451                                   gulong   handler_id );
9452
9453 void g_signal_handlers_disconnect_by_func( GObject   *object,
9454                                            GCallback  func,
9455                                            gpointer   data );
9456 </programlisting>
9457
9458 </sect2>
9459
9460 <!-- ----------------------------------------------------------------- -->
9461 <sect2>
9462 <title>Blocking and Unblocking Signal Handlers</title>
9463
9464 <programlisting role="C">
9465 void g_signal_handler_block( GObject *object,
9466                              gulong   handler_id);
9467
9468 void g_signal_handlers_block_by_func( GObject   *object,
9469                                       GCallback  func,
9470                                       gpointer   data );
9471
9472 void g_signal_handler_unblock( GObject *object,
9473                                gulong   handler_id );
9474
9475 void g_signal_handler_unblock_by_func( GObject   *object,
9476                                        GCallback  func,
9477                                        gpointer   data );
9478 </programlisting>
9479
9480 </sect2>
9481
9482 <!-- ----------------------------------------------------------------- -->
9483 <sect2>
9484 <title>Emitting and Stopping Signals</title>
9485
9486 <programlisting role="C">
9487 void g_signal_emit( GObject *object,
9488                     guint      signal_id,
9489                     ... );
9490
9491 void g_signal_emit_by_name( GObject     *object,
9492                             const gchar *name,
9493                             ... );
9494
9495 void g_signal_emitv( const GValue *instance_and_params,
9496                      guint         signal_id,
9497                      GQuark        detail,
9498                      GValue       *return_value );
9499
9500 void g_signal_stop_emission( GObject *object,
9501                              guint    signal_id,
9502                              GQuark   detail );
9503
9504 void g_signal_stop_emission_by_name( GObject   *object,
9505                                      const gchar *detailed_signal );
9506 </programlisting>
9507
9508 </sect2>
9509 </sect1>
9510
9511 <!-- ----------------------------------------------------------------- -->
9512 <sect1 id="sec-SignalEmissionAndPropagation">
9513 <title>Signal Emission and Propagation</title>
9514
9515 <para>Signal emission is the process whereby GTK runs all handlers for a
9516 specific object and signal.</para>
9517
9518 <para>First, note that the return value from a signal emission is the return
9519 value of the <emphasis>last</emphasis> handler executed. Since event signals are
9520 all of type <literal>GTK_RUN_LAST</literal>, this will be the default (GTK supplied)
9521 handler, unless you connect with gtk_signal_connect_after().</para>
9522
9523 <para>The way an event (say "button_press_event") is handled, is:</para>
9524
9525 <itemizedlist>
9526 <listitem><simpara>Start with the widget where the event occured.</simpara>
9527 </listitem>
9528
9529 <listitem><simpara>Emit the generic "event" signal. If that signal handler returns
9530 a value of TRUE, stop all processing.</simpara>
9531 </listitem>
9532
9533 <listitem><simpara>Otherwise, emit a specific, "button_press_event" signal. If that
9534 returns TRUE, stop all processing.</simpara>
9535 </listitem>
9536
9537 <listitem><simpara>Otherwise, go to the widget's parent, and repeat the above two
9538 steps.</simpara>
9539 </listitem>
9540
9541 <listitem><simpara>Continue until some signal handler returns TRUE, or until the
9542 top-level widget is reached.</simpara>
9543 </listitem>
9544 </itemizedlist>
9545
9546 <para>Some consequences of the above are:</para>
9547
9548 <itemizedlist>
9549 <listitem><simpara>Your handler's return value will have no effect if there is a
9550 default handler, unless you connect with gtk_signal_connect_after().</simpara>
9551 </listitem>
9552
9553 <listitem><simpara>To prevent the default handler from being run, you need to
9554 connect with gtk_signal_connect() and use
9555 gtk_signal_emit_stop_by_name() - the return value only affects whether
9556 the signal is propagated, not the current emission.</simpara>
9557 </listitem>
9558 </itemizedlist>
9559
9560 </sect1>
9561 </chapter>
9562
9563 <!-- continue GTK+ 2.0 review here -->
9564
9565 <!-- ***************************************************************** -->
9566 <chapter id="ch-ManagingSelections">
9567 <title>Managing Selections</title>
9568
9569 <!-- ----------------------------------------------------------------- -->
9570 <sect1 id="sec-SelectionsOverview">
9571 <title>Overview</title>
9572
9573 <para>One type of interprocess communication supported by X and GTK is
9574 <emphasis>selections</emphasis>. A selection identifies a chunk of data, for
9575 instance, a portion of text, selected by the user in some fashion, for
9576 instance, by dragging with the mouse. Only one application on a
9577 display (the <emphasis>owner</emphasis>) can own a particular selection at one
9578 time, so when a selection is claimed by one application, the previous
9579 owner must indicate to the user that selection has been
9580 relinquished. Other applications can request the contents of a
9581 selection in different forms, called <emphasis>targets</emphasis>. There can be
9582 any number of selections, but most X applications only handle one, the
9583 <emphasis>primary selection</emphasis>.</para>
9584
9585 <para>In most cases, it isn't necessary for a GTK application to deal with
9586 selections itself. The standard widgets, such as the Entry widget,
9587 already have the capability to claim the selection when appropriate
9588 (e.g., when the user drags over text), and to retrieve the contents of
9589 the selection owned by another widget or another application (e.g.,
9590 when the user clicks the second mouse button). However, there may be
9591 cases in which you want to give other widgets the ability to supply
9592 the selection, or you wish to retrieve targets not supported by
9593 default.</para>
9594
9595 <para>A fundamental concept needed to understand selection handling is that
9596 of the <emphasis>atom</emphasis>. An atom is an integer that uniquely identifies a
9597 string (on a certain display). Certain atoms are predefined by the X
9598 server, and in some cases there are constants in <literal>gtk.h</literal>
9599 corresponding to these atoms. For instance the constant
9600 <literal>GDK_PRIMARY_SELECTION</literal> corresponds to the string "PRIMARY".
9601 In other cases, you should use the functions
9602 <literal>gdk_atom_intern()</literal>, to get the atom corresponding to a string,
9603 and <literal>gdk_atom_name()</literal>, to get the name of an atom. Both
9604 selections and targets are identified by atoms.</para>
9605
9606 </sect1>
9607 <!-- ----------------------------------------------------------------- -->
9608 <sect1 id="sec-RetrievingTheSelection">
9609 <title>Retrieving the selection</title>
9610
9611 <para>Retrieving the selection is an asynchronous process. To start the
9612 process, you call:</para>
9613
9614 <programlisting role="C">
9615 gboolean gtk_selection_convert( GtkWidget *widget, 
9616                                 GdkAtom    selection, 
9617                                 GdkAtom    target,
9618                                 guint32    time );
9619 </programlisting>
9620
9621 <para>This <emphasis>converts</emphasis> the selection into the form specified by
9622 <literal>target</literal>. If at all possible, the time field should be the time
9623 from the event that triggered the selection. This helps make sure that
9624 events occur in the order that the user requested them. However, if it
9625 is not available (for instance, if the conversion was triggered by a
9626 "clicked" signal), then you can use the constant
9627 <literal>GDK_CURRENT_TIME</literal>.</para>
9628
9629 <para>When the selection owner responds to the request, a
9630 "selection_received" signal is sent to your application. The handler
9631 for this signal receives a pointer to a <literal>GtkSelectionData</literal>
9632 structure, which is defined as:</para>
9633
9634 <programlisting role="C">
9635 struct _GtkSelectionData
9636 {
9637   GdkAtom selection;
9638   GdkAtom target;
9639   GdkAtom type;
9640   gint    format;
9641   guchar *data;
9642   gint    length;
9643 };
9644 </programlisting>
9645
9646 <para><literal>selection</literal> and <literal>target</literal> are the values you gave in your
9647 <literal>gtk_selection_convert()</literal> call. <literal>type</literal> is an atom that
9648 identifies the type of data returned by the selection owner. Some
9649 possible values are "STRING", a string of latin-1 characters, "ATOM",
9650 a series of atoms, "INTEGER", an integer, etc. Most targets can only
9651 return one type. <literal>format</literal> gives the length of the units (for
9652 instance characters) in bits. Usually, you don't care about this when
9653 receiving data. <literal>data</literal> is a pointer to the returned data, and
9654 <literal>length</literal> gives the length of the returned data, in bytes. If
9655 <literal>length</literal> is negative, then an error occurred and the selection
9656 could not be retrieved. This might happen if no application owned the
9657 selection, or if you requested a target that the application didn't
9658 support. The buffer is actually guaranteed to be one byte longer than
9659 <literal>length</literal>; the extra byte will always be zero, so it isn't
9660 necessary to make a copy of strings just to nul-terminate them.</para>
9661
9662 <para>In the following example, we retrieve the special target "TARGETS",
9663 which is a list of all targets into which the selection can be
9664 converted.</para>
9665
9666 <programlisting role="C">
9667 <!-- example-start selection gettargets.c -->
9668
9669 #include &lt;stdlib.h&gt;
9670 #include &lt;gtk/gtk.h&gt;
9671
9672 static void selection_received( GtkWidget        *widget, 
9673                                 GtkSelectionData *selection_data, 
9674                                 gpointer          data );
9675
9676 /* Signal handler invoked when user clicks on the "Get Targets" button */
9677 static void get_targets( GtkWidget *widget,
9678                          gpointer data )
9679 {
9680   static GdkAtom targets_atom = GDK_NONE;
9681   GtkWidget *window = (GtkWidget *)data;        
9682
9683   /* Get the atom corresponding to the string "TARGETS" */
9684   if (targets_atom == GDK_NONE)
9685     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
9686
9687   /* And request the "TARGETS" target for the primary selection */
9688   gtk_selection_convert (window, GDK_SELECTION_PRIMARY, targets_atom,
9689                          GDK_CURRENT_TIME);
9690 }
9691
9692 /* Signal handler called when the selections owner returns the data */
9693 static void selection_received( GtkWidget        *widget,
9694                                 GtkSelectionData *selection_data, 
9695                                 gpointer          data )
9696 {
9697   GdkAtom *atoms;
9698   GList *item_list;
9699   int i;
9700
9701   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
9702   if (selection_data-&gt;length &lt; 0)
9703     {
9704       g_print ("Selection retrieval failed\n");
9705       return;
9706     }
9707   /* Make sure we got the data in the expected form */
9708   if (selection_data-&gt;type != GDK_SELECTION_TYPE_ATOM)
9709     {
9710       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
9711       return;
9712     }
9713   
9714   /* Print out the atoms we received */
9715   atoms = (GdkAtom *)selection_data-&gt;data;
9716
9717   item_list = NULL;
9718   for (i = 0; i &lt; selection_data-&gt;length / sizeof(GdkAtom); i++)
9719     {
9720       char *name;
9721       name = gdk_atom_name (atoms[i]);
9722       if (name != NULL)
9723         g_print ("%s\n",name);
9724       else
9725         g_print ("(bad atom)\n");
9726     }
9727
9728   return;
9729 }
9730
9731 int main( int   argc,
9732           char *argv[] )
9733 {
9734   GtkWidget *window;
9735   GtkWidget *button;
9736   
9737   gtk_init (&amp;argc, &amp;argv);
9738
9739   /* Create the toplevel window */
9740
9741   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9742   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
9743   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9744
9745   g_signal_connect (G_OBJECT (window), "destroy",
9746                     G_CALLBACK (exit), NULL);
9747
9748   /* Create a button the user can click to get targets */
9749
9750   button = gtk_button_new_with_label ("Get Targets");
9751   gtk_container_add (GTK_CONTAINER (window), button);
9752
9753   g_signal_connect (G_OBJECT (button), "clicked",
9754                     G_CALLBACK (get_targets), (gpointer) window);
9755   g_signal_connect (G_OBJECT (window), "selection_received",
9756                     G_CALLBACK (selection_received), NULL);
9757
9758   gtk_widget_show (button);
9759   gtk_widget_show (window);
9760   
9761   gtk_main ();
9762   
9763   return 0;
9764 }
9765 <!-- example-end -->
9766 </programlisting>
9767
9768 </sect1>
9769 <!-- ----------------------------------------------------------------- -->
9770 <sect1 id="sec-SupplyingTheSelection">
9771 <title>Supplying the selection</title>
9772
9773 <para>Supplying the selection is a bit more complicated. You must register 
9774 handlers that will be called when your selection is requested. For
9775 each selection/target pair you will handle, you make a call to:</para>
9776
9777 <programlisting role="C">
9778 void gtk_selection_add_target( GtkWidget           *widget, 
9779                                GdkAtom              selection,
9780                                GdkAtom              target,
9781                                guint                info );
9782 </programlisting>
9783
9784 <para><literal>widget</literal>, <literal>selection</literal>, and <literal>target</literal> identify the requests
9785 this handler will manage. When a request for a selection is received,
9786 the "selection_get" signal will be called. <literal>info</literal> can be used as an
9787 enumerator to identify the specific target within the callback function.</para>
9788
9789 <para>The callback function has the signature:</para>
9790
9791 <programlisting role="C">
9792 void  "selection_get"( GtkWidget          *widget,
9793                        GtkSelectionData   *selection_data,
9794                        guint               info,
9795                        guint               time );
9796 </programlisting>
9797
9798 <para>The GtkSelectionData is the same as above, but this time, we're
9799 responsible for filling in the fields <literal>type</literal>, <literal>format</literal>,
9800 <literal>data</literal>, and <literal>length</literal>. (The <literal>format</literal> field is actually
9801 important here - the X server uses it to figure out whether the data
9802 needs to be byte-swapped or not. Usually it will be 8 - <emphasis>i.e.</emphasis> a
9803 character - or 32 - <emphasis>i.e.</emphasis> an integer.) This is done by calling the
9804 function:</para>
9805
9806 <programlisting role="C">
9807 void gtk_selection_data_set( GtkSelectionData *selection_data,
9808                              GdkAtom           type,
9809                              gint              format,
9810                              guchar           *data,
9811                              gint              length );
9812 </programlisting>
9813
9814 <para>This function takes care of properly making a copy of the data so that
9815 you don't have to worry about keeping it around. (You should not fill
9816 in the fields of the GtkSelectionData structure by hand.)</para>
9817
9818 <para>When prompted by the user, you claim ownership of the selection by
9819 calling:</para>
9820
9821 <programlisting role="C">
9822 gboolean gtk_selection_owner_set( GtkWidget *widget,
9823                                   GdkAtom    selection,
9824                                   guint32    time );
9825 </programlisting>
9826
9827 <para>If another application claims ownership of the selection, you will
9828 receive a "selection_clear_event".</para>
9829
9830 <para>As an example of supplying the selection, the following program adds
9831 selection functionality to a toggle button. When the toggle button is
9832 depressed, the program claims the primary selection. The only target
9833 supported (aside from certain targets like "TARGETS" supplied by GTK
9834 itself), is the "STRING" target. When this target is requested, a
9835 string representation of the time is returned.</para>
9836
9837 <programlisting role="C">
9838 <!-- example-start selection setselection.c -->
9839
9840 #include &lt;stdlib.h&gt;
9841 #include &lt;gtk/gtk.h&gt;
9842 #include &lt;time.h&gt;
9843 #include &lt;string.h&gt;
9844
9845 GtkWidget *selection_button;
9846 GtkWidget *selection_widget;
9847
9848 /* Callback when the user toggles the selection */
9849 static void selection_toggled( GtkWidget *widget,
9850                                gint      *have_selection )
9851 {
9852   if (GTK_TOGGLE_BUTTON (widget)-&gt;active)
9853     {
9854       *have_selection = gtk_selection_owner_set (selection_widget,
9855                                                  GDK_SELECTION_PRIMARY,
9856                                                  GDK_CURRENT_TIME);
9857       /* if claiming the selection failed, we return the button to
9858          the out state */
9859       if (!*have_selection)
9860         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
9861     }
9862   else
9863     {
9864       if (*have_selection)
9865         {
9866           /* Before clearing the selection by setting the owner to NULL,
9867              we check if we are the actual owner */
9868           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget-&gt;window)
9869             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
9870                                      GDK_CURRENT_TIME);
9871           *have_selection = FALSE;
9872         }
9873     }
9874 }
9875
9876 /* Called when another application claims the selection */
9877 static gboolean selection_clear( GtkWidget         *widget,
9878                                  GdkEventSelection *event,
9879                                  gint              *have_selection )
9880 {
9881   *have_selection = FALSE;
9882   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (selection_button), FALSE);
9883
9884   return TRUE;
9885 }
9886
9887 /* Supplies the current time as the selection. */
9888 static void selection_handle( GtkWidget        *widget, 
9889                               GtkSelectionData *selection_data,
9890                               guint             info,
9891                               guint             time_stamp,
9892                               gpointer          data )
9893 {
9894   gchar *timestr;
9895   time_t current_time;
9896
9897   current_time = time (NULL);
9898   timestr = asctime (localtime (&amp;current_time)); 
9899   /* When we return a single string, it should not be null terminated.
9900      That will be done for us */
9901
9902   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
9903                           8, timestr, strlen (timestr));
9904 }
9905
9906 int main( int   argc,
9907           char *argv[] )
9908 {
9909   GtkWidget *window;
9910
9911   static int have_selection = FALSE;
9912   
9913   gtk_init (&amp;argc, &amp;argv);
9914
9915   /* Create the toplevel window */
9916
9917   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9918   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
9919   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9920
9921   g_signal_connect (G_OBJECT (window), "destroy",
9922                     G_CALLBACK (exit), NULL);
9923
9924   /* Create a toggle button to act as the selection */
9925
9926   selection_widget = gtk_invisible_new ();
9927   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
9928   gtk_container_add (GTK_CONTAINER (window), selection_button);
9929   gtk_widget_show (selection_button);
9930
9931   g_signal_connect (G_OBJECT (selection_button), "toggled",
9932                     G_CALLBACK (selection_toggled), (gpointer) &amp;have_selection);
9933   g_signal_connect (G_OBJECT (selection_widget), "selection_clear_event",
9934                     G_CALLBACK (selection_clear), (gpointer) &amp;have_selection);
9935
9936   gtk_selection_add_target (selection_widget,
9937                             GDK_SELECTION_PRIMARY,
9938                             GDK_SELECTION_TYPE_STRING,
9939                             1);
9940   g_signal_connect (G_OBJECT (selection_widget), "selection_get",
9941                     G_CALLBACK (selection_handle), (gpointer) &amp;have_selection);
9942
9943   gtk_widget_show (selection_button);
9944   gtk_widget_show (window);
9945   
9946   gtk_main ();
9947   
9948   return 0;
9949 }
9950 <!-- example-end -->
9951 </programlisting>
9952
9953 </sect1>
9954 </chapter>
9955
9956 <!-- ***************************************************************** -->
9957 <chapter id="ch-DragAngDrop">
9958 <title>Drag-and-drop (DND)</title>
9959
9960 <para>GTK+ has a high level set of functions for doing inter-process
9961 communication via the drag-and-drop system. GTK+ can perform
9962 drag-and-drop on top of the low level Xdnd and Motif drag-and-drop
9963 protocols.</para>
9964
9965 <!-- ----------------------------------------------------------------- -->
9966 <sect1 id="sec-DragAndDropOverview">
9967 <title>Overview</title>
9968
9969 <para>An application capable of GTK+ drag-and-drop first defines and sets up
9970 the GTK+ widget(s) for drag-and-drop. Each widget can be a source
9971 and/or destination for drag-and-drop. Note that these GTK+ widgets must have
9972 an associated X Window, check using GTK_WIDGET_NO_WINDOW(widget)).</para>
9973
9974 <para>Source widgets can send out drag data, thus allowing the user to drag
9975 things off of them, while destination widgets can receive drag data.
9976 Drag-and-drop destinations can limit who they accept drag data from,
9977 e.g. the same application or any application (including itself).</para>
9978
9979 <para>Sending and receiving drop data makes use of GTK+ signals.
9980 Dropping an item to a destination widget requires both a data
9981 request (for the source widget) and data received signal handler (for
9982 the target widget). Additional signal handers can be connected if you
9983 want to know when a drag begins (at the very instant it starts), to
9984 when a drop is made, and when the entire drag-and-drop procedure has
9985 ended (successfully or not).</para>
9986
9987 <para>Your application will need to provide data for source widgets when
9988 requested, that involves having a drag data request signal handler. For
9989 destination widgets they will need a drop data received signal
9990 handler. </para>
9991
9992 <para>So a typical drag-and-drop cycle would look as follows:</para>
9993 <orderedlist>
9994 <listitem><simpara> Drag begins.</simpara>
9995 </listitem>
9996 <listitem><simpara> Drag data request (when a drop occurs).</simpara>
9997 </listitem>
9998 <listitem><simpara> Drop data received (may be on same or different
9999 application).</simpara>
10000 </listitem>
10001 <listitem><simpara> Drag data delete (if the drag was a move).</simpara>
10002 </listitem>
10003 <listitem><simpara> Drag-and-drop procedure done.</simpara>
10004 </listitem>
10005 </orderedlist>
10006
10007 <para>There are a few minor steps that go in between here and there, but we
10008 will get into detail about that later.</para>
10009
10010 </sect1>
10011
10012 <!-- ----------------------------------------------------------------- -->
10013 <sect1 id="sec-DragAndDropProperties">
10014 <title>Properties</title>
10015
10016 <para>Drag data has the following properties:</para>
10017
10018 <itemizedlist>
10019 <listitem><simpara> Drag action type (ie GDK_ACTION_COPY, GDK_ACTION_MOVE).</simpara>
10020 </listitem>
10021
10022 <listitem><simpara> Client specified arbitrary drag-and-drop type (a name and number pair).</simpara>
10023 </listitem>
10024
10025 <listitem><simpara> Sent and received data format type.</simpara>
10026 </listitem>
10027 </itemizedlist>
10028
10029 <para>Drag actions are quite obvious, they specify if the widget can
10030 drag with the specified action(s), e.g. GDK_ACTION_COPY and/or
10031 GDK_ACTION_MOVE. A GDK_ACTION_COPY would be a typical drag-and-drop
10032 without the source data being deleted while GDK_ACTION_MOVE would be
10033 just like GDK_ACTION_COPY but the source data will be 'suggested' to be
10034 deleted after the received signal handler is called. There are
10035 additional drag actions including GDK_ACTION_LINK which you may want to
10036 look into when you get to more advanced levels of drag-and-drop.</para>
10037
10038 <para>The client specified arbitrary drag-and-drop type is much more
10039 flexible, because your application will be defining and checking for
10040 that specifically. You will need to set up your destination widgets to
10041 receive certain drag-and-drop types by specifying a name and/or number.
10042 It would be more reliable to use a name since another application may
10043 just happen to use the same number for an entirely different
10044 meaning.</para>
10045
10046 <para>Sent and received data format types (<emphasis>selection
10047 target</emphasis>) come into play only in your request and received
10048 data handler functions. The term <emphasis>selection target</emphasis>
10049 is somewhat misleading. It is a term adapted from GTK+ selection
10050 (cut/copy and paste). What <emphasis>selection target</emphasis>
10051 actually means is the data's format type (i.e. GdkAtom, integer, or
10052 string) that being sent or received. Your request data handler function
10053 needs to specify the type (<emphasis>selection target</emphasis>) of
10054 data that it sends out and your received data handler needs to handle
10055 the type (<emphasis>selection target</emphasis>) of data
10056 received.</para>
10057
10058 </sect1>
10059
10060 <!-- ----------------------------------------------------------------- -->
10061 <sect1 id="sec-DragAndDropFunctions">
10062 <title>Functions</title>
10063
10064 <!-- ----------------------------------------------------------------- -->
10065 <sect2 id="sec-DNDSourceWidgets">
10066 <title>Setting up the source widget</title>
10067
10068 <para>The function <literal>gtk_drag_source_set()</literal> specifies a
10069 set of target types for a drag operation on a widget.</para>
10070
10071 <programlisting role="C">
10072 void gtk_drag_source_set( GtkWidget            *widget,
10073                           GdkModifierType       start_button_mask,
10074                           const GtkTargetEntry *targets,
10075                           gint                  n_targets,
10076                           GdkDragAction         actions );
10077 </programlisting>
10078
10079 <para>The parameters signify the following:</para>
10080 <itemizedlist>
10081 <listitem><simpara><literal>widget</literal> specifies the drag source
10082 widget</simpara>
10083 </listitem>
10084 <listitem><simpara><literal>start_button_mask</literal> specifies a
10085 bitmask of buttons that can start the drag (e.g. GDK_BUTTON1_MASK)</simpara>
10086 </listitem>
10087 <listitem><simpara><literal>targets</literal> specifies a table of
10088 target data types the drag will support</simpara>
10089 </listitem>
10090 <listitem><simpara><literal>n_targets</literal> specifies the number of
10091 targets above</simpara>
10092 </listitem>
10093 <listitem><simpara><literal>actions</literal> specifies a bitmask of
10094 possible actions for a drag from this window</simpara>
10095 </listitem>
10096 </itemizedlist>
10097
10098 <para>The <literal>targets</literal> parameter is an array of the
10099 following structure:</para>
10100
10101 <programlisting role="C">
10102 struct GtkTargetEntry {
10103    gchar *target;
10104    guint  flags;
10105    guint  info;
10106  };
10107 </programlisting>
10108
10109 <para>The fields specify a string representing the drag type, optional
10110 flags and application assigned integer identifier.</para>
10111
10112 <para>If a widget is no longer required to act as a source for
10113 drag-and-drop operations, the function
10114 <literal>gtk_drag_source_unset()</literal> can be used to remove a set
10115 of drag-and-drop target types.</para>
10116
10117 <programlisting role="C">
10118 void gtk_drag_source_unset( GtkWidget *widget );
10119 </programlisting>
10120
10121 </sect2>
10122
10123 <!-- ----------------------------------------------------------------- -->
10124 <sect2 id="sec-SignalsOnSourceWidgets">
10125 <title>Signals on the source widget:</title>
10126
10127 <para>The source widget is sent the following signals during a
10128 drag-and-drop operation.</para>
10129
10130 <table pgwide="1">
10131 <title>Source widget signals</title>
10132 <tgroup cols="2">
10133 <colspec colname="Name" colwidth="150">
10134 <colspec colname="Prototype">
10135 <tbody>
10136 <row>
10137 <entry align="left" valign="middle">drag_begin</entry>
10138 <entry align="left" valign="middle"><literal>void (*drag_begin)(GtkWidget *widget,
10139 GdkDragContext *dc, gpointer data)</literal></entry>
10140 </row>
10141 <row>
10142 <entry align="left" valign="middle">drag_motion</entry>
10143 <entry align="left" valign="middle"><literal>gboolean (*drag_motion)(GtkWidget *widget,
10144 GdkDragContext *dc, gint x, gint y, guint t, gpointer data)</literal></entry>
10145 </row>
10146 <row>
10147 <entry align="left" valign="middle">drag_data_get</entry>
10148 <entry align="left" valign="middle"><literal>void (*drag_data_get)(GtkWidget *widget,
10149 GdkDragContext *dc, GtkSelectionData *selection_data, guint info, guint t, gpointer data)</literal></entry>
10150 </row>
10151 <row>
10152 <entry align="left" valign="middle">drag_data_delete</entry>
10153 <entry align="left" valign="middle"><literal>void (*drag_data_delete)(GtkWidget *widget,
10154 GdkDragContext *dc, gpointer data)</literal></entry>
10155 </row>
10156 <row>
10157 <entry align="left" valign="middle">drag_drop</entry>
10158 <entry align="left" valign="middle"><literal>gboolean (*drag_drop)(GtkWidget *widget,
10159 GdkDragContext *dc, gint x, gint y, guint t, gpointer data)</literal></entry>
10160 </row>
10161 <row>
10162 <entry align="left" valign="middle">drag_end</entry>
10163 <entry align="left" valign="middle"><literal>void (*drag_end)(GtkWidget *widget,
10164 GdkDragContext *dc, gpointer data)</literal></entry>
10165 </row>
10166 </tbody>
10167 </tgroup>
10168 </table>
10169
10170 </sect2>
10171
10172 <!-- ----------------------------------------------------------------- -->
10173 <sect2 id="sec-DNDDestWidgets">
10174 <title>Setting up a destination widget:</title>
10175
10176 <para> <literal> gtk_drag_dest_set()</literal> specifies
10177 that this widget can receive drops and specifies what types of drops it
10178 can receive.</para>
10179
10180 <para> <literal> gtk_drag_dest_unset()</literal> specifies
10181 that the widget can no longer receive drops.</para>
10182
10183 <programlisting role="C">
10184 void gtk_drag_dest_set( GtkWidget            *widget,
10185                         GtkDestDefaults       flags,
10186                         const GtkTargetEntry *targets,
10187                         gint                  n_targets,
10188                         GdkDragAction         actions );
10189
10190 void gtk_drag_dest_unset( GtkWidget *widget );
10191 </programlisting>
10192
10193 </sect2>
10194
10195 <!-- ----------------------------------------------------------------- -->
10196 <sect2 id="sec-SignalsOnDestWidgets">
10197 <title>Signals on the destination widget:</title>
10198
10199 <para>The destination widget is sent the following signals during a
10200 drag-and-drop operation.</para>
10201
10202 <table pgwide="1">
10203 <title>Destination widget signals</title>
10204 <tgroup cols="2">
10205 <colspec colname="Name" colwidth="150">
10206 <colspec colname="Prototype">
10207 <tbody>
10208 <row>
10209 <entry align="left" valign="middle">drag_data_received</entry>
10210 <entry align="left" valign="middle"><literal>void (*drag_data_received)(GtkWidget *widget,
10211 GdkDragContext *dc, gint x, gint y, GtkSelectionData *selection_data, guint info, guint t,
10212 gpointer data)</literal></entry>
10213 </row>
10214 </tbody>
10215 </tgroup>
10216 </table>
10217
10218 </sect2>
10219 </sect1>
10220 </chapter>
10221
10222 <!-- ***************************************************************** -->
10223 <chapter id="ch-GLib">
10224 <title>GLib</title>
10225
10226 <para>GLib is a lower-level library that provides many useful definitions
10227 and functions available for use when creating GDK and GTK
10228 applications. These include definitions for basic types and their
10229 limits, standard macros, type conversions, byte order, memory
10230 allocation, warnings and assertions, message logging, timers, string
10231 utilities, hook functions, a lexical scanner, dynamic loading of
10232 modules, and automatic string completion. A number of data structures
10233 (and their related operations) are also defined, including memory
10234 chunks, doubly-linked lists, singly-linked lists, hash tables, strings
10235 (which can grow dynamically), string chunks (groups of strings),
10236 arrays (which can grow in size as elements are added), balanced binary
10237 trees, N-ary trees, quarks (a two-way association of a string and a
10238 unique integer identifier), keyed data lists (lists of data elements
10239 accessible by a string or integer id), relations and tuples (tables of
10240 data which can be indexed on any number of fields), and caches.</para>
10241
10242 <para>A summary of some of GLib's capabilities follows; not every function,
10243 data structure, or operation is covered here.  For more complete
10244 information about the GLib routines, see the GLib documentation. One
10245 source of GLib documentation is <ulink url="http://www.gtk.org/">http://www.gtk.org/</ulink>.</para>
10246
10247 <para>If you are using a language other than C, you should consult your
10248 language's binding documentation. In some cases your language may
10249 have equivalent functionality built-in, while in other cases it may
10250 not.</para>
10251
10252 <!-- ----------------------------------------------------------------- -->
10253 <sect1 id="sec-Definitions">
10254 <title>Definitions</title>
10255
10256 <para>Definitions for the extremes of many of the standard types are:</para>
10257
10258 <programlisting role="C">
10259 G_MINFLOAT
10260 G_MAXFLOAT
10261 G_MINDOUBLE
10262 G_MAXDOUBLE
10263 G_MINSHORT
10264 G_MAXSHORT
10265 G_MAXUSHORT
10266 G_MININT
10267 G_MAXINT
10268 G_MAXUINT
10269 G_MINLONG
10270 G_MAXLONG
10271 G_MAXULONG
10272 G_MININT64
10273 G_MAXINT64
10274 G_MAXUINT64
10275 </programlisting>
10276
10277 <para>Also, the following typedefs. The ones left unspecified are dynamically set
10278 depending on the architecture. Remember to avoid counting on the size of a
10279 pointer if you want to be portable! E.g., a pointer on an Alpha is 8
10280 bytes, but 4 on Intel 80x86 family CPUs.</para>
10281
10282 <programlisting role="C">
10283 char   gchar;
10284 short  gshort;
10285 long   glong;
10286 int    gint;
10287 int    gboolean;
10288
10289 unsigned char   guchar;
10290 unsigned short  gushort;
10291 unsigned long   gulong;
10292 unsigned int    guint;
10293
10294 float   gfloat;
10295 double  gdouble;
10296
10297 unsigned int  gsize;
10298 signed int    gssize;
10299
10300 void*       gpointer;
10301 const void* gconstpointer;
10302
10303 gint8
10304 guint8
10305 gint16
10306 guint16
10307 gint32
10308 guint32
10309 gint64
10310 guint64
10311 </programlisting>
10312
10313 </sect1>
10314
10315 <!-- ----------------------------------------------------------------- -->
10316 <sect1 id="sec-DoublyLinkedLists">
10317 <title>Doubly Linked Lists</title>
10318
10319 <para>The following functions are used to create, manage, and destroy
10320 standard doubly linked lists. Each element in the list contains a
10321 piece of data, together with pointers which link to the previous and
10322 next elements in the list. This enables easy movement in either
10323 direction through the list. The data item is of type "gpointer",
10324 which means the data can be a pointer to your real data or (through
10325 casting) a numeric value (but do not assume that int and gpointer have
10326 the same size!). These routines internally allocate list elements in
10327 blocks, which is more efficient than allocating elements individually.</para>
10328
10329 <para>There is no function to specifically create a list. Instead, simply
10330 create a variable of type GList* and set its value to NULL; NULL is
10331 considered to be the empty list.</para>
10332
10333 <para>To add elements to a list, use the g_list_append(), g_list_prepend(),
10334 g_list_insert(), or g_list_insert_sorted() routines. In all cases
10335 they accept a pointer to the beginning of the list, and return the
10336 (possibly changed) pointer to the beginning of the list. Thus, for
10337 all of the operations that add or remove elements, be sure to save the
10338 returned value!</para>
10339
10340 <programlisting role="C">
10341 GList *g_list_append( GList    *list,
10342                       gpointer  data );
10343 </programlisting>
10344
10345 <para>This adds a new element (with value <literal>data</literal>) onto the end of the
10346 list.</para>
10347   
10348 <programlisting role="C">
10349 GList *g_list_prepend( GList    *list,
10350                        gpointer  data );
10351 </programlisting>
10352
10353 <para>This adds a new element (with value <literal>data</literal>) to the beginning of the
10354 list.</para>
10355
10356 <programlisting role="C">
10357 GList *g_list_insert( GList    *list,
10358                       gpointer  data,
10359                       gint      position );
10360 </programlisting>
10361
10362 <para>This inserts a new element (with value data) into the list at the
10363 given position. If position is 0, this is just like g_list_prepend();
10364 if position is less than 0, this is just like g_list_append().</para>
10365
10366 <programlisting role="C">
10367 GList *g_list_remove( GList    *list,
10368                       gpointer  data );
10369 </programlisting>
10370
10371 <para>This removes the element in the list with the value <literal>data</literal>;
10372 if the element isn't there, the list is unchanged.</para>
10373
10374 <programlisting role="C">
10375 void g_list_free( GList *list );
10376 </programlisting>
10377
10378 <para>This frees all of the memory used by a GList. If the list elements
10379 refer to dynamically-allocated memory, then they should be freed
10380 first.</para>
10381
10382 <para>There are many other GLib functions that support doubly linked lists;
10383 see the glib documentation for more information.  Here are a few of
10384 the more useful functions' signatures:</para>
10385
10386 <programlisting role="C">  
10387 GList *g_list_remove_link( GList *list,
10388                            GList *link );
10389
10390 GList *g_list_reverse( GList *list );
10391
10392 GList *g_list_nth( GList *list,
10393                    gint   n );
10394                            
10395 GList *g_list_find( GList    *list,
10396                     gpointer  data );
10397
10398 GList *g_list_last( GList *list );
10399
10400 GList *g_list_first( GList *list );
10401
10402 gint g_list_length( GList *list );
10403
10404 void g_list_foreach( GList    *list,
10405                      GFunc     func,
10406                      gpointer  user_data );
10407 </programlisting>
10408
10409 </sect1>
10410
10411 <!-- ----------------------------------------------------------------- -->
10412 <sect1 id="sec-SinglyLinkedLists">
10413 <title>Singly Linked Lists</title>
10414
10415 <para>Many of the above functions for singly linked lists are identical to the
10416 above. Here is a list of some of their operations:</para>
10417
10418 <programlisting role="C">
10419 GSList *g_slist_append( GSList   *list,
10420                         gpointer  data );
10421                 
10422 GSList *g_slist_prepend( GSList   *list,
10423                          gpointer  data );
10424                              
10425 GSList *g_slist_insert( GSList   *list,
10426                         gpointer  data,
10427                         gint      position );
10428                              
10429 GSList *g_slist_remove( GSList   *list,
10430                         gpointer  data );
10431                              
10432 GSList *g_slist_remove_link( GSList *list,
10433                              GSList *link );
10434                              
10435 GSList *g_slist_reverse( GSList *list );
10436
10437 GSList *g_slist_nth( GSList *list,
10438                      gint    n );
10439                              
10440 GSList *g_slist_find( GSList   *list,
10441                       gpointer  data );
10442                              
10443 GSList *g_slist_last( GSList *list );
10444
10445 gint g_slist_length( GSList *list );
10446
10447 void g_slist_foreach( GSList   *list,
10448                       GFunc     func,
10449                       gpointer  user_data );
10450         
10451 </programlisting>
10452
10453 </sect1>
10454
10455 <!-- ----------------------------------------------------------------- -->
10456 <sect1 id="sec-MemoryManagement">
10457 <title>Memory Management</title>
10458
10459 <programlisting role="C">
10460 gpointer g_malloc( gulong size );
10461 </programlisting>
10462
10463 <para>This is a replacement for malloc(). You do not need to check the return
10464 value as it is done for you in this function. If the memory allocation
10465 fails for whatever reasons, your applications will be terminated.</para>
10466
10467 <programlisting role="C">
10468 gpointer g_malloc0( gulong size );
10469 </programlisting>
10470
10471 <para>Same as above, but zeroes the memory before returning a pointer to it.</para>
10472
10473 <programlisting role="C">
10474 gpointer g_realloc( gpointer mem,
10475                     gulong   size );
10476 </programlisting>
10477
10478 <para>Relocates "size" bytes of memory starting at "mem".  Obviously, the
10479 memory should have been previously allocated.</para>
10480
10481 <programlisting role="C">
10482 void g_free( gpointer mem );
10483 </programlisting>
10484
10485 <para>Frees memory. Easy one. If <literal>mem</literal> is NULL it simply returns.</para>
10486
10487 <programlisting role="C">
10488 void g_mem_profile( void );
10489 </programlisting>
10490
10491 <para>Dumps a profile of used memory, but requires that you add <literal>#define
10492 MEM_PROFILE</literal> to the top of glib/gmem.c and re-make and make install.</para>
10493
10494 <programlisting role="C">
10495 void g_mem_check( gpointer mem );
10496 </programlisting>
10497
10498 <para>Checks that a memory location is valid. Requires you add <literal>#define
10499 MEM_CHECK</literal> to the top of gmem.c and re-make and make install.</para>
10500
10501 </sect1>
10502
10503 <!-- ----------------------------------------------------------------- -->
10504 <sect1 id="sec-Timers">
10505 <title>Timers</title>
10506
10507 <para>Timer functions can be used to time operations (e.g., to see how much
10508 time has elapsed). First, you create a new timer with g_timer_new().
10509 You can then use g_timer_start() to start timing an operation,
10510 g_timer_stop() to stop timing an operation, and g_timer_elapsed() to
10511 determine the elapsed time.</para>
10512
10513 <programlisting role="C">
10514 GTimer *g_timer_new( void );
10515
10516 void g_timer_destroy( GTimer *timer );
10517
10518 void g_timer_start( GTimer  *timer );
10519
10520 void g_timer_stop( GTimer  *timer );
10521
10522 void g_timer_reset( GTimer  *timer );
10523
10524 gdouble g_timer_elapsed( GTimer *timer,
10525                          gulong *microseconds );
10526 </programlisting>
10527
10528 </sect1>
10529
10530 <!-- ----------------------------------------------------------------- -->
10531 <sect1 id="sec-StringHandling">
10532 <title>String Handling</title>
10533
10534 <para>GLib defines a new type called a GString, which is similar to a
10535 standard C string but one that grows automatically. Its string data
10536 is null-terminated. What this gives you is protection from buffer
10537 overflow programming errors within your program. This is a very
10538 important feature, and hence I recommend that you make use of
10539 GStrings. GString itself has a simple public definition:</para>
10540
10541 <programlisting role="C">
10542 struct GString 
10543 {
10544   gchar *str; /* Points to the string's current \0-terminated value. */
10545   gint len; /* Current length */
10546 };
10547 </programlisting>
10548
10549 <para>As you might expect, there are a number of operations you can do with
10550 a GString.</para>
10551
10552 <programlisting role="C">
10553 GString *g_string_new( gchar *init );
10554 </programlisting>
10555
10556 <para>This constructs a GString, copying the string value of <literal>init</literal>
10557 into the GString and returning a pointer to it. NULL may be given as
10558 the argument for an initially empty GString.</para>
10559
10560 <programlisting role="C">
10561 void g_string_free( GString *string,
10562                     gint     free_segment );
10563 </programlisting>
10564
10565 <para>This frees the memory for the given GString. If <literal>free_segment</literal> is
10566 TRUE, then this also frees its character data.</para>
10567
10568 <programlisting role="C">            
10569 GString *g_string_assign( GString     *lval,
10570                           const gchar *rval );
10571 </programlisting>
10572
10573 <para>This copies the characters from rval into lval, destroying the
10574 previous contents of lval. Note that lval will be lengthened as
10575 necessary to hold the string's contents, unlike the standard strcpy()
10576 function.</para>
10577
10578 <para>The rest of these functions should be relatively obvious (the _c
10579 versions accept a character instead of a string):</para>
10580              
10581 <programlisting role="C">            
10582 GString *g_string_truncate( GString *string,
10583                             gint     len );
10584                              
10585 GString *g_string_append( GString *string,
10586                           gchar   *val );
10587                             
10588 GString *g_string_append_c( GString *string,
10589                             gchar    c );
10590         
10591 GString *g_string_prepend( GString *string,
10592                            gchar   *val );
10593                              
10594 GString *g_string_prepend_c( GString *string,
10595                              gchar    c );
10596         
10597 void g_string_sprintf( GString *string,
10598                        gchar   *fmt,
10599                        ...);
10600         
10601 void g_string_sprintfa ( GString *string,
10602                          gchar   *fmt,
10603                          ... );
10604 </programlisting>
10605
10606 </sect1>
10607
10608 <!-- ----------------------------------------------------------------- -->
10609 <sect1 id="sec-UtilityAndErrorFunctions">
10610 <title>Utility and Error Functions</title>
10611
10612 <programlisting role="C">
10613 gchar *g_strdup( const gchar *str );
10614 </programlisting>
10615
10616 <para>Replacement strdup function.  Copies the original strings contents to
10617 newly allocated memory, and returns a pointer to it.</para>
10618
10619 <programlisting role="C">
10620 gchar *g_strerror( gint errnum );
10621 </programlisting>
10622
10623 <para>I recommend using this for all error messages.  It's much nicer, and more
10624 portable than perror() or others.  The output is usually of the form:</para>
10625
10626 <programlisting role="C">
10627 program name:function that failed:file or further description:strerror
10628 </programlisting>
10629
10630 <para>Here's an example of one such call used in our hello_world program:</para>
10631
10632 <programlisting role="C">
10633 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
10634 </programlisting>
10635
10636 <programlisting role="C">
10637 void g_error( gchar *format, ... );
10638 </programlisting>
10639
10640 <para>Prints an error message. The format is just like printf, but it
10641 prepends "** ERROR **: " to your message, and exits the program.  
10642 Use only for fatal errors.</para>
10643
10644 <programlisting role="C">
10645 void g_warning( gchar *format, ... );
10646 </programlisting>
10647
10648 <para>Same as above, but prepends "** WARNING **: ", and does not exit the
10649 program.</para>
10650
10651 <programlisting role="C">
10652 void g_message( gchar *format, ... );
10653 </programlisting>
10654
10655 <para>Prints "message: " prepended to the string you pass in.</para>
10656
10657 <programlisting role="C">
10658 void g_print( gchar *format, ... );
10659 </programlisting>
10660
10661 <para>Replacement for printf().</para>
10662
10663 <para>And our last function:</para>
10664
10665 <programlisting role="C">
10666 gchar *g_strsignal( gint signum );
10667 </programlisting>
10668
10669 <para>Prints out the name of the Unix system signal given the signal number.
10670 Useful in generic signal handling functions.</para>
10671
10672 <para>All of the above are more or less just stolen from glib.h.  If anyone cares
10673 to document any function, just send me an email!</para>
10674
10675 </sect1>
10676 </chapter>
10677
10678 <!-- ***************************************************************** -->
10679 <chapter id="ch-GTKRCFiles">
10680 <title>GTK's rc Files</title>
10681
10682 <para>GTK has its own way of dealing with application defaults, by using rc
10683 files. These can be used to set the colors of just about any widget, and
10684 can also be used to tile pixmaps onto the background of some widgets.  </para>
10685
10686 <!-- ----------------------------------------------------------------- -->
10687 <sect1 id="sec-FunctionsForRCFiles">
10688 <title>Functions For rc Files</title>
10689
10690 <para>When your application starts, you should include a call to:</para>
10691
10692 <programlisting role="C">
10693 void gtk_rc_parse( char *filename );
10694 </programlisting>
10695
10696 <para>Passing in the filename of your rc file. This will cause GTK to parse
10697 this file, and use the style settings for the widget types defined
10698 there.</para>
10699
10700 <para>If you wish to have a special set of widgets that can take on a
10701 different style from others, or any other logical division of widgets,
10702 use a call to:</para>
10703
10704 <programlisting role="C">
10705 void gtk_widget_set_name( GtkWidget *widget,
10706                           gchar     *name );
10707 </programlisting>
10708
10709 <para>Passing your newly created widget as the first argument, and the name
10710 you wish to give it as the second. This will allow you to change the
10711 attributes of this widget by name through the rc file.</para>
10712
10713 <para>If we use a call something like this:</para>
10714
10715 <programlisting role="C">
10716 button = gtk_button_new_with_label ("Special Button");
10717 gtk_widget_set_name (button, "special button");
10718 </programlisting>
10719
10720 <para>Then this button is given the name "special button" and may be addressed by
10721 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]</para>
10722
10723 <para>The example rc file below, sets the properties of the main window, and lets
10724 all children of that main window inherit the style described by the "main
10725 button" style.  The code used in the application is:</para>
10726
10727 <programlisting role="C">
10728 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10729 gtk_widget_set_name (window, "main window");
10730 </programlisting>
10731
10732 <para>And then the style is defined in the rc file using:</para>
10733
10734 <programlisting role="C">
10735 widget "main window.*GtkButton*" style "main_button"
10736 </programlisting>
10737
10738 <para>Which sets all the Button widgets in the "main window" to the
10739 "main_buttons" style as defined in the rc file.</para>
10740
10741 <para>As you can see, this is a fairly powerful and flexible system.  Use your
10742 imagination as to how best to take advantage of this.</para>
10743
10744 </sect1>
10745
10746 <!-- ----------------------------------------------------------------- -->
10747 <sect1 id="sec-GTKsRCFileFormat">
10748 <title>GTK's rc File Format</title>
10749
10750 <para>The format of the GTK file is illustrated in the example below. This is
10751 the testgtkrc file from the GTK distribution, but I've added a
10752 few comments and things. You may wish to include this explanation in
10753 your application to allow the user to fine tune his application.</para>
10754
10755 <para>There are several directives to change the attributes of a widget.</para>
10756
10757 <itemizedlist>
10758 <listitem><simpara>fg - Sets the foreground color of a widget.</simpara>
10759 </listitem>
10760 <listitem><simpara>bg - Sets the background color of a widget.</simpara>
10761 </listitem>
10762 <listitem><simpara>bg_pixmap - Sets the background of a widget to a tiled pixmap.</simpara>
10763 </listitem>
10764 <listitem><simpara>font - Sets the font to be used with the given widget.</simpara>
10765 </listitem>
10766 </itemizedlist>
10767
10768 <para>In addition to this, there are several states a widget can be in, and you
10769 can set different colors, pixmaps and fonts for each state. These states are:</para>
10770
10771 <itemizedlist>
10772 <listitem><simpara>NORMAL - The normal state of a widget, without the mouse over top of
10773 it, and not being pressed, etc.</simpara>
10774 </listitem>
10775 <listitem><simpara>PRELIGHT - When the mouse is over top of the widget, colors defined
10776 using this state will be in effect.</simpara>
10777 </listitem>
10778 <listitem><simpara>ACTIVE - When the widget is pressed or clicked it will be active, and
10779 the attributes assigned by this tag will be in effect.</simpara>
10780 </listitem>
10781 <listitem><simpara>INSENSITIVE - When a widget is set insensitive, and cannot be
10782 activated, it will take these attributes.</simpara>
10783 </listitem>
10784 <listitem><simpara>SELECTED - When an object is selected, it takes these attributes.</simpara>
10785 </listitem>
10786 </itemizedlist>
10787
10788 <para>When using the "fg" and "bg" keywords to set the colors of widgets, the
10789 format is:</para>
10790
10791 <programlisting role="C">
10792 fg[&lt;STATE>] = { Red, Green, Blue }
10793 </programlisting>
10794
10795 <para>Where STATE is one of the above states (PRELIGHT, ACTIVE, etc), and the Red,
10796 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
10797 white. They must be in float form, or they will register as 0, so a straight 
10798 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
10799 doesn't matter if it's not recognized.  Unrecognized values are set to 0.</para>
10800
10801 <para>bg_pixmap is very similar to the above, except the colors are replaced by a
10802 filename.</para>
10803
10804 <para>pixmap_path is a list of paths separated by ":"'s.  These paths will be
10805 searched for any pixmap you specify.</para>
10806
10807 <para>The font directive is simply:</para>
10808
10809 <programlisting role="C">
10810 font = "&lt;font name>"
10811 </programlisting>
10812
10813 <para>The only hard part is figuring out the font string. Using xfontsel or
10814 a similar utility should help.</para>
10815
10816 <para>The "widget_class" sets the style of a class of widgets. These classes are
10817 listed in the widget overview on the class hierarchy.</para>
10818
10819 <para>The "widget" directive sets a specifically named set of widgets to a
10820 given style, overriding any style set for the given widget class.
10821 These widgets are registered inside the application using the
10822 gtk_widget_set_name() call. This allows you to specify the attributes of a
10823 widget on a per widget basis, rather than setting the attributes of an
10824 entire widget class. I urge you to document any of these special widgets so
10825 users may customize them.</para>
10826
10827 <para>When the keyword <literal>parent</> is used as an attribute, the widget will take on
10828 the attributes of its parent in the application.</para>
10829
10830 <para>When defining a style, you may assign the attributes of a previously defined
10831 style to this new one.</para>
10832
10833 <programlisting role="C">
10834 style "main_button" = "button"
10835 {
10836   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
10837   bg[PRELIGHT] = { 0.75, 0, 0 }
10838 }
10839 </programlisting>
10840
10841 <para>This example takes the "button" style, and creates a new "main_button" style
10842 simply by changing the font and prelight background color of the "button"
10843 style.</para>
10844
10845 <para>Of course, many of these attributes don't apply to all widgets. It's a
10846 simple matter of common sense really. Anything that could apply, should.</para>
10847
10848 </sect1>
10849
10850 <!-- ----------------------------------------------------------------- -->
10851 <sect1 id="sec-ExampleRCFile">
10852 <title>Example rc file</title>
10853
10854 <programlisting role="C">
10855 # pixmap_path "&lt;dir 1>:&lt;dir 2>:&lt;dir 3>:..."
10856 #
10857 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
10858 #
10859 # style &lt;name> [= &lt;name>]
10860 # {
10861 #   &lt;option>
10862 # }
10863 #
10864 # widget &lt;widget_set> style &lt;style_name>
10865 # widget_class &lt;widget_class_set> style &lt;style_name>
10866
10867 # Here is a list of all the possible states.  Note that some do not apply to
10868 # certain widgets.
10869 #
10870 # NORMAL - The normal state of a widget, without the mouse over top of
10871 # it, and not being pressed, etc.
10872 #
10873 # PRELIGHT - When the mouse is over top of the widget, colors defined
10874 # using this state will be in effect.
10875 #
10876 # ACTIVE - When the widget is pressed or clicked it will be active, and
10877 # the attributes assigned by this tag will be in effect.
10878 #
10879 # INSENSITIVE - When a widget is set insensitive, and cannot be
10880 # activated, it will take these attributes.
10881 #
10882 # SELECTED - When an object is selected, it takes these attributes.
10883 #
10884 # Given these states, we can set the attributes of the widgets in each of
10885 # these states using the following directives.
10886 #
10887 # fg - Sets the foreground color of a widget.
10888 # fg - Sets the background color of a widget.
10889 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
10890 # font - Sets the font to be used with the given widget.
10891 #
10892
10893 # This sets a style called "button".  The name is not really important, as
10894 # it is assigned to the actual widgets at the bottom of the file.
10895
10896 style "window"
10897 {
10898   #This sets the padding around the window to the pixmap specified.
10899   #bg_pixmap[&lt;STATE>] = "&lt;pixmap filename>"
10900   bg_pixmap[NORMAL] = "warning.xpm"
10901 }
10902
10903 style "scale"
10904 {
10905   #Sets the foreground color (font color) to red when in the "NORMAL"
10906   #state.
10907   
10908   fg[NORMAL] = { 1.0, 0, 0 }
10909   
10910   #Sets the background pixmap of this widget to that of its parent.
10911   bg_pixmap[NORMAL] = "&lt;parent>"
10912 }
10913
10914 style "button"
10915 {
10916   # This shows all the possible states for a button.  The only one that
10917   # doesn't apply is the SELECTED state.
10918   
10919   fg[PRELIGHT] = { 0, 1.0, 1.0 }
10920   bg[PRELIGHT] = { 0, 0, 1.0 }
10921   bg[ACTIVE] = { 1.0, 0, 0 }
10922   fg[ACTIVE] = { 0, 1.0, 0 }
10923   bg[NORMAL] = { 1.0, 1.0, 0 }
10924   fg[NORMAL] = { .99, 0, .99 }
10925   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
10926   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
10927 }
10928
10929 # In this example, we inherit the attributes of the "button" style and then
10930 # override the font and background color when prelit to create a new
10931 # "main_button" style.
10932
10933 style "main_button" = "button"
10934 {
10935   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
10936   bg[PRELIGHT] = { 0.75, 0, 0 }
10937 }
10938
10939 style "toggle_button" = "button"
10940 {
10941   fg[NORMAL] = { 1.0, 0, 0 }
10942   fg[ACTIVE] = { 1.0, 0, 0 }
10943   
10944   # This sets the background pixmap of the toggle_button to that of its
10945   # parent widget (as defined in the application).
10946   bg_pixmap[NORMAL] = "&lt;parent>"
10947 }
10948
10949 style "text"
10950 {
10951   bg_pixmap[NORMAL] = "marble.xpm"
10952   fg[NORMAL] = { 1.0, 1.0, 1.0 }
10953 }
10954
10955 style "ruler"
10956 {
10957   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
10958 }
10959
10960 # pixmap_path "~/.pixmaps"
10961
10962 # These set the widget types to use the styles defined above.
10963 # The widget types are listed in the class hierarchy, but could probably be
10964 # just listed in this document for the users reference.
10965
10966 widget_class "GtkWindow" style "window"
10967 widget_class "GtkDialog" style "window"
10968 widget_class "GtkFileSelection" style "window"
10969 widget_class "*Gtk*Scale" style "scale"
10970 widget_class "*GtkCheckButton*" style "toggle_button"
10971 widget_class "*GtkRadioButton*" style "toggle_button"
10972 widget_class "*GtkButton*" style "button"
10973 widget_class "*Ruler" style "ruler"
10974 widget_class "*GtkText" style "text"
10975
10976 # This sets all the buttons that are children of the "main window" to
10977 # the main_button style.  These must be documented to be taken advantage of.
10978 widget "main window.*GtkButton*" style "main_button"
10979 </programlisting>
10980
10981 </sect1>
10982 </chapter>
10983
10984 <!-- ***************************************************************** -->
10985 <chapter id="ch-WritingYourOwnWidgets">
10986 <title>Writing Your Own Widgets</title>
10987
10988 <!-- ----------------------------------------------------------------- -->
10989 <sect1 id="sec-WidgetsOverview">
10990 <title>Overview</title>
10991
10992 <para>Although the GTK distribution comes with many types of widgets that
10993 should cover most basic needs, there may come a time when you need to
10994 create your own new widget type. Since GTK uses widget inheritance
10995 extensively, and there is already a widget that is close to what you want,
10996 it is often possible to make a useful new widget type in
10997 just a few lines of code. But before starting work on a new widget, check
10998 around first to make sure that someone has not already written
10999 it. This will prevent duplication of effort and keep the number of
11000 GTK widgets out there to a minimum, which will help keep both the code
11001 and the interface of different applications consistent. As a flip side
11002 to this, once you finish your widget, announce it to the world so
11003 other people can benefit. The best place to do this is probably the
11004 <literal>gtk-list</literal>.</para>
11005
11006 <para>Complete sources for the example widgets are available at the place you 
11007 got this tutorial, or from:</para>
11008
11009 <para><ulink url="http://www.gtk.org/~otaylor/gtk/tutorial/">http://www.gtk.org/~otaylor/gtk/tutorial/</ulink></para>
11010
11011
11012 </sect1>
11013
11014 <!-- ----------------------------------------------------------------- -->
11015 <sect1 id="sec-TheAnatomyOfAWidget">
11016 <title>The Anatomy Of A Widget</title>
11017
11018 <para>In order to create a new widget, it is important to have an
11019 understanding of how GTK objects work. This section is just meant as a
11020 brief overview. See the reference documentation for the details. </para>
11021
11022 <para>GTK widgets are implemented in an object oriented fashion. However,
11023 they are implemented in standard C. This greatly improves portability
11024 and stability over using current generation C++ compilers; however,
11025 it does mean that the widget writer has to pay attention to some of
11026 the implementation details. The information common to all instances of
11027 one class of widgets (e.g., to all Button widgets) is stored in the 
11028 <emphasis>class structure</emphasis>. There is only one copy of this in
11029 which is stored information about the class's signals
11030 (which act like virtual functions in C). To support inheritance, the
11031 first field in the class structure must be a copy of the parent's
11032 class structure. The declaration of the class structure of GtkButtton
11033 looks like:</para>
11034
11035 <programlisting role="C">
11036 struct _GtkButtonClass
11037 {
11038   GtkContainerClass parent_class;
11039
11040   void (* pressed)  (GtkButton *button);
11041   void (* released) (GtkButton *button);
11042   void (* clicked)  (GtkButton *button);
11043   void (* enter)    (GtkButton *button);
11044   void (* leave)    (GtkButton *button);
11045 };
11046 </programlisting>
11047
11048 <para>When a button is treated as a container (for instance, when it is
11049 resized), its class structure can be cast to GtkContainerClass, and
11050 the relevant fields used to handle the signals.</para>
11051
11052 <para>There is also a structure for each widget that is created on a
11053 per-instance basis. This structure has fields to store information that
11054 is different for each instance of the widget. We'll call this
11055 structure the <emphasis>object structure</emphasis>. For the Button class, it looks
11056 like:</para>
11057
11058 <programlisting role="C">
11059 struct _GtkButton
11060 {
11061   GtkContainer container;
11062
11063   GtkWidget *child;
11064
11065   guint in_button : 1;
11066   guint button_down : 1;
11067 };
11068 </programlisting>
11069
11070 <para>Note that, similar to the class structure, the first field is the
11071 object structure of the parent class, so that this structure can be
11072 cast to the parent class' object structure as needed.</para>
11073
11074 </sect1>
11075
11076 <!-- ----------------------------------------------------------------- -->
11077 <sect1 id="sec-CreatingACompositeWidget">
11078 <title>Creating a Composite widget</title>
11079
11080 <!-- ----------------------------------------------------------------- -->
11081 <sect2>
11082 <title>Introduction</title>
11083
11084 <para>One type of widget that you may be interested in creating is a
11085 widget that is merely an aggregate of other GTK widgets. This type of
11086 widget does nothing that couldn't be done without creating new
11087 widgets, but provides a convenient way of packaging user interface
11088 elements for reuse. The FileSelection and ColorSelection widgets in
11089 the standard distribution are examples of this type of widget.</para>
11090
11091 <para>The example widget that we'll create in this section is the Tictactoe
11092 widget, a 3x3 array of toggle buttons which triggers a signal when all
11093 three buttons in a row, column, or on one of the diagonals are
11094 depressed. </para>
11095
11096 <para><emphasis>Note: the full source code for the Tictactoe example described
11097 below is in the <link linkend="sec-Tictactoe">Code Examples Appendix</link>
11098 </emphasis></para>
11099
11100 <para>
11101 <inlinemediaobject>
11102 <imageobject>
11103 <imagedata fileref="images/tictactoe.png" format="png">
11104 </imageobject>
11105 </inlinemediaobject>
11106 </para>
11107
11108 </sect2>
11109
11110 <!-- ----------------------------------------------------------------- -->
11111 <sect2>
11112 <title>Choosing a parent class</title>
11113
11114 <para>The parent class for a composite widget is typically the container
11115 class that holds all of the elements of the composite widget. For
11116 example, the parent class of the FileSelection widget is the
11117 Dialog class. Since our buttons will be arranged in a table, it
11118 is natural to make our parent class the Table class.</para>
11119
11120 </sect2>
11121
11122 <!-- ----------------------------------------------------------------- -->
11123 <sect2>
11124 <title>The header file</title>
11125
11126 <para>Each GObject class has a header file which declares the object and
11127 class structures for that object, along with public functions. 
11128 A couple of features are worth pointing out. To prevent duplicate
11129 definitions, we wrap the entire header file in:</para>
11130
11131 <programlisting role="C">
11132 #ifndef __TICTACTOE_H__
11133 #define __TICTACTOE_H__
11134 .
11135 .
11136 .
11137 #endif /* __TICTACTOE_H__ */
11138 </programlisting>
11139
11140 <para>And to keep C++ programs that include the header file happy, in:</para>
11141
11142 <programlisting role="C">
11143 #include &lt;glib.h&gt;
11144
11145 G_BEGIN_DECLS
11146 .
11147 .
11148 .
11149 G_END_DECLS
11150 </programlisting>
11151
11152 <para>Along with the functions and structures, we declare five standard
11153 macros in our header file, <literal>TICTACTOE_TYPE</literal>,
11154 <literal>TICTACTOE(obj)</literal>,
11155 <literal>TICTACTOE_CLASS(klass)</literal>,
11156 <literal>IS_TICTACTOE(obj)</literal>, and
11157 <literal>IS_TICTACTOE_CLASS(klass)</literal>, which cast a
11158 pointer into a pointer to the object or class structure, and check
11159 if an object is a Tictactoe widget respectively.</para>
11160
11161 </sect2>
11162
11163 <!-- ----------------------------------------------------------------- -->
11164 <sect2>
11165 <title>The <literal>_get_type()</literal> function</title>
11166
11167 <para>We now continue on to the implementation of our widget. A core
11168 function for every object is the function
11169 <literal>WIDGETNAME_get_type()</literal>. This function, when first called, tells
11170 Glib about the new class, and gets an ID that uniquely identifies
11171 the class. Upon subsequent calls, it just returns the ID.</para>
11172
11173 <programlisting role="C">
11174 GType
11175 tictactoe_get_type (void)
11176 {
11177   static GType ttt_type = 0;
11178
11179   if (!ttt_type)
11180     {
11181       static const GTypeInfo ttt_info =
11182       {
11183         sizeof (TictactoeClass),
11184         NULL, /* base_init */
11185         NULL, /* base_finalize */
11186         (GClassInitFunc) tictactoe_class_init,
11187         NULL, /* class_finalize */
11188         NULL, /* class_data */
11189         sizeof (Tictactoe),
11190         0,    /* n_preallocs */
11191         (GInstanceInitFunc) tictactoe_init,
11192       };
11193
11194       ttt_type = g_type_register_static (GTK_TYPE_TABLE,
11195                                          "Tictactoe",
11196                                          &amp;ttt_info,
11197                                          0);
11198     }
11199
11200   return ttt_type;
11201 }
11202 </programlisting>
11203
11204 <para>The GTypeInfo structure has the following definition:</para>
11205
11206 <programlisting role="C">
11207 struct _GTypeInfo
11208 {
11209   /* interface types, classed types, instantiated types */
11210   guint16                class_size;
11211    
11212   GBaseInitFunc          base_init;
11213   GBaseFinalizeFunc      base_finalize;
11214    
11215   /* classed types, instantiated types */
11216   GClassInitFunc         class_init;
11217   GClassFinalizeFunc     class_finalize;
11218   gconstpointer          class_data;
11219    
11220   /* instantiated types */
11221   guint16                instance_size;
11222   guint16                n_preallocs;
11223   GInstanceInitFunc      instance_init;
11224    
11225   /* value handling */
11226   const GTypeValueTable *value_table;
11227 };
11228 </programlisting>
11229
11230 <para>The important fields of this structure are pretty self-explanatory.
11231 We'll ignore the <literal>base_init</literal> and
11232  <literal>base_finalize</literal> as well as the <literal>value_table</literal>
11233 fields here. Once Glib has a correctly filled in copy of
11234 this structure, it knows how to create objects of a particular type. </para>
11235
11236 </sect2>
11237
11238 <!-- ----------------------------------------------------------------- -->
11239 <sect2>
11240 <title>The <literal>_class_init()</literal> function</title>
11241
11242 <para>The <literal>WIDGETNAME_class_init()</literal> function initializes the fields of
11243 the widget's class structure, and sets up any signals for the
11244 class. For our Tictactoe widget it looks like:</para>
11245
11246 <programlisting role="C">
11247 enum {
11248   TICTACTOE_SIGNAL,
11249   LAST_SIGNAL
11250 };
11251
11252
11253 static guint tictactoe_signals[LAST_SIGNAL] = { 0 };
11254
11255 static void
11256 tictactoe_class_init (TictactoeClass *klass)
11257 {
11258   tictactoe_signals[TICTACTOE_SIGNAL] =
11259     g_signal_new ("tictactoe",
11260                   G_TYPE_FROM_CLASS (klass),
11261                   G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
11262                   G_STRUCT_OFFSET (TictactoeClass, tictactoe),
11263                   NULL, NULL,
11264                   g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
11265 }
11266 </programlisting>
11267
11268 <para>Our widget has just one signal, the <literal>tictactoe</literal> signal that is
11269 invoked when a row, column, or diagonal is completely filled in. Not
11270 every composite widget needs signals, so if you are reading this for
11271 the first time, you may want to skip to the next section now, as
11272 things are going to get a bit complicated.</para>
11273
11274 <para>The function:</para>
11275
11276 <programlisting role="C">
11277 guint g_signal_new( const gchar         *signal_name,
11278                     GType                itype,
11279                     GSignalFlags         signal_flags,
11280                     guint                class_offset,
11281                     GSignalAccumulator  *accumulator,
11282                     gpointer             accu_data,
11283                     GSignalCMarshaller  *c_marshaller,
11284                     GType                return_type,
11285                     guint                n_params,
11286                     ...);
11287 </programlisting>
11288
11289 <para>Creates a new signal. The parameters are:</para>
11290
11291 <itemizedlist>
11292 <listitem><simpara> <literal>signal_name</literal>: The name of the signal.</simpara>
11293 </listitem>
11294
11295 <listitem><simpara> <literal>itype</literal>: The ID of the object that this signal applies
11296 to. (It will also apply to that objects descendants.)</simpara>
11297 </listitem>
11298                                                                                 
11299 <listitem><simpara> <literal>signal_flags</literal>: Whether the default handler runs before or after
11300 user handlers and other flags. Usually this will be one of
11301 <literal>G_SIGNAL_RUN_FIRST</literal> or <literal>G_SIGNAL_RUN_LAST</literal>,
11302 although there are other possibilities. The flag
11303 <literal>G_SIGNAL_ACTION</literal> specifies that no extra code needs to
11304 run that performs special pre or post emission adjustments. This means that
11305 the signal can also be emitted from object external code.</simpara>
11306 </listitem>
11307
11308 <listitem><simpara> <literal>class_offset</literal>: The offset within the class structure of
11309 a pointer to the default handler.</simpara>
11310 </listitem>
11311
11312 <listitem><simpara> <literal>accumulator</literal>: For most classes this can
11313 be set to NULL.</simpara></listitem>
11314
11315 <listitem><simpara> <literal>accu_data</literal>: User data that will be handed
11316 to the accumulator function.</simpara></listitem>
11317
11318 <listitem><simpara> <literal>c_marshaller</literal>: A function that is used to invoke the signal
11319 handler. For signal handlers that have no arguments other than the
11320 object that emitted the signal and user data, we can use the
11321 pre-supplied marshaller function <literal>g_cclosure_marshal_VOID__VOID</literal>.</simpara>
11322 </listitem>
11323
11324 <listitem><simpara> <literal>return_type</literal>: The type of the return value.</simpara>
11325 </listitem>
11326
11327 <listitem><simpara> <literal>n_params</literal>: The number of parameters of the signal handler
11328 (other than the two default ones mentioned above)</simpara>
11329 </listitem>
11330
11331 <listitem><simpara> <literal>...</literal>: The types of the parameters.</simpara>
11332 </listitem>
11333 </itemizedlist>
11334
11335 <para>When specifying types, the following standard types can be used:</para>
11336
11337 <programlisting role="C">
11338 G_TYPE_INVALID
11339 G_TYPE_NONE
11340 G_TYPE_INTERFACE
11341 G_TYPE_CHAR
11342 G_TYPE_UCHAR
11343 G_TYPE_BOOLEAN
11344 G_TYPE_INT
11345 G_TYPE_UINT
11346 G_TYPE_LONG
11347 G_TYPE_ULONG
11348 G_TYPE_INT64
11349 G_TYPE_UINT64
11350 G_TYPE_ENUM
11351 G_TYPE_FLAGS
11352 G_TYPE_FLOAT
11353 G_TYPE_DOUBLE
11354 G_TYPE_STRING
11355 G_TYPE_POINTER
11356 G_TYPE_BOXED
11357 G_TYPE_PARAM
11358 G_TYPE_OBJECT
11359 </programlisting>
11360
11361 <para><literal>g_signal_new()</literal> returns a unique integer identifier for the
11362 signal, that we store in the <literal>tictactoe_signals</literal> array, which we
11363 index using an enumeration. (Conventionally, the enumeration elements
11364 are the signal name, uppercased, but here there would be a conflict
11365 with the <literal>TICTACTOE()</literal> macro, so we called it <literal>TICTACTOE_SIGNAL</literal>
11366 instead.</para>
11367
11368 </sect2>
11369
11370 <!-- ----------------------------------------------------------------- -->
11371 <sect2>
11372 <title>The <literal>_init()</literal> function</title>
11373
11374 <para>Each class also needs a function to initialize the object
11375 structure. Usually, this function has the fairly limited role of
11376 setting the fields of the structure to default values. For composite
11377 widgets, however, this function also creates the component widgets.</para>
11378
11379 <programlisting role="C">
11380 static void
11381 tictactoe_init (Tictactoe *ttt)
11382 {
11383   gint i,j;
11384
11385   gtk_table_resize (GTK_TABLE (ttt), 3, 3);
11386   gtk_table_set_homogeneous (GTK_TABLE (ttt), TRUE);
11387
11388   for (i=0;i&lt;3; i++)
11389     for (j=0;j&lt;3; j++)
11390       {
11391         ttt->buttons[i][j] = gtk_toggle_button_new ();
11392         gtk_table_attach_defaults (GTK_TABLE (ttt), ttt->buttons[i][j], 
11393                                    i, i+1, j, j+1);
11394         g_signal_connect (G_OBJECT (ttt->buttons[i][j]), "toggled",
11395                           G_CALLBACK (tictactoe_toggle), ttt);
11396         gtk_widget_set_size_request (ttt->buttons[i][j], 20, 20);
11397         gtk_widget_show (ttt->buttons[i][j]);
11398       }
11399 }
11400 </programlisting>
11401
11402 </sect2>
11403
11404 <!-- ----------------------------------------------------------------- -->
11405 <sect2>
11406 <title>And the rest...</title>
11407
11408 <para>There is one more function that every object (except for abstract
11409 classes like Bin that cannot be instantiated) needs to have - the
11410 function that the user calls to create an object of that type. This is
11411 conventionally called <literal>OBJECTNAME_new()</literal>. In some
11412 widgets, though not for the Tictactoe widgets, this function takes
11413 arguments, and does some setup based on the arguments. The other two
11414 functions are specific to the Tictactoe widget. </para>
11415
11416 <para><literal>tictactoe_clear()</literal> is a public function that resets all the
11417 buttons in the widget to the up position. Note the use of
11418 <literal>g_signal_handlers_block_matched()</literal> to keep our signal handler for
11419 button toggles from being triggered unnecessarily.</para>
11420
11421 <para><literal>tictactoe_toggle()</literal> is the signal handler that is invoked when the
11422 user clicks on a button. It checks to see if there are any winning
11423 combinations that involve the toggled button, and if so, emits
11424 the "tictactoe" signal.</para>
11425
11426 <programlisting role="C">
11427 GtkWidget*
11428 tictactoe_new (void)
11429 {
11430   return GTK_WIDGET ( g_object_new (TICTACTOE_TYPE, NULL));
11431 }
11432
11433 void           
11434 tictactoe_clear (Tictactoe *ttt)
11435 {
11436   int i,j;
11437
11438   for (i=0;i&lt;3;i++)
11439     for (j=0;j&lt;3;j++)
11440       {
11441         g_signal_handlers_block_matched (G_OBJECT (ttt->buttons[i][j]),
11442                                          G_SIGNAL_MATCH_DATA,
11443                                          0, 0, NULL, NULL, ttt);
11444         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
11445                                      FALSE);
11446         g_signal_handlers_unblock_matched (G_OBJECT (ttt->buttons[i][j]),
11447                                            G_SIGNAL_MATCH_DATA,
11448                                            0, 0, NULL, NULL, ttt);
11449       }
11450 }
11451
11452 static void
11453 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
11454 {
11455   int i,k;
11456
11457   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
11458                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
11459                              { 0, 1, 2 }, { 0, 1, 2 } };
11460   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
11461                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
11462                              { 0, 1, 2 }, { 2, 1, 0 } };
11463
11464   int success, found;
11465
11466   for (k=0; k&lt;8; k++)
11467     {
11468       success = TRUE;
11469       found = FALSE;
11470
11471       for (i=0;i&lt;3;i++)
11472         {
11473           success = success &amp;&amp; 
11474             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
11475           found = found ||
11476             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
11477         }
11478       
11479       if (success &amp;&amp; found)
11480         {
11481           g_signal_emit (G_OBJECT (ttt), 
11482                          tictactoe_signals[TICTACTOE_SIGNAL], 0);
11483           break;
11484         }
11485     }
11486 }
11487 </programlisting>
11488
11489 <para>And finally, an example program using our Tictactoe widget:</para>
11490
11491 <programlisting role="C">
11492 #include &lt;gtk/gtk.h&gt;
11493 #include "tictactoe.h"
11494
11495 /* Invoked when a row, column or diagonal is completed */
11496 void
11497 win (GtkWidget *widget, gpointer data)
11498 {
11499   g_print ("Yay!\n");
11500   tictactoe_clear (TICTACTOE (widget));
11501 }
11502
11503 int 
11504 main (int argc, char *argv[])
11505 {
11506   GtkWidget *window;
11507   GtkWidget *ttt;
11508   
11509   gtk_init (&amp;argc, &amp;argv);
11510
11511   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11512   
11513   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
11514   
11515   g_signal_connect (G_OBJECT (window), "destroy",
11516                     G_CALLBACK (exit), NULL);
11517   
11518   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11519
11520   /* Create a new Tictactoe widget */
11521   ttt = tictactoe_new ();
11522   gtk_container_add (GTK_CONTAINER (window), ttt);
11523   gtk_widget_show (ttt);
11524
11525   /* And attach to its "tictactoe" signal */
11526   g_signal_connect (G_OBJECT (ttt), "tictactoe",
11527                     G_CALLBACK (win), NULL);
11528
11529   gtk_widget_show (window);
11530   
11531   gtk_main ();
11532   
11533   return 0;
11534 }
11535 </programlisting>
11536
11537 </sect2>
11538 </sect1>
11539
11540 <!-- ----------------------------------------------------------------- -->
11541 <sect1 id="sec-CreatingAWidgetFromScratch">
11542 <title>Creating a widget from scratch</title>
11543
11544 <!-- ----------------------------------------------------------------- -->
11545 <sect2>
11546 <title>Introduction</title>
11547
11548 <para>In this section, we'll learn more about how widgets display themselves
11549 on the screen and interact with events. As an example of this, we'll
11550 create an analog dial widget with a pointer that the user can drag to
11551 set the value.</para>
11552
11553 <para>
11554 <inlinemediaobject>
11555 <imageobject>
11556 <imagedata fileref="images/gtkdial.png" format="png">
11557 </imageobject>
11558 </inlinemediaobject>
11559 </para>
11560
11561 </sect2>
11562
11563 <!-- ----------------------------------------------------------------- -->
11564 <sect2>
11565 <title>Displaying a widget on the screen</title>
11566
11567 <para>There are several steps that are involved in displaying on the screen.
11568 After the widget is created with a call to <literal>WIDGETNAME_new()</literal>,
11569 several more functions are needed:</para>
11570
11571 <itemizedlist>
11572 <listitem><simpara> <literal>WIDGETNAME_realize()</literal> is responsible for creating an X
11573 window for the widget if it has one.</simpara>
11574 </listitem>
11575 <listitem><simpara> <literal>WIDGETNAME_map()</literal> is invoked after the user calls
11576 <literal>gtk_widget_show()</literal>. It is responsible for making sure the widget
11577 is actually drawn on the screen (<emphasis>mapped</emphasis>). For a container class,
11578 it must also make calls to <literal>map()</literal> functions of any child widgets.</simpara>
11579 </listitem>
11580 <listitem><simpara> <literal>WIDGETNAME_draw()</literal> is invoked when <literal>gtk_widget_draw()</literal>
11581 is called for the widget or one of its ancestors. It makes the actual
11582 calls to the drawing functions to draw the widget on the screen. For
11583 container widgets, this function must make calls to
11584 <literal>gtk_widget_draw()</literal> for its child widgets.</simpara>
11585 </listitem>
11586 <listitem><simpara> <literal>WIDGETNAME_expose()</literal> is a handler for expose events for the
11587 widget. It makes the necessary calls to the drawing functions to draw
11588 the exposed portion on the screen. For container widgets, this
11589 function must generate expose events for its child widgets which don't
11590 have their own windows. (If they have their own windows, then X will
11591 generate the necessary expose events.)</simpara>
11592 </listitem>
11593 </itemizedlist>
11594
11595 <para>You might notice that the last two functions are quite similar - each
11596 is responsible for drawing the widget on the screen. In fact many
11597 types of widgets don't really care about the difference between the
11598 two. The default <literal>draw()</literal> function in the widget class simply
11599 generates a synthetic expose event for the redrawn area. However, some
11600 types of widgets can save work by distinguishing between the two
11601 functions. For instance, if a widget has multiple X windows, then
11602 since expose events identify the exposed window, it can redraw only
11603 the affected window, which is not possible for calls to <literal>draw()</literal>.</para>
11604
11605 <para>Container widgets, even if they don't care about the difference for
11606 themselves, can't simply use the default <literal>draw()</literal> function because
11607 their child widgets might care about the difference. However,
11608 it would be wasteful to duplicate the drawing code between the two
11609 functions. The convention is that such widgets have a function called
11610 <literal>WIDGETNAME_paint()</literal> that does the actual work of drawing the
11611 widget, that is then called by the <literal>draw()</literal> and <literal>expose()</literal>
11612 functions.</para>
11613
11614 <para>In our example approach, since the dial widget is not a container
11615 widget, and only has a single window, we can take the simplest
11616 approach and use the default <literal>draw()</literal> function and only implement
11617 an <literal>expose()</literal> function.</para>
11618
11619 </sect2>
11620
11621 <!-- ----------------------------------------------------------------- -->
11622 <sect2>
11623 <title>The origins of the Dial Widget</title>
11624
11625 <para>Just as all land animals are just variants on the first amphibian that
11626 crawled up out of the mud, GTK widgets tend to start off as variants
11627 of some other, previously written widget. Thus, although this section
11628 is entitled "Creating a Widget from Scratch", the Dial widget really
11629 began with the source code for the Range widget. This was picked as a
11630 starting point because it would be nice if our Dial had the same
11631 interface as the Scale widgets which are just specialized descendants
11632 of the Range widget. So, though the source code is presented below in
11633 finished form, it should not be implied that it was written, <emphasis>ab
11634 initio</emphasis> in this fashion. Also, if you aren't yet familiar with
11635 how scale widgets work from the application writer's point of view, it
11636 would be a good idea to look them over before continuing.</para>
11637
11638 </sect2>
11639
11640 <!-- ----------------------------------------------------------------- -->
11641 <sect2>
11642 <title>The Basics</title>
11643
11644 <para>Quite a bit of our widget should look pretty familiar from the
11645 Tictactoe widget. First, we have a header file:</para>
11646
11647 <programlisting role="C">
11648 /* GTK - The GIMP Toolkit
11649  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
11650  *
11651  * This library is free software; you can redistribute it and/or
11652  * modify it under the terms of the GNU Library General Public
11653  * License as published by the Free Software Foundation; either
11654  * version 2 of the License, or (at your option) any later version.
11655  *
11656  * This library is distributed in the hope that it will be useful,
11657  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11658  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11659  * Library General Public License for more details.
11660  *
11661  * You should have received a copy of the GNU Library General Public
11662  * License along with this library; if not, write to the Free
11663  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
11664  */
11665
11666 #ifndef __GTK_DIAL_H__
11667 #define __GTK_DIAL_H__
11668
11669 #include &lt;gdk/gdk.h&gt;
11670 #include &lt;gtk/gtkadjustment.h&gt;
11671 #include &lt;gtk/gtkwidget.h&gt;
11672
11673
11674 #ifdef __cplusplus
11675 extern "C" {
11676 #endif /* __cplusplus */
11677
11678
11679 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
11680 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
11681 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
11682
11683
11684 typedef struct _GtkDial        GtkDial;
11685 typedef struct _GtkDialClass   GtkDialClass;
11686
11687 struct _GtkDial
11688 {
11689   GtkWidget widget;
11690
11691   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
11692   guint policy : 2;
11693
11694   /* Button currently pressed or 0 if none */
11695   guint8 button;
11696
11697   /* Dimensions of dial components */
11698   gint radius;
11699   gint pointer_width;
11700
11701   /* ID of update timer, or 0 if none */
11702   guint32 timer;
11703
11704   /* Current angle */
11705   gfloat angle;
11706
11707   /* Old values from adjustment stored so we know when something changes */
11708   gfloat old_value;
11709   gfloat old_lower;
11710   gfloat old_upper;
11711
11712   /* The adjustment object that stores the data for this dial */
11713   GtkAdjustment *adjustment;
11714 };
11715
11716 struct _GtkDialClass
11717 {
11718   GtkWidgetClass parent_class;
11719 };
11720
11721
11722 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
11723 GtkType        gtk_dial_get_type               (void);
11724 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
11725 void           gtk_dial_set_update_policy      (GtkDial      *dial,
11726                                                 GtkUpdateType  policy);
11727
11728 void           gtk_dial_set_adjustment         (GtkDial      *dial,
11729                                                 GtkAdjustment *adjustment);
11730 #ifdef __cplusplus
11731 }
11732 #endif /* __cplusplus */
11733
11734
11735 #endif /* __GTK_DIAL_H__ */
11736 </programlisting>
11737
11738 <para>Since there is quite a bit more going on in this widget than the last
11739 one, we have more fields in the data structure, but otherwise things
11740 are pretty similar.</para>
11741
11742 <para>Next, after including header files and declaring a few constants,
11743 we have some functions to provide information about the widget
11744 and initialize it:</para>
11745
11746 <programlisting role="C">
11747 #include &lt;math.h&gt;
11748 #include &lt;stdio.h&gt;
11749 #include &lt;gtk/gtkmain.h&gt;
11750 #include &lt;gtk/gtksignal.h&gt;
11751
11752 #include "gtkdial.h"
11753
11754 #define SCROLL_DELAY_LENGTH  300
11755 #define DIAL_DEFAULT_SIZE 100
11756
11757 /* Forward declarations */
11758
11759 [ omitted to save space ]
11760
11761 /* Local data */
11762
11763 static GtkWidgetClass *parent_class = NULL;
11764
11765 GtkType
11766 gtk_dial_get_type ()
11767 {
11768   static GtkType dial_type = 0;
11769
11770   if (!dial_type)
11771     {
11772       static const GtkTypeInfo dial_info =
11773       {
11774         "GtkDial",
11775         sizeof (GtkDial),
11776         sizeof (GtkDialClass),
11777         (GtkClassInitFunc) gtk_dial_class_init,
11778         (GtkObjectInitFunc) gtk_dial_init,
11779         /* reserved_1 */ NULL,
11780         /* reserved_1 */ NULL,
11781         (GtkClassInitFunc) NULL
11782       };
11783
11784       dial_type = gtk_type_unique (GTK_TYPE_WIDGET, &amp;dial_info);
11785     }
11786
11787   return dial_type;
11788 }
11789
11790 static void
11791 gtk_dial_class_init (GtkDialClass *class)
11792 {
11793   GtkObjectClass *object_class;
11794   GtkWidgetClass *widget_class;
11795
11796   object_class = (GtkObjectClass*) class;
11797   widget_class = (GtkWidgetClass*) class;
11798
11799   parent_class = gtk_type_class (gtk_widget_get_type ());
11800
11801   object_class->destroy = gtk_dial_destroy;
11802
11803   widget_class->realize = gtk_dial_realize;
11804   widget_class->expose_event = gtk_dial_expose;
11805   widget_class->size_request = gtk_dial_size_request;
11806   widget_class->size_allocate = gtk_dial_size_allocate;
11807   widget_class->button_press_event = gtk_dial_button_press;
11808   widget_class->button_release_event = gtk_dial_button_release;
11809   widget_class->motion_notify_event = gtk_dial_motion_notify;
11810 }
11811
11812 static void
11813 gtk_dial_init (GtkDial *dial)
11814 {
11815   dial->button = 0;
11816   dial->policy = GTK_UPDATE_CONTINUOUS;
11817   dial->timer = 0;
11818   dial->radius = 0;
11819   dial->pointer_width = 0;
11820   dial->angle = 0.0;
11821   dial->old_value = 0.0;
11822   dial->old_lower = 0.0;
11823   dial->old_upper = 0.0;
11824   dial->adjustment = NULL;
11825 }
11826
11827 GtkWidget*
11828 gtk_dial_new (GtkAdjustment *adjustment)
11829 {
11830   GtkDial *dial;
11831
11832   dial = gtk_type_new (gtk_dial_get_type ());
11833
11834   if (!adjustment)
11835     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
11836
11837   gtk_dial_set_adjustment (dial, adjustment);
11838
11839   return GTK_WIDGET (dial);
11840 }
11841
11842 static void
11843 gtk_dial_destroy (GtkObject *object)
11844 {
11845   GtkDial *dial;
11846
11847   g_return_if_fail (object != NULL);
11848   g_return_if_fail (GTK_IS_DIAL (object));
11849
11850   dial = GTK_DIAL (object);
11851
11852   if (dial->adjustment)
11853     gtk_object_unref (GTK_OBJECT (dial->adjustment));
11854
11855   if (GTK_OBJECT_CLASS (parent_class)->destroy)
11856     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
11857 }
11858 </programlisting>
11859
11860 <para>Note that this <literal>init()</literal> function does less than for the Tictactoe
11861 widget, since this is not a composite widget, and the <literal>new()</literal>
11862 function does more, since it now has an argument. Also, note that when
11863 we store a pointer to the Adjustment object, we increment its
11864 reference count, (and correspondingly decrement it when we no longer
11865 use it) so that GTK can keep track of when it can be safely destroyed.</para>
11866
11867 <para>Also, there are a few function to manipulate the widget's options:</para>
11868
11869 <programlisting role="C">
11870 GtkAdjustment*
11871 gtk_dial_get_adjustment (GtkDial *dial)
11872 {
11873   g_return_val_if_fail (dial != NULL, NULL);
11874   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
11875
11876   return dial->adjustment;
11877 }
11878
11879 void
11880 gtk_dial_set_update_policy (GtkDial      *dial,
11881                              GtkUpdateType  policy)
11882 {
11883   g_return_if_fail (dial != NULL);
11884   g_return_if_fail (GTK_IS_DIAL (dial));
11885
11886   dial->policy = policy;
11887 }
11888
11889 void
11890 gtk_dial_set_adjustment (GtkDial      *dial,
11891                           GtkAdjustment *adjustment)
11892 {
11893   g_return_if_fail (dial != NULL);
11894   g_return_if_fail (GTK_IS_DIAL (dial));
11895
11896   if (dial->adjustment)
11897     {
11898       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
11899       gtk_object_unref (GTK_OBJECT (dial->adjustment));
11900     }
11901
11902   dial->adjustment = adjustment;
11903   gtk_object_ref (GTK_OBJECT (dial->adjustment));
11904
11905   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
11906                       (GtkSignalFunc) gtk_dial_adjustment_changed,
11907                       (gpointer) dial);
11908   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
11909                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
11910                       (gpointer) dial);
11911
11912   dial->old_value = adjustment->value;
11913   dial->old_lower = adjustment->lower;
11914   dial->old_upper = adjustment->upper;
11915
11916   gtk_dial_update (dial);
11917 }
11918 </programlisting>
11919
11920 </sect2>
11921
11922 <!-- ----------------------------------------------------------------- -->
11923 <sect2>
11924 <title><literal>gtk_dial_realize()</literal></title>
11925
11926 <para>Now we come to some new types of functions. First, we have a function
11927 that does the work of creating the X window. Notice that a mask is
11928 passed to the function <literal>gdk_window_new()</literal> which specifies which fields of
11929 the GdkWindowAttr structure actually have data in them (the remaining
11930 fields will be given default values). Also worth noting is the way the
11931 event mask of the widget is created. We call
11932 <literal>gtk_widget_get_events()</literal> to retrieve the event mask that the user
11933 has specified for this widget (with <literal>gtk_widget_set_events()</literal>), and
11934 add the events that we are interested in ourselves.</para>
11935
11936 <para>After creating the window, we set its style and background, and put a
11937 pointer to the widget in the user data field of the GdkWindow. This
11938 last step allows GTK to dispatch events for this window to the correct
11939 widget.</para>
11940
11941 <programlisting role="C">
11942 static void
11943 gtk_dial_realize (GtkWidget *widget)
11944 {
11945   GtkDial *dial;
11946   GdkWindowAttr attributes;
11947   gint attributes_mask;
11948
11949   g_return_if_fail (widget != NULL);
11950   g_return_if_fail (GTK_IS_DIAL (widget));
11951
11952   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
11953   dial = GTK_DIAL (widget);
11954
11955   attributes.x = widget->allocation.x;
11956   attributes.y = widget->allocation.y;
11957   attributes.width = widget->allocation.width;
11958   attributes.height = widget->allocation.height;
11959   attributes.wclass = GDK_INPUT_OUTPUT;
11960   attributes.window_type = GDK_WINDOW_CHILD;
11961   attributes.event_mask = gtk_widget_get_events (widget) | 
11962     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
11963     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
11964     GDK_POINTER_MOTION_HINT_MASK;
11965   attributes.visual = gtk_widget_get_visual (widget);
11966   attributes.colormap = gtk_widget_get_colormap (widget);
11967
11968   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
11969   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
11970
11971   widget->style = gtk_style_attach (widget->style, widget->window);
11972
11973   gdk_window_set_user_data (widget->window, widget);
11974
11975   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
11976 }
11977 </programlisting>
11978
11979 </sect2>
11980
11981 <!-- ----------------------------------------------------------------- -->
11982 <sect2>
11983 <title>Size negotiation</title>
11984
11985 <para>Before the first time that the window containing a widget is
11986 displayed, and whenever the layout of the window changes, GTK asks
11987 each child widget for its desired size. This request is handled by the
11988 function <literal>gtk_dial_size_request()</literal>. Since our widget isn't a
11989 container widget, and has no real constraints on its size, we just
11990 return a reasonable default value.</para>
11991
11992 <programlisting role="C">
11993 static void 
11994 gtk_dial_size_request (GtkWidget      *widget,
11995                        GtkRequisition *requisition)
11996 {
11997   requisition->width = DIAL_DEFAULT_SIZE;
11998   requisition->height = DIAL_DEFAULT_SIZE;
11999 }
12000 </programlisting>
12001
12002 <para>After all the widgets have requested an ideal size, the layout of the
12003 window is computed and each child widget is notified of its actual
12004 size. Usually, this will be at least as large as the requested size,
12005 but if for instance the user has resized the window, it may
12006 occasionally be smaller than the requested size. The size notification
12007 is handled by the function <literal>gtk_dial_size_allocate()</literal>. Notice that
12008 as well as computing the sizes of some component pieces for future
12009 use, this routine also does the grunt work of moving the widget's X
12010 window into the new position and size.</para>
12011
12012 <programlisting role="C">
12013 static void
12014 gtk_dial_size_allocate (GtkWidget     *widget,
12015                         GtkAllocation *allocation)
12016 {
12017   GtkDial *dial;
12018
12019   g_return_if_fail (widget != NULL);
12020   g_return_if_fail (GTK_IS_DIAL (widget));
12021   g_return_if_fail (allocation != NULL);
12022
12023   widget->allocation = *allocation;
12024   if (GTK_WIDGET_REALIZED (widget))
12025     {
12026       dial = GTK_DIAL (widget);
12027
12028       gdk_window_move_resize (widget->window,
12029                               allocation->x, allocation->y,
12030                               allocation->width, allocation->height);
12031
12032       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
12033       dial->pointer_width = dial->radius / 5;
12034     }
12035 }
12036 </programlisting>
12037
12038 </sect2>
12039
12040 <!-- ----------------------------------------------------------------- -->
12041 <sect2>
12042 <title><literal>gtk_dial_expose()</literal></title>
12043
12044 <para>As mentioned above, all the drawing of this widget is done in the
12045 handler for expose events. There's not much to remark on here except
12046 the use of the function <literal>gtk_draw_polygon</literal> to draw the pointer with
12047 three dimensional shading according to the colors stored in the
12048 widget's style.</para>
12049
12050 <programlisting role="C">
12051 static gboolean
12052 gtk_dial_expose( GtkWidget      *widget,
12053                  GdkEventExpose *event )
12054 {
12055   GtkDial *dial;
12056   GdkPoint points[3];
12057   gdouble s,c;
12058   gdouble theta;
12059   gint xc, yc;
12060   gint tick_length;
12061   gint i;
12062
12063   g_return_val_if_fail (widget != NULL, FALSE);
12064   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12065   g_return_val_if_fail (event != NULL, FALSE);
12066
12067   if (event->count > 0)
12068     return FALSE;
12069   
12070   dial = GTK_DIAL (widget);
12071
12072   gdk_window_clear_area (widget->window,
12073                          0, 0,
12074                          widget->allocation.width,
12075                          widget->allocation.height);
12076
12077   xc = widget->allocation.width/2;
12078   yc = widget->allocation.height/2;
12079
12080   /* Draw ticks */
12081
12082   for (i=0; i<25; i++)
12083     {
12084       theta = (i*M_PI/18. - M_PI/6.);
12085       s = sin(theta);
12086       c = cos(theta);
12087
12088       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
12089       
12090       gdk_draw_line (widget->window,
12091                      widget->style->fg_gc[widget->state],
12092                      xc + c*(dial->radius - tick_length),
12093                      yc - s*(dial->radius - tick_length),
12094                      xc + c*dial->radius,
12095                      yc - s*dial->radius);
12096     }
12097
12098   /* Draw pointer */
12099
12100   s = sin(dial->angle);
12101   c = cos(dial->angle);
12102
12103
12104   points[0].x = xc + s*dial->pointer_width/2;
12105   points[0].y = yc + c*dial->pointer_width/2;
12106   points[1].x = xc + c*dial->radius;
12107   points[1].y = yc - s*dial->radius;
12108   points[2].x = xc - s*dial->pointer_width/2;
12109   points[2].y = yc - c*dial->pointer_width/2;
12110
12111   gtk_draw_polygon (widget->style,
12112                     widget->window,
12113                     GTK_STATE_NORMAL,
12114                     GTK_SHADOW_OUT,
12115                     points, 3,
12116                     TRUE);
12117   
12118   return FALSE;
12119 }
12120 </programlisting>
12121
12122 </sect2>
12123
12124 <!-- ----------------------------------------------------------------- -->
12125 <sect2>
12126 <title>Event handling</title>
12127
12128 <para>The rest of the widget's code handles various types of events, and
12129 isn't too different from what would be found in many GTK
12130 applications. Two types of events can occur - either the user can
12131 click on the widget with the mouse and drag to move the pointer, or
12132 the value of the Adjustment object can change due to some external
12133 circumstance.</para>
12134
12135 <para>When the user clicks on the widget, we check to see if the click was
12136 appropriately near the pointer, and if so, store the button that the
12137 user clicked with in the <literal>button</literal> field of the widget
12138 structure, and grab all mouse events with a call to
12139 <literal>gtk_grab_add()</literal>. Subsequent motion of the mouse causes the
12140 value of the control to be recomputed (by the function
12141 <literal>gtk_dial_update_mouse</literal>). Depending on the policy that has been
12142 set, "value_changed" events are either generated instantly
12143 (<literal>GTK_UPDATE_CONTINUOUS</literal>), after a delay in a timer added with
12144 <literal>gtk_timeout_add()</literal> (<literal>GTK_UPDATE_DELAYED</literal>), or only when the
12145 button is released (<literal>GTK_UPDATE_DISCONTINUOUS</literal>).</para>
12146
12147 <programlisting role="C">
12148 static gboolean
12149 gtk_dial_button_press( GtkWidget      *widget,
12150                        GdkEventButton *event )
12151 {
12152   GtkDial *dial;
12153   gint dx, dy;
12154   double s, c;
12155   double d_parallel;
12156   double d_perpendicular;
12157
12158   g_return_val_if_fail (widget != NULL, FALSE);
12159   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12160   g_return_val_if_fail (event != NULL, FALSE);
12161
12162   dial = GTK_DIAL (widget);
12163
12164   /* Determine if button press was within pointer region - we 
12165      do this by computing the parallel and perpendicular distance of
12166      the point where the mouse was pressed from the line passing through
12167      the pointer */
12168   
12169   dx = event->x - widget->allocation.width / 2;
12170   dy = widget->allocation.height / 2 - event->y;
12171   
12172   s = sin(dial->angle);
12173   c = cos(dial->angle);
12174   
12175   d_parallel = s*dy + c*dx;
12176   d_perpendicular = fabs(s*dx - c*dy);
12177   
12178   if (!dial->button &&
12179       (d_perpendicular < dial->pointer_width/2) &&
12180       (d_parallel > - dial->pointer_width))
12181     {
12182       gtk_grab_add (widget);
12183
12184       dial->button = event->button;
12185
12186       gtk_dial_update_mouse (dial, event->x, event->y);
12187     }
12188
12189   return FALSE;
12190 }
12191
12192 static gboolean
12193 gtk_dial_button_release( GtkWidget      *widget,
12194                          GdkEventButton *event )
12195 {
12196   GtkDial *dial;
12197
12198   g_return_val_if_fail (widget != NULL, FALSE);
12199   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12200   g_return_val_if_fail (event != NULL, FALSE);
12201
12202   dial = GTK_DIAL (widget);
12203
12204   if (dial->button == event->button)
12205     {
12206       gtk_grab_remove (widget);
12207
12208       dial->button = 0;
12209
12210       if (dial->policy == GTK_UPDATE_DELAYED)
12211         gtk_timeout_remove (dial->timer);
12212       
12213       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
12214           (dial->old_value != dial->adjustment->value))
12215         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12216     }
12217
12218   return FALSE;
12219 }
12220
12221 static gboolean
12222 gtk_dial_motion_notify( GtkWidget      *widget,
12223                         GdkEventMotion *event )
12224 {
12225   GtkDial *dial;
12226   GdkModifierType mods;
12227   gint x, y, mask;
12228
12229   g_return_val_if_fail (widget != NULL, FALSE);
12230   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12231   g_return_val_if_fail (event != NULL, FALSE);
12232
12233   dial = GTK_DIAL (widget);
12234
12235   if (dial->button != 0)
12236     {
12237       x = event->x;
12238       y = event->y;
12239
12240       if (event->is_hint || (event->window != widget->window))
12241         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
12242
12243       switch (dial->button)
12244         {
12245         case 1:
12246           mask = GDK_BUTTON1_MASK;
12247           break;
12248         case 2:
12249           mask = GDK_BUTTON2_MASK;
12250           break;
12251         case 3:
12252           mask = GDK_BUTTON3_MASK;
12253           break;
12254         default:
12255           mask = 0;
12256           break;
12257         }
12258
12259       if (mods & mask)
12260         gtk_dial_update_mouse (dial, x,y);
12261     }
12262
12263   return FALSE;
12264 }
12265
12266 static gboolean
12267 gtk_dial_timer( GtkDial *dial )
12268 {
12269   g_return_val_if_fail (dial != NULL, FALSE);
12270   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
12271
12272   if (dial->policy == GTK_UPDATE_DELAYED)
12273     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12274
12275   return FALSE;
12276 }
12277
12278 static void
12279 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
12280 {
12281   gint xc, yc;
12282   gfloat old_value;
12283
12284   g_return_if_fail (dial != NULL);
12285   g_return_if_fail (GTK_IS_DIAL (dial));
12286
12287   xc = GTK_WIDGET(dial)->allocation.width / 2;
12288   yc = GTK_WIDGET(dial)->allocation.height / 2;
12289
12290   old_value = dial->adjustment->value;
12291   dial->angle = atan2(yc-y, x-xc);
12292
12293   if (dial->angle < -M_PI/2.)
12294     dial->angle += 2*M_PI;
12295
12296   if (dial->angle < -M_PI/6)
12297     dial->angle = -M_PI/6;
12298
12299   if (dial->angle > 7.*M_PI/6.)
12300     dial->angle = 7.*M_PI/6.;
12301
12302   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
12303     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
12304
12305   if (dial->adjustment->value != old_value)
12306     {
12307       if (dial->policy == GTK_UPDATE_CONTINUOUS)
12308         {
12309           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12310         }
12311       else
12312         {
12313           gtk_widget_draw (GTK_WIDGET(dial), NULL);
12314
12315           if (dial->policy == GTK_UPDATE_DELAYED)
12316             {
12317               if (dial->timer)
12318                 gtk_timeout_remove (dial->timer);
12319
12320               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
12321                                              (GtkFunction) gtk_dial_timer,
12322                                              (gpointer) dial);
12323             }
12324         }
12325     }
12326 }
12327 </programlisting>
12328
12329 <para>Changes to the Adjustment by external means are communicated to our
12330 widget by the "changed" and "value_changed" signals. The handlers
12331 for these functions call <literal>gtk_dial_update()</literal> to validate the
12332 arguments, compute the new pointer angle, and redraw the widget (by
12333 calling <literal>gtk_widget_draw()</literal>).</para>
12334
12335 <programlisting role="C">
12336 static void
12337 gtk_dial_update (GtkDial *dial)
12338 {
12339   gfloat new_value;
12340   
12341   g_return_if_fail (dial != NULL);
12342   g_return_if_fail (GTK_IS_DIAL (dial));
12343
12344   new_value = dial->adjustment->value;
12345   
12346   if (new_value < dial->adjustment->lower)
12347     new_value = dial->adjustment->lower;
12348
12349   if (new_value > dial->adjustment->upper)
12350     new_value = dial->adjustment->upper;
12351
12352   if (new_value != dial->adjustment->value)
12353     {
12354       dial->adjustment->value = new_value;
12355       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12356     }
12357
12358   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
12359     (dial->adjustment->upper - dial->adjustment->lower);
12360
12361   gtk_widget_draw (GTK_WIDGET(dial), NULL);
12362 }
12363
12364 static void
12365 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
12366                               gpointer       data)
12367 {
12368   GtkDial *dial;
12369
12370   g_return_if_fail (adjustment != NULL);
12371   g_return_if_fail (data != NULL);
12372
12373   dial = GTK_DIAL (data);
12374
12375   if ((dial->old_value != adjustment->value) ||
12376       (dial->old_lower != adjustment->lower) ||
12377       (dial->old_upper != adjustment->upper))
12378     {
12379       gtk_dial_update (dial);
12380
12381       dial->old_value = adjustment->value;
12382       dial->old_lower = adjustment->lower;
12383       dial->old_upper = adjustment->upper;
12384     }
12385 }
12386
12387 static void
12388 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
12389                                     gpointer       data)
12390 {
12391   GtkDial *dial;
12392
12393   g_return_if_fail (adjustment != NULL);
12394   g_return_if_fail (data != NULL);
12395
12396   dial = GTK_DIAL (data);
12397
12398   if (dial->old_value != adjustment->value)
12399     {
12400       gtk_dial_update (dial);
12401
12402       dial->old_value = adjustment->value;
12403     }
12404 }
12405 </programlisting>
12406
12407 </sect2>
12408
12409 <!-- ----------------------------------------------------------------- -->
12410 <sect2>
12411 <title>Possible Enhancements</title>
12412
12413 <para>The Dial widget as we've described it so far runs about 670 lines of
12414 code. Although that might sound like a fair bit, we've really
12415 accomplished quite a bit with that much code, especially since much of
12416 that length is headers and boilerplate. However, there are quite a few
12417 more enhancements that could be made to this widget:</para>
12418
12419 <itemizedlist>
12420 <listitem><simpara> If you try this widget out, you'll find that there is some
12421 flashing as the pointer is dragged around. This is because the entire
12422 widget is erased every time the pointer is moved before being
12423 redrawn. Often, the best way to handle this problem is to draw to an
12424 offscreen pixmap, then copy the final results onto the screen in one
12425 step. (The ProgressBar widget draws itself in this fashion.)</simpara>
12426 </listitem>
12427
12428 <listitem><simpara> The user should be able to use the up and down arrow keys to
12429 increase and decrease the value.</simpara>
12430 </listitem>
12431
12432 <listitem><simpara> It would be nice if the widget had buttons to increase and
12433 decrease the value in small or large steps. Although it would be
12434 possible to use embedded Button widgets for this, we would also like
12435 the buttons to auto-repeat when held down, as the arrows on a
12436 scrollbar do. Most of the code to implement this type of behavior can
12437 be found in the Range widget.</simpara>
12438 </listitem>
12439
12440 <listitem><simpara> The Dial widget could be made into a container widget with a
12441 single child widget positioned at the bottom between the buttons
12442 mentioned above. The user could then add their choice of a label or
12443 entry widget to display the current value of the dial.</simpara>
12444 </listitem>
12445 </itemizedlist>
12446
12447 </sect2>
12448 </sect1>
12449
12450 <!-- ----------------------------------------------------------------- -->
12451 <sect1 id="sec-LearningMore">
12452 <title>Learning More</title>
12453
12454 <para>Only a small part of the many details involved in creating widgets
12455 could be described above. If you want to write your own widgets, the
12456 best source of examples is the GTK source itself. Ask yourself some
12457 questions about the widget you want to write: IS it a Container
12458 widget? Does it have its own window? Is it a modification of an
12459 existing widget? Then find a similar widget, and start making changes.
12460 Good luck!</para>
12461
12462 </sect1>
12463 </chapter>
12464
12465 <!-- ***************************************************************** -->
12466 <chapter id="ch-Scribble">
12467 <title>Scribble, A Simple Example Drawing Program</title>
12468
12469 <!-- ----------------------------------------------------------------- -->
12470 <sect1 id="sec-ScribbleOverview">
12471 <title>Overview</title>
12472
12473 <para>In this section, we will build a simple drawing program. In the
12474 process, we will examine how to handle mouse events, how to draw in a
12475 window, and how to do drawing better by using a backing pixmap. After
12476 creating the simple drawing program, we will extend it by adding
12477 support for XInput devices, such as drawing tablets. GTK provides
12478 support routines which makes getting extended information, such as
12479 pressure and tilt, from such devices quite easy.</para>
12480
12481 <para>
12482 <inlinemediaobject>
12483 <imageobject>
12484 <imagedata fileref="images/scribble.png" format="png">
12485 </imageobject>
12486 </inlinemediaobject>
12487 </para>
12488
12489 </sect1>
12490
12491 <!-- ----------------------------------------------------------------- -->
12492 <sect1 id="sec-EventHandling">
12493 <title>Event Handling</title>
12494
12495 <para>The GTK signals we have already discussed are for high-level actions,
12496 such as a menu item being selected. However, sometimes it is useful to
12497 learn about lower-level occurrences, such as the mouse being moved, or
12498 a key being pressed. There are also GTK signals corresponding to these
12499 low-level <emphasis>events</emphasis>. The handlers for these signals have an
12500 extra parameter which is a pointer to a structure containing
12501 information about the event. For instance, motion event handlers are
12502 passed a pointer to a GdkEventMotion structure which looks (in part)
12503 like:</para>
12504
12505 <programlisting role="C">
12506 struct _GdkEventMotion
12507 {
12508   GdkEventType type;
12509   GdkWindow *window;
12510   guint32 time;
12511   gdouble x;
12512   gdouble y;
12513   ...
12514   guint state;
12515   ...
12516 };
12517 </programlisting>
12518
12519 <para><literal>type</literal> will be set to the event type, in this case
12520 <literal>GDK_MOTION_NOTIFY</literal>, window is the window in which the event
12521 occurred. <literal>x</literal> and <literal>y</literal> give the coordinates of the event.
12522 <literal>state</literal> specifies the modifier state when the event
12523 occurred (that is, it specifies which modifier keys and mouse buttons
12524 were pressed). It is the bitwise OR of some of the following:</para>
12525
12526 <programlisting role="C">
12527 GDK_SHIFT_MASK  
12528 GDK_LOCK_MASK   
12529 GDK_CONTROL_MASK
12530 GDK_MOD1_MASK   
12531 GDK_MOD2_MASK   
12532 GDK_MOD3_MASK   
12533 GDK_MOD4_MASK   
12534 GDK_MOD5_MASK   
12535 GDK_BUTTON1_MASK
12536 GDK_BUTTON2_MASK
12537 GDK_BUTTON3_MASK
12538 GDK_BUTTON4_MASK
12539 GDK_BUTTON5_MASK
12540 </programlisting>
12541
12542 <para>As for other signals, to determine what happens when an event occurs
12543 we call <literal>gtk_signal_connect()</literal>. But we also need let GTK
12544 know which events we want to be notified about. To do this, we call
12545 the function:</para>
12546
12547 <programlisting role="C">
12548 void gtk_widget_set_events (GtkWidget *widget,
12549                             gint      events);
12550 </programlisting>
12551
12552 <para>The second field specifies the events we are interested in. It
12553 is the bitwise OR of constants that specify different types
12554 of events. For future reference the event types are:</para>
12555
12556 <programlisting role="C">
12557 GDK_EXPOSURE_MASK
12558 GDK_POINTER_MOTION_MASK
12559 GDK_POINTER_MOTION_HINT_MASK
12560 GDK_BUTTON_MOTION_MASK     
12561 GDK_BUTTON1_MOTION_MASK    
12562 GDK_BUTTON2_MOTION_MASK    
12563 GDK_BUTTON3_MOTION_MASK    
12564 GDK_BUTTON_PRESS_MASK      
12565 GDK_BUTTON_RELEASE_MASK    
12566 GDK_KEY_PRESS_MASK         
12567 GDK_KEY_RELEASE_MASK       
12568 GDK_ENTER_NOTIFY_MASK      
12569 GDK_LEAVE_NOTIFY_MASK      
12570 GDK_FOCUS_CHANGE_MASK      
12571 GDK_STRUCTURE_MASK         
12572 GDK_PROPERTY_CHANGE_MASK   
12573 GDK_PROXIMITY_IN_MASK      
12574 GDK_PROXIMITY_OUT_MASK     
12575 </programlisting>
12576
12577 <para>There are a few subtle points that have to be observed when calling
12578 <literal>gtk_widget_set_events()</literal>. First, it must be called before the X window
12579 for a GTK widget is created. In practical terms, this means you
12580 should call it immediately after creating the widget. Second, the
12581 widget must have an associated X window. For efficiency, many widget
12582 types do not have their own window, but draw in their parent's window.
12583 These widgets are:</para>
12584
12585 <programlisting role="C">
12586 GtkAlignment
12587 GtkArrow
12588 GtkBin
12589 GtkBox
12590 GtkImage
12591 GtkItem
12592 GtkLabel
12593 GtkPixmap
12594 GtkScrolledWindow
12595 GtkSeparator
12596 GtkTable
12597 GtkAspectFrame
12598 GtkFrame
12599 GtkVBox
12600 GtkHBox
12601 GtkVSeparator
12602 GtkHSeparator
12603 </programlisting>
12604
12605 <para>To capture events for these widgets, you need to use an EventBox
12606 widget. See the section on the <link linkend="sec-EventBox">EventBox</link> widget for details.</para>
12607
12608 <para>For our drawing program, we want to know when the mouse button is
12609 pressed and when the mouse is moved, so we specify
12610 <literal>GDK_POINTER_MOTION_MASK</literal> and <literal>GDK_BUTTON_PRESS_MASK</literal>. We also
12611 want to know when we need to redraw our window, so we specify
12612 <literal>GDK_EXPOSURE_MASK</literal>. Although we want to be notified via a
12613 Configure event when our window size changes, we don't have to specify
12614 the corresponding <literal>GDK_STRUCTURE_MASK</literal> flag, because it is
12615 automatically specified for all windows.</para>
12616
12617 <para>It turns out, however, that there is a problem with just specifying
12618 <literal>GDK_POINTER_MOTION_MASK</literal>. This will cause the server to add a new
12619 motion event to the event queue every time the user moves the mouse.
12620 Imagine that it takes us 0.1 seconds to handle a motion event, but the
12621 X server queues a new motion event every 0.05 seconds. We will soon
12622 get way behind the users drawing. If the user draws for 5 seconds,
12623 it will take us another 5 seconds to catch up after they release 
12624 the mouse button! What we would like is to only get one motion
12625 event for each event we process. The way to do this is to 
12626 specify <literal>GDK_POINTER_MOTION_HINT_MASK</literal>. </para>
12627
12628 <para>When we specify <literal>GDK_POINTER_MOTION_HINT_MASK</literal>, the server sends
12629 us a motion event the first time the pointer moves after entering
12630 our window, or after a button press or release event. Subsequent 
12631 motion events will be suppressed until we explicitly ask for
12632 the position of the pointer using the function:</para>
12633
12634 <programlisting role="C">
12635 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
12636                                           gint            *x,
12637                                           gint            *y,
12638                                           GdkModifierType *mask);
12639 </programlisting>
12640
12641 <para>(There is another function, <literal>gtk_widget_get_pointer()</literal> which
12642 has a simpler interface, but turns out not to be very useful, since
12643 it only retrieves the position of the mouse, not whether the buttons
12644 are pressed.)</para>
12645
12646 <para>The code to set the events for our window then looks like:</para>
12647
12648 <programlisting role="C">
12649   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
12650                       (GtkSignalFunc) expose_event, NULL);
12651   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
12652                       (GtkSignalFunc) configure_event, NULL);
12653   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
12654                       (GtkSignalFunc) motion_notify_event, NULL);
12655   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
12656                       (GtkSignalFunc) button_press_event, NULL);
12657
12658   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
12659                          | GDK_LEAVE_NOTIFY_MASK
12660                          | GDK_BUTTON_PRESS_MASK
12661                          | GDK_POINTER_MOTION_MASK
12662                          | GDK_POINTER_MOTION_HINT_MASK);
12663 </programlisting>
12664
12665 <para>We'll save the "expose_event" and "configure_event" handlers for
12666 later. The "motion_notify_event" and "button_press_event" handlers
12667 are pretty simple:</para>
12668
12669 <programlisting role="C">
12670 static gboolean
12671 button_press_event( GtkWidget *widget, GdkEventButton *event )
12672 {
12673   if (event->button == 1 &amp;&amp; pixmap != NULL)
12674       draw_brush (widget, event->x, event->y);
12675
12676   return TRUE;
12677 }
12678
12679 static gboolean
12680 motion_notify_event( GtkWidget *widget, GdkEventMotion *event )
12681 {
12682   int x, y;
12683   GdkModifierType state;
12684
12685   if (event->is_hint)
12686     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
12687   else
12688     {
12689       x = event->x;
12690       y = event->y;
12691       state = event->state;
12692     }
12693     
12694   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
12695     draw_brush (widget, x, y);
12696   
12697   return TRUE;
12698 }
12699 </programlisting>
12700
12701 </sect1>
12702
12703 <!-- ----------------------------------------------------------------- -->
12704 <sect1 id="sec-TheDrawingAreaWidget">
12705 <title>The DrawingArea Widget, And Drawing</title>
12706
12707 <para>We now turn to the process of drawing on the screen. The 
12708 widget we use for this is the DrawingArea widget. A drawing area
12709 widget is essentially an X window and nothing more. It is a blank
12710 canvas in which we can draw whatever we like. A drawing area
12711 is created using the call:</para>
12712
12713 <programlisting role="C">
12714 GtkWidget* gtk_drawing_area_new        (void);
12715 </programlisting>
12716
12717 <para>A default size for the widget can be specified by calling:</para>
12718
12719 <programlisting role="C">
12720 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
12721                                         gint                 width,
12722                                         gint                 height);
12723 </programlisting>
12724
12725 <para>This default size can be overridden, as is true for all widgets,
12726 by calling <literal>gtk_widget_set_size_request()</literal>, and that, in turn, can
12727 be overridden if the user manually resizes the the window containing
12728 the drawing area.</para>
12729
12730 <para>It should be noted that when we create a DrawingArea widget, we are
12731 <emphasis>completely</emphasis> responsible for drawing the contents. If our
12732 window is obscured then uncovered, we get an exposure event and must
12733 redraw what was previously hidden.</para>
12734
12735 <para>Having to remember everything that was drawn on the screen so we
12736 can properly redraw it can, to say the least, be a nuisance. In
12737 addition, it can be visually distracting if portions of the
12738 window are cleared, then redrawn step by step. The solution to
12739 this problem is to use an offscreen <emphasis>backing pixmap</emphasis>.
12740 Instead of drawing directly to the screen, we draw to an image
12741 stored in server memory but not displayed, then when the image
12742 changes or new portions of the image are displayed, we copy the
12743 relevant portions onto the screen.</para>
12744
12745 <para>To create an offscreen pixmap, we call the function:</para>
12746
12747 <programlisting role="C">
12748 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
12749                                          gint        width,
12750                                          gint        height,
12751                                          gint        depth);
12752 </programlisting>
12753
12754 <para>The <literal>window</literal> parameter specifies a GDK window that this pixmap
12755 takes some of its properties from. <literal>width</literal> and <literal>height</literal>
12756 specify the size of the pixmap. <literal>depth</literal> specifies the <emphasis>color
12757 depth</emphasis>, that is the number of bits per pixel, for the new window.
12758 If the depth is specified as <literal>-1</literal>, it will match the depth
12759 of <literal>window</literal>.</para>
12760
12761 <para>We create the pixmap in our "configure_event" handler. This event
12762 is generated whenever the window changes size, including when it
12763 is originally created.</para>
12764
12765 <programlisting role="C">
12766 /* Backing pixmap for drawing area */
12767 static GdkPixmap *pixmap = NULL;
12768
12769 /* Create a new backing pixmap of the appropriate size */
12770 static gboolean
12771 configure_event( GtkWidget *widget, GdkEventConfigure *event )
12772 {
12773   if (pixmap)
12774     gdk_pixmap_unref(pixmap);
12775
12776   pixmap = gdk_pixmap_new(widget->window,
12777                           widget->allocation.width,
12778                           widget->allocation.height,
12779                           -1);
12780   gdk_draw_rectangle (pixmap,
12781                       widget->style->white_gc,
12782                       TRUE,
12783                       0, 0,
12784                       widget->allocation.width,
12785                       widget->allocation.height);
12786
12787   return TRUE;
12788 }
12789 </programlisting>
12790
12791 <para>The call to <literal>gdk_draw_rectangle()</literal> clears the pixmap
12792 initially to white. We'll say more about that in a moment.</para>
12793
12794 <para>Our exposure event handler then simply copies the relevant portion
12795 of the pixmap onto the screen (we determine the area we need
12796 to redraw by using the event->area field of the exposure event):</para>
12797
12798 <programlisting role="C">
12799 /* Redraw the screen from the backing pixmap */
12800 static gboolean
12801 expose_event( GtkWidget *widget, GdkEventExpose *event )
12802 {
12803   gdk_draw_pixmap(widget->window,
12804                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
12805                   pixmap,
12806                   event->area.x, event->area.y,
12807                   event->area.x, event->area.y,
12808                   event->area.width, event->area.height);
12809
12810   return FALSE;
12811 }
12812 </programlisting>
12813
12814 <para>We've now seen how to keep the screen up to date with our pixmap, but
12815 how do we actually draw interesting stuff on our pixmap?  There are a
12816 large number of calls in GTK's GDK library for drawing on
12817 <emphasis>drawables</emphasis>. A drawable is simply something that can be drawn
12818 upon. It can be a window, a pixmap, or a bitmap (a black and white
12819 image).  We've already seen two such calls above,
12820 <literal>gdk_draw_rectangle()</literal> and <literal>gdk_draw_pixmap()</literal>. The
12821 complete list is:</para>
12822
12823 <programlisting role="C">
12824 gdk_draw_line ()
12825 gdk_draw_rectangle ()
12826 gdk_draw_arc ()
12827 gdk_draw_polygon ()
12828 gdk_draw_string ()
12829 gdk_draw_text ()
12830 gdk_draw_pixmap ()
12831 gdk_draw_bitmap ()
12832 gdk_draw_image ()
12833 gdk_draw_points ()
12834 gdk_draw_segments ()
12835 </programlisting>
12836
12837 <para>See the reference documentation or the header file
12838 <literal>&lt;gdk/gdk.h&gt;</literal> for further details on these functions.
12839 These functions all share the same first two arguments. The first
12840 argument is the drawable to draw upon, the second argument is a
12841 <emphasis>graphics context</emphasis> (GC). </para>
12842
12843 <para>A graphics context encapsulates information about things such as
12844 foreground and background color and line width. GDK has a full set of
12845 functions for creating and modifying graphics contexts, but to keep
12846 things simple we'll just use predefined graphics contexts. Each widget
12847 has an associated style. (Which can be modified in a gtkrc file, see
12848 the section GTK's rc file.) This, among other things, stores a number
12849 of graphics contexts. Some examples of accessing these graphics
12850 contexts are:</para>
12851
12852 <programlisting role="C">
12853 widget->style->white_gc
12854 widget->style->black_gc
12855 widget->style->fg_gc[GTK_STATE_NORMAL]
12856 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
12857 </programlisting>
12858
12859 <para>The fields <literal>fg_gc</literal>, <literal>bg_gc</literal>, <literal>dark_gc</literal>, and
12860 <literal>light_gc</literal> are indexed by a parameter of type
12861 <literal>GtkStateType</literal> which can take on the values:</para>
12862
12863 <programlisting role="C">
12864 GTK_STATE_NORMAL,
12865 GTK_STATE_ACTIVE,
12866 GTK_STATE_PRELIGHT,
12867 GTK_STATE_SELECTED,
12868 GTK_STATE_INSENSITIVE
12869 </programlisting>
12870
12871 <para>For instance, for <literal>GTK_STATE_SELECTED</literal> the default foreground
12872 color is white and the default background color, dark blue.</para>
12873
12874 <para>Our function <literal>draw_brush()</literal>, which does the actual drawing
12875 on the screen, is then:</para>
12876
12877 <programlisting role="C">
12878 /* Draw a rectangle on the screen */
12879 static void
12880 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
12881 {
12882   GdkRectangle update_rect;
12883
12884   update_rect.x = x - 5;
12885   update_rect.y = y - 5;
12886   update_rect.width = 10;
12887   update_rect.height = 10;
12888   gdk_draw_rectangle (pixmap,
12889                       widget->style->black_gc,
12890                       TRUE,
12891                       update_rect.x, update_rect.y,
12892                       update_rect.width, update_rect.height);
12893   gtk_widget_draw (widget, &amp;update_rect);
12894 }
12895 </programlisting>
12896
12897 <para>After we draw the rectangle representing the brush onto the pixmap,
12898 we call the function:</para>
12899
12900 <programlisting role="C">
12901 void       gtk_widget_draw                (GtkWidget           *widget,
12902                                            GdkRectangle        *area);
12903 </programlisting>
12904
12905 <para>which notifies X that the area given by the <literal>area</literal> parameter
12906 needs to be updated. X will eventually generate an expose event
12907 (possibly combining the areas passed in several calls to
12908 <literal>gtk_widget_draw()</literal>) which will cause our expose event handler
12909 to copy the relevant portions to the screen.</para>
12910
12911 <para>We have now covered the entire drawing program except for a few
12912 mundane details like creating the main window.</para>
12913
12914 </sect1>
12915
12916 <!-- ----------------------------------------------------------------- -->
12917 <sect1 id="sec-AddingXInputSupport">
12918 <title>Adding XInput support</title>
12919
12920 <para>It is now possible to buy quite inexpensive input devices such 
12921 as drawing tablets, which allow drawing with a much greater
12922 ease of artistic expression than does a mouse. The simplest way
12923 to use such devices is simply as a replacement for the mouse,
12924 but that misses out many of the advantages of these devices,
12925 such as:</para>
12926
12927 <itemizedlist>
12928 <listitem><simpara> Pressure sensitivity</simpara>
12929 </listitem>
12930 <listitem><simpara> Tilt reporting</simpara>
12931 </listitem>
12932 <listitem><simpara> Sub-pixel positioning</simpara>
12933 </listitem>
12934 <listitem><simpara> Multiple inputs (for example, a stylus with a point and eraser)</simpara>
12935 </listitem>
12936 </itemizedlist>
12937
12938 <para>For information about the XInput extension, see the <ulink
12939 url="http://www.gtk.org/~otaylor/xinput/howto/index.html">XInput HOWTO</ulink>.</para>
12940
12941 <para>If we examine the full definition of, for example, the GdkEventMotion
12942 structure, we see that it has fields to support extended device
12943 information.</para>
12944
12945 <programlisting role="C">
12946 struct _GdkEventMotion
12947 {
12948   GdkEventType type;
12949   GdkWindow *window;
12950   guint32 time;
12951   gdouble x;
12952   gdouble y;
12953   gdouble pressure;
12954   gdouble xtilt;
12955   gdouble ytilt;
12956   guint state;
12957   gint16 is_hint;
12958   GdkInputSource source;
12959   guint32 deviceid;
12960 };
12961 </programlisting>
12962
12963 <para><literal>pressure</literal> gives the pressure as a floating point number between
12964 0 and 1. <literal>xtilt</literal> and <literal>ytilt</literal> can take on values between 
12965 -1 and 1, corresponding to the degree of tilt in each direction.
12966 <literal>source</literal> and <literal>deviceid</literal> specify the device for which the
12967 event occurred in two different ways. <literal>source</literal> gives some simple
12968 information about the type of device. It can take the enumeration
12969 values:</para>
12970
12971 <programlisting role="C">
12972 GDK_SOURCE_MOUSE
12973 GDK_SOURCE_PEN
12974 GDK_SOURCE_ERASER
12975 GDK_SOURCE_CURSOR
12976 </programlisting>
12977
12978 <para><literal>deviceid</literal> specifies a unique numeric ID for the device. This can
12979 be used to find out further information about the device using the
12980 <literal>gdk_input_list_devices()</literal> call (see below). The special value
12981 <literal>GDK_CORE_POINTER</literal> is used for the core pointer device. (Usually
12982 the mouse.)</para>
12983
12984 <!-- ----------------------------------------------------------------- -->
12985 <sect2>
12986 <title>Enabling extended device information</title>
12987
12988 <para>To let GTK know about our interest in the extended device information,
12989 we merely have to add a single line to our program:</para>
12990
12991 <programlisting role="C">
12992 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
12993 </programlisting>
12994
12995 <para>By giving the value <literal>GDK_EXTENSION_EVENTS_CURSOR</literal> we say that
12996 we are interested in extension events, but only if we don't have
12997 to draw our own cursor. See the section <link
12998 linkend="sec-FurtherSophistications"> Further Sophistications </link> below
12999 for more information about drawing the cursor. We could also 
13000 give the values <literal>GDK_EXTENSION_EVENTS_ALL</literal> if we were willing 
13001 to draw our own cursor, or <literal>GDK_EXTENSION_EVENTS_NONE</literal> to revert
13002 back to the default condition.</para>
13003
13004 <para>This is not completely the end of the story however. By default,
13005 no extension devices are enabled. We need a mechanism to allow
13006 users to enable and configure their extension devices. GTK provides
13007 the InputDialog widget to automate this process. The following
13008 procedure manages an InputDialog widget. It creates the dialog if
13009 it isn't present, and raises it to the top otherwise.</para>
13010
13011 <programlisting role="C">
13012 void
13013 input_dialog_destroy (GtkWidget *w, gpointer data)
13014 {
13015   *((GtkWidget **)data) = NULL;
13016 }
13017
13018 void
13019 create_input_dialog ()
13020 {
13021   static GtkWidget *inputd = NULL;
13022
13023   if (!inputd)
13024     {
13025       inputd = gtk_input_dialog_new();
13026
13027       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
13028                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
13029       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
13030                                  "clicked",
13031                                  (GtkSignalFunc)gtk_widget_hide,
13032                                  GTK_OBJECT(inputd));
13033       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
13034
13035       gtk_widget_show (inputd);
13036     }
13037   else
13038     {
13039       if (!GTK_WIDGET_MAPPED(inputd))
13040         gtk_widget_show(inputd);
13041       else
13042         gdk_window_raise(inputd->window);
13043     }
13044 }
13045 </programlisting>
13046
13047 <para>(You might want to take note of the way we handle this dialog.  By
13048 connecting to the "destroy" signal, we make sure that we don't keep a
13049 pointer to dialog around after it is destroyed - that could lead to a
13050 segfault.)</para>
13051
13052 <para>The InputDialog has two buttons "Close" and "Save", which by default
13053 have no actions assigned to them. In the above function we make
13054 "Close" hide the dialog, hide the "Save" button, since we don't
13055 implement saving of XInput options in this program.</para>
13056
13057 </sect2>
13058
13059 <!-- ----------------------------------------------------------------- -->
13060 <sect2>
13061 <title>Using extended device information</title>
13062
13063 <para>Once we've enabled the device, we can just use the extended 
13064 device information in the extra fields of the event structures.
13065 In fact, it is always safe to use this information since these
13066 fields will have reasonable default values even when extended
13067 events are not enabled.</para>
13068
13069 <para>Once change we do have to make is to call
13070 <literal>gdk_input_window_get_pointer()</literal> instead of
13071 <literal>gdk_window_get_pointer</literal>. This is necessary because
13072 <literal>gdk_window_get_pointer</literal> doesn't return the extended device
13073 information.</para>
13074
13075 <programlisting role="C">
13076 void gdk_input_window_get_pointer( GdkWindow       *window,
13077                                    guint32         deviceid,
13078                                    gdouble         *x,
13079                                    gdouble         *y,
13080                                    gdouble         *pressure,
13081                                    gdouble         *xtilt,
13082                                    gdouble         *ytilt,
13083                                    GdkModifierType *mask);
13084 </programlisting>
13085
13086 <para>When calling this function, we need to specify the device ID as
13087 well as the window. Usually, we'll get the device ID from the
13088 <literal>deviceid</literal> field of an event structure. Again, this function
13089 will return reasonable values when extension events are not
13090 enabled. (In this case, <literal>event->deviceid</literal> will have the value
13091 <literal>GDK_CORE_POINTER</literal>).</para>
13092
13093 <para>So the basic structure of our button-press and motion event handlers
13094 doesn't change much - we just need to add code to deal with the
13095 extended information.</para>
13096
13097 <programlisting role="C">
13098 static gboolean
13099 button_press_event( GtkWidget *widget, GdkEventButton *event )
13100 {
13101   print_button_press (event->deviceid);
13102   
13103   if (event->button == 1 &amp;&amp; pixmap != NULL)
13104     draw_brush (widget, event->source, event->x, event->y, event->pressure);
13105
13106   return TRUE;
13107 }
13108
13109 static gboolean
13110 motion_notify_event( GtkWidget *widget, GdkEventMotion *event )
13111 {
13112   gdouble x, y;
13113   gdouble pressure;
13114   GdkModifierType state;
13115
13116   if (event->is_hint)
13117     gdk_input_window_get_pointer (event->window, event->deviceid,
13118                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
13119   else
13120     {
13121       x = event->x;
13122       y = event->y;
13123       pressure = event->pressure;
13124       state = event->state;
13125     }
13126     
13127   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
13128     draw_brush (widget, event->source, x, y, pressure);
13129   
13130   return TRUE;
13131 }
13132 </programlisting>
13133
13134 <para>We also need to do something with the new information. Our new
13135 <literal>draw_brush()</literal> function draws with a different color for
13136 each <literal>event->source</literal> and changes the brush size depending
13137 on the pressure.</para>
13138
13139 <programlisting role="C">
13140 /* Draw a rectangle on the screen, size depending on pressure,
13141    and color on the type of device */
13142 static void
13143 draw_brush (GtkWidget *widget, GdkInputSource source,
13144             gdouble x, gdouble y, gdouble pressure)
13145 {
13146   GdkGC *gc;
13147   GdkRectangle update_rect;
13148
13149   switch (source)
13150     {
13151     case GDK_SOURCE_MOUSE:
13152       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
13153       break;
13154     case GDK_SOURCE_PEN:
13155       gc = widget->style->black_gc;
13156       break;
13157     case GDK_SOURCE_ERASER:
13158       gc = widget->style->white_gc;
13159       break;
13160     default:
13161       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
13162     }
13163
13164   update_rect.x = x - 10 * pressure;
13165   update_rect.y = y - 10 * pressure;
13166   update_rect.width = 20 * pressure;
13167   update_rect.height = 20 * pressure;
13168   gdk_draw_rectangle (pixmap, gc, TRUE,
13169                       update_rect.x, update_rect.y,
13170                       update_rect.width, update_rect.height);
13171   gtk_widget_draw (widget, &amp;update_rect);
13172 }
13173 </programlisting>
13174
13175 </sect2>
13176
13177 <!-- ----------------------------------------------------------------- -->
13178 <sect2>
13179 <title>Finding out more about a device</title>
13180
13181 <para>As an example of how to find out more about a device, our program
13182 will print the name of the device that generates each button
13183 press. To find out the name of a device, we call the function:</para>
13184
13185 <programlisting role="C">
13186 GList *gdk_input_list_devices               (void);
13187 </programlisting>
13188
13189 <para>which returns a GList (a linked list type from the GLib library)
13190 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
13191 as:</para>
13192
13193 <programlisting role="C">
13194 struct _GdkDeviceInfo
13195 {
13196   guint32 deviceid;
13197   gchar *name;
13198   GdkInputSource source;
13199   GdkInputMode mode;
13200   gint has_cursor;
13201   gint num_axes;
13202   GdkAxisUse *axes;
13203   gint num_keys;
13204   GdkDeviceKey *keys;
13205 };
13206 </programlisting>
13207
13208 <para>Most of these fields are configuration information that you can ignore
13209 unless you are implementing XInput configuration saving. The fieldwe
13210 are interested in here is <literal>name</literal> which is simply the name that X
13211 assigns to the device. The other field that isn't configuration
13212 information is <literal>has_cursor</literal>. If <literal>has_cursor</literal> is false, then we
13213 we need to draw our own cursor. But since we've specified
13214 <literal>GDK_EXTENSION_EVENTS_CURSOR</literal>, we don't have to worry about this.</para>
13215
13216 <para>Our <literal>print_button_press()</literal> function simply iterates through
13217 the returned list until it finds a match, then prints out
13218 the name of the device.</para>
13219
13220 <programlisting role="C">
13221 static void
13222 print_button_press (guint32 deviceid)
13223 {
13224   GList *tmp_list;
13225
13226   /* gdk_input_list_devices returns an internal list, so we shouldn't
13227      free it afterwards */
13228   tmp_list = gdk_input_list_devices();
13229
13230   while (tmp_list)
13231     {
13232       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
13233
13234       if (info->deviceid == deviceid)
13235         {
13236           printf("Button press on device '%s'\n", info->name);
13237           return;
13238         }
13239
13240       tmp_list = tmp_list->next;
13241     }
13242 }
13243 </programlisting>
13244
13245 <para>That completes the changes to "XInputize" our program.</para>
13246
13247 </sect2>
13248
13249 <!-- ----------------------------------------------------------------- -->
13250 <sect2 id="sec-FurtherSophistications">
13251 <title>Further sophistications</title>
13252
13253 <para>Although our program now supports XInput quite well, it lacks some
13254 features we would want in a full-featured application. First, the user
13255 probably doesn't want to have to configure their device each time they
13256 run the program, so we should allow them to save the device
13257 configuration. This is done by iterating through the return of
13258 <literal>gdk_input_list_devices()</literal> and writing out the configuration to a
13259 file.</para>
13260
13261 <para>To restore the state next time the program is run, GDK provides
13262 functions to change device configuration:</para>
13263
13264 <programlisting role="C">
13265 gdk_input_set_extension_events()
13266 gdk_input_set_source()
13267 gdk_input_set_mode()
13268 gdk_input_set_axes()
13269 gdk_input_set_key()
13270 </programlisting>
13271
13272 <para>(The list returned from <literal>gdk_input_list_devices()</literal> should not be
13273 modified directly.) An example of doing this can be found in the
13274 drawing program gsumi. (Available from <ulink
13275 url="http://www.msc.cornell.edu/~otaylor/gsumi/">http://www.msc.cornell.edu/~otaylor/gsumi/</ulink>) Eventually, it
13276 would be nice to have a standard way of doing this for all
13277 applications. This probably belongs at a slightly higher level than
13278 GTK, perhaps in the GNOME library.</para>
13279
13280 <para>Another major omission that we have mentioned above is the lack of
13281 cursor drawing. Platforms other than XFree86 currently do not allow
13282 simultaneously using a device as both the core pointer and directly by
13283 an application. See the <ulink
13284 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html">XInput-HOWTO</ulink> for more information about this. This means that
13285 applications that want to support the widest audience need to draw
13286 their own cursor.</para>
13287
13288 <para>An application that draws its own cursor needs to do two things:
13289 determine if the current device needs a cursor drawn or not, and
13290 determine if the current device is in proximity. (If the current
13291 device is a drawing tablet, it's a nice touch to make the cursor 
13292 disappear when the stylus is lifted from the tablet. When the
13293 device is touching the stylus, that is called "in proximity.")
13294 The first is done by searching the device list, as we did
13295 to find out the device name. The second is achieved by selecting
13296 "proximity_out" events. An example of drawing one's own cursor is
13297 found in the "testinput" program found in the GTK distribution.</para>
13298
13299 </sect2>
13300
13301 </sect1>
13302 </chapter>
13303
13304 <!-- ***************************************************************** -->
13305 <chapter id="ch-Tips">
13306 <title>Tips For Writing GTK Applications</title>
13307
13308 <para>This section is simply a gathering of wisdom, general style guidelines
13309 and hints to creating good GTK applications. Currently this section
13310 is very short, but I hope it will get longer in future editions of
13311 this tutorial.</para>
13312
13313 <para>Use GNU autoconf and automake! They are your friends :) Automake
13314 examines C files, determines how they depend on each other, and
13315 generates a Makefile so the files can be compiled in the correct
13316 order. Autoconf permits automatic configuration of software
13317 installation, handling a large number of system quirks to increase
13318 portability. I am planning to make a quick intro on them here.</para>
13319
13320 <para>When writing C code, use only C comments (beginning with "/*" and
13321 ending with "*/"), and don't use C++-style comments ("//").  Although
13322 many C compilers understand C++ comments, others don't, and the ANSI C
13323 standard does not require that C++-style comments be processed as
13324 comments.</para>
13325
13326 </chapter>
13327
13328 <!-- ***************************************************************** -->
13329 <chapter id="ch-Contributing">
13330 <title>Contributing</title>
13331
13332 <para>This document, like so much other great software out there, was
13333 created for free by volunteers.  If you are at all knowledgeable about
13334 any aspect of GTK that does not already have documentation, please
13335 consider contributing to this document.</para>
13336
13337 <para>If you do decide to contribute, please mail your text to Tony Gale,
13338 <literal><ulink url="mailto:gale@gtk.org">gale@gtk.org</ulink></literal>. Also, be aware that the entirety of this
13339 document is free, and any addition by you provide must also be
13340 free. That is, people may use any portion of your examples in their
13341 programs, and copies of this document may be distributed at will, etc.</para>
13342
13343 <para>Thank you.</para>
13344
13345 </chapter>
13346
13347 <!-- ***************************************************************** -->
13348 <chapter id="ch-Credits">
13349 <title>Credits</title>
13350
13351 <para>We would like to thank the following for their contributions to this text.</para>
13352
13353 <itemizedlist>
13354 <listitem><simpara>Bawer Dagdeviren, <literal><ulink url="mailto:chamele0n@geocities.com">chamele0n@geocities.com</ulink></literal> for the menus tutorial.</simpara>
13355 </listitem>
13356
13357 <listitem><simpara>Raph Levien, <literal><ulink url="mailto:raph@acm.org">raph@acm.org</ulink></literal>
13358 for hello world ala GTK, widget packing, and general all around wisdom.
13359 He's also generously donated a home for this tutorial.</simpara>
13360 </listitem>
13361
13362 <listitem><simpara>Peter Mattis, <literal><ulink url="mailto:petm@xcf.berkeley.edu">petm@xcf.berkeley.edu</ulink></literal> for the simplest GTK program.. 
13363 and the ability to make it :)</simpara>
13364 </listitem>
13365
13366 <listitem><simpara>Werner Koch <literal><ulink url="mailto:werner.koch@guug.de">werner.koch@guug.de</ulink></literal> for converting the original plain text to
13367 SGML, and the widget class hierarchy.</simpara>
13368 </listitem>
13369
13370 <listitem><simpara>Mark Crichton <literal><ulink
13371 url="mailto:crichton@expert.cc.purdue.edu">crichton@expert.cc.purdue.edu</ulink></literal> for the menu factory code,
13372 and the table packing tutorial.</simpara>
13373 </listitem>
13374
13375 <listitem><simpara>Owen Taylor <literal><ulink url="mailto:owt1@cornell.edu">owt1@cornell.edu</ulink></literal> for the EventBox widget section (and the
13376 patch to the distro).  He's also responsible for the selections code
13377 and tutorial, as well as the sections on writing your own GTK widgets,
13378 and the example application. Thanks a lot Owen for all you help!</simpara>
13379 </listitem>
13380
13381 <listitem><simpara>Mark VanderBoom <literal><ulink url="mailto:mvboom42@calvin.edu">mvboom42@calvin.edu</ulink></literal> for his wonderful work on the
13382 Notebook, Progress Bar, Dialogs, and File selection widgets.  Thanks a
13383 lot Mark!  You've been a great help.</simpara>
13384 </listitem>
13385
13386 <listitem><simpara>Tim Janik <literal><ulink url="mailto:timj@gtk.org">timj@gtk.org</ulink></literal> for his great job on the Lists
13387 Widget. His excellent work on automatically extracting the widget tree
13388 and signal information from GTK. Thanks Tim :)</simpara>
13389 </listitem>
13390
13391 <listitem><simpara>Rajat Datta <literal><ulink url="mailto:rajat@ix.netcom.com">rajat@ix.netcom.com</ulink>
13392 </literal> for the excellent job on the Pixmap
13393 tutorial.</simpara>
13394 </listitem>
13395
13396 <listitem><simpara>Michael K. Johnson <literal><ulink url="mailto:johnsonm@redhat.com">johnsonm@redhat.com</ulink></literal> for info and code for popup menus.</simpara>
13397 </listitem>
13398
13399 <listitem><simpara>David Huggins-Daines <literal><ulink
13400 url="mailto:bn711@freenet.carleton.ca">bn711@freenet.carleton.ca</ulink></literal> for the Range Widgets and Tree
13401 Widget sections.</simpara>
13402 </listitem>
13403
13404 <listitem><simpara>Stefan Mars <literal><ulink url="mailto:mars@lysator.liu.se">mars@lysator.liu.se</ulink></literal> for the CList section.</simpara>
13405 </listitem>
13406
13407 <listitem><simpara>David A. Wheeler <literal><ulink url="mailto:dwheeler@ida.org">dwheeler@ida.org</ulink></literal> for portions of the text on GLib
13408 and various tutorial fixups and improvements.
13409 The GLib text was in turn based on material developed by Damon Chaplin
13410 <literal><ulink url="mailto:DAChaplin@msn.com">DAChaplin@msn.com</ulink></literal></simpara>
13411 </listitem>
13412
13413 <listitem><simpara>David King for style checking the entire document.</simpara>
13414 </listitem>
13415 </itemizedlist>
13416
13417 <para>And to all of you who commented on and helped refine this document.</para>
13418
13419 <para>Thanks.</para>
13420
13421 </chapter>
13422
13423 <!-- ***************************************************************** -->
13424 <chapter id="ch-Copyright">
13425 <title>Tutorial Copyright and Permissions Notice</title>
13426
13427 <para>The GTK Tutorial is Copyright (C) 1997 Ian Main. </para>
13428
13429 <para>Copyright (C) 1998-2002 Tony Gale.</para>
13430
13431 <para>Permission is granted to make and distribute verbatim copies of this 
13432 manual provided the copyright notice and this permission notice are 
13433 preserved on all copies.</para>
13434
13435 <para>Permission is granted to copy and distribute modified versions of 
13436 this document under the conditions for verbatim copying, provided that 
13437 this copyright notice is included exactly as in the original,
13438 and that the entire resulting derived work is distributed under 
13439 the terms of a permission notice identical to this one.</para>
13440
13441 <para>Permission is granted to copy and distribute translations of this 
13442 document into another language, under the above conditions for modified 
13443 versions.</para>
13444
13445 <para>If you are intending to incorporate this document into a published 
13446 work, please contact the maintainer, and we will make an effort 
13447 to ensure that you have the most up to date information available.</para>
13448
13449 <para>There is no guarantee that this document lives up to its intended
13450 purpose.  This is simply provided as a free resource.  As such,
13451 the authors and maintainers of the information provided within can
13452 not make any guarantee that the information is even accurate.</para>
13453
13454 </chapter>
13455
13456 <!-- ***************************************************************** -->
13457 <!-- ***************************************************************** -->
13458
13459 <!-- ***************************************************************** -->
13460 <appendix id="app-GTKSignals">
13461 <title>GTK Signals</title>
13462
13463 <para>As GTK is an object oriented widget set, it has a hierarchy of
13464 inheritance. This inheritance mechanism applies for
13465 signals. Therefore, you should refer to the widget hierarchy tree when
13466 using the signals listed in this section.</para>
13467
13468 <!-- ----------------------------------------------------------------- -->
13469 <sect1 id="sec-GtkObject">
13470 <title>GtkObject</title>
13471
13472 <programlisting role="C">
13473 void GtkObject::destroy (GtkObject *,
13474                          gpointer);
13475 </programlisting>
13476
13477 </sect1>
13478
13479 <!-- ----------------------------------------------------------------- -->
13480 <sect1 id="sec-GtkWidget">
13481 <title>GtkWidget</title>
13482
13483 <programlisting role="C">
13484 void GtkWidget::show    (GtkWidget *,
13485                          gpointer);
13486 void GtkWidget::hide    (GtkWidget *,
13487                          gpointer);
13488 void GtkWidget::map     (GtkWidget *,
13489                          gpointer);
13490 void GtkWidget::unmap   (GtkWidget *,
13491                          gpointer);
13492 void GtkWidget::realize (GtkWidget *,
13493                          gpointer);
13494 void GtkWidget::unrealize       (GtkWidget *,
13495                                  gpointer);
13496 void GtkWidget::draw    (GtkWidget *,
13497                          ggpointer,
13498                          gpointer);
13499 void GtkWidget::draw-focus      (GtkWidget *,
13500                                  gpointer);
13501 void GtkWidget::draw-default    (GtkWidget *,
13502                                  gpointer);
13503 void GtkWidget::size-request    (GtkWidget *,
13504                                  ggpointer,
13505                                  gpointer);
13506 void GtkWidget::size-allocate   (GtkWidget *,
13507                                  ggpointer,
13508                                  gpointer);
13509 void GtkWidget::state-changed   (GtkWidget *,
13510                                  GtkStateType,
13511                                  gpointer);
13512 void GtkWidget::parent-set      (GtkWidget *,
13513                                  GtkObject *,
13514                                  gpointer);
13515 void GtkWidget::style-set       (GtkWidget *,
13516                                  GtkStyle *,
13517                                  gpointer);
13518 void GtkWidget::add-accelerator (GtkWidget *,
13519                                  gguint,
13520                                  GtkAccelGroup *,
13521                                  gguint,
13522                                  GdkModifierType,
13523                                  GtkAccelFlags,
13524                                  gpointer);
13525 void GtkWidget::remove-accelerator      (GtkWidget *,
13526                                          GtkAccelGroup *,
13527                                          gguint,
13528                                          GdkModifierType,
13529                                          gpointer);
13530 gboolean GtkWidget::event       (GtkWidget *,
13531                                  GdkEvent *,
13532                                  gpointer);
13533 gboolean GtkWidget::button-press-event  (GtkWidget *,
13534                                          GdkEvent *,
13535                                          gpointer);
13536 gboolean GtkWidget::button-release-event        (GtkWidget *,
13537                                                  GdkEvent *,
13538                                                  gpointer);
13539 gboolean GtkWidget::motion-notify-event (GtkWidget *,
13540                                          GdkEvent *,
13541                                          gpointer);
13542 gboolean GtkWidget::delete-event        (GtkWidget *,
13543                                          GdkEvent *,
13544                                          gpointer);
13545 gboolean GtkWidget::destroy-event       (GtkWidget *,
13546                                          GdkEvent *,
13547                                          gpointer);
13548 gboolean GtkWidget::expose-event        (GtkWidget *,
13549                                          GdkEvent *,
13550                                          gpointer);
13551 gboolean GtkWidget::key-press-event     (GtkWidget *,
13552                                          GdkEvent *,
13553                                          gpointer);
13554 gboolean GtkWidget::key-release-event   (GtkWidget *,
13555                                          GdkEvent *,
13556                                          gpointer);
13557 gboolean GtkWidget::enter-notify-event  (GtkWidget *,
13558                                          GdkEvent *,
13559                                          gpointer);
13560 gboolean GtkWidget::leave-notify-event  (GtkWidget *,
13561                                          GdkEvent *,
13562                                          gpointer);
13563 gboolean GtkWidget::configure-event     (GtkWidget *,
13564                                          GdkEvent *,
13565                                          gpointer);
13566 gboolean GtkWidget::focus-in-event      (GtkWidget *,
13567                                          GdkEvent *,
13568                                          gpointer);
13569 gboolean GtkWidget::focus-out-event     (GtkWidget *,
13570                                          GdkEvent *,
13571                                          gpointer);
13572 gboolean GtkWidget::map-event   (GtkWidget *,
13573                                  GdkEvent *,
13574                                  gpointer);
13575 gboolean GtkWidget::unmap-event (GtkWidget *,
13576                                  GdkEvent *,
13577                                  gpointer);
13578 gboolean GtkWidget::property-notify-event       (GtkWidget *,
13579                                                  GdkEvent *,
13580                                                  gpointer);
13581 gboolean GtkWidget::selection-clear-event       (GtkWidget *,
13582                                                  GdkEvent *,
13583                                                  gpointer);
13584 gboolean GtkWidget::selection-request-event     (GtkWidget *,
13585                                                  GdkEvent *,
13586                                                  gpointer);
13587 gboolean GtkWidget::selection-notify-event      (GtkWidget *,
13588                                                  GdkEvent *,
13589                                                  gpointer);
13590 void GtkWidget::selection-get   (GtkWidget *,
13591                                  GtkSelectionData *,
13592                                  gguint,
13593                                  gpointer);
13594 void GtkWidget::selection-received      (GtkWidget *,
13595                                          GtkSelectionData *,
13596                                          gguint,
13597                                          gpointer);
13598 gboolean GtkWidget::proximity-in-event  (GtkWidget *,
13599                                          GdkEvent *,
13600                                          gpointer);
13601 gboolean GtkWidget::proximity-out-event (GtkWidget *,
13602                                          GdkEvent *,
13603                                          gpointer);
13604 void GtkWidget::drag-begin      (GtkWidget *,
13605                                  GdkDragContext *,
13606                                  gpointer);
13607 void GtkWidget::drag-end        (GtkWidget *,
13608                                  GdkDragContext *,
13609                                  gpointer);
13610 void GtkWidget::drag-data-delete        (GtkWidget *,
13611                                          GdkDragContext *,
13612                                          gpointer);
13613 void GtkWidget::drag-leave      (GtkWidget *,
13614                                  GdkDragContext *,
13615                                  gguint,
13616                                  gpointer);
13617 gboolean GtkWidget::drag-motion (GtkWidget *,
13618                                  GdkDragContext *,
13619                                  ggint,
13620                                  ggint,
13621                                  gguint,
13622                                  gpointer);
13623 gboolean GtkWidget::drag-drop   (GtkWidget *,
13624                                  GdkDragContext *,
13625                                  ggint,
13626                                  ggint,
13627                                  gguint,
13628                                  gpointer);
13629 void GtkWidget::drag-data-get   (GtkWidget *,
13630                                  GdkDragContext *,
13631                                  GtkSelectionData *,
13632                                  gguint,
13633                                  gguint,
13634                                  gpointer);
13635 void GtkWidget::drag-data-received      (GtkWidget *,
13636                                          GdkDragContext *,
13637                                          ggint,
13638                                          ggint,
13639                                          GtkSelectionData *,
13640                                          gguint,
13641                                          gguint,
13642                                          gpointer);
13643 gboolean GtkWidget::client-event        (GtkWidget *,
13644                                          GdkEvent *,
13645                                          gpointer);
13646 gboolean GtkWidget::no-expose-event     (GtkWidget *,
13647                                          GdkEvent *,
13648                                          gpointer);
13649 gboolean GtkWidget::visibility-notify-event     (GtkWidget *,
13650                                                  GdkEvent *,
13651                                                  gpointer);
13652 void GtkWidget::debug-msg       (GtkWidget *,
13653                                  GtkString *,
13654                                  gpointer);
13655 </programlisting>
13656
13657 </sect1>
13658
13659 <!-- ----------------------------------------------------------------- -->
13660 <sect1 id="sec-GtkData">
13661 <title>GtkData</title>
13662
13663 <programlisting role="C">
13664 void GtkData::disconnect        (GtkData *,
13665                                  gpointer);
13666 </programlisting>
13667
13668 </sect1>
13669
13670 <!-- ----------------------------------------------------------------- -->
13671 <sect1 id="sec-GtkContainer">
13672 <title>GtkContainer</title>
13673
13674 <programlisting role="C">
13675 void GtkContainer::add  (GtkContainer *,
13676                          GtkWidget *,
13677                          gpointer);
13678 void GtkContainer::remove       (GtkContainer *,
13679                                  GtkWidget *,
13680                                  gpointer);
13681 void GtkContainer::check-resize (GtkContainer *,
13682                                  gpointer);
13683 GtkDirectionType GtkContainer::focus    (GtkContainer *,
13684                                          GtkDirectionType,
13685                                          gpointer);
13686 void GtkContainer::set-focus-child      (GtkContainer *,
13687                                          GtkWidget *,
13688                                          gpointer);
13689 </programlisting>
13690
13691 </sect1>
13692
13693 <!-- ----------------------------------------------------------------- -->
13694 <sect1 id="sec-GtkCalendar">
13695 <title>GtkCalendar</title>
13696
13697 <programlisting role="C">
13698 void GtkCalendar::month-changed (GtkCalendar *,
13699                                  gpointer);
13700 void GtkCalendar::day-selected  (GtkCalendar *,
13701                                  gpointer);
13702 void GtkCalendar::day-selected-double-click     (GtkCalendar *,
13703                                                  gpointer);
13704 void GtkCalendar::prev-month    (GtkCalendar *,
13705                                  gpointer);
13706 void GtkCalendar::next-month    (GtkCalendar *,
13707                                  gpointer);
13708 void GtkCalendar::prev-year     (GtkCalendar *,
13709                                  gpointer);
13710 void GtkCalendar::next-year     (GtkCalendar *,
13711                                  gpointer);
13712 </programlisting>
13713
13714 </sect1>
13715
13716 <!-- ----------------------------------------------------------------- -->
13717 <sect1 id="sec-GtkEditable">
13718 <title>GtkEditable</title>
13719
13720 <programlisting role="C">
13721 void GtkEditable::changed       (GtkEditable *,
13722                                  gpointer);
13723 void GtkEditable::insert-text   (GtkEditable *,
13724                                  GtkString *,
13725                                  ggint,
13726                                  ggpointer,
13727                                  gpointer);
13728 void GtkEditable::delete-text   (GtkEditable *,
13729                                  ggint,
13730                                  ggint,
13731                                  gpointer);
13732 void GtkEditable::activate      (GtkEditable *,
13733                                  gpointer);
13734 void GtkEditable::set-editable  (GtkEditable *,
13735                                  gboolean,
13736                                  gpointer);
13737 void GtkEditable::move-cursor   (GtkEditable *,
13738                                  ggint,
13739                                  ggint,
13740                                  gpointer);
13741 void GtkEditable::move-word     (GtkEditable *,
13742                                  ggint,
13743                                  gpointer);
13744 void GtkEditable::move-page     (GtkEditable *,
13745                                  ggint,
13746                                  ggint,
13747                                  gpointer);
13748 void GtkEditable::move-to-row   (GtkEditable *,
13749                                  ggint,
13750                                  gpointer);
13751 void GtkEditable::move-to-column        (GtkEditable *,
13752                                          ggint,
13753                                          gpointer);
13754 void GtkEditable::kill-char     (GtkEditable *,
13755                                  ggint,
13756                                  gpointer);
13757 void GtkEditable::kill-word     (GtkEditable *,
13758                                  ggint,
13759                                  gpointer);
13760 void GtkEditable::kill-line     (GtkEditable *,
13761                                  ggint,
13762                                  gpointer);
13763 void GtkEditable::cut-clipboard (GtkEditable *,
13764                                  gpointer);
13765 void GtkEditable::copy-clipboard        (GtkEditable *,
13766                                          gpointer);
13767 void GtkEditable::paste-clipboard       (GtkEditable *,
13768                                          gpointer);
13769 </programlisting>
13770
13771 </sect1>
13772
13773 <!-- ----------------------------------------------------------------- -->
13774 <sect1 id="sec-GtkNotebook">
13775 <title>GtkNotebook</title>
13776
13777 <programlisting role="C">
13778 void GtkNotebook::switch-page   (GtkNotebook *,
13779                                  ggpointer,
13780                                  gguint,
13781                                  gpointer);
13782 </programlisting>
13783
13784 </sect1>
13785
13786 <!-- ----------------------------------------------------------------- -->
13787 <sect1 id="sec-GtkList">
13788 <title>GtkList</title>
13789
13790 <programlisting role="C">
13791 void GtkList::selection-changed (GtkList *,
13792                                  gpointer);
13793 void GtkList::select-child      (GtkList *,
13794                                  GtkWidget *,
13795                                  gpointer);
13796 void GtkList::unselect-child    (GtkList *,
13797                                  GtkWidget *,
13798                                  gpointer);
13799 </programlisting>
13800
13801 </sect1>
13802
13803 <!-- ----------------------------------------------------------------- -->
13804 <sect1 id="sec-GtkMenuShell">
13805 <title>GtkMenuShell</title>
13806
13807 <programlisting role="C">
13808 void GtkMenuShell::deactivate   (GtkMenuShell *,
13809                                  gpointer);
13810 void GtkMenuShell::selection-done       (GtkMenuShell *,
13811                                          gpointer);
13812 void GtkMenuShell::move-current (GtkMenuShell *,
13813                                  GtkMenuDirectionType,
13814                                  gpointer);
13815 void GtkMenuShell::activate-current     (GtkMenuShell *,
13816                                          gboolean,
13817                                          gpointer);
13818 void GtkMenuShell::cancel       (GtkMenuShell *,
13819                                  gpointer);
13820 </programlisting>
13821
13822 </sect1>
13823
13824 <!-- ----------------------------------------------------------------- -->
13825 <sect1 id="sec-GtkToolbar">
13826 <title>GtkToolbar</title>
13827
13828 <programlisting role="C">
13829 void GtkToolbar::orientation-changed    (GtkToolbar *,
13830                                          ggint,
13831                                          gpointer);
13832 void GtkToolbar::style-changed  (GtkToolbar *,
13833                                  ggint,
13834                                  gpointer);
13835 </programlisting>
13836
13837 </sect1>
13838
13839 <!-- ----------------------------------------------------------------- -->
13840 <sect1 id="sec-GtkButton">
13841 <title>GtkButton</title>
13842
13843 <programlisting role="C">
13844 void GtkButton::pressed (GtkButton *,
13845                          gpointer);
13846 void GtkButton::released        (GtkButton *,
13847                                  gpointer);
13848 void GtkButton::clicked (GtkButton *,
13849                          gpointer);
13850 void GtkButton::enter   (GtkButton *,
13851                          gpointer);
13852 void GtkButton::leave   (GtkButton *,
13853                          gpointer);
13854 </programlisting>
13855
13856 </sect1>
13857
13858 <!-- ----------------------------------------------------------------- -->
13859 <sect1 id="sec-GtkItem">
13860 <title>GtkItem</title>
13861
13862 <programlisting role="C">
13863 void GtkItem::select    (GtkItem *,
13864                          gpointer);
13865 void GtkItem::deselect  (GtkItem *,
13866                          gpointer);
13867 void GtkItem::toggle    (GtkItem *,
13868                          gpointer);
13869 </programlisting>
13870
13871 </sect1>
13872
13873 <!-- ----------------------------------------------------------------- -->
13874 <sect1 id="sec-GtkWindow">
13875 <title>GtkWindow</title>
13876
13877 <programlisting role="C">
13878 void GtkWindow::set-focus       (GtkWindow *,
13879                                  ggpointer,
13880                                  gpointer);
13881 </programlisting>
13882
13883 </sect1>
13884
13885 <!-- ----------------------------------------------------------------- -->
13886 <sect1 id="sec-GtkHandleBox">
13887 <title>GtkHandleBox</title>
13888
13889 <programlisting role="C">
13890 void GtkHandleBox::child-attached       (GtkHandleBox *,
13891                                          GtkWidget *,
13892                                          gpointer);
13893 void GtkHandleBox::child-detached       (GtkHandleBox *,
13894                                          GtkWidget *,
13895                                          gpointer);
13896 </programlisting>
13897
13898 </sect1>
13899
13900 <!-- ----------------------------------------------------------------- -->
13901 <sect1 id="sec-GtkToggleButton">
13902 <title>GtkToggleButton</title>
13903
13904 <programlisting role="C">
13905 void GtkToggleButton::toggled   (GtkToggleButton *,
13906                                  gpointer);
13907 </programlisting>
13908
13909 </sect1>
13910
13911 <!-- ----------------------------------------------------------------- -->
13912 <sect1 id="sec-GtkMenuItem">
13913 <title>GtkMenuItem</title>
13914
13915 <programlisting role="C">
13916 void GtkMenuItem::activate      (GtkMenuItem *,
13917                                  gpointer);
13918 void GtkMenuItem::activate-item (GtkMenuItem *,
13919                                  gpointer);
13920 </programlisting>
13921
13922 </sect1>
13923
13924 <!-- ----------------------------------------------------------------- -->
13925 <sect1 id="sec-GtkCheckMenuItem">
13926 <title>GtkCheckMenuItem</title>
13927
13928 <programlisting role="C">
13929 void GtkCheckMenuItem::toggled  (GtkCheckMenuItem *,
13930                                  gpointer);
13931 </programlisting>
13932
13933 </sect1>
13934
13935 <!-- ----------------------------------------------------------------- -->
13936 <sect1 id="sec-GtkInputDialog">
13937 <title>GtkInputDialog</title>
13938
13939 <programlisting role="C">
13940 void GtkInputDialog::enable-device      (GtkInputDialog *,
13941                                          ggint,
13942                                          gpointer);
13943 void GtkInputDialog::disable-device     (GtkInputDialog *,
13944                                          ggint,
13945                                          gpointer);
13946 </programlisting>
13947
13948 </sect1>
13949
13950 <!-- ----------------------------------------------------------------- -->
13951 <sect1 id="sec-GtkColorSelection">
13952 <title>GtkColorSelection</title>
13953
13954 <programlisting role="C">
13955 void GtkColorSelection::color-changed   (GtkColorSelection *,
13956                                          gpointer);
13957 </programlisting>
13958
13959 </sect1>
13960
13961 <!-- ----------------------------------------------------------------- -->
13962 <sect1 id="sec-GtkStatusBar">
13963 <title>GtkStatusBar</title>
13964
13965 <programlisting role="C">
13966 void GtkStatusbar::text-pushed  (GtkStatusbar *,
13967                                  gguint,
13968                                  GtkString *,
13969                                  gpointer);
13970 void GtkStatusbar::text-popped  (GtkStatusbar *,
13971                                  gguint,
13972                                  GtkString *,
13973                                  gpointer);
13974 </programlisting>
13975
13976 </sect1>
13977
13978 <!-- ----------------------------------------------------------------- -->
13979 <sect1 id="sec-GtkCurve">
13980 <title>GtkCurve</title>
13981
13982 <programlisting role="C">
13983 void GtkCurve::curve-type-changed       (GtkCurve *,
13984                                          gpointer);
13985 </programlisting>
13986
13987 </sect1>
13988
13989 <!-- ----------------------------------------------------------------- -->
13990 <sect1 id="sec-GtkAdjustment">
13991 <title>GtkAdjustment</title>
13992
13993 <programlisting role="C">
13994 void GtkAdjustment::changed     (GtkAdjustment *,
13995                                  gpointer);
13996 void GtkAdjustment::value-changed       (GtkAdjustment *,
13997                                          gpointer);
13998 </programlisting>
13999
14000 </sect1>
14001 </appendix>
14002
14003 <!-- ***************************************************************** -->
14004 <appendix id="app-GDKEventTypes">
14005 <title>GDK Event Types</title>
14006
14007 <para>The following data types are passed into event handlers by GTK+. For
14008 each data type listed, the signals that use this data type are listed.</para>
14009
14010 <itemizedlist>
14011 <listitem><simpara>  GdkEvent</simpara>
14012           <itemizedlist>
14013           <listitem><simpara>drag_end_event</simpara>
14014           </listitem>
14015           </itemizedlist>
14016 </listitem>
14017
14018 <listitem><simpara>  GdkEventType<</simpara>
14019 </listitem>
14020
14021 <listitem><simpara>  GdkEventAny</simpara>
14022           <itemizedlist>
14023           <listitem><simpara>delete_event</simpara>
14024           </listitem>
14025           <listitem><simpara>destroy_event</simpara>
14026           </listitem>
14027           <listitem><simpara>map_event</simpara>
14028           </listitem>
14029           <listitem><simpara>unmap_event</simpara>
14030           </listitem>
14031           <listitem><simpara>no_expose_event</simpara>
14032           </listitem>
14033           </itemizedlist>
14034 </listitem>
14035
14036 <listitem><simpara>  GdkEventExpose</simpara>
14037           <itemizedlist>
14038           <listitem><simpara>expose_event</simpara>
14039           </listitem>
14040           </itemizedlist>
14041 </listitem>
14042
14043 <listitem><simpara>  GdkEventNoExpose</simpara>
14044 </listitem>
14045
14046 <listitem><simpara>  GdkEventVisibility</simpara>
14047 </listitem>
14048
14049 <listitem><simpara>  GdkEventMotion</simpara>
14050           <itemizedlist>
14051           <listitem><simpara>motion_notify_event</simpara>
14052           </listitem>
14053           </itemizedlist>
14054 </listitem>
14055 <listitem><simpara>  GdkEventButton</simpara>
14056           <itemizedlist>
14057           <listitem><simpara>button_press_event</simpara>
14058           </listitem>
14059           <listitem><simpara>button_release_event</simpara>
14060           </listitem>
14061           </itemizedlist>
14062 </listitem>
14063
14064 <listitem><simpara>  GdkEventKey</simpara>
14065           <itemizedlist>
14066           <listitem><simpara>key_press_event</simpara>
14067           </listitem>
14068           <listitem><simpara>key_release_event</simpara>
14069           </listitem>
14070           </itemizedlist>
14071 </listitem>
14072
14073 <listitem><simpara>  GdkEventCrossing</simpara>
14074           <itemizedlist>
14075           <listitem><simpara>enter_notify_event</simpara>
14076           </listitem>
14077           <listitem><simpara>leave_notify_event</simpara>
14078           </listitem>
14079           </itemizedlist>
14080 </listitem>
14081
14082 <listitem><simpara>  GdkEventFocus</simpara>
14083           <itemizedlist>
14084           <listitem><simpara>focus_in_event</simpara>
14085           </listitem>
14086           <listitem><simpara>focus_out_event</simpara>
14087           </listitem>
14088           </itemizedlist>
14089 </listitem>
14090
14091 <listitem><simpara>  GdkEventConfigure</simpara>
14092           <itemizedlist>
14093           <listitem><simpara>configure_event</simpara>
14094           </listitem>
14095           </itemizedlist>
14096 </listitem>
14097
14098 <listitem><simpara>  GdkEventProperty</simpara>
14099           <itemizedlist>
14100           <listitem><simpara>property_notify_event</simpara>
14101           </listitem>
14102           </itemizedlist>
14103 </listitem>
14104
14105 <listitem><simpara>  GdkEventSelection</simpara>
14106           <itemizedlist>
14107           <listitem><simpara>selection_clear_event</simpara>
14108           </listitem>
14109           <listitem><simpara>selection_request_event</simpara>
14110           </listitem>
14111           <listitem><simpara>selection_notify_event</simpara>
14112           </listitem>
14113           </itemizedlist>
14114 </listitem>
14115
14116 <listitem><simpara>  GdkEventProximity</simpara>
14117           <itemizedlist>
14118           <listitem><simpara>proximity_in_event</simpara>
14119           </listitem>
14120           <listitem><simpara>proximity_out_event</simpara>
14121           </listitem>
14122           </itemizedlist>
14123 </listitem>
14124
14125 <listitem><simpara>  GdkEventDragBegin</simpara>
14126           <itemizedlist>
14127           <listitem><simpara>drag_begin_event</simpara>
14128           </listitem>
14129           </itemizedlist>
14130 </listitem>
14131
14132 <listitem><simpara>  GdkEventDragRequest</simpara>
14133           <itemizedlist>
14134           <listitem><simpara>drag_request_event</simpara>
14135           </listitem>
14136           </itemizedlist>
14137 </listitem>
14138
14139 <listitem><simpara>  GdkEventDropEnter</simpara>
14140           <itemizedlist>
14141           <listitem><simpara>drop_enter_event</simpara>
14142           </listitem>
14143           </itemizedlist>
14144 </listitem>
14145
14146 <listitem><simpara>  GdkEventDropLeave</simpara>
14147           <itemizedlist>
14148           <listitem><simpara>drop_leave_event</simpara>
14149           </listitem>
14150           </itemizedlist>
14151 </listitem>
14152
14153 <listitem><simpara>  GdkEventDropDataAvailable</simpara>
14154           <itemizedlist>
14155           <listitem><simpara>drop_data_available_event</simpara>
14156           </listitem>
14157           </itemizedlist>
14158 </listitem>
14159
14160 <listitem><simpara>  GdkEventClient</simpara>
14161           <itemizedlist>
14162           <listitem><simpara>client_event</simpara>
14163           </listitem>
14164           </itemizedlist>
14165 </listitem>
14166
14167 <listitem><simpara>  GdkEventOther</simpara>
14168           <itemizedlist>
14169           <listitem><simpara>other_event</simpara>
14170           </listitem>
14171           </itemizedlist>
14172 </listitem>
14173 </itemizedlist>
14174
14175 <para>The data type <literal>GdkEventType</literal> is a special data type that is used by
14176 all the other data types as an indicator of the data type being passed
14177 to the signal handler. As you will see below, each of the event data
14178 structures has a member of this type. It is defined as an enumeration
14179 type as follows:</para>
14180
14181 <programlisting role="C">
14182 typedef enum
14183 {
14184   GDK_NOTHING           = -1,
14185   GDK_DELETE            = 0,
14186   GDK_DESTROY           = 1,
14187   GDK_EXPOSE            = 2,
14188   GDK_MOTION_NOTIFY     = 3,
14189   GDK_BUTTON_PRESS      = 4,
14190   GDK_2BUTTON_PRESS     = 5,
14191   GDK_3BUTTON_PRESS     = 6,
14192   GDK_BUTTON_RELEASE    = 7,
14193   GDK_KEY_PRESS         = 8,
14194   GDK_KEY_RELEASE       = 9,
14195   GDK_ENTER_NOTIFY      = 10,
14196   GDK_LEAVE_NOTIFY      = 11,
14197   GDK_FOCUS_CHANGE      = 12,
14198   GDK_CONFIGURE         = 13,
14199   GDK_MAP               = 14,
14200   GDK_UNMAP             = 15,
14201   GDK_PROPERTY_NOTIFY   = 16,
14202   GDK_SELECTION_CLEAR   = 17,
14203   GDK_SELECTION_REQUEST = 18,
14204   GDK_SELECTION_NOTIFY  = 19,
14205   GDK_PROXIMITY_IN      = 20,
14206   GDK_PROXIMITY_OUT     = 21,
14207   GDK_DRAG_BEGIN        = 22,
14208   GDK_DRAG_REQUEST      = 23,
14209   GDK_DROP_ENTER        = 24,
14210   GDK_DROP_LEAVE        = 25,
14211   GDK_DROP_DATA_AVAIL   = 26,
14212   GDK_CLIENT_EVENT      = 27,
14213   GDK_VISIBILITY_NOTIFY = 28,
14214   GDK_NO_EXPOSE         = 29,
14215   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
14216 } GdkEventType;
14217 </programlisting>
14218
14219 <para>The other event type that is different from the others is
14220 <literal>GdkEvent</literal> itself. This is a union of all the other
14221 data types, which allows it to be cast to a specific
14222 event data type within a signal handler.</para>
14223
14224 <!-- Just a big list for now, needs expanding upon - TRG -->
14225 <para>So, the event data types are defined as follows:</para>
14226
14227 <programlisting role="C">
14228 struct _GdkEventAny
14229 {
14230   GdkEventType type;
14231   GdkWindow *window;
14232   gint8 send_event;
14233 };
14234
14235 struct _GdkEventExpose
14236 {
14237   GdkEventType type;
14238   GdkWindow *window;
14239   gint8 send_event;
14240   GdkRectangle area;
14241   gint count; /* If non-zero, how many more events follow. */
14242 };
14243
14244 struct _GdkEventNoExpose
14245 {
14246   GdkEventType type;
14247   GdkWindow *window;
14248   gint8 send_event;
14249   /* XXX: does anyone need the X major_code or minor_code fields? */
14250 };
14251
14252 struct _GdkEventVisibility
14253 {
14254   GdkEventType type;
14255   GdkWindow *window;
14256   gint8 send_event;
14257   GdkVisibilityState state;
14258 };
14259
14260 struct _GdkEventMotion
14261 {
14262   GdkEventType type;
14263   GdkWindow *window;
14264   gint8 send_event;
14265   guint32 time;
14266   gdouble x;
14267   gdouble y;
14268   gdouble pressure;
14269   gdouble xtilt;
14270   gdouble ytilt;
14271   guint state;
14272   gint16 is_hint;
14273   GdkInputSource source;
14274   guint32 deviceid;
14275   gdouble x_root, y_root;
14276 };
14277
14278 struct _GdkEventButton
14279 {
14280   GdkEventType type;
14281   GdkWindow *window;
14282   gint8 send_event;
14283   guint32 time;
14284   gdouble x;
14285   gdouble y;
14286   gdouble pressure;
14287   gdouble xtilt;
14288   gdouble ytilt;
14289   guint state;
14290   guint button;
14291   GdkInputSource source;
14292   guint32 deviceid;
14293   gdouble x_root, y_root;
14294 };
14295
14296 struct _GdkEventKey
14297 {
14298   GdkEventType type;
14299   GdkWindow *window;
14300   gint8 send_event;
14301   guint32 time;
14302   guint state;
14303   guint keyval;
14304   gint length;
14305   gchar *string;
14306 };
14307
14308 struct _GdkEventCrossing
14309 {
14310   GdkEventType type;
14311   GdkWindow *window;
14312   gint8 send_event;
14313   GdkWindow *subwindow;
14314   GdkNotifyType detail;
14315 };
14316
14317 struct _GdkEventFocus
14318 {
14319   GdkEventType type;
14320   GdkWindow *window;
14321   gint8 send_event;
14322   gint16 in;
14323 };
14324
14325 struct _GdkEventConfigure
14326 {
14327   GdkEventType type;
14328   GdkWindow *window;
14329   gint8 send_event;
14330   gint16 x, y;
14331   gint16 width;
14332   gint16 height;
14333 };
14334
14335 struct _GdkEventProperty
14336 {
14337   GdkEventType type;
14338   GdkWindow *window;
14339   gint8 send_event;
14340   GdkAtom atom;
14341   guint32 time;
14342   guint state;
14343 };
14344
14345 struct _GdkEventSelection
14346 {
14347   GdkEventType type;
14348   GdkWindow *window;
14349   gint8 send_event;
14350   GdkAtom selection;
14351   GdkAtom target;
14352   GdkAtom property;
14353   guint32 requestor;
14354   guint32 time;
14355 };
14356
14357 /* This event type will be used pretty rarely. It only is important
14358    for XInput aware programs that are drawing their own cursor */
14359
14360 struct _GdkEventProximity
14361 {
14362   GdkEventType type;
14363   GdkWindow *window;
14364   gint8 send_event;
14365   guint32 time;
14366   GdkInputSource source;
14367   guint32 deviceid;
14368 };
14369
14370 struct _GdkEventDragRequest
14371 {
14372   GdkEventType type;
14373   GdkWindow *window;
14374   gint8 send_event;
14375   guint32 requestor;
14376   union {
14377     struct {
14378       guint protocol_version:4;
14379       guint sendreply:1;
14380       guint willaccept:1;
14381       guint delete_data:1; /* Do *not* delete if link is sent, only
14382                               if data is sent */
14383       guint senddata:1;
14384       guint reserved:22;
14385     } flags;
14386     glong allflags;
14387   } u;
14388   guint8 isdrop; /* This gdk event can be generated by a couple of
14389                     X events - this lets the app know whether the
14390                     drop really occurred or we just set the data */
14391
14392   GdkPoint drop_coords;
14393   gchar *data_type;
14394   guint32 timestamp;
14395 };
14396
14397 struct _GdkEventDragBegin
14398 {
14399   GdkEventType type;
14400   GdkWindow *window;
14401   gint8 send_event;
14402   union {
14403     struct {
14404       guint protocol_version:4;
14405       guint reserved:28;
14406     } flags;
14407     glong allflags;
14408   } u;
14409 };
14410
14411 struct _GdkEventDropEnter
14412 {
14413   GdkEventType type;
14414   GdkWindow *window;
14415   gint8 send_event;
14416   guint32 requestor;
14417   union {
14418     struct {
14419       guint protocol_version:4;
14420       guint sendreply:1;
14421       guint extended_typelist:1;
14422       guint reserved:26;
14423     } flags;
14424     glong allflags;
14425   } u;
14426 };
14427
14428 struct _GdkEventDropLeave
14429 {
14430   GdkEventType type;
14431   GdkWindow *window;
14432   gint8 send_event;
14433   guint32 requestor;
14434   union {
14435     struct {
14436       guint protocol_version:4;
14437       guint reserved:28;
14438     } flags;
14439     glong allflags;
14440   } u;
14441 };
14442
14443 struct _GdkEventDropDataAvailable
14444 {
14445   GdkEventType type;
14446   GdkWindow *window;
14447   gint8 send_event;
14448   guint32 requestor;
14449   union {
14450     struct {
14451       guint protocol_version:4;
14452       guint isdrop:1;
14453       guint reserved:25;
14454     } flags;
14455     glong allflags;
14456   } u;
14457   gchar *data_type; /* MIME type */
14458   gulong data_numbytes;
14459   gpointer data;
14460   guint32 timestamp;
14461   GdkPoint coords;
14462 };
14463
14464 struct _GdkEventClient
14465 {
14466   GdkEventType type;
14467   GdkWindow *window;
14468   gint8 send_event;
14469   GdkAtom message_type;
14470   gushort data_format;
14471   union {
14472     char b[20];
14473     short s[10];
14474     long l[5];
14475   } data;
14476 };
14477
14478 struct _GdkEventOther
14479 {
14480   GdkEventType type;
14481   GdkWindow *window;
14482   gint8 send_event;
14483   GdkXEvent *xevent;
14484 };
14485 </programlisting>
14486
14487 </appendix>
14488
14489 <!-- ***************************************************************** -->
14490 <appendix id="app-CodeExamples">
14491 <title>Code Examples</title>
14492
14493 <para>Below are the code examples that are used in the above text
14494 which are not included in complete form elsewhere.</para>
14495
14496 <!-- ----------------------------------------------------------------- -->
14497 <sect1 id="sec-Tictactoe">
14498 <title>Tictactoe</title>
14499 <!-- ----------------------------------------------------------------- -->
14500 <sect2>
14501 <title>tictactoe.h</title>
14502
14503 <programlisting role="C">
14504 <!-- example-start tictactoe tictactoe.h -->
14505 /* GTK - The GIMP Toolkit
14506  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14507  *
14508  * This library is free software; you can redistribute it and/or
14509  * modify it under the terms of the GNU Library General Public
14510  * License as published by the Free Software Foundation; either
14511  * version 2 of the License, or (at your option) any later version.
14512  *
14513  * This library is distributed in the hope that it will be useful,
14514  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14515  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14516  * Library General Public License for more details.
14517  *
14518  * You should have received a copy of the GNU Library General Public
14519  * License along with this library; if not, write to the
14520  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14521  * Boston, MA 02111-1307, USA.
14522  */
14523 #ifndef __TICTACTOE_H__
14524 #define __TICTACTOE_H__
14525
14526
14527 #include &lt;glib.h&gt;
14528 #include &lt;glib-object.h&gt;
14529 #include &lt;gtk/gtktable.h&gt;
14530
14531
14532 G_BEGIN_DECLS
14533
14534 #define TICTACTOE_TYPE            (tictactoe_get_type ())
14535 #define TICTACTOE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TICTACTOE_TYPE, Tictactoe))
14536 #define TICTACTOE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TICTACTOE_TYPE, TictactoeClass))
14537 #define IS_TICTACTOE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TICTACTOE_TYPE))
14538 #define IS_TICTACTOE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TICTACTOE_TYPE))
14539
14540
14541 typedef struct _Tictactoe       Tictactoe;
14542 typedef struct _TictactoeClass  TictactoeClass;
14543
14544 struct _Tictactoe
14545 {
14546   GtkTable table;
14547   
14548   GtkWidget *buttons[3][3];
14549 };
14550
14551 struct _TictactoeClass
14552 {
14553   GtkTableClass parent_class;
14554
14555   void (* tictactoe) (Tictactoe *ttt);
14556 };
14557
14558 GType          tictactoe_get_type        (void);
14559 GtkWidget*     tictactoe_new             (void);
14560 void           tictactoe_clear           (Tictactoe *ttt);
14561
14562 G_END_DECLS
14563
14564 #endif /* __TICTACTOE_H__ */
14565
14566 <!-- example-end -->
14567 </programlisting>
14568
14569 </sect2>
14570
14571 <!-- ----------------------------------------------------------------- -->
14572 <sect2>
14573 <title>tictactoe.c</title>
14574
14575 <programlisting role="C">
14576 <!-- example-start tictactoe tictactoe.c -->
14577
14578 /* GTK - The GIMP Toolkit
14579  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14580  *
14581  * This library is free software; you can redistribute it and/or
14582  * modify it under the terms of the GNU Library General Public
14583  * License as published by the Free Software Foundation; either
14584  * version 2 of the License, or (at your option) any later version.
14585  *
14586  * This library is distributed in the hope that it will be useful,
14587  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14588  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14589  * Library General Public License for more details.
14590  *
14591  * You should have received a copy of the GNU Library General Public
14592  * License along with this library; if not, write to the
14593  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14594  * Boston, MA 02111-1307, USA.
14595  */
14596 #include &lt;gtk/gtksignal.h&gt;
14597 #include &lt;gtk/gtktable.h&gt;
14598 #include &lt;gtk/gtktogglebutton.h&gt;
14599 #include "tictactoe.h"
14600
14601 enum {
14602   TICTACTOE_SIGNAL,
14603   LAST_SIGNAL
14604 };
14605
14606 static void tictactoe_class_init          (TictactoeClass *klass);
14607 static void tictactoe_init                (Tictactoe      *ttt);
14608 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
14609
14610 static guint tictactoe_signals[LAST_SIGNAL] = { 0 };
14611
14612 GType
14613 tictactoe_get_type (void)
14614 {
14615   static GType ttt_type = 0;
14616
14617   if (!ttt_type)
14618     {
14619       static const GTypeInfo ttt_info =
14620       {
14621         sizeof (TictactoeClass),
14622         NULL, /* base_init */
14623         NULL, /* base_finalize */
14624         (GClassInitFunc) tictactoe_class_init,
14625         NULL, /* class_finalize */
14626         NULL, /* class_data */
14627         sizeof (Tictactoe),
14628         0,
14629         (GInstanceInitFunc) tictactoe_init,
14630       };
14631
14632       ttt_type = g_type_register_static (GTK_TYPE_TABLE, "Tictactoe", &amp;ttt_info, 0);
14633     }
14634
14635   return ttt_type;
14636 }
14637
14638 static void
14639 tictactoe_class_init (TictactoeClass *klass)
14640 {
14641   
14642   tictactoe_signals[TICTACTOE_SIGNAL] = g_signal_new ("tictactoe",
14643                                          G_TYPE_FROM_CLASS (klass),
14644                                          G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
14645                                          G_STRUCT_OFFSET (TictactoeClass, tictactoe),
14646                                          NULL, 
14647                                          NULL,                
14648                                          g_cclosure_marshal_VOID__VOID,
14649                                          G_TYPE_NONE, 0);
14650
14651
14652 }
14653
14654 static void
14655 tictactoe_init (Tictactoe *ttt)
14656 {
14657   gint i,j;
14658   
14659   gtk_table_resize (GTK_TABLE (ttt), 3, 3);
14660   gtk_table_set_homogeneous (GTK_TABLE (ttt), TRUE);
14661
14662   for (i=0;i&lt;3; i++)
14663     for (j=0;j&lt;3; j++)      {
14664         ttt-&gt;buttons[i][j] = gtk_toggle_button_new ();
14665         gtk_table_attach_defaults (GTK_TABLE (ttt), ttt-&gt;buttons[i][j], 
14666                                    i, i+1, j, j+1);
14667         g_signal_connect (G_OBJECT (ttt-&gt;buttons[i][j]), "toggled",
14668                           G_CALLBACK (tictactoe_toggle), (gpointer) ttt);
14669         gtk_widget_set_size_request (ttt-&gt;buttons[i][j], 20, 20);
14670         gtk_widget_show (ttt-&gt;buttons[i][j]);
14671       }
14672 }
14673
14674 GtkWidget*
14675 tictactoe_new ()
14676 {
14677   return GTK_WIDGET (g_object_new (tictactoe_get_type (), NULL));
14678 }
14679
14680 void           
14681 tictactoe_clear (Tictactoe *ttt)
14682 {
14683   int i,j;
14684
14685   for (i = 0; i&lt;3; i++)
14686     for (j = 0; j&lt;3; j++)
14687       {
14688         g_signal_handlers_block_matched (G_OBJECT (ttt-&gt;buttons[i][j]), 
14689                                          G_SIGNAL_MATCH_DATA,
14690                                          0, 0, NULL, NULL, ttt);
14691         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt-&gt;buttons[i][j]),
14692                                       FALSE);
14693         g_signal_handlers_unblock_matched (G_OBJECT (ttt->buttons[i][j]),
14694                                            G_SIGNAL_MATCH_DATA,
14695                                            0, 0, NULL, NULL, ttt);
14696       }
14697 }
14698
14699 static void
14700 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
14701 {
14702   int i,k;
14703
14704   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
14705                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
14706                              { 0, 1, 2 }, { 0, 1, 2 } };
14707   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
14708                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
14709                              { 0, 1, 2 }, { 2, 1, 0 } };
14710
14711   int success, found;
14712
14713   for (k = 0; k&lt;8; k++)
14714     {
14715       success = TRUE;
14716       found = FALSE;
14717
14718       for (i = 0; i&lt;3; i++)
14719         {
14720           success = success &amp;&amp; 
14721             GTK_TOGGLE_BUTTON (ttt-&gt;buttons[rwins[k][i]][cwins[k][i]])-&gt;active;
14722           found = found ||
14723             ttt-&gt;buttons[rwins[k][i]][cwins[k][i]] == widget;
14724         }
14725       
14726       if (success &amp;&amp; found)
14727         {
14728           g_signal_emit (G_OBJECT (ttt), 
14729                          tictactoe_signals[TICTACTOE_SIGNAL], 0);
14730           break;
14731         }
14732     }
14733 }
14734
14735 <!-- example-end -->
14736 </programlisting>
14737
14738 </sect2>
14739
14740 <!-- ----------------------------------------------------------------- -->
14741 <sect2>
14742 <title>ttt_test.c</title>
14743
14744 <programlisting role="C">
14745 <!-- example-start tictactoe ttt_test.c -->
14746
14747 #include &lt;stdlib.h&gt;
14748 #include &lt;gtk/gtk.h&gt;
14749 #include "tictactoe.h"
14750
14751 void win( GtkWidget *widget,
14752           gpointer   data )
14753 {
14754   g_print ("Yay!\n");
14755   tictactoe_clear (TICTACTOE (widget));
14756 }
14757
14758 int main( int   argc,
14759           char *argv[] )
14760 {
14761   GtkWidget *window;
14762   GtkWidget *ttt;
14763   
14764   gtk_init (&amp;argc, &amp;argv);
14765
14766   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
14767   
14768   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
14769   
14770   g_signal_connect (G_OBJECT (window), "destroy",
14771                     G_CALLBACK (exit), NULL);
14772   
14773   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
14774
14775   ttt = tictactoe_new ();
14776   
14777   gtk_container_add (GTK_CONTAINER (window), ttt);
14778   gtk_widget_show (ttt);
14779
14780   /* And attach to its "tictactoe" signal */
14781   g_signal_connect (G_OBJECT (ttt), "tictactoe",
14782                     G_CALLBACK (win), NULL);
14783
14784   gtk_widget_show (window);
14785   
14786   gtk_main ();
14787   
14788   return 0;
14789 }
14790
14791 <!-- example-end -->
14792 </programlisting>
14793
14794 </sect2>
14795 </sect1>
14796
14797 <!-- ----------------------------------------------------------------- -->
14798 <sect1 id="sec-GtkDial">
14799 <title>GtkDial</title>
14800
14801 <!-- ----------------------------------------------------------------- -->
14802 <sect2>
14803 <title>gtkdial.h</title>
14804
14805 <programlisting role="C">
14806 <!-- example-start gtkdial gtkdial.h -->
14807
14808 /* GTK - The GIMP Toolkit
14809  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14810  *
14811  * This library is free software; you can redistribute it and/or
14812  * modify it under the terms of the GNU Library General Public
14813  * License as published by the Free Software Foundation; either
14814  * version 2 of the License, or (at your option) any later version.
14815  *
14816  * This library is distributed in the hope that it will be useful,
14817  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14818  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14819  * Library General Public License for more details.
14820  *
14821  * You should have received a copy of the GNU Library General Public
14822  * License along with this library; if not, write to the
14823  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14824  * Boston, MA 02111-1307, USA.
14825  */
14826 #ifndef __GTK_DIAL_H__
14827 #define __GTK_DIAL_H__
14828
14829
14830 #include &lt;gdk/gdk.h&gt;
14831 #include &lt;gtk/gtkadjustment.h&gt;
14832 #include &lt;gtk/gtkwidget.h&gt;
14833
14834
14835 #ifdef __cplusplus
14836 extern "C" {
14837 #endif /* __cplusplus */
14838
14839
14840 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
14841 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
14842 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
14843
14844
14845 typedef struct _GtkDial        GtkDial;
14846 typedef struct _GtkDialClass   GtkDialClass;
14847
14848 struct _GtkDial
14849 {
14850   GtkWidget widget;
14851
14852   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
14853   guint policy : 2;
14854
14855   /* Button currently pressed or 0 if none */
14856   guint8 button;
14857
14858   /* Dimensions of dial components */
14859   gint radius;
14860   gint pointer_width;
14861
14862   /* ID of update timer, or 0 if none */
14863   guint32 timer;
14864
14865   /* Current angle */
14866   gfloat angle;
14867   gfloat last_angle;
14868
14869   /* Old values from adjustment stored so we know when something changes */
14870   gfloat old_value;
14871   gfloat old_lower;
14872   gfloat old_upper;
14873
14874   /* The adjustment object that stores the data for this dial */
14875   GtkAdjustment *adjustment;
14876 };
14877
14878 struct _GtkDialClass
14879 {
14880   GtkWidgetClass parent_class;
14881 };
14882
14883
14884 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
14885 GtkType        gtk_dial_get_type               (void);
14886 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
14887 void           gtk_dial_set_update_policy      (GtkDial      *dial,
14888                                                 GtkUpdateType  policy);
14889
14890 void           gtk_dial_set_adjustment         (GtkDial      *dial,
14891                                                 GtkAdjustment *adjustment);
14892 #ifdef __cplusplus
14893 }
14894 #endif /* __cplusplus */
14895
14896
14897 #endif /* __GTK_DIAL_H__ */
14898 <!-- example-end -->
14899 </programlisting>
14900
14901 </sect2>
14902
14903 <!-- ----------------------------------------------------------------- -->
14904 <sect2>
14905 <title>gtkdial.c</title>
14906
14907 <programlisting role="C">
14908 <!-- example-start gtkdial gtkdial.c -->
14909
14910 /* GTK - The GIMP Toolkit
14911  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14912  *
14913  * This library is free software; you can redistribute it and/or
14914  * modify it under the terms of the GNU Library General Public
14915  * License as published by the Free Software Foundation; either
14916  * version 2 of the License, or (at your option) any later version.
14917  *
14918  * This library is distributed in the hope that it will be useful,
14919  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14920  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14921  * Library General Public License for more details.
14922  *
14923  * You should have received a copy of the GNU Library General Public
14924  * License along with this library; if not, write to the
14925  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14926  * Boston, MA 02111-1307, USA.
14927  */
14928 #include &lt;math.h&gt;
14929 #include &lt;stdio.h&gt;
14930 #include &lt;gtk/gtkmain.h&gt;
14931 #include &lt;gtk/gtksignal.h&gt;
14932
14933 #include "gtkdial.h"
14934
14935 #define SCROLL_DELAY_LENGTH  300
14936 #define DIAL_DEFAULT_SIZE 100
14937
14938 /* Forward declarations */
14939
14940 static void gtk_dial_class_init               (GtkDialClass     *klass);
14941 static void gtk_dial_init                     (GtkDial          *dial);
14942 static void gtk_dial_destroy                  (GtkObject        *object);
14943 static void gtk_dial_realize                  (GtkWidget        *widget);
14944 static void gtk_dial_size_request             (GtkWidget        *widget,
14945                                                GtkRequisition   *requisition);
14946 static void gtk_dial_size_allocate            (GtkWidget        *widget,
14947                                                GtkAllocation    *allocation);
14948 static gboolean gtk_dial_expose               (GtkWidget        *widget,
14949                                                GdkEventExpose   *event);
14950 static gboolean gtk_dial_button_press         (GtkWidget        *widget,
14951                                                GdkEventButton   *event);
14952 static gboolean gtk_dial_button_release       (GtkWidget        *widget,
14953                                                GdkEventButton   *event);
14954 static gboolean gtk_dial_motion_notify        (GtkWidget        *widget,
14955                                                GdkEventMotion   *event);
14956 static gboolean gtk_dial_timer                (GtkDial          *dial);
14957
14958 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
14959 static void gtk_dial_update                   (GtkDial *dial);
14960 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
14961                                                 gpointer          data);
14962 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
14963                                                 gpointer          data);
14964
14965 /* Local data */
14966
14967 static GtkWidgetClass *parent_class = NULL;
14968
14969 GType
14970 gtk_dial_get_type ()
14971 {
14972   static GType dial_type = 0;
14973
14974   if (!dial_type)
14975     {
14976       static const GTypeInfo dial_info =
14977       {
14978         sizeof (GtkDialClass),
14979         NULL,
14980         NULL,
14981         (GClassInitFunc) gtk_dial_class_init,
14982         NULL,
14983         NULL,
14984         sizeof (GtkDial),
14985         0,
14986         (GInstanceInitFunc) gtk_dial_init,
14987       };
14988
14989       dial_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkDial", &amp;dial_info, 0);
14990     }
14991
14992   return dial_type;
14993 }
14994
14995 static void
14996 gtk_dial_class_init (GtkDialClass *class)
14997 {
14998   GtkObjectClass *object_class;
14999   GtkWidgetClass *widget_class;
15000
15001   object_class = (GtkObjectClass*) class;
15002   widget_class = (GtkWidgetClass*) class;
15003
15004   parent_class = gtk_type_class (gtk_widget_get_type ());
15005
15006   object_class-&gt;destroy = gtk_dial_destroy;
15007
15008   widget_class-&gt;realize = gtk_dial_realize;
15009   widget_class-&gt;expose_event = gtk_dial_expose;
15010   widget_class-&gt;size_request = gtk_dial_size_request;
15011   widget_class-&gt;size_allocate = gtk_dial_size_allocate;
15012   widget_class-&gt;button_press_event = gtk_dial_button_press;
15013   widget_class-&gt;button_release_event = gtk_dial_button_release;
15014   widget_class-&gt;motion_notify_event = gtk_dial_motion_notify;
15015 }
15016
15017 static void
15018 gtk_dial_init (GtkDial *dial)
15019 {
15020   dial-&gt;button = 0;
15021   dial-&gt;policy = GTK_UPDATE_CONTINUOUS;
15022   dial-&gt;timer = 0;
15023   dial-&gt;radius = 0;
15024   dial-&gt;pointer_width = 0;
15025   dial-&gt;angle = 0.0;
15026   dial-&gt;old_value = 0.0;
15027   dial-&gt;old_lower = 0.0;
15028   dial-&gt;old_upper = 0.0;
15029   dial-&gt;adjustment = NULL;
15030 }
15031
15032 GtkWidget*
15033 gtk_dial_new (GtkAdjustment *adjustment)
15034 {
15035   GtkDial *dial;
15036
15037   dial = g_object_new (gtk_dial_get_type (), NULL);
15038
15039   if (!adjustment)
15040     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
15041
15042   gtk_dial_set_adjustment (dial, adjustment);
15043
15044   return GTK_WIDGET (dial);
15045 }
15046
15047 static void
15048 gtk_dial_destroy (GtkObject *object)
15049 {
15050   GtkDial *dial;
15051
15052   g_return_if_fail (object != NULL);
15053   g_return_if_fail (GTK_IS_DIAL (object));
15054
15055   dial = GTK_DIAL (object);
15056
15057   if (dial-&gt;adjustment)
15058     {
15059       g_object_unref (GTK_OBJECT (dial-&gt;adjustment));
15060       dial-&gt;adjustment = NULL;
15061     }
15062
15063   if (GTK_OBJECT_CLASS (parent_class)-&gt;destroy)
15064     (* GTK_OBJECT_CLASS (parent_class)-&gt;destroy) (object);
15065 }
15066
15067 GtkAdjustment*
15068 gtk_dial_get_adjustment (GtkDial *dial)
15069 {
15070   g_return_val_if_fail (dial != NULL, NULL);
15071   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
15072
15073   return dial-&gt;adjustment;
15074 }
15075
15076 void
15077 gtk_dial_set_update_policy (GtkDial      *dial,
15078                              GtkUpdateType  policy)
15079 {
15080   g_return_if_fail (dial != NULL);
15081   g_return_if_fail (GTK_IS_DIAL (dial));
15082
15083   dial-&gt;policy = policy;
15084 }
15085
15086 void
15087 gtk_dial_set_adjustment (GtkDial      *dial,
15088                           GtkAdjustment *adjustment)
15089 {
15090   g_return_if_fail (dial != NULL);
15091   g_return_if_fail (GTK_IS_DIAL (dial));
15092
15093   if (dial-&gt;adjustment)
15094     {
15095       g_signal_handlers_disconnect_by_func (GTK_OBJECT (dial-&gt;adjustment), NULL, (gpointer) dial);
15096       g_object_unref (GTK_OBJECT (dial-&gt;adjustment));
15097     }
15098
15099   dial-&gt;adjustment = adjustment;
15100   g_object_ref (GTK_OBJECT (dial-&gt;adjustment));
15101
15102   g_signal_connect (GTK_OBJECT (adjustment), "changed",
15103                     GTK_SIGNAL_FUNC (gtk_dial_adjustment_changed),
15104                     (gpointer) dial);
15105   g_signal_connect (GTK_OBJECT (adjustment), "value_changed",
15106                     GTK_SIGNAL_FUNC (gtk_dial_adjustment_value_changed),
15107                     (gpointer) dial);
15108
15109   dial-&gt;old_value = adjustment-&gt;value;
15110   dial-&gt;old_lower = adjustment-&gt;lower;
15111   dial-&gt;old_upper = adjustment-&gt;upper;
15112
15113   gtk_dial_update (dial);
15114 }
15115
15116 static void
15117 gtk_dial_realize (GtkWidget *widget)
15118 {
15119   GtkDial *dial;
15120   GdkWindowAttr attributes;
15121   gint attributes_mask;
15122
15123   g_return_if_fail (widget != NULL);
15124   g_return_if_fail (GTK_IS_DIAL (widget));
15125
15126   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
15127   dial = GTK_DIAL (widget);
15128
15129   attributes.x = widget-&gt;allocation.x;
15130   attributes.y = widget-&gt;allocation.y;
15131   attributes.width = widget-&gt;allocation.width;
15132   attributes.height = widget-&gt;allocation.height;
15133   attributes.wclass = GDK_INPUT_OUTPUT;
15134   attributes.window_type = GDK_WINDOW_CHILD;
15135   attributes.event_mask = gtk_widget_get_events (widget) | 
15136     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
15137     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
15138     GDK_POINTER_MOTION_HINT_MASK;
15139   attributes.visual = gtk_widget_get_visual (widget);
15140   attributes.colormap = gtk_widget_get_colormap (widget);
15141
15142   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
15143   widget-&gt;window = gdk_window_new (widget-&gt;parent-&gt;window, &amp;attributes, attributes_mask);
15144
15145   widget-&gt;style = gtk_style_attach (widget-&gt;style, widget-&gt;window);
15146
15147   gdk_window_set_user_data (widget-&gt;window, widget);
15148
15149   gtk_style_set_background (widget-&gt;style, widget-&gt;window, GTK_STATE_ACTIVE);
15150 }
15151
15152 static void 
15153 gtk_dial_size_request (GtkWidget      *widget,
15154                        GtkRequisition *requisition)
15155 {
15156   requisition-&gt;width = DIAL_DEFAULT_SIZE;
15157   requisition-&gt;height = DIAL_DEFAULT_SIZE;
15158 }
15159
15160 static void
15161 gtk_dial_size_allocate (GtkWidget     *widget,
15162                         GtkAllocation *allocation)
15163 {
15164   GtkDial *dial;
15165
15166   g_return_if_fail (widget != NULL);
15167   g_return_if_fail (GTK_IS_DIAL (widget));
15168   g_return_if_fail (allocation != NULL);
15169
15170   widget-&gt;allocation = *allocation;
15171   dial = GTK_DIAL (widget);
15172
15173   if (GTK_WIDGET_REALIZED (widget))
15174     {
15175
15176       gdk_window_move_resize (widget-&gt;window,
15177                               allocation-&gt;x, allocation-&gt;y,
15178                               allocation-&gt;width, allocation-&gt;height);
15179
15180     }
15181   dial-&gt;radius = MIN (allocation-&gt;width, allocation-&gt;height) * 0.45;
15182   dial-&gt;pointer_width = dial-&gt;radius / 5;
15183 }
15184
15185 static gboolean
15186 gtk_dial_expose( GtkWidget      *widget,
15187                  GdkEventExpose *event )
15188 {
15189   GtkDial *dial;
15190   GdkPoint points[6];
15191   gdouble s,c;
15192   gdouble theta, last, increment;
15193   GtkStyle      *blankstyle;
15194   gint xc, yc;
15195   gint upper, lower;
15196   gint tick_length;
15197   gint i, inc;
15198
15199   g_return_val_if_fail (widget != NULL, FALSE);
15200   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15201   g_return_val_if_fail (event != NULL, FALSE);
15202
15203   if (event-&gt;count &gt; 0)
15204     return FALSE;
15205   
15206   dial = GTK_DIAL (widget);
15207
15208 /*  gdk_window_clear_area (widget-&gt;window,
15209                          0, 0,
15210                          widget-&gt;allocation.width,
15211                          widget-&gt;allocation.height);
15212 */
15213   xc = widget-&gt;allocation.width / 2;
15214   yc = widget-&gt;allocation.height / 2;
15215
15216   upper = dial-&gt;adjustment-&gt;upper;
15217   lower = dial-&gt;adjustment-&gt;lower;
15218
15219   /* Erase old pointer */
15220
15221   s = sin (dial-&gt;last_angle);
15222   c = cos (dial-&gt;last_angle);
15223   dial-&gt;last_angle = dial-&gt;angle;
15224
15225   points[0].x = xc + s*dial-&gt;pointer_width/2;
15226   points[0].y = yc + c*dial-&gt;pointer_width/2;
15227   points[1].x = xc + c*dial-&gt;radius;
15228   points[1].y = yc - s*dial-&gt;radius;
15229   points[2].x = xc - s*dial-&gt;pointer_width/2;
15230   points[2].y = yc - c*dial-&gt;pointer_width/2;
15231   points[3].x = xc - c*dial-&gt;radius/10;
15232   points[3].y = yc + s*dial-&gt;radius/10;
15233   points[4].x = points[0].x;
15234   points[4].y = points[0].y;
15235
15236   blankstyle = gtk_style_new ();
15237   blankstyle-&gt;bg_gc[GTK_STATE_NORMAL] =
15238                 widget-&gt;style-&gt;bg_gc[GTK_STATE_NORMAL];
15239   blankstyle-&gt;dark_gc[GTK_STATE_NORMAL] =
15240                 widget-&gt;style-&gt;bg_gc[GTK_STATE_NORMAL];
15241   blankstyle-&gt;light_gc[GTK_STATE_NORMAL] =
15242                 widget-&gt;style-&gt;bg_gc[GTK_STATE_NORMAL];
15243   blankstyle-&gt;black_gc =
15244                 widget-&gt;style-&gt;bg_gc[GTK_STATE_NORMAL];
15245
15246   gtk_paint_polygon (blankstyle,
15247                     widget-&gt;window,
15248                     GTK_STATE_NORMAL,
15249                     GTK_SHADOW_OUT,
15250                     NULL,
15251                     widget,
15252                     NULL,
15253                     points, 5,
15254                     FALSE);
15255
15256   g_object_unref (blankstyle);
15257
15258
15259   /* Draw ticks */
15260
15261   if ((upper - lower) == 0)
15262     return FALSE;
15263
15264   increment = (100*M_PI) / (dial-&gt;radius*dial-&gt;radius);
15265
15266   inc = (upper - lower);
15267
15268   while (inc &lt; 100) inc *= 10;
15269   while (inc &gt;= 1000) inc /= 10;
15270   last = -1;
15271
15272   for (i = 0; i &lt;= inc; i++)
15273     {
15274       theta = ((gfloat)i*M_PI / (18*inc/24.) - M_PI/6.);
15275
15276       if ((theta - last) &lt; (increment))
15277         continue;     
15278       last = theta;
15279
15280       s = sin (theta);
15281       c = cos (theta);
15282
15283       tick_length = (i%(inc/10) == 0) ? dial-&gt;pointer_width : dial-&gt;pointer_width / 2;
15284
15285       gdk_draw_line (widget-&gt;window,
15286                      widget-&gt;style-&gt;fg_gc[widget-&gt;state],
15287                      xc + c*(dial-&gt;radius - tick_length),
15288                      yc - s*(dial-&gt;radius - tick_length),
15289                      xc + c*dial-&gt;radius,
15290                      yc - s*dial-&gt;radius);
15291     }
15292
15293   /* Draw pointer */
15294
15295   s = sin (dial-&gt;angle);
15296   c = cos (dial-&gt;angle);
15297   dial-&gt;last_angle = dial-&gt;angle;
15298
15299   points[0].x = xc + s*dial-&gt;pointer_width/2;
15300   points[0].y = yc + c*dial-&gt;pointer_width/2;
15301   points[1].x = xc + c*dial-&gt;radius;
15302   points[1].y = yc - s*dial-&gt;radius;
15303   points[2].x = xc - s*dial-&gt;pointer_width/2;
15304   points[2].y = yc - c*dial-&gt;pointer_width/2;
15305   points[3].x = xc - c*dial-&gt;radius/10;
15306   points[3].y = yc + s*dial-&gt;radius/10;
15307   points[4].x = points[0].x;
15308   points[4].y = points[0].y;
15309
15310
15311   gtk_paint_polygon (widget-&gt;style,
15312                     widget-&gt;window,
15313                     GTK_STATE_NORMAL,
15314                     GTK_SHADOW_OUT,
15315                     NULL,
15316                     widget,
15317                     NULL,
15318                     points, 5,
15319                     TRUE);
15320
15321   return FALSE;
15322 }
15323
15324 static gboolean
15325 gtk_dial_button_press( GtkWidget      *widget,
15326                        GdkEventButton *event )
15327 {
15328   GtkDial *dial;
15329   gint dx, dy;
15330   double s, c;
15331   double d_parallel;
15332   double d_perpendicular;
15333
15334   g_return_val_if_fail (widget != NULL, FALSE);
15335   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15336   g_return_val_if_fail (event != NULL, FALSE);
15337
15338   dial = GTK_DIAL (widget);
15339
15340   /* Determine if button press was within pointer region - we 
15341      do this by computing the parallel and perpendicular distance of
15342      the point where the mouse was pressed from the line passing through
15343      the pointer */
15344   
15345   dx = event-&gt;x - widget-&gt;allocation.width / 2;
15346   dy = widget-&gt;allocation.height / 2 - event-&gt;y;
15347   
15348   s = sin (dial-&gt;angle);
15349   c = cos (dial-&gt;angle);
15350   
15351   d_parallel = s*dy + c*dx;
15352   d_perpendicular = fabs (s*dx - c*dy);
15353   
15354   if (!dial-&gt;button &amp;&amp;
15355       (d_perpendicular &lt; dial-&gt;pointer_width/2) &amp;&amp;
15356       (d_parallel &gt; - dial-&gt;pointer_width))
15357     {
15358       gtk_grab_add (widget);
15359
15360       dial-&gt;button = event-&gt;button;
15361
15362       gtk_dial_update_mouse (dial, event-&gt;x, event-&gt;y);
15363     }
15364
15365   return FALSE;
15366 }
15367
15368 static gboolean
15369 gtk_dial_button_release( GtkWidget      *widget,
15370                          GdkEventButton *event )
15371 {
15372   GtkDial *dial;
15373
15374   g_return_val_if_fail (widget != NULL, FALSE);
15375   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15376   g_return_val_if_fail (event != NULL, FALSE);
15377
15378   dial = GTK_DIAL (widget);
15379
15380   if (dial-&gt;button == event-&gt;button)
15381     {
15382       gtk_grab_remove (widget);
15383
15384       dial-&gt;button = 0;
15385
15386       if (dial-&gt;policy == GTK_UPDATE_DELAYED)
15387         gtk_timeout_remove (dial-&gt;timer);
15388       
15389       if ((dial-&gt;policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
15390           (dial-&gt;old_value != dial-&gt;adjustment-&gt;value))
15391         g_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), "value_changed");
15392     }
15393
15394   return FALSE;
15395 }
15396
15397 static gboolean
15398 gtk_dial_motion_notify( GtkWidget      *widget,
15399                         GdkEventMotion *event )
15400 {
15401   GtkDial *dial;
15402   GdkModifierType mods;
15403   gint x, y, mask;
15404
15405   g_return_val_if_fail (widget != NULL, FALSE);
15406   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15407   g_return_val_if_fail (event != NULL, FALSE);
15408
15409   dial = GTK_DIAL (widget);
15410
15411   if (dial-&gt;button != 0)
15412     {
15413       x = event-&gt;x;
15414       y = event-&gt;y;
15415
15416       if (event-&gt;is_hint || (event-&gt;window != widget-&gt;window))
15417         gdk_window_get_pointer (widget-&gt;window, &amp;x, &amp;y, &amp;mods);
15418
15419       switch (dial-&gt;button)
15420         {
15421         case 1:
15422           mask = GDK_BUTTON1_MASK;
15423           break;
15424         case 2:
15425           mask = GDK_BUTTON2_MASK;
15426           break;
15427         case 3:
15428           mask = GDK_BUTTON3_MASK;
15429           break;
15430         default:
15431           mask = 0;
15432           break;
15433         }
15434
15435       if (mods &amp; mask)
15436         gtk_dial_update_mouse (dial, x,y);
15437     }
15438
15439   return FALSE;
15440 }
15441
15442 static gboolean
15443 gtk_dial_timer( GtkDial *dial )
15444 {
15445   g_return_val_if_fail (dial != NULL, FALSE);
15446   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
15447
15448   if (dial-&gt;policy == GTK_UPDATE_DELAYED)
15449     g_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), "value_changed");
15450
15451   return FALSE;
15452 }
15453
15454 static void
15455 gtk_dial_update_mouse( GtkDial *dial, gint x, gint y )
15456 {
15457   gint xc, yc;
15458   gfloat old_value;
15459
15460   g_return_if_fail (dial != NULL);
15461   g_return_if_fail (GTK_IS_DIAL (dial));
15462
15463   xc = GTK_WIDGET(dial)-&gt;allocation.width / 2;
15464   yc = GTK_WIDGET(dial)-&gt;allocation.height / 2;
15465
15466   old_value = dial-&gt;adjustment-&gt;value;
15467   dial-&gt;angle = atan2(yc-y, x-xc);
15468
15469   if (dial-&gt;angle &lt; -M_PI/2.)
15470     dial-&gt;angle += 2*M_PI;
15471
15472   if (dial-&gt;angle &lt; -M_PI/6)
15473     dial-&gt;angle = -M_PI/6;
15474
15475   if (dial-&gt;angle &gt; 7.*M_PI/6.)
15476     dial-&gt;angle = 7.*M_PI/6.;
15477
15478   dial-&gt;adjustment-&gt;value = dial-&gt;adjustment-&gt;lower + (7.*M_PI/6 - dial-&gt;angle) *
15479     (dial-&gt;adjustment-&gt;upper - dial-&gt;adjustment-&gt;lower) / (4.*M_PI/3.);
15480
15481   if (dial-&gt;adjustment-&gt;value != old_value)
15482     {
15483       if (dial-&gt;policy == GTK_UPDATE_CONTINUOUS)
15484         {
15485           g_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), "value_changed");
15486         }
15487       else
15488         {
15489           gtk_widget_queue_draw (GTK_WIDGET (dial));
15490
15491           if (dial-&gt;policy == GTK_UPDATE_DELAYED)
15492             {
15493               if (dial-&gt;timer)
15494                 gtk_timeout_remove (dial-&gt;timer);
15495
15496               dial-&gt;timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
15497                                              (GtkFunction) gtk_dial_timer,
15498                                              (gpointer) dial);
15499             }
15500         }
15501     }
15502 }
15503
15504 static void
15505 gtk_dial_update (GtkDial *dial)
15506 {
15507   gfloat new_value;
15508   
15509   g_return_if_fail (dial != NULL);
15510   g_return_if_fail (GTK_IS_DIAL (dial));
15511
15512   new_value = dial-&gt;adjustment-&gt;value;
15513   
15514   if (new_value &lt; dial-&gt;adjustment-&gt;lower)
15515     new_value = dial-&gt;adjustment-&gt;lower;
15516
15517   if (new_value &gt; dial-&gt;adjustment-&gt;upper)
15518     new_value = dial-&gt;adjustment-&gt;upper;
15519
15520   if (new_value != dial-&gt;adjustment-&gt;value)
15521     {
15522       dial-&gt;adjustment-&gt;value = new_value;
15523       g_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), "value_changed");
15524     }
15525
15526   dial-&gt;angle = 7.*M_PI/6. - (new_value - dial-&gt;adjustment-&gt;lower) * 4.*M_PI/3. /
15527     (dial-&gt;adjustment-&gt;upper - dial-&gt;adjustment-&gt;lower);
15528
15529   gtk_widget_queue_draw (GTK_WIDGET (dial));
15530 }
15531
15532 static void
15533 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
15534                               gpointer       data)
15535 {
15536   GtkDial *dial;
15537
15538   g_return_if_fail (adjustment != NULL);
15539   g_return_if_fail (data != NULL);
15540
15541   dial = GTK_DIAL (data);
15542
15543   if ((dial-&gt;old_value != adjustment-&gt;value) ||
15544       (dial-&gt;old_lower != adjustment-&gt;lower) ||
15545       (dial-&gt;old_upper != adjustment-&gt;upper))
15546     {
15547       gtk_dial_update (dial);
15548
15549       dial-&gt;old_value = adjustment-&gt;value;
15550       dial-&gt;old_lower = adjustment-&gt;lower;
15551       dial-&gt;old_upper = adjustment-&gt;upper;
15552     }
15553 }
15554
15555 static void
15556 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
15557                                     gpointer       data)
15558 {
15559   GtkDial *dial;
15560
15561   g_return_if_fail (adjustment != NULL);
15562   g_return_if_fail (data != NULL);
15563
15564   dial = GTK_DIAL (data);
15565
15566   if (dial-&gt;old_value != adjustment-&gt;value)
15567     {
15568       gtk_dial_update (dial);
15569
15570       dial-&gt;old_value = adjustment-&gt;value;
15571     }
15572 }
15573 <!-- example-end -->
15574 </programlisting>
15575
15576 </sect2>
15577
15578 <!-- ----------------------------------------------------------------- -->
15579 <sect2>
15580 <title>dial_test.c</title>
15581
15582 <programlisting role="C">
15583 <!-- example-start gtkdial dial_test.c -->
15584
15585 #include &lt;stdio.h&gt;
15586 #include &lt;stdlib.h&gt;
15587 #include &lt;gtk/gtk.h&gt;
15588 #include "gtkdial.h"
15589
15590 void value_changed( GtkAdjustment *adjustment,
15591                     GtkWidget     *label )
15592 {
15593   char buffer[16];
15594
15595   sprintf(buffer,"%4.2f",adjustment-&gt;value);
15596   gtk_label_set_text (GTK_LABEL (label), buffer);
15597 }
15598
15599 int main( int   argc,
15600           char *argv[])
15601 {
15602   GtkWidget *window;
15603   GtkAdjustment *adjustment;
15604   GtkWidget *dial;
15605   GtkWidget *frame;
15606   GtkWidget *vbox;
15607   GtkWidget *label;
15608   
15609   gtk_init (&amp;argc, &amp;argv);
15610
15611   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15612   
15613   gtk_window_set_title (GTK_WINDOW (window), "Dial");
15614   
15615   g_signal_connect (G_OBJECT (window), "destroy",
15616                     G_CALLBACK (exit), NULL);
15617   
15618   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
15619
15620   vbox = gtk_vbox_new (FALSE, 5);
15621   gtk_container_add (GTK_CONTAINER (window), vbox);
15622   gtk_widget_show (vbox);
15623
15624   frame = gtk_frame_new (NULL);
15625   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
15626   gtk_container_add (GTK_CONTAINER (vbox), frame);
15627   gtk_widget_show (frame); 
15628  
15629   adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 100, 0.01, 0.1, 0));
15630   
15631   dial = gtk_dial_new (adjustment);
15632   gtk_dial_set_update_policy (GTK_DIAL (dial), GTK_UPDATE_DELAYED);
15633   /*  gtk_widget_set_size_request (dial, 100, 100); */
15634   
15635   gtk_container_add (GTK_CONTAINER (frame), dial);
15636   gtk_widget_show (dial);
15637
15638   label = gtk_label_new ("0.00");
15639   gtk_box_pack_end (GTK_BOX (vbox), label, 0, 0, 0);
15640   gtk_widget_show (label);
15641
15642   g_signal_connect (G_OBJECT (adjustment), "value_changed",
15643                     G_CALLBACK (value_changed), (gpointer) label);
15644   
15645   gtk_widget_show (window);
15646   
15647   gtk_main ();
15648   
15649   return 0;
15650 }
15651 <!-- example-end -->
15652 </programlisting>
15653
15654 </sect2>
15655 </sect1>
15656
15657 <!-- ----------------------------------------------------------------- -->
15658 <sect1 id="sec-Scribble">
15659 <title>Scribble</title>
15660
15661 <!-- ----------------------------------------------------------------- -->
15662 <sect2>
15663 <title>scribble-simple.c</title>
15664
15665 <programlisting role="C">
15666 <!-- example-start scribble-simple scribble-simple.c -->
15667
15668 /* GTK - The GIMP Toolkit
15669  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15670  *
15671  * This library is free software; you can redistribute it and/or
15672  * modify it under the terms of the GNU Library General Public
15673  * License as published by the Free Software Foundation; either
15674  * version 2 of the License, or (at your option) any later version.
15675  *
15676  * This library is distributed in the hope that it will be useful,
15677  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15678  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15679  * Library General Public License for more details.
15680  *
15681  * You should have received a copy of the GNU Library General Public
15682  * License along with this library; if not, write to the
15683  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15684  * Boston, MA 02111-1307, USA.
15685  */
15686
15687 #include &lt;stdlib.h&gt;
15688 #include &lt;gtk/gtk.h&gt;
15689
15690 /* Backing pixmap for drawing area */
15691 static GdkPixmap *pixmap = NULL;
15692
15693 /* Create a new backing pixmap of the appropriate size */
15694 static gboolean configure_event( GtkWidget         *widget,
15695                                  GdkEventConfigure *event )
15696 {
15697   if (pixmap)
15698     g_object_unref (pixmap);
15699
15700   pixmap = gdk_pixmap_new (widget-&gt;window,
15701                            widget-&gt;allocation.width,
15702                            widget-&gt;allocation.height,
15703                            -1);
15704   gdk_draw_rectangle (pixmap,
15705                       widget-&gt;style-&gt;white_gc,
15706                       TRUE,
15707                       0, 0,
15708                       widget-&gt;allocation.width,
15709                       widget-&gt;allocation.height);
15710
15711   return TRUE;
15712 }
15713
15714 /* Redraw the screen from the backing pixmap */
15715 static gboolean expose_event( GtkWidget      *widget,
15716                               GdkEventExpose *event )
15717 {
15718   gdk_draw_drawable (widget-&gt;window,
15719                      widget-&gt;style-&gt;fg_gc[GTK_WIDGET_STATE (widget)],
15720                      pixmap,
15721                      event-&gt;area.x, event-&gt;area.y,
15722                      event-&gt;area.x, event-&gt;area.y,
15723                      event-&gt;area.width, event-&gt;area.height);
15724
15725   return FALSE;
15726 }
15727
15728 /* Draw a rectangle on the screen */
15729 static void draw_brush( GtkWidget *widget,
15730                         gdouble    x,
15731                         gdouble    y)
15732 {
15733   GdkRectangle update_rect;
15734
15735   update_rect.x = x - 5;
15736   update_rect.y = y - 5;
15737   update_rect.width = 10;
15738   update_rect.height = 10;
15739   gdk_draw_rectangle (pixmap,
15740                       widget-&gt;style-&gt;black_gc,
15741                       TRUE,
15742                       update_rect.x, update_rect.y,
15743                       update_rect.width, update_rect.height);
15744   gtk_widget_queue_draw_area (widget, 
15745                       update_rect.x, update_rect.y,
15746                       update_rect.width, update_rect.height);
15747 }
15748
15749 static gboolean button_press_event( GtkWidget      *widget,
15750                                     GdkEventButton *event )
15751 {
15752   if (event-&gt;button == 1 &amp;&amp; pixmap != NULL)
15753     draw_brush (widget, event-&gt;x, event-&gt;y);
15754
15755   return TRUE;
15756 }
15757
15758 static gboolean motion_notify_event( GtkWidget *widget,
15759                                      GdkEventMotion *event )
15760 {
15761   int x, y;
15762   GdkModifierType state;
15763
15764   if (event-&gt;is_hint)
15765     gdk_window_get_pointer (event-&gt;window, &amp;x, &amp;y, &amp;state);
15766   else
15767     {
15768       x = event-&gt;x;
15769       y = event-&gt;y;
15770       state = event-&gt;state;
15771     }
15772     
15773   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
15774     draw_brush (widget, x, y);
15775   
15776   return TRUE;
15777 }
15778
15779 void quit ()
15780 {
15781   exit (0);
15782 }
15783
15784 int main( int   argc, 
15785           char *argv[] )
15786 {
15787   GtkWidget *window;
15788   GtkWidget *drawing_area;
15789   GtkWidget *vbox;
15790
15791   GtkWidget *button;
15792
15793   gtk_init (&amp;argc, &amp;argv);
15794
15795   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15796   gtk_widget_set_name (window, "Test Input");
15797
15798   vbox = gtk_vbox_new (FALSE, 0);
15799   gtk_container_add (GTK_CONTAINER (window), vbox);
15800   gtk_widget_show (vbox);
15801
15802   g_signal_connect (G_OBJECT (window), "destroy",
15803                     G_CALLBACK (quit), NULL);
15804
15805   /* Create the drawing area */
15806
15807   drawing_area = gtk_drawing_area_new ();
15808   gtk_widget_set_size_request (GTK_WIDGET (drawing_area), 200, 200);
15809   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
15810
15811   gtk_widget_show (drawing_area);
15812
15813   /* Signals used to handle backing pixmap */
15814
15815   g_signal_connect (G_OBJECT (drawing_area), "expose_event",
15816                     G_CALLBACK (expose_event), NULL);
15817   g_signal_connect (G_OBJECT (drawing_area),"configure_event",
15818                     G_CALLBACK (configure_event), NULL);
15819
15820   /* Event signals */
15821
15822   g_signal_connect (G_OBJECT (drawing_area), "motion_notify_event",
15823                     G_CALLBACK (motion_notify_event), NULL);
15824   g_signal_connect (G_OBJECT (drawing_area), "button_press_event",
15825                     G_CALLBACK (button_press_event), NULL);
15826
15827   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
15828                          | GDK_LEAVE_NOTIFY_MASK
15829                          | GDK_BUTTON_PRESS_MASK
15830                          | GDK_POINTER_MOTION_MASK
15831                          | GDK_POINTER_MOTION_HINT_MASK);
15832
15833   /* .. And a quit button */
15834   button = gtk_button_new_with_label ("Quit");
15835   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
15836
15837   g_signal_connect_swapped (G_OBJECT (button), "clicked",
15838                             G_CALLBACK (gtk_widget_destroy),
15839                             G_OBJECT (window));
15840   gtk_widget_show (button);
15841
15842   gtk_widget_show (window);
15843
15844   gtk_main ();
15845
15846   return 0;
15847 }
15848 <!-- example-end -->
15849 </programlisting>
15850
15851 </sect2>
15852
15853 <!-- ----------------------------------------------------------------- -->
15854 <sect2>
15855 <title>scribble-xinput.c</title>
15856
15857 <programlisting role="C">
15858 <!-- example-start scribble-xinput scribble-xinput.c -->
15859
15860 /* GTK - The GIMP Toolkit
15861  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15862  *
15863  * This library is free software; you can redistribute it and/or
15864  * modify it under the terms of the GNU Library General Public
15865  * License as published by the Free Software Foundation; either
15866  * version 2 of the License, or (at your option) any later version.
15867  *
15868  * This library is distributed in the hope that it will be useful,
15869  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15870  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15871  * Library General Public License for more details.
15872  *
15873  * You should have received a copy of the GNU Library General Public
15874  * License along with this library; if not, write to the
15875  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15876  * Boston, MA 02111-1307, USA.
15877  */
15878
15879 #include &lt;gtk/gtk.h&gt;
15880
15881 /* Backing pixmap for drawing area */
15882 static GdkPixmap *pixmap = NULL;
15883
15884 /* Create a new backing pixmap of the appropriate size */
15885 static gboolean
15886 configure_event (GtkWidget *widget, GdkEventConfigure *event)
15887 {
15888   if (pixmap)
15889      g_object_unref (pixmap);
15890
15891   pixmap = gdk_pixmap_new (widget-&gt;window,
15892                            widget-&gt;allocation.width,
15893                            widget-&gt;allocation.height,
15894                            -1);
15895   gdk_draw_rectangle (pixmap,
15896                       widget-&gt;style-&gt;white_gc,
15897                       TRUE,
15898                       0, 0,
15899                       widget-&gt;allocation.width,
15900                       widget-&gt;allocation.height);
15901
15902   return TRUE;
15903 }
15904
15905 /* Redraw the screen from the backing pixmap */
15906 static gboolean
15907 expose_event (GtkWidget *widget, GdkEventExpose *event)
15908 {
15909   gdk_draw_drawable (widget-&gt;window,
15910                      widget-&gt;style-&gt;fg_gc[GTK_WIDGET_STATE (widget)],
15911                      pixmap,
15912                      event-&gt;area.x, event-&gt;area.y,
15913                      event-&gt;area.x, event-&gt;area.y,
15914                      event-&gt;area.width, event-&gt;area.height);
15915
15916   return FALSE;
15917 }
15918
15919 /* Draw a rectangle on the screen, size depending on pressure,
15920    and color on the type of device */
15921 static void
15922 draw_brush (GtkWidget *widget, GdkInputSource source,
15923             gdouble x, gdouble y, gdouble pressure)
15924 {
15925   GdkGC *gc;
15926   GdkRectangle update_rect;
15927
15928   switch (source)
15929     {
15930     case GDK_SOURCE_MOUSE:
15931       gc = widget-&gt;style-&gt;dark_gc[GTK_WIDGET_STATE (widget)];
15932       break;
15933     case GDK_SOURCE_PEN:
15934       gc = widget-&gt;style-&gt;black_gc;
15935       break;
15936     case GDK_SOURCE_ERASER:
15937       gc = widget-&gt;style-&gt;white_gc;
15938       break;
15939     default:
15940       gc = widget-&gt;style-&gt;light_gc[GTK_WIDGET_STATE (widget)];
15941     }
15942
15943   update_rect.x = x - 10 * pressure;
15944   update_rect.y = y - 10 * pressure;
15945   update_rect.width = 20 * pressure;
15946   update_rect.height = 20 * pressure;
15947   gdk_draw_rectangle (pixmap, gc, TRUE,
15948                       update_rect.x, update_rect.y,
15949                       update_rect.width, update_rect.height);
15950   gtk_widget_queue_draw_area (widget, 
15951                       update_rect.x, update_rect.y,
15952                       update_rect.width, update_rect.height);
15953 }
15954
15955 static void
15956 print_button_press (GdkDevice *device)
15957 {
15958   g_print ("Button press on device '%s'\n", device-&gt;name);
15959 }
15960
15961 static gboolean
15962 button_press_event (GtkWidget *widget, GdkEventButton *event)
15963 {
15964   print_button_press (event-&gt;device);
15965   
15966   if (event-&gt;button == 1 &amp;&amp; pixmap != NULL) {
15967     gdouble pressure;
15968     gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_PRESSURE, &amp;pressure);
15969     draw_brush (widget, event-&gt;device-&gt;source, event-&gt;x, event-&gt;y, pressure);
15970   }
15971
15972   return TRUE;
15973 }
15974
15975 static gboolean
15976 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
15977 {
15978   gdouble x, y;
15979   gdouble pressure;
15980   GdkModifierType state;
15981
15982   if (event-&gt;is_hint) 
15983     {
15984       gdk_device_get_state (event-&gt;device, event-&gt;window, NULL, &amp;state);
15985       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_X, &amp;x);
15986       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_Y, &amp;y);
15987       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_PRESSURE, &amp;pressure);
15988     }
15989   else
15990     {
15991       x = event-&gt;x;
15992       y = event-&gt;y;
15993       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_PRESSURE, &amp;pressure);
15994       state = event-&gt;state;
15995     }
15996     
15997   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
15998     draw_brush (widget, event-&gt;device-&gt;source, x, y, pressure);
15999   
16000   return TRUE;
16001 }
16002
16003 void
16004 input_dialog_destroy (GtkWidget *w, gpointer data)
16005 {
16006   *((GtkWidget **)data) = NULL;
16007 }
16008
16009 void
16010 create_input_dialog ()
16011 {
16012   static GtkWidget *inputd = NULL;
16013
16014   if (!inputd)
16015     {
16016       inputd = gtk_input_dialog_new();
16017
16018       g_signal_connect (G_OBJECT (inputd), "destroy",
16019                         G_CALLBACK (input_dialog_destroy), (gpointer) &amp;inputd);
16020       g_signal_connect_swapped (G_OBJECT (GTK_INPUT_DIALOG (inputd)-&gt;close_button),
16021                                 "clicked",
16022                                 G_CALLBACK (gtk_widget_hide),
16023                                 G_OBJECT (inputd));
16024       gtk_widget_hide (GTK_INPUT_DIALOG (inputd)-&gt;save_button);
16025
16026       gtk_widget_show (inputd);
16027     }
16028   else
16029     {
16030       if (!GTK_WIDGET_MAPPED (inputd))
16031         gtk_widget_show (inputd);
16032       else
16033         gdk_window_raise (inputd-&gt;window);
16034     }
16035 }
16036
16037 void
16038 quit ()
16039 {
16040   exit (0);
16041 }
16042
16043 int
16044 main (int argc, char *argv[])
16045 {
16046   GtkWidget *window;
16047   GtkWidget *drawing_area;
16048   GtkWidget *vbox;
16049
16050   GtkWidget *button;
16051
16052   gtk_init (&amp;argc, &amp;argv);
16053
16054   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
16055   gtk_widget_set_name (window, "Test Input");
16056
16057   vbox = gtk_vbox_new (FALSE, 0);
16058   gtk_container_add (GTK_CONTAINER (window), vbox);
16059   gtk_widget_show (vbox);
16060
16061   g_signal_connect (G_OBJECT (window), "destroy",
16062                     G_CALLBACK (quit), NULL);
16063
16064   /* Create the drawing area */
16065
16066   drawing_area = gtk_drawing_area_new ();
16067   gtk_widget_set_size_request (GTK_WIDGET (drawing_area), 200, 200);
16068   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
16069
16070   gtk_widget_show (drawing_area);
16071
16072   /* Signals used to handle backing pixmap */
16073
16074   g_signal_connect (G_OBJECT (drawing_area), "expose_event",
16075                     G_CALLBACK (expose_event), NULL);
16076   g_signal_connect (G_OBJECT(drawing_area),"configure_event",
16077                     G_CALLBACK (configure_event), NULL);
16078
16079   /* Event signals */
16080
16081   g_signal_connect (G_OBJECT (drawing_area), "motion_notify_event",
16082                     G_CALLBACK (motion_notify_event), NULL);
16083   g_signal_connect (G_OBJECT (drawing_area), "button_press_event",
16084                     G_CALLBACK (button_press_event), NULL);
16085
16086   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
16087                          | GDK_LEAVE_NOTIFY_MASK
16088                          | GDK_BUTTON_PRESS_MASK
16089                          | GDK_POINTER_MOTION_MASK
16090                          | GDK_POINTER_MOTION_HINT_MASK);
16091
16092   /* The following call enables tracking and processing of extension
16093      events for the drawing area */
16094   gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
16095
16096   /* .. And some buttons */
16097   button = gtk_button_new_with_label ("Input Dialog");
16098   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
16099
16100   g_signal_connect (G_OBJECT (button), "clicked",
16101                     G_CALLBACK (create_input_dialog), NULL);
16102   gtk_widget_show (button);
16103
16104   button = gtk_button_new_with_label ("Quit");
16105   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
16106
16107   g_signal_connect_swapped (G_OBJECT (button), "clicked",
16108                             G_CALLBACK (gtk_widget_destroy),
16109                             G_OBJECT (window));
16110   gtk_widget_show (button);
16111
16112   gtk_widget_show (window);
16113
16114   gtk_main ();
16115
16116   return 0;
16117 }
16118 <!-- example-end -->
16119 </programlisting>
16120
16121 </sect2>
16122 </sect1>
16123
16124 </appendix>
16125 </book>