]> Pileus Git - ~andy/gtk/blob - docs/tutorial/gtk-tut.sgml
f45f6972f00faa2a0ef058468b229aabf3495d01
[~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/documentation.html#Tutorials">http://www.gtk.org/documentation.html#Tutorials</ulink>. You can also find other GTK+ tutorials there.</para>
41
42 <para>A packaged version 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 package is primary for those people wanting
46 to have the tutorial available for offline reference and for printing. Note
47 that the packaged version may be older than the online version.</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.</para>
68
69 <para>GTK is essentially an object oriented application programmers
70 interface (API). Although written completely in C, it is implemented
71 using the idea of classes and callback functions (pointers to
72 functions).</para>
73
74 <para>There is also a third component called GLib which contains a few
75 replacements for some standard calls, as well as some additional
76 functions for handling linked lists, etc. The replacement functions
77 are used to increase GTK's portability, as some of the functions
78 implemented here are not available or are nonstandard on other Unixes
79 such as g_strerror(). Some also contain enhancements to the libc
80 versions, such as g_malloc() that has enhanced debugging utilities.</para>
81
82 <para>In version 2.0, GLib has picked up the type system which forms the
83 foundation for GTK's class hierarchy, the signal system which is used
84 throughout GTK, a thread API which abstracts the different native thread APIs 
85 of the various platforms and a facility for loading modules.
86 </para>
87
88 <para>As the last component, GTK uses the Pango library for internationalized
89 text output.
90 </para>
91
92 <para>This tutorial describes the C interface to GTK. There are GTK
93 bindings for many other languages including C++, Guile, Perl, Python,
94 TOM, Ada95, Objective C, Free Pascal, Eiffel, Java and C#. If you intend to
95 use another language's bindings to GTK, look at that binding's
96 documentation first. In some cases that documentation may describe
97 some important conventions (which you should know first) and then
98 refer you back to this tutorial. There are also some cross-platform
99 APIs (such as wxWindows and V) which use GTK as one of their target
100 platforms; again, consult their documentation first.</para>
101
102 <para>If you're developing your GTK application in C++, a few extra notes
103 are in order. There's a C++ binding to GTK called GTK--, which
104 provides a more C++-like interface to GTK; you should probably look
105 into this instead. If you don't like that approach for whatever
106 reason, there are two alternatives for using GTK. First, you can use
107 only the C subset of C++ when interfacing with GTK and then use the C
108 interface as described in this tutorial. Second, you can use GTK and
109 C++ together by declaring all callbacks as static functions in C++
110 classes, and again calling GTK using its C interface. If you choose
111 this last approach, you can include as the callback's data value a
112 pointer to the object to be manipulated (the so-called "this" value).
113 Selecting between these options is simply a matter of preference,
114 since in all three approaches you get C++ and GTK. None of these
115 approaches requires the use of a specialized preprocessor, so no
116 matter what you choose you can use standard C++ with GTK.</para>
117
118 <para>This tutorial is an attempt to document as much as possible of GTK,
119 but it is by no means complete. This tutorial assumes a good
120 understanding of C, and how to create C programs. It would be a great
121 benefit for the reader to have previous X programming experience, but
122 it shouldn't be necessary. If you are learning GTK as your first
123 widget set, please comment on how you found this tutorial, and what
124 you had trouble with. There are also C++, Objective C, ADA, Guile and
125 other language bindings available, but I don't follow these.</para>
126
127 <para>This document is a "work in progress". Please look for updates on
128 <ulink url="http://www.gtk.org/">http://www.gtk.org/</ulink>.</para>
129
130 <para>I would very much like to hear of any problems you have learning GTK
131 from this document, and would appreciate input as to how it may be
132 improved. Please see the section on <link linkend="ch-Contributing">Contributing
133 </link> for further information.</para>
134
135 </chapter>
136
137 <!-- ***************************************************************** -->
138 <chapter id="ch-GettingStarted">
139 <title>Getting Started</title>
140
141 <para>The first thing to do, of course, is download the GTK source and
142 install it. You can always get the latest version from <ulink 
143 url="ftp://ftp.gtk.org/pub/gtk">ftp.gtk.org</ulink>. You can also view 
144 other sources of GTK information on
145 <ulink url="http://www.gtk.org/">http://www.gtk.org/</ulink>. GTK
146 uses GNU autoconf for configuration. Once untar'd, type 
147 <literal>./configure --help</literal> to see a list of options.</para>
148
149 <para>The GTK source distribution also contains the complete source to all
150 of the examples used in this tutorial, along with Makefiles to aid
151 compilation.</para>
152
153 <para>To begin our introduction to GTK, we'll start with the simplest
154 program possible. This program will create a 200x200 pixel window and
155 has no way of exiting except to be killed by using the shell.</para>
156
157 <para>
158 <inlinemediaobject>
159 <imageobject>
160 <imagedata fileref="images/base.png" format="png">
161 </imageobject>
162 </inlinemediaobject>
163 </para>
164
165 <programlisting role="C">
166 <!-- example-start base base.c -->
167
168 #include &lt;gtk/gtk.h&gt;
169
170 int main( int   argc,
171           char *argv[] )
172 {
173     GtkWidget *window;
174     
175     gtk_init (&amp;argc, &amp;argv);
176     
177     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
178     gtk_widget_show  (window);
179     
180     gtk_main ();
181     
182     return 0;
183 }
184 <!-- example-end -->
185 </programlisting>
186
187 <para>You can compile the above program with gcc using:</para>
188 <para><literallayout>
189 <literal>gcc base.c -o base `pkg-config --cflags --libs gtk+-2.0`</literal>
190 </literallayout></para>
191
192 <para>The meaning of the unusual compilation options is explained below in
193 <link linkend="sec-Compiling">Compiling Hello World</link>.</para>
194
195 <para>All programs will of course include <filename>gtk/gtk.h</filename> which 
196 declares the variables, functions, structures, etc. that will be used in your GTK
197 application.</para>
198
199 <para>The next line:</para>
200
201 <programlisting role="C">
202 gtk_init (&amp;argc, &amp;argv);
203 </programlisting>
204
205 <para>calls the function gtk_init(gint *argc, gchar ***argv) which will be called 
206 in all GTK applications. This sets up a few things for us such as the default visual 
207 and color map and then proceeds to call gdk_init(gint *argc, gchar ***argv). 
208 This function initializes the library for use, sets up default signal handlers, and 
209 checks the arguments passed to your application on the command line, looking for
210 one of the following:</para>
211
212 <itemizedlist spacing=Compact>
213 <listitem><simpara> <literal>--gtk-module</literal></simpara>
214 </listitem>
215 <listitem><simpara> <literal>--g-fatal-warnings</literal></simpara>
216 </listitem>
217 <listitem><simpara> <literal>--gtk-debug</literal></simpara>
218 </listitem>
219 <listitem><simpara> <literal>--gtk-no-debug</literal></simpara>
220 </listitem>
221 <listitem><simpara> <literal>--gdk-debug</literal></simpara>
222 </listitem>
223 <listitem><simpara> <literal>--gdk-no-debug</literal></simpara>
224 </listitem>
225 <listitem><simpara> <literal>--display</literal></simpara>
226 </listitem>
227 <listitem><simpara> <literal>--sync</literal></simpara>
228 </listitem>
229 <listitem><simpara> <literal>--name</literal></simpara>
230 </listitem>
231 <listitem><simpara> <literal>--class</literal></simpara>
232 </listitem>
233 </itemizedlist>
234
235 <para>It removes these from the argument list, leaving anything it does not
236 recognize for your application to parse or ignore. This creates a set
237 of standard arguments accepted by all GTK applications.</para>
238
239 <para>The next two lines of code create and display a window.</para>
240
241 <programlisting role="C">
242   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
243   gtk_widget_show (window);
244 </programlisting>
245
246 <para>The <literal>GTK_WINDOW_TOPLEVEL</literal> argument specifies that we want the
247 window to undergo window manager decoration and placement. Rather than
248 create a window of 0x0 size, a window without children is set to
249 200x200 by default so you can still manipulate it.</para>
250
251 <para>The gtk_widget_show() function lets GTK know that we are done setting
252 the attributes of this widget, and that it can display it.</para>
253
254 <para>The last line enters the GTK main processing loop.</para>
255
256 <programlisting role="C">
257   gtk_main ();
258 </programlisting>
259
260 <para>gtk_main() is another call you will see in every GTK application.
261 When control reaches this point, GTK will sleep waiting for X events
262 (such as button or key presses), timeouts, or file IO notifications to
263 occur. In our simple example, however, events are ignored.</para>
264
265 <!-- ----------------------------------------------------------------- -->
266 <sect1 id="sec-HelloWorld">
267 <title>Hello World in GTK</title>
268
269 <para>Now for a program with a widget (a button). It's the classic
270 hello world a la GTK.</para>
271
272 <para>
273 <inlinemediaobject>
274 <imageobject>
275 <imagedata fileref="images/helloworld.png" format="png">
276 </imageobject>
277 </inlinemediaobject>
278 </para>
279
280 <programlisting role="C">
281 <!-- example-start helloworld helloworld.c -->
282
283 #include &lt;gtk/gtk.h&gt;
284
285 /* This is a callback function. The data arguments are ignored
286  * in this example. More on callbacks below. */
287 static void hello( GtkWidget *widget,
288                    gpointer   data )
289 {
290     g_print ("Hello World\n");
291 }
292
293 static gboolean delete_event( GtkWidget *widget,
294                               GdkEvent  *event,
295                               gpointer   data )
296 {
297     /* If you return FALSE in the "delete_event" signal handler,
298      * GTK will emit the "destroy" signal. Returning TRUE means
299      * you don't want the window to be destroyed.
300      * This is useful for popping up 'are you sure you want to quit?'
301      * type dialogs. */
302
303     g_print ("delete event occurred\n");
304
305     /* Change TRUE to FALSE and the main window will be destroyed with
306      * a "delete_event". */
307
308     return TRUE;
309 }
310
311 /* Another callback */
312 static void destroy( GtkWidget *widget,
313                      gpointer   data )
314 {
315     gtk_main_quit ();
316 }
317
318 int main( int   argc,
319           char *argv[] )
320 {
321     /* GtkWidget is the storage type for widgets */
322     GtkWidget *window;
323     GtkWidget *button;
324     
325     /* This is called in all GTK applications. Arguments are parsed
326      * from the command line and are returned to the application. */
327     gtk_init (&amp;argc, &amp;argv);
328     
329     /* create a new window */
330     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
331     
332     /* When the window is given the "delete_event" signal (this is given
333      * by the window manager, usually by the "close" option, or on the
334      * titlebar), we ask it to call the delete_event () function
335      * as defined above. The data passed to the callback
336      * function is NULL and is ignored in the callback function. */
337     g_signal_connect (G_OBJECT (window), "delete_event",
338                       G_CALLBACK (delete_event), NULL);
339     
340     /* Here we connect the "destroy" event to a signal handler.  
341      * This event occurs when we call gtk_widget_destroy() on the window,
342      * or if we return FALSE in the "delete_event" callback. */
343     g_signal_connect (G_OBJECT (window), "destroy",
344                       G_CALLBACK (destroy), NULL);
345     
346     /* Sets the border width of the window. */
347     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
348     
349     /* Creates a new button with the label "Hello World". */
350     button = gtk_button_new_with_label ("Hello World");
351     
352     /* When the button receives the "clicked" signal, it will call the
353      * function hello() passing it NULL as its argument.  The hello()
354      * function is defined above. */
355     g_signal_connect (G_OBJECT (button), "clicked",
356                       G_CALLBACK (hello), NULL);
357     
358     /* This will cause the window to be destroyed by calling
359      * gtk_widget_destroy(window) when "clicked".  Again, the destroy
360      * signal could come from here, or the window manager. */
361     g_signal_connect_swapped (G_OBJECT (button), "clicked",
362                               G_CALLBACK (gtk_widget_destroy),
363                               G_OBJECT (window));
364     
365     /* This packs the button into the window (a gtk container). */
366     gtk_container_add (GTK_CONTAINER (window), button);
367     
368     /* The final step is to display this newly created widget. */
369     gtk_widget_show (button);
370     
371     /* and the window */
372     gtk_widget_show (window);
373     
374     /* All GTK applications must have a gtk_main(). Control ends here
375      * and waits for an event to occur (like a key press or
376      * mouse event). */
377     gtk_main ();
378     
379     return 0;
380 }
381 <!-- example-end -->
382 </programlisting>
383
384 </sect1>
385
386 <!-- ----------------------------------------------------------------- -->
387 <sect1 id="sec-Compiling">
388 <title>Compiling Hello World</title>
389
390 <para>To compile use:</para>
391
392 <para><literallayout>
393 <literal>gcc -Wall -g helloworld.c -o helloworld `pkg-config --cflags gtk+-2.0` \</literal>
394 <literal>    `pkg-config --libs gtk+-2.0`</literal>
395 </literallayout></para>
396
397 <para>This uses the program <literal>pkg-config</literal>, which can be obtained from
398 <ulink url="http://www.freedesktop.org">www.freedesktop.org</ulink>. This program 
399 reads the <filename>.pc</filename> which comes with GTK to determine what 
400 compiler switches are needed to compile programs that use GTK. 
401 <literal>pkg-config --cflags gtk+-2.0</literal> will output a list of include
402 directories for the compiler to look in, and 
403 <literal>pkg-config --libs gtk+-2.0</literal>
404 will output the list of libraries for the compiler to link with and
405 the directories to find them in. In the above example they could have
406 been combined into a single instance, such as
407 <literal>pkg-config --cflags --libs gtk+-2.0</literal>.</para>
408
409 <para>Note that the type of single quote used in the compile command above
410 is significant.</para>
411
412 <para>The libraries that are usually linked in are:</para>
413
414 <itemizedlist>
415 <listitem><simpara>The GTK library (<literal>-lgtk</literal>), the widget library, 
416 based on top of GDK.</simpara>
417 </listitem>
418
419 <listitem><simpara>The GDK library (<literal>-lgdk</literal>), the Xlib wrapper.</simpara>
420 </listitem>
421
422 <listitem><simpara>The gdk-pixbuf library (<literal>-lgdk_pixbuf</literal>), the image 
423 manipulation library.</simpara>
424 </listitem>
425
426 <listitem><simpara>The Pango library (<literal>-lpango</literal>) for internationalized 
427 text.</simpara>
428 </listitem>
429
430 <listitem><simpara>The gobject library (<literal>-lgobject</literal>), containing the
431 type system on which GTK is based.</simpara>
432 </listitem>
433
434 <listitem><simpara>The gmodule library (<literal>-lgmodule</literal>), which is used 
435 to load run time extensions.</simpara>
436 </listitem>
437
438 <listitem><simpara>The GLib library (<literal>-lglib</literal>), containing miscellaneous
439 functions; only g_print() is used in this particular example. GTK is built on top
440 of GLib so you will always require this library. See the section on
441 <link linkend="ch-glib">GLib</link> for details.</simpara>
442 </listitem>
443
444 <listitem><simpara>The Xlib library (<literal>-lX11</literal>) which is used by GDK.</simpara>
445 </listitem>
446
447 <listitem><simpara>The Xext library (<literal>-lXext</literal>). This contains code 
448 for shared memory pixmaps and other X extensions.</simpara>
449 </listitem>
450
451 <listitem><simpara>The math library (<literal>-lm</literal>). This is used by GTK 
452 for various purposes.</simpara>
453 </listitem>
454 </itemizedlist>
455
456 </sect1>
457
458 <!-- ----------------------------------------------------------------- -->
459 <sect1 id="sec-TheoryOfSignalsAndCallbacks">
460 <title>Theory of Signals and Callbacks</title>
461
462 <note>
463 <para>In version 2.0, the signal system has been moved from GTK to GLib, therefore the
464 functions and types explained in this section have a "g_" prefix rather than a "gtk_" 
465 prefix. We won't go into details about the extensions which the GLib 2.0 signal system
466 has relative to the GTK 1.2 signal system.</para>
467 </note>
468
469 <para>Before we look in detail at <emphasis>helloworld</emphasis>, we'll discuss signals
470 and callbacks. GTK is an event driven toolkit, which means it will
471 sleep in gtk_main() until an event occurs and control is passed to the
472 appropriate function.</para>
473
474 <para>This passing of control is done using the idea of "signals". (Note
475 that these signals are not the same as the Unix system signals, and
476 are not implemented using them, although the terminology is almost
477 identical.) When an event occurs, such as the press of a mouse button,
478 the appropriate signal will be "emitted" by the widget that was
479 pressed.  This is how GTK does most of its useful work. There are
480 signals that all widgets inherit, such as "destroy", and there are
481 signals that are widget specific, such as "toggled" on a toggle
482 button.</para>
483
484 <para>To make a button perform an action, we set up a signal handler to
485 catch these signals and call the appropriate function. This is done by
486 using a function such as:</para>
487
488 <programlisting role="C">
489 gulong g_signal_connect( gpointer      *object,
490                          const gchar   *name,
491                          GCallback     func,
492                          gpointer      func_data );
493 </programlisting>
494
495 <para>where the first argument is the widget which will be emitting the
496 signal, and the second the name of the signal you wish to catch. The
497 third is the function you wish to be called when it is caught, and the
498 fourth, the data you wish to have passed to this function.</para>
499
500 <para>The function specified in the third argument is called a "callback
501 function", and should generally be of the form</para>
502
503 <programlisting role="C">
504 void callback_func( GtkWidget *widget,
505                     ... /* other signal arguments */
506                     gpointer   callback_data );
507 </programlisting>
508
509 <para>where the first argument will be a pointer to the widget that emitted
510 the signal, and the last a pointer to the data given as the last
511 argument to the g_signal_connect() function as shown above.</para>
512
513 <para>Note that the above form for a signal callback function declaration is
514 only a general guide, as some widget specific signals generate
515 different calling parameters.</para>
516
517 <para>Another call used in the <emphasis>helloworld</emphasis> example, is:</para>
518
519 <programlisting role="C">
520 gulong g_signal_connect_swapped( gpointer     *object,
521                                  const gchar  *name,
522                                  GCallback    func,
523                                  gpointer     *callback_data );
524 </programlisting>
525
526 <para>g_signal_connect_swapped() is the same as g_signal_connect() except
527 that the instance on which the signal is emitted and data will be swapped when
528 calling the handler. So when using this function to connect signals, the callback
529 should be of the form</para>
530
531 <programlisting role="C">
532 void callback_func( gpointer   callback_data,
533                     ... /* other signal arguments */
534                     GtkWidget *widget);
535 </programlisting>
536
537 <para>where the object is usually a widget. We usually don't setup callbacks
538 for g_signal_connect_swapped() however. They are usually used to call a
539 GTK function that accepts a single widget or object as an argument, when a signal
540 is emitted on some <emphasis>other</emphasis> object. In the 
541 <emphasis>helloworld</emphasis> example, we connect to the "clicked" signal
542 on the button, but call gtk_widget_destroy() on the window.</para>
543
544 <para>If your callbacks need additional data, use g_signal_connect() instead
545 of g_signal_connect_swapped().</para>
546
547 </sect1>
548
549 <!-- ----------------------------------------------------------------- -->
550 <sect1 id="sec-Events">
551 <title>Events</title>
552
553 <para>In addition to the signal mechanism described above, there is a set
554 of <emphasis>events</emphasis> that reflect the X event mechanism. Callbacks may
555 also be attached to these events. These events are:</para>
556
557 <itemizedlist spacing=Compact>
558 <listitem><simpara> event</simpara>
559 </listitem>
560 <listitem><simpara> button_press_event</simpara>
561 </listitem>
562 <listitem><simpara> button_release_event</simpara>
563 </listitem>
564 <listitem><simpara> scroll_event</simpara>
565 </listitem>
566 <listitem><simpara> motion_notify_event</simpara>
567 </listitem>
568 <listitem><simpara> delete_event</simpara>
569 </listitem>
570 <listitem><simpara> destroy_event</simpara>
571 </listitem>
572 <listitem><simpara> expose_event</simpara>
573 </listitem>
574 <listitem><simpara> key_press_event</simpara>
575 </listitem>
576 <listitem><simpara> key_release_event</simpara>
577 </listitem>
578 <listitem><simpara> enter_notify_event</simpara>
579 </listitem>
580 <listitem><simpara> leave_notify_event</simpara>
581 </listitem>
582 <listitem><simpara> configure_event</simpara>
583 </listitem>
584 <listitem><simpara> focus_in_event</simpara>
585 </listitem>
586 <listitem><simpara> focus_out_event</simpara>
587 </listitem>
588 <listitem><simpara> map_event</simpara>
589 </listitem>
590 <listitem><simpara> unmap_event</simpara>
591 </listitem>
592 <listitem><simpara> property_notify_event</simpara>
593 </listitem>
594 <listitem><simpara> selection_clear_event</simpara>
595 </listitem>
596 <listitem><simpara> selection_request_event</simpara>
597 </listitem>
598 <listitem><simpara> selection_notify_event</simpara>
599 </listitem>
600 <listitem><simpara> proximity_in_event</simpara>
601 </listitem>
602 <listitem><simpara> proximity_out_event</simpara>
603 </listitem>
604 <listitem><simpara> visibility_notify_event</simpara>
605 </listitem>
606 <listitem><simpara> client_event</simpara>
607 </listitem>
608 <listitem><simpara> no_expose_event</simpara>
609 </listitem>
610 <listitem><simpara> window_state_event</simpara>
611 </listitem>
612 </itemizedlist>
613
614 <para>In order to connect a callback function to one of these events you
615 use the function g_signal_connect(), as described above, using one of
616 the above event names as the <literal>name</literal> parameter. The callback
617 function for events has a slightly different form than that for
618 signals:</para>
619
620 <programlisting role="C">
621 gint callback_func( GtkWidget *widget,
622                     GdkEvent  *event,
623                     gpointer   callback_data );
624 </programlisting>
625
626 <para>GdkEvent is a C <literal>union</literal> structure whose type will depend upon 
627 which of the above events has occurred. In order for us to tell which event
628 has been issued each of the possible alternatives has a <literal>type</literal>
629 member that reflects the event being issued. The other components
630 of the event structure will depend upon the type of the
631 event. Possible values for the type are:</para>
632
633 <programlisting role="C">
634   GDK_NOTHING
635   GDK_DELETE
636   GDK_DESTROY
637   GDK_EXPOSE
638   GDK_MOTION_NOTIFY
639   GDK_BUTTON_PRESS
640   GDK_2BUTTON_PRESS
641   GDK_3BUTTON_PRESS
642   GDK_BUTTON_RELEASE
643   GDK_KEY_PRESS
644   GDK_KEY_RELEASE
645   GDK_ENTER_NOTIFY
646   GDK_LEAVE_NOTIFY
647   GDK_FOCUS_CHANGE
648   GDK_CONFIGURE
649   GDK_MAP
650   GDK_UNMAP
651   GDK_PROPERTY_NOTIFY
652   GDK_SELECTION_CLEAR
653   GDK_SELECTION_REQUEST
654   GDK_SELECTION_NOTIFY
655   GDK_PROXIMITY_IN
656   GDK_PROXIMITY_OUT
657   GDK_DRAG_ENTER
658   GDK_DRAG_LEAVE
659   GDK_DRAG_MOTION
660   GDK_DRAG_STATUS
661   GDK_DROP_START
662   GDK_DROP_FINISHED
663   GDK_CLIENT_EVENT
664   GDK_VISIBILITY_NOTIFY
665   GDK_NO_EXPOSE
666   GDK_SCROLL
667   GDK_WINDOW_STATE
668   GDK_SETTING
669 </programlisting>
670
671 <para>So, to connect a callback function to one of these events we would use
672 something like:</para>
673
674 <programlisting role="C">
675 g_signal_connect (G_OBJECT (button), "button_press_event",
676                   G_CALLBACK (button_press_callback), NULL);
677 </programlisting>
678
679 <para>This assumes that <literal>button</literal> is a Button widget. Now, when the
680 mouse is over the button and a mouse button is pressed, the function
681 button_press_callback() will be called. This function may be declared as:</para>
682
683 <programlisting role="C">
684 static gboolean button_press_callback( GtkWidget      *widget, 
685                                        GdkEventButton *event,
686                                        gpointer        data );
687 </programlisting>
688
689 <para>Note that we can declare the second argument as type
690 <literal>GdkEventButton</literal> as we know what type of event will occur for this
691 function to be called.</para>
692
693 <para>The value returned from this function indicates whether the event
694 should be propagated further by the GTK event handling
695 mechanism. Returning TRUE indicates that the event has been handled,
696 and that it should not propagate further. Returning FALSE continues
697 the normal event handling.  See the section on
698 <link linkend="ch-AdvancedEventsAndSignals">Advanced Event and Signal Handling</link> 
699 for more details on this propagation process.</para>
700
701 <para>For details on the GdkEvent data types, see the appendix entitled
702 <link linkend="app-GDKEventTypes">GDK Event Types</link>.</para>
703
704 <para>The GDK selection and drag-and-drop APIs also emit a number of events which
705 are reflected in GTK by the signals. See <link 
706 linkend="sec-SignalsOnSourceWidgets">Signals on the source widget</link> and <link 
707 linkend="sec-SignalsOnDestWidgets">Signals on the destination widget</link>
708 for details on the signatures of the callback functions for these signals:</para>
709
710 <itemizedlist spacing=Compact>
711 <listitem><simpara> selection_received</simpara>
712 </listitem>
713 <listitem><simpara> selection_get</simpara>
714 </listitem>
715 <listitem><simpara> drag_begin_event</simpara>
716 </listitem>
717 <listitem><simpara> drag_end_event</simpara>
718 </listitem>
719 <listitem><simpara> drag_data_delete</simpara>
720 </listitem>
721 <listitem><simpara> drag_motion</simpara>
722 </listitem>
723 <listitem><simpara> drag_drop</simpara>
724 </listitem>
725 <listitem><simpara> drag_data_get</simpara>
726 </listitem>
727 <listitem><simpara> drag_data_received</simpara>
728 </listitem>
729 </itemizedlist>
730
731 </sect1>
732
733 <!-- ----------------------------------------------------------------- -->
734 <sect1 id="sec-SteppingThroughHelloWorld">
735 <title>Stepping Through Hello World</title>
736
737 <para>Now that we know the theory behind this, let's clarify by walking
738 through the example <emphasis>helloworld</emphasis> program.</para>
739
740 <para>Here is the callback function that will be called when the button is
741 "clicked". We ignore both the widget and the data in this example, but
742 it is not hard to do things with them. The next example will use the
743 data argument to tell us which button was pressed.</para>
744
745 <programlisting role="C">
746 static void hello( GtkWidget *widget,
747                    gpointer   data )
748 {
749     g_print ("Hello World\n");
750 }
751 </programlisting>
752
753 <para>The next callback is a bit special. The "delete_event" occurs when the
754 window manager sends this event to the application. We have a choice
755 here as to what to do about these events. We can ignore them, make
756 some sort of response, or simply quit the application.</para>
757
758 <para>The value you return in this callback lets GTK know what action to
759 take.  By returning TRUE, we let it know that we don't want to have
760 the "destroy" signal emitted, keeping our application running. By
761 returning FALSE, we ask that "destroy" be emitted, which in turn will
762 call our "destroy" signal handler.</para>
763
764
765 <programlisting role="C">
766 static gboolean delete_event( GtkWidget *widget,
767                               GdkEvent  *event,
768                               gpointer   data )
769 {
770     g_print ("delete event occurred\n");
771
772     return TRUE; 
773 }
774 </programlisting>
775
776 <para>Here is another callback function which causes the program to quit by
777 calling gtk_main_quit(). This function tells GTK that it is to exit
778 from gtk_main when control is returned to it.</para>
779
780 <programlisting role="C">
781 static void destroy( GtkWidget *widget,
782                      gpointer   data )
783 {
784     gtk_main_quit ();
785 }
786 </programlisting>
787
788 <para>I assume you know about the main() function... yes, as with other
789 applications, all GTK applications will also have one of these.</para>
790
791 <programlisting role="C">
792 int main( int   argc,
793           char *argv[] )
794 {
795 </programlisting>
796
797 <para>This next part declares pointers to a structure of type
798 GtkWidget. These are used below to create a window and a button.</para>
799
800 <programlisting role="C">
801     GtkWidget *window;
802     GtkWidget *button;
803 </programlisting>
804
805 <para>Here is our gtk_init() again. As before, this initializes the toolkit,
806 and parses the arguments found on the command line. Any argument it
807 recognizes from the command line, it removes from the list, and
808 modifies argc and argv to make it look like they never existed,
809 allowing your application to parse the remaining arguments.</para>
810
811 <programlisting role="C">
812     gtk_init (&amp;argc, &amp;argv);
813 </programlisting>
814
815 <para>Create a new window. This is fairly straightforward. Memory is
816 allocated for the GtkWidget *window structure so it now points to a
817 valid structure. It sets up a new window, but it is not displayed
818 until we call gtk_widget_show(window) near the end of our program.</para>
819
820 <programlisting role="C">
821     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
822 </programlisting>
823
824 <para>Here are two examples of connecting a signal handler to an object, in
825 this case, the window. Here, the "delete_event" and "destroy" signals
826 are caught. The first is emitted when we use the window manager to
827 kill the window, or when we use the gtk_widget_destroy() call passing
828 in the window widget as the object to destroy. The second is emitted
829 when, in the "delete_event" handler, we return FALSE.
830  
831 The <literal>G_OBJECT</literal> and <literal>G_CALLBACK</literal> are macros 
832 that perform type casting and checking for us, as well as aid the readability of
833 the code.</para>
834
835 <programlisting role="C">
836     g_signal_connect (G_OBJECT (window), "delete_event",
837                       G_CALLBACK (delete_event), NULL);
838     g_signal_connect (G_OBJECT (window), "destroy",
839                       G_CALLBACK (destroy), NULL);
840 </programlisting>
841
842 <para>This next function is used to set an attribute of a container object.
843 This just sets the window so it has a blank area along the inside of
844 it 10 pixels wide where no widgets will go. There are other similar
845 functions which we will look at in the section on
846 <link linkend="ch-SettingWidgetAttributes">Setting Widget Attributes</link></para>
847
848 <para>And again, <literal>GTK_CONTAINER</literal> is a macro to perform type casting.</para>
849
850 <programlisting role="C">
851     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
852 </programlisting>
853
854 <para>This call creates a new button. It allocates space for a new GtkWidget
855 structure in memory, initializes it, and makes the button pointer
856 point to it. It will have the label "Hello World" on it when
857 displayed.</para>
858
859 <programlisting role="C">
860     button = gtk_button_new_with_label ("Hello World");
861 </programlisting>
862
863 <para>Here, we take this button, and make it do something useful. We attach
864 a signal handler to it so when it emits the "clicked" signal, our
865 hello() function is called. The data is ignored, so we simply pass in
866 NULL to the hello() callback function. Obviously, the "clicked" signal
867 is emitted when we click the button with our mouse pointer.</para>
868
869 <programlisting role="C">
870     g_signal_connect (G_OBJECT (button), "clicked",
871                       G_CALLBACK (hello), NULL);
872 </programlisting>
873
874 <para>We are also going to use this button to exit our program. This will
875 illustrate how the "destroy" signal may come from either the window
876 manager, or our program. When the button is "clicked", same as above,
877 it calls the first hello() callback function, and then this one in the
878 order they are set up. You may have as many callback functions as you
879 need, and all will be executed in the order you connected
880 them. Because the gtk_widget_destroy() function accepts only a
881 GtkWidget *widget as an argument, we use the g_signal_connect_swapped() 
882 function here instead of straight g_signal_connect().</para>
883
884 <programlisting role="C">
885     g_signal_connect_swapped (G_OBJECT (button), "clicked",
886                               G_CALLBACK (gtk_widget_destroy),
887                               G_OBJECT (window));
888 </programlisting>
889
890 <para>This is a packing call, which will be explained in depth later on in
891 <link linkend="ch-PackingWidgets">Packing Widgets</link>. But it is
892 fairly easy to understand. It simply tells GTK that the button is to
893 be placed in the window where it will be displayed. Note that a GTK
894 container can only contain one widget. There are other widgets, that
895 are described later, which are designed to layout multiple widgets in
896 various ways.
897  </para>
898
899 <programlisting role="C">
900     gtk_container_add (GTK_CONTAINER (window), button);
901 </programlisting>
902
903 <para>Now we have everything set up the way we want it to be. With all the
904 signal handlers in place, and the button placed in the window where it
905 should be, we ask GTK to "show" the widgets on the screen. The window
906 widget is shown last so the whole window will pop up at once rather
907 than seeing the window pop up, and then the button form inside of
908 it. Although with such a simple example, you'd never notice.</para>
909
910 <programlisting role="C">
911     gtk_widget_show (button);
912
913     gtk_widget_show (window);
914 </programlisting>
915
916 <para>And of course, we call gtk_main() which waits for events to come from
917 the X server and will call on the widgets to emit signals when these
918 events come.</para>
919
920 <programlisting role="C">
921     gtk_main ();
922 </programlisting>
923
924 <para>And the final return. Control returns here after gtk_main_quit() is called.</para>
925
926 <programlisting role="C">
927     return 0;
928 </programlisting>
929
930 <para>Now, when we click the mouse button on a GTK button, the widget emits
931 a "clicked" signal. In order for us to use this information, our
932 program sets up a signal handler to catch that signal, which
933 dispatches the function of our choice. In our example, when the button
934 we created is "clicked", the hello() function is called with a NULL
935 argument, and then the next handler for this signal is called. This
936 calls the gtk_widget_destroy() function, passing it the window widget
937 as its argument, destroying the window widget. This causes the window
938 to emit the "destroy" signal, which is caught, and calls our destroy()
939 callback function, which simply exits GTK.</para>
940
941 <para>Another course of events is to use the window manager to kill the
942 window, which will cause the "delete_event" to be emitted. This will
943 call our "delete_event" handler. If we return TRUE here, the window
944 will be left as is and nothing will happen. Returning FALSE will cause
945 GTK to emit the "destroy" signal which of course calls the "destroy"
946 callback, exiting GTK.</para>
947
948 </sect1>
949 </chapter>
950
951 <!-- ***************************************************************** -->
952 <chapter id="ch-MovingOn">
953 <title>Moving On</title>
954
955 <!-- ----------------------------------------------------------------- -->
956 <sect1 id="sec-DataTypes">
957 <title>Data Types</title>
958
959 <para>There are a few things you probably noticed in the previous examples
960 that need explaining. The gint, gchar, etc. that you see are typedefs
961 to int and char, respectively, that are part of the GLib system. This
962 is done to get around that nasty dependency on the size of simple data
963 types when doing calculations.</para>
964
965 <para>A good example is "gint32" which will be typedef'd to a 32 bit integer
966 for any given platform, whether it be the 64 bit alpha, or the 32 bit
967 i386. The typedefs are very straightforward and intuitive. They are
968 all defined in <filename>glib/glib.h</filename> (which gets included from 
969 <filename>gtk.h</filename>).</para>
970
971 <para>You'll also notice GTK's ability to use GtkWidget when the function
972 calls for a GtkObject. GTK is an object oriented design, and a widget
973 is an object.</para>
974
975 </sect1>
976
977 <!-- ----------------------------------------------------------------- -->
978 <sect1 id="sec-MoreOnSignalHandlers">
979 <title>More on Signal Handlers</title>
980
981 <para>Lets take another look at the g_signal_connect() declaration.</para>
982
983 <programlisting role="C">
984 gulong g_signal_connect( gpointer object,
985                          const gchar *name,
986                          GCallback func,
987                          gpointer func_data );
988 </programlisting>
989
990 <para>Notice the gulong return value? This is a tag that identifies your
991 callback function. As stated above, you may have as many callbacks per
992 signal and per object as you need, and each will be executed in turn,
993 in the order they were attached.</para>
994
995 <para>This tag allows you to remove this callback from the list by using:</para>
996
997 <programlisting role="C">
998 void g_signal_handler_disconnect( gpointer object,
999                                   gulong   id );
1000 </programlisting>
1001
1002 <para>So, by passing in the widget you wish to remove the handler from, and
1003 the tag returned by one of the signal_connect functions, you can
1004 disconnect a signal handler.</para>
1005
1006 <para>You can also temporarily disable signal handlers with the
1007 g_signal_handler_block() and g_signal_handler_unblock() family of
1008 functions.</para>
1009
1010 <programlisting role="C">
1011 void g_signal_handler_block( gpointer object,
1012                              gulong   id );
1013
1014 void g_signal_handlers_block_by_func( gpointer  object,
1015                                       GCallback func,
1016                                       gpointer  data );
1017
1018 void g_signal_handler_unblock( gpointer object,
1019                                gulong   id );
1020
1021 void g_signal_handlers_unblock_by_func( gpointer  object,
1022                                         GCallback func,
1023                                         gpointer  data );
1024 </programlisting>
1025
1026 </sect1>
1027
1028 <!-- ----------------------------------------------------------------- -->
1029 <sect1 id="sec-AnUpgradedHelloWorld">
1030 <title>An Upgraded Hello World</title>
1031
1032 <para>Let's take a look at a slightly improved <emphasis>helloworld</emphasis> with
1033 better examples of callbacks. This will also introduce us to our next
1034 topic, packing widgets.</para>
1035
1036 <para>
1037 <inlinemediaobject>
1038 <imageobject>
1039 <imagedata fileref="images/helloworld2.png" format="png">
1040 </imageobject>
1041 </inlinemediaobject>
1042 </para>
1043
1044 <programlisting role="C">
1045 <!-- example-start helloworld2 helloworld2.c -->
1046
1047 #include &lt;gtk/gtk.h&gt;
1048
1049 /* Our new improved callback.  The data passed to this function
1050  * is printed to stdout. */
1051 static void callback( GtkWidget *widget,
1052                       gpointer   data )
1053 {
1054     g_print ("Hello again - %s was pressed\n", (gchar *) data);
1055 }
1056
1057 /* another callback */
1058 static gboolean delete_event( GtkWidget *widget,
1059                               GdkEvent  *event,
1060                               gpointer   data )
1061 {
1062     gtk_main_quit ();
1063     return FALSE;
1064 }
1065
1066 int main( int   argc,
1067           char *argv[] )
1068 {
1069     /* GtkWidget is the storage type for widgets */
1070     GtkWidget *window;
1071     GtkWidget *button;
1072     GtkWidget *box1;
1073
1074     /* This is called in all GTK applications. Arguments are parsed
1075      * from the command line and are returned to the application. */
1076     gtk_init (&amp;argc, &amp;argv);
1077
1078     /* Create a new window */
1079     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1080
1081     /* This is a new call, which just sets the title of our
1082      * new window to "Hello Buttons!" */
1083     gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
1084
1085     /* Here we just set a handler for delete_event that immediately
1086      * exits GTK. */
1087     g_signal_connect (G_OBJECT (window), "delete_event",
1088                       G_CALLBACK (delete_event), NULL);
1089
1090     /* Sets the border width of the window. */
1091     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1092
1093     /* We create a box to pack widgets into.  This is described in detail
1094      * in the "packing" section. The box is not really visible, it
1095      * is just used as a tool to arrange widgets. */
1096     box1 = gtk_hbox_new (FALSE, 0);
1097
1098     /* Put the box into the main window. */
1099     gtk_container_add (GTK_CONTAINER (window), box1);
1100
1101     /* Creates a new button with the label "Button 1". */
1102     button = gtk_button_new_with_label ("Button 1");
1103     
1104     /* Now when the button is clicked, we call the "callback" function
1105      * with a pointer to "button 1" as its argument */
1106     g_signal_connect (G_OBJECT (button), "clicked",
1107                       G_CALLBACK (callback), (gpointer) "button 1");
1108
1109     /* Instead of gtk_container_add, we pack this button into the invisible
1110      * box, which has been packed into the window. */
1111     gtk_box_pack_start (GTK_BOX(box1), button, TRUE, TRUE, 0);
1112
1113     /* Always remember this step, this tells GTK that our preparation for
1114      * this button is complete, and it can now be displayed. */
1115     gtk_widget_show (button);
1116
1117     /* Do these same steps again to create a second button */
1118     button = gtk_button_new_with_label ("Button 2");
1119
1120     /* Call the same callback function with a different argument,
1121      * passing a pointer to "button 2" instead. */
1122     g_signal_connect (G_OBJECT (button), "clicked",
1123                       G_CALLBACK (callback), (gpointer) "button 2");
1124
1125     gtk_box_pack_start(GTK_BOX (box1), button, TRUE, TRUE, 0);
1126
1127     /* The order in which we show the buttons is not really important, but I
1128      * recommend showing the window last, so it all pops up at once. */
1129     gtk_widget_show (button);
1130
1131     gtk_widget_show (box1);
1132
1133     gtk_widget_show (window);
1134     
1135     /* Rest in gtk_main and wait for the fun to begin! */
1136     gtk_main ();
1137
1138     return 0;
1139 }
1140 <!-- example-end -->
1141 </programlisting>
1142
1143 <para>Compile this program using the same linking arguments as our first
1144 example.  You'll notice this time there is no easy way to exit the
1145 program, you have to use your window manager or command line to kill
1146 it. A good exercise for the reader would be to insert a third "Quit"
1147 button that will exit the program. You may also wish to play with the
1148 options to gtk_box_pack_start() while reading the next section.  Try
1149 resizing the window, and observe the behavior.</para>
1150
1151 </sect1>
1152 </chapter>
1153
1154 <!-- ***************************************************************** -->
1155 <chapter id="ch-PackingWidgets">
1156 <title>Packing Widgets</title>
1157
1158 <para>When creating an application, you'll want to put more than one widget
1159 inside a window. Our first <emphasis>helloworld</emphasis> example only used one
1160 widget so we could simply use a gtk_container_add() call to "pack" the
1161 widget into the window. But when you want to put more than one widget
1162 into a window, how do you control where that widget is positioned?
1163 This is where packing comes in.</para>
1164
1165 <!-- ----------------------------------------------------------------- -->
1166 <sect1 id="sec-TheoryOfPackingBoxes">
1167 <title>Theory of Packing Boxes</title>
1168
1169 <para>Most packing is done by creating boxes. These
1170 are invisible widget containers that we can pack our widgets into
1171 which come in two forms, a horizontal box, and a vertical box. When
1172 packing widgets into a horizontal box, the objects are inserted
1173 horizontally from left to right or right to left depending on the call
1174 used. In a vertical box, widgets are packed from top to bottom or vice
1175 versa. You may use any combination of boxes inside or beside other
1176 boxes to create the desired effect.</para>
1177
1178 <para>To create a new horizontal box, we use a call to gtk_hbox_new(), and
1179 for vertical boxes, gtk_vbox_new(). The gtk_box_pack_start() and
1180 gtk_box_pack_end() functions are used to place objects inside of these
1181 containers. The gtk_box_pack_start() function will start at the top
1182 and work its way down in a vbox, and pack left to right in an hbox.
1183 gtk_box_pack_end() will do the opposite, packing from bottom to top in
1184 a vbox, and right to left in an hbox. Using these functions allows us
1185 to right justify or left justify our widgets and may be mixed in any
1186 way to achieve the desired effect. We will use gtk_box_pack_start() in
1187 most of our examples. An object may be another container or a
1188 widget. In fact, many widgets are actually containers themselves,
1189 including the button, but we usually only use a label inside a button.</para>
1190
1191 <para>By using these calls, GTK knows where you want to place your widgets
1192 so it can do automatic resizing and other nifty things. There are also
1193 a number of options as to how your widgets should be packed. As you
1194 can imagine, this method gives us a quite a bit of flexibility when
1195 placing and creating widgets.</para>
1196
1197 </sect1>
1198
1199 <!-- ----------------------------------------------------------------- -->
1200 <sect1 id="sec-DetailsOfBoxes">
1201 <title>Details of Boxes</title>
1202
1203 <para>Because of this flexibility, packing boxes in GTK can be confusing at
1204 first. There are a lot of options, and it's not immediately obvious how
1205 they all fit together. In the end, however, there are basically five
1206 different styles.</para>
1207
1208 <para>
1209 <inlinemediaobject>
1210 <imageobject>
1211 <imagedata fileref="images/packbox1.png" format="png">
1212 </imageobject>
1213 </inlinemediaobject>
1214 </para>
1215
1216 <para>Each line contains one horizontal box (hbox) with several buttons. The
1217 call to gtk_box_pack is shorthand for the call to pack each of the
1218 buttons into the hbox. Each of the buttons is packed into the hbox the
1219 same way (i.e., same arguments to the gtk_box_pack_start() function).</para>
1220
1221 <para>This is the declaration of the gtk_box_pack_start() function.</para>
1222
1223 <programlisting role="C">
1224 void gtk_box_pack_start( GtkBox    *box,
1225                          GtkWidget *child,
1226                          gboolean   expand,
1227                          gboolean   fill,
1228                          guint      padding );
1229 </programlisting>
1230
1231 <para>The first argument is the box you are packing the object into, the
1232 second is the object. The objects will all be buttons for now, so
1233 we'll be packing buttons into boxes.</para>
1234
1235 <para>The expand argument to gtk_box_pack_start() and gtk_box_pack_end()
1236 controls whether the widgets are laid out in the box to fill in all
1237 the extra space in the box so the box is expanded to fill the area
1238 allotted to it (TRUE); or the box is shrunk to just fit the widgets
1239 (FALSE). Setting expand to FALSE will allow you to do right and left
1240 justification of your widgets.  Otherwise, they will all expand to fit
1241 into the box, and the same effect could be achieved by using only one
1242 of gtk_box_pack_start() or gtk_box_pack_end().</para>
1243
1244 <para>The fill argument to the gtk_box_pack functions control whether the
1245 extra space is allocated to the objects themselves (TRUE), or as extra
1246 padding in the box around these objects (FALSE). It only has an effect
1247 if the expand argument is also TRUE.</para>
1248
1249 <para>When creating a new box, the function looks like this:</para>
1250
1251 <programlisting role="C">
1252 GtkWidget *gtk_hbox_new ( gboolean homogeneous,
1253                           gint     spacing );
1254 </programlisting>
1255
1256 <para>The homogeneous argument to gtk_hbox_new() (and the same for
1257 gtk_vbox_new()) controls whether each object in the box has the same
1258 size (i.e., the same width in an hbox, or the same height in a
1259 vbox). If it is set, the gtk_box_pack() routines function essentially
1260 as if the <literal>expand</literal> argument was always turned on.</para>
1261
1262 <para>What's the difference between spacing (set when the box is created)
1263 and padding (set when elements are packed)? Spacing is added between
1264 objects, and padding is added on either side of an object. The
1265 following figure should make it clearer:</para>
1266
1267 <para>
1268 <inlinemediaobject>
1269 <imageobject>
1270 <imagedata fileref="images/packbox2.png" format="png">
1271 </imageobject>
1272 </inlinemediaobject>
1273 </para>
1274
1275 <para>Here is the code used to create the above images. I've commented it
1276 fairly heavily so I hope you won't have any problems following
1277 it. Compile it yourself and play with it.</para>
1278
1279 </sect1>
1280
1281 <!-- ----------------------------------------------------------------- -->
1282 <sect1 id="sec-PackingDemonstrationProgram">
1283 <title>Packing Demonstration Program</title>
1284
1285 <programlisting role="C">
1286 /* example-start packbox packbox.c */
1287
1288 #include &lt;stdio.h&gt;
1289 #include &lt;stdlib.h&gt;
1290 #include "gtk/gtk.h"
1291
1292 static gboolean delete_event( GtkWidget *widget,
1293                               GdkEvent  *event,
1294                               gpointer   data )
1295 {
1296     gtk_main_quit ();
1297     return FALSE;
1298 }
1299
1300 /* Make a new hbox filled with button-labels. Arguments for the 
1301  * variables we're interested are passed in to this function. 
1302  * We do not show the box, but do show everything inside. */
1303 static GtkWidget *make_box( gboolean homogeneous,
1304                             gint     spacing,
1305                             gboolean expand,
1306                             gboolean fill,
1307                             guint    padding ) 
1308 {
1309     GtkWidget *box;
1310     GtkWidget *button;
1311     char padstr[80];
1312     
1313     /* Create a new hbox with the appropriate homogeneous
1314      * and spacing settings */
1315     box = gtk_hbox_new (homogeneous, spacing);
1316     
1317     /* Create a series of buttons with the appropriate settings */
1318     button = gtk_button_new_with_label ("gtk_box_pack");
1319     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1320     gtk_widget_show (button);
1321     
1322     button = gtk_button_new_with_label ("(box,");
1323     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1324     gtk_widget_show (button);
1325     
1326     button = gtk_button_new_with_label ("button,");
1327     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1328     gtk_widget_show (button);
1329     
1330     /* Create a button with the label depending on the value of
1331      * expand. */
1332     if (expand == TRUE)
1333             button = gtk_button_new_with_label ("TRUE,");
1334     else
1335             button = gtk_button_new_with_label ("FALSE,");
1336     
1337     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1338     gtk_widget_show (button);
1339     
1340     /* This is the same as the button creation for "expand"
1341      * above, but uses the shorthand form. */
1342     button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
1343     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1344     gtk_widget_show (button);
1345     
1346     sprintf (padstr, "%d);", padding);
1347     
1348     button = gtk_button_new_with_label (padstr);
1349     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1350     gtk_widget_show (button);
1351     
1352     return box;
1353 }
1354
1355 int main( int   argc,
1356           char *argv[]) 
1357 {
1358     GtkWidget *window;
1359     GtkWidget *button;
1360     GtkWidget *box1;
1361     GtkWidget *box2;
1362     GtkWidget *separator;
1363     GtkWidget *label;
1364     GtkWidget *quitbox;
1365     int which;
1366     
1367     /* Our init, don't forget this! :) */
1368     gtk_init (&amp;argc, &amp;argv);
1369     
1370     if (argc != 2) {
1371         fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n");
1372         /* This just does cleanup in GTK and exits with an exit status of 1. */
1373         exit (1);
1374     }
1375     
1376     which = atoi (argv[1]);
1377
1378     /* Create our window */
1379     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1380
1381     /* You should always remember to connect the delete_event signal
1382      * to the main window. This is very important for proper intuitive
1383      * behavior */
1384     g_signal_connect (G_OBJECT (window), "delete_event",
1385                       G_CALLBACK (delete_event), NULL);
1386     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1387     
1388     /* We create a vertical box (vbox) to pack the horizontal boxes into.
1389      * This allows us to stack the horizontal boxes filled with buttons one
1390      * on top of the other in this vbox. */
1391     box1 = gtk_vbox_new (FALSE, 0);
1392     
1393     /* which example to show. These correspond to the pictures above. */
1394     switch (which) {
1395     case 1:
1396         /* create a new label. */
1397         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1398         
1399         /* Align the label to the left side.  We'll discuss this function and 
1400          * others in the section on Widget Attributes. */
1401         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1402
1403         /* Pack the label into the vertical box (vbox box1).  Remember that 
1404          * widgets added to a vbox will be packed one on top of the other in
1405          * order. */
1406         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1407         
1408         /* Show the label */
1409         gtk_widget_show (label);
1410         
1411         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1412          * expand = FALSE, fill = FALSE, padding = 0 */
1413         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1414         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1415         gtk_widget_show (box2);
1416
1417         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1418          * expand = TRUE, fill = FALSE, padding = 0 */
1419         box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
1420         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1421         gtk_widget_show (box2);
1422         
1423         /* Args are: homogeneous, spacing, expand, fill, padding */
1424         box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
1425         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1426         gtk_widget_show (box2);
1427         
1428         /* Creates a separator, we'll learn more about these later, 
1429          * but they are quite simple. */
1430         separator = gtk_hseparator_new ();
1431         
1432         /* Pack the separator into the vbox. Remember each of these
1433          * widgets is being packed into a vbox, so they'll be stacked
1434          * vertically. */
1435         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1436         gtk_widget_show (separator);
1437         
1438         /* Create another new label, and show it. */
1439         label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
1440         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1441         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1442         gtk_widget_show (label);
1443         
1444         /* Args are: homogeneous, spacing, expand, fill, padding */
1445         box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
1446         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1447         gtk_widget_show (box2);
1448         
1449         /* Args are: homogeneous, spacing, expand, fill, padding */
1450         box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
1451         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1452         gtk_widget_show (box2);
1453         
1454         /* Another new separator. */
1455         separator = gtk_hseparator_new ();
1456         /* The last 3 arguments to gtk_box_pack_start are:
1457          * expand, fill, padding. */
1458         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1459         gtk_widget_show (separator);
1460         
1461         break;
1462
1463     case 2:
1464
1465         /* Create a new label, remember box1 is a vbox as created 
1466          * near the beginning of main() */
1467         label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
1468         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1469         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1470         gtk_widget_show (label);
1471         
1472         /* Args are: homogeneous, spacing, expand, fill, padding */
1473         box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
1474         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1475         gtk_widget_show (box2);
1476         
1477         /* Args are: homogeneous, spacing, expand, fill, padding */
1478         box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
1479         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1480         gtk_widget_show (box2);
1481         
1482         separator = gtk_hseparator_new ();
1483         /* The last 3 arguments to gtk_box_pack_start are:
1484          * expand, fill, padding. */
1485         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1486         gtk_widget_show (separator);
1487         
1488         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1489         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1490         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1491         gtk_widget_show (label);
1492         
1493         /* Args are: homogeneous, spacing, expand, fill, padding */
1494         box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
1495         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1496         gtk_widget_show (box2);
1497         
1498         /* Args are: homogeneous, spacing, expand, fill, padding */
1499         box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
1500         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1501         gtk_widget_show (box2);
1502         
1503         separator = gtk_hseparator_new ();
1504         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1505         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1506         gtk_widget_show (separator);
1507         break;
1508     
1509     case 3:
1510
1511         /* This demonstrates the ability to use gtk_box_pack_end() to
1512          * right justify widgets. First, we create a new box as before. */
1513         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1514
1515         /* Create the label that will be put at the end. */
1516         label = gtk_label_new ("end");
1517         /* Pack it using gtk_box_pack_end(), so it is put on the right
1518          * side of the hbox created in the make_box() call. */
1519         gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
1520         /* Show the label. */
1521         gtk_widget_show (label);
1522         
1523         /* Pack box2 into box1 (the vbox remember ? :) */
1524         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1525         gtk_widget_show (box2);
1526         
1527         /* A separator for the bottom. */
1528         separator = gtk_hseparator_new ();
1529         /* This explicitly sets the separator to 400 pixels wide by 5 pixels
1530          * high. This is so the hbox we created will also be 400 pixels wide,
1531          * and the "end" label will be separated from the other labels in the
1532          * hbox. Otherwise, all the widgets in the hbox would be packed as
1533          * close together as possible. */
1534         gtk_widget_set_size_request (separator, 400, 5);
1535         /* pack the separator into the vbox (box1) created near the start 
1536          * of main() */
1537         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1538         gtk_widget_show (separator);    
1539     }
1540     
1541     /* Create another new hbox.. remember we can use as many as we need! */
1542     quitbox = gtk_hbox_new (FALSE, 0);
1543     
1544     /* Our quit button. */
1545     button = gtk_button_new_with_label ("Quit");
1546     
1547     /* Setup the signal to terminate the program when the button is clicked */
1548     g_signal_connect_swapped (G_OBJECT (button), "clicked",
1549                               G_CALLBACK (gtk_main_quit),
1550                               G_OBJECT (window));
1551     /* Pack the button into the quitbox.
1552      * The last 3 arguments to gtk_box_pack_start are:
1553      * expand, fill, padding. */
1554     gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
1555     /* pack the quitbox into the vbox (box1) */
1556     gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
1557     
1558     /* Pack the vbox (box1) which now contains all our widgets, into the
1559      * main window. */
1560     gtk_container_add (GTK_CONTAINER (window), box1);
1561     
1562     /* And show everything left */
1563     gtk_widget_show (button);
1564     gtk_widget_show (quitbox);
1565     
1566     gtk_widget_show (box1);
1567     /* Showing the window last so everything pops up at once. */
1568     gtk_widget_show (window);
1569     
1570     /* And of course, our main function. */
1571     gtk_main ();
1572
1573     /* Control returns here when gtk_main_quit() is called, but not when 
1574      * exit() is used. */
1575     
1576     return 0;
1577 }
1578 <!-- example-end -->
1579 </programlisting>
1580
1581 </sect1>
1582
1583 <!-- ----------------------------------------------------------------- -->
1584 <sect1 id="sec-PackingUsingTables">
1585 <title>Packing Using Tables</title>
1586
1587 <para>Let's take a look at another way of packing - Tables. These can be
1588 extremely useful in certain situations.</para>
1589
1590 <para>Using tables, we create a grid that we can place widgets in. The
1591 widgets may take up as many spaces as we specify.</para>
1592
1593 <para>The first thing to look at, of course, is the gtk_table_new() function:</para>
1594
1595 <programlisting role="C">
1596 GtkWidget *gtk_table_new( guint    rows,
1597                           guint    columns,
1598                           gboolean homogeneous );
1599 </programlisting>
1600
1601 <para>The first argument is the number of rows to make in the table, while
1602 the second, obviously, is the number of columns.</para>
1603
1604 <para>The homogeneous argument has to do with how the table's boxes are
1605 sized. If homogeneous is TRUE, the table boxes are resized to the size
1606 of the largest widget in the table. If homogeneous is FALSE, the size
1607 of a table boxes is dictated by the tallest widget in its same row,
1608 and the widest widget in its column.</para>
1609
1610 <para>The rows and columns are laid out from 0 to n, where n was the number
1611 specified in the call to gtk_table_new. So, if you specify rows = 2
1612 and columns = 2, the layout would look something like this:</para>
1613
1614 <programlisting role="C">
1615  0          1          2
1616 0+----------+----------+
1617  |          |          |
1618 1+----------+----------+
1619  |          |          |
1620 2+----------+----------+
1621 </programlisting>
1622
1623 <para>Note that the coordinate system starts in the upper left hand corner.
1624 To place a widget into a box, use the following function:</para>
1625
1626 <programlisting role="C">
1627 void gtk_table_attach( GtkTable         *table,
1628                        GtkWidget        *child,
1629                        guint            left_attach,
1630                        guint            right_attach,
1631                        guint            top_attach,
1632                        guint            bottom_attach,
1633                        GtkAttachOptions xoptions,
1634                        GtkAttachOptions yoptions,
1635                        guint            xpadding,
1636                        guint            ypadding );
1637 </programlisting>
1638
1639 <para>The first argument ("table") is the table you've created and the
1640 second ("child") the widget you wish to place in the table.</para>
1641
1642 <para>The left and right attach arguments specify where to place the widget,
1643 and how many boxes to use. If you want a button in the lower right
1644 table entry of our 2x2 table, and want it to fill that entry <emphasis>only</emphasis>,
1645 left_attach would be = 1, right_attach = 2, top_attach = 1,
1646 bottom_attach = 2.</para>
1647
1648 <para>Now, if you wanted a widget to take up the whole top row of our 2x2
1649 table, you'd use left_attach = 0, right_attach = 2, top_attach = 0,
1650 bottom_attach = 1.</para>
1651
1652 <para>The xoptions and yoptions are used to specify packing options and may
1653 be bitwise OR'ed together to allow multiple options.</para>
1654
1655 <para>These options are:</para>
1656
1657 <variablelist>
1658 <varlistentry>
1659 <term><literal>GTK_FILL</literal></term>
1660 <listitem><para>If the table box is larger than the widget, and
1661 <literal>GTK_FILL</literal> is specified, the widget will expand to use all the room
1662 available.</para>
1663 </listitem>
1664 </varlistentry>
1665
1666 <varlistentry>
1667 <term><literal>GTK_SHRINK</literal></term>
1668 <listitem><para>If the table widget was allocated less space
1669 then was requested (usually by the user resizing the window), then the
1670 widgets would normally just be pushed off the bottom of the window and
1671 disappear. If <literal>GTK_SHRINK</literal> is specified, the widgets will shrink
1672 with the table.</para>
1673 </listitem>
1674 </varlistentry>
1675
1676 <varlistentry>
1677 <term><literal>GTK_EXPAND</literal></term>
1678 <listitem><para>This will cause the table to expand to use up
1679 any remaining space in the window.</para>
1680 </listitem>
1681 </varlistentry>
1682 </variablelist>
1683
1684 <para>Padding is just like in boxes, creating a clear area around the widget
1685 specified in pixels.</para>
1686
1687 <para>gtk_table_attach() has a <emphasis>lot</emphasis> of options.  
1688 So, there's a shortcut:</para>
1689
1690 <programlisting role="C">
1691 void gtk_table_attach_defaults( GtkTable  *table,
1692                                 GtkWidget *widget,
1693                                 guint      left_attach,
1694                                 guint      right_attach,
1695                                 guint      top_attach,
1696                                 guint      bottom_attach );
1697 </programlisting>
1698
1699 <para>The X and Y options default to <literal>GTK_FILL | GTK_EXPAND</literal>, 
1700 and X and Y padding are set to 0. The rest of the arguments are identical to the
1701 previous function.</para>
1702
1703 <para>We also have gtk_table_set_row_spacing() and
1704 gtk_table_set_col_spacing(). These places spacing between the rows at
1705 the specified row or column.</para>
1706
1707 <programlisting role="C">
1708 void gtk_table_set_row_spacing( GtkTable *table,
1709                                 guint     row,
1710                                 guint     spacing );
1711 </programlisting>
1712
1713 <para>and</para>
1714
1715 <programlisting role="C">
1716 void gtk_table_set_col_spacing ( GtkTable *table,
1717                                  guint     column,
1718                                  guint     spacing );
1719 </programlisting>
1720
1721 <para>Note that for columns, the space goes to the right of the column, and
1722 for rows, the space goes below the row.</para>
1723
1724 <para>You can also set a consistent spacing of all rows and/or columns with:</para>
1725
1726 <programlisting role="C">
1727 void gtk_table_set_row_spacings( GtkTable *table,
1728                                  guint    spacing );
1729 </programlisting>
1730
1731 <para>And,</para>
1732
1733 <programlisting role="C">
1734 void gtk_table_set_col_spacings( GtkTable *table,
1735                                  guint     spacing );
1736 </programlisting>
1737
1738 <para>Note that with these calls, the last row and last column do not get
1739 any spacing.</para>
1740
1741 </sect1>
1742
1743 <!-- ----------------------------------------------------------------- -->
1744 <sect1 id="sec-TablePackingExamples">
1745 <title>Table Packing Example</title>
1746
1747 <para>Here we make a window with three buttons in a 2x2 table.
1748 The first two buttons will be placed in the upper row.
1749 A third, quit button, is placed in the lower row, spanning both columns.
1750 Which means it should look something like this:</para>
1751
1752 <para>
1753 <inlinemediaobject>
1754 <imageobject>
1755 <imagedata fileref="images/table.png" format="png">
1756 </imageobject>
1757 </inlinemediaobject>
1758 </para>
1759
1760 <para>Here's the source code:</para>
1761
1762 <programlisting role="C">
1763 <!-- example-start table table.c -->
1764
1765 #include &lt;gtk/gtk.h&gt;
1766
1767 /* Our callback.
1768  * The data passed to this function is printed to stdout */
1769 static void callback( GtkWidget *widget,
1770                       gpointer   data )
1771 {
1772     g_print ("Hello again - %s was pressed\n", (char *) data);
1773 }
1774
1775 /* This callback quits the program */
1776 static gboolean delete_event( GtkWidget *widget,
1777                               GdkEvent  *event,
1778                               gpointer   data )
1779 {
1780     gtk_main_quit ();
1781     return FALSE;
1782 }
1783
1784 int main( int   argc,
1785           char *argv[] )
1786 {
1787     GtkWidget *window;
1788     GtkWidget *button;
1789     GtkWidget *table;
1790
1791     gtk_init (&amp;argc, &amp;argv);
1792
1793     /* Create a new window */
1794     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1795
1796     /* Set the window title */
1797     gtk_window_set_title (GTK_WINDOW (window), "Table");
1798
1799     /* Set a handler for delete_event that immediately
1800      * exits GTK. */
1801     g_signal_connect (G_OBJECT (window), "delete_event",
1802                       G_CALLBACK (delete_event), NULL);
1803
1804     /* Sets the border width of the window. */
1805     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
1806
1807     /* Create a 2x2 table */
1808     table = gtk_table_new (2, 2, TRUE);
1809
1810     /* Put the table in the main window */
1811     gtk_container_add (GTK_CONTAINER (window), table);
1812
1813     /* Create first button */
1814     button = gtk_button_new_with_label ("button 1");
1815
1816     /* When the button is clicked, we call the "callback" function
1817      * with a pointer to "button 1" as its argument */
1818     g_signal_connect (G_OBJECT (button), "clicked",
1819                       G_CALLBACK (callback), (gpointer) "button 1");
1820
1821
1822     /* Insert button 1 into the upper left quadrant of the table */
1823     gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 1, 0, 1);
1824
1825     gtk_widget_show (button);
1826
1827     /* Create second button */
1828
1829     button = gtk_button_new_with_label ("button 2");
1830
1831     /* When the button is clicked, we call the "callback" function
1832      * with a pointer to "button 2" as its argument */
1833     g_signal_connect (G_OBJECT (button), "clicked",
1834                       G_CALLBACK (callback), (gpointer) "button 2");
1835     /* Insert button 2 into the upper right quadrant of the table */
1836     gtk_table_attach_defaults (GTK_TABLE (table), button, 1, 2, 0, 1);
1837
1838     gtk_widget_show (button);
1839
1840     /* Create "Quit" button */
1841     button = gtk_button_new_with_label ("Quit");
1842
1843     /* When the button is clicked, we call the "delete_event" function
1844      * and the program exits */
1845     g_signal_connect (G_OBJECT (button), "clicked",
1846                       G_CALLBACK (delete_event), NULL);
1847
1848     /* Insert the quit button into the both 
1849      * lower quadrants of the table */
1850     gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 2, 1, 2);
1851
1852     gtk_widget_show (button);
1853
1854     gtk_widget_show (table);
1855     gtk_widget_show (window);
1856
1857     gtk_main ();
1858
1859     return 0;
1860 }
1861 <!-- example-end -->
1862 </programlisting>
1863
1864 </sect1>
1865 </chapter>
1866
1867 <!-- ***************************************************************** -->
1868 <chapter id="ch-WidgetOverview">
1869 <title>Widget Overview</title>
1870
1871 <para>The general steps to creating a widget in GTK are:</para>
1872 <orderedlist>
1873 <listitem><simpara> gtk_*_new() - one of various functions to create a new widget.
1874 These are all detailed in this section.</simpara>
1875 </listitem>
1876
1877 <listitem><simpara> Connect all signals and events we wish to use to the
1878 appropriate handlers.</simpara>
1879 </listitem>
1880
1881 <listitem><simpara> Set the attributes of the widget.</simpara>
1882 </listitem>
1883
1884 <listitem><simpara> Pack the widget into a container using the appropriate call
1885 such as gtk_container_add() or gtk_box_pack_start().</simpara>
1886 </listitem>
1887
1888 <listitem><simpara> gtk_widget_show() the widget.</simpara>
1889 </listitem>
1890 </orderedlist>
1891
1892 <para>gtk_widget_show() lets GTK know that we are done setting the
1893 attributes of the widget, and it is ready to be displayed. You may
1894 also use gtk_widget_hide to make it disappear again. The order in
1895 which you show the widgets is not important, but I suggest showing the
1896 window last so the whole window pops up at once rather than seeing the
1897 individual widgets come up on the screen as they're formed. The
1898 children of a widget (a window is a widget too) will not be displayed
1899 until the window itself is shown using the gtk_widget_show() function.</para>
1900
1901 <!-- ----------------------------------------------------------------- -->
1902 <sect1 id="sec-Casting">
1903 <title>Casting</title>
1904
1905 <para>You'll notice as you go on that GTK uses a type casting system. This
1906 is always done using macros that both test the ability to cast the
1907 given item, and perform the cast. Some common ones you will see are:</para>
1908
1909 <programlisting role="C">
1910   G_OBJECT (object)
1911   GTK_WIDGET (widget)
1912   GTK_OBJECT (object)
1913   GTK_SIGNAL_FUNC (function)
1914   GTK_CONTAINER (container)
1915   GTK_WINDOW (window)
1916   GTK_BOX (box)
1917 </programlisting>
1918
1919 <para>These are all used to cast arguments in functions. You'll see them in the
1920 examples, and can usually tell when to use them simply by looking at the
1921 function's declaration.</para>
1922
1923 <para>As you can see below in the class hierarchy, all GtkWidgets are
1924 derived from the GObject base class. This means you can use a widget
1925 in any place the function asks for an object - simply use the
1926 <literal>G_OBJECT()</literal> macro.</para>
1927
1928 <para>For example:</para>
1929
1930 <programlisting role="C">
1931 g_signal_connect( G_OBJECT (button), "clicked",
1932                   G_CALLBACK (callback_function), callback_data);
1933 </programlisting>
1934
1935 <para>This casts the button into an object, and provides a cast for the
1936 function pointer to the callback.</para>
1937
1938 <para>Many widgets are also containers. If you look in the class hierarchy
1939 below, you'll notice that many widgets derive from the Container
1940 class. Any one of these widgets may be used with the
1941 <literal>GTK_CONTAINER</literal> macro to pass them to functions that ask for
1942 containers.</para>
1943
1944 <para>Unfortunately, these macros are not extensively covered in the
1945 tutorial, but I recommend taking a look through the GTK header
1946 files or the GTK API reference manual. It can be very educational. In fact, 
1947 it's not difficult to learn how a widget works just by looking at the 
1948 function declarations.</para>
1949
1950 </sect1>
1951
1952 <!-- ----------------------------------------------------------------- -->
1953 <sect1 id="sec-WidgetHierarchy">
1954 <title>Widget Hierarchy</title>
1955
1956 <para>For your reference, here is the class hierarchy tree used to implement 
1957 widgets. (Deprecated widgets and auxiliary classes have been omitted.)</para>
1958
1959 <programlisting role="C">
1960 GObject
1961  |  
1962  GtkObject
1963   +GtkWidget
1964   | +GtkMisc
1965   | | +GtkLabel
1966   | | | `GtkAccelLabel
1967   | | +GtkArrow
1968   | | `GtkImage
1969   | +GtkContainer
1970   | | +GtkBin
1971   | | | +GtkAlignment
1972   | | | +GtkFrame
1973   | | | | `GtkAspectFrame
1974   | | | +GtkButton
1975   | | | | +GtkToggleButton
1976   | | | | | `GtkCheckButton
1977   | | | | |   `GtkRadioButton
1978   | | | | `GtkOptionMenu
1979   | | | +GtkItem
1980   | | | | +GtkMenuItem
1981   | | | |   +GtkCheckMenuItem
1982   | | | |   | `GtkRadioMenuItem
1983   | | | |   +GtkImageMenuItem
1984   | | | |   +GtkSeparatorMenuItem
1985   | | | |   `GtkTearoffMenuItem
1986   | | | +GtkWindow
1987   | | | | +GtkDialog
1988   | | | | | +GtkColorSelectionDialog
1989   | | | | | +GtkFileSelection
1990   | | | | | +GtkFontSelectionDialog
1991   | | | | | +GtkInputDialog
1992   | | | | | `GtkMessageDialog
1993   | | | | `GtkPlug
1994   | | | +GtkEventBox
1995   | | | +GtkHandleBox
1996   | | | +GtkScrolledWindow
1997   | | | `GtkViewport
1998   | | +GtkBox
1999   | | | +GtkButtonBox
2000   | | | | +GtkHButtonBox
2001   | | | | `GtkVButtonBox
2002   | | | +GtkVBox
2003   | | | | +GtkColorSelection
2004   | | | | +GtkFontSelection
2005   | | | | `GtkGammaCurve
2006   | | | `GtkHBox
2007   | | |   +GtkCombo
2008   | | |   `GtkStatusbar
2009   | | +GtkFixed
2010   | | +GtkPaned
2011   | | | +GtkHPaned
2012   | | | `GtkVPaned
2013   | | +GtkLayout
2014   | | +GtkMenuShell
2015   | | | +GtkMenuBar
2016   | | | `GtkMenu
2017   | | +GtkNotebook
2018   | | +GtkSocket
2019   | | +GtkTable
2020   | | +GtkTextView
2021   | | +GtkToolbar
2022   | | `GtkTreeView
2023   | +GtkCalendar
2024   | +GtkDrawingArea
2025   | | `GtkCurve
2026   | +GtkEditable
2027   | | +GtkEntry
2028   | |   `GtkSpinButton
2029   | +GtkRuler
2030   | | +GtkHRuler
2031   | | `GtkVRuler
2032   | +GtkRange
2033   | | +GtkScale
2034   | | | +GtkHScale
2035   | | | `GtkVScale
2036   | | `GtkScrollbar
2037   | |   +GtkHScrollbar
2038   | |   `GtkVScrollbar
2039   | +GtkSeparator
2040   | | +GtkHSeparator
2041   | | `GtkVSeparator
2042   | +GtkInvisible
2043   | +GtkPreview
2044   | `GtkProgressBar
2045   +GtkAdjustment
2046   +GtkCellRenderer
2047   | +GtkCellRendererPixbuf
2048   | +GtkCellRendererText
2049   | +GtkCellRendererToggle
2050   +GtkItemFactory
2051   +GtkTooltips
2052   `GtkTreeViewColumn
2053 </programlisting>
2054
2055 </sect1>
2056
2057 <!-- ----------------------------------------------------------------- -->
2058 <sect1 id="sec-WidgetsWithoutWindows">
2059 <title>Widgets Without Windows</title>
2060
2061 <para>The following widgets do not have an associated window. If you want to
2062 capture events, you'll have to use the EventBox. See the section on
2063 the <link linkend="sec-EventBox">EventBox</link> widget.</para>
2064
2065 <programlisting role="C">
2066 GtkAlignment
2067 GtkArrow
2068 GtkBin
2069 GtkBox
2070 GtkButton
2071 GtkCheckButton
2072 GtkFixed
2073 GtkImage
2074 GtkLabel
2075 GtkMenuItem
2076 GtkNotebook
2077 GtkPaned
2078 GtkRadioButton
2079 GtkRange
2080 GtkScrolledWindow
2081 GtkSeparator
2082 GtkTable
2083 GtkToolbar
2084 GtkAspectFrame
2085 GtkFrame
2086 GtkVBox
2087 GtkHBox
2088 GtkVSeparator
2089 GtkHSeparator
2090 </programlisting>
2091
2092 <para>We'll further our exploration of GTK by examining each widget in turn,
2093 creating a few simple functions to display them. Another good source
2094 is the <literal>testgtk</literal> program that comes with GTK. It can be found in
2095 <filename>tests/testgtk.c</filename>.</para>
2096
2097 </sect1>
2098 </chapter>
2099
2100 <!-- ***************************************************************** -->
2101 <chapter id="ch-ButtonWidget">
2102 <title>The Button Widget</title>
2103
2104 <!-- ----------------------------------------------------------------- -->
2105 <sect1 id="sec-NormalButtons">
2106 <title>Normal Buttons</title>
2107
2108 <para>We've almost seen all there is to see of the button widget. It's
2109 pretty simple. There is however more than one way to create a button. You can
2110 use the gtk_button_new_with_label() or gtk_button_new_with_mnemonic() to create 
2111 a button with a label, use gtk_button_new_from_stock() to create a button
2112 containing the image and text from a stock item or use gtk_button_new() to
2113 create a blank button. It's then up to you to pack a label or pixmap into 
2114 this new button. To do this, create a new box, and then pack your objects into 
2115 this box using the usual gtk_box_pack_start(), and then use gtk_container_add() 
2116 to pack the box into the button.</para>
2117
2118 <para>Here's an example of using gtk_button_new() to create a button with a
2119 image and a label in it. I've broken up the code to create a box from the rest 
2120 so you can use it in your programs. There are further examples of using images 
2121 later in the tutorial.</para>
2122
2123 <para>
2124 <inlinemediaobject>
2125 <imageobject>
2126 <imagedata fileref="images/buttons.png" format="png">
2127 </imageobject>
2128 </inlinemediaobject>
2129 </para>
2130
2131 <programlisting role="C">
2132 <!-- example-start buttons buttons.c -->
2133
2134 #include &lt;stdlib.h&gt;
2135 #include &lt;gtk/gtk.h&gt;
2136
2137 /* Create a new hbox with an image and a label packed into it
2138  * and return the box. */
2139
2140 static GtkWidget *xpm_label_box( gchar     *xpm_filename,
2141                                  gchar     *label_text )
2142 {
2143     GtkWidget *box;
2144     GtkWidget *label;
2145     GtkWidget *image;
2146
2147     /* Create box for image and label */
2148     box = gtk_hbox_new (FALSE, 0);
2149     gtk_container_set_border_width (GTK_CONTAINER (box), 2);
2150
2151     /* Now on to the image stuff */
2152     image = gtk_image_new_from_file (xpm_filename);
2153
2154     /* Create a label for the button */
2155     label = gtk_label_new (label_text);
2156
2157     /* Pack the image and label into the box */
2158     gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 3);
2159     gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 3);
2160
2161     gtk_widget_show (image);
2162     gtk_widget_show (label);
2163
2164     return box;
2165 }
2166
2167 /* Our usual callback function */
2168 static void callback( GtkWidget *widget,
2169                       gpointer   data )
2170 {
2171     g_print ("Hello again - %s was pressed\n", (char *) data);
2172 }
2173
2174 int main( int   argc,
2175           char *argv[] )
2176 {
2177     /* GtkWidget is the storage type for widgets */
2178     GtkWidget *window;
2179     GtkWidget *button;
2180     GtkWidget *box;
2181
2182     gtk_init (&amp;argc, &amp;argv);
2183
2184     /* Create a new window */
2185     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2186
2187     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
2188
2189     /* It's a good idea to do this for all windows. */
2190     g_signal_connect (G_OBJECT (window), "destroy",
2191                       G_CALLBACK (gtk_main_quit), NULL);
2192
2193     g_signal_connect (G_OBJECT (window), "delete_event",
2194                       G_CALLBACK (gtk_main_quit), NULL);
2195
2196     /* Sets the border width of the window. */
2197     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
2198
2199     /* Create a new button */
2200     button = gtk_button_new ();
2201
2202     /* Connect the "clicked" signal of the button to our callback */
2203     g_signal_connect (G_OBJECT (button), "clicked",
2204                       G_CALLBACK (callback), (gpointer) "cool button");
2205
2206     /* This calls our box creating function */
2207     box = xpm_label_box ("info.xpm", "cool button");
2208
2209     /* Pack and show all our widgets */
2210     gtk_widget_show (box);
2211
2212     gtk_container_add (GTK_CONTAINER (button), box);
2213
2214     gtk_widget_show (button);
2215
2216     gtk_container_add (GTK_CONTAINER (window), button);
2217
2218     gtk_widget_show (window);
2219
2220     /* Rest in gtk_main and wait for the fun to begin! */
2221     gtk_main ();
2222
2223     return 0;
2224 }
2225 <!-- example-end -->
2226 </programlisting>
2227
2228 <para>The xpm_label_box() function could be used to pack images and labels into
2229 any widget that can be a container.</para>
2230
2231 <para>The Button widget has the following signals:</para>
2232
2233 <itemizedlist>
2234 <listitem><simpara><literal>pressed</literal> - emitted when pointer button is pressed within
2235 Button widget</simpara>
2236 </listitem>
2237 <listitem><simpara><literal>released</literal> - emitted when pointer button is released within
2238 Button widget</simpara>
2239 </listitem>
2240 <listitem><simpara><literal>clicked</literal> - emitted when pointer button is pressed and then
2241 released within Button widget</simpara>
2242 </listitem>
2243 <listitem><simpara><literal>enter</literal> - emitted when pointer enters Button widget</simpara>
2244 </listitem>
2245 <listitem><simpara><literal>leave</literal> - emitted when pointer leaves Button widget</simpara>
2246 </listitem>
2247 </itemizedlist>
2248
2249 </sect1>
2250
2251 <!-- ----------------------------------------------------------------- -->
2252 <sect1 id="sec-ToggleButtons">
2253 <title>Toggle Buttons</title>
2254
2255 <para>Toggle buttons are derived from normal buttons and are very similar,
2256 except they will always be in one of two states, alternated by a
2257 click. They may be depressed, and when you click again, they will pop
2258 back up. Click again, and they will pop back down.</para>
2259
2260 <para>Toggle buttons are the basis for check buttons and radio buttons, as
2261 such, many of the calls used for toggle buttons are inherited by radio
2262 and check buttons. I will point these out when we come to them.</para>
2263
2264 <para>Creating a new toggle button:</para>
2265
2266 <programlisting role="C">
2267 GtkWidget *gtk_toggle_button_new( void );
2268
2269 GtkWidget *gtk_toggle_button_new_with_label( const gchar *label );
2270
2271 GtkWidget *gtk_toggle_button_new_with_mnemonic( const gchar *label );
2272 </programlisting>
2273
2274 <para>As you can imagine, these work identically to the normal button widget
2275 calls. The first creates a blank toggle button, and the last two, a
2276 button with a label widget already packed into it. The _mnemonic() variant
2277 additionally parses the label for '_'-prefixed mnemonic characters.</para>
2278
2279 <para>To retrieve the state of the toggle widget, including radio and check
2280 buttons, we use a construct as shown in our example below. This tests
2281 the state of the toggle button, by accessing the <literal>active</literal> field of the
2282 toggle widget's structure, after first using the
2283 <literal>GTK_TOGGLE_BUTTON</literal> macro to cast the widget pointer into a toggle
2284 widget pointer. The signal of interest to us emitted by toggle
2285 buttons (the toggle button, check button, and radio button widgets) is
2286 the "toggled" signal. To check the state of these buttons, set up a
2287 signal handler to catch the toggled signal, and access the structure
2288 to determine its state. The callback will look something like:</para>
2289
2290 <programlisting role="C">
2291 void toggle_button_callback (GtkWidget *widget, gpointer data)
2292 {
2293     if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) 
2294     {
2295         /* If control reaches here, the toggle button is down */
2296     
2297     } else {
2298     
2299         /* If control reaches here, the toggle button is up */
2300     }
2301 }
2302 </programlisting>
2303
2304 <para>To force the state of a toggle button, and its children, the radio and
2305 check buttons, use this function:</para>
2306
2307 <programlisting role="C">
2308 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2309                                    gboolean        is_active );
2310 </programlisting>
2311
2312 <para>The above call can be used to set the state of the toggle button, and
2313 its children the radio and check buttons. Passing in your created
2314 button as the first argument, and a TRUE or FALSE for the second state
2315 argument to specify whether it should be down (depressed) or up
2316 (released). Default is up, or FALSE.</para>
2317
2318 <para>Note that when you use the gtk_toggle_button_set_active() function, and
2319 the state is actually changed, it causes the "clicked" and "toggled"
2320 signals to be emitted from the button.</para>
2321
2322 <programlisting role="C">
2323 gboolean gtk_toggle_button_get_active   (GtkToggleButton *toggle_button);
2324 </programlisting>
2325
2326 <para>This returns the current state of the toggle button as a boolean
2327 TRUE/FALSE value.</para>
2328
2329 </sect1>
2330
2331 <!-- ----------------------------------------------------------------- -->
2332 <sect1 id="sec-CheckButtons">
2333 <title>Check Buttons</title>
2334
2335 <para>Check buttons inherit many properties and functions from the the
2336 toggle buttons above, but look a little different. Rather than being
2337 buttons with text inside them, they are small squares with the text to
2338 the right of them. These are often used for toggling options on and
2339 off in applications.</para>
2340
2341 <para>The creation functions are similar to those of the normal button.</para>
2342
2343 <programlisting role="C">
2344 GtkWidget *gtk_check_button_new( void );
2345
2346 GtkWidget *gtk_check_button_new_with_label ( const gchar *label );
2347
2348 GtkWidget *gtk_check_button_new_with_mnemonic ( const gchar *label );
2349 </programlisting>
2350
2351 <para>The gtk_check_button_new_with_label() function creates a check button 
2352 with a label beside it.</para>
2353
2354 <para>Checking the state of the check button is identical to that of the
2355 toggle button.</para>
2356
2357 </sect1>
2358
2359 <!-- ----------------------------------------------------------------- -->
2360 <sect1 id="sec-RadioButtons">
2361 <title>Radio Buttons</title>
2362
2363 <para>Radio buttons are similar to check buttons except they are grouped so
2364 that only one may be selected/depressed at a time. This is good for
2365 places in your application where you need to select from a short list
2366 of options.</para>
2367
2368 <para>Creating a new radio button is done with one of these calls:</para>
2369
2370 <programlisting role="C">
2371 GtkWidget *gtk_radio_button_new( GSList *group );
2372
2373 GtkWidget *gtk_radio_button_new_from_widget( GtkRadioButton *group );
2374
2375 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
2376                                             const gchar  *label );
2377
2378 GtkWidget* gtk_radio_button_new_with_label_from_widget( GtkRadioButton *group,
2379                                                         const gchar    *label );
2380
2381 GtkWidget *gtk_radio_button_new_with_mnemonic( GSList *group,
2382                                                const gchar  *label );
2383
2384 GtkWidget *gtk_radio_button_new_with_mnemonic_from_widget( GtkRadioButton *group,
2385                                                            const gchar  *label );
2386
2387 </programlisting>
2388
2389 <para>You'll notice the extra argument to these calls. They require a group
2390 to perform their duty properly. The first call to gtk_radio_button_new() or 
2391 gtk_radio_button_new_with_label() should pass NULL as the first argument. 
2392 Then create a group using:</para>
2393
2394 <programlisting role="C">
2395 GSList *gtk_radio_button_get_group( GtkRadioButton *radio_button );
2396 </programlisting>
2397
2398 <para>The important thing to remember is that gtk_radio_button_get_group() must be
2399 called for each new button added to the group, with the previous button passed 
2400 in as an argument. The result is then passed into the next call to 
2401 gtk_radio_button_new() or gtk_radio_button_new_with_label(). This allows a
2402 chain of buttons to be established. The example below should make this clear.</para>
2403
2404 <para>You can shorten this slightly by using the following syntax, which
2405 removes the need for a variable to hold the list of buttons:</para>
2406
2407 <programlisting role="C">
2408      button2 = gtk_radio_button_new_with_label(
2409                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button1)),
2410                  "button2");
2411 </programlisting>
2412
2413 <para>
2414 The _from_widget() variants of the creation functions allow you to shorten this
2415 further, by omitting the gtk_radio_button_get_group() call. This form is used 
2416 in the example to create the third button:
2417 </para>
2418
2419 <programlisting role="C">
2420      button2 = gtk_radio_button_new_with_label_from_widget(
2421                  GTK_RADIO_BUTTON (button1), 
2422                  "button2");
2423 </programlisting>
2424
2425 <para>It is also a good idea to explicitly set which button should be the
2426 default depressed button with:</para>
2427
2428 <programlisting role="C">
2429 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2430                                    gboolean        state );
2431 </programlisting>
2432
2433 <para>This is described in the section on toggle buttons, and works in
2434 exactly the same way.  Once the radio buttons are grouped together,
2435 only one of the group may be active at a time. If the user clicks on
2436 one radio button, and then on another, the first radio button will
2437 first emit a "toggled" signal (to report becoming inactive), and then
2438 the second will emit its "toggled" signal (to report becoming active).</para>
2439
2440 <para>The following example creates a radio button group with three buttons.</para>
2441
2442 <para>
2443 <inlinemediaobject>
2444 <imageobject>
2445 <imagedata fileref="images/radiobuttons.png" format="png">
2446 </imageobject>
2447 </inlinemediaobject>
2448 </para>
2449
2450 <programlisting role="C">
2451 <!-- example-start radiobuttons radiobuttons.c -->
2452
2453 #include &lt;glib.h&gt;
2454 #include &lt;gtk/gtk.h&gt;
2455
2456 static gboolean close_application( GtkWidget *widget,
2457                                    GdkEvent  *event,
2458                                    gpointer   data )
2459 {
2460   gtk_main_quit ();
2461   return FALSE;
2462 }
2463
2464 int main( int   argc,
2465           char *argv[] )
2466 {
2467     GtkWidget *window = NULL;
2468     GtkWidget *box1;
2469     GtkWidget *box2;
2470     GtkWidget *button;
2471     GtkWidget *separator;
2472     GSList *group;
2473   
2474     gtk_init (&amp;argc, &amp;argv);    
2475       
2476     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2477   
2478     g_signal_connect (G_OBJECT (window), "delete_event",
2479                       G_CALLBACK (close_application),
2480                       NULL);
2481
2482     gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
2483     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2484
2485     box1 = gtk_vbox_new (FALSE, 0);
2486     gtk_container_add (GTK_CONTAINER (window), box1);
2487     gtk_widget_show (box1);
2488
2489     box2 = gtk_vbox_new (FALSE, 10);
2490     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2491     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2492     gtk_widget_show (box2);
2493
2494     button = gtk_radio_button_new_with_label (NULL, "button1");
2495     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2496     gtk_widget_show (button);
2497
2498     group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
2499     button = gtk_radio_button_new_with_label (group, "button2");
2500     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2501     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2502     gtk_widget_show (button);
2503
2504     button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (button),
2505                                                           "button3");
2506     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2507     gtk_widget_show (button);
2508
2509     separator = gtk_hseparator_new ();
2510     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2511     gtk_widget_show (separator);
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, FALSE, TRUE, 0);
2516     gtk_widget_show (box2);
2517
2518     button = gtk_button_new_with_label ("close");
2519     g_signal_connect_swapped (G_OBJECT (button), "clicked",
2520                               G_CALLBACK (close_application),
2521                               G_OBJECT (window));
2522     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2523     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2524     gtk_widget_grab_default (button);
2525     gtk_widget_show (button);
2526     gtk_widget_show (window);
2527      
2528     gtk_main ();
2529
2530     return 0;
2531 }
2532 <!-- example-end -->
2533 </programlisting>
2534
2535 </sect1>
2536 </chapter>
2537
2538 <!-- ***************************************************************** -->
2539 <chapter id="ch-Adjustments">
2540 <title>Adjustments</title>
2541
2542 <para>GTK has various widgets that can be visually adjusted by the user
2543 using the mouse or the keyboard, such as the range widgets, described
2544 in the <link linkend="ch-RangeWidgets">Range Widgets</link>
2545 section. There are also a few widgets that display some adjustable
2546 portion of a larger area of data, such as the text widget and the
2547 viewport widget.</para>
2548
2549 <para>Obviously, an application needs to be able to react to changes the
2550 user makes in range widgets. One way to do this would be to have each
2551 widget emit its own type of signal when its adjustment changes, and
2552 either pass the new value to the signal handler, or require it to look
2553 inside the widget's data structure in order to ascertain the value.
2554 But you may also want to connect the adjustments of several widgets
2555 together, so that adjusting one adjusts the others. The most obvious
2556 example of this is connecting a scrollbar to a panning viewport or a
2557 scrolling text area. If each widget has its own way of setting or
2558 getting the adjustment value, then the programmer may have to write
2559 their own signal handlers to translate between the output of one
2560 widget's signal and the "input" of another's adjustment setting
2561 function.</para>
2562
2563 <para>GTK solves this problem using the Adjustment object, which is not a
2564 widget but a way for widgets to store and pass adjustment information
2565 in an abstract and flexible form. The most obvious use of Adjustment
2566 is to store the configuration parameters and values of range widgets,
2567 such as scrollbars and scale controls. However, since Adjustments are
2568 derived from Object, they have some special powers beyond those of
2569 normal data structures. Most importantly, they can emit signals, just
2570 like widgets, and these signals can be used not only to allow your
2571 program to react to user input on adjustable widgets, but also to
2572 propagate adjustment values transparently between adjustable widgets.</para>
2573
2574 <para>You will see how adjustments fit in when you see the other widgets
2575 that incorporate them:
2576 <link linkend="sec-ProgressBars">Progress Bars</link>,
2577 <link linkend="sec-Viewports">Viewports</link>,
2578 <link linkend="sec-ScrolledWindows">Scrolled Windows</link>, and others.</para>
2579
2580 <!-- ----------------------------------------------------------------- -->
2581 <sect1 id="sec-CreatingAnAdjustment">
2582 <title>Creating an Adjustment</title>
2583
2584 <para>Many of the widgets which use adjustment objects do so automatically,
2585 but some cases will be shown in later examples where you may need to
2586 create one yourself. You create an adjustment using:</para>
2587
2588 <programlisting role="C">
2589 GtkObject *gtk_adjustment_new( gdouble value,
2590                                gdouble lower,
2591                                gdouble upper,
2592                                gdouble step_increment,
2593                                gdouble page_increment,
2594                                gdouble page_size );
2595 </programlisting>
2596
2597 <para>The <literal>value</literal> argument is the initial value you want to give to the
2598 adjustment, usually corresponding to the topmost or leftmost position
2599 of an adjustable widget. The <literal>lower</literal> argument specifies the lowest
2600 value which the adjustment can hold. The <literal>step_increment</literal> argument
2601 specifies the "smaller" of the two increments by which the user can
2602 change the value, while the <literal>page_increment</literal> is the "larger" one.
2603 The <literal>page_size</literal> argument usually corresponds somehow to the visible
2604 area of a panning widget. The <literal>upper</literal> argument is used to represent
2605 the bottom most or right most coordinate in a panning widget's
2606 child. Therefore it is <emphasis>not</emphasis> always the largest number that
2607 <literal>value</literal> can take, since the <literal>page_size</literal> of such widgets is
2608 usually non-zero.</para>
2609
2610 </sect1>
2611
2612 <!-- ----------------------------------------------------------------- -->
2613 <sect1 id="sec-UsingAdjustments">
2614 <title>Using Adjustments the Easy Way</title>
2615
2616 <para>The adjustable widgets can be roughly divided into those which use and
2617 require specific units for these values and those which treat them as
2618 arbitrary numbers. The group which treats the values as arbitrary
2619 numbers includes the range widgets (scrollbars and scales, the
2620 progress bar widget, and the spin button widget). These widgets are
2621 all the widgets which are typically "adjusted" directly by the user
2622 with the mouse or keyboard. They will treat the <literal>lower</literal> and
2623 <literal>upper</literal> values of an adjustment as a range within which the user
2624 can manipulate the adjustment's <literal>value</literal>. By default, they will only
2625 modify the <literal>value</literal> of an adjustment.</para>
2626
2627 <para>The other group includes the text widget, the viewport widget, the
2628 compound list widget, and the scrolled window widget. All of these
2629 widgets use pixel values for their adjustments. These are also all
2630 widgets which are typically "adjusted" indirectly using scrollbars.
2631 While all widgets which use adjustments can either create their own
2632 adjustments or use ones you supply, you'll generally want to let this
2633 particular category of widgets create its own adjustments. Usually,
2634 they will eventually override all the values except the <literal>value</literal>
2635 itself in whatever adjustments you give them, but the results are, in
2636 general, undefined (meaning, you'll have to read the source code to
2637 find out, and it may be different from widget to widget).</para>
2638
2639 <para>Now, you're probably thinking, since text widgets and viewports insist
2640 on setting everything except the <literal>value</literal> of their adjustments,
2641 while scrollbars will <emphasis>only</emphasis> touch the adjustment's 
2642 <literal>value</literal>, if you <emphasis>share</emphasis> an adjustment
2643 object between a scrollbar and a text widget, manipulating the scrollbar will 
2644 automagically adjust the viewport widget?  Of course it will! Just like this:</para>
2645
2646 <programlisting role="C">
2647   /* creates its own adjustments */
2648   viewport = gtk_viewport_new (NULL, NULL);
2649   /* uses the newly-created adjustment for the scrollbar as well */
2650   vscrollbar = gtk_vscrollbar_new (gtk_viewport_get_vadjustment (viewport));
2651 </programlisting>
2652
2653 </sect1>
2654
2655 <!-- ----------------------------------------------------------------- -->
2656 <sect1 id="sec-AdjustmentInternals">
2657 <title>Adjustment Internals</title>
2658
2659 <para>Ok, you say, that's nice, but what if I want to create my own handlers
2660 to respond when the user adjusts a range widget or a spin button, and
2661 how do I get at the value of the adjustment in these handlers?  To
2662 answer these questions and more, let's start by taking a look at
2663 <literal>struct _GtkAdjustment</literal> itself:</para>
2664
2665 <programlisting role="C">
2666 struct _GtkAdjustment
2667 {
2668   GtkObject parent_instance;
2669   
2670   gdouble lower;
2671   gdouble upper;
2672   gdouble value;
2673   gdouble step_increment;
2674   gdouble page_increment;
2675   gdouble page_size;
2676 };
2677 </programlisting>
2678
2679 <para>If you don't like to poke directly at struct internals like a 
2680 <emphasis>real</emphasis> C programmer, you can use the following accessor to
2681 inspect the <literal>value</literal> of an adjustment:</para>
2682
2683 <programlisting role="C">
2684 gdouble gtk_adjustment_get_value( GtkAdjustment *adjustment);
2685 </programlisting>
2686
2687 <para>Since, when you set the <literal>value</literal> of an Adjustment, you generally
2688 want the change to be reflected by every widget that uses this
2689 adjustment, GTK provides this convenience function to do this:</para>
2690
2691 <programlisting role="C">
2692 void gtk_adjustment_set_value( GtkAdjustment *adjustment,
2693                                gdouble       value );
2694 </programlisting>
2695
2696 <para>As mentioned earlier, Adjustment is a subclass of Object just
2697 like all the various widgets, and thus it is able to emit signals.
2698 This is, of course, why updates happen automagically when you share an
2699 adjustment object between a scrollbar and another adjustable widget;
2700 all adjustable widgets connect signal handlers to their adjustment's
2701 <literal>value_changed</literal> signal, as can your program. Here's the definition
2702 of this signal in <literal>struct _GtkAdjustmentClass</literal>:</para>
2703
2704 <programlisting role="C">
2705   void (* value_changed) (GtkAdjustment *adjustment);
2706 </programlisting>
2707
2708 <para>The various widgets that use the Adjustment object will emit this
2709 signal on an adjustment whenever they change its value. This happens
2710 both when user input causes the slider to move on a range widget, as
2711 well as when the program explicitly changes the value with
2712 gtk_adjustment_set_value(). So, for example, if you have a scale
2713 widget, and you want to change the rotation of a picture whenever its
2714 value changes, you would create a callback like this:</para>
2715
2716 <programlisting role="C">
2717 void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
2718 {
2719   set_picture_rotation (picture, gtk_adjustment_get_value (adj));
2720 ...
2721 </programlisting>
2722
2723 <para>and connect it to the scale widget's adjustment like this:</para>
2724
2725 <programlisting role="C">
2726 g_signal_connect (G_OBJECT (adj), "value_changed",
2727                   G_CALLBACK (cb_rotate_picture), (gpointer) picture);
2728 </programlisting>
2729
2730 <para>What about when a widget reconfigures the <literal>upper</literal> or <literal>lower</literal>
2731 fields of its adjustment, such as when a user adds more text to a text
2732 widget?  In this case, it emits the <literal>changed</literal> signal, which looks
2733 like this:</para>
2734
2735 <programlisting role="C">
2736   void (* changed) (GtkAdjustment *adjustment);
2737 </programlisting>
2738
2739 <para>Range widgets typically connect a handler to this signal, which
2740 changes their appearance to reflect the change - for example, the size
2741 of the slider in a scrollbar will grow or shrink in inverse proportion
2742 to the difference between the <literal>lower</literal> and <literal>upper</literal> values of its
2743 adjustment.</para>
2744
2745 <para>You probably won't ever need to attach a handler to this signal,
2746 unless you're writing a new type of range widget.  However, if you
2747 change any of the values in a Adjustment directly, you should emit
2748 this signal on it to reconfigure whatever widgets are using it, like
2749 this:</para>
2750
2751 <programlisting role="C">
2752 g_signal_emit_by_name (G_OBJECT (adjustment), "changed");
2753 </programlisting>
2754
2755 <para>Now go forth and adjust!</para>
2756
2757 </sect1>
2758 </chapter>
2759
2760 <!-- ***************************************************************** -->
2761 <chapter id="ch-RangeWidgets">
2762 <title>Range Widgets</title>
2763
2764 <para>The category of range widgets includes the ubiquitous scrollbar widget
2765 and the less common scale widget. Though these two types of widgets
2766 are generally used for different purposes, they are quite similar in
2767 function and implementation. All range widgets share a set of common
2768 graphic elements, each of which has its own X window and receives
2769 events. They all contain a "trough" and a "slider" (what is sometimes
2770 called a "thumbwheel" in other GUI environments). Dragging the slider
2771 with the pointer moves it back and forth within the trough, while
2772 clicking in the trough advances the slider towards the location of the
2773 click, either completely, or by a designated amount, depending on
2774 which mouse button is used.</para>
2775
2776 <para>As mentioned in <link linkend="ch-Adjustments">Adjustments</link> above,
2777 all range widgets are associated with an adjustment object, from which
2778 they calculate the length of the slider and its position within the
2779 trough. When the user manipulates the slider, the range widget will
2780 change the value of the adjustment.</para>
2781
2782 <!-- ----------------------------------------------------------------- -->
2783 <sect1 id="sec-ScrollbarWidgets">
2784 <title>Scrollbar Widgets</title>
2785
2786 <para>These are your standard, run-of-the-mill scrollbars. These should be
2787 used only for scrolling some other widget, such as a list, a text box,
2788 or a viewport (and it's generally easier to use the scrolled window
2789 widget in most cases).  For other purposes, you should use scale
2790 widgets, as they are friendlier and more featureful.</para>
2791
2792 <para>There are separate types for horizontal and vertical scrollbars.
2793 There really isn't much to say about these. You create them with the
2794 following functions:</para>
2795
2796 <programlisting role="C">
2797 GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );
2798
2799 GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );
2800 </programlisting>
2801
2802 <para>and that's about it (if you don't believe me, look in the header
2803 files!).  The <literal>adjustment</literal> argument can either be a pointer to an
2804 existing Adjustment, or NULL, in which case one will be created for
2805 you. Specifying NULL might actually be useful in this case, if you
2806 wish to pass the newly-created adjustment to the constructor function
2807 of some other widget which will configure it for you, such as a text
2808 widget.</para>
2809
2810 </sect1>
2811
2812 <!-- ----------------------------------------------------------------- -->
2813 <sect1 id="sec-ScaleWidgets">
2814 <title>Scale Widgets</title>
2815
2816 <para>Scale widgets are used to allow the user to visually select and
2817 manipulate a value within a specific range. You might want to use a
2818 scale widget, for example, to adjust the magnification level on a
2819 zoomed preview of a picture, or to control the brightness of a color,
2820 or to specify the number of minutes of inactivity before a screensaver
2821 takes over the screen.</para>
2822
2823 <!-- ----------------------------------------------------------------- -->
2824 <sect2>
2825 <title>Creating a Scale Widget</title>
2826
2827 <para>As with scrollbars, there are separate widget types for horizontal and
2828 vertical scale widgets. (Most programmers seem to favour horizontal
2829 scale widgets.) Since they work essentially the same way, there's no
2830 need to treat them separately here. The following functions create vertical and 
2831 horizontal scale widgets, respectively:</para>
2832
2833 <programlisting role="C">
2834 GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );
2835
2836 GtkWidget *gtk_vscale_new_with_range( gdouble min,
2837                                       gdouble max,
2838                                       gdouble step );
2839
2840 GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );
2841
2842 GtkWidget *gtk_hscale_new_with_range( gdouble min,
2843                                       gdouble max,
2844                                       gdouble step );
2845 </programlisting>
2846
2847 <para>The <literal>adjustment</literal> argument can either be an adjustment which has
2848 already been created with gtk_adjustment_new(), or NULL, in
2849 which case, an anonymous Adjustment is created with all of its
2850 values set to <literal>0.0</literal> (which isn't very useful in this case). 
2851 In order to avoid confusing yourself, you probably want to create your
2852 adjustment with a <literal>page_size</literal> of <literal>0.0</literal> so 
2853 that its <literal>upper</literal> value actually corresponds to the highest 
2854 value the user can select. The _new_with_range()�variants take care of creating
2855 a suitable adjustment. (If you're <emphasis>already</emphasis> thoroughly
2856 confused, read the section on <link linkend="ch-Adjustments">Adjustments</link> 
2857 again for an explanation of what exactly adjustments do and how to create and 
2858 manipulate them.)</para>
2859
2860 </sect2>
2861
2862 <!-- ----------------------------------------------------------------- -->
2863 <sect2>
2864 <title>Functions and Signals (well, functions, at least)</title>
2865
2866 <para>Scale widgets can display their current value as a number beside the
2867 trough. The default behaviour is to show the value, but you can change
2868 this with this function:</para>
2869
2870 <programlisting role="C">
2871 void gtk_scale_set_draw_value( GtkScale *scale,
2872                                gboolean draw_value );
2873 </programlisting>
2874
2875 <para>As you might have guessed, <literal>draw_value</literal> is either <literal>TRUE</literal> or
2876 <literal>FALSE</literal>, with predictable consequences for either one.</para>
2877
2878 <para>The value displayed by a scale widget is rounded to one decimal point
2879 by default, as is the <literal>value</literal> field in its Adjustment. You can
2880 change this with:</para>
2881
2882 <programlisting role="C">
2883 void gtk_scale_set_digits( GtkScale *scale,
2884                             gint     digits );
2885 </programlisting>
2886
2887 <para>where <literal>digits</literal> is the number of decimal places you want. You can
2888 set <literal>digits</literal> to anything you like, but no more than 13 decimal
2889 places will actually be drawn on screen.</para>
2890
2891 <para>Finally, the value can be drawn in different positions
2892 relative to the trough:</para>
2893
2894 <programlisting role="C">
2895 void gtk_scale_set_value_pos( GtkScale        *scale,
2896                               GtkPositionType  pos );
2897 </programlisting>
2898
2899 <para>The argument <literal>pos</literal> is of type <literal>GtkPositionType</literal>,
2900 which can take one of the following values:</para>
2901
2902 <programlisting role="C">
2903   GTK_POS_LEFT
2904   GTK_POS_RIGHT
2905   GTK_POS_TOP
2906   GTK_POS_BOTTOM
2907 </programlisting>
2908
2909 <para>If you position the value on the "side" of the trough (e.g., on the
2910 top or bottom of a horizontal scale widget), then it will follow the
2911 slider up and down the trough.</para>
2912
2913 <para>All the preceding functions are defined in
2914 <literal>&lt;gtk/gtkscale.h&gt;</literal>. The header files for all GTK widgets
2915 are automatically included when you include
2916 <literal>&lt;gtk/gtk.h&gt;</literal>. But you should look over the header files
2917 of all widgets that interest you, in order to learn more about their functions
2918 and features.</para>
2919
2920 </sect2>
2921 </sect1>
2922
2923 <!-- ----------------------------------------------------------------- -->
2924 <sect1 id="sec-CommonRangeFunctions">
2925 <title>Common Range Functions</title>
2926
2927 <para>The Range widget class is fairly complicated internally, but, like
2928 all the "base class" widgets, most of its complexity is only
2929 interesting if you want to hack on it. Also, almost all of the
2930 functions and signals it defines are only really used in writing
2931 derived widgets. There are, however, a few useful functions that are
2932 defined in <literal>&lt;gtk/gtkrange.h&gt;</literal> and will work on all range
2933 widgets.</para>
2934
2935 <!-- ----------------------------------------------------------------- -->
2936 <sect2>
2937 <title>Setting the Update Policy</title>
2938
2939 <para>The "update policy" of a range widget defines at what points during
2940 user interaction it will change the <literal>value</literal> field of its
2941 Adjustment and emit the "value_changed" signal on this
2942 Adjustment. The update policies, defined in
2943 <literal>&lt;gtk/gtkenums.h&gt;</literal> as type <literal>enum GtkUpdateType</literal>,
2944 are:</para>
2945
2946 <variablelist>
2947 <varlistentry>
2948 <term><literal>GTK_UPDATE_CONTINUOUS</literal></term>
2949 <listitem><para>This is the default. The
2950 "value_changed" signal is emitted continuously, i.e., whenever the
2951 slider is moved by even the tiniest amount.</para>
2952 </listitem>
2953 </varlistentry>
2954 <varlistentry>
2955 <term><literal>GTK_UPDATE_DISCONTINUOUS</literal></term>
2956 <listitem><para>The "value_changed" signal is
2957 only emitted once the slider has stopped moving and the user has
2958 released the mouse button.</para>
2959 </listitem>
2960 </varlistentry>
2961 <varlistentry>
2962 <term><literal>GTK_UPDATE_DELAYED</literal></term>
2963 <listitem><para>The "value_changed" signal is emitted
2964 when the user releases the mouse button, or if the slider stops moving
2965 for a short period of time.</para>
2966 </listitem>
2967 </varlistentry>
2968 </variablelist>
2969
2970 <para>The update policy of a range widget can be set by casting it using the
2971 <literal>GTK_RANGE(widget)</literal> macro and passing it to this function:</para>
2972
2973 <programlisting role="C">
2974 void gtk_range_set_update_policy( GtkRange      *range,
2975                                   GtkUpdateType  policy);
2976 </programlisting>
2977
2978 </sect2>
2979
2980 <!-- ----------------------------------------------------------------- -->
2981 <sect2>
2982 <title>Getting and Setting Adjustments</title>
2983
2984 <para>Getting and setting the adjustment for a range widget "on the fly" is
2985 done, predictably, with:</para>
2986
2987 <programlisting role="C">
2988 GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );
2989
2990 void gtk_range_set_adjustment( GtkRange      *range,
2991                                GtkAdjustment *adjustment );
2992 </programlisting>
2993
2994 <para><literal>gtk_range_get_adjustment()</literal> returns a pointer to the adjustment to
2995 which <literal>range</literal> is connected.</para>
2996
2997 <para><literal>gtk_range_set_adjustment()</literal> does absolutely nothing if you pass it
2998 the adjustment that <literal>range</literal> is already using, regardless of whether
2999 you changed any of its fields or not. If you pass it a new
3000 Adjustment, it will unreference the old one if it exists (possibly
3001 destroying it), connect the appropriate signals to the new one, and
3002 call the private function <literal>gtk_range_adjustment_changed()</literal>, which
3003 will (or at least, is supposed to...) recalculate the size and/or
3004 position of the slider and redraw if necessary. As mentioned in the
3005 section on adjustments, if you wish to reuse the same Adjustment,
3006 when you modify its values directly, you should emit the "changed"
3007 signal on it, like this:</para>
3008
3009 <programlisting role="C">
3010 g_signal_emit_by_name (G_OBJECT (adjustment), "changed");
3011 </programlisting>
3012
3013 </sect2>
3014 </sect1>
3015
3016 <!-- ----------------------------------------------------------------- -->
3017 <sect1 id="sec-KeyAndMouseBindings">
3018 <title>Key and Mouse bindings</title>
3019
3020 <para>All of the GTK range widgets react to mouse clicks in more or less
3021 the same way. Clicking button-1 in the trough will cause its
3022 adjustment's <literal>page_increment</literal> to be added or subtracted from its
3023 <literal>value</literal>, and the slider to be moved accordingly. Clicking mouse
3024 button-2 in the trough will jump the slider to the point at which the
3025 button was clicked. Clicking button-3 in the trough of a range or any button on 
3026 a scrollbar's arrows will cause its adjustment's value to change by
3027 <literal>step_increment</literal> at a time.</para>
3028
3029 <para>Scrollbars are not focusable, thus have no key bindings. The key bindings
3030 for the other range widgets (which are, of course, only active when the widget 
3031 has focus) are do <emphasis>not</emphasis> differentiate between horizontal and 
3032 vertical range widgets.</para>
3033
3034 <para>All range widgets can be operated with the left, right, up and down arrow
3035 keys, as well as with the <literal>Page Up</literal> and <literal>Page Down</literal> 
3036 keys. The arrows move the slider up and down by <literal>step_increment</literal>, while
3037 <literal>Page Up</literal> and <literal>Page Down</literal> move it by 
3038 <literal>page_increment</literal>.</para>
3039
3040 <para>The user can also move the slider all the way to one end or the other
3041 of the trough using the keyboard. This is done with the <literal>Home</literal> 
3042 and <literal>End</literal> keys.</para>
3043
3044 </sect1>
3045
3046 <!-- ----------------------------------------------------------------- -->
3047 <sect1 id="sec-RangeWidgetsExample">
3048 <title>Example</title>
3049
3050 <para>This example is a somewhat modified version of the "range controls"
3051 test from <filename>testgtk.c</filename>. It basically puts up a window with three
3052 range widgets all connected to the same adjustment, and a couple of
3053 controls for adjusting some of the parameters mentioned above and in
3054 the section on adjustments, so you can see how they affect the way
3055 these widgets work for the user.</para>
3056
3057 <para>
3058 <inlinemediaobject>
3059 <imageobject>
3060 <imagedata fileref="images/rangewidgets.png" format="png">
3061 </imageobject>
3062 </inlinemediaobject>
3063 </para>
3064
3065 <programlisting role="C">
3066 <!-- example-start rangewidgets rangewidgets.c -->
3067
3068 #include &lt;gtk/gtk.h&gt;
3069
3070 GtkWidget *hscale, *vscale;
3071
3072 static void cb_pos_menu_select( GtkWidget       *item,
3073                                 GtkPositionType  pos )
3074 {
3075     /* Set the value position on both scale widgets */
3076     gtk_scale_set_value_pos (GTK_SCALE (hscale), pos);
3077     gtk_scale_set_value_pos (GTK_SCALE (vscale), pos);
3078 }
3079
3080 static void cb_update_menu_select( GtkWidget     *item,
3081                                    GtkUpdateType  policy )
3082 {
3083     /* Set the update policy for both scale widgets */
3084     gtk_range_set_update_policy (GTK_RANGE (hscale), policy);
3085     gtk_range_set_update_policy (GTK_RANGE (vscale), policy);
3086 }
3087
3088 static void cb_digits_scale( GtkAdjustment *adj )
3089 {
3090     /* Set the number of decimal places to which adj->value is rounded */
3091     gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
3092     gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
3093 }
3094
3095 static void cb_page_size( GtkAdjustment *get,
3096                           GtkAdjustment *set )
3097 {
3098     /* Set the page size and page increment size of the sample
3099      * adjustment to the value specified by the "Page Size" scale */
3100     set->page_size = get->value;
3101     set->page_increment = get->value;
3102
3103     /* This sets the adjustment and makes it emit the "changed" signal to 
3104        reconfigure all the widgets that are attached to this signal.  */
3105     gtk_adjustment_set_value (set, CLAMP (set->value,
3106                                           set->lower,
3107                                           (set->upper - set->page_size)));
3108     g_signal_emit_by_name(G_OBJECT(set), "changed");
3109 }
3110
3111 static void cb_draw_value( GtkToggleButton *button )
3112 {
3113     /* Turn the value display on the scale widgets off or on depending
3114      *  on the state of the checkbutton */
3115     gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active);
3116     gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active);  
3117 }
3118
3119 /* Convenience functions */
3120
3121 static GtkWidget *make_menu_item ( gchar     *name,
3122                                    GCallback  callback,
3123                                    gpointer   data )
3124 {
3125     GtkWidget *item;
3126   
3127     item = gtk_menu_item_new_with_label (name);
3128     g_signal_connect (G_OBJECT (item), "activate",
3129                       callback, (gpointer) data);
3130     gtk_widget_show (item);
3131
3132     return item;
3133 }
3134
3135 static void scale_set_default_values( GtkScale *scale )
3136 {
3137     gtk_range_set_update_policy (GTK_RANGE (scale),
3138                                  GTK_UPDATE_CONTINUOUS);
3139     gtk_scale_set_digits (scale, 1);
3140     gtk_scale_set_value_pos (scale, GTK_POS_TOP);
3141     gtk_scale_set_draw_value (scale, TRUE);
3142 }
3143
3144 /* makes the sample window */
3145
3146 static void create_range_controls( void )
3147 {
3148     GtkWidget *window;
3149     GtkWidget *box1, *box2, *box3;
3150     GtkWidget *button;
3151     GtkWidget *scrollbar;
3152     GtkWidget *separator;
3153     GtkWidget *opt, *menu, *item;
3154     GtkWidget *label;
3155     GtkWidget *scale;
3156     GtkObject *adj1, *adj2;
3157
3158     /* Standard window-creating stuff */
3159     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3160     g_signal_connect (G_OBJECT (window), "destroy",
3161                       G_CALLBACK (gtk_main_quit),
3162                       NULL);
3163     gtk_window_set_title (GTK_WINDOW (window), "range controls");
3164
3165     box1 = gtk_vbox_new (FALSE, 0);
3166     gtk_container_add (GTK_CONTAINER (window), box1);
3167     gtk_widget_show (box1);
3168
3169     box2 = gtk_hbox_new (FALSE, 10);
3170     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3171     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3172     gtk_widget_show (box2);
3173
3174     /* value, lower, upper, step_increment, page_increment, page_size */
3175     /* Note that the page_size value only makes a difference for
3176      * scrollbar widgets, and the highest value you'll get is actually
3177      * (upper - page_size). */
3178     adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
3179   
3180     vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1));
3181     scale_set_default_values (GTK_SCALE (vscale));
3182     gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0);
3183     gtk_widget_show (vscale);
3184
3185     box3 = gtk_vbox_new (FALSE, 10);
3186     gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0);
3187     gtk_widget_show (box3);
3188
3189     /* Reuse the same adjustment */
3190     hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1));
3191     gtk_widget_set_size_request (GTK_WIDGET (hscale), 200, -1);
3192     scale_set_default_values (GTK_SCALE (hscale));
3193     gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0);
3194     gtk_widget_show (hscale);
3195
3196     /* Reuse the same adjustment again */
3197     scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1));
3198     /* Notice how this causes the scales to always be updated
3199      * continuously when the scrollbar is moved */
3200     gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
3201                                  GTK_UPDATE_CONTINUOUS);
3202     gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0);
3203     gtk_widget_show (scrollbar);
3204
3205     box2 = gtk_hbox_new (FALSE, 10);
3206     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3207     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3208     gtk_widget_show (box2);
3209
3210     /* A checkbutton to control whether the value is displayed or not */
3211     button = gtk_check_button_new_with_label("Display value on scale widgets");
3212     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
3213     g_signal_connect (G_OBJECT (button), "toggled",
3214                       G_CALLBACK (cb_draw_value), NULL);
3215     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3216     gtk_widget_show (button);
3217   
3218     box2 = gtk_hbox_new (FALSE, 10);
3219     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3220
3221     /* An option menu to change the position of the value */
3222     label = gtk_label_new ("Scale Value Position:");
3223     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3224     gtk_widget_show (label);
3225   
3226     opt = gtk_option_menu_new ();
3227     menu = gtk_menu_new ();
3228
3229     item = make_menu_item ("Top",
3230                            G_CALLBACK (cb_pos_menu_select),
3231                            GINT_TO_POINTER (GTK_POS_TOP));
3232     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3233   
3234     item = make_menu_item ("Bottom", G_CALLBACK (cb_pos_menu_select), 
3235                            GINT_TO_POINTER (GTK_POS_BOTTOM));
3236     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3237   
3238     item = make_menu_item ("Left", G_CALLBACK (cb_pos_menu_select),
3239                            GINT_TO_POINTER (GTK_POS_LEFT));
3240     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3241   
3242     item = make_menu_item ("Right", G_CALLBACK (cb_pos_menu_select),
3243                            GINT_TO_POINTER (GTK_POS_RIGHT));
3244     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3245   
3246     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
3247     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
3248     gtk_widget_show (opt);
3249
3250     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3251     gtk_widget_show (box2);
3252
3253     box2 = gtk_hbox_new (FALSE, 10);
3254     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3255
3256     /* Yet another option menu, this time for the update policy of the
3257      * scale widgets */
3258     label = gtk_label_new ("Scale Update Policy:");
3259     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3260     gtk_widget_show (label);
3261   
3262     opt = gtk_option_menu_new ();
3263     menu = gtk_menu_new ();
3264   
3265     item = make_menu_item ("Continuous",
3266                            G_CALLBACK (cb_update_menu_select),
3267                            GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS));
3268     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3269   
3270     item = make_menu_item ("Discontinuous",
3271                            G_CALLBACK (cb_update_menu_select),
3272                            GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS));
3273     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3274   
3275     item = make_menu_item ("Delayed",
3276                            G_CALLBACK (cb_update_menu_select),
3277                            GINT_TO_POINTER (GTK_UPDATE_DELAYED));
3278     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3279   
3280     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
3281     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
3282     gtk_widget_show (opt);
3283   
3284     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3285     gtk_widget_show (box2);
3286
3287     box2 = gtk_hbox_new (FALSE, 10);
3288     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3289   
3290     /* An HScale widget for adjusting the number of digits on the
3291      * sample scales. */
3292     label = gtk_label_new ("Scale Digits:");
3293     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3294     gtk_widget_show (label);
3295
3296     adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0);
3297     g_signal_connect (G_OBJECT (adj2), "value_changed",
3298                       G_CALLBACK (cb_digits_scale), NULL);
3299     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
3300     gtk_scale_set_digits (GTK_SCALE (scale), 0);
3301     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
3302     gtk_widget_show (scale);
3303
3304     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3305     gtk_widget_show (box2);
3306   
3307     box2 = gtk_hbox_new (FALSE, 10);
3308     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3309   
3310     /* And, one last HScale widget for adjusting the page size of the
3311      * scrollbar. */
3312     label = gtk_label_new ("Scrollbar Page Size:");
3313     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3314     gtk_widget_show (label);
3315
3316     adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0);
3317     g_signal_connect (G_OBJECT (adj2), "value_changed",
3318                       G_CALLBACK (cb_page_size), (gpointer) adj1);
3319     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
3320     gtk_scale_set_digits (GTK_SCALE (scale), 0);
3321     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
3322     gtk_widget_show (scale);
3323
3324     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3325     gtk_widget_show (box2);
3326
3327     separator = gtk_hseparator_new ();
3328     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3329     gtk_widget_show (separator);
3330
3331     box2 = gtk_vbox_new (FALSE, 10);
3332     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3333     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3334     gtk_widget_show (box2);
3335
3336     button = gtk_button_new_with_label ("Quit");
3337     g_signal_connect_swapped (G_OBJECT (button), "clicked",
3338                               G_CALLBACK (gtk_main_quit),
3339                               NULL);
3340     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3341     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3342     gtk_widget_grab_default (button);
3343     gtk_widget_show (button);
3344
3345     gtk_widget_show (window);
3346 }
3347
3348 int main( int   argc,
3349           char *argv[] )
3350 {
3351     gtk_init (&amp;argc, &amp;argv);
3352
3353     create_range_controls ();
3354
3355     gtk_main ();
3356
3357     return 0;
3358 }
3359
3360 <!-- example-end -->
3361 </programlisting>
3362
3363 <para>You will notice that the program does not call g_signal_connect()
3364 for the "delete_event", but only for the "destroy" signal. This will
3365 still perform the desired function, because an unhandled
3366 "delete_event" will result in a "destroy" signal being given to the
3367 window.</para>
3368
3369 </sect1>
3370 </chapter>
3371
3372 <!-- ***************************************************************** -->
3373 <chapter id="ch-MiscWidgets">
3374 <title>Miscellaneous Widgets</title>
3375
3376 <!-- ----------------------------------------------------------------- -->
3377 <sect1 id="sec-Labels">
3378 <title>Labels</title>
3379
3380 <para>Labels are used a lot in GTK, and are relatively simple. Labels emit
3381 no signals as they do not have an associated X window. If you need to
3382 catch signals, or do clipping, place it inside a <link linkend="sec-EventBox">
3383 EventBox</link> widget or a Button widget.</para>
3384
3385 <para>To create a new label, use:</para>
3386
3387 <programlisting role="C">
3388 GtkWidget *gtk_label_new( const char *str );
3389
3390 GtkWidget *gtk_label_new_with_mnemonic( const char *str );
3391 </programlisting>
3392
3393 <para>The sole argument is the string you wish the label to display.</para>
3394
3395 <para>To change the label's text after creation, use the function:</para>
3396
3397 <programlisting role="C">
3398 void gtk_label_set_text( GtkLabel   *label,
3399                          const char *str );
3400 </programlisting>
3401
3402 <para>The first argument is the label you created previously (cast
3403 using the <literal>GTK_LABEL()</literal> macro), and the second is the new string.</para>
3404
3405 <para>The space needed for the new string will be automatically adjusted if
3406 needed. You can produce multi-line labels by putting line breaks in
3407 the label string.</para>
3408
3409 <para>To retrieve the current string, use:</para>
3410
3411 <programlisting role="C">
3412 const gchar* gtk_label_get_text( GtkLabel  *label );                    
3413 </programlisting>
3414
3415 <para>Do not free the returned string, as it is used internally by GTK.</para>
3416
3417 <para>The label text can be justified using:</para>
3418
3419 <programlisting role="C">
3420 void gtk_label_set_justify( GtkLabel         *label,
3421                             GtkJustification  jtype );
3422 </programlisting>
3423
3424 <para>Values for <literal>jtype</literal> are:</para>
3425 <programlisting role="C">
3426   GTK_JUSTIFY_LEFT
3427   GTK_JUSTIFY_RIGHT
3428   GTK_JUSTIFY_CENTER (the default)
3429   GTK_JUSTIFY_FILL
3430 </programlisting>
3431
3432 <para>The label widget is also capable of line wrapping the text
3433 automatically. This can be activated using:</para>
3434
3435 <programlisting role="C">
3436 void gtk_label_set_line_wrap (GtkLabel *label,
3437                               gboolean  wrap);
3438 </programlisting>
3439
3440 <para>The <literal>wrap</literal> argument takes a TRUE or FALSE value.</para>
3441
3442 <para>If you want your label underlined, then you can set a pattern on the
3443 label:</para>
3444
3445 <programlisting role="C">
3446 void       gtk_label_set_pattern   (GtkLabel          *label,
3447                                     const gchar       *pattern);
3448 </programlisting>
3449
3450 <para>The pattern argument indicates how the underlining should look. It
3451 consists of a string of underscore and space characters. An underscore
3452 indicates that the corresponding character in the label should be
3453 underlined. For example, the string <literal>"__     __"</literal> would underline the
3454 first two characters and eight and ninth characters.</para>
3455
3456 <note><para>If you simply want to have an underlined accelerator ("mnemonic") 
3457 in your label, you should use gtk_label_new_with_mnemonic() or 
3458 gtk_label_set_text_with_mnemonic(), not gtk_label_set_pattern().</para>
3459 </note>
3460
3461 <para>Below is a short example to illustrate these functions. This example
3462 makes use of the Frame widget to better demonstrate the label
3463 styles. You can ignore this for now as the <link linkend="sec-Frames">Frame</link> 
3464 widget is explained later on.</para>
3465
3466 <para>In GTK+ 2.0, label texts can contain markup for font and other text attribute 
3467 changes, and labels may be selectable (for copy-and-paste). These advanced features
3468 won't be explained here.</para>
3469
3470 <para>
3471 <inlinemediaobject>
3472 <imageobject>
3473 <imagedata fileref="images/label.png" format="png">
3474 </imageobject>
3475 </inlinemediaobject>
3476 </para>
3477
3478 <programlisting role="C">
3479 <!-- example-start label label.c -->
3480
3481 #include &lt;gtk/gtk.h&gt;
3482
3483 int main( int   argc,
3484           char *argv[] )
3485 {
3486   static GtkWidget *window = NULL;
3487   GtkWidget *hbox;
3488   GtkWidget *vbox;
3489   GtkWidget *frame;
3490   GtkWidget *label;
3491
3492   /* Initialise GTK */
3493   gtk_init (&amp;argc, &amp;argv);
3494
3495   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3496   g_signal_connect (G_OBJECT (window), "destroy",
3497                     G_CALLBACK (gtk_main_quit),
3498                     NULL);
3499
3500   gtk_window_set_title (GTK_WINDOW (window), "Label");
3501   vbox = gtk_vbox_new (FALSE, 5);
3502   hbox = gtk_hbox_new (FALSE, 5);
3503   gtk_container_add (GTK_CONTAINER (window), hbox);
3504   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3505   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3506   
3507   frame = gtk_frame_new ("Normal Label");
3508   label = gtk_label_new ("This is a Normal label");
3509   gtk_container_add (GTK_CONTAINER (frame), label);
3510   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3511   
3512   frame = gtk_frame_new ("Multi-line Label");
3513   label = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \
3514                          "Third line");
3515   gtk_container_add (GTK_CONTAINER (frame), label);
3516   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3517   
3518   frame = gtk_frame_new ("Left Justified Label");
3519   label = gtk_label_new ("This is a Left-Justified\n" \
3520                          "Multi-line label.\nThird      line");
3521   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3522   gtk_container_add (GTK_CONTAINER (frame), label);
3523   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3524   
3525   frame = gtk_frame_new ("Right Justified Label");
3526   label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \
3527                          "Fourth line, (j/k)");
3528   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3529   gtk_container_add (GTK_CONTAINER (frame), label);
3530   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3531
3532   vbox = gtk_vbox_new (FALSE, 5);
3533   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3534   frame = gtk_frame_new ("Line wrapped label");
3535   label = gtk_label_new ("This is an example of a line-wrapped label.  It " \
3536                          "should not be taking up the entire             " /* big space to test spacing */\
3537                          "width allocated to it, but automatically " \
3538                          "wraps the words to fit.  " \
3539                          "The time has come, for all good men, to come to " \
3540                          "the aid of their party.  " \
3541                          "The sixth sheik's six sheep's sick.\n" \
3542                          "     It supports multiple paragraphs correctly, " \
3543                          "and  correctly   adds "\
3544                          "many          extra  spaces. ");
3545   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
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 ("Filled, wrapped label");
3550   label = gtk_label_new ("This is an example of a line-wrapped, filled label.  " \
3551                          "It should be taking "\
3552                          "up the entire              width allocated to it.  " \
3553                          "Here is a sentence to prove "\
3554                          "my point.  Here is another sentence. "\
3555                          "Here comes the sun, do de do de do.\n"\
3556                          "    This is a new paragraph.\n"\
3557                          "    This is another newer, longer, better " \
3558                          "paragraph.  It is coming to an end, "\
3559                          "unfortunately.");
3560   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3561   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3562   gtk_container_add (GTK_CONTAINER (frame), label);
3563   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3564   
3565   frame = gtk_frame_new ("Underlined label");
3566   label = gtk_label_new ("This label is underlined!\n"
3567                          "This one is underlined in quite a funky fashion");
3568   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3569   gtk_label_set_pattern (GTK_LABEL (label),
3570                          "_________________________ _ _________ _ ______     __ _______ ___");
3571   gtk_container_add (GTK_CONTAINER (frame), label);
3572   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3573   
3574   gtk_widget_show_all (window);
3575
3576   gtk_main ();
3577   
3578   return 0;
3579 }
3580 <!-- example-end -->
3581 </programlisting>
3582
3583 </sect1>
3584
3585 <!-- ----------------------------------------------------------------- -->
3586 <sect1 id="sec-Arrows">
3587 <title>Arrows</title>
3588
3589 <para>The Arrow widget draws an arrowhead, facing in a number of possible
3590 directions and having a number of possible styles. It can be very
3591 useful when placed on a button in many applications. Like the Label
3592 widget, it emits no signals.</para>
3593
3594 <para>There are only two functions for manipulating an Arrow widget:</para>
3595
3596 <programlisting role="C">
3597 GtkWidget *gtk_arrow_new( GtkArrowType   arrow_type,
3598                           GtkShadowType  shadow_type );
3599
3600 void gtk_arrow_set( GtkArrow      *arrow,
3601                     GtkArrowType   arrow_type,
3602                     GtkShadowType  shadow_type );
3603 </programlisting>
3604
3605 <para>The first creates a new arrow widget with the indicated type and
3606 appearance. The second allows these values to be altered
3607 retrospectively. The <literal>arrow_type</literal> argument may take one of the
3608 following values:</para>
3609
3610 <programlisting role="C">
3611   GTK_ARROW_UP
3612   GTK_ARROW_DOWN
3613   GTK_ARROW_LEFT
3614   GTK_ARROW_RIGHT
3615 </programlisting>
3616
3617 <para>These values obviously indicate the direction in which the arrow will
3618 point. The <literal>shadow_type</literal> argument may take one of these values:</para>
3619
3620 <programlisting role="C">
3621   GTK_SHADOW_IN
3622   GTK_SHADOW_OUT (the default)
3623   GTK_SHADOW_ETCHED_IN
3624   GTK_SHADOW_ETCHED_OUT
3625 </programlisting>
3626
3627 <para>Here's a brief example to illustrate their use.</para>
3628
3629 <para>
3630 <inlinemediaobject>
3631 <imageobject>
3632 <imagedata fileref="images/arrow.png" format="png">
3633 </imageobject>
3634 </inlinemediaobject>
3635 </para>
3636
3637 <programlisting role="C">
3638 <!-- example-start arrow arrow.c -->
3639
3640 #include &lt;gtk/gtk.h&gt;
3641
3642 /* Create an Arrow widget with the specified parameters
3643  * and pack it into a button */
3644 static GtkWidget *create_arrow_button( GtkArrowType  arrow_type,
3645                                        GtkShadowType shadow_type )
3646 {
3647   GtkWidget *button;
3648   GtkWidget *arrow;
3649
3650   button = gtk_button_new ();
3651   arrow = gtk_arrow_new (arrow_type, shadow_type);
3652
3653   gtk_container_add (GTK_CONTAINER (button), arrow);
3654   
3655   gtk_widget_show (button);
3656   gtk_widget_show (arrow);
3657
3658   return button;
3659 }
3660
3661 int main( int   argc,
3662           char *argv[] )
3663 {
3664   /* GtkWidget is the storage type for widgets */
3665   GtkWidget *window;
3666   GtkWidget *button;
3667   GtkWidget *box;
3668
3669   /* Initialize the toolkit */
3670   gtk_init (&amp;argc, &amp;argv);
3671
3672   /* Create a new window */
3673   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3674
3675   gtk_window_set_title (GTK_WINDOW (window), "Arrow Buttons");
3676
3677   /* It's a good idea to do this for all windows. */
3678   g_signal_connect (G_OBJECT (window), "destroy",
3679                     G_CALLBACK (gtk_main_quit), NULL);
3680
3681   /* Sets the border width of the window. */
3682   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
3683
3684   /* Create a box to hold the arrows/buttons */
3685   box = gtk_hbox_new (FALSE, 0);
3686   gtk_container_set_border_width (GTK_CONTAINER (box), 2);
3687   gtk_container_add (GTK_CONTAINER (window), box);
3688
3689   /* Pack and show all our widgets */
3690   gtk_widget_show (box);
3691
3692   button = create_arrow_button (GTK_ARROW_UP, GTK_SHADOW_IN);
3693   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3694
3695   button = create_arrow_button (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
3696   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3697   
3698   button = create_arrow_button (GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN);
3699   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3700   
3701   button = create_arrow_button (GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT);
3702   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3703   
3704   gtk_widget_show (window);
3705   
3706   /* Rest in gtk_main and wait for the fun to begin! */
3707   gtk_main ();
3708   
3709   return 0;
3710 }
3711 <!-- example-end -->
3712 </programlisting>
3713
3714 </sect1>
3715
3716 <!-- ----------------------------------------------------------------- -->
3717 <sect1 id="sec-TheTooltipsObject">
3718 <title>The Tooltips Object</title>
3719
3720 <para>These are the little text strings that pop up when you leave your
3721 pointer over a button or other widget for a few seconds. They are easy
3722 to use, so I will just explain them without giving an example. If you
3723 want to see some code, take a look at the <filename>testgtk.c</filename> program
3724 distributed with GTK.</para>
3725
3726 <para>Widgets that do not receive events (widgets that do not have their
3727 own window) will not work with tooltips.</para>
3728
3729 <para>The first call you will use creates a new tooltip. You only need to do
3730 this once for a set of tooltips as the <literal>GtkTooltips</literal> object this
3731 function returns can be used to create multiple tooltips.</para>
3732
3733 <programlisting role="C">
3734 GtkTooltips *gtk_tooltips_new( void );
3735 </programlisting>
3736
3737 <para>Once you have created a new tooltip, and the widget you wish to use it
3738 on, simply use this call to set it:</para>
3739
3740 <programlisting role="C">
3741 void gtk_tooltips_set_tip( GtkTooltips *tooltips,
3742                            GtkWidget   *widget,
3743                            const gchar *tip_text,
3744                            const gchar *tip_private );
3745 </programlisting>
3746
3747 <para>The first argument is the tooltip you've already created, followed by
3748 the widget you wish to have this tooltip pop up for, and the text you
3749 wish it to say. The last argument is a text string that can be used as
3750 an identifier when using GtkTipsQuery to implement context sensitive
3751 help. For now, you can set it to NULL.</para>
3752
3753 <!-- TODO: sort out what how to do the context sensitive help -->
3754
3755 <para>Here's a short example:</para>
3756
3757 <programlisting role="C">
3758 GtkTooltips *tooltips;
3759 GtkWidget *button;
3760 .
3761 .
3762 .
3763 tooltips = gtk_tooltips_new ();
3764 button = gtk_button_new_with_label ("button 1");
3765 .
3766 .
3767 .
3768 gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);
3769 </programlisting>
3770
3771 <para>There are other calls that can be used with tooltips. I will just list
3772 them with a brief description of what they do.</para>
3773
3774 <programlisting role="C">
3775 void gtk_tooltips_enable( GtkTooltips *tooltips );
3776 </programlisting>
3777
3778 <para>Enable a disabled set of tooltips.</para>
3779
3780 <programlisting role="C">
3781 void gtk_tooltips_disable( GtkTooltips *tooltips );
3782 </programlisting>
3783
3784 <para>Disable an enabled set of tooltips.</para>
3785
3786 <para>And that's all the functions associated with tooltips. More than
3787 you'll ever want to know :-)</para>
3788
3789 </sect1>
3790
3791 <!-- ----------------------------------------------------------------- -->
3792 <sect1 id="sec-ProgressBars">
3793 <title>Progress Bars</title>
3794
3795 <para>Progress bars are used to show the status of an operation. They are
3796 pretty easy to use, as you will see with the code below. But first
3797 lets start out with the calls to create a new progress bar.</para>
3798
3799 <programlisting role="C">
3800 GtkWidget *gtk_progress_bar_new( void );
3801 </programlisting>
3802
3803 <para>Now that the progress bar has been created we can use it.</para>
3804
3805 <programlisting role="C">
3806 void gtk_progress_bar_set_fraction ( GtkProgressBar *pbar,
3807                                      gdouble        fraction );
3808 </programlisting>
3809
3810 <para>The first argument is the progress bar you wish to operate on, and the
3811 second argument is the amount "completed", meaning the amount the
3812 progress bar has been filled from 0-100%. This is passed to the
3813 function as a real number ranging from 0 to 1.</para>
3814
3815 <para>GTK v1.2 has added new functionality to the progress bar that enables
3816 it to display its value in different ways, and to inform the user of
3817 its current value and its range.</para>
3818
3819 <para>A progress bar may be set to one of a number of orientations using the
3820 function</para>
3821
3822 <programlisting role="C">
3823 void gtk_progress_bar_set_orientation( GtkProgressBar *pbar,
3824                                        GtkProgressBarOrientation orientation );
3825 </programlisting>
3826
3827 <para>The <literal>orientation</literal> argument may take one of the following
3828 values to indicate the direction in which the progress bar moves:</para>
3829
3830 <programlisting role="C">
3831   GTK_PROGRESS_LEFT_TO_RIGHT
3832   GTK_PROGRESS_RIGHT_TO_LEFT
3833   GTK_PROGRESS_BOTTOM_TO_TOP
3834   GTK_PROGRESS_TOP_TO_BOTTOM
3835 </programlisting>
3836
3837 <para>As well as indicating the amount of progress that has occured, the
3838 progress bar may be set to just indicate that there is some activity. 
3839 This can be useful in situations where progress cannot be measured against 
3840 a value range. The following function indicates that some progress has been 
3841 made.</para>
3842
3843 <programlisting role="C">
3844 void gtk_progress_bar_pulse ( GtkProgressBar *progress );
3845 </programlisting>
3846
3847 <para>The step size of the activity indicator is set using the following 
3848 function.</para>
3849
3850 <programlisting role="C">
3851 void gtk_progress_bar_set_pulse_step( GtkProgressBar *pbar,
3852                                       gdouble         fraction );
3853 </programlisting>
3854
3855 <para>When not in activity mode, the progress bar can also display a
3856 configurable text string within its trough, using the following
3857 function.</para>
3858
3859 <programlisting role="C">
3860 void gtk_progress_bar_set_text( GtkProgressBar *progress,
3861                                 const gchar    *text );
3862 </programlisting>
3863
3864 <note><para>Note that gtk_progress_set_text() doesn't support the printf()-like formatting
3865 of the GTK+ 1.2 Progressbar.</para></note>
3866
3867 <para>You can turn off the display of the string by calling gtk_progess_bar_set_text()
3868 again with NULL as second argument.</para>
3869
3870 <para>The current text setting of a progressbar can be retrieved with the 
3871 following function. Do not free the returned string.</para>
3872
3873 <programlisting role="C">
3874 const gchar *gtk_progress_bar_get_text( GtkProgressBar *pbar );
3875 </programlisting>
3876
3877 <para>Progress Bars are usually used with timeouts or other such functions
3878 (see section on <link linkend="ch-Timeouts">Timeouts, I/O and Idle Functions</link>) 
3879 to give the illusion of multitasking. All will employ the
3880 gtk_progress_bar_set_fraction() or gtk_progress_bar_pulse() functions in the 
3881 same manner.</para>
3882
3883 <para>Here is an example of the progress bar, updated using timeouts. This
3884 code also shows you how to reset the Progress Bar.</para>
3885
3886 <para>
3887 <inlinemediaobject>
3888 <imageobject>
3889 <imagedata fileref="images/progressbar.png" format="png">
3890 </imageobject>
3891 </inlinemediaobject>
3892 </para>
3893
3894 <programlisting role="C">
3895 <!-- example-start progressbar progressbar.c -->
3896
3897 #include &lt;gtk/gtk.h&gt;
3898
3899 typedef struct _ProgressData {
3900   GtkWidget *window;
3901   GtkWidget *pbar;
3902   int timer;
3903   gboolean activity_mode;
3904 } ProgressData;
3905
3906 /* Update the value of the progress bar so that we get
3907  * some movement */
3908 static gboolean progress_timeout( gpointer data )
3909 {
3910   ProgressData *pdata = (ProgressData *)data;
3911   gdouble new_val;
3912   
3913   if (pdata-&gt;activity_mode) 
3914     gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata-&gt;pbar));
3915   else 
3916     {
3917       /* Calculate the value of the progress bar using the
3918        * value range set in the adjustment object */
3919       
3920       new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata-&gt;pbar)) + 0.01;
3921       
3922       if (new_val &gt; 1.0)
3923         new_val = 0.0;
3924       
3925       /* Set the new value */
3926       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata-&gt;pbar), new_val);
3927     }
3928   
3929   /* As this is a timeout function, return TRUE so that it
3930    * continues to get called */
3931   return TRUE;
3932
3933
3934 /* Callback that toggles the text display within the progress bar trough */
3935 static void toggle_show_text( GtkWidget    *widget,
3936                               ProgressData *pdata )
3937 {
3938   const gchar *text;
3939   
3940   text = gtk_progress_bar_get_text (GTK_PROGRESS_BAR (pdata-&gt;pbar));
3941   if (text &amp;&amp; *text)
3942     gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata-&gt;pbar), "");
3943   else 
3944     gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata-&gt;pbar), "some text");
3945 }
3946
3947 /* Callback that toggles the activity mode of the progress bar */
3948 static void toggle_activity_mode( GtkWidget    *widget,
3949                                   ProgressData *pdata )
3950 {
3951   pdata-&gt;activity_mode = !pdata-&gt;activity_mode;
3952   if (pdata-&gt;activity_mode) 
3953       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata-&gt;pbar));
3954   else
3955       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata-&gt;pbar), 0.0);
3956 }
3957
3958  
3959 /* Callback that toggles the orientation of the progress bar */
3960 static void toggle_orientation( GtkWidget    *widget,
3961                                 ProgressData *pdata )
3962 {
3963   switch (gtk_progress_bar_get_orientation (GTK_PROGRESS_BAR (pdata-&gt;pbar))) {
3964   case GTK_PROGRESS_LEFT_TO_RIGHT:
3965     gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata-&gt;pbar), 
3966                                       GTK_PROGRESS_RIGHT_TO_LEFT);
3967     break;
3968   case GTK_PROGRESS_RIGHT_TO_LEFT:
3969     gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata-&gt;pbar), 
3970                                       GTK_PROGRESS_LEFT_TO_RIGHT);
3971     break;
3972   default:;
3973     /* do nothing */
3974   }
3975 }
3976
3977  
3978 /* Clean up allocated memory and remove the timer */
3979 static void destroy_progress( GtkWidget    *widget,
3980                               ProgressData *pdata)
3981 {
3982     g_source_remove (pdata-&gt;timer);
3983     pdata-&gt;timer = 0;
3984     pdata-&gt;window = NULL;
3985     g_free (pdata);
3986     gtk_main_quit ();
3987 }
3988
3989 int main( int   argc,
3990           char *argv[])
3991 {
3992     ProgressData *pdata;
3993     GtkWidget *align;
3994     GtkWidget *separator;
3995     GtkWidget *table;
3996     GtkWidget *button;
3997     GtkWidget *check;
3998     GtkWidget *vbox;
3999
4000     gtk_init (&amp;argc, &amp;argv);
4001
4002     /* Allocate memory for the data that is passed to the callbacks */
4003     pdata = g_malloc (sizeof (ProgressData));
4004   
4005     pdata-&gt;window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4006     gtk_window_set_resizable (GTK_WINDOW (pdata-&gt;window), TRUE);
4007
4008     g_signal_connect (G_OBJECT (pdata-&gt;window), "destroy",
4009                       G_CALLBACK (destroy_progress),
4010                       (gpointer) pdata);
4011     gtk_window_set_title (GTK_WINDOW (pdata-&gt;window), "GtkProgressBar");
4012     gtk_container_set_border_width (GTK_CONTAINER (pdata-&gt;window), 0);
4013
4014     vbox = gtk_vbox_new (FALSE, 5);
4015     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
4016     gtk_container_add (GTK_CONTAINER (pdata-&gt;window), vbox);
4017     gtk_widget_show (vbox);
4018   
4019     /* Create a centering alignment object */
4020     align = gtk_alignment_new (0.5, 0.5, 0, 0);
4021     gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
4022     gtk_widget_show (align);
4023
4024     /* Create the GtkProgressBar */
4025     pdata-&gt;pbar = gtk_progress_bar_new ();
4026     pdata-&gt;activity_mode = FALSE;
4027
4028     gtk_container_add (GTK_CONTAINER (align), pdata-&gt;pbar);
4029     gtk_widget_show (pdata-&gt;pbar);
4030
4031     /* Add a timer callback to update the value of the progress bar */
4032     pdata-&gt;timer = g_timeout_add (100, progress_timeout, pdata);
4033
4034     separator = gtk_hseparator_new ();
4035     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
4036     gtk_widget_show (separator);
4037
4038     /* rows, columns, homogeneous */
4039     table = gtk_table_new (2, 3, FALSE);
4040     gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
4041     gtk_widget_show (table);
4042
4043     /* Add a check button to select displaying of the trough text */
4044     check = gtk_check_button_new_with_label ("Show text");
4045     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
4046                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
4047                       5, 5);
4048     g_signal_connect (G_OBJECT (check), "clicked",
4049                       G_CALLBACK (toggle_show_text),
4050                       (gpointer) pdata);
4051     gtk_widget_show (check);
4052
4053     /* Add a check button to toggle activity mode */
4054     check = gtk_check_button_new_with_label ("Activity mode");
4055     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
4056                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
4057                       5, 5);
4058     g_signal_connect (G_OBJECT (check), "clicked",
4059                       G_CALLBACK (toggle_activity_mode),
4060                       (gpointer) pdata);
4061     gtk_widget_show (check);
4062
4063     /* Add a check button to toggle orientation */
4064     check = gtk_check_button_new_with_label ("Right to Left");
4065     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 2, 3,
4066                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
4067                       5, 5);
4068     g_signal_connect (G_OBJECT (check), "clicked",
4069                       G_CALLBACK (toggle_orientation),
4070                       (gpointer) pdata);
4071     gtk_widget_show (check);
4072
4073     /* Add a button to exit the program */
4074     button = gtk_button_new_with_label ("close");
4075     g_signal_connect_swapped (G_OBJECT (button), "clicked",
4076                               G_CALLBACK (gtk_widget_destroy),
4077                               G_OBJECT (pdata-&gt;window));
4078     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
4079
4080     /* This makes it so the button is the default. */
4081     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4082
4083     /* This grabs this button to be the default button. Simply hitting
4084      * the "Enter" key will cause this button to activate. */
4085     gtk_widget_grab_default (button);
4086     gtk_widget_show (button);
4087
4088     gtk_widget_show (pdata-&gt;window);
4089
4090     gtk_main ();
4091     
4092     return 0;
4093 }
4094 <!-- example-end -->
4095 </programlisting>
4096
4097 </sect1>
4098
4099 <!-- ----------------------------------------------------------------- -->
4100 <sect1 id="sec-Dialogs">
4101 <title>Dialogs</title>
4102
4103 <para>The Dialog widget is very simple, and is actually just a window with a
4104 few things pre-packed into it for you. The structure for a Dialog is:</para>
4105
4106 <programlisting role="C">
4107 struct GtkDialog
4108 {
4109       GtkWindow window;
4110     
4111       GtkWidget *vbox;
4112       GtkWidget *action_area;
4113 };
4114 </programlisting>
4115
4116 <para>So you see, it simply creates a window, and then packs a vbox into the
4117 top, which contains a separator and then an hbox called the
4118 "action_area".</para>
4119
4120 <para>The Dialog widget can be used for pop-up messages to the user, and
4121 other similar tasks. There are two functions to create a new Dialog.</para>
4122
4123 <programlisting role="C">
4124 GtkWidget *gtk_dialog_new( void );
4125
4126 GtkWidget *gtk_dialog_new_with_buttons( const gchar    *title,
4127                                         GtkWindow      *parent,
4128                                         GtkDialogFlags  flags, 
4129                                         const gchar    *first_button_text,
4130                                         ... );
4131 </programlisting>
4132
4133 <para>The first function will create an empty dialog, and it is now up to you to use
4134  it. You could pack a button in the action_area by doing something like this:</para>
4135
4136 <programlisting role="C">
4137     button = ...
4138     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
4139                         button, TRUE, TRUE, 0);
4140     gtk_widget_show (button);
4141 </programlisting>
4142
4143 <para>And you could add to the vbox area by packing, for instance, a label 
4144 in it, try something like this:</para>
4145
4146 <programlisting role="C">
4147     label = gtk_label_new ("Dialogs are groovy");
4148     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
4149                         label, TRUE, TRUE, 0);
4150     gtk_widget_show (label);
4151 </programlisting>
4152
4153 <para>As an example in using the dialog box, you could put two buttons in
4154 the action_area, a Cancel button and an Ok button, and a label in the
4155 vbox area, asking the user a question or giving an error etc. Then
4156 you could attach a different signal to each of the buttons and perform
4157 the operation the user selects.</para>
4158
4159 <para>If the simple functionality provided by the default vertical and
4160 horizontal boxes in the two areas doesn't give you enough control for
4161 your application, then you can simply pack another layout widget into
4162 the boxes provided. For example, you could pack a table into the
4163 vertical box.</para>
4164
4165 <para>The more complicated _new_with_buttons() variant allows to set one or
4166 more of the following flags.</para>
4167
4168 <variablelist>
4169 <varlistentry>
4170 <term><literal>GTK_DIALOG_MODAL</literal></term>
4171 <listitem><para>make the dialog modal.
4172 </para></listitem>
4173 </varlistentry>
4174 <varlistentry>
4175 <term><literal>GTK_DIALOG_DESTROY_WITH_PARENT</literal></term>
4176 <listitem><para>ensures that the dialog window is destroyed together with the specified
4177 parent.</para></listitem>
4178 </varlistentry>
4179 <varlistentry>
4180 <term><literal>GTK_DIALOG_NO_SEPARATOR</literal></term>
4181 <listitem><para>omits the separator between the vbox and the action_area.
4182 </para></listitem>
4183 </varlistentry>
4184 </variablelist>
4185 </sect1>
4186
4187 <!-- ----------------------------------------------------------------- -->
4188 <sect1 id="sec-Rulers">
4189 <title>Rulers</title>
4190
4191 <para>Ruler widgets are used to indicate the location of the mouse pointer
4192 in a given window. A window can have a vertical ruler spanning across
4193 the height and a horizontal ruler spanning down the width. A small
4194 triangular indicator on the ruler shows the exact location of the
4195 pointer relative to the ruler.</para>
4196
4197 <para>A ruler must first be created. Horizontal and vertical rulers are
4198 created using</para>
4199
4200 <programlisting role="C">
4201 GtkWidget *gtk_hruler_new( void );    /* horizontal ruler */
4202
4203 GtkWidget *gtk_vruler_new( void );    /* vertical ruler   */
4204 </programlisting>
4205
4206 <para>Once a ruler is created, we can define the unit of measurement. Units
4207 of measure for rulers can be <literal>GTK_PIXELS</literal>, <literal>GTK_INCHES</literal> or
4208 <literal>GTK_CENTIMETERS</literal>. This is set using</para>
4209
4210 <programlisting role="C">
4211 void gtk_ruler_set_metric( GtkRuler      *ruler,
4212                            GtkMetricType  metric );
4213 </programlisting>
4214
4215 <para>The default measure is <literal>GTK_PIXELS</literal>.</para>
4216
4217 <programlisting role="C">
4218     gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
4219 </programlisting>
4220
4221 <para>Other important characteristics of a ruler are how to mark the units
4222 of scale and where the position indicator is initially placed. These
4223 are set for a ruler using</para>
4224
4225 <programlisting role="C">
4226 void gtk_ruler_set_range( GtkRuler *ruler,
4227                           gdouble   lower,
4228                           gdouble   upper,
4229                           gdouble   position,
4230                           gdouble   max_size );
4231 </programlisting>
4232
4233 <para>The lower and upper arguments define the extent of the ruler, and
4234 max_size is the largest possible number that will be displayed.
4235 Position defines the initial position of the pointer indicator within
4236 the ruler.</para>
4237
4238 <para>A vertical ruler can span an 800 pixel wide window thus</para>
4239
4240 <programlisting role="C">
4241     gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
4242 </programlisting>
4243
4244 <para>The markings displayed on the ruler will be from 0 to 800, with a
4245 number for every 100 pixels. If instead we wanted the ruler to range
4246 from 7 to 16, we would code</para>
4247
4248 <programlisting role="C">
4249     gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
4250 </programlisting>
4251
4252 <para>The indicator on the ruler is a small triangular mark that indicates
4253 the position of the pointer relative to the ruler. If the ruler is
4254 used to follow the mouse pointer, the motion_notify_event signal
4255 should be connected to the motion_notify_event method of the ruler.
4256 To follow all mouse movements within a window area, we would use</para>
4257
4258 <programlisting role="C">
4259 #define EVENT_METHOD(i, x) GTK_WIDGET_GET_CLASS(i)->x
4260
4261     g_signal_connect_swapped (G_OBJECT (area), "motion_notify_event",
4262            G_CALLBACK (EVENT_METHOD (ruler, motion_notify_event)),
4263            G_OBJECT (ruler));
4264 </programlisting>
4265
4266 <para>The following example creates a drawing area with a horizontal ruler
4267 above it and a vertical ruler to the left of it. The size of the
4268 drawing area is 600 pixels wide by 400 pixels high. The horizontal
4269 ruler spans from 7 to 13 with a mark every 100 pixels, while the
4270 vertical ruler spans from 0 to 400 with a mark every 100 pixels.
4271 Placement of the drawing area and the rulers is done using a table.</para>
4272
4273 <para>
4274 <inlinemediaobject>
4275 <imageobject>
4276 <imagedata fileref="images/rulers.png" format="png">
4277 </imageobject>
4278 </inlinemediaobject>
4279 </para>
4280
4281 <programlisting role="C">
4282 <!-- example-start rulers rulers.c -->
4283
4284 #include &lt;gtk/gtk.h&gt;
4285
4286 #define EVENT_METHOD(i, x) GTK_WIDGET_GET_CLASS(i)-&gt;x
4287
4288 #define XSIZE  600
4289 #define YSIZE  400
4290
4291 /* This routine gets control when the close button is clicked */
4292 static gboolean close_application( GtkWidget *widget,
4293                                    GdkEvent  *event,
4294                                    gpointer   data )
4295 {
4296     gtk_main_quit ();
4297     return FALSE;
4298 }
4299
4300 /* The main routine */
4301 int main( int   argc,
4302           char *argv[] ) {
4303     GtkWidget *window, *table, *area, *hrule, *vrule;
4304
4305     /* Initialize GTK and create the main window */
4306     gtk_init (&amp;argc, &amp;argv);
4307
4308     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4309     g_signal_connect (G_OBJECT (window), "delete_event",
4310                       G_CALLBACK (close_application), NULL);
4311     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
4312
4313     /* Create a table for placing the ruler and the drawing area */
4314     table = gtk_table_new (3, 2, FALSE);
4315     gtk_container_add (GTK_CONTAINER (window), table);
4316
4317     area = gtk_drawing_area_new ();
4318     gtk_widget_set_size_request (GTK_WIDGET (area), XSIZE, YSIZE);
4319     gtk_table_attach (GTK_TABLE (table), area, 1, 2, 1, 2,
4320                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0);
4321     gtk_widget_set_events (area, GDK_POINTER_MOTION_MASK |
4322                                  GDK_POINTER_MOTION_HINT_MASK);
4323
4324     /* The horizontal ruler goes on top. As the mouse moves across the
4325      * drawing area, a motion_notify_event is passed to the
4326      * appropriate event handler for the ruler. */
4327     hrule = gtk_hruler_new ();
4328     gtk_ruler_set_metric (GTK_RULER (hrule), GTK_PIXELS);
4329     gtk_ruler_set_range (GTK_RULER (hrule), 7, 13, 0, 20);
4330     g_signal_connect_swapped (G_OBJECT (area), "motion_notify_event",
4331                               G_CALLBACK (EVENT_METHOD (hrule, motion_notify_event)),
4332                               G_OBJECT (hrule));
4333     gtk_table_attach (GTK_TABLE (table), hrule, 1, 2, 0, 1,
4334                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0);
4335     
4336     /* The vertical ruler goes on the left. As the mouse moves across
4337      * the drawing area, a motion_notify_event is passed to the
4338      * appropriate event handler for the ruler. */
4339     vrule = gtk_vruler_new ();
4340     gtk_ruler_set_metric (GTK_RULER (vrule), GTK_PIXELS);
4341     gtk_ruler_set_range (GTK_RULER (vrule), 0, YSIZE, 10, YSIZE );
4342     g_signal_connect_swapped (G_OBJECT (area), "motion_notify_event",
4343                               G_CALLBACK (EVENT_METHOD (vrule, motion_notify_event)),
4344                               G_OBJECT (vrule));
4345     gtk_table_attach (GTK_TABLE (table), vrule, 0, 1, 1, 2,
4346                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0);
4347
4348     /* Now show everything */
4349     gtk_widget_show (area);
4350     gtk_widget_show (hrule);
4351     gtk_widget_show (vrule);
4352     gtk_widget_show (table);
4353     gtk_widget_show (window);
4354     gtk_main ();
4355
4356     return 0;
4357 }
4358 <!-- example-end -->
4359 </programlisting>
4360
4361 </sect1>
4362
4363 <!-- ----------------------------------------------------------------- -->
4364 <sect1 id="sec-Statusbars">
4365 <title>Statusbars</title>
4366
4367 <para>Statusbars are simple widgets used to display a text message. They
4368 keep a stack of the messages pushed onto them, so that popping the
4369 current message will re-display the previous text message.</para>
4370
4371 <para>In order to allow different parts of an application to use the same
4372 statusbar to display messages, the statusbar widget issues Context
4373 Identifiers which are used to identify different "users". The message
4374 on top of the stack is the one displayed, no matter what context it is
4375 in. Messages are stacked in last-in-first-out order, not context
4376 identifier order.</para>
4377
4378 <para>A statusbar is created with a call to:</para>
4379
4380 <programlisting role="C">
4381 GtkWidget *gtk_statusbar_new( void );
4382 </programlisting>
4383
4384 <para>A new Context Identifier is requested using a call to the following 
4385 function with a short textual description of the context:</para>
4386
4387 <programlisting role="C">
4388 guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
4389                                     const gchar  *context_description );
4390 </programlisting>
4391
4392 <para>There are three functions that can operate on statusbars:</para>
4393
4394 <programlisting role="C">
4395 guint gtk_statusbar_push( GtkStatusbar *statusbar,
4396                           guint         context_id,
4397                           const gchar  *text );
4398
4399 void gtk_statusbar_pop( GtkStatusbar *statusbar)
4400                         guint         context_id );
4401
4402 void gtk_statusbar_remove( GtkStatusbar *statusbar,
4403                            guint         context_id,
4404                            guint         message_id ); 
4405 </programlisting>
4406
4407 <para>The first, gtk_statusbar_push(), is used to add a new message to the
4408 statusbar.  It returns a Message Identifier, which can be passed later
4409 to the function gtk_statusbar_remove to remove the message with the
4410 given Message and Context Identifiers from the statusbar's stack.</para>
4411
4412 <para>The function gtk_statusbar_pop() removes the message highest in the
4413 stack with the given Context Identifier.</para>
4414
4415 <para>In addition to messages, statusbars may also display a resize grip, which 
4416 can be dragged with the mouse to resize the toplevel window containing the statusbar,
4417 similar to dragging the window frame. The following functions control the display
4418 of the resize grip.</para>
4419
4420 <programlisting role="C">
4421 void     gtk_statusbar_set_has_resize_grip( GtkStatusbar *statusbar,
4422                                             gboolean      setting );
4423
4424 gboolean gtk_statusbar_get_has_resize_grip( GtkStatusbar *statusbar );
4425 </programlisting>
4426
4427 <para>The following example creates a statusbar and two buttons, one for
4428 pushing items onto the statusbar, and one for popping the last item
4429 back off.</para>
4430
4431 <para>
4432 <inlinemediaobject>
4433 <imageobject>
4434 <imagedata fileref="images/statusbar.png" format="png">
4435 </imageobject>
4436 </inlinemediaobject>
4437 </para>
4438
4439 <programlisting role="C">
4440 <!-- example-start statusbar statusbar.c -->
4441
4442 #include &lt;stdlib.h&gt;
4443 #include &lt;gtk/gtk.h&gt;
4444 #include &lt;glib.h&gt;
4445
4446 GtkWidget *status_bar;
4447
4448 static void push_item( GtkWidget *widget,
4449                        gpointer   data )
4450 {
4451   static int count = 1;
4452   gchar *buff;
4453
4454   buff = g_strdup_printf ("Item %d", count++);
4455   gtk_statusbar_push (GTK_STATUSBAR (status_bar), GPOINTER_TO_INT (data), buff);
4456   g_free (buff);
4457 }
4458
4459 static void pop_item( GtkWidget *widget,
4460                       gpointer   data )
4461 {
4462   gtk_statusbar_pop (GTK_STATUSBAR (status_bar), GPOINTER_TO_INT (data));
4463 }
4464
4465 int main( int   argc,
4466           char *argv[] )
4467 {
4468
4469     GtkWidget *window;
4470     GtkWidget *vbox;
4471     GtkWidget *button;
4472
4473     gint context_id;
4474
4475     gtk_init (&amp;argc, &amp;argv);
4476
4477     /* create a new window */
4478     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4479     gtk_widget_set_size_request (GTK_WIDGET (window), 200, 100);
4480     gtk_window_set_title (GTK_WINDOW (window), "GTK Statusbar Example");
4481     g_signal_connect (G_OBJECT (window), "delete_event",
4482                       G_CALLBACK (exit), NULL);
4483  
4484     vbox = gtk_vbox_new (FALSE, 1);
4485     gtk_container_add (GTK_CONTAINER (window), vbox);
4486     gtk_widget_show (vbox);
4487           
4488     status_bar = gtk_statusbar_new ();      
4489     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
4490     gtk_widget_show (status_bar);
4491
4492     context_id = gtk_statusbar_get_context_id(
4493                           GTK_STATUSBAR (status_bar), "Statusbar example");
4494
4495     button = gtk_button_new_with_label ("push item");
4496     g_signal_connect (G_OBJECT (button), "clicked",
4497                       G_CALLBACK (push_item), GINT_TO_POINTER (context_id));
4498     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 2);
4499     gtk_widget_show (button);              
4500
4501     button = gtk_button_new_with_label ("pop last item");
4502     g_signal_connect (G_OBJECT (button), "clicked",
4503                       G_CALLBACK (pop_item), GINT_TO_POINTER (context_id));
4504     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 2);
4505     gtk_widget_show (button);
4506
4507     /* always display the window as the last step so it all splashes on
4508      * the screen at once. */
4509     gtk_widget_show (window);
4510
4511     gtk_main ();
4512
4513     return 0;
4514 }
4515 <!-- example-end -->
4516 </programlisting>
4517
4518 </sect1>
4519
4520 <!-- ----------------------------------------------------------------- -->
4521 <sect1 id="sec-TextEntries">
4522 <title>Text Entries</title>
4523
4524 <para>The Entry widget allows text to be typed and displayed in a single line
4525 text box. The text may be set with function calls that allow new text
4526 to replace, prepend or append the current contents of the Entry widget.</para>
4527
4528 <para>Create a new Entry widget with the following function.</para>
4529
4530 <programlisting role="C">
4531 GtkWidget *gtk_entry_new( void );
4532 </programlisting>
4533
4534 <para>The next function alters the text which is currently
4535 within the Entry widget.</para>
4536
4537 <programlisting role="C">
4538 void gtk_entry_set_text( GtkEntry    *entry,
4539                          const gchar *text );
4540 </programlisting>
4541
4542 <para>The function gtk_entry_set_text() sets the contents of the Entry widget,
4543 replacing the current contents. Note that the class Entry implements the Editable
4544 interface (yes, gobject supports Java-like interfaces) which contains some more
4545 functions for manipulating the contents.
4546  </para>
4547
4548 <para>The contents of the Entry can be retrieved by using a call to the
4549 following function. This is useful in the callback functions described below.</para>
4550
4551 <programlisting role="C">
4552 const gchar *gtk_entry_get_text( GtkEntry *entry );
4553 </programlisting>
4554
4555 <para>The value returned by this function is used internally, and must not
4556 be freed using either free() or g_free().</para>
4557
4558 <para>If we don't want the contents of the Entry to be changed by someone typing
4559 into it, we can change its editable state.</para>
4560
4561 <programlisting role="C">
4562 void gtk_editable_set_editable( GtkEditable *entry,
4563                                 gboolean     editable );
4564 </programlisting>
4565
4566 <para>The function above allows us to toggle the editable state of the
4567 Entry widget by passing in a TRUE or FALSE value for the <literal>editable</literal>
4568 argument.</para>
4569
4570 <para>If we are using the Entry where we don't want the text entered to be
4571 visible, for example when a password is being entered, we can use the
4572 following function, which also takes a boolean flag.</para>
4573
4574 <programlisting role="C">
4575 void gtk_entry_set_visibility( GtkEntry *entry,
4576                                gboolean  visible );
4577 </programlisting>
4578
4579 <para>A region of the text may be set as selected by using the following
4580 function. This would most often be used after setting some default
4581 text in an Entry, making it easy for the user to remove it.</para>
4582
4583 <programlisting role="C">
4584 void gtk_editable_select_region( GtkEditable *entry,
4585                                  gint         start,
4586                                  gint         end );
4587 </programlisting>
4588
4589 <para>If we want to catch when the user has entered text, we can connect to
4590 the <literal>activate</literal> or <literal>changed</literal> signal. Activate is raised when the
4591 user hits the enter key within the Entry widget. Changed is raised
4592 when the text changes at all, e.g., for every character entered or
4593 removed.</para>
4594
4595 <para>The following code is an example of using an Entry widget.</para>
4596
4597 <para>
4598 <inlinemediaobject>
4599 <imageobject>
4600 <imagedata fileref="images/entry.png" format="png">
4601 </imageobject>
4602 </inlinemediaobject>
4603 </para>
4604
4605 <programlisting role="C">
4606 <!-- example-start entry entry.c -->
4607
4608 #include &lt;stdio.h&gt;
4609 #include &lt;stdlib.h&gt;
4610 #include &lt;gtk/gtk.h&gt;
4611
4612 static void enter_callback( GtkWidget *widget,
4613                             GtkWidget *entry )
4614 {
4615   const gchar *entry_text;
4616   entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
4617   printf ("Entry contents: %s\n", entry_text);
4618 }
4619
4620 static void entry_toggle_editable( GtkWidget *checkbutton,
4621                                    GtkWidget *entry )
4622 {
4623   gtk_editable_set_editable (GTK_EDITABLE (entry),
4624                              GTK_TOGGLE_BUTTON (checkbutton)-&gt;active);
4625 }
4626
4627 static void entry_toggle_visibility( GtkWidget *checkbutton,
4628                                      GtkWidget *entry )
4629 {
4630   gtk_entry_set_visibility (GTK_ENTRY (entry),
4631                             GTK_TOGGLE_BUTTON (checkbutton)-&gt;active);
4632 }
4633
4634 int main( int   argc,
4635           char *argv[] )
4636 {
4637
4638     GtkWidget *window;
4639     GtkWidget *vbox, *hbox;
4640     GtkWidget *entry;
4641     GtkWidget *button;
4642     GtkWidget *check;
4643     gint tmp_pos;
4644
4645     gtk_init (&amp;argc, &amp;argv);
4646
4647     /* create a new window */
4648     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4649     gtk_widget_set_size_request (GTK_WIDGET (window), 200, 100);
4650     gtk_window_set_title (GTK_WINDOW (window), "GTK Entry");
4651     g_signal_connect (G_OBJECT (window), "destroy",
4652                       G_CALLBACK (gtk_main_quit), NULL);
4653     g_signal_connect_swapped (G_OBJECT (window), "delete_event",
4654                               G_CALLBACK (gtk_widget_destroy), 
4655                               G_OBJECT (window));
4656
4657     vbox = gtk_vbox_new (FALSE, 0);
4658     gtk_container_add (GTK_CONTAINER (window), vbox);
4659     gtk_widget_show (vbox);
4660
4661     entry = gtk_entry_new ();
4662     gtk_entry_set_max_length (GTK_ENTRY (entry), 50);
4663     g_signal_connect (G_OBJECT (entry), "activate",
4664                       G_CALLBACK (enter_callback),
4665                       (gpointer) entry);
4666     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
4667     tmp_pos = GTK_ENTRY (entry)-&gt;text_length;
4668     gtk_editable_insert_text (GTK_EDITABLE (entry), " world", -1, &amp;tmp_pos);
4669     gtk_editable_select_region (GTK_EDITABLE (entry),
4670                                 0, GTK_ENTRY (entry)-&gt;text_length);
4671     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4672     gtk_widget_show (entry);
4673
4674     hbox = gtk_hbox_new (FALSE, 0);
4675     gtk_container_add (GTK_CONTAINER (vbox), hbox);
4676     gtk_widget_show (hbox);
4677                                   
4678     check = gtk_check_button_new_with_label ("Editable");
4679     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4680     g_signal_connect (G_OBJECT (check), "toggled",
4681                       G_CALLBACK (entry_toggle_editable), (gpointer) entry);
4682     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
4683     gtk_widget_show (check);
4684     
4685     check = gtk_check_button_new_with_label ("Visible");
4686     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4687     g_signal_connect (G_OBJECT (check), "toggled",
4688                       G_CALLBACK (entry_toggle_visibility), (gpointer) entry);
4689     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
4690     gtk_widget_show (check);
4691                                    
4692     button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
4693     g_signal_connect_swapped (G_OBJECT (button), "clicked",
4694                               G_CALLBACK (gtk_widget_destroy),
4695                               G_OBJECT (window));
4696     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4697     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4698     gtk_widget_grab_default (button);
4699     gtk_widget_show (button);
4700     
4701     gtk_widget_show (window);
4702
4703     gtk_main();
4704
4705     return 0;
4706 }
4707 <!-- example-end -->
4708 </programlisting>
4709
4710 </sect1>
4711
4712 <!-- ----------------------------------------------------------------- -->
4713 <sect1 id="sec-SpinButtons">
4714 <title>Spin Buttons</title>
4715
4716 <para>The Spin Button widget is generally used to allow the user to select a
4717 value from a range of numeric values. It consists of a text
4718 entry box with up and down arrow buttons attached to the
4719 side. Selecting one of the buttons causes the value to "spin" up and
4720 down the range of possible values. The entry box may also be edited
4721 directly to enter a specific value.</para>
4722
4723 <para>The Spin Button allows the value to have zero or a number of decimal
4724 places and to be incremented/decremented in configurable steps. The
4725 action of holding down one of the buttons optionally results in an
4726 acceleration of change in the value according to how long it is
4727 depressed.</para>
4728
4729 <para>The Spin Button uses an <link linkend="ch-Adjustments">Adjustment</link>
4730 object to hold information about the range of values that the spin
4731 button can take. This makes for a powerful Spin Button widget.</para>
4732
4733 <para>Recall that an adjustment widget is created with the following
4734 function, which illustrates the information that it holds:</para>
4735
4736 <programlisting role="C">
4737 GtkObject *gtk_adjustment_new( gdouble value,
4738                                gdouble lower,
4739                                gdouble upper,
4740                                gdouble step_increment,
4741                                gdouble page_increment,
4742                                gdouble page_size );
4743 </programlisting>
4744
4745 <para>These attributes of an Adjustment are used by the Spin Button in the
4746 following way:</para>
4747
4748 <itemizedlist>
4749 <listitem><simpara> <literal>value</literal>: initial value for the Spin Button</simpara>
4750 </listitem>
4751 <listitem><simpara> <literal>lower</literal>: lower range value</simpara>
4752 </listitem>
4753 <listitem><simpara> <literal>upper</literal>: upper range value</simpara>
4754 </listitem>
4755 <listitem><simpara> <literal>step_increment</literal>: value to increment/decrement when pressing
4756 mouse button 1 on a button</simpara>
4757 </listitem>
4758 <listitem><simpara> <literal>page_increment</literal>: value to increment/decrement when pressing
4759 mouse button 2 on a button</simpara>
4760 </listitem>
4761 <listitem><simpara> <literal>page_size</literal>: unused</simpara>
4762 </listitem>
4763 </itemizedlist>
4764
4765 <para>Additionally, mouse button 3 can be used to jump directly to the
4766 <literal>upper</literal> or <literal>lower</literal> values when used to select one of the
4767 buttons. Lets look at how to create a Spin Button:</para>
4768
4769 <programlisting role="C">
4770 GtkWidget *gtk_spin_button_new( GtkAdjustment *adjustment,
4771                                 gdouble        climb_rate,
4772                                 guint          digits );
4773 </programlisting>
4774
4775 <para>The <literal>climb_rate</literal> argument take a value between 0.0 and 1.0 and
4776 indicates the amount of acceleration that the Spin Button has. The
4777 <literal>digits</literal> argument specifies the number of decimal places to which
4778 the value will be displayed.</para>
4779
4780 <para>A Spin Button can be reconfigured after creation using the following
4781 function:</para>
4782
4783 <programlisting role="C">
4784 void gtk_spin_button_configure( GtkSpinButton *spin_button,
4785                                 GtkAdjustment *adjustment,
4786                                 gdouble        climb_rate,
4787                                 guint          digits );
4788 </programlisting>
4789
4790 <para>The <literal>spin_button</literal> argument specifies the Spin Button widget that is
4791 to be reconfigured. The other arguments are as specified above.</para>
4792
4793 <para>The adjustment can be set and retrieved independantly using the
4794 following two functions:</para>
4795
4796 <programlisting role="C">
4797 void gtk_spin_button_set_adjustment( GtkSpinButton  *spin_button,
4798                                      GtkAdjustment  *adjustment );
4799
4800 GtkAdjustment *gtk_spin_button_get_adjustment( GtkSpinButton *spin_button );
4801 </programlisting>
4802
4803 <para>The number of decimal places can also be altered using:</para>
4804
4805 <programlisting role="C">
4806 void gtk_spin_button_set_digits( GtkSpinButton *spin_button,
4807                                  guint          digits) ;
4808 </programlisting>
4809
4810 <para>The value that a Spin Button is currently displaying can be changed
4811 using the following function:</para>
4812
4813 <programlisting role="C">
4814 void gtk_spin_button_set_value( GtkSpinButton *spin_button,
4815                                 gdouble        value );
4816 </programlisting>
4817
4818 <para>The current value of a Spin Button can be retrieved as either a
4819 floating point or integer value with the following functions:</para>
4820
4821 <programlisting role="C">
4822 gdouble gtk_spin_button_get_value ( GtkSpinButton *spin_button );
4823
4824 gint gtk_spin_button_get_value_as_int( GtkSpinButton *spin_button );
4825 </programlisting>
4826
4827 <para>If you want to alter the value of a Spin Button relative to its current
4828 value, then the following function can be used:</para>
4829
4830 <programlisting role="C">
4831 void gtk_spin_button_spin( GtkSpinButton *spin_button,
4832                            GtkSpinType    direction,
4833                            gdouble        increment );
4834 </programlisting>
4835
4836 <para>The <literal>direction</literal> parameter can take one of the following values:</para>
4837
4838 <programlisting role="C">
4839   GTK_SPIN_STEP_FORWARD
4840   GTK_SPIN_STEP_BACKWARD
4841   GTK_SPIN_PAGE_FORWARD
4842   GTK_SPIN_PAGE_BACKWARD
4843   GTK_SPIN_HOME
4844   GTK_SPIN_END
4845   GTK_SPIN_USER_DEFINED
4846 </programlisting>
4847
4848 <para>This function packs in quite a bit of functionality, which I will
4849 attempt to clearly explain. Many of these settings use values from the
4850 Adjustment object that is associated with a Spin Button.</para>
4851
4852 <para><literal>GTK_SPIN_STEP_FORWARD</literal> and <literal>GTK_SPIN_STEP_BACKWARD</literal> change the
4853 value of the Spin Button by the amount specified by <literal>increment</literal>,
4854 unless <literal>increment</literal> is equal to 0, in which case the value is
4855 changed by the value of <literal>step_increment</literal> in theAdjustment.</para>
4856
4857 <para><literal>GTK_SPIN_PAGE_FORWARD</literal> and <literal>GTK_SPIN_PAGE_BACKWARD</literal> simply
4858 alter the value of the Spin Button by <literal>increment</literal>.</para>
4859
4860 <para><literal>GTK_SPIN_HOME</literal> sets the value of the Spin Button to the bottom of
4861 the Adjustments range.</para>
4862
4863 <para><literal>GTK_SPIN_END</literal> sets the value of the Spin Button to the top of the
4864 Adjustments range.</para>
4865
4866 <para><literal>GTK_SPIN_USER_DEFINED</literal> simply alters the value of the Spin Button
4867 by the specified amount.</para>
4868
4869 <para>We move away from functions for setting and retreving the range attributes
4870 of the Spin Button now, and move onto functions that affect the
4871 appearance and behaviour of the Spin Button widget itself.</para>
4872
4873 <para>The first of these functions is used to constrain the text box of the
4874 Spin Button such that it may only contain a numeric value. This
4875 prevents a user from typing anything other than numeric values into
4876 the text box of a Spin Button:</para>
4877
4878 <programlisting role="C">
4879 void gtk_spin_button_set_numeric( GtkSpinButton *spin_button,
4880                                   gboolean       numeric );
4881 </programlisting>
4882
4883 <para>You can set whether a Spin Button will wrap around between the upper
4884 and lower range values with the following function:</para>
4885
4886 <programlisting role="C">
4887 void gtk_spin_button_set_wrap( GtkSpinButton *spin_button,
4888                                gboolean       wrap );
4889 </programlisting>
4890
4891 <para>You can set a Spin Button to round the value to the nearest
4892 <literal>step_increment</literal>, which is set within the Adjustment object used
4893 with the Spin Button. This is accomplished with the following
4894 function:</para>
4895
4896 <programlisting role="C">
4897 void gtk_spin_button_set_snap_to_ticks( GtkSpinButton  *spin_button,
4898                                         gboolean        snap_to_ticks );
4899 </programlisting>
4900
4901 <para>The update policy of a Spin Button can be changed with the following
4902 function:</para>
4903
4904 <programlisting role="C">
4905 void gtk_spin_button_set_update_policy( GtkSpinButton  *spin_button,
4906                                         GtkSpinButtonUpdatePolicy policy );
4907 </programlisting>
4908
4909 <para>The possible values of <literal>policy</literal> are either <literal>GTK_UPDATE_ALWAYS</literal> or
4910 <literal>GTK_UPDATE_IF_VALID</literal>.</para>
4911
4912 <para>These policies affect the behavior of a Spin Button when parsing
4913 inserted text and syncing its value with the values of the
4914 Adjustment.</para>
4915
4916 <para>In the case of <literal>GTK_UPDATE_IF_VALID</literal> the Spin Button value only
4917 gets changed if the text input is a numeric value that is within the
4918 range specified by the Adjustment. Otherwise the text is reset to the
4919 current value.</para>
4920
4921 <para>In case of <literal>GTK_UPDATE_ALWAYS</literal> we ignore errors while converting
4922 text into a numeric value.</para>
4923
4924 <para>Finally, you can explicitly request that a Spin Button update itself:</para>
4925
4926 <programlisting role="C">
4927 void gtk_spin_button_update( GtkSpinButton  *spin_button );
4928 </programlisting>
4929
4930 <para>It's example time again.</para>
4931
4932 <para>
4933 <inlinemediaobject>
4934 <imageobject>
4935 <imagedata fileref="images/spinbutton.png" format="png">
4936 </imageobject>
4937 </inlinemediaobject>
4938 </para>
4939
4940 <programlisting role="C">
4941 <!-- example-start spinbutton spinbutton.c -->
4942
4943 #include &lt;stdio.h&gt;
4944 #include &lt;gtk/gtk.h&gt;
4945
4946 static GtkWidget *spinner1;
4947
4948 static void toggle_snap( GtkWidget     *widget,
4949                          GtkSpinButton *spin )
4950 {
4951   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)-&gt;active);
4952 }
4953
4954 static void toggle_numeric( GtkWidget *widget,
4955                             GtkSpinButton *spin )
4956 {
4957   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)-&gt;active);
4958 }
4959
4960 static void change_digits( GtkWidget *widget,
4961                            GtkSpinButton *spin )
4962 {
4963   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
4964                               gtk_spin_button_get_value_as_int (spin));
4965 }
4966
4967 static void get_value( GtkWidget *widget,
4968                        gpointer data )
4969 {
4970   gchar *buf;
4971   GtkLabel *label;
4972   GtkSpinButton *spin;
4973
4974   spin = GTK_SPIN_BUTTON (spinner1);
4975   label = GTK_LABEL (g_object_get_data (G_OBJECT (widget), "user_data"));
4976   if (GPOINTER_TO_INT (data) == 1)
4977     buf = g_strdup_printf ("%d", gtk_spin_button_get_value_as_int (spin));
4978   else
4979     buf = g_strdup_printf ("%0.*f", spin-&gt;digits,
4980                            gtk_spin_button_get_value (spin));
4981   gtk_label_set_text (label, buf);
4982   g_free (buf);
4983 }
4984
4985
4986 int main( int   argc,
4987           char *argv[] )
4988 {
4989   GtkWidget *window;
4990   GtkWidget *frame;
4991   GtkWidget *hbox;
4992   GtkWidget *main_vbox;
4993   GtkWidget *vbox;
4994   GtkWidget *vbox2;
4995   GtkWidget *spinner2;
4996   GtkWidget *spinner;
4997   GtkWidget *button;
4998   GtkWidget *label;
4999   GtkWidget *val_label;
5000   GtkAdjustment *adj;
5001
5002   /* Initialise GTK */
5003   gtk_init (&amp;argc, &amp;argv);
5004
5005   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5006
5007   g_signal_connect (G_OBJECT (window), "destroy",
5008                     G_CALLBACK (gtk_main_quit),
5009                     NULL);
5010
5011   gtk_window_set_title (GTK_WINDOW (window), "Spin Button");
5012
5013   main_vbox = gtk_vbox_new (FALSE, 5);
5014   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5015   gtk_container_add (GTK_CONTAINER (window), main_vbox);
5016   
5017   frame = gtk_frame_new ("Not accelerated");
5018   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5019   
5020   vbox = gtk_vbox_new (FALSE, 0);
5021   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5022   gtk_container_add (GTK_CONTAINER (frame), vbox);
5023   
5024   /* Day, month, year spinners */
5025   
5026   hbox = gtk_hbox_new (FALSE, 0);
5027   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5028   
5029   vbox2 = gtk_vbox_new (FALSE, 0);
5030   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5031   
5032   label = gtk_label_new ("Day :");
5033   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5034   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5035   
5036   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 31.0, 1.0,
5037                                               5.0, 0.0);
5038   spinner = gtk_spin_button_new (adj, 0, 0);
5039   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5040   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5041   
5042   vbox2 = gtk_vbox_new (FALSE, 0);
5043   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5044   
5045   label = gtk_label_new ("Month :");
5046   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5047   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5048   
5049   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5050                                               5.0, 0.0);
5051   spinner = gtk_spin_button_new (adj, 0, 0);
5052   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5053   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5054   
5055   vbox2 = gtk_vbox_new (FALSE, 0);
5056   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5057   
5058   label = gtk_label_new ("Year :");
5059   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5060   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5061   
5062   adj = (GtkAdjustment *) gtk_adjustment_new (1998.0, 0.0, 2100.0,
5063                                               1.0, 100.0, 0.0);
5064   spinner = gtk_spin_button_new (adj, 0, 0);
5065   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), FALSE);
5066   gtk_widget_set_size_request (spinner, 55, -1);
5067   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5068   
5069   frame = gtk_frame_new ("Accelerated");
5070   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5071   
5072   vbox = gtk_vbox_new (FALSE, 0);
5073   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5074   gtk_container_add (GTK_CONTAINER (frame), vbox);
5075   
5076   hbox = gtk_hbox_new (FALSE, 0);
5077   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5078   
5079   vbox2 = gtk_vbox_new (FALSE, 0);
5080   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5081   
5082   label = gtk_label_new ("Value :");
5083   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5084   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5085   
5086   adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
5087                                               0.5, 100.0, 0.0);
5088   spinner1 = gtk_spin_button_new (adj, 1.0, 2);
5089   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
5090   gtk_widget_set_size_request (spinner1, 100, -1);
5091   gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
5092   
5093   vbox2 = gtk_vbox_new (FALSE, 0);
5094   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5095   
5096   label = gtk_label_new ("Digits :");
5097   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5098   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5099   
5100   adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 5, 1, 1, 0);
5101   spinner2 = gtk_spin_button_new (adj, 0.0, 0);
5102   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner2), TRUE);
5103   g_signal_connect (G_OBJECT (adj), "value_changed",
5104                     G_CALLBACK (change_digits),
5105                     (gpointer) spinner2);
5106   gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
5107   
5108   hbox = gtk_hbox_new (FALSE, 0);
5109   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5110   
5111   button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
5112   g_signal_connect (G_OBJECT (button), "clicked",
5113                     G_CALLBACK (toggle_snap),
5114                     (gpointer) spinner1);
5115   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5116   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5117   
5118   button = gtk_check_button_new_with_label ("Numeric only input mode");
5119   g_signal_connect (G_OBJECT (button), "clicked",
5120                     G_CALLBACK (toggle_numeric),
5121                     (gpointer) spinner1);
5122   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5123   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5124   
5125   val_label = gtk_label_new ("");
5126   
5127   hbox = gtk_hbox_new (FALSE, 0);
5128   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5129   button = gtk_button_new_with_label ("Value as Int");
5130   g_object_set_data (G_OBJECT (button), "user_data", val_label);
5131   g_signal_connect (G_OBJECT (button), "clicked",
5132                     G_CALLBACK (get_value),
5133                     GINT_TO_POINTER (1));
5134   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5135   
5136   button = gtk_button_new_with_label ("Value as Float");
5137   g_object_set_data (G_OBJECT (button), "user_data", val_label);
5138   g_signal_connect (G_OBJECT (button), "clicked",
5139                     G_CALLBACK (get_value),
5140                     GINT_TO_POINTER (2));
5141   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5142   
5143   gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
5144   gtk_label_set_text (GTK_LABEL (val_label), "0");
5145   
5146   hbox = gtk_hbox_new (FALSE, 0);
5147   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5148   
5149   button = gtk_button_new_with_label ("Close");
5150   g_signal_connect_swapped (G_OBJECT (button), "clicked",
5151                             G_CALLBACK (gtk_widget_destroy),
5152                             G_OBJECT (window));
5153   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5154
5155   gtk_widget_show_all (window);
5156
5157   /* Enter the event loop */
5158   gtk_main ();
5159     
5160   return 0;
5161 }
5162
5163 <!-- example-end -->
5164 </programlisting>
5165
5166 </sect1>
5167
5168 <!-- ----------------------------------------------------------------- -->
5169 <sect1 id="sec-ComboBox">
5170 <title>Combo Box</title>
5171
5172 <para>The combo box is another fairly simple widget that is really just a
5173 collection of other widgets. From the user's point of view, the widget
5174 consists of a text entry box and a pull down menu from which the user
5175 can select one of a set of predefined entries. Alternatively, the user
5176 can type a different option directly into the text box.</para>
5177
5178 <para>The following extract from the structure that defines a Combo Box
5179 identifies several of the components:</para>
5180
5181 <programlisting role="C">
5182 struct _GtkCombo { 
5183         GtkHBox hbox; 
5184         GtkWidget *entry; 
5185         GtkWidget *button;
5186         GtkWidget *popup; 
5187         GtkWidget *popwin; 
5188         GtkWidget *list;
5189         ...  };
5190 </programlisting>
5191
5192 <para>As you can see, the Combo Box has two principal parts that you really
5193 care about: an entry and a list.</para>
5194
5195 <para>First off, to create a combo box, use:</para>
5196
5197 <programlisting role="C">
5198 GtkWidget *gtk_combo_new( void );
5199 </programlisting>
5200
5201 <para>Now, if you want to set the string in the entry section of the combo
5202 box, this is done by manipulating the <literal>entry</literal> widget directly:</para>
5203
5204 <programlisting role="C">
5205     gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo)->entry), "My String.");
5206 </programlisting>
5207
5208 <para>To set the values in the popdown list, one uses the function:</para>
5209
5210 <programlisting role="C">
5211 void gtk_combo_set_popdown_strings( GtkCombo *combo,
5212                                     GList    *strings );
5213 </programlisting>
5214
5215 <para>Before you can do this, you have to assemble a GList of the strings
5216 that you want. GList is a linked list implementation that is part of
5217 <link linkend="ch-GLib">GLib</link>, a library supporting GTK. For the
5218 moment, the quick and dirty explanation is that you need to set up a
5219 GList pointer, set it equal to NULL, then append strings to it with</para>
5220
5221 <programlisting role="C">
5222 GList *g_list_append( GList *glist, 
5223                       gpointer data );
5224 </programlisting>
5225
5226 <para>It is important that you set the initial GList pointer to NULL. The
5227 value returned from the g_list_append() function must be used as the new
5228 pointer to the GList.</para>
5229
5230 <para>Here's a typical code segment for creating a set of options:</para>
5231
5232 <programlisting role="C">
5233     GList *glist = NULL;
5234
5235     glist = g_list_append (glist, "String 1");
5236     glist = g_list_append (glist, "String 2");
5237     glist = g_list_append (glist, "String 3"); 
5238     glist = g_list_append (glist, "String 4");
5239
5240     gtk_combo_set_popdown_strings (GTK_COMBO (combo), glist);
5241     
5242     /* can free glist now, combo takes a copy */
5243 </programlisting>
5244
5245 <para>The combo widget makes a copy of the strings passed to it in the glist
5246 structure. As a result, you need to make sure you free the memory used
5247 by the list if that is appropriate for your application.</para>
5248
5249 <para>At this point you have a working combo box that has been set up.
5250 There are a few aspects of its behavior that you can change. These
5251 are accomplished with the functions: </para>
5252
5253 <programlisting role="C">
5254 void gtk_combo_set_use_arrows( GtkCombo *combo,
5255                                gboolean  val );
5256
5257 void gtk_combo_set_use_arrows_always( GtkCombo *combo,
5258                                       gboolean  val );
5259
5260 void gtk_combo_set_case_sensitive( GtkCombo *combo,
5261                                    gboolean  val );
5262 </programlisting>
5263
5264 <para>gtk_combo_set_use_arrows() lets the user change the value in the
5265 entry using the up/down arrow keys. This doesn't bring up the list, but
5266 rather replaces the current text in the entry with the next list entry
5267 (up or down, as your key choice indicates). It does this by searching
5268 in the list for the item corresponding to the current value in the
5269 entry and selecting the previous/next item accordingly. Usually in an
5270 entry the arrow keys are used to change focus (you can do that anyway
5271 using TAB). Note that when the current item is the last of the list
5272 and you press arrow-down it changes the focus (the same applies with
5273 the first item and arrow-up).</para>
5274
5275 <para>If the current value in the entry is not in the list, then the
5276 function of gtk_combo_set_use_arrows() is disabled.</para>
5277
5278 <para>gtk_combo_set_use_arrows_always() similarly allows the use the
5279 the up/down arrow keys to cycle through the choices in the dropdown
5280 list, except that it wraps around the values in the list, completely
5281 disabling the use of the up and down arrow keys for changing focus.</para>
5282
5283 <para>gtk_combo_set_case_sensitive() toggles whether or not GTK
5284 searches for entries in a case sensitive manner. This is used when the
5285 Combo widget is asked to find a value from the list using the current
5286 entry in the text box. This completion can be performed in either a
5287 case sensitive or insensitive manner, depending upon the use of this
5288 function. The Combo widget can also simply complete the current entry
5289 if the user presses the key combination MOD-1 and "Tab". MOD-1 is
5290 often mapped to the "Alt" key, by the <literal>xmodmap</literal> utility. Note,
5291 however that some window managers also use this key combination, which
5292 will override its use within GTK.</para>
5293
5294 <para>Now that we have a combo box, tailored to look and act how we want it,
5295 all that remains is being able to get data from the combo box. This is
5296 relatively straightforward. The majority of the time, all you are
5297 going to care about getting data from is the entry. The entry is
5298 accessed simply by <literal>GTK_ENTRY (GTK_COMBO (combo)->entry)</literal>. The
5299 two principal things that you are going to want to do with it are
5300 connect to the activate signal, which indicates that the user has
5301 pressed the Return or Enter key, and read the text. The first is
5302 accomplished using something like:</para>
5303
5304 <programlisting role="C">
5305     g_signal_connect (G_OBJECT (GTK_COMBO (combo)->entry), "activate",
5306                       G_CALLBACK (my_callback_function), (gpointer) my_data);
5307 </programlisting>
5308
5309 <para>Getting the text at any arbitrary time is accomplished by simply using
5310 the entry function:</para>
5311
5312 <programlisting role="C">
5313 gchar *gtk_entry_get_text( GtkEntry *entry );
5314 </programlisting>
5315
5316 <para>Such as:</para>
5317
5318 <programlisting role="C">
5319     gchar *string;
5320
5321     string = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (combo)->entry));
5322 </programlisting>
5323
5324 <para>That's about all there is to it. There is a function</para>
5325
5326 <programlisting role="C">
5327 void gtk_combo_disable_activate( GtkCombo *combo );
5328 </programlisting>
5329
5330 <para>that will disable the activate signal on the entry widget in the combo
5331 box. Personally, I can't think of why you'd want to use it, but it
5332 does exist.</para>
5333
5334 <!-- There is also a function to set the string on a particular item, void
5335 gtk_combo_set_item_string(GtkCombo *combo, GtkItem *item, const gchar
5336 *item_value), but this requires that you have a pointer to the
5337 appropriate Item. Frankly, I have no idea how to do that.
5338 -->
5339
5340 </sect1>
5341
5342 <!-- ----------------------------------------------------------------- -->
5343 <sect1 id="sec-Calendar">
5344 <title>Calendar</title>
5345
5346 <para>The Calendar widget is an effective way to display and retrieve
5347 monthly date related information. It is a very simple widget to create
5348 and work with.</para>
5349
5350 <para>Creating a GtkCalendar widget is a simple as: </para>
5351
5352 <programlisting role="C">
5353 GtkWidget *gtk_calendar_new( void );
5354 </programlisting>
5355
5356 <para>There might be times where you need to change a lot of information
5357 within this widget and the following functions allow you to make
5358 multiple change to a Calendar widget without the user seeing multiple
5359 on-screen updates.</para>
5360
5361 <programlisting role="C">
5362 void gtk_calendar_freeze( GtkCalendar *Calendar );
5363
5364 void gtk_calendar_thaw( GtkCalendar *Calendar );
5365 </programlisting>
5366
5367 <para>They work just like the freeze/thaw functions of every other
5368 widget.</para>
5369
5370 <para>The Calendar widget has a few options that allow you to change the way
5371 the widget both looks and operates by using the function</para>
5372
5373 <programlisting role="C">
5374 void gtk_calendar_display_options( GtkCalendar               *calendar,
5375                                    GtkCalendarDisplayOptions  flags );
5376 </programlisting>
5377
5378 <para>The <literal>flags</literal> argument can be formed by combining either of the
5379 following five options using the logical bitwise OR (|) operation:</para>
5380
5381 <variablelist>
5382 <varlistentry>
5383 <term><literal>GTK_CALENDAR_SHOW_HEADING</literal></term>
5384 <listitem><para>this option specifies that the month and year should be shown 
5385 when drawing the calendar.</para>
5386 </listitem>
5387 </varlistentry>
5388 <varlistentry>
5389 <term><literal>GTK_CALENDAR_SHOW_DAY_NAMES</literal></term>
5390 <listitem><para>this option specifies that the three letter descriptions should 
5391 be displayed for each day (eg Mon,Tue, etc.).</para>
5392 </listitem>
5393 </varlistentry>
5394 <varlistentry>
5395 <term><literal>GTK_CALENDAR_NO_MONTH_CHANGE</literal></term>
5396 <listitem><para>this option states that the user
5397 should not and can not change the currently displayed month. This can
5398 be good if you only need to display a particular month such as if you
5399 are displaying 12 calendar widgets for every month in a particular
5400 year.</para>
5401 </listitem>
5402 </varlistentry>
5403 <varlistentry>
5404 <term><literal>GTK_CALENDAR_SHOW_WEEK_NUMBERS</literal></term>
5405 <listitem><para>this option specifies that the
5406 number for each week should be displayed down the left side of the
5407 calendar. (eg. Jan 1 = Week 1,Dec 31 = Week 52).</para>
5408 </listitem>
5409 </varlistentry>
5410 <varlistentry>
5411 <term><literal>GTK_CALENDAR_WEEK_START_MONDAY</literal></term>
5412 <listitem><para>this option states that the
5413 calander week will start on Monday instead of Sunday which is the
5414 default. This only affects the order in which days are displayed from
5415 left to right.</para>
5416 </listitem>
5417 </varlistentry>
5418 </variablelist>
5419
5420 <para>The following functions are used to set the the currently displayed
5421 date:</para>
5422
5423 <programlisting role="C">
5424 gint gtk_calendar_select_month( GtkCalendar *calendar, 
5425                                 guint        month,
5426                                 guint        year );
5427
5428 void gtk_calendar_select_day( GtkCalendar *calendar,
5429                               guint        day );
5430 </programlisting>
5431
5432 <para>The return value from <literal>gtk_calendar_select_month()</literal> is a boolean
5433 value indicating whether the selection was successful.</para>
5434
5435 <para>With <literal>gtk_calendar_select_day()</literal> the specified day number is
5436 selected within the current month, if that is possible. A
5437 <literal>day</literal> value of 0 will deselect any current selection.</para>
5438
5439 <para>In addition to having a day selected, any number of days in the month
5440 may be "marked". A marked day is highlighted within the calendar
5441 display. The following functions are provided to manipulate marked
5442 days:</para>
5443
5444 <programlisting role="C">
5445 gint gtk_calendar_mark_day( GtkCalendar *calendar,
5446                             guint        day);
5447
5448 gint gtk_calendar_unmark_day( GtkCalendar *calendar,
5449                               guint        day);
5450
5451 void gtk_calendar_clear_marks( GtkCalendar *calendar);
5452 </programlisting>
5453
5454 <para>The currently marked days are stored within an array within the
5455 GtkCalendar structure. This array is 31 elements long so to test
5456 whether a particular day is currently marked, you need to access the
5457 corresponding element of the array (don't forget in C that array
5458 elements are numbered 0 to n-1). For example:</para>
5459
5460 <programlisting role="C">
5461     GtkCalendar *calendar;
5462     calendar = gtk_calendar_new ();
5463
5464     ...
5465
5466     /* Is day 7 marked? */
5467     if (calendar->marked_date[7-1])
5468        /* day is marked */
5469 </programlisting>
5470
5471 <para>Note that marks are persistent across month and year changes.</para>
5472
5473 <para>The final Calendar widget function is used to retrieve the currently
5474 selected date, month and/or year.</para>
5475
5476 <programlisting role="C">
5477 void gtk_calendar_get_date( GtkCalendar *calendar, 
5478                             guint       *year,
5479                             guint       *month,
5480                             guint       *day );
5481 </programlisting>
5482
5483 <para>This function requires you to pass the addresses of <literal>guint</literal>
5484 variables, into which the result will be placed. Passing <literal>NULL</literal> as
5485 a value will result in the corresponding value not being returned.</para>
5486
5487 <para>The Calendar widget can generate a number of signals indicating date
5488 selection and change. The names of these signals are self explanatory,
5489 and are:</para>
5490
5491 <itemizedlist>
5492 <listitem><simpara> <literal>month_changed</literal></simpara>
5493 </listitem>
5494 <listitem><simpara> <literal>day_selected</literal></simpara>
5495 </listitem>
5496 <listitem><simpara> <literal>day_selected_double_click</literal></simpara>
5497 </listitem>
5498 <listitem><simpara> <literal>prev_month</literal></simpara>
5499 </listitem>
5500 <listitem><simpara> <literal>next_month</literal></simpara>
5501 </listitem>
5502 <listitem><simpara> <literal>prev_year</literal></simpara>
5503 </listitem>
5504 <listitem><simpara> <literal>next_year</literal></simpara>
5505 </listitem>
5506 </itemizedlist>
5507
5508 <para>That just leaves us with the need to put all of this together into
5509 example code.</para>
5510
5511 <para>
5512 <inlinemediaobject>
5513 <imageobject>
5514 <imagedata fileref="images/calendar.png" format="png">
5515 </imageobject>
5516 </inlinemediaobject>
5517 </para>
5518
5519 <programlisting role="C">
5520 <!-- example-start calendar calendar.c -->
5521 /*
5522  * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson, Mattias Gr�nlund
5523  * Copyright (C) 2000 Tony Gale
5524  *
5525  * This program is free software; you can redistribute it and/or modify
5526  * it under the terms of the GNU General Public License as published by
5527  * the Free Software Foundation; either version 2 of the License, or
5528  * (at your option) any later version.
5529  *
5530  * This program is distributed in the hope that it will be useful,
5531  * but WITHOUT ANY WARRANTY; without even the implied warranty of
5532  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5533  * GNU General Public License for more details.
5534  *
5535  * You should have received a copy of the GNU General Public License
5536  * along with this program; if not, write to the Free Software
5537  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5538  */
5539
5540 #include &lt;stdio.h&gt;
5541 #include &lt;string.h&gt;
5542 #include &lt;gtk/gtk.h&gt;
5543
5544 #define DEF_PAD 10
5545 #define DEF_PAD_SMALL 5
5546
5547 #define TM_YEAR_BASE 1900
5548
5549 typedef struct _CalendarData {
5550   GtkWidget *flag_checkboxes[5];
5551   gboolean  settings[5];
5552   GtkWidget *font_dialog;
5553   GtkWidget *window;
5554   GtkWidget *prev2_sig;
5555   GtkWidget *prev_sig;
5556   GtkWidget *last_sig;
5557   GtkWidget *month;
5558 } CalendarData;
5559
5560 enum {
5561   calendar_show_header,
5562   calendar_show_days,
5563   calendar_month_change, 
5564   calendar_show_week,
5565   calendar_monday_first
5566 };
5567
5568 /*
5569  * GtkCalendar
5570  */
5571
5572 static void calendar_date_to_string( CalendarData *data,
5573                                      char         *buffer,
5574                                      gint          buff_len )
5575 {
5576   GDate date;
5577   guint year, month, day;
5578
5579   gtk_calendar_get_date (GTK_CALENDAR (data-&gt;window),
5580                          &amp;year, &amp;month, &amp;day);
5581   g_date_set_dmy (&amp;date, day, month + 1, year);
5582   g_date_strftime (buffer, buff_len - 1, "%x", &amp;date);
5583
5584 }
5585
5586 static void calendar_set_signal_strings( char         *sig_str,
5587                                          CalendarData *data )
5588 {
5589   const gchar *prev_sig;
5590
5591   prev_sig = gtk_label_get_text (GTK_LABEL (data-&gt;prev_sig));
5592   gtk_label_set_text (GTK_LABEL (data-&gt;prev2_sig), prev_sig);
5593
5594   prev_sig = gtk_label_get_text (GTK_LABEL (data-&gt;last_sig));
5595   gtk_label_set_text (GTK_LABEL (data-&gt;prev_sig), prev_sig);
5596   gtk_label_set_text (GTK_LABEL (data-&gt;last_sig), sig_str);
5597 }
5598
5599 static void calendar_month_changed( GtkWidget    *widget,
5600                                     CalendarData *data )
5601 {
5602   char buffer[256] = "month_changed: ";
5603
5604   calendar_date_to_string (data, buffer + 15, 256 - 15);
5605   calendar_set_signal_strings (buffer, data);
5606 }
5607
5608 static void calendar_day_selected( GtkWidget    *widget,
5609                                    CalendarData *data )
5610 {
5611   char buffer[256] = "day_selected: ";
5612
5613   calendar_date_to_string (data, buffer + 14, 256 - 14);
5614   calendar_set_signal_strings (buffer, data);
5615 }
5616
5617 static void calendar_day_selected_double_click ( GtkWidget    *widget,
5618                                                  CalendarData *data )
5619 {
5620   char buffer[256] = "day_selected_double_click: ";
5621   guint day;
5622
5623   calendar_date_to_string (data, buffer + 27, 256 - 27);
5624   calendar_set_signal_strings (buffer, data);
5625
5626   gtk_calendar_get_date (GTK_CALENDAR (data-&gt;window),
5627                          NULL, NULL, &amp;day);
5628
5629   if (GTK_CALENDAR (data-&gt;window)-&gt;marked_date[day-1] == 0) {
5630     gtk_calendar_mark_day (GTK_CALENDAR (data-&gt;window), day);
5631   } else { 
5632     gtk_calendar_unmark_day (GTK_CALENDAR (data-&gt;window), day);
5633   }
5634 }
5635
5636 static void calendar_prev_month( GtkWidget    *widget,
5637                                  CalendarData *data )
5638 {
5639   char buffer[256] = "prev_month: ";
5640
5641   calendar_date_to_string (data, buffer + 12, 256 - 12);
5642   calendar_set_signal_strings (buffer, data);
5643 }
5644
5645 static void calendar_next_month( GtkWidget    *widget,
5646                                  CalendarData *data )
5647 {
5648   char buffer[256] = "next_month: ";
5649
5650   calendar_date_to_string (data, buffer + 12, 256 - 12);
5651   calendar_set_signal_strings (buffer, data);
5652 }
5653
5654 static void calendar_prev_year( GtkWidget    *widget,
5655                                 CalendarData *data )
5656 {
5657   char buffer[256] = "prev_year: ";
5658
5659   calendar_date_to_string (data, buffer + 11, 256 - 11);
5660   calendar_set_signal_strings (buffer, data);
5661 }
5662
5663 static void calendar_next_year( GtkWidget    *widget,
5664                                 CalendarData *data )
5665 {
5666   char buffer[256] = "next_year: ";
5667
5668   calendar_date_to_string (data, buffer + 11, 256 - 11);
5669   calendar_set_signal_strings (buffer, data);
5670 }
5671
5672
5673 static void calendar_set_flags( CalendarData *calendar )
5674 {
5675   gint i;
5676   gint options = 0;
5677   for (i = 0;i &lt; 5; i++) 
5678     if (calendar-&gt;settings[i])
5679       {
5680         options = options + (1 &lt;&lt; i);
5681       }
5682   if (calendar-&gt;window)
5683     gtk_calendar_display_options (GTK_CALENDAR (calendar-&gt;window), options);
5684 }
5685
5686 static void calendar_toggle_flag( GtkWidget    *toggle,
5687                                   CalendarData *calendar)
5688 {
5689   gint i;
5690   gint j;
5691   j = 0;
5692   for (i = 0; i &lt; 5; i++)
5693     if (calendar-&gt;flag_checkboxes[i] == toggle)
5694       j = i;
5695
5696   calendar-&gt;settings[j] = !calendar-&gt;settings[j];
5697   calendar_set_flags (calendar);
5698   
5699 }
5700
5701 static void calendar_font_selection_ok( GtkWidget    *button,
5702                                         CalendarData *calendar )
5703 {
5704   GtkRcStyle *style;
5705   char *font_name;
5706
5707   if (calendar-&gt;window)
5708     {
5709       font_name = gtk_font_selection_dialog_get_font_name (GTK_FONT_SELECTION_DIALOG (calendar-&gt;font_dialog));
5710       if (font_name) 
5711         {
5712           style = gtk_rc_style_new ();
5713           pango_font_description_free (style-&gt;font_desc);
5714           style-&gt;font_desc = pango_font_description_from_string (font_name);
5715           gtk_widget_modify_style (calendar-&gt;window, style);
5716           g_free (font_name);
5717         }
5718     }
5719
5720   gtk_widget_destroy (calendar-&gt;font_dialog);
5721 }
5722
5723 static void calendar_select_font( GtkWidget    *button,
5724                                   CalendarData *calendar )
5725 {
5726   GtkWidget *window;
5727
5728   if (!calendar-&gt;font_dialog) {
5729     window = gtk_font_selection_dialog_new ("Font Selection Dialog");
5730     g_return_if_fail (GTK_IS_FONT_SELECTION_DIALOG (window));
5731     calendar-&gt;font_dialog = window;
5732     
5733     gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
5734     
5735     g_signal_connect (window, "destroy",
5736                       G_CALLBACK (gtk_widget_destroyed),
5737                       &amp;calendar-&gt;font_dialog);
5738     
5739     g_signal_connect (GTK_FONT_SELECTION_DIALOG (window)-&gt;ok_button,
5740                       "clicked", G_CALLBACK (calendar_font_selection_ok),
5741                       calendar);
5742     g_signal_connect_swapped (GTK_FONT_SELECTION_DIALOG (window)-&gt;cancel_button,
5743                              "clicked", G_CALLBACK (gtk_widget_destroy), 
5744                              calendar-&gt;font_dialog);
5745   }
5746   window = calendar-&gt;font_dialog;
5747   if (!GTK_WIDGET_VISIBLE (window))
5748     gtk_widget_show (window);
5749   else
5750     gtk_widget_destroy (window);
5751
5752 }
5753
5754 static void create_calendar( void )
5755 {
5756   GtkWidget *window;
5757   GtkWidget *vbox, *vbox2, *vbox3;
5758   GtkWidget *hbox;
5759   GtkWidget *hbbox;
5760   GtkWidget *calendar;
5761   GtkWidget *toggle;
5762   GtkWidget *button;
5763   GtkWidget *frame;
5764   GtkWidget *separator;
5765   GtkWidget *label;
5766   GtkWidget *bbox;
5767   static CalendarData calendar_data;
5768   gint i;
5769   
5770   struct {
5771     char *label;
5772   } flags[] =
5773     {
5774       { "Show Heading" },
5775       { "Show Day Names" },
5776       { "No Month Change" },
5777       { "Show Week Numbers" },
5778       { "Week Start Monday" }
5779     };
5780
5781   
5782   calendar_data.window = NULL;
5783   calendar_data.font_dialog = NULL;
5784
5785   for (i = 0; i &lt; 5; i++) {
5786     calendar_data.settings[i] = 0;
5787   }
5788
5789   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5790   gtk_window_set_title (GTK_WINDOW (window), "GtkCalendar Example");
5791   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
5792   g_signal_connect (window, "destroy",
5793                     G_CALLBACK (gtk_main_quit),
5794                     NULL);
5795   g_signal_connect (window, "delete-event",
5796                     G_CALLBACK (gtk_false),
5797                     NULL);
5798   gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
5799
5800   vbox = gtk_vbox_new (FALSE, DEF_PAD);
5801   gtk_container_add (GTK_CONTAINER (window), vbox);
5802
5803   /*
5804    * The top part of the window, Calendar, flags and fontsel.
5805    */
5806
5807   hbox = gtk_hbox_new (FALSE, DEF_PAD);
5808   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, DEF_PAD);
5809   hbbox = gtk_hbutton_box_new ();
5810   gtk_box_pack_start (GTK_BOX (hbox), hbbox, FALSE, FALSE, DEF_PAD);
5811   gtk_button_box_set_layout (GTK_BUTTON_BOX (hbbox), GTK_BUTTONBOX_SPREAD);
5812   gtk_box_set_spacing (GTK_BOX (hbbox), 5);
5813
5814   /* Calendar widget */
5815   frame = gtk_frame_new ("Calendar");
5816   gtk_box_pack_start(GTK_BOX (hbbox), frame, FALSE, TRUE, DEF_PAD);
5817   calendar=gtk_calendar_new ();
5818   calendar_data.window = calendar;
5819   calendar_set_flags (&amp;calendar_data);
5820   gtk_calendar_mark_day (GTK_CALENDAR (calendar), 19);  
5821   gtk_container_add (GTK_CONTAINER (frame), calendar);
5822   g_signal_connect (calendar, "month_changed", 
5823                     G_CALLBACK (calendar_month_changed),
5824                     &amp;calendar_data);
5825   g_signal_connect (calendar, "day_selected", 
5826                     G_CALLBACK (calendar_day_selected),
5827                     &amp;calendar_data);
5828   g_signal_connect (calendar, "day_selected_double_click", 
5829                     G_CALLBACK (calendar_day_selected_double_click),
5830                     &amp;calendar_data);
5831   g_signal_connect (calendar, "prev_month", 
5832                     G_CALLBACK (calendar_prev_month),
5833                     &amp;calendar_data);
5834   g_signal_connect (calendar, "next_month", 
5835                     G_CALLBACK (calendar_next_month),
5836                     &amp;calendar_data);
5837   g_signal_connect (calendar, "prev_year", 
5838                     G_CALLBACK (calendar_prev_year),
5839                     &amp;calendar_data);
5840   g_signal_connect (calendar, "next_year", 
5841                     G_CALLBACK (calendar_next_year),
5842                     &amp;calendar_data);
5843
5844
5845   separator = gtk_vseparator_new ();
5846   gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, TRUE, 0);
5847
5848   vbox2 = gtk_vbox_new (FALSE, DEF_PAD);
5849   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, DEF_PAD);
5850   
5851   /* Build the Right frame with the flags in */ 
5852
5853   frame = gtk_frame_new ("Flags");
5854   gtk_box_pack_start (GTK_BOX (vbox2), frame, TRUE, TRUE, DEF_PAD);
5855   vbox3 = gtk_vbox_new (TRUE, DEF_PAD_SMALL);
5856   gtk_container_add (GTK_CONTAINER (frame), vbox3);
5857
5858   for (i = 0; i &lt; 5; i++)
5859     {
5860       toggle = gtk_check_button_new_with_label (flags[i].label);
5861       g_signal_connect (toggle,
5862                         "toggled",
5863                         G_CALLBACK (calendar_toggle_flag),
5864                         &amp;calendar_data);
5865       gtk_box_pack_start (GTK_BOX (vbox3), toggle, TRUE, TRUE, 0);
5866       calendar_data.flag_checkboxes[i] = toggle;
5867     }
5868   /* Build the right font-button */ 
5869   button = gtk_button_new_with_label ("Font...");
5870   g_signal_connect (button,
5871                     "clicked",
5872                     G_CALLBACK (calendar_select_font),
5873                     &amp;calendar_data);
5874   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
5875
5876   /*
5877    *  Build the Signal-event part.
5878    */
5879
5880   frame = gtk_frame_new ("Signal events");
5881   gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, DEF_PAD);
5882
5883   vbox2 = gtk_vbox_new (TRUE, DEF_PAD_SMALL);
5884   gtk_container_add (GTK_CONTAINER (frame), vbox2);
5885   
5886   hbox = gtk_hbox_new (FALSE, 3);
5887   gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
5888   label = gtk_label_new ("Signal:");
5889   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5890   calendar_data.last_sig = gtk_label_new ("");
5891   gtk_box_pack_start (GTK_BOX (hbox), calendar_data.last_sig, FALSE, TRUE, 0);
5892
5893   hbox = gtk_hbox_new (FALSE, 3);
5894   gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
5895   label = gtk_label_new ("Previous signal:");
5896   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5897   calendar_data.prev_sig = gtk_label_new ("");
5898   gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev_sig, FALSE, TRUE, 0);
5899
5900   hbox = gtk_hbox_new (FALSE, 3);
5901   gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
5902   label = gtk_label_new ("Second previous signal:");
5903   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5904   calendar_data.prev2_sig = gtk_label_new ("");
5905   gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev2_sig, FALSE, TRUE, 0);
5906
5907   bbox = gtk_hbutton_box_new ();
5908   gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
5909   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
5910
5911   button = gtk_button_new_with_label ("Close");
5912   g_signal_connect (button, "clicked", 
5913                     G_CALLBACK (gtk_main_quit), 
5914                     NULL);
5915   gtk_container_add (GTK_CONTAINER (bbox), button);
5916   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
5917   gtk_widget_grab_default (button);
5918
5919   gtk_widget_show_all (window);
5920 }
5921
5922
5923 int main (int   argc,
5924           char *argv[])
5925 {
5926   gtk_init (&amp;argc, &amp;argv);
5927
5928   create_calendar ();
5929
5930   gtk_main ();
5931
5932   return 0;
5933 }
5934 <!-- example-end -->
5935 </programlisting>
5936
5937 </sect1>
5938
5939 <!-- ----------------------------------------------------------------- -->
5940 <sect1 id="sec-ColorSelection">
5941 <title>Color Selection</title>
5942
5943 <para>The color selection widget is, not surprisingly, a widget for
5944 interactive selection of colors. This composite widget lets the user
5945 select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
5946 Saturation, Value) triples.  This is done either by adjusting single
5947 values with sliders or entries, or by picking the desired color from a
5948 hue-saturation wheel/value bar.  Optionally, the opacity of the color
5949 can also be set.</para>
5950
5951 <para>The color selection widget currently emits only one signal,
5952 "color_changed", which is emitted whenever the current color in the
5953 widget changes, either when the user changes it or if it's set
5954 explicitly through gtk_color_selection_set_color().</para>
5955
5956 <para>Lets have a look at what the color selection widget has to offer
5957 us. The widget comes in two flavours: GtkColorSelection and
5958 GtkColorSelectionDialog.</para>
5959
5960 <programlisting role="C">
5961 GtkWidget *gtk_color_selection_new( void );
5962 </programlisting>
5963         
5964 <para>You'll probably not be using this constructor directly. It creates an
5965 orphan ColorSelection widget which you'll have to parent
5966 yourself. The ColorSelection widget inherits from the VBox
5967 widget.</para>
5968
5969 <programlisting role="C">
5970 GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
5971 </programlisting>
5972
5973 <para>This is the most common color selection constructor. It creates a
5974 ColorSelectionDialog. It consists of a Frame containing a
5975 ColorSelection widget, an HSeparator and an HBox with three buttons,
5976 "Ok", "Cancel" and "Help". You can reach these buttons by accessing
5977 the "ok_button", "cancel_button" and "help_button" widgets in the
5978 ColorSelectionDialog structure,
5979 (i.e., <literal>GTK_COLOR_SELECTION_DIALOG (colorseldialog)->ok_button</literal>)).</para>
5980
5981 <programlisting role="C">
5982 void gtk_color_selection_set_has_opacity_control( GtkColorSelection *colorsel,
5983                                                   gboolean           has_opacity );
5984 </programlisting>
5985
5986 <para>The color selection widget supports adjusting the opacity of a color
5987 (also known as the alpha channel). This is disabled by
5988 default. Calling this function with has_opacity set to TRUE enables
5989 opacity. Likewise, has_opacity set to FALSE will disable opacity.</para>
5990
5991 <programlisting role="C">
5992 void gtk_color_selection_set_current_color( GtkColorSelection *colorsel,
5993                                             GdkColor          *color );
5994
5995 void gtk_color_selection_set_current_alpha( GtkColorSelection *colorsel,
5996                                             guint16            alpha );
5997 </programlisting>
5998
5999 <para>You can set the current color explicitly by calling 
6000 gtk_color_selection_set_current_color() with a pointer to a GdkColor. 
6001 Setting the opacity (alpha channel) is done with 
6002 gtk_color_selection_set_current_alpha(). The alpha value should be between
6003 0 (fully transparent) and 65535 (fully opaque).
6004 </para>
6005
6006 <programlisting role="C">
6007 void gtk_color_selection_get_current_color( GtkColorSelection *colorsel,
6008                                             GdkColor *color );
6009
6010 void gtk_color_selection_get_current_alpha( GtkColorSelection *colorsel,
6011                                             guint16           *alpha );
6012 </programlisting>
6013
6014 <para>When you need to query the current color, typically when you've
6015 received a "color_changed" signal, you use these functions.</para>
6016
6017 <para><!-- Need to do a whole section on DnD - TRG
6018 Drag and drop
6019 -------------</para>
6020
6021 <para>The color sample areas (right under the hue-saturation wheel) supports
6022 drag and drop. The type of drag and drop is "application/x-color". The
6023 message data consists of an array of 4 (or 5 if opacity is enabled)
6024 gdouble values, where the value at position 0 is 0.0 (opacity on) or
6025 1.0 (opacity off) followed by the red, green and blue values at
6026 positions 1,2 and 3 respectively.  If opacity is enabled, the opacity
6027 is passed in the value at position 4.
6028 --></para>
6029
6030 <para>Here's a simple example demonstrating the use of the
6031 ColorSelectionDialog. The program displays a window containing a
6032 drawing area. Clicking on it opens a color selection dialog, and
6033 changing the color in the color selection dialog changes the
6034 background color.</para>
6035
6036 <para>
6037 <inlinemediaobject>
6038 <imageobject>
6039 <imagedata fileref="images/colorsel.png" format="png">
6040 </imageobject>
6041 </inlinemediaobject>
6042 </para>
6043
6044 <programlisting role="C">
6045 <!-- example-start colorsel colorsel.c -->
6046
6047 #include &lt;glib.h&gt;
6048 #include &lt;gdk/gdk.h&gt;
6049 #include &lt;gtk/gtk.h&gt;
6050
6051 GtkWidget *colorseldlg = NULL;
6052 GtkWidget *drawingarea = NULL;
6053 GdkColor color;
6054
6055 /* Color changed handler */
6056
6057 static void color_changed_cb( GtkWidget         *widget,
6058                               GtkColorSelection *colorsel )
6059 {
6060   GdkColor ncolor;
6061
6062   gtk_color_selection_get_current_color (colorsel, &amp;ncolor);
6063   gtk_widget_modify_bg (drawingarea, GTK_STATE_NORMAL, &amp;ncolor);       
6064 }
6065
6066 /* Drawingarea event handler */
6067
6068 static gboolean area_event( GtkWidget *widget,
6069                             GdkEvent  *event,
6070                             gpointer   client_data )
6071 {
6072   gint handled = FALSE;
6073   gint response;
6074   GtkColorSelection *colorsel;
6075
6076   /* Check if we've received a button pressed event */
6077
6078   if (event-&gt;type == GDK_BUTTON_PRESS)
6079     {
6080       handled = TRUE;
6081
6082        /* Create color selection dialog */
6083       if (colorseldlg == NULL)
6084         colorseldlg = gtk_color_selection_dialog_new ("Select background color");
6085
6086       /* Get the ColorSelection widget */
6087       colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (colorseldlg)-&gt;colorsel);
6088
6089       gtk_color_selection_set_previous_color (colorsel, &amp;color);
6090       gtk_color_selection_set_current_color (colorsel, &amp;color);
6091       gtk_color_selection_set_has_palette (colorsel, TRUE);
6092
6093       /* Connect to the "color_changed" signal, set the client-data
6094        * to the colorsel widget */
6095       g_signal_connect (G_OBJECT (colorsel), "color_changed",
6096                         G_CALLBACK (color_changed_cb), (gpointer) colorsel);
6097
6098       /* Show the dialog */
6099       response = gtk_dialog_run (GTK_DIALOG (colorseldlg));
6100
6101       if (response == GTK_RESPONSE_OK)
6102         gtk_color_selection_get_current_color (colorsel, &amp;color);
6103       else 
6104         gtk_widget_modify_bg (drawingarea, GTK_STATE_NORMAL, &amp;color);
6105
6106       gtk_widget_hide (colorseldlg);
6107     }
6108
6109   return handled;
6110 }
6111
6112 /* Close down and exit handler */
6113
6114 static gboolean destroy_window( GtkWidget *widget,
6115                                 GdkEvent  *event,
6116                                 gpointer   client_data )
6117 {
6118   gtk_main_quit ();
6119   return TRUE;
6120 }
6121
6122 /* Main */
6123
6124 gint main( gint   argc,
6125            gchar *argv[] )
6126 {
6127   GtkWidget *window;
6128
6129   /* Initialize the toolkit, remove gtk-related commandline stuff */
6130
6131   gtk_init (&amp;argc, &amp;argv);
6132
6133   /* Create toplevel window, set title and policies */
6134
6135   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6136   gtk_window_set_title (GTK_WINDOW (window), "Color selection test");
6137   gtk_window_set_policy (GTK_WINDOW (window), TRUE, TRUE, TRUE);
6138
6139   /* Attach to the "delete" and "destroy" events so we can exit */
6140
6141   g_signal_connect (GTK_OBJECT (window), "delete_event",
6142                     GTK_SIGNAL_FUNC (destroy_window), (gpointer) window);
6143   
6144   /* Create drawingarea, set size and catch button events */
6145
6146   drawingarea = gtk_drawing_area_new ();
6147
6148   color.red = 0;
6149   color.blue = 65535;
6150   color.green = 0;
6151   gtk_widget_modify_bg (drawingarea, GTK_STATE_NORMAL, &amp;color);       
6152
6153   gtk_widget_set_size_request (GTK_WIDGET (drawingarea), 200, 200);
6154
6155   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
6156
6157   g_signal_connect (GTK_OBJECT (drawingarea), "event", 
6158                     GTK_SIGNAL_FUNC (area_event), (gpointer) drawingarea);
6159   
6160   /* Add drawingarea to window, then show them both */
6161
6162   gtk_container_add (GTK_CONTAINER (window), drawingarea);
6163
6164   gtk_widget_show (drawingarea);
6165   gtk_widget_show (window);
6166   
6167   /* Enter the gtk main loop (this never returns) */
6168
6169   gtk_main ();
6170
6171   /* Satisfy grumpy compilers */
6172
6173   return 0;
6174 }
6175 <!-- example-end -->
6176 </programlisting>
6177
6178 </sect1>
6179
6180 <!-- ----------------------------------------------------------------- -->
6181 <sect1 id="sec-FileSelections">
6182 <title>File Selections</title>
6183
6184 <para>The file selection widget is a quick and simple way to display a File
6185 dialog box. It comes complete with Ok, Cancel, and Help buttons, a
6186 great way to cut down on programming time.</para>
6187
6188 <para>To create a new file selection box use:</para>
6189
6190 <programlisting role="C">
6191 GtkWidget *gtk_file_selection_new( const gchar *title );
6192 </programlisting>
6193
6194 <para>To set the filename, for example to bring up a specific directory, or
6195 give a default filename, use this function:</para>
6196
6197 <programlisting role="C">
6198 void gtk_file_selection_set_filename( GtkFileSelection *filesel,
6199                                       const gchar      *filename );
6200 </programlisting>
6201
6202 <para>To grab the text that the user has entered or clicked on, use this 
6203 function:</para>
6204
6205 <programlisting role="C">
6206 gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel );
6207 </programlisting>
6208
6209 <para>There are also pointers to the widgets contained within the file 
6210 selection widget. These are:</para>
6211
6212 <programlisting role="C">
6213   dir_list
6214   file_list
6215   selection_entry
6216   selection_text
6217   main_vbox
6218   ok_button
6219   cancel_button
6220   help_button
6221 </programlisting>
6222  
6223 <para>Most likely you will want to use the ok_button, cancel_button, and
6224 help_button pointers in signaling their use.</para>
6225
6226 <para>Included here is an example stolen from <filename>testgtk.c</filename>,
6227 modified to run on its own. As you will see, there is nothing much to creating a file
6228 selection widget. While in this example the Help button appears on the
6229 screen, it does nothing as there is not a signal attached to it.</para>
6230
6231 <para>
6232 <inlinemediaobject>
6233 <imageobject>
6234 <imagedata fileref="images/filesel.png" format="png">
6235 </imageobject>
6236 </inlinemediaobject>
6237 </para>
6238
6239 <programlisting role="C">
6240 <!-- example-start filesel filesel.c -->
6241
6242 #include &lt;gtk/gtk.h&gt;
6243
6244 /* Get the selected filename and print it to the console */
6245 static void file_ok_sel( GtkWidget        *w,
6246                          GtkFileSelection *fs )
6247 {
6248     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
6249 }
6250
6251 int main( int   argc,
6252           char *argv[] )
6253 {
6254     GtkWidget *filew;
6255     
6256     gtk_init (&amp;argc, &amp;argv);
6257     
6258     /* Create a new file selection widget */
6259     filew = gtk_file_selection_new ("File selection");
6260     
6261     g_signal_connect (G_OBJECT (filew), "destroy",
6262                       G_CALLBACK (gtk_main_quit), NULL);
6263     /* Connect the ok_button to file_ok_sel function */
6264     g_signal_connect (G_OBJECT (GTK_FILE_SELECTION (filew)-&gt;ok_button),
6265                       "clicked", G_CALLBACK (file_ok_sel), (gpointer) filew);
6266     
6267     /* Connect the cancel_button to destroy the widget */
6268     g_signal_connect_swapped (G_OBJECT (GTK_FILE_SELECTION (filew)-&gt;cancel_button),
6269                               "clicked", G_CALLBACK (gtk_widget_destroy),
6270                               G_OBJECT (filew));
6271     
6272     /* Lets set the filename, as if this were a save dialog, and we are giving
6273      a default filename */
6274     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
6275                                      "penguin.png");
6276     
6277     gtk_widget_show (filew);
6278     gtk_main ();
6279     return 0;
6280 }
6281 <!-- example-end -->
6282 </programlisting>
6283
6284 </sect1>
6285 </chapter>
6286
6287 <!-- ***************************************************************** -->
6288 <chapter id="ch-ContainerWidgets">
6289 <title>Container Widgets</title>
6290
6291 <!-- ----------------------------------------------------------------- -->   
6292 <sect1 id="sec-EventBox">
6293 <title>The EventBox</title>
6294
6295 <para>Some GTK widgets don't have associated X windows, so they just draw on
6296 their parents. Because of this, they cannot receive events and if they
6297 are incorrectly sized, they don't clip so you can get messy
6298 overwriting, etc. If you require more from these widgets, the EventBox
6299 is for you.</para>
6300
6301 <para>At first glance, the EventBox widget might appear to be totally
6302 useless. It draws nothing on the screen and responds to no
6303 events. However, it does serve a function - it provides an X window
6304 for its child widget. This is important as many GTK widgets do not
6305 have an associated X window. Not having an X window saves memory and
6306 improves performance, but also has some drawbacks. A widget without an
6307 X window cannot receive events, and does not perform any clipping on
6308 its contents. Although the name <emphasis>EventBox</emphasis> emphasizes the
6309 event-handling function, the widget can also be used for clipping.
6310 (and more, see the example below).</para>
6311
6312 <para>To create a new EventBox widget, use:</para>
6313
6314 <programlisting role="C">
6315 GtkWidget *gtk_event_box_new( void );
6316 </programlisting>
6317
6318 <para>A child widget can then be added to this EventBox:</para>
6319
6320 <programlisting role="C">
6321     gtk_container_add (GTK_CONTAINER (event_box), child_widget);
6322 </programlisting>
6323
6324 <para>The following example demonstrates both uses of an EventBox - a label
6325 is created that is clipped to a small box, and set up so that a
6326 mouse-click on the label causes the program to exit. Resizing the
6327 window reveals varying amounts of the label.</para>
6328
6329 <para>
6330 <inlinemediaobject>
6331 <imageobject>
6332 <imagedata fileref="images/eventbox.png" format="png">
6333 </imageobject>
6334 </inlinemediaobject>
6335 </para>
6336
6337 <programlisting role="C">
6338 <!-- example-start eventbox eventbox.c -->
6339
6340 #include &lt;stdlib.h&gt;
6341 #include &lt;gtk/gtk.h&gt;
6342
6343 int main( int argc,
6344           char *argv[] )
6345 {
6346     GtkWidget *window;
6347     GtkWidget *event_box;
6348     GtkWidget *label;
6349     
6350     gtk_init (&amp;argc, &amp;argv);
6351     
6352     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6353     
6354     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
6355     
6356     g_signal_connect (G_OBJECT (window), "destroy",
6357                       G_CALLBACK (exit), NULL);
6358     
6359     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6360     
6361     /* Create an EventBox and add it to our toplevel window */
6362     
6363     event_box = gtk_event_box_new ();
6364     gtk_container_add (GTK_CONTAINER (window), event_box);
6365     gtk_widget_show (event_box);
6366     
6367     /* Create a long label */
6368     
6369     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
6370     gtk_container_add (GTK_CONTAINER (event_box), label);
6371     gtk_widget_show (label);
6372     
6373     /* Clip it short. */
6374     gtk_widget_set_size_request (label, 110, 20);
6375     
6376     /* And bind an action to it */
6377     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
6378     g_signal_connect (G_OBJECT (event_box), "button_press_event",
6379                       G_CALLBACK (exit), NULL);
6380     
6381     /* Yet one more thing you need an X window for ... */
6382     
6383     gtk_widget_realize (event_box);
6384     gdk_window_set_cursor (event_box-&gt;window, gdk_cursor_new (GDK_HAND1));
6385     
6386     gtk_widget_show (window);
6387     
6388     gtk_main ();
6389     
6390     return 0;
6391 }
6392 <!-- example-end -->
6393 </programlisting>
6394
6395 </sect1>
6396
6397 <!-- ----------------------------------------------------------------- -->   
6398 <sect1 id="sec-TheAlignmentWidget">
6399 <title>The Alignment widget</title>
6400
6401 <para>The alignment widget allows you to place a widget within its window at
6402 a position and size relative to the size of the Alignment widget
6403 itself. For example, it can be very useful for centering a widget
6404 within the window.</para>
6405
6406 <para>There are only two functions associated with the Alignment widget:</para>
6407
6408 <programlisting role="C">
6409 GtkWidget* gtk_alignment_new( gfloat xalign,
6410                               gfloat yalign,
6411                               gfloat xscale,
6412                               gfloat yscale );
6413
6414 void gtk_alignment_set( GtkAlignment *alignment,
6415                         gfloat        xalign,
6416                         gfloat        yalign,
6417                         gfloat        xscale,
6418                         gfloat        yscale );
6419 </programlisting>
6420
6421 <para>The first function creates a new Alignment widget with the specified
6422 parameters. The second function allows the alignment parameters of an
6423 exisiting Alignment widget to be altered.</para>
6424
6425 <para>All four alignment parameters are floating point numbers which can
6426 range from 0.0 to 1.0. The <literal>xalign</literal> and <literal>yalign</literal> arguments
6427 affect the position of the widget placed within the Alignment
6428 widget. The <literal>xscale</literal> and <literal>yscale</literal> arguments affect the amount of
6429 space allocated to the widget.</para>
6430
6431 <para>A child widget can be added to this Alignment widget using:</para>
6432
6433 <programlisting role="C">
6434     gtk_container_add (GTK_CONTAINER (alignment), child_widget);
6435 </programlisting>
6436
6437 <para>For an example of using an Alignment widget, refer to the example for
6438 the <link linkend="sec-ProgressBars">Progress Bar</link> widget.</para>
6439
6440 </sect1>
6441
6442 <!-- ----------------------------------------------------------------- -->
6443 <sect1 id="sec-FixedContainer">
6444 <title>Fixed Container</title>
6445
6446 <para>The Fixed container allows you to place widgets at a fixed position
6447 within it's window, relative to it's upper left hand corner. The
6448 position of the widgets can be changed dynamically.</para>
6449
6450 <para>There are only a few functions associated with the fixed widget:</para>
6451
6452 <programlisting role="C">
6453 GtkWidget* gtk_fixed_new( void );
6454
6455 void gtk_fixed_put( GtkFixed  *fixed,
6456                     GtkWidget *widget,
6457                     gint       x,
6458                     gint       y );
6459
6460 void gtk_fixed_move( GtkFixed  *fixed,
6461                      GtkWidget *widget,
6462                      gint       x,
6463                      gint       y );
6464 </programlisting>
6465
6466 <para>The function gtk_fixed_new() allows you to create a new Fixed
6467 container.</para>
6468
6469 <para>gtk_fixed_put() places <literal>widget</literal> in the container <literal>fixed</literal> at
6470 the position specified by <literal>x</literal> and <literal>y</literal>.</para>
6471
6472 <para>gtk_fixed_move() allows the specified widget to be moved to a new
6473 position.</para>
6474
6475 <programlisting role="C">
6476 void gtk_fixed_set_has_window( GtkFixed  *fixed,
6477                                gboolean   has_window );
6478
6479 gboolean gtk_fixed_get_has_window( GtkFixed *fixed );
6480 </programlisting>
6481
6482 <para>Normally, Fixed widgets don't have their own X window. Since this is
6483 different from the behaviour of Fixed widgets in earlier releases of GTK, 
6484 the function gtk_fixed_set_has_window() allows the creation of Fixed widgets 
6485 <emphasis>with</emphasis> their own window. It has to be called before
6486 realizing the widget.</para>
6487
6488 <para>The following example illustrates how to use the Fixed Container.</para>
6489
6490 <para>
6491 <inlinemediaobject>
6492 <imageobject>
6493 <imagedata fileref="images/fixed.png" format="png">
6494 </imageobject>
6495 </inlinemediaobject>
6496 </para>
6497
6498 <programlisting role="C">
6499 <!-- example-start fixed fixed.c -->
6500
6501 #include &lt;gtk/gtk.h&gt;
6502
6503 /* I'm going to be lazy and use some global variables to
6504  * store the position of the widget within the fixed
6505  * container */
6506 gint x = 50;
6507 gint y = 50;
6508
6509 /* This callback function moves the button to a new position
6510  * in the Fixed container. */
6511 static void move_button( GtkWidget *widget,
6512                          GtkWidget *fixed )
6513 {
6514   x = (x + 30) % 300;
6515   y = (y + 50) % 300;
6516   gtk_fixed_move (GTK_FIXED (fixed), widget, x, y); 
6517 }
6518
6519 int main( int   argc,
6520           char *argv[] )
6521 {
6522   /* GtkWidget is the storage type for widgets */
6523   GtkWidget *window;
6524   GtkWidget *fixed;
6525   GtkWidget *button;
6526   gint i;
6527
6528   /* Initialise GTK */
6529   gtk_init (&amp;argc, &amp;argv);
6530     
6531   /* Create a new window */
6532   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6533   gtk_window_set_title (GTK_WINDOW (window), "Fixed Container");
6534
6535   /* Here we connect the "destroy" event to a signal handler */ 
6536   g_signal_connect (G_OBJECT (window), "destroy",
6537                     G_CALLBACK (gtk_main_quit), NULL);
6538  
6539   /* Sets the border width of the window. */
6540   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6541
6542   /* Create a Fixed Container */
6543   fixed = gtk_fixed_new ();
6544   gtk_container_add (GTK_CONTAINER (window), fixed);
6545   gtk_widget_show (fixed);
6546   
6547   for (i = 1 ; i &lt;= 3 ; i++) {
6548     /* Creates a new button with the label "Press me" */
6549     button = gtk_button_new_with_label ("Press me");
6550   
6551     /* When the button receives the "clicked" signal, it will call the
6552      * function move_button() passing it the Fixed Container as its
6553      * argument. */
6554     g_signal_connect (G_OBJECT (button), "clicked",
6555                       G_CALLBACK (move_button), (gpointer) fixed);
6556   
6557     /* This packs the button into the fixed containers window. */
6558     gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
6559   
6560     /* The final step is to display this newly created widget. */
6561     gtk_widget_show (button);
6562   }
6563
6564   /* Display the window */
6565   gtk_widget_show (window);
6566     
6567   /* Enter the event loop */
6568   gtk_main ();
6569     
6570   return 0;
6571 }
6572 <!-- example-end -->
6573 </programlisting>
6574
6575 </sect1>
6576
6577 <!-- ----------------------------------------------------------------- -->
6578 <sect1 id="sec-LayoutContainer">
6579 <title>Layout Container</title>
6580
6581 <para>The Layout container is similar to the Fixed container except that it
6582 implements an infinite (where infinity is less than 2^32) scrolling
6583 area. The X window system has a limitation where windows can be at
6584 most 32767 pixels wide or tall. The Layout container gets around this
6585 limitation by doing some exotic stuff using window and bit gravities,
6586 so that you can have smooth scrolling even when you have many child
6587 widgets in your scrolling area.</para>
6588
6589 <para>A Layout container is created using:</para>
6590
6591 <programlisting role="C">
6592 GtkWidget *gtk_layout_new( GtkAdjustment *hadjustment,
6593                            GtkAdjustment *vadjustment );
6594 </programlisting>
6595
6596 <para>As you can see, you can optionally specify the Adjustment objects that
6597 the Layout widget will use for its scrolling.</para>
6598
6599 <para>You can add and move widgets in the Layout container using the
6600 following two functions:</para>
6601
6602 <programlisting role="C">
6603 void gtk_layout_put( GtkLayout *layout,
6604                      GtkWidget *widget,
6605                      gint       x,
6606                      gint       y );
6607
6608 void gtk_layout_move( GtkLayout *layout,
6609                       GtkWidget *widget,
6610                       gint       x,
6611                       gint       y );
6612 </programlisting>
6613
6614 <para>The size of the Layout container can be set using the next function:</para>
6615
6616 <programlisting role="C">
6617 void gtk_layout_set_size( GtkLayout *layout,
6618                           guint      width,
6619                           guint      height );
6620 </programlisting>
6621
6622 <para>The final four functions for use with Layout widgets are for
6623 manipulating the horizontal and vertical adjustment widgets:</para>
6624
6625 <programlisting role="C">
6626 GtkAdjustment* gtk_layout_get_hadjustment( GtkLayout *layout );
6627
6628 GtkAdjustment* gtk_layout_get_vadjustment( GtkLayout *layout );
6629
6630 void gtk_layout_set_hadjustment( GtkLayout     *layout,
6631                                  GtkAdjustment *adjustment );
6632
6633 void gtk_layout_set_vadjustment( GtkLayout     *layout,
6634                                  GtkAdjustment *adjustment);
6635 </programlisting>
6636
6637 </sect1>
6638
6639 <!-- ----------------------------------------------------------------- -->
6640 <sect1 id="sec-Frames">
6641 <title>Frames</title>
6642
6643 <para>Frames can be used to enclose one or a group of widgets with a box
6644 which can optionally be labelled. The position of the label and the
6645 style of the box can be altered to suit.</para>
6646
6647 <para>A Frame can be created with the following function:</para>
6648
6649 <programlisting role="C">
6650 GtkWidget *gtk_frame_new( const gchar *label );
6651 </programlisting>
6652
6653 <para>The label is by default placed in the upper left hand corner of the
6654 frame. A value of NULL for the <literal>label</literal> argument will result in no
6655 label being displayed. The text of the label can be changed using the
6656 next function.</para>
6657
6658 <programlisting role="C">
6659 void gtk_frame_set_label( GtkFrame    *frame,
6660                           const gchar *label );
6661 </programlisting>
6662
6663 <para>The position of the label can be changed using this function:</para>
6664
6665 <programlisting role="C">
6666 void gtk_frame_set_label_align( GtkFrame *frame,
6667                                 gfloat    xalign,
6668                                 gfloat    yalign );
6669 </programlisting>
6670
6671 <para><literal>xalign</literal> and <literal>yalign</literal> take values between 0.0 and 1.0. <literal>xalign</literal>
6672 indicates the position of the label along the top horizontal of the
6673 frame. <literal>yalign</literal> is not currently used. The default value of xalign
6674 is 0.0 which places the label at the left hand end of the frame.</para>
6675
6676 <para>The next function alters the style of the box that is used to outline
6677 the frame.</para>
6678
6679 <programlisting role="C">
6680 void gtk_frame_set_shadow_type( GtkFrame      *frame,
6681                                 GtkShadowType  type);
6682 </programlisting>
6683
6684 <para>The <literal>type</literal> argument can take one of the following values:</para>
6685 <programlisting role="C">
6686   GTK_SHADOW_NONE
6687   GTK_SHADOW_IN
6688   GTK_SHADOW_OUT
6689   GTK_SHADOW_ETCHED_IN (the default)
6690   GTK_SHADOW_ETCHED_OUT
6691 </programlisting>
6692
6693 <para>The following code example illustrates the use of the Frame widget.</para>
6694
6695 <para>
6696 <inlinemediaobject>
6697 <imageobject>
6698 <imagedata fileref="images/frame.png" format="png">
6699 </imageobject>
6700 </inlinemediaobject>
6701 </para>
6702
6703 <programlisting role="C">
6704 <!-- example-start frame frame.c -->
6705
6706 #include &lt;gtk/gtk.h&gt;
6707
6708 int main( int   argc,
6709           char *argv[] )
6710 {
6711   /* GtkWidget is the storage type for widgets */
6712   GtkWidget *window;
6713   GtkWidget *frame;
6714
6715   /* Initialise GTK */
6716   gtk_init (&amp;argc, &amp;argv);
6717     
6718   /* Create a new window */
6719   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6720   gtk_window_set_title (GTK_WINDOW (window), "Frame Example");
6721
6722   /* Here we connect the "destroy" event to a signal handler */ 
6723   g_signal_connect (G_OBJECT (window), "destroy",
6724                     G_CALLBACK (gtk_main_quit), NULL);
6725
6726   gtk_widget_set_size_request (window, 300, 300);
6727   /* Sets the border width of the window. */
6728   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6729
6730   /* Create a Frame */
6731   frame = gtk_frame_new (NULL);
6732   gtk_container_add (GTK_CONTAINER (window), frame);
6733
6734   /* Set the frame's label */
6735   gtk_frame_set_label (GTK_FRAME (frame), "GTK Frame Widget");
6736
6737   /* Align the label at the right of the frame */
6738   gtk_frame_set_label_align (GTK_FRAME (frame), 1.0, 0.0);
6739
6740   /* Set the style of the frame */
6741   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);
6742
6743   gtk_widget_show (frame);
6744   
6745   /* Display the window */
6746   gtk_widget_show (window);
6747     
6748   /* Enter the event loop */
6749   gtk_main ();
6750     
6751   return 0;
6752 }
6753 <!-- example-end -->
6754 </programlisting>
6755 </sect1>
6756
6757 <!-- ----------------------------------------------------------------- -->   
6758 <sect1 id="sec-AspectFrames">
6759 <title>Aspect Frames</title>
6760
6761 <para>The aspect frame widget is like a frame widget, except that it also
6762 enforces the aspect ratio (that is, the ratio of the width to the
6763 height) of the child widget to have a certain value, adding extra
6764 space if necessary. This is useful, for instance, if you want to
6765 preview a larger image. The size of the preview should vary when the
6766 user resizes the window, but the aspect ratio needs to always match
6767 the original image.</para>
6768   
6769 <para>To create a new aspect frame use:</para>
6770
6771 <programlisting role="C">
6772 GtkWidget *gtk_aspect_frame_new( const gchar *label,
6773                                  gfloat       xalign,
6774                                  gfloat       yalign,
6775                                  gfloat       ratio,
6776                                  gboolean     obey_child);
6777 </programlisting>
6778    
6779 <para><literal>xalign</literal> and <literal>yalign</literal> specify alignment as with Alignment
6780 widgets. If <literal>obey_child</literal> is TRUE, the aspect ratio of a child
6781 widget will match the aspect ratio of the ideal size it requests.
6782 Otherwise, it is given by <literal>ratio</literal>.</para>
6783    
6784 <para>To change the options of an existing aspect frame, you can use:</para>
6785
6786 <programlisting role="C">
6787 void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
6788                            gfloat          xalign,
6789                            gfloat          yalign,
6790                            gfloat          ratio,
6791                            gboolean        obey_child);
6792 </programlisting>
6793    
6794 <para>As an example, the following program uses an AspectFrame to present a
6795 drawing area whose aspect ratio will always be 2:1, no matter how the
6796 user resizes the top-level window.</para>
6797
6798 <para>
6799 <inlinemediaobject>
6800 <imageobject>
6801 <imagedata fileref="images/aspectframe.png" format="png">
6802 </imageobject>
6803 </inlinemediaobject>
6804 </para>
6805
6806 <programlisting role="C">
6807 <!-- example-start aspectframe aspectframe.c -->
6808
6809 #include &lt;gtk/gtk.h&gt;
6810    
6811 int main( int argc,
6812           char *argv[] )
6813 {
6814     GtkWidget *window;
6815     GtkWidget *aspect_frame;
6816     GtkWidget *drawing_area;
6817     gtk_init (&amp;argc, &amp;argv);
6818    
6819     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6820     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
6821     g_signal_connect (G_OBJECT (window), "destroy",
6822                       G_CALLBACK (gtk_main_quit), NULL);
6823     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6824    
6825     /* Create an aspect_frame and add it to our toplevel window */
6826    
6827     aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
6828                                          0.5, /* center x */
6829                                          0.5, /* center y */
6830                                          2, /* xsize/ysize = 2 */
6831                                          FALSE /* ignore child's aspect */);
6832    
6833     gtk_container_add (GTK_CONTAINER (window), aspect_frame);
6834     gtk_widget_show (aspect_frame);
6835    
6836     /* Now add a child widget to the aspect frame */
6837    
6838     drawing_area = gtk_drawing_area_new ();
6839    
6840     /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
6841      * window since we are forcing a 2x1 aspect ratio */
6842     gtk_widget_set_size_request (drawing_area, 200, 200);
6843     gtk_container_add (GTK_CONTAINER (aspect_frame), drawing_area);
6844     gtk_widget_show (drawing_area);
6845    
6846     gtk_widget_show (window);
6847     gtk_main ();
6848     return 0;
6849 }
6850 <!-- example-end -->
6851 </programlisting>
6852
6853 </sect1>
6854
6855 <!-- ----------------------------------------------------------------- -->   
6856 <sect1 id="sec-PanedWindowWidgets">
6857 <title>Paned Window Widgets</title>
6858
6859 <para>The paned window widgets are useful when you want to divide an area
6860 into two parts, with the relative size of the two parts controlled by
6861 the user. A groove is drawn between the two portions with a handle
6862 that the user can drag to change the ratio. The division can either be
6863 horizontal (HPaned) or vertical (VPaned).</para>
6864    
6865 <para>To create a new paned window, call one of:</para>
6866
6867 <programlisting role="C">
6868 GtkWidget *gtk_hpaned_new (void);
6869
6870 GtkWidget *gtk_vpaned_new (void);
6871 </programlisting>
6872
6873 <para>After creating the paned window widget, you need to add child widgets
6874 to its two halves. To do this, use the functions:</para>
6875
6876 <programlisting role="C">
6877 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
6878
6879 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
6880 </programlisting>
6881
6882 <para><literal>gtk_paned_add1()</literal> adds the child widget to the left or top half of
6883 the paned window. <literal>gtk_paned_add2()</literal> adds the child widget to the
6884 right or bottom half of the paned window.</para>
6885
6886 <para>As an example, we will create part of the user interface of an
6887 imaginary email program. A window is divided into two portions
6888 vertically, with the top portion being a list of email messages and
6889 the bottom portion the text of the email message. Most of the program
6890 is pretty straightforward. A couple of points to note: text can't be
6891 added to a Text widget until it is realized. This could be done by
6892 calling gtk_widget_realize(), but as a demonstration of an
6893 alternate technique, we connect a handler to the "realize" signal to
6894 add the text. Also, we need to add the <literal>GTK_SHRINK</literal> option to some
6895 of the items in the table containing the text window and its
6896 scrollbars, so that when the bottom portion is made smaller, the
6897 correct portions shrink instead of being pushed off the bottom of the
6898 window.</para>
6899
6900 <para>
6901 <inlinemediaobject>
6902 <imageobject>
6903 <imagedata fileref="images/paned.png" format="png">
6904 </imageobject>
6905 </inlinemediaobject>
6906 </para>
6907
6908 <programlisting role="C">
6909 <!-- example-start paned paned.c -->
6910
6911 #include &lt;stdio.h&gt;
6912 #include &lt;gtk/gtk.h&gt;
6913    
6914 /* Create the list of "messages" */
6915 static GtkWidget *create_list( void )
6916 {
6917
6918     GtkWidget *scrolled_window;
6919     GtkWidget *tree_view;
6920     GtkListStore *model;
6921     GtkTreeIter iter;
6922     GtkCellRenderer *cell;
6923     GtkTreeViewColumn *column;
6924
6925     int i;
6926    
6927     /* Create a new scrolled window, with scrollbars only if needed */
6928     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6929     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6930                                     GTK_POLICY_AUTOMATIC, 
6931                                     GTK_POLICY_AUTOMATIC);
6932    
6933     model = gtk_list_store_new (1, G_TYPE_STRING);
6934     tree_view = gtk_tree_view_new ();
6935     gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
6936     gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (model));
6937     gtk_widget_show (tree_view);
6938    
6939     /* Add some messages to the window */
6940     for (i = 0; i &lt; 10; i++) {
6941         gchar *msg = g_strdup_printf ("Message #%d", i);
6942         gtk_list_store_append (GTK_LIST_STORE (model), &amp;iter);
6943         gtk_list_store_set (GTK_LIST_STORE (model), 
6944                             &amp;iter,
6945                             0, msg,
6946                             -1);
6947         g_free (msg);
6948     }
6949    
6950     cell = gtk_cell_renderer_text_new ();
6951
6952     column = gtk_tree_view_column_new_with_attributes ("Messages",
6953                                                        cell,
6954                                                        "text", 0,
6955                                                        NULL);
6956   
6957     gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
6958                                  GTK_TREE_VIEW_COLUMN (column));
6959
6960     return scrolled_window;
6961 }
6962    
6963 /* Add some text to our text widget - this is a callback that is invoked
6964 when our window is realized. We could also force our window to be
6965 realized with gtk_widget_realize, but it would have to be part of
6966 a hierarchy first */
6967
6968 static void insert_text( GtkTextBuffer *buffer )
6969 {
6970    GtkTextIter iter;
6971  
6972    gtk_text_buffer_get_iter_at_offset (buffer, &amp;iter, 0);
6973
6974    gtk_text_buffer_insert (buffer, &amp;iter,   
6975     "From: pathfinder@nasa.gov\n"
6976     "To: mom@nasa.gov\n"
6977     "Subject: Made it!\n"
6978     "\n"
6979     "We just got in this morning. The weather has been\n"
6980     "great - clear but cold, and there are lots of fun sights.\n"
6981     "Sojourner says hi. See you soon.\n"
6982     " -Path\n", -1);
6983 }
6984    
6985 /* Create a scrolled text area that displays a "message" */
6986 static GtkWidget *create_text( void )
6987 {
6988    GtkWidget *scrolled_window;
6989    GtkWidget *view;
6990    GtkTextBuffer *buffer;
6991
6992    view = gtk_text_view_new ();
6993    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
6994
6995    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6996    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6997                                    GTK_POLICY_AUTOMATIC,
6998                                    GTK_POLICY_AUTOMATIC);
6999
7000    gtk_container_add (GTK_CONTAINER (scrolled_window), view);
7001    insert_text (buffer);
7002
7003    gtk_widget_show_all (scrolled_window);
7004
7005    return scrolled_window;
7006 }
7007    
7008 int main( int   argc,
7009           char *argv[] )
7010 {
7011     GtkWidget *window;
7012     GtkWidget *vpaned;
7013     GtkWidget *list;
7014     GtkWidget *text;
7015
7016     gtk_init (&amp;argc, &amp;argv);
7017    
7018     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7019     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
7020     g_signal_connect (G_OBJECT (window), "destroy",
7021                       G_CALLBACK (gtk_main_quit), NULL);
7022     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7023     gtk_widget_set_size_request (GTK_WIDGET (window), 450, 400);
7024
7025     /* create a vpaned widget and add it to our toplevel window */
7026    
7027     vpaned = gtk_vpaned_new ();
7028     gtk_container_add (GTK_CONTAINER (window), vpaned);
7029     gtk_widget_show (vpaned);
7030    
7031     /* Now create the contents of the two halves of the window */
7032    
7033     list = create_list ();
7034     gtk_paned_add1 (GTK_PANED (vpaned), list);
7035     gtk_widget_show (list);
7036    
7037     text = create_text ();
7038     gtk_paned_add2 (GTK_PANED (vpaned), text);
7039     gtk_widget_show (text);
7040     gtk_widget_show (window);
7041
7042     gtk_main ();
7043
7044     return 0;
7045 }
7046 <!-- example-end -->
7047 </programlisting>
7048
7049 </sect1>
7050
7051 <!-- ----------------------------------------------------------------- -->
7052 <sect1 id="sec-Viewports">
7053 <title>Viewports</title>
7054
7055 <para>It is unlikely that you will ever need to use the Viewport widget
7056 directly. You are much more likely to use the
7057 <link linkend="sec-ScrolledWindows">Scrolled Window</link> widget which
7058 itself uses the Viewport.</para>
7059
7060 <para>A viewport widget allows you to place a larger widget within it such
7061 that you can view a part of it at a time. It uses
7062 <link linkend="ch-Adjustments">Adjustments</link> to define the area that
7063 is currently in view.</para>
7064
7065 <para>A Viewport is created with the function</para>
7066
7067 <programlisting role="C">
7068 GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment,
7069                              GtkAdjustment *vadjustment );
7070 </programlisting>
7071
7072 <para>As you can see you can specify the horizontal and vertical Adjustments
7073 that the widget is to use when you create the widget. It will create
7074 its own if you pass NULL as the value of the arguments.</para>
7075
7076 <para>You can get and set the adjustments after the widget has been created
7077 using the following four functions:</para>
7078
7079 <programlisting role="C">
7080 GtkAdjustment *gtk_viewport_get_hadjustment( GtkViewport *viewport );
7081
7082 GtkAdjustment *gtk_viewport_get_vadjustment( GtkViewport *viewport );
7083
7084 void gtk_viewport_set_hadjustment( GtkViewport   *viewport,
7085                                    GtkAdjustment *adjustment );
7086
7087 void gtk_viewport_set_vadjustment( GtkViewport   *viewport,
7088                                    GtkAdjustment *adjustment );
7089 </programlisting>
7090
7091 <para>The only other viewport function is used to alter its appearance:</para>
7092
7093 <programlisting role="C">
7094 void gtk_viewport_set_shadow_type( GtkViewport   *viewport,
7095                                    GtkShadowType  type );
7096 </programlisting>
7097
7098 <para>Possible values for the <literal>type</literal> parameter are:</para>
7099 <programlisting role="C">
7100   GTK_SHADOW_NONE,
7101   GTK_SHADOW_IN,
7102   GTK_SHADOW_OUT,
7103   GTK_SHADOW_ETCHED_IN,
7104   GTK_SHADOW_ETCHED_OUT
7105 </programlisting>
7106  
7107 </sect1>
7108
7109 <!-- ----------------------------------------------------------------- -->
7110 <sect1 id="sec-ScrolledWindows"
7111 <title>Scrolled Windows</title>
7112
7113 <para>Scrolled windows are used to create a scrollable area with another
7114 widget inside it. You may insert any type of widget into a scrolled
7115 window, and it will be accessible regardless of the size by using the
7116 scrollbars.</para>
7117
7118 <para>The following function is used to create a new scrolled window.</para>
7119
7120 <programlisting role="C">
7121 GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
7122                                     GtkAdjustment *vadjustment );
7123 </programlisting>
7124
7125 <para>Where the first argument is the adjustment for the horizontal
7126 direction, and the second, the adjustment for the vertical direction.
7127 These are almost always set to NULL.</para>
7128
7129 <programlisting role="C">
7130 void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
7131                                      GtkPolicyType      hscrollbar_policy,
7132                                      GtkPolicyType      vscrollbar_policy );
7133 </programlisting>
7134
7135 <para>This sets the policy to be used with respect to the scrollbars.
7136 The first argument is the scrolled window you wish to change. The second
7137 sets the policy for the horizontal scrollbar, and the third the policy for 
7138 the vertical scrollbar.</para>
7139
7140 <para>The policy may be one of <literal>GTK_POLICY_AUTOMATIC</literal> or
7141 <literal>GTK_POLICY_ALWAYS</literal>. <literal>GTK_POLICY_AUTOMATIC</literal> will automatically
7142 decide whether you need scrollbars, whereas <literal>GTK_POLICY_ALWAYS</literal>
7143 will always leave the scrollbars there.</para>
7144
7145 <para>You can then place your object into the scrolled window using the
7146 following function.</para>
7147
7148 <programlisting role="C">
7149 void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
7150                                             GtkWidget         *child);
7151 </programlisting>
7152
7153 <para>Here is a simple example that packs a table with 100 toggle buttons
7154 into a scrolled window. I've only commented on the parts that may be
7155 new to you.</para>
7156
7157 <para>
7158 <inlinemediaobject>
7159 <imageobject>
7160 <imagedata fileref="images/scrolledwin.png" format="png">
7161 </imageobject>
7162 </inlinemediaobject>
7163 </para>
7164
7165 <programlisting role="C">
7166 <!-- example-start scrolledwin scrolledwin.c -->
7167
7168 #include &lt;stdio.h&gt;
7169 #include &lt;gtk/gtk.h&gt;
7170
7171 static void destroy( GtkWidget *widget,
7172                      gpointer   data )
7173 {
7174     gtk_main_quit ();
7175 }
7176
7177 int main( int   argc,
7178           char *argv[] )
7179 {
7180     static GtkWidget *window;
7181     GtkWidget *scrolled_window;
7182     GtkWidget *table;
7183     GtkWidget *button;
7184     char buffer[32];
7185     int i, j;
7186     
7187     gtk_init (&amp;argc, &amp;argv);
7188     
7189     /* Create a new dialog window for the scrolled window to be
7190      * packed into.  */
7191     window = gtk_dialog_new ();
7192     g_signal_connect (G_OBJECT (window), "destroy",
7193                       G_CALLBACK (destroy), NULL);
7194     gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
7195     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7196     gtk_widget_set_size_request (window, 300, 300);
7197     
7198     /* create a new scrolled window. */
7199     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
7200     
7201     gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
7202     
7203     /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
7204      * GTK_POLICY_AUTOMATIC will automatically decide whether you need
7205      * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
7206      * there.  The first one is the horizontal scrollbar, the second, 
7207      * the vertical. */
7208     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
7209                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
7210     /* The dialog window is created with a vbox packed into it. */                                                              
7211     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)-&gt;vbox), scrolled_window, 
7212                         TRUE, TRUE, 0);
7213     gtk_widget_show (scrolled_window);
7214     
7215     /* create a table of 10 by 10 squares. */
7216     table = gtk_table_new (10, 10, FALSE);
7217     
7218     /* set the spacing to 10 on x and 10 on y */
7219     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
7220     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
7221     
7222     /* pack the table into the scrolled window */
7223     gtk_scrolled_window_add_with_viewport (
7224                    GTK_SCROLLED_WINDOW (scrolled_window), table);
7225     gtk_widget_show (table);
7226     
7227     /* this simply creates a grid of toggle buttons on the table
7228      * to demonstrate the scrolled window. */
7229     for (i = 0; i &lt; 10; i++)
7230        for (j = 0; j &lt; 10; j++) {
7231           sprintf (buffer, "button (%d,%d)\n", i, j);
7232           button = gtk_toggle_button_new_with_label (buffer);
7233           gtk_table_attach_defaults (GTK_TABLE (table), button,
7234                                      i, i+1, j, j+1);
7235           gtk_widget_show (button);
7236        }
7237     
7238     /* Add a "close" button to the bottom of the dialog */
7239     button = gtk_button_new_with_label ("close");
7240     g_signal_connect_swapped (G_OBJECT (button), "clicked",
7241                               G_CALLBACK (gtk_widget_destroy),
7242                               G_OBJECT (window));
7243     
7244     /* this makes it so the button is the default. */
7245     
7246     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
7247     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)-&gt;action_area), button, TRUE, TRUE, 0);
7248     
7249     /* This grabs this button to be the default button. Simply hitting
7250      * the "Enter" key will cause this button to activate. */
7251     gtk_widget_grab_default (button);
7252     gtk_widget_show (button);
7253     
7254     gtk_widget_show (window);
7255     
7256     gtk_main();
7257     
7258     return 0;
7259 }
7260 <!-- example-end -->
7261 </programlisting>
7262
7263 <para>Try playing with resizing the window. You'll notice how the scrollbars
7264 react. You may also wish to use the gtk_widget_set_size_request() call to set
7265 the default size of the window or other widgets.</para>
7266
7267 </sect1>
7268
7269 <!-- ----------------------------------------------------------------- -->   
7270 <sect1 id="sec-ButtonBoxes">
7271 <title>Button Boxes</title>
7272
7273 <para>Button Boxes are a convenient way to quickly layout a group of
7274 buttons. They come in both horizontal and vertical flavours. You
7275 create a new Button Box with one of the following calls, which create
7276 a horizontal or vertical box, respectively:</para>
7277
7278 <programlisting role="C">
7279 GtkWidget *gtk_hbutton_box_new( void );
7280
7281 GtkWidget *gtk_vbutton_box_new( void );
7282 </programlisting>
7283
7284 <para>Buttons are added to a Button Box using the usual function:</para>
7285
7286 <programlisting role="C">
7287     gtk_container_add (GTK_CONTAINER (button_box), child_widget);
7288 </programlisting>
7289
7290 <para>Here's an example that illustrates all the different layout settings
7291 for Button Boxes.</para>
7292
7293 <para>
7294 <inlinemediaobject>
7295 <imageobject>
7296 <imagedata fileref="images/buttonbox.png" format="png">
7297 </imageobject>
7298 </inlinemediaobject>
7299 </para>
7300
7301 <programlisting role="C">
7302 <!-- example-start buttonbox buttonbox.c -->
7303
7304 #include &lt;gtk/gtk.h&gt;
7305
7306 /* Create a Button Box with the specified parameters */
7307 static GtkWidget *create_bbox( gint  horizontal,
7308                                char *title,
7309                                gint  spacing,
7310                                gint  child_w,
7311                                gint  child_h,
7312                                gint  layout )
7313 {
7314   GtkWidget *frame;
7315   GtkWidget *bbox;
7316   GtkWidget *button;
7317
7318   frame = gtk_frame_new (title);
7319
7320   if (horizontal)
7321     bbox = gtk_hbutton_box_new ();
7322   else
7323     bbox = gtk_vbutton_box_new ();
7324
7325   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
7326   gtk_container_add (GTK_CONTAINER (frame), bbox);
7327
7328   /* Set the appearance of the Button Box */
7329   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
7330   gtk_box_set_spacing (GTK_BOX (bbox), spacing);
7331   /*gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);*/
7332
7333   button = gtk_button_new_from_stock (GTK_STOCK_OK);
7334   gtk_container_add (GTK_CONTAINER (bbox), button);
7335
7336   button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
7337   gtk_container_add (GTK_CONTAINER (bbox), button);
7338
7339   button = gtk_button_new_from_stock (GTK_STOCK_HELP);
7340   gtk_container_add (GTK_CONTAINER (bbox), button);
7341
7342   return frame;
7343 }
7344
7345 int main( int   argc,
7346           char *argv[] )
7347 {
7348   static GtkWidget* window = NULL;
7349   GtkWidget *main_vbox;
7350   GtkWidget *vbox;
7351   GtkWidget *hbox;
7352   GtkWidget *frame_horz;
7353   GtkWidget *frame_vert;
7354
7355   /* Initialize GTK */
7356   gtk_init (&amp;argc, &amp;argv);
7357
7358   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7359   gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
7360
7361   g_signal_connect (G_OBJECT (window), "destroy",
7362                     G_CALLBACK (gtk_main_quit),
7363                     NULL);
7364
7365   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7366
7367   main_vbox = gtk_vbox_new (FALSE, 0);
7368   gtk_container_add (GTK_CONTAINER (window), main_vbox);
7369
7370   frame_horz = gtk_frame_new ("Horizontal Button Boxes");
7371   gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
7372
7373   vbox = gtk_vbox_new (FALSE, 0);
7374   gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
7375   gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
7376
7377   gtk_box_pack_start (GTK_BOX (vbox),
7378            create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
7379                       TRUE, TRUE, 0);
7380
7381   gtk_box_pack_start (GTK_BOX (vbox),
7382            create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
7383                       TRUE, TRUE, 5);
7384
7385   gtk_box_pack_start (GTK_BOX (vbox),
7386            create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
7387                       TRUE, TRUE, 5);
7388
7389   gtk_box_pack_start (GTK_BOX (vbox),
7390            create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END),
7391                       TRUE, TRUE, 5);
7392
7393   frame_vert = gtk_frame_new ("Vertical Button Boxes");
7394   gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
7395
7396   hbox = gtk_hbox_new (FALSE, 0);
7397   gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
7398   gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
7399
7400   gtk_box_pack_start (GTK_BOX (hbox),
7401            create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD),
7402                       TRUE, TRUE, 0);
7403
7404   gtk_box_pack_start (GTK_BOX (hbox),
7405            create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
7406                       TRUE, TRUE, 5);
7407
7408   gtk_box_pack_start (GTK_BOX (hbox),
7409            create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
7410                       TRUE, TRUE, 5);
7411
7412   gtk_box_pack_start (GTK_BOX (hbox),
7413            create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END),
7414                       TRUE, TRUE, 5);
7415
7416   gtk_widget_show_all (window);
7417
7418   /* Enter the event loop */
7419   gtk_main ();
7420     
7421   return 0;
7422 }
7423 <!-- example-end -->
7424 </programlisting>
7425
7426 </sect1>
7427
7428 <!-- ----------------------------------------------------------------- -->   
7429 <sect1 id="sec-Toolbar">
7430 <title>Toolbar</title>
7431
7432 <para>Toolbars are usually used to group some number of widgets in order to
7433 simplify customization of their look and layout. Typically a toolbar
7434 consists of buttons with icons, labels and tooltips, but any other
7435 widget can also be put inside a toolbar. Finally, items can be
7436 arranged horizontally or vertically and buttons can be displayed with
7437 icons, labels, or both.</para>
7438
7439 <para>Creating a toolbar is (as one may already suspect) done with the
7440 following function:</para>
7441
7442 <programlisting role="C">
7443 GtkWidget *gtk_toolbar_new( void );
7444 </programlisting>
7445
7446 <para>After creating a toolbar one can append, prepend and insert items
7447 (that means simple text strings) or elements (that means any widget
7448 types) into the toolbar. To describe an item we need a label text, a
7449 tooltip text, a private tooltip text, an icon for the button and a
7450 callback function for it. For example, to append or prepend an item
7451 you may use the following functions:</para>
7452
7453 <programlisting role="C">
7454 GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
7455                                     const char    *text,
7456                                     const char    *tooltip_text,
7457                                     const char    *tooltip_private_text,
7458                                     GtkWidget     *icon,
7459                                     GtkSignalFunc  callback,
7460                                     gpointer       user_data );
7461
7462 GtkWidget *gtk_toolbar_prepend_item( GtkToolbar    *toolbar,
7463                                      const char    *text,
7464                                      const char    *tooltip_text,
7465                                      const char    *tooltip_private_text,
7466                                      GtkWidget     *icon,
7467                                      GtkSignalFunc  callback,
7468                                      gpointer       user_data );
7469 </programlisting>
7470
7471 <para>If you want to use gtk_toolbar_insert_item(), the only additional
7472 parameter which must be specified is the position in which the item
7473 should be inserted, thus:</para>
7474
7475 <programlisting role="C">
7476 GtkWidget *gtk_toolbar_insert_item( GtkToolbar    *toolbar,
7477                                     const char    *text,
7478                                     const char    *tooltip_text,
7479                                     const char    *tooltip_private_text,
7480                                     GtkWidget     *icon,
7481                                     GtkSignalFunc  callback,
7482                                     gpointer       user_data,
7483                                     gint           position );
7484 </programlisting>
7485
7486 <para>To simplify adding spaces between toolbar items, you may use the
7487 following functions:</para>
7488
7489 <programlisting role="C">
7490 void gtk_toolbar_append_space( GtkToolbar *toolbar );
7491
7492 void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
7493
7494 void gtk_toolbar_insert_space( GtkToolbar *toolbar,
7495                                gint        position );
7496 </programlisting>
7497
7498 <para>If it's required, the orientation of a toolbar and its style can be
7499 changed "on the fly" using the following functions:</para>
7500
7501 <programlisting role="C">
7502 void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
7503                                   GtkOrientation  orientation );
7504
7505 void gtk_toolbar_set_style( GtkToolbar      *toolbar,
7506                             GtkToolbarStyle  style );
7507
7508 void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
7509                                gint        enable );
7510 </programlisting>
7511
7512 <para>Where <literal>orientation</literal> is one of <literal>GTK_ORIENTATION_HORIZONTAL</literal> or
7513 <literal>GTK_ORIENTATION_VERTICAL</literal>. The <literal>style</literal> is used to set
7514 appearance of the toolbar items by using one of
7515 <literal>GTK_TOOLBAR_ICONS</literal>, <literal>GTK_TOOLBAR_TEXT</literal>, or
7516 <literal>GTK_TOOLBAR_BOTH</literal>.</para>
7517
7518 <para>To show some other things that can be done with a toolbar, let's take
7519 the following program (we'll interrupt the listing with some
7520 additional explanations):</para>
7521
7522 <programlisting role="C">
7523 #include &lt;gtk/gtk.h&gt;
7524
7525 /* This function is connected to the Close button or
7526  * closing the window from the WM */
7527 static gboolean delete_event( GtkWidget *widget,
7528                               GdkEvent *event,
7529                               gpointer data )
7530 {
7531   gtk_main_quit ();
7532   return FALSE;
7533 }
7534 </programlisting>
7535
7536 <para>The above beginning seems for sure familiar to you if it's not your first
7537 GTK program. There is one additional thing though, we include a nice XPM
7538 picture to serve as an icon for all of the buttons.</para>
7539
7540 <programlisting role="C">
7541 GtkWidget* close_button; /* This button will emit signal to close
7542                           * application */
7543 GtkWidget* tooltips_button; /* to enable/disable tooltips */
7544 GtkWidget* text_button,
7545          * icon_button,
7546          * both_button; /* radio buttons for toolbar style */
7547 GtkWidget* entry; /* a text entry to show packing any widget into
7548                    * toolbar */
7549 </programlisting>
7550
7551 <para>In fact not all of the above widgets are needed here, but to make things
7552 clearer I put them all together.</para>
7553
7554 <programlisting role="C">
7555 /* that's easy... when one of the buttons is toggled, we just
7556  * check which one is active and set the style of the toolbar
7557  * accordingly
7558  * ATTENTION: our toolbar is passed as data to callback ! */
7559 static void radio_event( GtkWidget *widget,
7560                          gpointer data )
7561 {
7562   if (GTK_TOGGLE_BUTTON (text_button)->active) 
7563     gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_TEXT);
7564   else if (GTK_TOGGLE_BUTTON (icon_button)->active)
7565     gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_ICONS);
7566   else if (GTK_TOGGLE_BUTTON (both_button)->active)
7567     gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH);
7568 }
7569
7570 /* even easier, just check given toggle button and enable/disable 
7571  * tooltips */
7572 static void toggle_event( GtkWidget *widget,
7573                           gpointer   data )
7574 {
7575   gtk_toolbar_set_tooltips (GTK_TOOLBAR (data),
7576                             GTK_TOGGLE_BUTTON (widget)->active );
7577 }
7578 </programlisting>
7579
7580 <para>The above are just two callback functions that will be called when
7581 one of the buttons on a toolbar is pressed. You should already be
7582 familiar with things like this if you've already used toggle buttons (and
7583 radio buttons).</para>
7584
7585 <programlisting role="C">
7586 int main (int argc, char *argv[])
7587 {
7588   /* Here is our main window (a dialog) and a handle for the handlebox */
7589   GtkWidget* dialog;
7590   GtkWidget* handlebox;
7591
7592   /* Ok, we need a toolbar, an icon with a mask (one for all of 
7593      the buttons) and an icon widget to put this icon in (but 
7594      we'll create a separate widget for each button) */
7595   GtkWidget * toolbar;
7596   GtkWidget * iconw;
7597
7598   /* this is called in all GTK application. */
7599   gtk_init (&amp;argc, &amp;argv);
7600   
7601   /* create a new window with a given title, and nice size */
7602   dialog = gtk_dialog_new ();
7603   gtk_window_set_title (GTK_WINDOW (dialog), "GTKToolbar Tutorial");
7604   gtk_widget_set_size_request (GTK_WIDGET (dialog), 600, 300);
7605   GTK_WINDOW (dialog)->allow_shrink = TRUE;
7606
7607   /* typically we quit if someone tries to close us */
7608   g_signal_connect (G_OBJECT (dialog), "delete_event",
7609                     G_CALLBACK (delete_event), NULL);
7610
7611   /* we need to realize the window because we use pixmaps for 
7612    * items on the toolbar in the context of it */
7613   gtk_widget_realize (dialog);
7614
7615   /* to make it nice we'll put the toolbar into the handle box, 
7616    * so that it can be detached from the main window */
7617   handlebox = gtk_handle_box_new ();
7618   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
7619                       handlebox, FALSE, FALSE, 5);
7620 </programlisting>
7621
7622 <para>The above should be similar to any other GTK application. Just
7623 initialization of GTK, creating the window, etc. There is only one
7624 thing that probably needs some explanation: a handle box. A handle box
7625 is just another box that can be used to pack widgets in to. The
7626 difference between it and typical boxes is that it can be detached
7627 from a parent window (or, in fact, the handle box remains in the
7628 parent, but it is reduced to a very small rectangle, while all of its
7629 contents are reparented to a new freely floating window). It is
7630 usually nice to have a detachable toolbar, so these two widgets occur
7631 together quite often.</para>
7632
7633 <programlisting role="C">
7634   /* toolbar will be horizontal, with both icons and text, and
7635    * with 5pxl spaces between items and finally, 
7636    * we'll also put it into our handlebox */
7637   toolbar = gtk_toolbar_new ();
7638   gtk_toolbar_set_orientation (GTK_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
7639   gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH);
7640   gtk_container_set_border_width (GTK_CONTAINER (toolbar), 5);
7641   gtk_toolbar_set_space_size (GTK_TOOLBAR (toolbar), 5);
7642   gtk_container_add (GTK_CONTAINER (handlebox), toolbar);
7643 </programlisting>
7644
7645 <para>Well, what we do above is just a straightforward initialization of
7646 the toolbar widget.</para>
7647
7648 <programlisting role="C">
7649   /* our first item is &lt;close&gt; button */
7650   iconw = gtk_image_new_from_file ("gtk.xpm"); /* icon widget */
7651   close_button = 
7652     gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), /* our toolbar */
7653                              "Close",               /* button label */
7654                              "Closes this app",     /* this button's tooltip */
7655                              "Private",             /* tooltip private info */
7656                              iconw,                 /* icon widget */
7657                              GTK_SIGNAL_FUNC (delete_event), /* a signal */
7658                              NULL);
7659   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar)); /* space after item */
7660 </programlisting>
7661
7662 <para>In the above code you see the simplest case: adding a button to
7663 toolbar.  Just before appending a new item, we have to construct an
7664 image widget to serve as an icon for this item; this step will have
7665 to be repeated for each new item. Just after the item we also add a
7666 space, so the following items will not touch each other. As you see
7667 gtk_toolbar_append_item() returns a pointer to our newly created button
7668 widget, so that we can work with it in the normal way.</para>
7669
7670 <programlisting role="C">
7671   /* now, let's make our radio buttons group... */
7672   iconw = gtk_image_new_from_file ("gtk.xpm");
7673   icon_button = gtk_toolbar_append_element (
7674                     GTK_TOOLBAR (toolbar),
7675                     GTK_TOOLBAR_CHILD_RADIOBUTTON, /* a type of element */
7676                     NULL,                          /* pointer to widget */
7677                     "Icon",                        /* label */
7678                     "Only icons in toolbar",       /* tooltip */
7679                     "Private",                     /* tooltip private string */
7680                     iconw,                         /* icon */
7681                     GTK_SIGNAL_FUNC (radio_event), /* signal */
7682                     toolbar);                      /* data for signal */
7683   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
7684 </programlisting>
7685
7686 <para>Here we begin creating a radio buttons group. To do this we use
7687 gtk_toolbar_append_element.  In fact, using this function one can also
7688 +add simple items or even spaces (type = <literal>GTK_TOOLBAR_CHILD_SPACE</literal>
7689 or +<literal>GTK_TOOLBAR_CHILD_BUTTON</literal>). In the above case we start
7690 creating a radio group. In creating other radio buttons for this group
7691 a pointer to the previous button in the group is required, so that a
7692 list of buttons can be easily constructed (see the section on <link
7693 linkend="sec-RadioButtons">Radio Buttons</link> earlier in this
7694 tutorial).</para>
7695
7696 <programlisting role="C">
7697   /* following radio buttons refer to previous ones */
7698   iconw = gtk_image_new_from_file ("gtk.xpm");
7699   text_button = 
7700     gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
7701                                 GTK_TOOLBAR_CHILD_RADIOBUTTON,
7702                                 icon_button,
7703                                 "Text",
7704                                 "Only texts in toolbar",
7705                                 "Private",
7706                                 iconw,
7707                                 GTK_SIGNAL_FUNC (radio_event),
7708                                 toolbar);
7709   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
7710                                           
7711   iconw = gtk_image_new_from_file ("gtk.xpm");
7712   both_button = 
7713     gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
7714                                 GTK_TOOLBAR_CHILD_RADIOBUTTON,
7715                                 text_button,
7716                                 "Both",
7717                                 "Icons and text in toolbar",
7718                                 "Private",
7719                                 iconw,
7720                                 GTK_SIGNAL_FUNC (radio_event),
7721                                 toolbar);
7722   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
7723   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (both_button), TRUE);
7724 </programlisting>
7725
7726 <para>In the end we have to set the state of one of the buttons manually
7727 (otherwise they all stay in active state, preventing us from switching
7728 between them).</para>
7729
7730 <programlisting role="C">
7731   /* here we have just a simple toggle button */
7732   iconw = gtk_image_new_from_file ("gtk.xpm");
7733   tooltips_button = 
7734     gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
7735                                 GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
7736                                 NULL,
7737                                 "Tooltips",
7738                                 "Toolbar with or without tips",
7739                                 "Private",
7740                                 iconw,
7741                                 GTK_SIGNAL_FUNC (toggle_event),
7742                                 toolbar);
7743   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
7744   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tooltips_button), TRUE);
7745 </programlisting>
7746
7747 <para>A toggle button can be created in the obvious way (if one knows how to create
7748 radio buttons already).</para>
7749
7750 <programlisting role="C">
7751   /* to pack a widget into toolbar, we only have to 
7752    * create it and append it with an appropriate tooltip */
7753   entry = gtk_entry_new ();
7754   gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), 
7755                              entry, 
7756                              "This is just an entry", 
7757                              "Private");
7758
7759   /* well, it isn't created within the toolbar, so we must still show it */
7760   gtk_widget_show (entry);
7761 </programlisting>
7762
7763 <para>As you see, adding any kind of widget to a toolbar is simple. The
7764 one thing you have to remember is that this widget must be shown manually
7765 (contrary to other items which will be shown together with the toolbar).</para>
7766
7767 <programlisting role="C">
7768   /* that's it ! let's show everything. */
7769   gtk_widget_show (toolbar);
7770   gtk_widget_show (handlebox);
7771   gtk_widget_show (dialog);
7772
7773   /* rest in gtk_main and wait for the fun to begin! */
7774   gtk_main ();
7775   
7776   return 0;
7777 }
7778 </programlisting>
7779
7780 <para>So, here we are at the end of toolbar tutorial. Of course, to appreciate
7781 it in full you need also this nice XPM icon, so here it is:</para>
7782
7783 <programlisting role="C">
7784 /* XPM */
7785 static char * gtk_xpm[] = {
7786 "32 39 5 1",
7787 ".      c none",
7788 "+      c black",
7789 "@      c #3070E0",
7790 "#      c #F05050",
7791 "$      c #35E035",
7792 "................+...............",
7793 "..............+++++.............",
7794 "............+++++@@++...........",
7795 "..........+++++@@@@@@++.........",
7796 "........++++@@@@@@@@@@++........",
7797 "......++++@@++++++++@@@++.......",
7798 ".....+++@@@+++++++++++@@@++.....",
7799 "...+++@@@@+++@@@@@@++++@@@@+....",
7800 "..+++@@@@+++@@@@@@@@+++@@@@@++..",
7801 ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
7802 ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
7803 ".+##++@@@@+++@@@+++++@@@@@@@@$@.",
7804 ".+###++@@@@+++@@@+++@@@@@++$$$@.",
7805 ".+####+++@@@+++++++@@@@@+@$$$$@.",
7806 ".+#####+++@@@@+++@@@@++@$$$$$$+.",
7807 ".+######++++@@@@@@@++@$$$$$$$$+.",
7808 ".+#######+##+@@@@+++$$$$$$@@$$+.",
7809 ".+###+++##+##+@@++@$$$$$$++$$$+.",
7810 ".+###++++##+##+@@$$$$$$$@+@$$@+.",
7811 ".+###++++++#+++@$$@+@$$@++$$$@+.",
7812 ".+####+++++++#++$$@+@$$++$$$$+..",
7813 ".++####++++++#++$$@+@$++@$$$$+..",
7814 ".+#####+++++##++$$++@+++$$$$$+..",
7815 ".++####+++##+#++$$+++++@$$$$$+..",
7816 ".++####+++####++$$++++++@$$$@+..",
7817 ".+#####++#####++$$+++@++++@$@+..",
7818 ".+#####++#####++$$++@$$@+++$@@..",
7819 ".++####++#####++$$++$$$$$+@$@++.",
7820 ".++####++#####++$$++$$$$$$$$+++.",
7821 ".+++####+#####++$$++$$$$$$$@+++.",
7822 "..+++#########+@$$+@$$$$$$+++...",
7823 "...+++########+@$$$$$$$$@+++....",
7824 ".....+++######+@$$$$$$$+++......",
7825 "......+++#####+@$$$$$@++........",
7826 ".......+++####+@$$$$+++.........",
7827 ".........++###+$$$@++...........",
7828 "..........++##+$@+++............",
7829 "...........+++++++..............",
7830 ".............++++..............."};
7831 </programlisting>
7832
7833 </sect1>
7834
7835 <!-- ----------------------------------------------------------------- -->
7836 <sect1 id="sec-Notebooks">
7837 <title>Notebooks</title>
7838
7839 <para>The NoteBook Widget is a collection of "pages" that overlap each
7840 other, each page contains different information with only one page
7841 visible at a time. This widget has become more common lately in GUI
7842 programming, and it is a good way to show blocks of similar
7843 information that warrant separation in their display.</para>
7844
7845 <para>The first function call you will need to know, as you can probably
7846 guess by now, is used to create a new notebook widget.</para>
7847
7848 <programlisting role="C">
7849 GtkWidget *gtk_notebook_new( void );
7850 </programlisting>
7851
7852 <para>Once the notebook has been created, there are a number of functions
7853 that operate on the notebook widget. Let's look at them individually.</para>
7854
7855 <para>The first one we will look at is how to position the page indicators.
7856 These page indicators or "tabs" as they are referred to, can be
7857 positioned in four ways: top, bottom, left, or right.</para>
7858
7859 <programlisting role="C">
7860 void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
7861                                GtkPositionType  pos );
7862 </programlisting>
7863
7864 <para>GtkPositionType will be one of the following, which are pretty self
7865 explanatory:</para>
7866 <programlisting role="C">
7867   GTK_POS_LEFT
7868   GTK_POS_RIGHT
7869   GTK_POS_TOP
7870   GTK_POS_BOTTOM
7871 </programlisting>
7872
7873 <para><literal>GTK_POS_TOP</literal> is the default.</para>
7874
7875 <para>Next we will look at how to add pages to the notebook. There are three
7876 ways to add pages to the NoteBook. Let's look at the first two
7877 together as they are quite similar.</para>
7878
7879 <programlisting role="C">
7880 void gtk_notebook_append_page( GtkNotebook *notebook,
7881                                GtkWidget   *child,
7882                                GtkWidget   *tab_label );
7883
7884 void gtk_notebook_prepend_page( GtkNotebook *notebook,
7885                                 GtkWidget   *child,
7886                                 GtkWidget   *tab_label );
7887 </programlisting>
7888
7889 <para>These functions add pages to the notebook by inserting them from the
7890 back of the notebook (append), or the front of the notebook (prepend).
7891 <literal>child</literal> is the widget that is placed within the notebook page, and
7892 <literal>tab_label</literal> is the label for the page being added. The <literal>child</literal>
7893 widget must be created separately, and is typically a set of options
7894 setup witin one of the other container widgets, such as a table.</para>
7895
7896 <para>The final function for adding a page to the notebook contains all of
7897 the properties of the previous two, but it allows you to specify what
7898 position you want the page to be in the notebook.</para>
7899
7900 <programlisting role="C">
7901 void gtk_notebook_insert_page( GtkNotebook *notebook,
7902                                GtkWidget   *child,
7903                                GtkWidget   *tab_label,
7904                                gint         position );
7905 </programlisting>
7906
7907 <para>The parameters are the same as _append_ and _prepend_ except it
7908 contains an extra parameter, <literal>position</literal>.  This parameter is used to
7909 specify what place this page will be inserted into the first page
7910 having position zero.</para>
7911
7912 <para>Now that we know how to add a page, lets see how we can remove a page
7913 from the notebook.</para>
7914
7915 <programlisting role="C">
7916 void gtk_notebook_remove_page( GtkNotebook *notebook,
7917                                gint         page_num );
7918 </programlisting>
7919
7920 <para>This function takes the page specified by <literal>page_num</literal> and removes it
7921 from the widget pointed to by <literal>notebook</literal>.</para>
7922
7923 <para>To find out what the current page is in a notebook use the function:</para>
7924
7925 <programlisting role="C">
7926 gint gtk_notebook_get_current_page( GtkNotebook *notebook );
7927 </programlisting>
7928
7929 <para>These next two functions are simple calls to move the notebook page
7930 forward or backward. Simply provide the respective function call with
7931 the notebook widget you wish to operate on. Note: When the NoteBook is
7932 currently on the last page, and gtk_notebook_next_page() is called, the
7933 notebook will wrap back to the first page. Likewise, if the NoteBook
7934 is on the first page, and gtk_notebook_prev_page() is called, the
7935 notebook will wrap to the last page.</para>
7936
7937 <programlisting role="C">
7938 void gtk_notebook_next_page( GtkNoteBook *notebook );
7939
7940 void gtk_notebook_prev_page( GtkNoteBook *notebook );
7941 </programlisting>
7942
7943 <para>This next function sets the "active" page. If you wish the notebook to
7944 be opened to page 5 for example, you would use this function.  Without
7945 using this function, the notebook defaults to the first page.</para>
7946
7947 <programlisting role="C">
7948 void gtk_notebook_set_current_page( GtkNotebook *notebook,
7949                                     gint         page_num );
7950 </programlisting>
7951
7952 <para>The next two functions add or remove the notebook page tabs and the
7953 notebook border respectively.</para>
7954
7955 <programlisting role="C">
7956 void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
7957                                  gboolean     show_tabs );
7958
7959 void gtk_notebook_set_show_border( GtkNotebook *notebook,
7960                                    gboolean     show_border );
7961 </programlisting>
7962
7963 <para>The next function is useful when the you have a large number of pages,
7964 and the tabs don't fit on the page. It allows the tabs to be scrolled
7965 through using two arrow buttons.</para>
7966
7967 <programlisting role="C">
7968 void gtk_notebook_set_scrollable( GtkNotebook *notebook,
7969                                   gboolean     scrollable );
7970 </programlisting>
7971
7972 <para><literal>show_tabs</literal>, <literal>show_border</literal> and <literal>scrollable</literal> can be either
7973 TRUE or FALSE.</para>
7974
7975 <para>Now let's look at an example, it is expanded from the 
7976 <filename>testgtk.c</filename> code
7977 that comes with the GTK distribution. This small program creates a
7978 window with a notebook and six buttons. The notebook contains 11
7979 pages, added in three different ways, appended, inserted, and
7980 prepended. The buttons allow you rotate the tab positions, add/remove
7981 the tabs and border, remove a page, change pages in both a forward and
7982 backward manner, and exit the program.</para>
7983
7984 <para>
7985 <inlinemediaobject>
7986 <imageobject>
7987 <imagedata fileref="images/notebook.png" format="png">
7988 </imageobject>
7989 </inlinemediaobject>
7990 </para>
7991
7992 <programlisting role="C">
7993 <!-- example-start notebook notebook.c -->
7994
7995 #include &lt;stdio.h&gt;
7996 #include &lt;gtk/gtk.h&gt;
7997
7998 /* This function rotates the position of the tabs */
7999 static void rotate_book( GtkButton   *button,
8000                          GtkNotebook *notebook )
8001 {
8002     gtk_notebook_set_tab_pos (notebook, (notebook-&gt;tab_pos + 1) % 4);
8003 }
8004
8005 /* Add/Remove the page tabs and the borders */
8006 static void tabsborder_book( GtkButton   *button,
8007                              GtkNotebook *notebook )
8008 {
8009     gint tval = FALSE;
8010     gint bval = FALSE;
8011     if (notebook-&gt;show_tabs == 0)
8012             tval = TRUE; 
8013     if (notebook-&gt;show_border == 0)
8014             bval = TRUE;
8015     
8016     gtk_notebook_set_show_tabs (notebook, tval);
8017     gtk_notebook_set_show_border (notebook, bval);
8018 }
8019
8020 /* Remove a page from the notebook */
8021 static void remove_book( GtkButton   *button,
8022                          GtkNotebook *notebook )
8023 {
8024     gint page;
8025     
8026     page = gtk_notebook_get_current_page (notebook);
8027     gtk_notebook_remove_page (notebook, page);
8028     /* Need to refresh the widget -- 
8029      This forces the widget to redraw itself. */
8030     gtk_widget_queue_draw (GTK_WIDGET (notebook));
8031 }
8032
8033 static gboolean delete( GtkWidget *widget,
8034                         GtkWidget *event,
8035                         gpointer   data )
8036 {
8037     gtk_main_quit ();
8038     return FALSE;
8039 }
8040
8041 int main( int argc,
8042           char *argv[] )
8043 {
8044     GtkWidget *window;
8045     GtkWidget *button;
8046     GtkWidget *table;
8047     GtkWidget *notebook;
8048     GtkWidget *frame;
8049     GtkWidget *label;
8050     GtkWidget *checkbutton;
8051     int i;
8052     char bufferf[32];
8053     char bufferl[32];
8054     
8055     gtk_init (&amp;argc, &amp;argv);
8056     
8057     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8058     
8059     g_signal_connect (G_OBJECT (window), "delete_event",
8060                       G_CALLBACK (delete), NULL);
8061     
8062     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8063
8064     table = gtk_table_new (3, 6, FALSE);
8065     gtk_container_add (GTK_CONTAINER (window), table);
8066     
8067     /* Create a new notebook, place the position of the tabs */
8068     notebook = gtk_notebook_new ();
8069     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
8070     gtk_table_attach_defaults (GTK_TABLE (table), notebook, 0, 6, 0, 1);
8071     gtk_widget_show (notebook);
8072     
8073     /* Let's append a bunch of pages to the notebook */
8074     for (i = 0; i &lt; 5; i++) {
8075         sprintf(bufferf, "Append Frame %d", i + 1);
8076         sprintf(bufferl, "Page %d", i + 1);
8077         
8078         frame = gtk_frame_new (bufferf);
8079         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
8080         gtk_widget_set_size_request (frame, 100, 75);
8081         gtk_widget_show (frame);
8082         
8083         label = gtk_label_new (bufferf);
8084         gtk_container_add (GTK_CONTAINER (frame), label);
8085         gtk_widget_show (label);
8086         
8087         label = gtk_label_new (bufferl);
8088         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
8089     }
8090       
8091     /* Now let's add a page to a specific spot */
8092     checkbutton = gtk_check_button_new_with_label ("Check me please!");
8093     gtk_widget_set_size_request (checkbutton, 100, 75);
8094     gtk_widget_show (checkbutton);
8095    
8096     label = gtk_label_new ("Add page");
8097     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
8098     
8099     /* Now finally let's prepend pages to the notebook */
8100     for (i = 0; i &lt; 5; i++) {
8101         sprintf (bufferf, "Prepend Frame %d", i + 1);
8102         sprintf (bufferl, "PPage %d", i + 1);
8103         
8104         frame = gtk_frame_new (bufferf);
8105         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
8106         gtk_widget_set_size_request (frame, 100, 75);
8107         gtk_widget_show (frame);
8108         
8109         label = gtk_label_new (bufferf);
8110         gtk_container_add (GTK_CONTAINER (frame), label);
8111         gtk_widget_show (label);
8112         
8113         label = gtk_label_new (bufferl);
8114         gtk_notebook_prepend_page (GTK_NOTEBOOK (notebook), frame, label);
8115     }
8116     
8117     /* Set what page to start at (page 4) */
8118     gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 3);
8119
8120     /* Create a bunch of buttons */
8121     button = gtk_button_new_with_label ("close");
8122     g_signal_connect_swapped (G_OBJECT (button), "clicked",
8123                               G_CALLBACK (delete), NULL);
8124     gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 1, 1, 2);
8125     gtk_widget_show (button);
8126     
8127     button = gtk_button_new_with_label ("next page");
8128     g_signal_connect_swapped (G_OBJECT (button), "clicked",
8129                               G_CALLBACK (gtk_notebook_next_page),
8130                               G_OBJECT (notebook));
8131     gtk_table_attach_defaults (GTK_TABLE (table), button, 1, 2, 1, 2);
8132     gtk_widget_show (button);
8133     
8134     button = gtk_button_new_with_label ("prev page");
8135     g_signal_connect_swapped (G_OBJECT (button), "clicked",
8136                               G_CALLBACK (gtk_notebook_prev_page),
8137                               G_OBJECT (notebook));
8138     gtk_table_attach_defaults (GTK_TABLE (table), button, 2, 3, 1, 2);
8139     gtk_widget_show (button);
8140     
8141     button = gtk_button_new_with_label ("tab position");
8142     g_signal_connect (G_OBJECT (button), "clicked",
8143                       G_CALLBACK (rotate_book),
8144                       (gpointer) notebook);
8145     gtk_table_attach_defaults (GTK_TABLE (table), button, 3, 4, 1, 2);
8146     gtk_widget_show (button);
8147     
8148     button = gtk_button_new_with_label ("tabs/border on/off");
8149     g_signal_connect (G_OBJECT (button), "clicked",
8150                       G_CALLBACK (tabsborder_book),
8151                       (gpointer) notebook);
8152     gtk_table_attach_defaults (GTK_TABLE (table), button, 4, 5, 1, 2);
8153     gtk_widget_show (button);
8154     
8155     button = gtk_button_new_with_label ("remove page");
8156     g_signal_connect (G_OBJECT (button), "clicked",
8157                       G_CALLBACK (remove_book),
8158                       (gpointer) notebook);
8159     gtk_table_attach_defaults (GTK_TABLE (table), button, 5, 6, 1, 2);
8160     gtk_widget_show (button);
8161     
8162     gtk_widget_show (table);
8163     gtk_widget_show (window);
8164     
8165     gtk_main ();
8166     
8167     return 0;
8168 }
8169 <!-- example-end -->
8170 </programlisting>
8171
8172 <para>I hope this helps you on your way with creating notebooks for your
8173 GTK applications.</para>
8174
8175 </sect1>
8176 </chapter>
8177
8178 <!-- ***************************************************************** -->
8179 <chapter id="ch-MenuWidget">
8180 <title>Menu Widget</title>
8181
8182 <para>There are two ways to create menus: there's the easy way, and there's
8183 the hard way. Both have their uses, but you can usually use the
8184 Itemfactory (the easy way). The "hard" way is to create all the menus
8185 using the calls directly. The easy way is to use the gtk_item_factory
8186 calls. This is much simpler, but there are advantages and
8187 disadvantages to each approach.</para>
8188
8189 <para>The Itemfactory is much easier to use, and to add new menus to,
8190 although writing a few wrapper functions to create menus using the
8191 manual method could go a long way towards usability. With the
8192 Itemfactory, it is not possible to add images or the character '/' to
8193 the menus.</para>
8194
8195 <!-- ----------------------------------------------------------------- -->
8196 <sect1 id="sec-ManualMenuCreation">
8197 <title>Manual Menu Creation</title>
8198
8199 <para>In the true tradition of teaching, we'll show you the hard way
8200 first. <literal>:)</literal></para>
8201
8202 <para>There are three widgets that go into making a menubar and submenus:</para>
8203
8204 <itemizedlist>
8205 <listitem><simpara>a menu item, which is what the user wants to select, e.g.,
8206 "Save"</simpara>
8207 </listitem>
8208 <listitem><simpara>a menu, which acts as a container for the menu items, and</simpara>
8209 </listitem>
8210 <listitem><simpara>a menubar, which is a container for each of the individual
8211 menus.</simpara>
8212 </listitem>
8213 </itemizedlist>
8214
8215 <para>This is slightly complicated by the fact that menu item widgets are
8216 used for two different things. They are both the widgets that are
8217 packed into the menu, and the widget that is packed into the menubar,
8218 which, when selected, activates the menu.</para>
8219
8220 <para>Let's look at the functions that are used to create menus and
8221 menubars.  This first function is used to create a new menubar.</para>
8222
8223 <programlisting role="C">
8224 GtkWidget *gtk_menu_bar_new( void );
8225 </programlisting>
8226
8227 <para>This rather self explanatory function creates a new menubar. You use
8228 gtk_container_add() to pack this into a window, or the box_pack
8229 functions to pack it into a box - the same as buttons.</para>
8230
8231 <programlisting role="C">
8232 GtkWidget *gtk_menu_new( void );
8233 </programlisting>
8234
8235 <para>This function returns a pointer to a new menu; it is never actually
8236 shown (with gtk_widget_show()), it is just a container for the menu
8237 items. I hope this will become more clear when you look at the
8238 example below.</para>
8239
8240 <para>The next three calls are used to create menu items that are packed into
8241 the menu (and menubar).</para>
8242
8243 <programlisting role="C">
8244 GtkWidget *gtk_menu_item_new( void );
8245
8246 GtkWidget *gtk_menu_item_new_with_label( const char *label );
8247
8248 GtkWidget *gtk_menu_item_new_with_mnemonic( const char *label );
8249 </programlisting>
8250
8251 <para>These calls are used to create the menu items that are to be
8252 displayed.  Remember to differentiate between a "menu" as created with
8253 gtk_menu_new() and a "menu item" as created by the gtk_menu_item_new()
8254 functions. The menu item will be an actual button with an associated
8255 action, whereas a menu will be a container holding menu items.</para>
8256
8257 <para>The gtk_menu_item_new_with_label() and gtk_menu_item_new() functions are just as
8258 you'd expect after reading about the buttons. One creates a new menu
8259 item with a label already packed into it, and the other just creates a
8260 blank menu item.</para>
8261
8262 <para>Once you've created a menu item you have to put it into a menu. This
8263 is done using the function gtk_menu_shelll_append. In order to capture when
8264 the item is selected by the user, we need to connect to the
8265 <literal>activate</literal> signal in the usual way. So, if we wanted to create a
8266 standard <literal>File</literal> menu, with the options <literal>Open</literal>, <literal>Save</literal>, and
8267 <literal>Quit</literal>, the code would look something like:</para>
8268
8269 <programlisting role="C">
8270     file_menu = gtk_menu_new ();    /* Don't need to show menus */
8271
8272     /* Create the menu items */
8273     open_item = gtk_menu_item_new_with_label ("Open");
8274     save_item = gtk_menu_item_new_with_label ("Save");
8275     quit_item = gtk_menu_item_new_with_label ("Quit");
8276
8277     /* Add them to the menu */
8278     gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), open_item);
8279     gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), save_item);
8280     gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), quit_item);
8281
8282     /* Attach the callback functions to the activate signal */
8283     g_signal_connect_swapped (G_OBJECT (open_item), "activate",
8284                               G_CALLBACK (menuitem_response),
8285                               (gpointer) "file.open");
8286     g_signal_connect_swapped (G_OBJECT (save_item), "activate",
8287                               G_CALLBACK (menuitem_response),
8288                               (gpointer) "file.save");
8289
8290     /* We can attach the Quit menu item to our exit function */
8291     g_signal_connect_swapped (G_OBJECT (quit_item), "activate",
8292                               G_CALLBACK (destroy),
8293                               (gpointer) "file.quit");
8294
8295     /* We do need to show menu items */
8296     gtk_widget_show (open_item);
8297     gtk_widget_show (save_item);
8298     gtk_widget_show (quit_item);
8299 </programlisting>
8300
8301 <para>At this point we have our menu. Now we need to create a menubar and a
8302 menu item for the <literal>File</literal> entry, to which we add our menu. The code
8303 looks like this:</para>
8304
8305 <programlisting role="C">
8306     menu_bar = gtk_menu_bar_new ();
8307     gtk_container_add (GTK_CONTAINER (window), menu_bar);
8308     gtk_widget_show (menu_bar);
8309
8310     file_item = gtk_menu_item_new_with_label ("File");
8311     gtk_widget_show (file_item);
8312 </programlisting>
8313
8314 <para>Now we need to associate the menu with <literal>file_item</literal>. This is done
8315 with the function</para>
8316
8317 <programlisting role="C">
8318 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
8319                                 GtkWidget   *submenu );
8320 </programlisting>
8321
8322 <para>So, our example would continue with</para>
8323
8324 <programlisting role="C">
8325     gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_item), file_menu);
8326 </programlisting>
8327
8328 <para>All that is left to do is to add the menu to the menubar, which is
8329 accomplished using the function</para>
8330
8331 <programlisting role="C">
8332 void gtk_menu_bar_append( GtkMenuBar *menu_bar,
8333                           GtkWidget  *menu_item );
8334 </programlisting>
8335
8336 <para>which in our case looks like this:</para>
8337
8338 <programlisting role="C">
8339     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), file_item);
8340 </programlisting>
8341
8342 <para>If we wanted the menu right justified on the menubar, such as help
8343 menus often are, we can use the following function (again on
8344 <literal>file_item</literal> in the current example) before attaching it to the
8345 menubar.</para>
8346
8347 <programlisting role="C">
8348 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
8349 </programlisting>
8350
8351 <para>Here is a summary of the steps needed to create a menu bar with menus
8352 attached:</para>
8353
8354 <itemizedlist>
8355 <listitem><simpara> Create a new menu using gtk_menu_new()</simpara>
8356 </listitem>
8357
8358 <listitem><simpara> Use multiple calls to gtk_menu_item_new() for each item you
8359 wish to have on your menu. And use gtk_menu_shell_append() to put each of
8360 these new items on to the menu.</simpara>
8361 </listitem>
8362
8363 <listitem><simpara> Create a menu item using gtk_menu_item_new(). This will be the
8364 root of the menu, the text appearing here will be on the menubar
8365 itself.</simpara>
8366 </listitem>
8367
8368 <listitem><simpara>Use gtk_menu_item_set_submenu() to attach the menu to the root
8369 menu item (the one created in the above step).</simpara>
8370 </listitem>
8371
8372 <listitem><simpara> Create a new menubar using gtk_menu_bar_new. This step only
8373 needs to be done once when creating a series of menus on one menu bar.</simpara>
8374 </listitem>
8375
8376 <listitem><simpara> Use gtk_menu_bar_append() to put the root menu onto the menubar.</simpara>
8377 </listitem>
8378 </itemizedlist>
8379
8380 <para>Creating a popup menu is nearly the same. The difference is that the
8381 menu is not posted "automatically" by a menubar, but explicitly by
8382 calling the function gtk_menu_popup() from a button-press event, for
8383 example.  Take these steps:</para>
8384
8385 <itemizedlist>
8386 <listitem><simpara>Create an event handling function. It needs to have the
8387 prototype</simpara>
8388 <programlisting role="C">
8389 static gboolean handler( GtkWidget *widget,
8390                          GdkEvent  *event );
8391 </programlisting>
8392 <simpara>and it will use the event to find out where to pop up the menu.</simpara>
8393 </listitem>
8394
8395 <listitem><simpara>In the event handler, if the event is a mouse button press,
8396 treat <literal>event</literal> as a button event (which it is) and use it as
8397 shown in the sample code to pass information to gtk_menu_popup().</simpara>
8398 </listitem>
8399
8400 <listitem><simpara>Bind that event handler to a widget with</simpara>
8401 <programlisting role="C">
8402     g_signal_connect_swapped (G_OBJECT (widget), "event",
8403                               G_CALLBACK (handler),
8404                               G_OBJECT (menu));
8405 </programlisting>
8406 <simpara>where <literal>widget</literal> is the widget you are binding to,
8407 <literal>handler</literal> is the handling function, and <literal>menu</literal> is a menu
8408 created with gtk_menu_new(). This can be a menu which is also posted
8409 by a menu bar, as shown in the sample code.</simpara>
8410 </listitem>
8411 </itemizedlist>
8412
8413 </sect1>
8414
8415 <!-- ----------------------------------------------------------------- -->
8416 <sect1 id="sec-ManualMenuExample">
8417 <title>Manual Menu Example</title>
8418
8419 <para>That should about do it. Let's take a look at an example to help clarify.</para>
8420
8421 <para>
8422 <inlinemediaobject>
8423 <imageobject>
8424 <imagedata fileref="images/menu.png" format="png">
8425 </imageobject>
8426 </inlinemediaobject>
8427 </para>
8428
8429 <programlisting role="C">
8430 <!-- example-start menu menu.c -->
8431
8432 #include &lt;stdio.h&gt;
8433 #include &lt;gtk/gtk.h&gt;
8434
8435 static gboolean button_press (GtkWidget *, GdkEvent *);
8436 static void menuitem_response (gchar *);
8437
8438 int main( int   argc,
8439           char *argv[] )
8440 {
8441
8442     GtkWidget *window;
8443     GtkWidget *menu;
8444     GtkWidget *menu_bar;
8445     GtkWidget *root_menu;
8446     GtkWidget *menu_items;
8447     GtkWidget *vbox;
8448     GtkWidget *button;
8449     char buf[128];
8450     int i;
8451
8452     gtk_init (&amp;argc, &amp;argv);
8453
8454     /* create a new window */
8455     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8456     gtk_widget_set_size_request (GTK_WIDGET (window), 200, 100);
8457     gtk_window_set_title (GTK_WINDOW (window), "GTK Menu Test");
8458     g_signal_connect (G_OBJECT (window), "delete_event",
8459                       G_CALLBACK (gtk_main_quit), NULL);
8460
8461     /* Init the menu-widget, and remember -- never
8462      * gtk_show_widget() the menu widget!! 
8463      * This is the menu that holds the menu items, the one that
8464      * will pop up when you click on the "Root Menu" in the app */
8465     menu = gtk_menu_new ();
8466
8467     /* Next we make a little loop that makes three menu-entries for "test-menu".
8468      * Notice the call to gtk_menu_shell_append.  Here we are adding a list of
8469      * menu items to our menu.  Normally, we'd also catch the "clicked"
8470      * signal on each of the menu items and setup a callback for it,
8471      * but it's omitted here to save space. */
8472
8473     for (i = 0; i &lt; 3; i++)
8474         {
8475             /* Copy the names to the buf. */
8476             sprintf (buf, "Test-undermenu - %d", i);
8477
8478             /* Create a new menu-item with a name... */
8479             menu_items = gtk_menu_item_new_with_label (buf);
8480
8481             /* ...and add it to the menu. */
8482             gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
8483
8484             /* Do something interesting when the menuitem is selected */
8485             g_signal_connect_swapped (G_OBJECT (menu_items), "activate",
8486                                       G_CALLBACK (menuitem_response), 
8487                                       (gpointer) g_strdup (buf));
8488
8489             /* Show the widget */
8490             gtk_widget_show (menu_items);
8491         }
8492
8493     /* This is the root menu, and will be the label
8494      * displayed on the menu bar.  There won't be a signal handler attached,
8495      * as it only pops up the rest of the menu when pressed. */
8496     root_menu = gtk_menu_item_new_with_label ("Root Menu");
8497
8498     gtk_widget_show (root_menu);
8499
8500     /* Now we specify that we want our newly created "menu" to be the menu
8501      * for the "root menu" */
8502     gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu);
8503
8504     /* A vbox to put a menu and a button in: */
8505     vbox = gtk_vbox_new (FALSE, 0);
8506     gtk_container_add (GTK_CONTAINER (window), vbox);
8507     gtk_widget_show (vbox);
8508
8509     /* Create a menu-bar to hold the menus and add it to our main window */
8510     menu_bar = gtk_menu_bar_new ();
8511     gtk_box_pack_start (GTK_BOX (vbox), menu_bar, FALSE, FALSE, 2);
8512     gtk_widget_show (menu_bar);
8513
8514     /* Create a button to which to attach menu as a popup */
8515     button = gtk_button_new_with_label ("press me");
8516     g_signal_connect_swapped (G_OBJECT (button), "event",
8517                               G_CALLBACK (button_press), 
8518                               G_OBJECT (menu));
8519     gtk_box_pack_end (GTK_BOX (vbox), button, TRUE, TRUE, 2);
8520     gtk_widget_show (button);
8521
8522     /* And finally we append the menu-item to the menu-bar -- this is the
8523      * "root" menu-item I have been raving about =) */
8524     gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), root_menu);
8525
8526     /* always display the window as the last step so it all splashes on
8527      * the screen at once. */
8528     gtk_widget_show (window);
8529
8530     gtk_main ();
8531
8532     return 0;
8533 }
8534
8535 /* Respond to a button-press by posting a menu passed in as widget.
8536  *
8537  * Note that the "widget" argument is the menu being posted, NOT
8538  * the button that was pressed.
8539  */
8540
8541 static gboolean button_press( GtkWidget *widget,
8542                               GdkEvent *event )
8543 {
8544
8545     if (event-&gt;type == GDK_BUTTON_PRESS) {
8546         GdkEventButton *bevent = (GdkEventButton *) event; 
8547         gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
8548                         bevent-&gt;button, bevent-&gt;time);
8549         /* Tell calling code that we have handled this event; the buck
8550          * stops here. */
8551         return TRUE;
8552     }
8553
8554     /* Tell calling code that we have not handled this event; pass it on. */
8555     return FALSE;
8556 }
8557
8558
8559 /* Print a string when a menu item is selected */
8560
8561 static void menuitem_response( gchar *string )
8562 {
8563     printf ("%s\n", string);
8564 }
8565 <!-- example-end -->
8566 </programlisting>
8567
8568 <para>You may also set a menu item to be insensitive and, using an accelerator
8569 table, bind keys to menu functions.</para>
8570
8571 </sect1>
8572
8573 <!-- ----------------------------------------------------------------- -->
8574 <sect1 id="sec-UsingItemFactory">
8575 <title>Using ItemFactory</title>
8576
8577 <para>Now that we've shown you the hard way, here's how you do it using the
8578 gtk_item_factory calls.</para>
8579
8580 <para>ItemFactory creates a menu out of an array of ItemFactory entries. This 
8581 means you can define your menu in its simplest form and then create the
8582 menu/menubar widgets with a minimum of function calls.</para>
8583
8584 <!-- ----------------------------------------------------------------- -->
8585 <sect2 id="sec-ItemFactoryEntries">
8586 <title>ItemFactory entries</title>
8587
8588 <para>At the core of ItemFactory is the ItemFactoryEntry. This structure defines
8589 one menu item, and when an array of these entries is defined a whole
8590 menu is formed. The ItemFactory entry struct definition looks like this:</para>
8591
8592 <programlisting role="C">
8593 struct _GtkItemFactoryEntry
8594 {
8595   gchar *path;
8596   gchar *accelerator;
8597
8598   GtkItemFactoryCallback callback;
8599   guint                  callback_action;
8600
8601   gchar          *item_type;
8602 };
8603 </programlisting>
8604
8605 <para>Each field defines part of the menu item.</para>
8606
8607 <para><literal>*path</literal> is a string which defines both the name and the
8608 path of a menu item, for example, "/File/Open" would be the name of a menu
8609 item which would come under the ItemFactory entry with path "/File". Note however
8610 that "/File/Open" would be displayed in the File menu as "Open". Also note
8611 since the forward slashes are used to define the path of the menu,
8612 they cannot be used as part of the name. A letter preceded by an underscore
8613 indicates an accelerator (shortcut) key once the menu is open.</para>
8614
8615 <para>
8616 <literal>*accelerator</literal> is a string that indicates a key combination
8617 that can be used as a shortcut to that menu item. The string can be made up
8618 of either a single character, or a combination of modifier keys with a single
8619 character. It is case insensitive.</para>
8620
8621
8622 <para>The available modifier keys are:</para>
8623
8624 <programlisting role="C">
8625 "&lt;ALT&gt;                             - alt
8626 "&lt;CTL&gt;" or "&lt;CTRL&gt;" or "&lt;CONTROL&gt;" - control
8627 "&lt;MOD1&gt;" to "&lt;MOD5&gt;"               - modn
8628 "&lt;SHFT&gt;" or "&lt;SHIFT&gt;"              - shift
8629 </programlisting>
8630
8631 <para>Examples:</para>
8632 <programlisting role="C">
8633 "&lt;ConTroL&gt;a"
8634 "&lt;SHFT&gt;&lt;ALT&gt;&lt;CONTROL&gt;X"
8635 </programlisting>
8636
8637 <para>
8638 <literal>callback</literal> is the function that is called when the menu item
8639 emits the "activate" signal. The form of the callback is described
8640 in the <link linkend="sec-ItemFactoryCallback">Callback Description</link>
8641 section.</para>
8642
8643 <para>
8644 The value of <literal>callback_action</literal> is passed to the callback
8645 function. It also affects the function prototype, as shown
8646 in the <link linkend="sec-ItemFactoryCallback">Callback Description</link>
8647 section.</para>
8648
8649 <para>
8650 <literal>item_type</literal> is a string that defines what type of widget is
8651 packed into the menu items container. It can be:</para>
8652
8653 <programlisting role="C">
8654 NULL or "" or "&lt;Item&gt;" - create a simple item
8655 "&lt;Title&gt;"              - create a title item
8656 "&lt;CheckItem&gt;"          - create a check item
8657 "&lt;ToggleItem&gt;"         - create a toggle item
8658 "&lt;RadioItem&gt;"          - create a (root) radio item
8659 "Path"                 - create a sister radio item
8660 "&lt;Tearoff&gt;"            - create a tearoff
8661 "&lt;Separator&gt;"          - create a separator
8662 "&lt;Branch&gt;"             - create an item to hold submenus (optional)
8663 "&lt;LastBranch&gt;"         - create a right justified branch
8664 "&lt;StockItem&gt;"          - create a simple item with a stock image. 
8665                                see <filename>gtkstock.h</filename> for builtin stock items
8666  
8667 </programlisting>
8668
8669 <para>Note that &lt;LastBranch&gt; is only useful for one submenu of
8670 a menubar.</para>
8671
8672 <!-- ----------------------------------------------------------------- -->
8673 <sect3 id="sec-ItemFactoryCallback">
8674 <title>Callback Description</title>
8675
8676 <para>
8677 The callback for an ItemFactory entry can take two forms. If
8678 <literal>callback_action</literal> is zero, it is of the following
8679 form:</para>
8680
8681 <programlisting role="C">
8682 void callback( void )
8683 </programlisting>
8684
8685 <para>otherwise it is of the form:</para>
8686
8687 <programlisting role="C">
8688 void callback( gpointer    callback_data,
8689                guint       callback_action,
8690                GtkWidget  *widget )
8691 </programlisting>
8692
8693 <para>
8694 <literal>callback_data</literal> is a pointer to an arbitrary piece of data and
8695 is set during the call to gtk_item_factory_create_items().</para>
8696
8697 <para>
8698 <literal>callback_action</literal> is the same value as
8699 <literal>callback_action</literal> in the ItemFactory entry.</para>
8700
8701 <para>
8702 <literal>*widget</literal> is a pointer to a menu item widget
8703 (described in <link linkend="sec-ManualMenuCreation">Manual Menu Creation</link>).
8704 </para>
8705 </sect3>
8706
8707 <!-- ----------------------------------------------------------------- -->
8708 <sect3 id="sec-ItemFactoryEntryExamples">
8709 <title>ItemFactory entry examples</title>
8710
8711 <para>Creating a simple menu item:</para>
8712
8713 <programlisting role="C">
8714 GtkItemFactoryEntry entry = {"/_File/_Open...", "&lt;CTRL&gt;O", print_hello,
8715                                 0, "&lt;Item&gt;"};
8716 </programlisting>
8717
8718 <para>This will define a new simple menu entry "/File/Open" (displayed as "Open"),
8719 under the menu entry "/File". It has the accelerator (shortcut) control+'O'
8720 that when clicked calls the function print_hello(). print_hello() is of
8721 the form <literal>void print_hello(void)</literal> since the callback_action
8722 field is zero. When displayed the 'O' in "Open" will be underlined and if the
8723 menu item is visible on the screen pressing 'O' will activate the item. Note
8724 that "File/_Open" could also have been used as the path instead of
8725 "/_File/_Open".</para>
8726
8727 <para>Creating an entry with a more complex callback:</para>
8728
8729 <programlisting role="C">
8730 GtkItemFactoryEntry entry = {"/_View/Display _FPS", NULL, print_state,
8731                                 7,"&lt;CheckItem&gt;"};
8732 </programlisting>
8733
8734 <para>This defines a new menu item displayed as "Display FPS" which is under
8735 the menu item "View". When clicked the function print_state() will be called.
8736 Since <literal>callback_action</literal> is not zero print_state() is of the
8737 form:</para>
8738
8739 <programlisting role="C">
8740 void print_state( gpointer    callback_data,
8741                   guint       callback_action,
8742                   GtkWidget  *widget )
8743 </programlisting>
8744
8745 <para>with <literal>callback_action</literal> equal to 7.</para>
8746
8747 <para>Creating a radio button set:</para>
8748
8749 <programlisting role="C">
8750 GtkItemFactoryEntry entry1 = {"/_View/_Low Resolution", NULL, change_resolution,
8751                                 1, "&lt;RadioButton&gt;"};
8752 GtkItemFactoryEntry entry2 = {"/_View/_High Resolution", NULL, change_resolution,
8753                                 2, "/View/Low Resolution"};
8754 </programlisting>
8755
8756 <para><literal>entry1</literal> defines a lone radio button that when toggled
8757 calls the function change_resolution() with the parameter
8758 <literal>callback_action</literal> equal to 1. change_resolution() is of
8759 the form:</para>
8760
8761 <programlisting role="C">
8762 void change_resolution(gpointer    callback_data,
8763                        guint       callback_action,
8764                        GtkWidget  *widget)
8765 </programlisting>
8766
8767 <para><literal>entry2</literal> defines a radio button that belongs to the
8768 radio group that entry1 belongs to. It calls the same function when toggled
8769 but with the parameter <literal>callback_action</literal> equal to 2. Note that
8770 the item_type of <literal>entry2</literal> is the path of entry1
8771 <emphasis>without</emphasis> the accelerators ('_'). If another radio button was
8772 required in the same group then it would be defined in the same way as
8773 <literal>entry2</literal> was with its <literal>item_type</literal> again
8774 equal to "/View/Low Resolution".</para>
8775 </sect3>
8776
8777 <!-- ----------------------------------------------------------------- -->
8778 <sect3 id="sec-ItemFactoryEntryArrays">
8779 <title>ItemFactoryEntry Arrays</title>
8780
8781 <para>An ItemFactoryEntry on it's own however isn't useful. An array of
8782 entries is what's required to define a menu. Below is an example of how
8783 you'd declare this array.</para>
8784
8785 <programlisting role="C">
8786 static GtkItemFactoryEntry entries[] = {
8787   { "/_File",         NULL,      NULL,         0, "&lt;Branch&gt;" },
8788   { "/File/tear1",    NULL,      NULL,         0, "&lt;Tearoff&gt;" },
8789   { "/File/_New",     "&lt;CTRL&gt;N", new_file,     1, "&lt;Item&gt;" },
8790   { "/File/_Open...", "&lt;CTRL&gt;O", open_file,    1, "&lt;Item&gt;" },
8791   { "/File/sep1",     NULL,      NULL,         0, "&lt;Separator&gt;" },
8792   { "/File/_Quit",    "&lt;CTRL&gt;Q", quit_program, 0, "&lt;StockItem&gt;", GTK_STOCK_QUIT } };
8793 </programlisting>
8794 </sect3>
8795 </sect2>
8796
8797 <!-- ----------------------------------------------------------------- -->
8798 <sect2 id="sec-ItemFactoryCreation">
8799 <title>Creating an ItemFactory</title>
8800
8801 <para>An array of GtkItemFactoryEntry items defines a menu. Once this
8802 array is defined then the item factory can be created. The function that
8803 does this is:</para>
8804
8805 <programlisting role="C">
8806 GtkItemFactory* gtk_item_factory_new( GtkType        container_type,
8807                                       const gchar   *path,
8808                                       GtkAccelGroup *accel_group );
8809 </programlisting>
8810
8811 <para><literal>container_type</literal> can be one of:</para>
8812
8813 <programlisting role="C">
8814 GTK_TYPE_MENU
8815 GTK_TYPE_MENU_BAR
8816 GTK_TYPE_OPTION_MENU
8817 </programlisting>
8818
8819 <para><literal>container_type</literal> defines what type of menu
8820 you want, so when you extract it later it is either a menu (for pop-ups
8821 for instance), a menu bar, or an option menu (like a combo box but with
8822 a menu of pull downs).</para>
8823
8824 <para><literal>path</literal> defines the path of the root of the menu.
8825 Basically it is a unique name for the root of the menu, it must be
8826 surrounded by "&lt;&gt;". This is important for the naming of the
8827 accelerators and should be unique. It should be unique both for each
8828 menu and between each program. For example in a program named 'foo', the
8829 main menu should be called "&lt;FooMain&gt;", and a pop-up menu
8830 "&lt;FooImagePopUp&gt;", or similar. What's important is that they're unique.</para>
8831
8832 <para><literal>accel_group</literal> is a pointer to a gtk_accel_group. The
8833 item factory sets up the accelerator table while generating menus. New
8834 accelerator groups are generated by gtk_accel_group_new().</para>
8835
8836 <para>But this is just the first step. To convert the array of GtkItemFactoryEntry
8837 information into widgets the following function is used:</para>
8838
8839 <programlisting role="C">
8840 void gtk_item_factory_create_items( GtkItemFactory      *ifactory,
8841                                     guint                n_entries,
8842                                     GtkItemFactoryEntry *entries,
8843                                     gpointer             callback_data );
8844 </programlisting>
8845
8846 <para><literal>*ifactory</literal> a pointer to the above created item factory.</para>
8847 <para><literal>n_entries</literal> is the number of entries in the
8848 GtkItemFactoryEntry array.</para>
8849 <para><literal>*entries</literal> is a pointer to the GtkItemFactoryEntry array.</para>
8850 <para><literal>callback_data</literal> is what gets passed to all the callback functions
8851 for all the entries with callback_action != 0.</para>
8852
8853 <para>The accelerator group has now been formed, so you'll probably want
8854 to attach it to the window the menu is in:</para>
8855
8856 <programlisting role="C">
8857 void gtk_window_add_accel_group( GtkWindow     *window,
8858                                  GtkAccelGroup *accel_group);
8859 </programlisting>
8860 </sect2>
8861
8862 <!-- ----------------------------------------------------------------- -->
8863 <sect2 id="sec-UsingMenuandItems">
8864 <title>Making use of the menu and its menu items</title>
8865
8866 <para>The last thing to do is make use of the menu. The following function
8867 extracts the relevant widgets from the ItemFactory:</para>
8868
8869 <programlisting role="C">
8870 GtkWidget* gtk_item_factory_get_widget( GtkItemFactory *ifactory,
8871                                         const gchar    *path );
8872 </programlisting>
8873
8874 <para>For instance if an ItemFactory has two entries "/File" and "/File/New",
8875 using a path of "/File" would retrieve a <emphasis>menu</emphasis> widget from the
8876 ItemFactory. Using a path of "/File/New" would retrieve a
8877 <emphasis>menu item</emphasis> widget. This makes it possible to set the initial state
8878 of menu items. For example to set the default radio
8879 item to the one with the path "/Shape/Oval" then the following code would
8880 be used:</para>
8881
8882 <programlisting role="C">
8883 gtk_check_menu_item_set_active(
8884         GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory, "/Shape/Oval")),
8885         TRUE);
8886 </programlisting>
8887
8888 <para>Finally to retrieve the root of the menu use gtk_item_factory_get_item()
8889 with a path of "&lt;main&gt;" (or whatever path was used in
8890 gtk_item_factory_new()). In the case of the ItemFactory being created with
8891 type GTK_TYPE_MENU_BAR this returns a menu bar widget. With type GTK_TYPE_MENU
8892 a menu widget is returned. With type GTK_TYPE_OPTION_MENU an option menu
8893 widget is returned.</para>
8894
8895 <para><emphasis>Remember</emphasis> for an entry defined with path "/_File"
8896 the path here is actually "/File".</para>
8897
8898 <para>Now you have a menubar or menu which can be manipulated in the same
8899 way as shown in the
8900 <link linkend="sec-ManualMenuCreation">Manual Menu Creation</link>
8901 section.</para>
8902 </sect2>
8903 </sect1>
8904
8905 <!-- ----------------------------------------------------------------- -->
8906 <sect1 id="sec-ItemFactoryExample">
8907 <title>Item Factory Example</title>
8908
8909 <para>Here is an example using the GTK item factory.</para>
8910
8911 <programlisting role="C">
8912 <!-- example-start menu itemfactory.c -->
8913
8914 #include &lt;gtk/gtk.h&gt;
8915
8916 /* Obligatory basic callback */
8917 static void print_hello( GtkWidget *w,
8918                          gpointer   data )
8919 {
8920   g_message ("Hello, World!\n");
8921 }
8922
8923 /* For the check button */
8924 static void print_toggle( gpointer   callback_data,
8925                           guint      callback_action,
8926                           GtkWidget *menu_item )
8927 {
8928    g_message ("Check button state - %d\n",
8929               GTK_CHECK_MENU_ITEM (menu_item)-&gt;active);
8930 }
8931
8932 /* For the radio buttons */
8933 static void print_selected( gpointer   callback_data,
8934                             guint      callback_action,
8935                             GtkWidget *menu_item )
8936 {
8937    if(GTK_CHECK_MENU_ITEM(menu_item)-&gt;active)
8938      g_message ("Radio button %d selected\n", callback_action);
8939 }
8940
8941 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
8942 static GtkItemFactoryEntry menu_items[] = {
8943   { "/_File",         NULL,         NULL,           0, "&lt;Branch&gt;" },
8944   { "/File/_New",     "&lt;control&gt;N", print_hello,    0, "&lt;StockItem&gt;", GTK_STOCK_NEW },
8945   { "/File/_Open",    "&lt;control&gt;O", print_hello,    0, "&lt;StockItem&gt;", GTK_STOCK_OPEN },
8946   { "/File/_Save",    "&lt;control&gt;S", print_hello,    0, "&lt;StockItem&gt;", GTK_STOCK_SAVE },
8947   { "/File/Save _As", NULL,         NULL,           0, "&lt;Item&gt;" },
8948   { "/File/sep1",     NULL,         NULL,           0, "&lt;Separator&gt;" },
8949   { "/File/_Quit",    "&lt;CTRL&gt;Q", gtk_main_quit, 0, "&lt;StockItem&gt;", GTK_STOCK_QUIT },
8950   { "/_Options",      NULL,         NULL,           0, "&lt;Branch&gt;" },
8951   { "/Options/tear",  NULL,         NULL,           0, "&lt;Tearoff&gt;" },
8952   { "/Options/Check", NULL,         print_toggle,   1, "&lt;CheckItem&gt;" },
8953   { "/Options/sep",   NULL,         NULL,           0, "&lt;Separator&gt;" },
8954   { "/Options/Rad1",  NULL,         print_selected, 1, "&lt;RadioItem&gt;" },
8955   { "/Options/Rad2",  NULL,         print_selected, 2, "/Options/Rad1" },
8956   { "/Options/Rad3",  NULL,         print_selected, 3, "/Options/Rad1" },
8957   { "/_Help",         NULL,         NULL,           0, "&lt;LastBranch&gt;" },
8958   { "/_Help/About",   NULL,         NULL,           0, "&lt;Item&gt;" },
8959 };
8960
8961 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
8962
8963 /* Returns a menubar widget made from the above menu */
8964 static GtkWidget *get_menubar_menu( GtkWidget  *window )
8965 {
8966   GtkItemFactory *item_factory;
8967   GtkAccelGroup *accel_group;
8968
8969   /* Make an accelerator group (shortcut keys) */
8970   accel_group = gtk_accel_group_new ();
8971
8972   /* Make an ItemFactory (that makes a menubar) */
8973   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "&lt;main&gt;",
8974                                        accel_group);
8975
8976   /* This function generates the menu items. Pass the item factory,
8977      the number of items in the array, the array itself, and any
8978      callback data for the the menu items. */
8979   gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
8980
8981   /* Attach the new accelerator group to the window. */
8982   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
8983
8984   /* Finally, return the actual menu bar created by the item factory. */
8985   return gtk_item_factory_get_widget (item_factory, "&lt;main&gt;");
8986 }
8987
8988 /* Popup the menu when the popup button is pressed */
8989 static gboolean popup_cb( GtkWidget *widget,
8990                           GdkEvent *event,
8991                           GtkWidget *menu )
8992 {
8993    GdkEventButton *bevent = (GdkEventButton *)event;
8994   
8995    /* Only take button presses */
8996    if (event-&gt;type != GDK_BUTTON_PRESS)
8997      return FALSE;
8998   
8999    /* Show the menu */
9000    gtk_menu_popup (GTK_MENU(menu), NULL, NULL,
9001                    NULL, NULL, bevent-&gt;button, bevent-&gt;time);
9002   
9003    return TRUE;
9004 }
9005
9006 /* Same as with get_menubar_menu() but just return a button with a signal to
9007    call a popup menu */
9008 GtkWidget *get_popup_menu( void )
9009 {
9010    GtkItemFactory *item_factory;
9011    GtkWidget *button, *menu;
9012   
9013    /* Same as before but don't bother with the accelerators */
9014    item_factory = gtk_item_factory_new (GTK_TYPE_MENU, "&lt;main&gt;",
9015                                         NULL);
9016    gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
9017    menu = gtk_item_factory_get_widget (item_factory, "&lt;main&gt;");
9018   
9019    /* Make a button to activate the popup menu */
9020    button = gtk_button_new_with_label ("Popup");
9021    /* Make the menu popup when clicked */
9022    g_signal_connect (G_OBJECT(button),
9023                      "event",
9024                      G_CALLBACK(popup_cb),
9025                      (gpointer) menu);
9026
9027    return button;
9028 }
9029
9030 /* Same again but return an option menu */
9031 GtkWidget *get_option_menu( void )
9032 {
9033    GtkItemFactory *item_factory;
9034    GtkWidget *option_menu;
9035   
9036    /* Same again, not bothering with the accelerators */
9037    item_factory = gtk_item_factory_new (GTK_TYPE_OPTION_MENU, "&lt;main&gt;",
9038                                         NULL);
9039    gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
9040    option_menu = gtk_item_factory_get_widget (item_factory, "&lt;main&gt;");
9041
9042    return option_menu;
9043 }
9044
9045 /* You have to start somewhere */
9046 int main( int argc,
9047           char *argv[] )
9048 {
9049   GtkWidget *window;
9050   GtkWidget *main_vbox;
9051   GtkWidget *menubar, *option_menu, *popup_button;
9052  
9053   /* Initialize GTK */
9054   gtk_init (&amp;argc, &amp;argv);
9055  
9056   /* Make a window */
9057   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9058   g_signal_connect (G_OBJECT (window), "destroy",
9059                     G_CALLBACK (gtk_main_quit),
9060                     NULL);
9061   gtk_window_set_title (GTK_WINDOW(window), "Item Factory");
9062   gtk_widget_set_size_request (GTK_WIDGET(window), 300, 200);
9063  
9064   /* Make a vbox to put the three menus in */
9065   main_vbox = gtk_vbox_new (FALSE, 1);
9066   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 1);
9067   gtk_container_add (GTK_CONTAINER (window), main_vbox);
9068  
9069   /* Get the three types of menu */
9070   /* Note: all three menus are separately created, so they are not the
9071      same menu */
9072   menubar = get_menubar_menu (window);
9073   popup_button = get_popup_menu ();
9074   option_menu = get_option_menu ();
9075   
9076   /* Pack it all together */
9077   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
9078   gtk_box_pack_end (GTK_BOX (main_vbox), popup_button, FALSE, TRUE, 0);
9079   gtk_box_pack_end (GTK_BOX (main_vbox), option_menu, FALSE, TRUE, 0);
9080
9081   /* Show the widgets */
9082   gtk_widget_show_all (window);
9083   
9084   /* Finished! */
9085   gtk_main ();
9086  
9087   return 0;
9088 }
9089 <!-- example-end -->
9090 </programlisting>
9091
9092 </sect1>
9093 </chapter>
9094
9095 <!-- ***************************************************************** -->
9096 <chapter id="ch-UndocWidgets">
9097 <title>Undocumented Widgets</title>
9098
9099 <para>These all require authors! :) Please consider contributing to our
9100 tutorial.</para>
9101
9102 <para>If you must use one of these widgets that are undocumented, I strongly
9103 suggest you take a look at their respective header files in the GTK
9104 distribution. GTK's function names are very descriptive. Once you
9105 have an understanding of how things work, it's not difficult to figure
9106 out how to use a widget simply by looking at its function
9107 declarations. This, along with a few examples from others' code, and
9108 it should be no problem.</para>
9109
9110 <para>When you do come to understand all the functions of a new undocumented
9111 widget, please consider writing a tutorial on it so others may benefit
9112 from your time.</para>
9113
9114 <!-- ----------------------------------------------------------------- -->
9115 <sect1 id="sec-AccelLabel">
9116 <title>Accel Label</title>
9117
9118 <para></para>
9119
9120 </sect1>
9121
9122 <!-- ----------------------------------------------------------------- -->
9123 <sect1 id="sec-OptionMenu">
9124 <title>Option Menu</title>
9125
9126 <para></para>
9127
9128 </sect1>
9129
9130 <!-- ----------------------------------------------------------------- -->
9131 <sect1 id="sec-MenuItems">
9132 <title>Menu Items</title>
9133
9134 <para></para>
9135
9136 <sect2 id="sec-CheckMenuItem">
9137 <title>Check Menu Item</title>
9138
9139 <para></para>
9140 </sect2>
9141
9142 <sect2 id="sec-RadioMenuItem">
9143 <title>Radio Menu Item</title>
9144
9145 <para></para>
9146 </sect2>
9147
9148 <sect2 id="sec-SeparatorMenuItem">
9149 <title>Separator Menu Item</title>
9150
9151 <para></para>
9152 </sect2>
9153
9154 <sect2 id="sec-TearoffMenuItem">
9155 <title>Tearoff Menu Item</title>
9156
9157 <para></para>
9158 </sect2>
9159 </sect1>
9160
9161 <!-- ----------------------------------------------------------------- -->
9162 <sect1 id="sec-Curves">
9163 <title>Curves</title>
9164
9165 <para></para>
9166
9167 </sect1>
9168
9169 <!-- ----------------------------------------------------------------- -->
9170 <sect1 id="sec-DrawingArea">
9171 <title>Drawing Area</title>
9172
9173 <para></para>
9174
9175 </sect1>
9176
9177 <!-- ----------------------------------------------------------------- -->
9178 <sect1 id="sec-FontSelectionDialog">
9179 <title>Font Selection Dialog</title>
9180
9181 <para></para>
9182
9183 </sect1>
9184
9185 <!-- ----------------------------------------------------------------- -->
9186 <sect1 id="sec-MessageDialog">
9187 <title>Message Dialog</title>
9188
9189 <para></para>
9190
9191 </sect1>
9192
9193 <!-- ----------------------------------------------------------------- -->
9194 <sect1 id="sec-GammaCurve">
9195 <title>Gamma Curve</title>
9196
9197 <para></para>
9198
9199 </sect1>
9200
9201 <!-- ----------------------------------------------------------------- -->
9202 <sect1 id="sec-Image">
9203 <title>Image</title>
9204
9205 <para></para>
9206
9207 </sect1>
9208
9209 <!-- ----------------------------------------------------------------- -->
9210 <sect1 id="sec-PlugsAndSockets">
9211 <title>Plugs and Sockets</title>
9212
9213 <para></para>
9214
9215 </sect1>
9216
9217 <!-- ----------------------------------------------------------------- -->
9218 <sect1 id="sec-TreeView">
9219 <title>Tree View</title>
9220
9221 <para></para>
9222
9223 </sect1>
9224
9225 <!-- ----------------------------------------------------------------- -->
9226 <sect1 id="sec-TextView">
9227 <title>Text View</title>
9228
9229 <para></para>
9230
9231 </sect1>
9232 </chapter>
9233
9234 <!-- ***************************************************************** -->
9235 <chapter id="ch-SettingWidgetAttributes">
9236 <title>Setting Widget Attributes</title>
9237
9238 <para>This describes the functions used to operate on widgets. These can be
9239 used to set style, padding, size, etc.</para>
9240
9241 <para>(Maybe I should make a whole section on accelerators.)</para>
9242
9243 <programlisting role="C">
9244 void gtk_widget_activate( GtkWidget *widget );
9245
9246 void gtk_widget_set_name( GtkWidget *widget,
9247                           gchar     *name );
9248
9249 gchar *gtk_widget_get_name( GtkWidget *widget );
9250
9251 void gtk_widget_set_sensitive( GtkWidget *widget,
9252                                gboolean   sensitive );
9253
9254 void gtk_widget_set_style( GtkWidget *widget,
9255                            GtkStyle  *style );
9256                                            
9257 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
9258
9259 GtkStyle *gtk_widget_get_default_style( void );
9260
9261 void gtk_widget_set_size_request( GtkWidget *widget,
9262                                   gint       width,
9263                                   gint       height );
9264
9265 void gtk_widget_grab_focus( GtkWidget *widget );
9266
9267 void gtk_widget_show( GtkWidget *widget );
9268
9269 void gtk_widget_hide( GtkWidget *widget );
9270 </programlisting>
9271
9272 </chapter>
9273
9274 <!-- ***************************************************************** -->
9275 <chapter id="ch-Timeouts">
9276 <title>Timeouts, IO and Idle Functions</title>
9277
9278 <!-- ----------------------------------------------------------------- -->
9279 <sect1 id="sec-Timeouts">
9280 <title>Timeouts</title>
9281
9282 <para>You may be wondering how you make GTK do useful work when in gtk_main.
9283 Well, you have several options. Using the following function you can
9284 create a timeout function that will be called every "interval"
9285 milliseconds.</para>
9286
9287 <programlisting role="C">
9288 gint g_timeout_add (guint32     interval,
9289                     GtkFunction function,
9290                     gpointer    data);
9291 </programlisting>
9292
9293 <para>The first argument is the number of milliseconds between calls to your
9294 function. The second argument is the function you wish to have called,
9295 and the third, the data passed to this callback function. The return
9296 value is an integer "tag" which may be used to stop the timeout by
9297 calling:</para>
9298
9299 <programlisting role="C">
9300 void g_source_remove (gint tag);
9301 </programlisting>
9302
9303 <para>You may also stop the timeout function by returning zero or FALSE from
9304 your callback function. Obviously this means if you want your function
9305 to continue to be called, it should return a non-zero value,
9306 i.e., TRUE.</para>
9307
9308 <para>The declaration of your callback should look something like this:</para>
9309
9310 <programlisting role="C">
9311 gint timeout_callback (gpointer data);
9312 </programlisting>
9313
9314 </sect1>
9315
9316 <!-- ----------------------------------------------------------------- -->
9317 <sect1 id="sec-MonitoringIO">
9318 <title>Monitoring IO</title>
9319
9320 <para>A nifty feature of GDK (the library that underlies GTK), is the
9321 ability to have it check for data on a file descriptor for you (as
9322 returned by open(2) or socket(2)). This is especially useful for
9323 networking applications. The function:</para>
9324
9325 <programlisting role="C">
9326 gint gdk_input_add( gint              source,
9327                     GdkInputCondition condition,
9328                     GdkInputFunction  function,
9329                     gpointer          data );
9330 </programlisting>
9331
9332 <para>Where the first argument is the file descriptor you wish to have
9333 watched, and the second specifies what you want GDK to look for. This
9334 may be one of:</para>
9335
9336 <itemizedlist>
9337 <listitem><simpara><literal>GDK_INPUT_READ</literal> - Call your function when there is data
9338 ready for reading on your file descriptor.</simpara>
9339 </listitem>
9340
9341 <listitem><simpara><literal>GDK_INPUT_WRITE</literal> - Call your function when the file
9342 descriptor is ready for writing.</simpara>
9343 </listitem>
9344 </itemizedlist>
9345
9346 <para>As I'm sure you've figured out already, the third argument is the
9347 function you wish to have called when the above conditions are
9348 satisfied, and the fourth is the data to pass to this function.</para>
9349
9350 <para>The return value is a tag that may be used to stop GDK from monitoring
9351 this file descriptor using the following function.</para>
9352
9353 <programlisting role="C">
9354 void gdk_input_remove( gint tag );
9355 </programlisting>
9356
9357 <para>The callback function should be declared as:</para>
9358
9359 <programlisting role="C">
9360 void input_callback( gpointer          data,
9361                      gint              source, 
9362                      GdkInputCondition condition );
9363 </programlisting>
9364
9365 <para>Where <literal>source</literal> and <literal>condition</literal> are as specified above.</para>
9366
9367 </sect1>
9368
9369 <!-- ----------------------------------------------------------------- -->
9370 <sect1 id="sec-IdleFunctions">
9371 <title>Idle Functions</title>
9372
9373 <para><!-- TODO: Need to check on idle priorities - TRG -->
9374 What if you have a function which you want to be called when nothing
9375 else is happening ?</para>
9376
9377 <programlisting role="C">
9378 gint gtk_idle_add( GtkFunction function,
9379                    gpointer    data );
9380 </programlisting>
9381
9382 <para>This causes GTK to call the specified function whenever nothing else
9383 is happening.</para>
9384
9385 <programlisting role="C">
9386 void gtk_idle_remove( gint tag );
9387 </programlisting>
9388
9389 <para>I won't explain the meaning of the arguments as they follow very much
9390 like the ones above. The function pointed to by the first argument to
9391 gtk_idle_add will be called whenever the opportunity arises. As with
9392 the others, returning FALSE will stop the idle function from being
9393 called.</para>
9394
9395 </sect1>
9396 </chapter>
9397
9398 <!-- ***************************************************************** -->
9399 <chapter id="ch-AdvancedEventsAndSignals">
9400 <title>Advanced Event and Signal Handling</title>
9401
9402 <!-- ----------------------------------------------------------------- -->
9403 <sect1 id="sec-SignalFunctions">
9404 <title>Signal Functions</title>
9405
9406 <!-- ----------------------------------------------------------------- -->
9407 <sect2>
9408 <title>Connecting and Disconnecting Signal Handlers</title>
9409
9410 <programlisting role="C">
9411 gulong g_signal_connect( GObject     *object,
9412                          const gchar *name,
9413                          GCallback    func,
9414                          gpointer     func_data );
9415
9416 gulong g_signal_connect_after( GObject       *object,
9417                                const gchar   *name,
9418                                GCallback      func,
9419                                gpointer       func_data );
9420
9421 gulong g_signal_connect_swapped( GObject       *object,
9422                                  const gchar   *name,
9423                                  GCallback      func,
9424                                  GObject       *slot_object );
9425
9426 void g_signal_handler_disconnect( GObject *object,
9427                                   gulong   handler_id );
9428
9429 void g_signal_handlers_disconnect_by_func( GObject   *object,
9430                                            GCallback  func,
9431                                            gpointer   data );
9432 </programlisting>
9433
9434 </sect2>
9435
9436 <!-- ----------------------------------------------------------------- -->
9437 <sect2>
9438 <title>Blocking and Unblocking Signal Handlers</title>
9439
9440 <programlisting role="C">
9441 void g_signal_handler_block( GObject *object,
9442                              gulong   handler_id);
9443
9444 void g_signal_handlers_block_by_func( GObject   *object,
9445                                       GCallback  func,
9446                                       gpointer   data );
9447
9448 void g_signal_handler_unblock( GObject *object,
9449                                gulong   handler_id );
9450
9451 void g_signal_handler_unblock_by_func( GObject   *object,
9452                                        GCallback  func,
9453                                        gpointer   data );
9454 </programlisting>
9455
9456 </sect2>
9457
9458 <!-- ----------------------------------------------------------------- -->
9459 <sect2>
9460 <title>Emitting and Stopping Signals</title>
9461
9462 <programlisting role="C">
9463 void g_signal_emit( GObject *object,
9464                     guint      signal_id,
9465                     ... );
9466
9467 void g_signal_emit_by_name( GObject     *object,
9468                             const gchar *name,
9469                             ... );
9470
9471 void g_signal_emitv( const GValue *instance_and_params,
9472                      guint         signal_id,
9473                      GQuark        detail,
9474                      GValue       *return_value );
9475
9476 void g_signal_stop_emission( GObject *object,
9477                              guint    signal_id,
9478                              GQuark   detail );
9479
9480 void g_signal_stop_emission_by_name( GObject   *object,
9481                                      const gchar *detailed_signal );
9482 </programlisting>
9483
9484 </sect2>
9485 </sect1>
9486
9487 <!-- ----------------------------------------------------------------- -->
9488 <sect1 id="sec-SignalEmissionAndPropagation">
9489 <title>Signal Emission and Propagation</title>
9490
9491 <para>Signal emission is the process whereby GTK runs all handlers for a
9492 specific object and signal.</para>
9493
9494 <para>First, note that the return value from a signal emission is the return
9495 value of the <emphasis>last</emphasis> handler executed. Since event signals are
9496 all of type <literal>GTK_RUN_LAST</literal>, this will be the default (GTK supplied)
9497 handler, unless you connect with gtk_signal_connect_after().</para>
9498
9499 <para>The way an event (say "button_press_event") is handled, is:</para>
9500
9501 <itemizedlist>
9502 <listitem><simpara>Start with the widget where the event occured.</simpara>
9503 </listitem>
9504
9505 <listitem><simpara>Emit the generic "event" signal. If that signal handler returns
9506 a value of TRUE, stop all processing.</simpara>
9507 </listitem>
9508
9509 <listitem><simpara>Otherwise, emit a specific, "button_press_event" signal. If that
9510 returns TRUE, stop all processing.</simpara>
9511 </listitem>
9512
9513 <listitem><simpara>Otherwise, go to the widget's parent, and repeat the above two
9514 steps.</simpara>
9515 </listitem>
9516
9517 <listitem><simpara>Continue until some signal handler returns TRUE, or until the
9518 top-level widget is reached.</simpara>
9519 </listitem>
9520 </itemizedlist>
9521
9522 <para>Some consequences of the above are:</para>
9523
9524 <itemizedlist>
9525 <listitem><simpara>Your handler's return value will have no effect if there is a
9526 default handler, unless you connect with gtk_signal_connect_after().</simpara>
9527 </listitem>
9528
9529 <listitem><simpara>To prevent the default handler from being run, you need to
9530 connect with gtk_signal_connect() and use
9531 gtk_signal_emit_stop_by_name() - the return value only affects whether
9532 the signal is propagated, not the current emission.</simpara>
9533 </listitem>
9534 </itemizedlist>
9535
9536 </sect1>
9537 </chapter>
9538
9539 <!-- continue GTK+ 2.0 review here -->
9540
9541 <!-- ***************************************************************** -->
9542 <chapter id="ch-ManagingSelections">
9543 <title>Managing Selections</title>
9544
9545 <!-- ----------------------------------------------------------------- -->
9546 <sect1 id="sec-SelectionsOverview">
9547 <title>Overview</title>
9548
9549 <para>One type of interprocess communication supported by X and GTK is
9550 <emphasis>selections</emphasis>. A selection identifies a chunk of data, for
9551 instance, a portion of text, selected by the user in some fashion, for
9552 instance, by dragging with the mouse. Only one application on a
9553 display (the <emphasis>owner</emphasis>) can own a particular selection at one
9554 time, so when a selection is claimed by one application, the previous
9555 owner must indicate to the user that selection has been
9556 relinquished. Other applications can request the contents of a
9557 selection in different forms, called <emphasis>targets</emphasis>. There can be
9558 any number of selections, but most X applications only handle one, the
9559 <emphasis>primary selection</emphasis>.</para>
9560
9561 <para>In most cases, it isn't necessary for a GTK application to deal with
9562 selections itself. The standard widgets, such as the Entry widget,
9563 already have the capability to claim the selection when appropriate
9564 (e.g., when the user drags over text), and to retrieve the contents of
9565 the selection owned by another widget or another application (e.g.,
9566 when the user clicks the second mouse button). However, there may be
9567 cases in which you want to give other widgets the ability to supply
9568 the selection, or you wish to retrieve targets not supported by
9569 default.</para>
9570
9571 <para>A fundamental concept needed to understand selection handling is that
9572 of the <emphasis>atom</emphasis>. An atom is an integer that uniquely identifies a
9573 string (on a certain display). Certain atoms are predefined by the X
9574 server, and in some cases there are constants in <literal>gtk.h</literal>
9575 corresponding to these atoms. For instance the constant
9576 <literal>GDK_PRIMARY_SELECTION</literal> corresponds to the string "PRIMARY".
9577 In other cases, you should use the functions
9578 <literal>gdk_atom_intern()</literal>, to get the atom corresponding to a string,
9579 and <literal>gdk_atom_name()</literal>, to get the name of an atom. Both
9580 selections and targets are identified by atoms.</para>
9581
9582 </sect1>
9583 <!-- ----------------------------------------------------------------- -->
9584 <sect1 id="sec-RetrievingTheSelection">
9585 <title>Retrieving the selection</title>
9586
9587 <para>Retrieving the selection is an asynchronous process. To start the
9588 process, you call:</para>
9589
9590 <programlisting role="C">
9591 gboolean gtk_selection_convert( GtkWidget *widget, 
9592                                 GdkAtom    selection, 
9593                                 GdkAtom    target,
9594                                 guint32    time );
9595 </programlisting>
9596
9597 <para>This <emphasis>converts</emphasis> the selection into the form specified by
9598 <literal>target</literal>. If at all possible, the time field should be the time
9599 from the event that triggered the selection. This helps make sure that
9600 events occur in the order that the user requested them. However, if it
9601 is not available (for instance, if the conversion was triggered by a
9602 "clicked" signal), then you can use the constant
9603 <literal>GDK_CURRENT_TIME</literal>.</para>
9604
9605 <para>When the selection owner responds to the request, a
9606 "selection_received" signal is sent to your application. The handler
9607 for this signal receives a pointer to a <literal>GtkSelectionData</literal>
9608 structure, which is defined as:</para>
9609
9610 <programlisting role="C">
9611 struct _GtkSelectionData
9612 {
9613   GdkAtom selection;
9614   GdkAtom target;
9615   GdkAtom type;
9616   gint    format;
9617   guchar *data;
9618   gint    length;
9619 };
9620 </programlisting>
9621
9622 <para><literal>selection</literal> and <literal>target</literal> are the values you gave in your
9623 <literal>gtk_selection_convert()</literal> call. <literal>type</literal> is an atom that
9624 identifies the type of data returned by the selection owner. Some
9625 possible values are "STRING", a string of latin-1 characters, "ATOM",
9626 a series of atoms, "INTEGER", an integer, etc. Most targets can only
9627 return one type. <literal>format</literal> gives the length of the units (for
9628 instance characters) in bits. Usually, you don't care about this when
9629 receiving data. <literal>data</literal> is a pointer to the returned data, and
9630 <literal>length</literal> gives the length of the returned data, in bytes. If
9631 <literal>length</literal> is negative, then an error occurred and the selection
9632 could not be retrieved. This might happen if no application owned the
9633 selection, or if you requested a target that the application didn't
9634 support. The buffer is actually guaranteed to be one byte longer than
9635 <literal>length</literal>; the extra byte will always be zero, so it isn't
9636 necessary to make a copy of strings just to nul-terminate them.</para>
9637
9638 <para>In the following example, we retrieve the special target "TARGETS",
9639 which is a list of all targets into which the selection can be
9640 converted.</para>
9641
9642 <programlisting role="C">
9643 <!-- example-start selection gettargets.c -->
9644
9645 #include &lt;stdlib.h&gt;
9646 #include &lt;gtk/gtk.h&gt;
9647
9648 static void selection_received( GtkWidget        *widget, 
9649                                 GtkSelectionData *selection_data, 
9650                                 gpointer          data );
9651
9652 /* Signal handler invoked when user clicks on the "Get Targets" button */
9653 static void get_targets( GtkWidget *widget,
9654                          gpointer data )
9655 {
9656   static GdkAtom targets_atom = GDK_NONE;
9657   GtkWidget *window = (GtkWidget *)data;        
9658
9659   /* Get the atom corresponding to the string "TARGETS" */
9660   if (targets_atom == GDK_NONE)
9661     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
9662
9663   /* And request the "TARGETS" target for the primary selection */
9664   gtk_selection_convert (window, GDK_SELECTION_PRIMARY, targets_atom,
9665                          GDK_CURRENT_TIME);
9666 }
9667
9668 /* Signal handler called when the selections owner returns the data */
9669 static void selection_received( GtkWidget        *widget,
9670                                 GtkSelectionData *selection_data, 
9671                                 gpointer          data )
9672 {
9673   GdkAtom *atoms;
9674   GList *item_list;
9675   int i;
9676
9677   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
9678   if (selection_data-&gt;length &lt; 0)
9679     {
9680       g_print ("Selection retrieval failed\n");
9681       return;
9682     }
9683   /* Make sure we got the data in the expected form */
9684   if (selection_data-&gt;type != GDK_SELECTION_TYPE_ATOM)
9685     {
9686       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
9687       return;
9688     }
9689   
9690   /* Print out the atoms we received */
9691   atoms = (GdkAtom *)selection_data-&gt;data;
9692
9693   item_list = NULL;
9694   for (i = 0; i &lt; selection_data-&gt;length / sizeof(GdkAtom); i++)
9695     {
9696       char *name;
9697       name = gdk_atom_name (atoms[i]);
9698       if (name != NULL)
9699         g_print ("%s\n",name);
9700       else
9701         g_print ("(bad atom)\n");
9702     }
9703
9704   return;
9705 }
9706
9707 int main( int   argc,
9708           char *argv[] )
9709 {
9710   GtkWidget *window;
9711   GtkWidget *button;
9712   
9713   gtk_init (&amp;argc, &amp;argv);
9714
9715   /* Create the toplevel window */
9716
9717   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9718   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
9719   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9720
9721   g_signal_connect (G_OBJECT (window), "destroy",
9722                     G_CALLBACK (exit), NULL);
9723
9724   /* Create a button the user can click to get targets */
9725
9726   button = gtk_button_new_with_label ("Get Targets");
9727   gtk_container_add (GTK_CONTAINER (window), button);
9728
9729   g_signal_connect (G_OBJECT (button), "clicked",
9730                     G_CALLBACK (get_targets), (gpointer) window);
9731   g_signal_connect (G_OBJECT (window), "selection_received",
9732                     G_CALLBACK (selection_received), NULL);
9733
9734   gtk_widget_show (button);
9735   gtk_widget_show (window);
9736   
9737   gtk_main ();
9738   
9739   return 0;
9740 }
9741 <!-- example-end -->
9742 </programlisting>
9743
9744 </sect1>
9745 <!-- ----------------------------------------------------------------- -->
9746 <sect1 id="sec-SupplyingTheSelection">
9747 <title>Supplying the selection</title>
9748
9749 <para>Supplying the selection is a bit more complicated. You must register 
9750 handlers that will be called when your selection is requested. For
9751 each selection/target pair you will handle, you make a call to:</para>
9752
9753 <programlisting role="C">
9754 void gtk_selection_add_target( GtkWidget           *widget, 
9755                                GdkAtom              selection,
9756                                GdkAtom              target,
9757                                guint                info );
9758 </programlisting>
9759
9760 <para><literal>widget</literal>, <literal>selection</literal>, and <literal>target</literal> identify the requests
9761 this handler will manage. When a request for a selection is received,
9762 the "selection_get" signal will be called. <literal>info</literal> can be used as an
9763 enumerator to identify the specific target within the callback function.</para>
9764
9765 <para>The callback function has the signature:</para>
9766
9767 <programlisting role="C">
9768 void  "selection_get"( GtkWidget          *widget,
9769                        GtkSelectionData   *selection_data,
9770                        guint               info,
9771                        guint               time );
9772 </programlisting>
9773
9774 <para>The GtkSelectionData is the same as above, but this time, we're
9775 responsible for filling in the fields <literal>type</literal>, <literal>format</literal>,
9776 <literal>data</literal>, and <literal>length</literal>. (The <literal>format</literal> field is actually
9777 important here - the X server uses it to figure out whether the data
9778 needs to be byte-swapped or not. Usually it will be 8 - <emphasis>i.e.</emphasis> a
9779 character - or 32 - <emphasis>i.e.</emphasis> an integer.) This is done by calling the
9780 function:</para>
9781
9782 <programlisting role="C">
9783 void gtk_selection_data_set( GtkSelectionData *selection_data,
9784                              GdkAtom           type,
9785                              gint              format,
9786                              guchar           *data,
9787                              gint              length );
9788 </programlisting>
9789
9790 <para>This function takes care of properly making a copy of the data so that
9791 you don't have to worry about keeping it around. (You should not fill
9792 in the fields of the GtkSelectionData structure by hand.)</para>
9793
9794 <para>When prompted by the user, you claim ownership of the selection by
9795 calling:</para>
9796
9797 <programlisting role="C">
9798 gboolean gtk_selection_owner_set( GtkWidget *widget,
9799                                   GdkAtom    selection,
9800                                   guint32    time );
9801 </programlisting>
9802
9803 <para>If another application claims ownership of the selection, you will
9804 receive a "selection_clear_event".</para>
9805
9806 <para>As an example of supplying the selection, the following program adds
9807 selection functionality to a toggle button. When the toggle button is
9808 depressed, the program claims the primary selection. The only target
9809 supported (aside from certain targets like "TARGETS" supplied by GTK
9810 itself), is the "STRING" target. When this target is requested, a
9811 string representation of the time is returned.</para>
9812
9813 <programlisting role="C">
9814 <!-- example-start selection setselection.c -->
9815
9816 #include &lt;stdlib.h&gt;
9817 #include &lt;gtk/gtk.h&gt;
9818 #include &lt;time.h&gt;
9819 #include &lt;string.h&gt;
9820
9821 GtkWidget *selection_button;
9822 GtkWidget *selection_widget;
9823
9824 /* Callback when the user toggles the selection */
9825 static void selection_toggled( GtkWidget *widget,
9826                                gint      *have_selection )
9827 {
9828   if (GTK_TOGGLE_BUTTON (widget)-&gt;active)
9829     {
9830       *have_selection = gtk_selection_owner_set (selection_widget,
9831                                                  GDK_SELECTION_PRIMARY,
9832                                                  GDK_CURRENT_TIME);
9833       /* if claiming the selection failed, we return the button to
9834          the out state */
9835       if (!*have_selection)
9836         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
9837     }
9838   else
9839     {
9840       if (*have_selection)
9841         {
9842           /* Before clearing the selection by setting the owner to NULL,
9843              we check if we are the actual owner */
9844           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget-&gt;window)
9845             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
9846                                      GDK_CURRENT_TIME);
9847           *have_selection = FALSE;
9848         }
9849     }
9850 }
9851
9852 /* Called when another application claims the selection */
9853 static gboolean selection_clear( GtkWidget         *widget,
9854                                  GdkEventSelection *event,
9855                                  gint              *have_selection )
9856 {
9857   *have_selection = FALSE;
9858   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (selection_button), FALSE);
9859
9860   return TRUE;
9861 }
9862
9863 /* Supplies the current time as the selection. */
9864 static void selection_handle( GtkWidget        *widget, 
9865                               GtkSelectionData *selection_data,
9866                               guint             info,
9867                               guint             time_stamp,
9868                               gpointer          data )
9869 {
9870   gchar *timestr;
9871   time_t current_time;
9872
9873   current_time = time (NULL);
9874   timestr = asctime (localtime (&amp;current_time)); 
9875   /* When we return a single string, it should not be null terminated.
9876      That will be done for us */
9877
9878   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
9879                           8, timestr, strlen (timestr));
9880 }
9881
9882 int main( int   argc,
9883           char *argv[] )
9884 {
9885   GtkWidget *window;
9886
9887   static int have_selection = FALSE;
9888   
9889   gtk_init (&amp;argc, &amp;argv);
9890
9891   /* Create the toplevel window */
9892
9893   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9894   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
9895   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9896
9897   g_signal_connect (G_OBJECT (window), "destroy",
9898                     G_CALLBACK (exit), NULL);
9899
9900   /* Create a toggle button to act as the selection */
9901
9902   selection_widget = gtk_invisible_new ();
9903   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
9904   gtk_container_add (GTK_CONTAINER (window), selection_button);
9905   gtk_widget_show (selection_button);
9906
9907   g_signal_connect (G_OBJECT (selection_button), "toggled",
9908                     G_CALLBACK (selection_toggled), (gpointer) &amp;have_selection);
9909   g_signal_connect (G_OBJECT (selection_widget), "selection_clear_event",
9910                     G_CALLBACK (selection_clear), (gpointer) &amp;have_selection);
9911
9912   gtk_selection_add_target (selection_widget,
9913                             GDK_SELECTION_PRIMARY,
9914                             GDK_SELECTION_TYPE_STRING,
9915                             1);
9916   g_signal_connect (G_OBJECT (selection_widget), "selection_get",
9917                     G_CALLBACK (selection_handle), (gpointer) &amp;have_selection);
9918
9919   gtk_widget_show (selection_button);
9920   gtk_widget_show (window);
9921   
9922   gtk_main ();
9923   
9924   return 0;
9925 }
9926 <!-- example-end -->
9927 </programlisting>
9928
9929 </sect1>
9930 </chapter>
9931
9932 <!-- ***************************************************************** -->
9933 <chapter id="ch-DragAngDrop">
9934 <title>Drag-and-drop (DND)</title>
9935
9936 <para>GTK+ has a high level set of functions for doing inter-process
9937 communication via the drag-and-drop system. GTK+ can perform
9938 drag-and-drop on top of the low level Xdnd and Motif drag-and-drop
9939 protocols.</para>
9940
9941 <!-- ----------------------------------------------------------------- -->
9942 <sect1 id="sec-DragAndDropOverview">
9943 <title>Overview</title>
9944
9945 <para>An application capable of GTK+ drag-and-drop first defines and sets up
9946 the GTK+ widget(s) for drag-and-drop. Each widget can be a source
9947 and/or destination for drag-and-drop. Note that these GTK+ widgets must have
9948 an associated X Window, check using GTK_WIDGET_NO_WINDOW(widget)).</para>
9949
9950 <para>Source widgets can send out drag data, thus allowing the user to drag
9951 things off of them, while destination widgets can receive drag data.
9952 Drag-and-drop destinations can limit who they accept drag data from,
9953 e.g. the same application or any application (including itself).</para>
9954
9955 <para>Sending and receiving drop data makes use of GTK+ signals.
9956 Dropping an item to a destination widget requires both a data
9957 request (for the source widget) and data received signal handler (for
9958 the target widget). Additional signal handers can be connected if you
9959 want to know when a drag begins (at the very instant it starts), to
9960 when a drop is made, and when the entire drag-and-drop procedure has
9961 ended (successfully or not).</para>
9962
9963 <para>Your application will need to provide data for source widgets when
9964 requested, that involves having a drag data request signal handler. For
9965 destination widgets they will need a drop data received signal
9966 handler. </para>
9967
9968 <para>So a typical drag-and-drop cycle would look as follows:</para>
9969 <orderedlist>
9970 <listitem><simpara> Drag begins.</simpara>
9971 </listitem>
9972 <listitem><simpara> Drag data request (when a drop occurs).</simpara>
9973 </listitem>
9974 <listitem><simpara> Drop data received (may be on same or different
9975 application).</simpara>
9976 </listitem>
9977 <listitem><simpara> Drag data delete (if the drag was a move).</simpara>
9978 </listitem>
9979 <listitem><simpara> Drag-and-drop procedure done.</simpara>
9980 </listitem>
9981 </orderedlist>
9982
9983 <para>There are a few minor steps that go in between here and there, but we
9984 will get into detail about that later.</para>
9985
9986 </sect1>
9987
9988 <!-- ----------------------------------------------------------------- -->
9989 <sect1 id="sec-DragAndDropProperties">
9990 <title>Properties</title>
9991
9992 <para>Drag data has the following properties:</para>
9993
9994 <itemizedlist>
9995 <listitem><simpara> Drag action type (ie GDK_ACTION_COPY, GDK_ACTION_MOVE).</simpara>
9996 </listitem>
9997
9998 <listitem><simpara> Client specified arbitrary drag-and-drop type (a name and number pair).</simpara>
9999 </listitem>
10000
10001 <listitem><simpara> Sent and received data format type.</simpara>
10002 </listitem>
10003 </itemizedlist>
10004
10005 <para>Drag actions are quite obvious, they specify if the widget can
10006 drag with the specified action(s), e.g. GDK_ACTION_COPY and/or
10007 GDK_ACTION_MOVE. A GDK_ACTION_COPY would be a typical drag-and-drop
10008 without the source data being deleted while GDK_ACTION_MOVE would be
10009 just like GDK_ACTION_COPY but the source data will be 'suggested' to be
10010 deleted after the received signal handler is called. There are
10011 additional drag actions including GDK_ACTION_LINK which you may want to
10012 look into when you get to more advanced levels of drag-and-drop.</para>
10013
10014 <para>The client specified arbitrary drag-and-drop type is much more
10015 flexible, because your application will be defining and checking for
10016 that specifically. You will need to set up your destination widgets to
10017 receive certain drag-and-drop types by specifying a name and/or number.
10018 It would be more reliable to use a name since another application may
10019 just happen to use the same number for an entirely different
10020 meaning.</para>
10021
10022 <para>Sent and received data format types (<emphasis>selection
10023 target</emphasis>) come into play only in your request and received
10024 data handler functions. The term <emphasis>selection target</emphasis>
10025 is somewhat misleading. It is a term adapted from GTK+ selection
10026 (cut/copy and paste). What <emphasis>selection target</emphasis>
10027 actually means is the data's format type (i.e. GdkAtom, integer, or
10028 string) that being sent or received. Your request data handler function
10029 needs to specify the type (<emphasis>selection target</emphasis>) of
10030 data that it sends out and your received data handler needs to handle
10031 the type (<emphasis>selection target</emphasis>) of data
10032 received.</para>
10033
10034 </sect1>
10035
10036 <!-- ----------------------------------------------------------------- -->
10037 <sect1 id="sec-DragAndDropFunctions">
10038 <title>Functions</title>
10039
10040 <!-- ----------------------------------------------------------------- -->
10041 <sect2 id="sec-DNDSourceWidgets">
10042 <title>Setting up the source widget</title>
10043
10044 <para>The function <literal>gtk_drag_source_set()</literal> specifies a
10045 set of target types for a drag operation on a widget.</para>
10046
10047 <programlisting role="C">
10048 void gtk_drag_source_set( GtkWidget            *widget,
10049                           GdkModifierType       start_button_mask,
10050                           const GtkTargetEntry *targets,
10051                           gint                  n_targets,
10052                           GdkDragAction         actions );
10053 </programlisting>
10054
10055 <para>The parameters signify the following:</para>
10056 <itemizedlist>
10057 <listitem><simpara><literal>widget</literal> specifies the drag source
10058 widget</simpara>
10059 </listitem>
10060 <listitem><simpara><literal>start_button_mask</literal> specifies a
10061 bitmask of buttons that can start the drag (e.g. GDK_BUTTON1_MASK)</simpara>
10062 </listitem>
10063 <listitem><simpara><literal>targets</literal> specifies a table of
10064 target data types the drag will support</simpara>
10065 </listitem>
10066 <listitem><simpara><literal>n_targets</literal> specifies the number of
10067 targets above</simpara>
10068 </listitem>
10069 <listitem><simpara><literal>actions</literal> specifies a bitmask of
10070 possible actions for a drag from this window</simpara>
10071 </listitem>
10072 </itemizedlist>
10073
10074 <para>The <literal>targets</literal> parameter is an array of the
10075 following structure:</para>
10076
10077 <programlisting role="C">
10078 struct GtkTargetEntry {
10079    gchar *target;
10080    guint  flags;
10081    guint  info;
10082  };
10083 </programlisting>
10084
10085 <para>The fields specify a string representing the drag type, optional
10086 flags and application assigned integer identifier.</para>
10087
10088 <para>If a widget is no longer required to act as a source for
10089 drag-and-drop operations, the function
10090 <literal>gtk_drag_source_unset()</literal> can be used to remove a set
10091 of drag-and-drop target types.</para>
10092
10093 <programlisting role="C">
10094 void gtk_drag_source_unset( GtkWidget *widget );
10095 </programlisting>
10096
10097 </sect2>
10098
10099 <!-- ----------------------------------------------------------------- -->
10100 <sect2 id="sec-SignalsOnSourceWidgets">
10101 <title>Signals on the source widget:</title>
10102
10103 <para>The source widget is sent the following signals during a
10104 drag-and-drop operation.</para>
10105
10106 <table pgwide="1">
10107 <title>Source widget signals</title>
10108 <tgroup cols="2">
10109 <colspec colname="Name" colwidth="150">
10110 <colspec colname="Prototype">
10111 <tbody>
10112 <row>
10113 <entry align="left" valign="middle">drag_begin</entry>
10114 <entry align="left" valign="middle"><literal>void (*drag_begin)(GtkWidget *widget,
10115 GdkDragContext *dc, gpointer data)</literal></entry>
10116 </row>
10117 <row>
10118 <entry align="left" valign="middle">drag_motion</entry>
10119 <entry align="left" valign="middle"><literal>gboolean (*drag_motion)(GtkWidget *widget,
10120 GdkDragContext *dc, gint x, gint y, guint t, gpointer data)</literal></entry>
10121 </row>
10122 <row>
10123 <entry align="left" valign="middle">drag_data_get</entry>
10124 <entry align="left" valign="middle"><literal>void (*drag_data_get)(GtkWidget *widget,
10125 GdkDragContext *dc, GtkSelectionData *selection_data, guint info, guint t, gpointer data)</literal></entry>
10126 </row>
10127 <row>
10128 <entry align="left" valign="middle">drag_data_delete</entry>
10129 <entry align="left" valign="middle"><literal>void (*drag_data_delete)(GtkWidget *widget,
10130 GdkDragContext *dc, gpointer data)</literal></entry>
10131 </row>
10132 <row>
10133 <entry align="left" valign="middle">drag_drop</entry>
10134 <entry align="left" valign="middle"><literal>gboolean (*drag_drop)(GtkWidget *widget,
10135 GdkDragContext *dc, gint x, gint y, guint t, gpointer data)</literal></entry>
10136 </row>
10137 <row>
10138 <entry align="left" valign="middle">drag_end</entry>
10139 <entry align="left" valign="middle"><literal>void (*drag_end)(GtkWidget *widget,
10140 GdkDragContext *dc, gpointer data)</literal></entry>
10141 </row>
10142 </tbody>
10143 </tgroup>
10144 </table>
10145
10146 </sect2>
10147
10148 <!-- ----------------------------------------------------------------- -->
10149 <sect2 id="sec-DNDDestWidgets">
10150 <title>Setting up a destination widget:</title>
10151
10152 <para> <literal> gtk_drag_dest_set()</literal> specifies
10153 that this widget can receive drops and specifies what types of drops it
10154 can receive.</para>
10155
10156 <para> <literal> gtk_drag_dest_unset()</literal> specifies
10157 that the widget can no longer receive drops.</para>
10158
10159 <programlisting role="C">
10160 void gtk_drag_dest_set( GtkWidget            *widget,
10161                         GtkDestDefaults       flags,
10162                         const GtkTargetEntry *targets,
10163                         gint                  n_targets,
10164                         GdkDragAction         actions );
10165
10166 void gtk_drag_dest_unset( GtkWidget *widget );
10167 </programlisting>
10168
10169 </sect2>
10170
10171 <!-- ----------------------------------------------------------------- -->
10172 <sect2 id="sec-SignalsOnDestWidgets">
10173 <title>Signals on the destination widget:</title>
10174
10175 <para>The destination widget is sent the following signals during a
10176 drag-and-drop operation.</para>
10177
10178 <table pgwide="1">
10179 <title>Destination widget signals</title>
10180 <tgroup cols="2">
10181 <colspec colname="Name" colwidth="150">
10182 <colspec colname="Prototype">
10183 <tbody>
10184 <row>
10185 <entry align="left" valign="middle">drag_data_received</entry>
10186 <entry align="left" valign="middle"><literal>void (*drag_data_received)(GtkWidget *widget,
10187 GdkDragContext *dc, gint x, gint y, GtkSelectionData *selection_data, guint info, guint t,
10188 gpointer data)</literal></entry>
10189 </row>
10190 </tbody>
10191 </tgroup>
10192 </table>
10193
10194 </sect2>
10195 </sect1>
10196 </chapter>
10197
10198 <!-- ***************************************************************** -->
10199 <chapter id="ch-GLib">
10200 <title>GLib</title>
10201
10202 <para>GLib is a lower-level library that provides many useful definitions
10203 and functions available for use when creating GDK and GTK
10204 applications. These include definitions for basic types and their
10205 limits, standard macros, type conversions, byte order, memory
10206 allocation, warnings and assertions, message logging, timers, string
10207 utilities, hook functions, a lexical scanner, dynamic loading of
10208 modules, and automatic string completion. A number of data structures
10209 (and their related operations) are also defined, including memory
10210 chunks, doubly-linked lists, singly-linked lists, hash tables, strings
10211 (which can grow dynamically), string chunks (groups of strings),
10212 arrays (which can grow in size as elements are added), balanced binary
10213 trees, N-ary trees, quarks (a two-way association of a string and a
10214 unique integer identifier), keyed data lists (lists of data elements
10215 accessible by a string or integer id), relations and tuples (tables of
10216 data which can be indexed on any number of fields), and caches.</para>
10217
10218 <para>A summary of some of GLib's capabilities follows; not every function,
10219 data structure, or operation is covered here.  For more complete
10220 information about the GLib routines, see the GLib documentation. One
10221 source of GLib documentation is <ulink url="http://www.gtk.org/">http://www.gtk.org/</ulink>.</para>
10222
10223 <para>If you are using a language other than C, you should consult your
10224 language's binding documentation. In some cases your language may
10225 have equivalent functionality built-in, while in other cases it may
10226 not.</para>
10227
10228 <!-- ----------------------------------------------------------------- -->
10229 <sect1 id="sec-Definitions">
10230 <title>Definitions</title>
10231
10232 <para>Definitions for the extremes of many of the standard types are:</para>
10233
10234 <programlisting role="C">
10235 G_MINFLOAT
10236 G_MAXFLOAT
10237 G_MINDOUBLE
10238 G_MAXDOUBLE
10239 G_MINSHORT
10240 G_MAXSHORT
10241 G_MAXUSHORT
10242 G_MININT
10243 G_MAXINT
10244 G_MAXUINT
10245 G_MINLONG
10246 G_MAXLONG
10247 G_MAXULONG
10248 G_MININT64
10249 G_MAXINT64
10250 G_MAXUINT64
10251 </programlisting>
10252
10253 <para>Also, the following typedefs. The ones left unspecified are dynamically set
10254 depending on the architecture. Remember to avoid counting on the size of a
10255 pointer if you want to be portable! E.g., a pointer on an Alpha is 8
10256 bytes, but 4 on Intel 80x86 family CPUs.</para>
10257
10258 <programlisting role="C">
10259 char   gchar;
10260 short  gshort;
10261 long   glong;
10262 int    gint;
10263 int    gboolean;
10264
10265 unsigned char   guchar;
10266 unsigned short  gushort;
10267 unsigned long   gulong;
10268 unsigned int    guint;
10269
10270 float   gfloat;
10271 double  gdouble;
10272
10273 unsigned int  gsize;
10274 signed int    gssize;
10275
10276 void*       gpointer;
10277 const void* gconstpointer;
10278
10279 gint8
10280 guint8
10281 gint16
10282 guint16
10283 gint32
10284 guint32
10285 gint64
10286 guint64
10287 </programlisting>
10288
10289 </sect1>
10290
10291 <!-- ----------------------------------------------------------------- -->
10292 <sect1 id="sec-DoublyLinkedLists">
10293 <title>Doubly Linked Lists</title>
10294
10295 <para>The following functions are used to create, manage, and destroy
10296 standard doubly linked lists. Each element in the list contains a
10297 piece of data, together with pointers which link to the previous and
10298 next elements in the list. This enables easy movement in either
10299 direction through the list. The data item is of type "gpointer",
10300 which means the data can be a pointer to your real data or (through
10301 casting) a numeric value (but do not assume that int and gpointer have
10302 the same size!). These routines internally allocate list elements in
10303 blocks, which is more efficient than allocating elements individually.</para>
10304
10305 <para>There is no function to specifically create a list. Instead, simply
10306 create a variable of type GList* and set its value to NULL; NULL is
10307 considered to be the empty list.</para>
10308
10309 <para>To add elements to a list, use the g_list_append(), g_list_prepend(),
10310 g_list_insert(), or g_list_insert_sorted() routines. In all cases
10311 they accept a pointer to the beginning of the list, and return the
10312 (possibly changed) pointer to the beginning of the list. Thus, for
10313 all of the operations that add or remove elements, be sure to save the
10314 returned value!</para>
10315
10316 <programlisting role="C">
10317 GList *g_list_append( GList    *list,
10318                       gpointer  data );
10319 </programlisting>
10320
10321 <para>This adds a new element (with value <literal>data</literal>) onto the end of the
10322 list.</para>
10323   
10324 <programlisting role="C">
10325 GList *g_list_prepend( GList    *list,
10326                        gpointer  data );
10327 </programlisting>
10328
10329 <para>This adds a new element (with value <literal>data</literal>) to the beginning of the
10330 list.</para>
10331
10332 <programlisting role="C">
10333 GList *g_list_insert( GList    *list,
10334                       gpointer  data,
10335                       gint      position );
10336 </programlisting>
10337
10338 <para>This inserts a new element (with value data) into the list at the
10339 given position. If position is 0, this is just like g_list_prepend();
10340 if position is less than 0, this is just like g_list_append().</para>
10341
10342 <programlisting role="C">
10343 GList *g_list_remove( GList    *list,
10344                       gpointer  data );
10345 </programlisting>
10346
10347 <para>This removes the element in the list with the value <literal>data</literal>;
10348 if the element isn't there, the list is unchanged.</para>
10349
10350 <programlisting role="C">
10351 void g_list_free( GList *list );
10352 </programlisting>
10353
10354 <para>This frees all of the memory used by a GList. If the list elements
10355 refer to dynamically-allocated memory, then they should be freed
10356 first.</para>
10357
10358 <para>There are many other GLib functions that support doubly linked lists;
10359 see the glib documentation for more information.  Here are a few of
10360 the more useful functions' signatures:</para>
10361
10362 <programlisting role="C">  
10363 GList *g_list_remove_link( GList *list,
10364                            GList *link );
10365
10366 GList *g_list_reverse( GList *list );
10367
10368 GList *g_list_nth( GList *list,
10369                    gint   n );
10370                            
10371 GList *g_list_find( GList    *list,
10372                     gpointer  data );
10373
10374 GList *g_list_last( GList *list );
10375
10376 GList *g_list_first( GList *list );
10377
10378 gint g_list_length( GList *list );
10379
10380 void g_list_foreach( GList    *list,
10381                      GFunc     func,
10382                      gpointer  user_data );
10383 </programlisting>
10384
10385 </sect1>
10386
10387 <!-- ----------------------------------------------------------------- -->
10388 <sect1 id="sec-SinglyLinkedLists">
10389 <title>Singly Linked Lists</title>
10390
10391 <para>Many of the above functions for singly linked lists are identical to the
10392 above. Here is a list of some of their operations:</para>
10393
10394 <programlisting role="C">
10395 GSList *g_slist_append( GSList   *list,
10396                         gpointer  data );
10397                 
10398 GSList *g_slist_prepend( GSList   *list,
10399                          gpointer  data );
10400                              
10401 GSList *g_slist_insert( GSList   *list,
10402                         gpointer  data,
10403                         gint      position );
10404                              
10405 GSList *g_slist_remove( GSList   *list,
10406                         gpointer  data );
10407                              
10408 GSList *g_slist_remove_link( GSList *list,
10409                              GSList *link );
10410                              
10411 GSList *g_slist_reverse( GSList *list );
10412
10413 GSList *g_slist_nth( GSList *list,
10414                      gint    n );
10415                              
10416 GSList *g_slist_find( GSList   *list,
10417                       gpointer  data );
10418                              
10419 GSList *g_slist_last( GSList *list );
10420
10421 gint g_slist_length( GSList *list );
10422
10423 void g_slist_foreach( GSList   *list,
10424                       GFunc     func,
10425                       gpointer  user_data );
10426         
10427 </programlisting>
10428
10429 </sect1>
10430
10431 <!-- ----------------------------------------------------------------- -->
10432 <sect1 id="sec-MemoryManagement">
10433 <title>Memory Management</title>
10434
10435 <programlisting role="C">
10436 gpointer g_malloc( gulong size );
10437 </programlisting>
10438
10439 <para>This is a replacement for malloc(). You do not need to check the return
10440 value as it is done for you in this function. If the memory allocation
10441 fails for whatever reasons, your applications will be terminated.</para>
10442
10443 <programlisting role="C">
10444 gpointer g_malloc0( gulong size );
10445 </programlisting>
10446
10447 <para>Same as above, but zeroes the memory before returning a pointer to it.</para>
10448
10449 <programlisting role="C">
10450 gpointer g_realloc( gpointer mem,
10451                     gulong   size );
10452 </programlisting>
10453
10454 <para>Relocates "size" bytes of memory starting at "mem".  Obviously, the
10455 memory should have been previously allocated.</para>
10456
10457 <programlisting role="C">
10458 void g_free( gpointer mem );
10459 </programlisting>
10460
10461 <para>Frees memory. Easy one. If <literal>mem</literal> is NULL it simply returns.</para>
10462
10463 <programlisting role="C">
10464 void g_mem_profile( void );
10465 </programlisting>
10466
10467 <para>Dumps a profile of used memory, but requires that you add <literal>#define
10468 MEM_PROFILE</literal> to the top of glib/gmem.c and re-make and make install.</para>
10469
10470 <programlisting role="C">
10471 void g_mem_check( gpointer mem );
10472 </programlisting>
10473
10474 <para>Checks that a memory location is valid. Requires you add <literal>#define
10475 MEM_CHECK</literal> to the top of gmem.c and re-make and make install.</para>
10476
10477 </sect1>
10478
10479 <!-- ----------------------------------------------------------------- -->
10480 <sect1 id="sec-Timers">
10481 <title>Timers</title>
10482
10483 <para>Timer functions can be used to time operations (e.g., to see how much
10484 time has elapsed). First, you create a new timer with g_timer_new().
10485 You can then use g_timer_start() to start timing an operation,
10486 g_timer_stop() to stop timing an operation, and g_timer_elapsed() to
10487 determine the elapsed time.</para>
10488
10489 <programlisting role="C">
10490 GTimer *g_timer_new( void );
10491
10492 void g_timer_destroy( GTimer *timer );
10493
10494 void g_timer_start( GTimer  *timer );
10495
10496 void g_timer_stop( GTimer  *timer );
10497
10498 void g_timer_reset( GTimer  *timer );
10499
10500 gdouble g_timer_elapsed( GTimer *timer,
10501                          gulong *microseconds );
10502 </programlisting>
10503
10504 </sect1>
10505
10506 <!-- ----------------------------------------------------------------- -->
10507 <sect1 id="sec-StringHandling">
10508 <title>String Handling</title>
10509
10510 <para>GLib defines a new type called a GString, which is similar to a
10511 standard C string but one that grows automatically. Its string data
10512 is null-terminated. What this gives you is protection from buffer
10513 overflow programming errors within your program. This is a very
10514 important feature, and hence I recommend that you make use of
10515 GStrings. GString itself has a simple public definition:</para>
10516
10517 <programlisting role="C">
10518 struct GString 
10519 {
10520   gchar *str; /* Points to the string's current \0-terminated value. */
10521   gint len; /* Current length */
10522 };
10523 </programlisting>
10524
10525 <para>As you might expect, there are a number of operations you can do with
10526 a GString.</para>
10527
10528 <programlisting role="C">
10529 GString *g_string_new( gchar *init );
10530 </programlisting>
10531
10532 <para>This constructs a GString, copying the string value of <literal>init</literal>
10533 into the GString and returning a pointer to it. NULL may be given as
10534 the argument for an initially empty GString.</para>
10535
10536 <programlisting role="C">
10537 void g_string_free( GString *string,
10538                     gint     free_segment );
10539 </programlisting>
10540
10541 <para>This frees the memory for the given GString. If <literal>free_segment</literal> is
10542 TRUE, then this also frees its character data.</para>
10543
10544 <programlisting role="C">            
10545 GString *g_string_assign( GString     *lval,
10546                           const gchar *rval );
10547 </programlisting>
10548
10549 <para>This copies the characters from rval into lval, destroying the
10550 previous contents of lval. Note that lval will be lengthened as
10551 necessary to hold the string's contents, unlike the standard strcpy()
10552 function.</para>
10553
10554 <para>The rest of these functions should be relatively obvious (the _c
10555 versions accept a character instead of a string):</para>
10556              
10557 <programlisting role="C">            
10558 GString *g_string_truncate( GString *string,
10559                             gint     len );
10560                              
10561 GString *g_string_append( GString *string,
10562                           gchar   *val );
10563                             
10564 GString *g_string_append_c( GString *string,
10565                             gchar    c );
10566         
10567 GString *g_string_prepend( GString *string,
10568                            gchar   *val );
10569                              
10570 GString *g_string_prepend_c( GString *string,
10571                              gchar    c );
10572         
10573 void g_string_sprintf( GString *string,
10574                        gchar   *fmt,
10575                        ...);
10576         
10577 void g_string_sprintfa ( GString *string,
10578                          gchar   *fmt,
10579                          ... );
10580 </programlisting>
10581
10582 </sect1>
10583
10584 <!-- ----------------------------------------------------------------- -->
10585 <sect1 id="sec-UtilityAndErrorFunctions">
10586 <title>Utility and Error Functions</title>
10587
10588 <programlisting role="C">
10589 gchar *g_strdup( const gchar *str );
10590 </programlisting>
10591
10592 <para>Replacement strdup function.  Copies the original strings contents to
10593 newly allocated memory, and returns a pointer to it.</para>
10594
10595 <programlisting role="C">
10596 gchar *g_strerror( gint errnum );
10597 </programlisting>
10598
10599 <para>I recommend using this for all error messages.  It's much nicer, and more
10600 portable than perror() or others.  The output is usually of the form:</para>
10601
10602 <programlisting role="C">
10603 program name:function that failed:file or further description:strerror
10604 </programlisting>
10605
10606 <para>Here's an example of one such call used in our hello_world program:</para>
10607
10608 <programlisting role="C">
10609 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
10610 </programlisting>
10611
10612 <programlisting role="C">
10613 void g_error( gchar *format, ... );
10614 </programlisting>
10615
10616 <para>Prints an error message. The format is just like printf, but it
10617 prepends "** ERROR **: " to your message, and exits the program.  
10618 Use only for fatal errors.</para>
10619
10620 <programlisting role="C">
10621 void g_warning( gchar *format, ... );
10622 </programlisting>
10623
10624 <para>Same as above, but prepends "** WARNING **: ", and does not exit the
10625 program.</para>
10626
10627 <programlisting role="C">
10628 void g_message( gchar *format, ... );
10629 </programlisting>
10630
10631 <para>Prints "message: " prepended to the string you pass in.</para>
10632
10633 <programlisting role="C">
10634 void g_print( gchar *format, ... );
10635 </programlisting>
10636
10637 <para>Replacement for printf().</para>
10638
10639 <para>And our last function:</para>
10640
10641 <programlisting role="C">
10642 gchar *g_strsignal( gint signum );
10643 </programlisting>
10644
10645 <para>Prints out the name of the Unix system signal given the signal number.
10646 Useful in generic signal handling functions.</para>
10647
10648 <para>All of the above are more or less just stolen from glib.h.  If anyone cares
10649 to document any function, just send me an email!</para>
10650
10651 </sect1>
10652 </chapter>
10653
10654 <!-- ***************************************************************** -->
10655 <chapter id="ch-GTKRCFiles">
10656 <title>GTK's rc Files</title>
10657
10658 <para>GTK has its own way of dealing with application defaults, by using rc
10659 files. These can be used to set the colors of just about any widget, and
10660 can also be used to tile pixmaps onto the background of some widgets.  </para>
10661
10662 <!-- ----------------------------------------------------------------- -->
10663 <sect1 id="sec-FunctionsForRCFiles">
10664 <title>Functions For rc Files</title>
10665
10666 <para>When your application starts, you should include a call to:</para>
10667
10668 <programlisting role="C">
10669 void gtk_rc_parse( char *filename );
10670 </programlisting>
10671
10672 <para>Passing in the filename of your rc file. This will cause GTK to parse
10673 this file, and use the style settings for the widget types defined
10674 there.</para>
10675
10676 <para>If you wish to have a special set of widgets that can take on a
10677 different style from others, or any other logical division of widgets,
10678 use a call to:</para>
10679
10680 <programlisting role="C">
10681 void gtk_widget_set_name( GtkWidget *widget,
10682                           gchar     *name );
10683 </programlisting>
10684
10685 <para>Passing your newly created widget as the first argument, and the name
10686 you wish to give it as the second. This will allow you to change the
10687 attributes of this widget by name through the rc file.</para>
10688
10689 <para>If we use a call something like this:</para>
10690
10691 <programlisting role="C">
10692 button = gtk_button_new_with_label ("Special Button");
10693 gtk_widget_set_name (button, "special button");
10694 </programlisting>
10695
10696 <para>Then this button is given the name "special button" and may be addressed by
10697 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]</para>
10698
10699 <para>The example rc file below, sets the properties of the main window, and lets
10700 all children of that main window inherit the style described by the "main
10701 button" style.  The code used in the application is:</para>
10702
10703 <programlisting role="C">
10704 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10705 gtk_widget_set_name (window, "main window");
10706 </programlisting>
10707
10708 <para>And then the style is defined in the rc file using:</para>
10709
10710 <programlisting role="C">
10711 widget "main window.*GtkButton*" style "main_button"
10712 </programlisting>
10713
10714 <para>Which sets all the Button widgets in the "main window" to the
10715 "main_buttons" style as defined in the rc file.</para>
10716
10717 <para>As you can see, this is a fairly powerful and flexible system.  Use your
10718 imagination as to how best to take advantage of this.</para>
10719
10720 </sect1>
10721
10722 <!-- ----------------------------------------------------------------- -->
10723 <sect1 id="sec-GTKsRCFileFormat">
10724 <title>GTK's rc File Format</title>
10725
10726 <para>The format of the GTK file is illustrated in the example below. This is
10727 the testgtkrc file from the GTK distribution, but I've added a
10728 few comments and things. You may wish to include this explanation in
10729 your application to allow the user to fine tune his application.</para>
10730
10731 <para>There are several directives to change the attributes of a widget.</para>
10732
10733 <itemizedlist>
10734 <listitem><simpara>fg - Sets the foreground color of a widget.</simpara>
10735 </listitem>
10736 <listitem><simpara>bg - Sets the background color of a widget.</simpara>
10737 </listitem>
10738 <listitem><simpara>bg_pixmap - Sets the background of a widget to a tiled pixmap.</simpara>
10739 </listitem>
10740 <listitem><simpara>font - Sets the font to be used with the given widget.</simpara>
10741 </listitem>
10742 </itemizedlist>
10743
10744 <para>In addition to this, there are several states a widget can be in, and you
10745 can set different colors, pixmaps and fonts for each state. These states are:</para>
10746
10747 <itemizedlist>
10748 <listitem><simpara>NORMAL - The normal state of a widget, without the mouse over top of
10749 it, and not being pressed, etc.</simpara>
10750 </listitem>
10751 <listitem><simpara>PRELIGHT - When the mouse is over top of the widget, colors defined
10752 using this state will be in effect.</simpara>
10753 </listitem>
10754 <listitem><simpara>ACTIVE - When the widget is pressed or clicked it will be active, and
10755 the attributes assigned by this tag will be in effect.</simpara>
10756 </listitem>
10757 <listitem><simpara>INSENSITIVE - When a widget is set insensitive, and cannot be
10758 activated, it will take these attributes.</simpara>
10759 </listitem>
10760 <listitem><simpara>SELECTED - When an object is selected, it takes these attributes.</simpara>
10761 </listitem>
10762 </itemizedlist>
10763
10764 <para>When using the "fg" and "bg" keywords to set the colors of widgets, the
10765 format is:</para>
10766
10767 <programlisting role="C">
10768 fg[&lt;STATE>] = { Red, Green, Blue }
10769 </programlisting>
10770
10771 <para>Where STATE is one of the above states (PRELIGHT, ACTIVE, etc), and the Red,
10772 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
10773 white. They must be in float form, or they will register as 0, so a straight 
10774 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
10775 doesn't matter if it's not recognized.  Unrecognized values are set to 0.</para>
10776
10777 <para>bg_pixmap is very similar to the above, except the colors are replaced by a
10778 filename.</para>
10779
10780 <para>pixmap_path is a list of paths separated by ":"'s.  These paths will be
10781 searched for any pixmap you specify.</para>
10782
10783 <para>The font directive is simply:</para>
10784
10785 <programlisting role="C">
10786 font = "&lt;font name>"
10787 </programlisting>
10788
10789 <para>The only hard part is figuring out the font string. Using xfontsel or
10790 a similar utility should help.</para>
10791
10792 <para>The "widget_class" sets the style of a class of widgets. These classes are
10793 listed in the widget overview on the class hierarchy.</para>
10794
10795 <para>The "widget" directive sets a specifically named set of widgets to a
10796 given style, overriding any style set for the given widget class.
10797 These widgets are registered inside the application using the
10798 gtk_widget_set_name() call. This allows you to specify the attributes of a
10799 widget on a per widget basis, rather than setting the attributes of an
10800 entire widget class. I urge you to document any of these special widgets so
10801 users may customize them.</para>
10802
10803 <para>When the keyword <literal>parent</> is used as an attribute, the widget will take on
10804 the attributes of its parent in the application.</para>
10805
10806 <para>When defining a style, you may assign the attributes of a previously defined
10807 style to this new one.</para>
10808
10809 <programlisting role="C">
10810 style "main_button" = "button"
10811 {
10812   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
10813   bg[PRELIGHT] = { 0.75, 0, 0 }
10814 }
10815 </programlisting>
10816
10817 <para>This example takes the "button" style, and creates a new "main_button" style
10818 simply by changing the font and prelight background color of the "button"
10819 style.</para>
10820
10821 <para>Of course, many of these attributes don't apply to all widgets. It's a
10822 simple matter of common sense really. Anything that could apply, should.</para>
10823
10824 </sect1>
10825
10826 <!-- ----------------------------------------------------------------- -->
10827 <sect1 id="sec-ExampleRCFile">
10828 <title>Example rc file</title>
10829
10830 <programlisting role="C">
10831 # pixmap_path "&lt;dir 1>:&lt;dir 2>:&lt;dir 3>:..."
10832 #
10833 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
10834 #
10835 # style &lt;name> [= &lt;name>]
10836 # {
10837 #   &lt;option>
10838 # }
10839 #
10840 # widget &lt;widget_set> style &lt;style_name>
10841 # widget_class &lt;widget_class_set> style &lt;style_name>
10842
10843 # Here is a list of all the possible states.  Note that some do not apply to
10844 # certain widgets.
10845 #
10846 # NORMAL - The normal state of a widget, without the mouse over top of
10847 # it, and not being pressed, etc.
10848 #
10849 # PRELIGHT - When the mouse is over top of the widget, colors defined
10850 # using this state will be in effect.
10851 #
10852 # ACTIVE - When the widget is pressed or clicked it will be active, and
10853 # the attributes assigned by this tag will be in effect.
10854 #
10855 # INSENSITIVE - When a widget is set insensitive, and cannot be
10856 # activated, it will take these attributes.
10857 #
10858 # SELECTED - When an object is selected, it takes these attributes.
10859 #
10860 # Given these states, we can set the attributes of the widgets in each of
10861 # these states using the following directives.
10862 #
10863 # fg - Sets the foreground color of a widget.
10864 # fg - Sets the background color of a widget.
10865 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
10866 # font - Sets the font to be used with the given widget.
10867 #
10868
10869 # This sets a style called "button".  The name is not really important, as
10870 # it is assigned to the actual widgets at the bottom of the file.
10871
10872 style "window"
10873 {
10874   #This sets the padding around the window to the pixmap specified.
10875   #bg_pixmap[&lt;STATE>] = "&lt;pixmap filename>"
10876   bg_pixmap[NORMAL] = "warning.xpm"
10877 }
10878
10879 style "scale"
10880 {
10881   #Sets the foreground color (font color) to red when in the "NORMAL"
10882   #state.
10883   
10884   fg[NORMAL] = { 1.0, 0, 0 }
10885   
10886   #Sets the background pixmap of this widget to that of its parent.
10887   bg_pixmap[NORMAL] = "&lt;parent>"
10888 }
10889
10890 style "button"
10891 {
10892   # This shows all the possible states for a button.  The only one that
10893   # doesn't apply is the SELECTED state.
10894   
10895   fg[PRELIGHT] = { 0, 1.0, 1.0 }
10896   bg[PRELIGHT] = { 0, 0, 1.0 }
10897   bg[ACTIVE] = { 1.0, 0, 0 }
10898   fg[ACTIVE] = { 0, 1.0, 0 }
10899   bg[NORMAL] = { 1.0, 1.0, 0 }
10900   fg[NORMAL] = { .99, 0, .99 }
10901   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
10902   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
10903 }
10904
10905 # In this example, we inherit the attributes of the "button" style and then
10906 # override the font and background color when prelit to create a new
10907 # "main_button" style.
10908
10909 style "main_button" = "button"
10910 {
10911   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
10912   bg[PRELIGHT] = { 0.75, 0, 0 }
10913 }
10914
10915 style "toggle_button" = "button"
10916 {
10917   fg[NORMAL] = { 1.0, 0, 0 }
10918   fg[ACTIVE] = { 1.0, 0, 0 }
10919   
10920   # This sets the background pixmap of the toggle_button to that of its
10921   # parent widget (as defined in the application).
10922   bg_pixmap[NORMAL] = "&lt;parent>"
10923 }
10924
10925 style "text"
10926 {
10927   bg_pixmap[NORMAL] = "marble.xpm"
10928   fg[NORMAL] = { 1.0, 1.0, 1.0 }
10929 }
10930
10931 style "ruler"
10932 {
10933   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
10934 }
10935
10936 # pixmap_path "~/.pixmaps"
10937
10938 # These set the widget types to use the styles defined above.
10939 # The widget types are listed in the class hierarchy, but could probably be
10940 # just listed in this document for the users reference.
10941
10942 widget_class "GtkWindow" style "window"
10943 widget_class "GtkDialog" style "window"
10944 widget_class "GtkFileSelection" style "window"
10945 widget_class "*Gtk*Scale" style "scale"
10946 widget_class "*GtkCheckButton*" style "toggle_button"
10947 widget_class "*GtkRadioButton*" style "toggle_button"
10948 widget_class "*GtkButton*" style "button"
10949 widget_class "*Ruler" style "ruler"
10950 widget_class "*GtkText" style "text"
10951
10952 # This sets all the buttons that are children of the "main window" to
10953 # the main_button style.  These must be documented to be taken advantage of.
10954 widget "main window.*GtkButton*" style "main_button"
10955 </programlisting>
10956
10957 </sect1>
10958 </chapter>
10959
10960 <!-- ***************************************************************** -->
10961 <chapter id="ch-WritingYourOwnWidgets">
10962 <title>Writing Your Own Widgets</title>
10963
10964 <!-- ----------------------------------------------------------------- -->
10965 <sect1 id="sec-WidgetsOverview">
10966 <title>Overview</title>
10967
10968 <para>Although the GTK distribution comes with many types of widgets that
10969 should cover most basic needs, there may come a time when you need to
10970 create your own new widget type. Since GTK uses widget inheritance
10971 extensively, and there is already a widget that is close to what you want,
10972 it is often possible to make a useful new widget type in
10973 just a few lines of code. But before starting work on a new widget, check
10974 around first to make sure that someone has not already written
10975 it. This will prevent duplication of effort and keep the number of
10976 GTK widgets out there to a minimum, which will help keep both the code
10977 and the interface of different applications consistent. As a flip side
10978 to this, once you finish your widget, announce it to the world so
10979 other people can benefit. The best place to do this is probably the
10980 <literal>gtk-list</literal>.</para>
10981
10982 <para>Complete sources for the example widgets are available at the place you 
10983 got this tutorial, or from:</para>
10984
10985 <para><ulink url="http://www.gtk.org/~otaylor/gtk/tutorial/">http://www.gtk.org/~otaylor/gtk/tutorial/</ulink></para>
10986
10987
10988 </sect1>
10989
10990 <!-- ----------------------------------------------------------------- -->
10991 <sect1 id="sec-TheAnatomyOfAWidget">
10992 <title>The Anatomy Of A Widget</title>
10993
10994 <para>In order to create a new widget, it is important to have an
10995 understanding of how GTK objects work. This section is just meant as a
10996 brief overview. See the reference documentation for the details. </para>
10997
10998 <para>GTK widgets are implemented in an object oriented fashion. However,
10999 they are implemented in standard C. This greatly improves portability
11000 and stability over using current generation C++ compilers; however,
11001 it does mean that the widget writer has to pay attention to some of
11002 the implementation details. The information common to all instances of
11003 one class of widgets (e.g., to all Button widgets) is stored in the 
11004 <emphasis>class structure</emphasis>. There is only one copy of this in
11005 which is stored information about the class's signals
11006 (which act like virtual functions in C). To support inheritance, the
11007 first field in the class structure must be a copy of the parent's
11008 class structure. The declaration of the class structure of GtkButtton
11009 looks like:</para>
11010
11011 <programlisting role="C">
11012 struct _GtkButtonClass
11013 {
11014   GtkContainerClass parent_class;
11015
11016   void (* pressed)  (GtkButton *button);
11017   void (* released) (GtkButton *button);
11018   void (* clicked)  (GtkButton *button);
11019   void (* enter)    (GtkButton *button);
11020   void (* leave)    (GtkButton *button);
11021 };
11022 </programlisting>
11023
11024 <para>When a button is treated as a container (for instance, when it is
11025 resized), its class structure can be cast to GtkContainerClass, and
11026 the relevant fields used to handle the signals.</para>
11027
11028 <para>There is also a structure for each widget that is created on a
11029 per-instance basis. This structure has fields to store information that
11030 is different for each instance of the widget. We'll call this
11031 structure the <emphasis>object structure</emphasis>. For the Button class, it looks
11032 like:</para>
11033
11034 <programlisting role="C">
11035 struct _GtkButton
11036 {
11037   GtkContainer container;
11038
11039   GtkWidget *child;
11040
11041   guint in_button : 1;
11042   guint button_down : 1;
11043 };
11044 </programlisting>
11045
11046 <para>Note that, similar to the class structure, the first field is the
11047 object structure of the parent class, so that this structure can be
11048 cast to the parent class' object structure as needed.</para>
11049
11050 </sect1>
11051
11052 <!-- ----------------------------------------------------------------- -->
11053 <sect1 id="sec-CreatingACompositeWidget">
11054 <title>Creating a Composite widget</title>
11055
11056 <!-- ----------------------------------------------------------------- -->
11057 <sect2>
11058 <title>Introduction</title>
11059
11060 <para>One type of widget that you may be interested in creating is a
11061 widget that is merely an aggregate of other GTK widgets. This type of
11062 widget does nothing that couldn't be done without creating new
11063 widgets, but provides a convenient way of packaging user interface
11064 elements for reuse. The FileSelection and ColorSelection widgets in
11065 the standard distribution are examples of this type of widget.</para>
11066
11067 <para>The example widget that we'll create in this section is the Tictactoe
11068 widget, a 3x3 array of toggle buttons which triggers a signal when all
11069 three buttons in a row, column, or on one of the diagonals are
11070 depressed. </para>
11071
11072 <para><emphasis>Note: the full source code for the Tictactoe example described
11073 below is in the <link linkend="sec-Tictactoe">Code Examples Appendix</link>
11074 </emphasis></para>
11075
11076 <para>
11077 <inlinemediaobject>
11078 <imageobject>
11079 <imagedata fileref="images/tictactoe.png" format="png">
11080 </imageobject>
11081 </inlinemediaobject>
11082 </para>
11083
11084 </sect2>
11085
11086 <!-- ----------------------------------------------------------------- -->
11087 <sect2>
11088 <title>Choosing a parent class</title>
11089
11090 <para>The parent class for a composite widget is typically the container
11091 class that holds all of the elements of the composite widget. For
11092 example, the parent class of the FileSelection widget is the
11093 Dialog class. Since our buttons will be arranged in a table, it
11094 is natural to make our parent class the Table class.</para>
11095
11096 </sect2>
11097
11098 <!-- ----------------------------------------------------------------- -->
11099 <sect2>
11100 <title>The header file</title>
11101
11102 <para>Each GObject class has a header file which declares the object and
11103 class structures for that object, along with public functions. 
11104 A couple of features are worth pointing out. To prevent duplicate
11105 definitions, we wrap the entire header file in:</para>
11106
11107 <programlisting role="C">
11108 #ifndef __TICTACTOE_H__
11109 #define __TICTACTOE_H__
11110 .
11111 .
11112 .
11113 #endif /* __TICTACTOE_H__ */
11114 </programlisting>
11115
11116 <para>And to keep C++ programs that include the header file happy, in:</para>
11117
11118 <programlisting role="C">
11119 #include &lt;glib.h&gt;
11120
11121 G_BEGIN_DECLS
11122 .
11123 .
11124 .
11125 G_END_DECLS
11126 </programlisting>
11127
11128 <para>Along with the functions and structures, we declare five standard
11129 macros in our header file, <literal>TICTACTOE_TYPE</literal>,
11130 <literal>TICTACTOE(obj)</literal>,
11131 <literal>TICTACTOE_CLASS(klass)</literal>,
11132 <literal>IS_TICTACTOE(obj)</literal>, and
11133 <literal>IS_TICTACTOE_CLASS(klass)</literal>, which cast a
11134 pointer into a pointer to the object or class structure, and check
11135 if an object is a Tictactoe widget respectively.</para>
11136
11137 </sect2>
11138
11139 <!-- ----------------------------------------------------------------- -->
11140 <sect2>
11141 <title>The <literal>_get_type()</literal> function</title>
11142
11143 <para>We now continue on to the implementation of our widget. A core
11144 function for every object is the function
11145 <literal>WIDGETNAME_get_type()</literal>. This function, when first called, tells
11146 Glib about the new class, and gets an ID that uniquely identifies
11147 the class. Upon subsequent calls, it just returns the ID.</para>
11148
11149 <programlisting role="C">
11150 GType
11151 tictactoe_get_type (void)
11152 {
11153   static GType ttt_type = 0;
11154
11155   if (!ttt_type)
11156     {
11157       static const GTypeInfo ttt_info =
11158       {
11159         sizeof (TictactoeClass),
11160         NULL, /* base_init */
11161         NULL, /* base_finalize */
11162         (GClassInitFunc) tictactoe_class_init,
11163         NULL, /* class_finalize */
11164         NULL, /* class_data */
11165         sizeof (Tictactoe),
11166         0,    /* n_preallocs */
11167         (GInstanceInitFunc) tictactoe_init,
11168       };
11169
11170       ttt_type = g_type_register_static (GTK_TYPE_TABLE,
11171                                          "Tictactoe",
11172                                          &amp;ttt_info,
11173                                          0);
11174     }
11175
11176   return ttt_type;
11177 }
11178 </programlisting>
11179
11180 <para>The GTypeInfo structure has the following definition:</para>
11181
11182 <programlisting role="C">
11183 struct _GTypeInfo
11184 {
11185   /* interface types, classed types, instantiated types */
11186   guint16                class_size;
11187    
11188   GBaseInitFunc          base_init;
11189   GBaseFinalizeFunc      base_finalize;
11190    
11191   /* classed types, instantiated types */
11192   GClassInitFunc         class_init;
11193   GClassFinalizeFunc     class_finalize;
11194   gconstpointer          class_data;
11195    
11196   /* instantiated types */
11197   guint16                instance_size;
11198   guint16                n_preallocs;
11199   GInstanceInitFunc      instance_init;
11200    
11201   /* value handling */
11202   const GTypeValueTable *value_table;
11203 };
11204 </programlisting>
11205
11206 <para>The important fields of this structure are pretty self-explanatory.
11207 We'll ignore the <literal>base_init</literal> and
11208  <literal>base_finalize</literal> as well as the <literal>value_table</literal>
11209 fields here. Once Glib has a correctly filled in copy of
11210 this structure, it knows how to create objects of a particular type. </para>
11211
11212 </sect2>
11213
11214 <!-- ----------------------------------------------------------------- -->
11215 <sect2>
11216 <title>The <literal>_class_init()</literal> function</title>
11217
11218 <para>The <literal>WIDGETNAME_class_init()</literal> function initializes the fields of
11219 the widget's class structure, and sets up any signals for the
11220 class. For our Tictactoe widget it looks like:</para>
11221
11222 <programlisting role="C">
11223 enum {
11224   TICTACTOE_SIGNAL,
11225   LAST_SIGNAL
11226 };
11227
11228
11229 static guint tictactoe_signals[LAST_SIGNAL] = { 0 };
11230
11231 static void
11232 tictactoe_class_init (TictactoeClass *klass)
11233 {
11234   tictactoe_signals[TICTACTOE_SIGNAL] =
11235     g_signal_new ("tictactoe",
11236                   G_TYPE_FROM_CLASS (klass),
11237                   G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
11238                   G_STRUCT_OFFSET (TictactoeClass, tictactoe),
11239                   NULL, NULL,
11240                   g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
11241 }
11242 </programlisting>
11243
11244 <para>Our widget has just one signal, the <literal>tictactoe</literal> signal that is
11245 invoked when a row, column, or diagonal is completely filled in. Not
11246 every composite widget needs signals, so if you are reading this for
11247 the first time, you may want to skip to the next section now, as
11248 things are going to get a bit complicated.</para>
11249
11250 <para>The function:</para>
11251
11252 <programlisting role="C">
11253 guint g_signal_new( const gchar         *signal_name,
11254                     GType                itype,
11255                     GSignalFlags         signal_flags,
11256                     guint                class_offset,
11257                     GSignalAccumulator  *accumulator,
11258                     gpointer             accu_data,
11259                     GSignalCMarshaller  *c_marshaller,
11260                     GType                return_type,
11261                     guint                n_params,
11262                     ...);
11263 </programlisting>
11264
11265 <para>Creates a new signal. The parameters are:</para>
11266
11267 <itemizedlist>
11268 <listitem><simpara> <literal>signal_name</literal>: The name of the signal.</simpara>
11269 </listitem>
11270
11271 <listitem><simpara> <literal>itype</literal>: The ID of the object that this signal applies
11272 to. (It will also apply to that objects descendants.)</simpara>
11273 </listitem>
11274                                                                                 
11275 <listitem><simpara> <literal>signal_flags</literal>: Whether the default handler runs before or after
11276 user handlers and other flags. Usually this will be one of
11277 <literal>G_SIGNAL_RUN_FIRST</literal> or <literal>G_SIGNAL_RUN_LAST</literal>,
11278 although there are other possibilities. The flag
11279 <literal>G_SIGNAL_ACTION</literal> specifies that no extra code needs to
11280 run that performs special pre or post emission adjustments. This means that
11281 the signal can also be emitted from object external code.</simpara>
11282 </listitem>
11283
11284 <listitem><simpara> <literal>class_offset</literal>: The offset within the class structure of
11285 a pointer to the default handler.</simpara>
11286 </listitem>
11287
11288 <listitem><simpara> <literal>accumulator</literal>: For most classes this can
11289 be set to NULL.</simpara></listitem>
11290
11291 <listitem><simpara> <literal>accu_data</literal>: User data that will be handed
11292 to the accumulator function.</simpara></listitem>
11293
11294 <listitem><simpara> <literal>c_marshaller</literal>: A function that is used to invoke the signal
11295 handler. For signal handlers that have no arguments other than the
11296 object that emitted the signal and user data, we can use the
11297 pre-supplied marshaller function <literal>g_cclosure_marshal_VOID__VOID</literal>.</simpara>
11298 </listitem>
11299
11300 <listitem><simpara> <literal>return_type</literal>: The type of the return value.</simpara>
11301 </listitem>
11302
11303 <listitem><simpara> <literal>n_params</literal>: The number of parameters of the signal handler
11304 (other than the two default ones mentioned above)</simpara>
11305 </listitem>
11306
11307 <listitem><simpara> <literal>...</literal>: The types of the parameters.</simpara>
11308 </listitem>
11309 </itemizedlist>
11310
11311 <para>When specifying types, the following standard types can be used:</para>
11312
11313 <programlisting role="C">
11314 G_TYPE_INVALID
11315 G_TYPE_NONE
11316 G_TYPE_INTERFACE
11317 G_TYPE_CHAR
11318 G_TYPE_UCHAR
11319 G_TYPE_BOOLEAN
11320 G_TYPE_INT
11321 G_TYPE_UINT
11322 G_TYPE_LONG
11323 G_TYPE_ULONG
11324 G_TYPE_INT64
11325 G_TYPE_UINT64
11326 G_TYPE_ENUM
11327 G_TYPE_FLAGS
11328 G_TYPE_FLOAT
11329 G_TYPE_DOUBLE
11330 G_TYPE_STRING
11331 G_TYPE_POINTER
11332 G_TYPE_BOXED
11333 G_TYPE_PARAM
11334 G_TYPE_OBJECT
11335 </programlisting>
11336
11337 <para><literal>g_signal_new()</literal> returns a unique integer identifier for the
11338 signal, that we store in the <literal>tictactoe_signals</literal> array, which we
11339 index using an enumeration. (Conventionally, the enumeration elements
11340 are the signal name, uppercased, but here there would be a conflict
11341 with the <literal>TICTACTOE()</literal> macro, so we called it <literal>TICTACTOE_SIGNAL</literal>
11342 instead.</para>
11343
11344 </sect2>
11345
11346 <!-- ----------------------------------------------------------------- -->
11347 <sect2>
11348 <title>The <literal>_init()</literal> function</title>
11349
11350 <para>Each class also needs a function to initialize the object
11351 structure. Usually, this function has the fairly limited role of
11352 setting the fields of the structure to default values. For composite
11353 widgets, however, this function also creates the component widgets.</para>
11354
11355 <programlisting role="C">
11356 static void
11357 tictactoe_init (Tictactoe *ttt)
11358 {
11359   gint i,j;
11360
11361   gtk_table_resize (GTK_TABLE (ttt), 3, 3);
11362   gtk_table_set_homogeneous (GTK_TABLE (ttt), TRUE);
11363
11364   for (i=0;i&lt;3; i++)
11365     for (j=0;j&lt;3; j++)
11366       {
11367         ttt->buttons[i][j] = gtk_toggle_button_new ();
11368         gtk_table_attach_defaults (GTK_TABLE (ttt), ttt->buttons[i][j], 
11369                                    i, i+1, j, j+1);
11370         g_signal_connect (G_OBJECT (ttt->buttons[i][j]), "toggled",
11371                           G_CALLBACK (tictactoe_toggle), ttt);
11372         gtk_widget_set_size_request (ttt->buttons[i][j], 20, 20);
11373         gtk_widget_show (ttt->buttons[i][j]);
11374       }
11375 }
11376 </programlisting>
11377
11378 </sect2>
11379
11380 <!-- ----------------------------------------------------------------- -->
11381 <sect2>
11382 <title>And the rest...</title>
11383
11384 <para>There is one more function that every object (except for abstract
11385 classes like Bin that cannot be instantiated) needs to have - the
11386 function that the user calls to create an object of that type. This is
11387 conventionally called <literal>OBJECTNAME_new()</literal>. In some
11388 widgets, though not for the Tictactoe widgets, this function takes
11389 arguments, and does some setup based on the arguments. The other two
11390 functions are specific to the Tictactoe widget. </para>
11391
11392 <para><literal>tictactoe_clear()</literal> is a public function that resets all the
11393 buttons in the widget to the up position. Note the use of
11394 <literal>g_signal_handlers_block_matched()</literal> to keep our signal handler for
11395 button toggles from being triggered unnecessarily.</para>
11396
11397 <para><literal>tictactoe_toggle()</literal> is the signal handler that is invoked when the
11398 user clicks on a button. It checks to see if there are any winning
11399 combinations that involve the toggled button, and if so, emits
11400 the "tictactoe" signal.</para>
11401
11402 <programlisting role="C">
11403 GtkWidget*
11404 tictactoe_new (void)
11405 {
11406   return GTK_WIDGET ( g_object_new (TICTACTOE_TYPE, NULL));
11407 }
11408
11409 void           
11410 tictactoe_clear (Tictactoe *ttt)
11411 {
11412   int i,j;
11413
11414   for (i=0;i&lt;3;i++)
11415     for (j=0;j&lt;3;j++)
11416       {
11417         g_signal_handlers_block_matched (G_OBJECT (ttt->buttons[i][j]),
11418                                          G_SIGNAL_MATCH_DATA,
11419                                          0, 0, NULL, NULL, ttt);
11420         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
11421                                      FALSE);
11422         g_signal_handlers_unblock_matched (G_OBJECT (ttt->buttons[i][j]),
11423                                            G_SIGNAL_MATCH_DATA,
11424                                            0, 0, NULL, NULL, ttt);
11425       }
11426 }
11427
11428 static void
11429 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
11430 {
11431   int i,k;
11432
11433   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
11434                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
11435                              { 0, 1, 2 }, { 0, 1, 2 } };
11436   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
11437                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
11438                              { 0, 1, 2 }, { 2, 1, 0 } };
11439
11440   int success, found;
11441
11442   for (k=0; k&lt;8; k++)
11443     {
11444       success = TRUE;
11445       found = FALSE;
11446
11447       for (i=0;i&lt;3;i++)
11448         {
11449           success = success &amp;&amp; 
11450             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
11451           found = found ||
11452             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
11453         }
11454       
11455       if (success &amp;&amp; found)
11456         {
11457           g_signal_emit (G_OBJECT (ttt), 
11458                          tictactoe_signals[TICTACTOE_SIGNAL], 0);
11459           break;
11460         }
11461     }
11462 }
11463 </programlisting>
11464
11465 <para>And finally, an example program using our Tictactoe widget:</para>
11466
11467 <programlisting role="C">
11468 #include &lt;gtk/gtk.h&gt;
11469 #include "tictactoe.h"
11470
11471 /* Invoked when a row, column or diagonal is completed */
11472 void
11473 win (GtkWidget *widget, gpointer data)
11474 {
11475   g_print ("Yay!\n");
11476   tictactoe_clear (TICTACTOE (widget));
11477 }
11478
11479 int 
11480 main (int argc, char *argv[])
11481 {
11482   GtkWidget *window;
11483   GtkWidget *ttt;
11484   
11485   gtk_init (&amp;argc, &amp;argv);
11486
11487   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11488   
11489   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
11490   
11491   g_signal_connect (G_OBJECT (window), "destroy",
11492                     G_CALLBACK (exit), NULL);
11493   
11494   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11495
11496   /* Create a new Tictactoe widget */
11497   ttt = tictactoe_new ();
11498   gtk_container_add (GTK_CONTAINER (window), ttt);
11499   gtk_widget_show (ttt);
11500
11501   /* And attach to its "tictactoe" signal */
11502   g_signal_connect (G_OBJECT (ttt), "tictactoe",
11503                     G_CALLBACK (win), NULL);
11504
11505   gtk_widget_show (window);
11506   
11507   gtk_main ();
11508   
11509   return 0;
11510 }
11511 </programlisting>
11512
11513 </sect2>
11514 </sect1>
11515
11516 <!-- ----------------------------------------------------------------- -->
11517 <sect1 id="sec-CreatingAWidgetFromScratch">
11518 <title>Creating a widget from scratch</title>
11519
11520 <!-- ----------------------------------------------------------------- -->
11521 <sect2>
11522 <title>Introduction</title>
11523
11524 <para>In this section, we'll learn more about how widgets display themselves
11525 on the screen and interact with events. As an example of this, we'll
11526 create an analog dial widget with a pointer that the user can drag to
11527 set the value.</para>
11528
11529 <para>
11530 <inlinemediaobject>
11531 <imageobject>
11532 <imagedata fileref="images/gtkdial.png" format="png">
11533 </imageobject>
11534 </inlinemediaobject>
11535 </para>
11536
11537 </sect2>
11538
11539 <!-- ----------------------------------------------------------------- -->
11540 <sect2>
11541 <title>Displaying a widget on the screen</title>
11542
11543 <para>There are several steps that are involved in displaying on the screen.
11544 After the widget is created with a call to <literal>WIDGETNAME_new()</literal>,
11545 several more functions are needed:</para>
11546
11547 <itemizedlist>
11548 <listitem><simpara> <literal>WIDGETNAME_realize()</literal> is responsible for creating an X
11549 window for the widget if it has one.</simpara>
11550 </listitem>
11551 <listitem><simpara> <literal>WIDGETNAME_map()</literal> is invoked after the user calls
11552 <literal>gtk_widget_show()</literal>. It is responsible for making sure the widget
11553 is actually drawn on the screen (<emphasis>mapped</emphasis>). For a container class,
11554 it must also make calls to <literal>map()</literal> functions of any child widgets.</simpara>
11555 </listitem>
11556 <listitem><simpara> <literal>WIDGETNAME_draw()</literal> is invoked when <literal>gtk_widget_draw()</literal>
11557 is called for the widget or one of its ancestors. It makes the actual
11558 calls to the drawing functions to draw the widget on the screen. For
11559 container widgets, this function must make calls to
11560 <literal>gtk_widget_draw()</literal> for its child widgets.</simpara>
11561 </listitem>
11562 <listitem><simpara> <literal>WIDGETNAME_expose()</literal> is a handler for expose events for the
11563 widget. It makes the necessary calls to the drawing functions to draw
11564 the exposed portion on the screen. For container widgets, this
11565 function must generate expose events for its child widgets which don't
11566 have their own windows. (If they have their own windows, then X will
11567 generate the necessary expose events.)</simpara>
11568 </listitem>
11569 </itemizedlist>
11570
11571 <para>You might notice that the last two functions are quite similar - each
11572 is responsible for drawing the widget on the screen. In fact many
11573 types of widgets don't really care about the difference between the
11574 two. The default <literal>draw()</literal> function in the widget class simply
11575 generates a synthetic expose event for the redrawn area. However, some
11576 types of widgets can save work by distinguishing between the two
11577 functions. For instance, if a widget has multiple X windows, then
11578 since expose events identify the exposed window, it can redraw only
11579 the affected window, which is not possible for calls to <literal>draw()</literal>.</para>
11580
11581 <para>Container widgets, even if they don't care about the difference for
11582 themselves, can't simply use the default <literal>draw()</literal> function because
11583 their child widgets might care about the difference. However,
11584 it would be wasteful to duplicate the drawing code between the two
11585 functions. The convention is that such widgets have a function called
11586 <literal>WIDGETNAME_paint()</literal> that does the actual work of drawing the
11587 widget, that is then called by the <literal>draw()</literal> and <literal>expose()</literal>
11588 functions.</para>
11589
11590 <para>In our example approach, since the dial widget is not a container
11591 widget, and only has a single window, we can take the simplest
11592 approach and use the default <literal>draw()</literal> function and only implement
11593 an <literal>expose()</literal> function.</para>
11594
11595 </sect2>
11596
11597 <!-- ----------------------------------------------------------------- -->
11598 <sect2>
11599 <title>The origins of the Dial Widget</title>
11600
11601 <para>Just as all land animals are just variants on the first amphibian that
11602 crawled up out of the mud, GTK widgets tend to start off as variants
11603 of some other, previously written widget. Thus, although this section
11604 is entitled "Creating a Widget from Scratch", the Dial widget really
11605 began with the source code for the Range widget. This was picked as a
11606 starting point because it would be nice if our Dial had the same
11607 interface as the Scale widgets which are just specialized descendants
11608 of the Range widget. So, though the source code is presented below in
11609 finished form, it should not be implied that it was written, <emphasis>ab
11610 initio</emphasis> in this fashion. Also, if you aren't yet familiar with
11611 how scale widgets work from the application writer's point of view, it
11612 would be a good idea to look them over before continuing.</para>
11613
11614 </sect2>
11615
11616 <!-- ----------------------------------------------------------------- -->
11617 <sect2>
11618 <title>The Basics</title>
11619
11620 <para>Quite a bit of our widget should look pretty familiar from the
11621 Tictactoe widget. First, we have a header file:</para>
11622
11623 <programlisting role="C">
11624 /* GTK - The GIMP Toolkit
11625  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
11626  *
11627  * This library is free software; you can redistribute it and/or
11628  * modify it under the terms of the GNU Library General Public
11629  * License as published by the Free Software Foundation; either
11630  * version 2 of the License, or (at your option) any later version.
11631  *
11632  * This library is distributed in the hope that it will be useful,
11633  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11634  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11635  * Library General Public License for more details.
11636  *
11637  * You should have received a copy of the GNU Library General Public
11638  * License along with this library; if not, write to the Free
11639  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
11640  */
11641
11642 #ifndef __GTK_DIAL_H__
11643 #define __GTK_DIAL_H__
11644
11645 #include &lt;gdk/gdk.h&gt;
11646 #include &lt;gtk/gtkadjustment.h&gt;
11647 #include &lt;gtk/gtkwidget.h&gt;
11648
11649
11650 #ifdef __cplusplus
11651 extern "C" {
11652 #endif /* __cplusplus */
11653
11654
11655 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
11656 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
11657 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
11658
11659
11660 typedef struct _GtkDial        GtkDial;
11661 typedef struct _GtkDialClass   GtkDialClass;
11662
11663 struct _GtkDial
11664 {
11665   GtkWidget widget;
11666
11667   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
11668   guint policy : 2;
11669
11670   /* Button currently pressed or 0 if none */
11671   guint8 button;
11672
11673   /* Dimensions of dial components */
11674   gint radius;
11675   gint pointer_width;
11676
11677   /* ID of update timer, or 0 if none */
11678   guint32 timer;
11679
11680   /* Current angle */
11681   gfloat angle;
11682
11683   /* Old values from adjustment stored so we know when something changes */
11684   gfloat old_value;
11685   gfloat old_lower;
11686   gfloat old_upper;
11687
11688   /* The adjustment object that stores the data for this dial */
11689   GtkAdjustment *adjustment;
11690 };
11691
11692 struct _GtkDialClass
11693 {
11694   GtkWidgetClass parent_class;
11695 };
11696
11697
11698 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
11699 GtkType        gtk_dial_get_type               (void);
11700 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
11701 void           gtk_dial_set_update_policy      (GtkDial      *dial,
11702                                                 GtkUpdateType  policy);
11703
11704 void           gtk_dial_set_adjustment         (GtkDial      *dial,
11705                                                 GtkAdjustment *adjustment);
11706 #ifdef __cplusplus
11707 }
11708 #endif /* __cplusplus */
11709
11710
11711 #endif /* __GTK_DIAL_H__ */
11712 </programlisting>
11713
11714 <para>Since there is quite a bit more going on in this widget than the last
11715 one, we have more fields in the data structure, but otherwise things
11716 are pretty similar.</para>
11717
11718 <para>Next, after including header files and declaring a few constants,
11719 we have some functions to provide information about the widget
11720 and initialize it:</para>
11721
11722 <programlisting role="C">
11723 #include &lt;math.h&gt;
11724 #include &lt;stdio.h&gt;
11725 #include &lt;gtk/gtkmain.h&gt;
11726 #include &lt;gtk/gtksignal.h&gt;
11727
11728 #include "gtkdial.h"
11729
11730 #define SCROLL_DELAY_LENGTH  300
11731 #define DIAL_DEFAULT_SIZE 100
11732
11733 /* Forward declarations */
11734
11735 [ omitted to save space ]
11736
11737 /* Local data */
11738
11739 static GtkWidgetClass *parent_class = NULL;
11740
11741 GtkType
11742 gtk_dial_get_type ()
11743 {
11744   static GtkType dial_type = 0;
11745
11746   if (!dial_type)
11747     {
11748       static const GtkTypeInfo dial_info =
11749       {
11750         "GtkDial",
11751         sizeof (GtkDial),
11752         sizeof (GtkDialClass),
11753         (GtkClassInitFunc) gtk_dial_class_init,
11754         (GtkObjectInitFunc) gtk_dial_init,
11755         /* reserved_1 */ NULL,
11756         /* reserved_1 */ NULL,
11757         (GtkClassInitFunc) NULL
11758       };
11759
11760       dial_type = gtk_type_unique (GTK_TYPE_WIDGET, &amp;dial_info);
11761     }
11762
11763   return dial_type;
11764 }
11765
11766 static void
11767 gtk_dial_class_init (GtkDialClass *class)
11768 {
11769   GtkObjectClass *object_class;
11770   GtkWidgetClass *widget_class;
11771
11772   object_class = (GtkObjectClass*) class;
11773   widget_class = (GtkWidgetClass*) class;
11774
11775   parent_class = gtk_type_class (gtk_widget_get_type ());
11776
11777   object_class->destroy = gtk_dial_destroy;
11778
11779   widget_class->realize = gtk_dial_realize;
11780   widget_class->expose_event = gtk_dial_expose;
11781   widget_class->size_request = gtk_dial_size_request;
11782   widget_class->size_allocate = gtk_dial_size_allocate;
11783   widget_class->button_press_event = gtk_dial_button_press;
11784   widget_class->button_release_event = gtk_dial_button_release;
11785   widget_class->motion_notify_event = gtk_dial_motion_notify;
11786 }
11787
11788 static void
11789 gtk_dial_init (GtkDial *dial)
11790 {
11791   dial->button = 0;
11792   dial->policy = GTK_UPDATE_CONTINUOUS;
11793   dial->timer = 0;
11794   dial->radius = 0;
11795   dial->pointer_width = 0;
11796   dial->angle = 0.0;
11797   dial->old_value = 0.0;
11798   dial->old_lower = 0.0;
11799   dial->old_upper = 0.0;
11800   dial->adjustment = NULL;
11801 }
11802
11803 GtkWidget*
11804 gtk_dial_new (GtkAdjustment *adjustment)
11805 {
11806   GtkDial *dial;
11807
11808   dial = gtk_type_new (gtk_dial_get_type ());
11809
11810   if (!adjustment)
11811     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
11812
11813   gtk_dial_set_adjustment (dial, adjustment);
11814
11815   return GTK_WIDGET (dial);
11816 }
11817
11818 static void
11819 gtk_dial_destroy (GtkObject *object)
11820 {
11821   GtkDial *dial;
11822
11823   g_return_if_fail (object != NULL);
11824   g_return_if_fail (GTK_IS_DIAL (object));
11825
11826   dial = GTK_DIAL (object);
11827
11828   if (dial->adjustment)
11829     gtk_object_unref (GTK_OBJECT (dial->adjustment));
11830
11831   if (GTK_OBJECT_CLASS (parent_class)->destroy)
11832     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
11833 }
11834 </programlisting>
11835
11836 <para>Note that this <literal>init()</literal> function does less than for the Tictactoe
11837 widget, since this is not a composite widget, and the <literal>new()</literal>
11838 function does more, since it now has an argument. Also, note that when
11839 we store a pointer to the Adjustment object, we increment its
11840 reference count, (and correspondingly decrement it when we no longer
11841 use it) so that GTK can keep track of when it can be safely destroyed.</para>
11842
11843 <para>Also, there are a few function to manipulate the widget's options:</para>
11844
11845 <programlisting role="C">
11846 GtkAdjustment*
11847 gtk_dial_get_adjustment (GtkDial *dial)
11848 {
11849   g_return_val_if_fail (dial != NULL, NULL);
11850   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
11851
11852   return dial->adjustment;
11853 }
11854
11855 void
11856 gtk_dial_set_update_policy (GtkDial      *dial,
11857                              GtkUpdateType  policy)
11858 {
11859   g_return_if_fail (dial != NULL);
11860   g_return_if_fail (GTK_IS_DIAL (dial));
11861
11862   dial->policy = policy;
11863 }
11864
11865 void
11866 gtk_dial_set_adjustment (GtkDial      *dial,
11867                           GtkAdjustment *adjustment)
11868 {
11869   g_return_if_fail (dial != NULL);
11870   g_return_if_fail (GTK_IS_DIAL (dial));
11871
11872   if (dial->adjustment)
11873     {
11874       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
11875       gtk_object_unref (GTK_OBJECT (dial->adjustment));
11876     }
11877
11878   dial->adjustment = adjustment;
11879   gtk_object_ref (GTK_OBJECT (dial->adjustment));
11880
11881   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
11882                       (GtkSignalFunc) gtk_dial_adjustment_changed,
11883                       (gpointer) dial);
11884   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
11885                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
11886                       (gpointer) dial);
11887
11888   dial->old_value = adjustment->value;
11889   dial->old_lower = adjustment->lower;
11890   dial->old_upper = adjustment->upper;
11891
11892   gtk_dial_update (dial);
11893 }
11894 </programlisting>
11895
11896 </sect2>
11897
11898 <!-- ----------------------------------------------------------------- -->
11899 <sect2>
11900 <title><literal>gtk_dial_realize()</literal></title>
11901
11902 <para>Now we come to some new types of functions. First, we have a function
11903 that does the work of creating the X window. Notice that a mask is
11904 passed to the function <literal>gdk_window_new()</literal> which specifies which fields of
11905 the GdkWindowAttr structure actually have data in them (the remaining
11906 fields will be given default values). Also worth noting is the way the
11907 event mask of the widget is created. We call
11908 <literal>gtk_widget_get_events()</literal> to retrieve the event mask that the user
11909 has specified for this widget (with <literal>gtk_widget_set_events()</literal>), and
11910 add the events that we are interested in ourselves.</para>
11911
11912 <para>After creating the window, we set its style and background, and put a
11913 pointer to the widget in the user data field of the GdkWindow. This
11914 last step allows GTK to dispatch events for this window to the correct
11915 widget.</para>
11916
11917 <programlisting role="C">
11918 static void
11919 gtk_dial_realize (GtkWidget *widget)
11920 {
11921   GtkDial *dial;
11922   GdkWindowAttr attributes;
11923   gint attributes_mask;
11924
11925   g_return_if_fail (widget != NULL);
11926   g_return_if_fail (GTK_IS_DIAL (widget));
11927
11928   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
11929   dial = GTK_DIAL (widget);
11930
11931   attributes.x = widget->allocation.x;
11932   attributes.y = widget->allocation.y;
11933   attributes.width = widget->allocation.width;
11934   attributes.height = widget->allocation.height;
11935   attributes.wclass = GDK_INPUT_OUTPUT;
11936   attributes.window_type = GDK_WINDOW_CHILD;
11937   attributes.event_mask = gtk_widget_get_events (widget) | 
11938     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
11939     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
11940     GDK_POINTER_MOTION_HINT_MASK;
11941   attributes.visual = gtk_widget_get_visual (widget);
11942   attributes.colormap = gtk_widget_get_colormap (widget);
11943
11944   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
11945   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &amp;attributes, attributes_mask);
11946
11947   widget->style = gtk_style_attach (widget->style, widget->window);
11948
11949   gdk_window_set_user_data (widget->window, widget);
11950
11951   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
11952 }
11953 </programlisting>
11954
11955 </sect2>
11956
11957 <!-- ----------------------------------------------------------------- -->
11958 <sect2>
11959 <title>Size negotiation</title>
11960
11961 <para>Before the first time that the window containing a widget is
11962 displayed, and whenever the layout of the window changes, GTK asks
11963 each child widget for its desired size. This request is handled by the
11964 function <literal>gtk_dial_size_request()</literal>. Since our widget isn't a
11965 container widget, and has no real constraints on its size, we just
11966 return a reasonable default value.</para>
11967
11968 <programlisting role="C">
11969 static void 
11970 gtk_dial_size_request (GtkWidget      *widget,
11971                        GtkRequisition *requisition)
11972 {
11973   requisition->width = DIAL_DEFAULT_SIZE;
11974   requisition->height = DIAL_DEFAULT_SIZE;
11975 }
11976 </programlisting>
11977
11978 <para>After all the widgets have requested an ideal size, the layout of the
11979 window is computed and each child widget is notified of its actual
11980 size. Usually, this will be at least as large as the requested size,
11981 but if for instance the user has resized the window, it may
11982 occasionally be smaller than the requested size. The size notification
11983 is handled by the function <literal>gtk_dial_size_allocate()</literal>. Notice that
11984 as well as computing the sizes of some component pieces for future
11985 use, this routine also does the grunt work of moving the widget's X
11986 window into the new position and size.</para>
11987
11988 <programlisting role="C">
11989 static void
11990 gtk_dial_size_allocate (GtkWidget     *widget,
11991                         GtkAllocation *allocation)
11992 {
11993   GtkDial *dial;
11994
11995   g_return_if_fail (widget != NULL);
11996   g_return_if_fail (GTK_IS_DIAL (widget));
11997   g_return_if_fail (allocation != NULL);
11998
11999   widget->allocation = *allocation;
12000   if (GTK_WIDGET_REALIZED (widget))
12001     {
12002       dial = GTK_DIAL (widget);
12003
12004       gdk_window_move_resize (widget->window,
12005                               allocation->x, allocation->y,
12006                               allocation->width, allocation->height);
12007
12008       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
12009       dial->pointer_width = dial->radius / 5;
12010     }
12011 }
12012 </programlisting>
12013
12014 </sect2>
12015
12016 <!-- ----------------------------------------------------------------- -->
12017 <sect2>
12018 <title><literal>gtk_dial_expose()</literal></title>
12019
12020 <para>As mentioned above, all the drawing of this widget is done in the
12021 handler for expose events. There's not much to remark on here except
12022 the use of the function <literal>gtk_draw_polygon</literal> to draw the pointer with
12023 three dimensional shading according to the colors stored in the
12024 widget's style.</para>
12025
12026 <programlisting role="C">
12027 static gboolean
12028 gtk_dial_expose( GtkWidget      *widget,
12029                  GdkEventExpose *event )
12030 {
12031   GtkDial *dial;
12032   GdkPoint points[3];
12033   gdouble s,c;
12034   gdouble theta;
12035   gint xc, yc;
12036   gint tick_length;
12037   gint i;
12038
12039   g_return_val_if_fail (widget != NULL, FALSE);
12040   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12041   g_return_val_if_fail (event != NULL, FALSE);
12042
12043   if (event->count > 0)
12044     return FALSE;
12045   
12046   dial = GTK_DIAL (widget);
12047
12048   gdk_window_clear_area (widget->window,
12049                          0, 0,
12050                          widget->allocation.width,
12051                          widget->allocation.height);
12052
12053   xc = widget->allocation.width/2;
12054   yc = widget->allocation.height/2;
12055
12056   /* Draw ticks */
12057
12058   for (i=0; i<25; i++)
12059     {
12060       theta = (i*M_PI/18. - M_PI/6.);
12061       s = sin(theta);
12062       c = cos(theta);
12063
12064       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
12065       
12066       gdk_draw_line (widget->window,
12067                      widget->style->fg_gc[widget->state],
12068                      xc + c*(dial->radius - tick_length),
12069                      yc - s*(dial->radius - tick_length),
12070                      xc + c*dial->radius,
12071                      yc - s*dial->radius);
12072     }
12073
12074   /* Draw pointer */
12075
12076   s = sin(dial->angle);
12077   c = cos(dial->angle);
12078
12079
12080   points[0].x = xc + s*dial->pointer_width/2;
12081   points[0].y = yc + c*dial->pointer_width/2;
12082   points[1].x = xc + c*dial->radius;
12083   points[1].y = yc - s*dial->radius;
12084   points[2].x = xc - s*dial->pointer_width/2;
12085   points[2].y = yc - c*dial->pointer_width/2;
12086
12087   gtk_draw_polygon (widget->style,
12088                     widget->window,
12089                     GTK_STATE_NORMAL,
12090                     GTK_SHADOW_OUT,
12091                     points, 3,
12092                     TRUE);
12093   
12094   return FALSE;
12095 }
12096 </programlisting>
12097
12098 </sect2>
12099
12100 <!-- ----------------------------------------------------------------- -->
12101 <sect2>
12102 <title>Event handling</title>
12103
12104 <para>The rest of the widget's code handles various types of events, and
12105 isn't too different from what would be found in many GTK
12106 applications. Two types of events can occur - either the user can
12107 click on the widget with the mouse and drag to move the pointer, or
12108 the value of the Adjustment object can change due to some external
12109 circumstance.</para>
12110
12111 <para>When the user clicks on the widget, we check to see if the click was
12112 appropriately near the pointer, and if so, store the button that the
12113 user clicked with in the <literal>button</literal> field of the widget
12114 structure, and grab all mouse events with a call to
12115 <literal>gtk_grab_add()</literal>. Subsequent motion of the mouse causes the
12116 value of the control to be recomputed (by the function
12117 <literal>gtk_dial_update_mouse</literal>). Depending on the policy that has been
12118 set, "value_changed" events are either generated instantly
12119 (<literal>GTK_UPDATE_CONTINUOUS</literal>), after a delay in a timer added with
12120 <literal>g_timeout_add()</literal> (<literal>GTK_UPDATE_DELAYED</literal>), or only when the
12121 button is released (<literal>GTK_UPDATE_DISCONTINUOUS</literal>).</para>
12122
12123 <programlisting role="C">
12124 static gboolean
12125 gtk_dial_button_press( GtkWidget      *widget,
12126                        GdkEventButton *event )
12127 {
12128   GtkDial *dial;
12129   gint dx, dy;
12130   double s, c;
12131   double d_parallel;
12132   double d_perpendicular;
12133
12134   g_return_val_if_fail (widget != NULL, FALSE);
12135   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12136   g_return_val_if_fail (event != NULL, FALSE);
12137
12138   dial = GTK_DIAL (widget);
12139
12140   /* Determine if button press was within pointer region - we 
12141      do this by computing the parallel and perpendicular distance of
12142      the point where the mouse was pressed from the line passing through
12143      the pointer */
12144   
12145   dx = event->x - widget->allocation.width / 2;
12146   dy = widget->allocation.height / 2 - event->y;
12147   
12148   s = sin(dial->angle);
12149   c = cos(dial->angle);
12150   
12151   d_parallel = s*dy + c*dx;
12152   d_perpendicular = fabs(s*dx - c*dy);
12153   
12154   if (!dial->button &&
12155       (d_perpendicular < dial->pointer_width/2) &&
12156       (d_parallel > - dial->pointer_width))
12157     {
12158       gtk_grab_add (widget);
12159
12160       dial->button = event->button;
12161
12162       gtk_dial_update_mouse (dial, event->x, event->y);
12163     }
12164
12165   return FALSE;
12166 }
12167
12168 static gboolean
12169 gtk_dial_button_release( GtkWidget      *widget,
12170                          GdkEventButton *event )
12171 {
12172   GtkDial *dial;
12173
12174   g_return_val_if_fail (widget != NULL, FALSE);
12175   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12176   g_return_val_if_fail (event != NULL, FALSE);
12177
12178   dial = GTK_DIAL (widget);
12179
12180   if (dial->button == event->button)
12181     {
12182       gtk_grab_remove (widget);
12183
12184       dial->button = 0;
12185
12186       if (dial->policy == GTK_UPDATE_DELAYED)
12187         g_source_remove (dial->timer);
12188       
12189       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
12190           (dial->old_value != dial->adjustment->value))
12191         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12192     }
12193
12194   return FALSE;
12195 }
12196
12197 static gboolean
12198 gtk_dial_motion_notify( GtkWidget      *widget,
12199                         GdkEventMotion *event )
12200 {
12201   GtkDial *dial;
12202   GdkModifierType mods;
12203   gint x, y, mask;
12204
12205   g_return_val_if_fail (widget != NULL, FALSE);
12206   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12207   g_return_val_if_fail (event != NULL, FALSE);
12208
12209   dial = GTK_DIAL (widget);
12210
12211   if (dial->button != 0)
12212     {
12213       x = event->x;
12214       y = event->y;
12215
12216       if (event->is_hint || (event->window != widget->window))
12217         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
12218
12219       switch (dial->button)
12220         {
12221         case 1:
12222           mask = GDK_BUTTON1_MASK;
12223           break;
12224         case 2:
12225           mask = GDK_BUTTON2_MASK;
12226           break;
12227         case 3:
12228           mask = GDK_BUTTON3_MASK;
12229           break;
12230         default:
12231           mask = 0;
12232           break;
12233         }
12234
12235       if (mods & mask)
12236         gtk_dial_update_mouse (dial, x,y);
12237     }
12238
12239   return FALSE;
12240 }
12241
12242 static gboolean
12243 gtk_dial_timer( GtkDial *dial )
12244 {
12245   g_return_val_if_fail (dial != NULL, FALSE);
12246   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
12247
12248   if (dial->policy == GTK_UPDATE_DELAYED)
12249     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12250
12251   return FALSE;
12252 }
12253
12254 static void
12255 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
12256 {
12257   gint xc, yc;
12258   gfloat old_value;
12259
12260   g_return_if_fail (dial != NULL);
12261   g_return_if_fail (GTK_IS_DIAL (dial));
12262
12263   xc = GTK_WIDGET(dial)->allocation.width / 2;
12264   yc = GTK_WIDGET(dial)->allocation.height / 2;
12265
12266   old_value = dial->adjustment->value;
12267   dial->angle = atan2(yc-y, x-xc);
12268
12269   if (dial->angle < -M_PI/2.)
12270     dial->angle += 2*M_PI;
12271
12272   if (dial->angle < -M_PI/6)
12273     dial->angle = -M_PI/6;
12274
12275   if (dial->angle > 7.*M_PI/6.)
12276     dial->angle = 7.*M_PI/6.;
12277
12278   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
12279     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
12280
12281   if (dial->adjustment->value != old_value)
12282     {
12283       if (dial->policy == GTK_UPDATE_CONTINUOUS)
12284         {
12285           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12286         }
12287       else
12288         {
12289           gtk_widget_draw (GTK_WIDGET(dial), NULL);
12290
12291           if (dial->policy == GTK_UPDATE_DELAYED)
12292             {
12293               if (dial->timer)
12294                 g_source_remove (dial->timer);
12295
12296               dial->timer = g_timeout_add (SCROLL_DELAY_LENGTH,
12297                                            (GtkFunction) gtk_dial_timer,
12298                                            (gpointer) dial);
12299             }
12300         }
12301     }
12302 }
12303 </programlisting>
12304
12305 <para>Changes to the Adjustment by external means are communicated to our
12306 widget by the "changed" and "value_changed" signals. The handlers
12307 for these functions call <literal>gtk_dial_update()</literal> to validate the
12308 arguments, compute the new pointer angle, and redraw the widget (by
12309 calling <literal>gtk_widget_draw()</literal>).</para>
12310
12311 <programlisting role="C">
12312 static void
12313 gtk_dial_update (GtkDial *dial)
12314 {
12315   gfloat new_value;
12316   
12317   g_return_if_fail (dial != NULL);
12318   g_return_if_fail (GTK_IS_DIAL (dial));
12319
12320   new_value = dial->adjustment->value;
12321   
12322   if (new_value < dial->adjustment->lower)
12323     new_value = dial->adjustment->lower;
12324
12325   if (new_value > dial->adjustment->upper)
12326     new_value = dial->adjustment->upper;
12327
12328   if (new_value != dial->adjustment->value)
12329     {
12330       dial->adjustment->value = new_value;
12331       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12332     }
12333
12334   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
12335     (dial->adjustment->upper - dial->adjustment->lower);
12336
12337   gtk_widget_draw (GTK_WIDGET(dial), NULL);
12338 }
12339
12340 static void
12341 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
12342                               gpointer       data)
12343 {
12344   GtkDial *dial;
12345
12346   g_return_if_fail (adjustment != NULL);
12347   g_return_if_fail (data != NULL);
12348
12349   dial = GTK_DIAL (data);
12350
12351   if ((dial->old_value != adjustment->value) ||
12352       (dial->old_lower != adjustment->lower) ||
12353       (dial->old_upper != adjustment->upper))
12354     {
12355       gtk_dial_update (dial);
12356
12357       dial->old_value = adjustment->value;
12358       dial->old_lower = adjustment->lower;
12359       dial->old_upper = adjustment->upper;
12360     }
12361 }
12362
12363 static void
12364 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
12365                                     gpointer       data)
12366 {
12367   GtkDial *dial;
12368
12369   g_return_if_fail (adjustment != NULL);
12370   g_return_if_fail (data != NULL);
12371
12372   dial = GTK_DIAL (data);
12373
12374   if (dial->old_value != adjustment->value)
12375     {
12376       gtk_dial_update (dial);
12377
12378       dial->old_value = adjustment->value;
12379     }
12380 }
12381 </programlisting>
12382
12383 </sect2>
12384
12385 <!-- ----------------------------------------------------------------- -->
12386 <sect2>
12387 <title>Possible Enhancements</title>
12388
12389 <para>The Dial widget as we've described it so far runs about 670 lines of
12390 code. Although that might sound like a fair bit, we've really
12391 accomplished quite a bit with that much code, especially since much of
12392 that length is headers and boilerplate. However, there are quite a few
12393 more enhancements that could be made to this widget:</para>
12394
12395 <itemizedlist>
12396 <listitem><simpara> If you try this widget out, you'll find that there is some
12397 flashing as the pointer is dragged around. This is because the entire
12398 widget is erased every time the pointer is moved before being
12399 redrawn. Often, the best way to handle this problem is to draw to an
12400 offscreen pixmap, then copy the final results onto the screen in one
12401 step. (The ProgressBar widget draws itself in this fashion.)</simpara>
12402 </listitem>
12403
12404 <listitem><simpara> The user should be able to use the up and down arrow keys to
12405 increase and decrease the value.</simpara>
12406 </listitem>
12407
12408 <listitem><simpara> It would be nice if the widget had buttons to increase and
12409 decrease the value in small or large steps. Although it would be
12410 possible to use embedded Button widgets for this, we would also like
12411 the buttons to auto-repeat when held down, as the arrows on a
12412 scrollbar do. Most of the code to implement this type of behavior can
12413 be found in the Range widget.</simpara>
12414 </listitem>
12415
12416 <listitem><simpara> The Dial widget could be made into a container widget with a
12417 single child widget positioned at the bottom between the buttons
12418 mentioned above. The user could then add their choice of a label or
12419 entry widget to display the current value of the dial.</simpara>
12420 </listitem>
12421 </itemizedlist>
12422
12423 </sect2>
12424 </sect1>
12425
12426 <!-- ----------------------------------------------------------------- -->
12427 <sect1 id="sec-LearningMore">
12428 <title>Learning More</title>
12429
12430 <para>Only a small part of the many details involved in creating widgets
12431 could be described above. If you want to write your own widgets, the
12432 best source of examples is the GTK source itself. Ask yourself some
12433 questions about the widget you want to write: IS it a Container
12434 widget? Does it have its own window? Is it a modification of an
12435 existing widget? Then find a similar widget, and start making changes.
12436 Good luck!</para>
12437
12438 </sect1>
12439 </chapter>
12440
12441 <!-- ***************************************************************** -->
12442 <chapter id="ch-Scribble">
12443 <title>Scribble, A Simple Example Drawing Program</title>
12444
12445 <!-- ----------------------------------------------------------------- -->
12446 <sect1 id="sec-ScribbleOverview">
12447 <title>Overview</title>
12448
12449 <para>In this section, we will build a simple drawing program. In the
12450 process, we will examine how to handle mouse events, how to draw in a
12451 window, and how to do drawing better by using a backing pixmap. After
12452 creating the simple drawing program, we will extend it by adding
12453 support for XInput devices, such as drawing tablets. GTK provides
12454 support routines which makes getting extended information, such as
12455 pressure and tilt, from such devices quite easy.</para>
12456
12457 <para>
12458 <inlinemediaobject>
12459 <imageobject>
12460 <imagedata fileref="images/scribble.png" format="png">
12461 </imageobject>
12462 </inlinemediaobject>
12463 </para>
12464
12465 </sect1>
12466
12467 <!-- ----------------------------------------------------------------- -->
12468 <sect1 id="sec-EventHandling">
12469 <title>Event Handling</title>
12470
12471 <para>The GTK signals we have already discussed are for high-level actions,
12472 such as a menu item being selected. However, sometimes it is useful to
12473 learn about lower-level occurrences, such as the mouse being moved, or
12474 a key being pressed. There are also GTK signals corresponding to these
12475 low-level <emphasis>events</emphasis>. The handlers for these signals have an
12476 extra parameter which is a pointer to a structure containing
12477 information about the event. For instance, motion event handlers are
12478 passed a pointer to a GdkEventMotion structure which looks (in part)
12479 like:</para>
12480
12481 <programlisting role="C">
12482 struct _GdkEventMotion
12483 {
12484   GdkEventType type;
12485   GdkWindow *window;
12486   guint32 time;
12487   gdouble x;
12488   gdouble y;
12489   ...
12490   guint state;
12491   ...
12492 };
12493 </programlisting>
12494
12495 <para><literal>type</literal> will be set to the event type, in this case
12496 <literal>GDK_MOTION_NOTIFY</literal>, window is the window in which the event
12497 occurred. <literal>x</literal> and <literal>y</literal> give the coordinates of the event.
12498 <literal>state</literal> specifies the modifier state when the event
12499 occurred (that is, it specifies which modifier keys and mouse buttons
12500 were pressed). It is the bitwise OR of some of the following:</para>
12501
12502 <programlisting role="C">
12503 GDK_SHIFT_MASK  
12504 GDK_LOCK_MASK   
12505 GDK_CONTROL_MASK
12506 GDK_MOD1_MASK   
12507 GDK_MOD2_MASK   
12508 GDK_MOD3_MASK   
12509 GDK_MOD4_MASK   
12510 GDK_MOD5_MASK   
12511 GDK_BUTTON1_MASK
12512 GDK_BUTTON2_MASK
12513 GDK_BUTTON3_MASK
12514 GDK_BUTTON4_MASK
12515 GDK_BUTTON5_MASK
12516 </programlisting>
12517
12518 <para>As for other signals, to determine what happens when an event occurs
12519 we call <literal>gtk_signal_connect()</literal>. But we also need let GTK
12520 know which events we want to be notified about. To do this, we call
12521 the function:</para>
12522
12523 <programlisting role="C">
12524 void gtk_widget_set_events (GtkWidget *widget,
12525                             gint      events);
12526 </programlisting>
12527
12528 <para>The second field specifies the events we are interested in. It
12529 is the bitwise OR of constants that specify different types
12530 of events. For future reference the event types are:</para>
12531
12532 <programlisting role="C">
12533 GDK_EXPOSURE_MASK
12534 GDK_POINTER_MOTION_MASK
12535 GDK_POINTER_MOTION_HINT_MASK
12536 GDK_BUTTON_MOTION_MASK     
12537 GDK_BUTTON1_MOTION_MASK    
12538 GDK_BUTTON2_MOTION_MASK    
12539 GDK_BUTTON3_MOTION_MASK    
12540 GDK_BUTTON_PRESS_MASK      
12541 GDK_BUTTON_RELEASE_MASK    
12542 GDK_KEY_PRESS_MASK         
12543 GDK_KEY_RELEASE_MASK       
12544 GDK_ENTER_NOTIFY_MASK      
12545 GDK_LEAVE_NOTIFY_MASK      
12546 GDK_FOCUS_CHANGE_MASK      
12547 GDK_STRUCTURE_MASK         
12548 GDK_PROPERTY_CHANGE_MASK   
12549 GDK_PROXIMITY_IN_MASK      
12550 GDK_PROXIMITY_OUT_MASK     
12551 </programlisting>
12552
12553 <para>There are a few subtle points that have to be observed when calling
12554 <literal>gtk_widget_set_events()</literal>. First, it must be called before the X window
12555 for a GTK widget is created. In practical terms, this means you
12556 should call it immediately after creating the widget. Second, the
12557 widget must have an associated X window. For efficiency, many widget
12558 types do not have their own window, but draw in their parent's window.
12559 These widgets are:</para>
12560
12561 <programlisting role="C">
12562 GtkAlignment
12563 GtkArrow
12564 GtkBin
12565 GtkBox
12566 GtkImage
12567 GtkItem
12568 GtkLabel
12569 GtkPixmap
12570 GtkScrolledWindow
12571 GtkSeparator
12572 GtkTable
12573 GtkAspectFrame
12574 GtkFrame
12575 GtkVBox
12576 GtkHBox
12577 GtkVSeparator
12578 GtkHSeparator
12579 </programlisting>
12580
12581 <para>To capture events for these widgets, you need to use an EventBox
12582 widget. See the section on the <link linkend="sec-EventBox">EventBox</link> widget for details.</para>
12583
12584 <para>For our drawing program, we want to know when the mouse button is
12585 pressed and when the mouse is moved, so we specify
12586 <literal>GDK_POINTER_MOTION_MASK</literal> and <literal>GDK_BUTTON_PRESS_MASK</literal>. We also
12587 want to know when we need to redraw our window, so we specify
12588 <literal>GDK_EXPOSURE_MASK</literal>. Although we want to be notified via a
12589 Configure event when our window size changes, we don't have to specify
12590 the corresponding <literal>GDK_STRUCTURE_MASK</literal> flag, because it is
12591 automatically specified for all windows.</para>
12592
12593 <para>It turns out, however, that there is a problem with just specifying
12594 <literal>GDK_POINTER_MOTION_MASK</literal>. This will cause the server to add a new
12595 motion event to the event queue every time the user moves the mouse.
12596 Imagine that it takes us 0.1 seconds to handle a motion event, but the
12597 X server queues a new motion event every 0.05 seconds. We will soon
12598 get way behind the users drawing. If the user draws for 5 seconds,
12599 it will take us another 5 seconds to catch up after they release 
12600 the mouse button! What we would like is to only get one motion
12601 event for each event we process. The way to do this is to 
12602 specify <literal>GDK_POINTER_MOTION_HINT_MASK</literal>. </para>
12603
12604 <para>When we specify <literal>GDK_POINTER_MOTION_HINT_MASK</literal>, the server sends
12605 us a motion event the first time the pointer moves after entering
12606 our window, or after a button press or release event. Subsequent 
12607 motion events will be suppressed until we explicitly ask for
12608 the position of the pointer using the function:</para>
12609
12610 <programlisting role="C">
12611 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
12612                                           gint            *x,
12613                                           gint            *y,
12614                                           GdkModifierType *mask);
12615 </programlisting>
12616
12617 <para>(There is another function, <literal>gtk_widget_get_pointer()</literal> which
12618 has a simpler interface, but turns out not to be very useful, since
12619 it only retrieves the position of the mouse, not whether the buttons
12620 are pressed.)</para>
12621
12622 <para>The code to set the events for our window then looks like:</para>
12623
12624 <programlisting role="C">
12625   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
12626                       (GtkSignalFunc) expose_event, NULL);
12627   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
12628                       (GtkSignalFunc) configure_event, NULL);
12629   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
12630                       (GtkSignalFunc) motion_notify_event, NULL);
12631   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
12632                       (GtkSignalFunc) button_press_event, NULL);
12633
12634   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
12635                          | GDK_LEAVE_NOTIFY_MASK
12636                          | GDK_BUTTON_PRESS_MASK
12637                          | GDK_POINTER_MOTION_MASK
12638                          | GDK_POINTER_MOTION_HINT_MASK);
12639 </programlisting>
12640
12641 <para>We'll save the "expose_event" and "configure_event" handlers for
12642 later. The "motion_notify_event" and "button_press_event" handlers
12643 are pretty simple:</para>
12644
12645 <programlisting role="C">
12646 static gboolean
12647 button_press_event( GtkWidget *widget, GdkEventButton *event )
12648 {
12649   if (event->button == 1 &amp;&amp; pixmap != NULL)
12650       draw_brush (widget, event->x, event->y);
12651
12652   return TRUE;
12653 }
12654
12655 static gboolean
12656 motion_notify_event( GtkWidget *widget, GdkEventMotion *event )
12657 {
12658   int x, y;
12659   GdkModifierType state;
12660
12661   if (event->is_hint)
12662     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
12663   else
12664     {
12665       x = event->x;
12666       y = event->y;
12667       state = event->state;
12668     }
12669     
12670   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
12671     draw_brush (widget, x, y);
12672   
12673   return TRUE;
12674 }
12675 </programlisting>
12676
12677 </sect1>
12678
12679 <!-- ----------------------------------------------------------------- -->
12680 <sect1 id="sec-TheDrawingAreaWidget">
12681 <title>The DrawingArea Widget, And Drawing</title>
12682
12683 <para>We now turn to the process of drawing on the screen. The 
12684 widget we use for this is the DrawingArea widget. A drawing area
12685 widget is essentially an X window and nothing more. It is a blank
12686 canvas in which we can draw whatever we like. A drawing area
12687 is created using the call:</para>
12688
12689 <programlisting role="C">
12690 GtkWidget* gtk_drawing_area_new        (void);
12691 </programlisting>
12692
12693 <para>A default size for the widget can be specified by calling:</para>
12694
12695 <programlisting role="C">
12696 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
12697                                         gint                 width,
12698                                         gint                 height);
12699 </programlisting>
12700
12701 <para>This default size can be overridden, as is true for all widgets,
12702 by calling <literal>gtk_widget_set_size_request()</literal>, and that, in turn, can
12703 be overridden if the user manually resizes the the window containing
12704 the drawing area.</para>
12705
12706 <para>It should be noted that when we create a DrawingArea widget, we are
12707 <emphasis>completely</emphasis> responsible for drawing the contents. If our
12708 window is obscured then uncovered, we get an exposure event and must
12709 redraw what was previously hidden.</para>
12710
12711 <para>Having to remember everything that was drawn on the screen so we
12712 can properly redraw it can, to say the least, be a nuisance. In
12713 addition, it can be visually distracting if portions of the
12714 window are cleared, then redrawn step by step. The solution to
12715 this problem is to use an offscreen <emphasis>backing pixmap</emphasis>.
12716 Instead of drawing directly to the screen, we draw to an image
12717 stored in server memory but not displayed, then when the image
12718 changes or new portions of the image are displayed, we copy the
12719 relevant portions onto the screen.</para>
12720
12721 <para>To create an offscreen pixmap, we call the function:</para>
12722
12723 <programlisting role="C">
12724 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
12725                                          gint        width,
12726                                          gint        height,
12727                                          gint        depth);
12728 </programlisting>
12729
12730 <para>The <literal>window</literal> parameter specifies a GDK window that this pixmap
12731 takes some of its properties from. <literal>width</literal> and <literal>height</literal>
12732 specify the size of the pixmap. <literal>depth</literal> specifies the <emphasis>color
12733 depth</emphasis>, that is the number of bits per pixel, for the new window.
12734 If the depth is specified as <literal>-1</literal>, it will match the depth
12735 of <literal>window</literal>.</para>
12736
12737 <para>We create the pixmap in our "configure_event" handler. This event
12738 is generated whenever the window changes size, including when it
12739 is originally created.</para>
12740
12741 <programlisting role="C">
12742 /* Backing pixmap for drawing area */
12743 static GdkPixmap *pixmap = NULL;
12744
12745 /* Create a new backing pixmap of the appropriate size */
12746 static gboolean
12747 configure_event( GtkWidget *widget, GdkEventConfigure *event )
12748 {
12749   if (pixmap)
12750     g_object_unref(pixmap);
12751
12752   pixmap = gdk_pixmap_new(widget->window,
12753                           widget->allocation.width,
12754                           widget->allocation.height,
12755                           -1);
12756   gdk_draw_rectangle (pixmap,
12757                       widget->style->white_gc,
12758                       TRUE,
12759                       0, 0,
12760                       widget->allocation.width,
12761                       widget->allocation.height);
12762
12763   return TRUE;
12764 }
12765 </programlisting>
12766
12767 <para>The call to <literal>gdk_draw_rectangle()</literal> clears the pixmap
12768 initially to white. We'll say more about that in a moment.</para>
12769
12770 <para>Our exposure event handler then simply copies the relevant portion
12771 of the pixmap onto the screen (we determine the area we need
12772 to redraw by using the event->area field of the exposure event):</para>
12773
12774 <programlisting role="C">
12775 /* Redraw the screen from the backing pixmap */
12776 static gboolean
12777 expose_event( GtkWidget *widget, GdkEventExpose *event )
12778 {
12779   gdk_draw_drawable(widget->window,
12780                     widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
12781                     pixmap,
12782                     event->area.x, event->area.y,
12783                     event->area.x, event->area.y,
12784                     event->area.width, event->area.height);
12785
12786   return FALSE;
12787 }
12788 </programlisting>
12789
12790 <para>We've now seen how to keep the screen up to date with our pixmap, but
12791 how do we actually draw interesting stuff on our pixmap?  There are a
12792 large number of calls in GTK's GDK library for drawing on
12793 <emphasis>drawables</emphasis>. A drawable is simply something that can be drawn
12794 upon. It can be a window, a pixmap, or a bitmap (a black and white
12795 image).  We've already seen two such calls above,
12796 <literal>gdk_draw_rectangle()</literal> and <literal>gdk_draw_drawable()</literal>. The
12797 complete list is:</para>
12798
12799 <programlisting role="C">
12800 gdk_draw_point ()
12801 gdk_draw_line ()
12802 gdk_draw_rectangle ()
12803 gdk_draw_arc ()
12804 gdk_draw_polygon ()
12805 gdk_draw_pixmap ()
12806 gdk_draw_bitmap ()
12807 gdk_draw_image ()
12808 gdk_draw_points ()
12809 gdk_draw_segments ()
12810 gdk_draw_lines ()
12811 gdk_draw_pixbuf ()
12812 gdk_draw_glyphs ()
12813 gdk_draw_layout_line ()
12814 gdk_draw_layout ()
12815 gdk_draw_layout_line_with_colors ()
12816 gdk_draw_layout_with_colors ()
12817 gdk_draw_glyphs_transformed ()
12818 gdk_draw_glyphs_trapezoids ()
12819 </programlisting>
12820
12821 <para>See the reference documentation or the header file
12822 <literal>&lt;gdk/gdkdrawable.h&gt;</literal> for further details on these functions.
12823 These functions all share the same first two arguments. The first
12824 argument is the drawable to draw upon, the second argument is a
12825 <emphasis>graphics context</emphasis> (GC).</para>
12826
12827 <para>A graphics context encapsulates information about things such as
12828 foreground and background color and line width. GDK has a full set of
12829 functions for creating and modifying graphics contexts, but to keep
12830 things simple we'll just use predefined graphics contexts. Each widget
12831 has an associated style. (Which can be modified in a gtkrc file, see
12832 the section GTK's rc file.) This, among other things, stores a number
12833 of graphics contexts. Some examples of accessing these graphics
12834 contexts are:</para>
12835
12836 <programlisting role="C">
12837 widget->style->white_gc
12838 widget->style->black_gc
12839 widget->style->fg_gc[GTK_STATE_NORMAL]
12840 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
12841 </programlisting>
12842
12843 <para>The fields <literal>fg_gc</literal>, <literal>bg_gc</literal>, <literal>dark_gc</literal>, and
12844 <literal>light_gc</literal> are indexed by a parameter of type
12845 <literal>GtkStateType</literal> which can take on the values:</para>
12846
12847 <programlisting role="C">
12848 GTK_STATE_NORMAL,
12849 GTK_STATE_ACTIVE,
12850 GTK_STATE_PRELIGHT,
12851 GTK_STATE_SELECTED,
12852 GTK_STATE_INSENSITIVE
12853 </programlisting>
12854
12855 <para>For instance, for <literal>GTK_STATE_SELECTED</literal> the default foreground
12856 color is white and the default background color, dark blue.</para>
12857
12858 <para>Our function <literal>draw_brush()</literal>, which does the actual drawing
12859 on the screen, is then:</para>
12860
12861 <programlisting role="C">
12862 /* Draw a rectangle on the screen */
12863 static void
12864 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
12865 {
12866   GdkRectangle update_rect;
12867
12868   update_rect.x = x - 5;
12869   update_rect.y = y - 5;
12870   update_rect.width = 10;
12871   update_rect.height = 10;
12872   gdk_draw_rectangle (pixmap,
12873                       widget->style->black_gc,
12874                       TRUE,
12875                       update_rect.x, update_rect.y,
12876                       update_rect.width, update_rect.height);
12877   gtk_widget_queue_draw_area (widget,                 
12878                               update_rect.x, update_rect.y,
12879                               update_rect.width, update_rect.height);
12880 }
12881 </programlisting>
12882
12883 <para>After we draw the rectangle representing the brush onto the pixmap,
12884 we call the function:</para>
12885
12886 <programlisting role="C">
12887 void       gtk_widget_queue_draw_area (GtkWidget           *widget,
12888                                        gint                 x,
12889                                        gint                 y,
12890                                        gint                 width,
12891                                        gint                 height)
12892 </programlisting>
12893
12894 <para>which notifies X that the area given by the <literal>x</literal>, 
12895 <literal>y</literal>, <literal>width</literal> and <literal>height</literal> parameters
12896 needs to be updated. X will eventually generate an expose event
12897 (possibly combining the areas passed in several calls to
12898 <literal>gtk_widget_queue_draw_area()</literal>) which will cause our expose event handler
12899 to copy the relevant portions to the screen.</para>
12900
12901 <para>We have now covered the entire drawing program except for a few
12902 mundane details like creating the main window.</para>
12903
12904 </sect1>
12905
12906 <!-- ----------------------------------------------------------------- -->
12907 <sect1 id="sec-AddingXInputSupport">
12908 <title>Adding XInput support</title>
12909
12910 <para>It is now possible to buy quite inexpensive input devices such 
12911 as drawing tablets, which allow drawing with a much greater
12912 ease of artistic expression than does a mouse. The simplest way
12913 to use such devices is simply as a replacement for the mouse,
12914 but that misses out many of the advantages of these devices,
12915 such as:</para>
12916
12917 <itemizedlist>
12918 <listitem><simpara> Pressure sensitivity</simpara>
12919 </listitem>
12920 <listitem><simpara> Tilt reporting</simpara>
12921 </listitem>
12922 <listitem><simpara> Sub-pixel positioning</simpara>
12923 </listitem>
12924 <listitem><simpara> Multiple inputs (for example, a stylus with a point and eraser)</simpara>
12925 </listitem>
12926 </itemizedlist>
12927
12928 <para>For information about the XInput extension, see the <ulink
12929 url="http://www.gtk.org/~otaylor/xinput/howto/index.html">XInput HOWTO</ulink>.</para>
12930
12931 <para>If we examine the full definition of, for example, the GdkEventMotion
12932 structure, we see that it has fields to support extended device
12933 information.</para>
12934
12935 <programlisting role="C">
12936 struct _GdkEventMotion
12937 {
12938   GdkEventType type;
12939   GdkWindow *window;
12940   guint32 time;
12941   gdouble x;
12942   gdouble y;
12943   gdouble pressure;
12944   gdouble xtilt;
12945   gdouble ytilt;
12946   guint state;
12947   gint16 is_hint;
12948   GdkInputSource source;
12949   guint32 deviceid;
12950 };
12951 </programlisting>
12952
12953 <para><literal>pressure</literal> gives the pressure as a floating point number between
12954 0 and 1. <literal>xtilt</literal> and <literal>ytilt</literal> can take on values between 
12955 -1 and 1, corresponding to the degree of tilt in each direction.
12956 <literal>source</literal> and <literal>deviceid</literal> specify the device for which the
12957 event occurred in two different ways. <literal>source</literal> gives some simple
12958 information about the type of device. It can take the enumeration
12959 values:</para>
12960
12961 <programlisting role="C">
12962 GDK_SOURCE_MOUSE
12963 GDK_SOURCE_PEN
12964 GDK_SOURCE_ERASER
12965 GDK_SOURCE_CURSOR
12966 </programlisting>
12967
12968 <para><literal>deviceid</literal> specifies a unique numeric ID for the device. This can
12969 be used to find out further information about the device using the
12970 <literal>gdk_input_list_devices()</literal> call (see below). The special value
12971 <literal>GDK_CORE_POINTER</literal> is used for the core pointer device. (Usually
12972 the mouse.)</para>
12973
12974 <!-- ----------------------------------------------------------------- -->
12975 <sect2>
12976 <title>Enabling extended device information</title>
12977
12978 <para>To let GTK know about our interest in the extended device information,
12979 we merely have to add a single line to our program:</para>
12980
12981 <programlisting role="C">
12982 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
12983 </programlisting>
12984
12985 <para>By giving the value <literal>GDK_EXTENSION_EVENTS_CURSOR</literal> we say that
12986 we are interested in extension events, but only if we don't have
12987 to draw our own cursor. See the section <link
12988 linkend="sec-FurtherSophistications"> Further Sophistications </link> below
12989 for more information about drawing the cursor. We could also 
12990 give the values <literal>GDK_EXTENSION_EVENTS_ALL</literal> if we were willing 
12991 to draw our own cursor, or <literal>GDK_EXTENSION_EVENTS_NONE</literal> to revert
12992 back to the default condition.</para>
12993
12994 <para>This is not completely the end of the story however. By default,
12995 no extension devices are enabled. We need a mechanism to allow
12996 users to enable and configure their extension devices. GTK provides
12997 the InputDialog widget to automate this process. The following
12998 procedure manages an InputDialog widget. It creates the dialog if
12999 it isn't present, and raises it to the top otherwise.</para>
13000
13001 <programlisting role="C">
13002 void
13003 input_dialog_destroy (GtkWidget *w, gpointer data)
13004 {
13005   *((GtkWidget **)data) = NULL;
13006 }
13007
13008 void
13009 create_input_dialog ()
13010 {
13011   static GtkWidget *inputd = NULL;
13012
13013   if (!inputd)
13014     {
13015       inputd = gtk_input_dialog_new();
13016
13017       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
13018                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
13019       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
13020                                  "clicked",
13021                                  (GtkSignalFunc)gtk_widget_hide,
13022                                  GTK_OBJECT(inputd));
13023       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
13024
13025       gtk_widget_show (inputd);
13026     }
13027   else
13028     {
13029       if (!GTK_WIDGET_MAPPED(inputd))
13030         gtk_widget_show(inputd);
13031       else
13032         gdk_window_raise(inputd->window);
13033     }
13034 }
13035 </programlisting>
13036
13037 <para>(You might want to take note of the way we handle this dialog.  By
13038 connecting to the "destroy" signal, we make sure that we don't keep a
13039 pointer to dialog around after it is destroyed - that could lead to a
13040 segfault.)</para>
13041
13042 <para>The InputDialog has two buttons "Close" and "Save", which by default
13043 have no actions assigned to them. In the above function we make
13044 "Close" hide the dialog, hide the "Save" button, since we don't
13045 implement saving of XInput options in this program.</para>
13046
13047 </sect2>
13048
13049 <!-- ----------------------------------------------------------------- -->
13050 <sect2>
13051 <title>Using extended device information</title>
13052
13053 <para>Once we've enabled the device, we can just use the extended 
13054 device information in the extra fields of the event structures.
13055 In fact, it is always safe to use this information since these
13056 fields will have reasonable default values even when extended
13057 events are not enabled.</para>
13058
13059 <para>Once change we do have to make is to call
13060 <literal>gdk_input_window_get_pointer()</literal> instead of
13061 <literal>gdk_window_get_pointer</literal>. This is necessary because
13062 <literal>gdk_window_get_pointer</literal> doesn't return the extended device
13063 information.</para>
13064
13065 <programlisting role="C">
13066 void gdk_input_window_get_pointer( GdkWindow       *window,
13067                                    guint32         deviceid,
13068                                    gdouble         *x,
13069                                    gdouble         *y,
13070                                    gdouble         *pressure,
13071                                    gdouble         *xtilt,
13072                                    gdouble         *ytilt,
13073                                    GdkModifierType *mask);
13074 </programlisting>
13075
13076 <para>When calling this function, we need to specify the device ID as
13077 well as the window. Usually, we'll get the device ID from the
13078 <literal>deviceid</literal> field of an event structure. Again, this function
13079 will return reasonable values when extension events are not
13080 enabled. (In this case, <literal>event->deviceid</literal> will have the value
13081 <literal>GDK_CORE_POINTER</literal>).</para>
13082
13083 <para>So the basic structure of our button-press and motion event handlers
13084 doesn't change much - we just need to add code to deal with the
13085 extended information.</para>
13086
13087 <programlisting role="C">
13088 static gboolean
13089 button_press_event( GtkWidget *widget, GdkEventButton *event )
13090 {
13091   print_button_press (event->deviceid);
13092   
13093   if (event->button == 1 &amp;&amp; pixmap != NULL)
13094     draw_brush (widget, event->source, event->x, event->y, event->pressure);
13095
13096   return TRUE;
13097 }
13098
13099 static gboolean
13100 motion_notify_event( GtkWidget *widget, GdkEventMotion *event )
13101 {
13102   gdouble x, y;
13103   gdouble pressure;
13104   GdkModifierType state;
13105
13106   if (event->is_hint)
13107     gdk_input_window_get_pointer (event->window, event->deviceid,
13108                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
13109   else
13110     {
13111       x = event->x;
13112       y = event->y;
13113       pressure = event->pressure;
13114       state = event->state;
13115     }
13116     
13117   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
13118     draw_brush (widget, event->source, x, y, pressure);
13119   
13120   return TRUE;
13121 }
13122 </programlisting>
13123
13124 <para>We also need to do something with the new information. Our new
13125 <literal>draw_brush()</literal> function draws with a different color for
13126 each <literal>event->source</literal> and changes the brush size depending
13127 on the pressure.</para>
13128
13129 <programlisting role="C">
13130 /* Draw a rectangle on the screen, size depending on pressure,
13131    and color on the type of device */
13132 static void
13133 draw_brush (GtkWidget *widget, GdkInputSource source,
13134             gdouble x, gdouble y, gdouble pressure)
13135 {
13136   GdkGC *gc;
13137   GdkRectangle update_rect;
13138
13139   switch (source)
13140     {
13141     case GDK_SOURCE_MOUSE:
13142       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
13143       break;
13144     case GDK_SOURCE_PEN:
13145       gc = widget->style->black_gc;
13146       break;
13147     case GDK_SOURCE_ERASER:
13148       gc = widget->style->white_gc;
13149       break;
13150     default:
13151       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
13152     }
13153
13154   update_rect.x = x - 10 * pressure;
13155   update_rect.y = y - 10 * pressure;
13156   update_rect.width = 20 * pressure;
13157   update_rect.height = 20 * pressure;
13158   gdk_draw_rectangle (pixmap, gc, TRUE,
13159                       update_rect.x, update_rect.y,
13160                       update_rect.width, update_rect.height);
13161   gtk_widget_draw (widget, &amp;update_rect);
13162 }
13163 </programlisting>
13164
13165 </sect2>
13166
13167 <!-- ----------------------------------------------------------------- -->
13168 <sect2>
13169 <title>Finding out more about a device</title>
13170
13171 <para>As an example of how to find out more about a device, our program
13172 will print the name of the device that generates each button
13173 press. To find out the name of a device, we call the function:</para>
13174
13175 <programlisting role="C">
13176 GList *gdk_input_list_devices               (void);
13177 </programlisting>
13178
13179 <para>which returns a GList (a linked list type from the GLib library)
13180 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
13181 as:</para>
13182
13183 <programlisting role="C">
13184 struct _GdkDeviceInfo
13185 {
13186   guint32 deviceid;
13187   gchar *name;
13188   GdkInputSource source;
13189   GdkInputMode mode;
13190   gint has_cursor;
13191   gint num_axes;
13192   GdkAxisUse *axes;
13193   gint num_keys;
13194   GdkDeviceKey *keys;
13195 };
13196 </programlisting>
13197
13198 <para>Most of these fields are configuration information that you can ignore
13199 unless you are implementing XInput configuration saving. The fieldwe
13200 are interested in here is <literal>name</literal> which is simply the name that X
13201 assigns to the device. The other field that isn't configuration
13202 information is <literal>has_cursor</literal>. If <literal>has_cursor</literal> is false, then we
13203 we need to draw our own cursor. But since we've specified
13204 <literal>GDK_EXTENSION_EVENTS_CURSOR</literal>, we don't have to worry about this.</para>
13205
13206 <para>Our <literal>print_button_press()</literal> function simply iterates through
13207 the returned list until it finds a match, then prints out
13208 the name of the device.</para>
13209
13210 <programlisting role="C">
13211 static void
13212 print_button_press (guint32 deviceid)
13213 {
13214   GList *tmp_list;
13215
13216   /* gdk_input_list_devices returns an internal list, so we shouldn't
13217      free it afterwards */
13218   tmp_list = gdk_input_list_devices();
13219
13220   while (tmp_list)
13221     {
13222       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
13223
13224       if (info->deviceid == deviceid)
13225         {
13226           printf("Button press on device '%s'\n", info->name);
13227           return;
13228         }
13229
13230       tmp_list = tmp_list->next;
13231     }
13232 }
13233 </programlisting>
13234
13235 <para>That completes the changes to "XInputize" our program.</para>
13236
13237 </sect2>
13238
13239 <!-- ----------------------------------------------------------------- -->
13240 <sect2 id="sec-FurtherSophistications">
13241 <title>Further sophistications</title>
13242
13243 <para>Although our program now supports XInput quite well, it lacks some
13244 features we would want in a full-featured application. First, the user
13245 probably doesn't want to have to configure their device each time they
13246 run the program, so we should allow them to save the device
13247 configuration. This is done by iterating through the return of
13248 <literal>gdk_input_list_devices()</literal> and writing out the configuration to a
13249 file.</para>
13250
13251 <para>To restore the state next time the program is run, GDK provides
13252 functions to change device configuration:</para>
13253
13254 <programlisting role="C">
13255 gdk_input_set_extension_events()
13256 gdk_input_set_source()
13257 gdk_input_set_mode()
13258 gdk_input_set_axes()
13259 gdk_input_set_key()
13260 </programlisting>
13261
13262 <para>(The list returned from <literal>gdk_input_list_devices()</literal> should not be
13263 modified directly.) An example of doing this can be found in the
13264 drawing program gsumi. (Available from <ulink
13265 url="http://www.msc.cornell.edu/~otaylor/gsumi/">http://www.msc.cornell.edu/~otaylor/gsumi/</ulink>) Eventually, it
13266 would be nice to have a standard way of doing this for all
13267 applications. This probably belongs at a slightly higher level than
13268 GTK, perhaps in the GNOME library.</para>
13269
13270 <para>Another major omission that we have mentioned above is the lack of
13271 cursor drawing. Platforms other than XFree86 currently do not allow
13272 simultaneously using a device as both the core pointer and directly by
13273 an application. See the <ulink
13274 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html">XInput-HOWTO</ulink> for more information about this. This means that
13275 applications that want to support the widest audience need to draw
13276 their own cursor.</para>
13277
13278 <para>An application that draws its own cursor needs to do two things:
13279 determine if the current device needs a cursor drawn or not, and
13280 determine if the current device is in proximity. (If the current
13281 device is a drawing tablet, it's a nice touch to make the cursor 
13282 disappear when the stylus is lifted from the tablet. When the
13283 device is touching the stylus, that is called "in proximity.")
13284 The first is done by searching the device list, as we did
13285 to find out the device name. The second is achieved by selecting
13286 "proximity_out" events. An example of drawing one's own cursor is
13287 found in the "testinput" program found in the GTK distribution.</para>
13288
13289 </sect2>
13290
13291 </sect1>
13292 </chapter>
13293
13294 <!-- ***************************************************************** -->
13295 <chapter id="ch-Tips">
13296 <title>Tips For Writing GTK Applications</title>
13297
13298 <para>This section is simply a gathering of wisdom, general style guidelines
13299 and hints to creating good GTK applications. Currently this section
13300 is very short, but I hope it will get longer in future editions of
13301 this tutorial.</para>
13302
13303 <para>Use GNU autoconf and automake! They are your friends :) Automake
13304 examines C files, determines how they depend on each other, and
13305 generates a Makefile so the files can be compiled in the correct
13306 order. Autoconf permits automatic configuration of software
13307 installation, handling a large number of system quirks to increase
13308 portability. I am planning to make a quick intro on them here.</para>
13309
13310 <para>When writing C code, use only C comments (beginning with "/*" and
13311 ending with "*/"), and don't use C++-style comments ("//").  Although
13312 many C compilers understand C++ comments, others don't, and the ANSI C
13313 standard does not require that C++-style comments be processed as
13314 comments.</para>
13315
13316 </chapter>
13317
13318 <!-- ***************************************************************** -->
13319 <chapter id="ch-Contributing">
13320 <title>Contributing</title>
13321
13322 <para>This document, like so much other great software out there, was
13323 created for free by volunteers.  If you are at all knowledgeable about
13324 any aspect of GTK that does not already have documentation, please
13325 consider contributing to this document.</para>
13326
13327 <para>If you do decide to contribute, please mail your text to Tony Gale,
13328 <literal><ulink url="mailto:gale@gtk.org">gale@gtk.org</ulink></literal>. Also, be aware that the entirety of this
13329 document is free, and any addition by you provide must also be
13330 free. That is, people may use any portion of your examples in their
13331 programs, and copies of this document may be distributed at will, etc.</para>
13332
13333 <para>Thank you.</para>
13334
13335 </chapter>
13336
13337 <!-- ***************************************************************** -->
13338 <chapter id="ch-Credits">
13339 <title>Credits</title>
13340
13341 <para>We would like to thank the following for their contributions to this text.</para>
13342
13343 <itemizedlist>
13344 <listitem><simpara>Bawer Dagdeviren, <literal><ulink url="mailto:chamele0n@geocities.com">chamele0n@geocities.com</ulink></literal> for the menus tutorial.</simpara>
13345 </listitem>
13346
13347 <listitem><simpara>Raph Levien, <literal><ulink url="mailto:raph@acm.org">raph@acm.org</ulink></literal>
13348 for hello world ala GTK, widget packing, and general all around wisdom.
13349 He's also generously donated a home for this tutorial.</simpara>
13350 </listitem>
13351
13352 <listitem><simpara>Peter Mattis, <literal><ulink url="mailto:petm@xcf.berkeley.edu">petm@xcf.berkeley.edu</ulink></literal> for the simplest GTK program.. 
13353 and the ability to make it :)</simpara>
13354 </listitem>
13355
13356 <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
13357 SGML, and the widget class hierarchy.</simpara>
13358 </listitem>
13359
13360 <listitem><simpara>Mark Crichton <literal><ulink
13361 url="mailto:crichton@expert.cc.purdue.edu">crichton@expert.cc.purdue.edu</ulink></literal> for the menu factory code,
13362 and the table packing tutorial.</simpara>
13363 </listitem>
13364
13365 <listitem><simpara>Owen Taylor <literal><ulink url="mailto:owt1@cornell.edu">owt1@cornell.edu</ulink></literal> for the EventBox widget section (and the
13366 patch to the distro).  He's also responsible for the selections code
13367 and tutorial, as well as the sections on writing your own GTK widgets,
13368 and the example application. Thanks a lot Owen for all you help!</simpara>
13369 </listitem>
13370
13371 <listitem><simpara>Mark VanderBoom <literal><ulink url="mailto:mvboom42@calvin.edu">mvboom42@calvin.edu</ulink></literal> for his wonderful work on the
13372 Notebook, Progress Bar, Dialogs, and File selection widgets.  Thanks a
13373 lot Mark!  You've been a great help.</simpara>
13374 </listitem>
13375
13376 <listitem><simpara>Tim Janik <literal><ulink url="mailto:timj@gtk.org">timj@gtk.org</ulink></literal> for his great job on the Lists
13377 Widget. His excellent work on automatically extracting the widget tree
13378 and signal information from GTK. Thanks Tim :)</simpara>
13379 </listitem>
13380
13381 <listitem><simpara>Rajat Datta <literal><ulink url="mailto:rajat@ix.netcom.com">rajat@ix.netcom.com</ulink>
13382 </literal> for the excellent job on the Pixmap
13383 tutorial.</simpara>
13384 </listitem>
13385
13386 <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>
13387 </listitem>
13388
13389 <listitem><simpara>David Huggins-Daines <literal><ulink
13390 url="mailto:bn711@freenet.carleton.ca">bn711@freenet.carleton.ca</ulink></literal> for the Range Widgets and Tree
13391 Widget sections.</simpara>
13392 </listitem>
13393
13394 <listitem><simpara>Stefan Mars <literal><ulink url="mailto:mars@lysator.liu.se">mars@lysator.liu.se</ulink></literal> for the CList section.</simpara>
13395 </listitem>
13396
13397 <listitem><simpara>David A. Wheeler <literal><ulink url="mailto:dwheeler@ida.org">dwheeler@ida.org</ulink></literal> for portions of the text on GLib
13398 and various tutorial fixups and improvements.
13399 The GLib text was in turn based on material developed by Damon Chaplin
13400 <literal><ulink url="mailto:DAChaplin@msn.com">DAChaplin@msn.com</ulink></literal></simpara>
13401 </listitem>
13402
13403 <listitem><simpara>David King for style checking the entire document.</simpara>
13404 </listitem>
13405 </itemizedlist>
13406
13407 <para>And to all of you who commented on and helped refine this document.</para>
13408
13409 <para>Thanks.</para>
13410
13411 </chapter>
13412
13413 <!-- ***************************************************************** -->
13414 <chapter id="ch-Copyright">
13415 <title>Tutorial Copyright and Permissions Notice</title>
13416
13417 <para>The GTK Tutorial is Copyright (C) 1997 Ian Main. </para>
13418
13419 <para>Copyright (C) 1998-2002 Tony Gale.</para>
13420
13421 <para>Permission is granted to make and distribute verbatim copies of this 
13422 manual provided the copyright notice and this permission notice are 
13423 preserved on all copies.</para>
13424
13425 <para>Permission is granted to copy and distribute modified versions of 
13426 this document under the conditions for verbatim copying, provided that 
13427 this copyright notice is included exactly as in the original,
13428 and that the entire resulting derived work is distributed under 
13429 the terms of a permission notice identical to this one.</para>
13430
13431 <para>Permission is granted to copy and distribute translations of this 
13432 document into another language, under the above conditions for modified 
13433 versions.</para>
13434
13435 <para>If you are intending to incorporate this document into a published 
13436 work, please contact the maintainer, and we will make an effort 
13437 to ensure that you have the most up to date information available.</para>
13438
13439 <para>There is no guarantee that this document lives up to its intended
13440 purpose.  This is simply provided as a free resource.  As such,
13441 the authors and maintainers of the information provided within can
13442 not make any guarantee that the information is even accurate.</para>
13443
13444 </chapter>
13445
13446 <!-- ***************************************************************** -->
13447 <!-- ***************************************************************** -->
13448
13449 <!-- ***************************************************************** -->
13450 <appendix id="app-GTKSignals">
13451 <title>GTK Signals</title>
13452
13453 <para>As GTK is an object oriented widget set, it has a hierarchy of
13454 inheritance. This inheritance mechanism applies for
13455 signals. Therefore, you should refer to the widget hierarchy tree when
13456 using the signals listed in this section.</para>
13457
13458 <!-- ----------------------------------------------------------------- -->
13459 <sect1 id="sec-GtkObject">
13460 <title>GtkObject</title>
13461
13462 <programlisting role="C">
13463 void GtkObject::destroy (GtkObject *,
13464                          gpointer);
13465 </programlisting>
13466
13467 </sect1>
13468
13469 <!-- ----------------------------------------------------------------- -->
13470 <sect1 id="sec-GtkWidget">
13471 <title>GtkWidget</title>
13472
13473 <programlisting role="C">
13474 void GtkWidget::show    (GtkWidget *,
13475                          gpointer);
13476 void GtkWidget::hide    (GtkWidget *,
13477                          gpointer);
13478 void GtkWidget::map     (GtkWidget *,
13479                          gpointer);
13480 void GtkWidget::unmap   (GtkWidget *,
13481                          gpointer);
13482 void GtkWidget::realize (GtkWidget *,
13483                          gpointer);
13484 void GtkWidget::unrealize       (GtkWidget *,
13485                                  gpointer);
13486 void GtkWidget::draw    (GtkWidget *,
13487                          ggpointer,
13488                          gpointer);
13489 void GtkWidget::draw-focus      (GtkWidget *,
13490                                  gpointer);
13491 void GtkWidget::draw-default    (GtkWidget *,
13492                                  gpointer);
13493 void GtkWidget::size-request    (GtkWidget *,
13494                                  ggpointer,
13495                                  gpointer);
13496 void GtkWidget::size-allocate   (GtkWidget *,
13497                                  ggpointer,
13498                                  gpointer);
13499 void GtkWidget::state-changed   (GtkWidget *,
13500                                  GtkStateType,
13501                                  gpointer);
13502 void GtkWidget::parent-set      (GtkWidget *,
13503                                  GtkObject *,
13504                                  gpointer);
13505 void GtkWidget::style-set       (GtkWidget *,
13506                                  GtkStyle *,
13507                                  gpointer);
13508 void GtkWidget::add-accelerator (GtkWidget *,
13509                                  gguint,
13510                                  GtkAccelGroup *,
13511                                  gguint,
13512                                  GdkModifierType,
13513                                  GtkAccelFlags,
13514                                  gpointer);
13515 void GtkWidget::remove-accelerator      (GtkWidget *,
13516                                          GtkAccelGroup *,
13517                                          gguint,
13518                                          GdkModifierType,
13519                                          gpointer);
13520 gboolean GtkWidget::event       (GtkWidget *,
13521                                  GdkEvent *,
13522                                  gpointer);
13523 gboolean GtkWidget::button-press-event  (GtkWidget *,
13524                                          GdkEvent *,
13525                                          gpointer);
13526 gboolean GtkWidget::button-release-event        (GtkWidget *,
13527                                                  GdkEvent *,
13528                                                  gpointer);
13529 gboolean GtkWidget::motion-notify-event (GtkWidget *,
13530                                          GdkEvent *,
13531                                          gpointer);
13532 gboolean GtkWidget::delete-event        (GtkWidget *,
13533                                          GdkEvent *,
13534                                          gpointer);
13535 gboolean GtkWidget::destroy-event       (GtkWidget *,
13536                                          GdkEvent *,
13537                                          gpointer);
13538 gboolean GtkWidget::expose-event        (GtkWidget *,
13539                                          GdkEvent *,
13540                                          gpointer);
13541 gboolean GtkWidget::key-press-event     (GtkWidget *,
13542                                          GdkEvent *,
13543                                          gpointer);
13544 gboolean GtkWidget::key-release-event   (GtkWidget *,
13545                                          GdkEvent *,
13546                                          gpointer);
13547 gboolean GtkWidget::enter-notify-event  (GtkWidget *,
13548                                          GdkEvent *,
13549                                          gpointer);
13550 gboolean GtkWidget::leave-notify-event  (GtkWidget *,
13551                                          GdkEvent *,
13552                                          gpointer);
13553 gboolean GtkWidget::configure-event     (GtkWidget *,
13554                                          GdkEvent *,
13555                                          gpointer);
13556 gboolean GtkWidget::focus-in-event      (GtkWidget *,
13557                                          GdkEvent *,
13558                                          gpointer);
13559 gboolean GtkWidget::focus-out-event     (GtkWidget *,
13560                                          GdkEvent *,
13561                                          gpointer);
13562 gboolean GtkWidget::map-event   (GtkWidget *,
13563                                  GdkEvent *,
13564                                  gpointer);
13565 gboolean GtkWidget::unmap-event (GtkWidget *,
13566                                  GdkEvent *,
13567                                  gpointer);
13568 gboolean GtkWidget::property-notify-event       (GtkWidget *,
13569                                                  GdkEvent *,
13570                                                  gpointer);
13571 gboolean GtkWidget::selection-clear-event       (GtkWidget *,
13572                                                  GdkEvent *,
13573                                                  gpointer);
13574 gboolean GtkWidget::selection-request-event     (GtkWidget *,
13575                                                  GdkEvent *,
13576                                                  gpointer);
13577 gboolean GtkWidget::selection-notify-event      (GtkWidget *,
13578                                                  GdkEvent *,
13579                                                  gpointer);
13580 void GtkWidget::selection-get   (GtkWidget *,
13581                                  GtkSelectionData *,
13582                                  gguint,
13583                                  gpointer);
13584 void GtkWidget::selection-received      (GtkWidget *,
13585                                          GtkSelectionData *,
13586                                          gguint,
13587                                          gpointer);
13588 gboolean GtkWidget::proximity-in-event  (GtkWidget *,
13589                                          GdkEvent *,
13590                                          gpointer);
13591 gboolean GtkWidget::proximity-out-event (GtkWidget *,
13592                                          GdkEvent *,
13593                                          gpointer);
13594 void GtkWidget::drag-begin      (GtkWidget *,
13595                                  GdkDragContext *,
13596                                  gpointer);
13597 void GtkWidget::drag-end        (GtkWidget *,
13598                                  GdkDragContext *,
13599                                  gpointer);
13600 void GtkWidget::drag-data-delete        (GtkWidget *,
13601                                          GdkDragContext *,
13602                                          gpointer);
13603 void GtkWidget::drag-leave      (GtkWidget *,
13604                                  GdkDragContext *,
13605                                  gguint,
13606                                  gpointer);
13607 gboolean GtkWidget::drag-motion (GtkWidget *,
13608                                  GdkDragContext *,
13609                                  ggint,
13610                                  ggint,
13611                                  gguint,
13612                                  gpointer);
13613 gboolean GtkWidget::drag-drop   (GtkWidget *,
13614                                  GdkDragContext *,
13615                                  ggint,
13616                                  ggint,
13617                                  gguint,
13618                                  gpointer);
13619 void GtkWidget::drag-data-get   (GtkWidget *,
13620                                  GdkDragContext *,
13621                                  GtkSelectionData *,
13622                                  gguint,
13623                                  gguint,
13624                                  gpointer);
13625 void GtkWidget::drag-data-received      (GtkWidget *,
13626                                          GdkDragContext *,
13627                                          ggint,
13628                                          ggint,
13629                                          GtkSelectionData *,
13630                                          gguint,
13631                                          gguint,
13632                                          gpointer);
13633 gboolean GtkWidget::client-event        (GtkWidget *,
13634                                          GdkEvent *,
13635                                          gpointer);
13636 gboolean GtkWidget::no-expose-event     (GtkWidget *,
13637                                          GdkEvent *,
13638                                          gpointer);
13639 gboolean GtkWidget::visibility-notify-event     (GtkWidget *,
13640                                                  GdkEvent *,
13641                                                  gpointer);
13642 void GtkWidget::debug-msg       (GtkWidget *,
13643                                  GtkString *,
13644                                  gpointer);
13645 </programlisting>
13646
13647 </sect1>
13648
13649 <!-- ----------------------------------------------------------------- -->
13650 <sect1 id="sec-GtkData">
13651 <title>GtkData</title>
13652
13653 <programlisting role="C">
13654 void GtkData::disconnect        (GtkData *,
13655                                  gpointer);
13656 </programlisting>
13657
13658 </sect1>
13659
13660 <!-- ----------------------------------------------------------------- -->
13661 <sect1 id="sec-GtkContainer">
13662 <title>GtkContainer</title>
13663
13664 <programlisting role="C">
13665 void GtkContainer::add  (GtkContainer *,
13666                          GtkWidget *,
13667                          gpointer);
13668 void GtkContainer::remove       (GtkContainer *,
13669                                  GtkWidget *,
13670                                  gpointer);
13671 void GtkContainer::check-resize (GtkContainer *,
13672                                  gpointer);
13673 GtkDirectionType GtkContainer::focus    (GtkContainer *,
13674                                          GtkDirectionType,
13675                                          gpointer);
13676 void GtkContainer::set-focus-child      (GtkContainer *,
13677                                          GtkWidget *,
13678                                          gpointer);
13679 </programlisting>
13680
13681 </sect1>
13682
13683 <!-- ----------------------------------------------------------------- -->
13684 <sect1 id="sec-GtkCalendar">
13685 <title>GtkCalendar</title>
13686
13687 <programlisting role="C">
13688 void GtkCalendar::month-changed (GtkCalendar *,
13689                                  gpointer);
13690 void GtkCalendar::day-selected  (GtkCalendar *,
13691                                  gpointer);
13692 void GtkCalendar::day-selected-double-click     (GtkCalendar *,
13693                                                  gpointer);
13694 void GtkCalendar::prev-month    (GtkCalendar *,
13695                                  gpointer);
13696 void GtkCalendar::next-month    (GtkCalendar *,
13697                                  gpointer);
13698 void GtkCalendar::prev-year     (GtkCalendar *,
13699                                  gpointer);
13700 void GtkCalendar::next-year     (GtkCalendar *,
13701                                  gpointer);
13702 </programlisting>
13703
13704 </sect1>
13705
13706 <!-- ----------------------------------------------------------------- -->
13707 <sect1 id="sec-GtkEditable">
13708 <title>GtkEditable</title>
13709
13710 <programlisting role="C">
13711 void GtkEditable::changed       (GtkEditable *,
13712                                  gpointer);
13713 void GtkEditable::insert-text   (GtkEditable *,
13714                                  GtkString *,
13715                                  ggint,
13716                                  ggpointer,
13717                                  gpointer);
13718 void GtkEditable::delete-text   (GtkEditable *,
13719                                  ggint,
13720                                  ggint,
13721                                  gpointer);
13722 void GtkEditable::activate      (GtkEditable *,
13723                                  gpointer);
13724 void GtkEditable::set-editable  (GtkEditable *,
13725                                  gboolean,
13726                                  gpointer);
13727 void GtkEditable::move-cursor   (GtkEditable *,
13728                                  ggint,
13729                                  ggint,
13730                                  gpointer);
13731 void GtkEditable::move-word     (GtkEditable *,
13732                                  ggint,
13733                                  gpointer);
13734 void GtkEditable::move-page     (GtkEditable *,
13735                                  ggint,
13736                                  ggint,
13737                                  gpointer);
13738 void GtkEditable::move-to-row   (GtkEditable *,
13739                                  ggint,
13740                                  gpointer);
13741 void GtkEditable::move-to-column        (GtkEditable *,
13742                                          ggint,
13743                                          gpointer);
13744 void GtkEditable::kill-char     (GtkEditable *,
13745                                  ggint,
13746                                  gpointer);
13747 void GtkEditable::kill-word     (GtkEditable *,
13748                                  ggint,
13749                                  gpointer);
13750 void GtkEditable::kill-line     (GtkEditable *,
13751                                  ggint,
13752                                  gpointer);
13753 void GtkEditable::cut-clipboard (GtkEditable *,
13754                                  gpointer);
13755 void GtkEditable::copy-clipboard        (GtkEditable *,
13756                                          gpointer);
13757 void GtkEditable::paste-clipboard       (GtkEditable *,
13758                                          gpointer);
13759 </programlisting>
13760
13761 </sect1>
13762
13763 <!-- ----------------------------------------------------------------- -->
13764 <sect1 id="sec-GtkNotebook">
13765 <title>GtkNotebook</title>
13766
13767 <programlisting role="C">
13768 void GtkNotebook::switch-page   (GtkNotebook *,
13769                                  ggpointer,
13770                                  gguint,
13771                                  gpointer);
13772 </programlisting>
13773
13774 </sect1>
13775
13776 <!-- ----------------------------------------------------------------- -->
13777 <sect1 id="sec-GtkList">
13778 <title>GtkList</title>
13779
13780 <programlisting role="C">
13781 void GtkList::selection-changed (GtkList *,
13782                                  gpointer);
13783 void GtkList::select-child      (GtkList *,
13784                                  GtkWidget *,
13785                                  gpointer);
13786 void GtkList::unselect-child    (GtkList *,
13787                                  GtkWidget *,
13788                                  gpointer);
13789 </programlisting>
13790
13791 </sect1>
13792
13793 <!-- ----------------------------------------------------------------- -->
13794 <sect1 id="sec-GtkMenuShell">
13795 <title>GtkMenuShell</title>
13796
13797 <programlisting role="C">
13798 void GtkMenuShell::deactivate   (GtkMenuShell *,
13799                                  gpointer);
13800 void GtkMenuShell::selection-done       (GtkMenuShell *,
13801                                          gpointer);
13802 void GtkMenuShell::move-current (GtkMenuShell *,
13803                                  GtkMenuDirectionType,
13804                                  gpointer);
13805 void GtkMenuShell::activate-current     (GtkMenuShell *,
13806                                          gboolean,
13807                                          gpointer);
13808 void GtkMenuShell::cancel       (GtkMenuShell *,
13809                                  gpointer);
13810 </programlisting>
13811
13812 </sect1>
13813
13814 <!-- ----------------------------------------------------------------- -->
13815 <sect1 id="sec-GtkToolbar">
13816 <title>GtkToolbar</title>
13817
13818 <programlisting role="C">
13819 void GtkToolbar::orientation-changed    (GtkToolbar *,
13820                                          ggint,
13821                                          gpointer);
13822 void GtkToolbar::style-changed  (GtkToolbar *,
13823                                  ggint,
13824                                  gpointer);
13825 </programlisting>
13826
13827 </sect1>
13828
13829 <!-- ----------------------------------------------------------------- -->
13830 <sect1 id="sec-GtkButton">
13831 <title>GtkButton</title>
13832
13833 <programlisting role="C">
13834 void GtkButton::pressed (GtkButton *,
13835                          gpointer);
13836 void GtkButton::released        (GtkButton *,
13837                                  gpointer);
13838 void GtkButton::clicked (GtkButton *,
13839                          gpointer);
13840 void GtkButton::enter   (GtkButton *,
13841                          gpointer);
13842 void GtkButton::leave   (GtkButton *,
13843                          gpointer);
13844 </programlisting>
13845
13846 </sect1>
13847
13848 <!-- ----------------------------------------------------------------- -->
13849 <sect1 id="sec-GtkItem">
13850 <title>GtkItem</title>
13851
13852 <programlisting role="C">
13853 void GtkItem::select    (GtkItem *,
13854                          gpointer);
13855 void GtkItem::deselect  (GtkItem *,
13856                          gpointer);
13857 void GtkItem::toggle    (GtkItem *,
13858                          gpointer);
13859 </programlisting>
13860
13861 </sect1>
13862
13863 <!-- ----------------------------------------------------------------- -->
13864 <sect1 id="sec-GtkWindow">
13865 <title>GtkWindow</title>
13866
13867 <programlisting role="C">
13868 void GtkWindow::set-focus       (GtkWindow *,
13869                                  ggpointer,
13870                                  gpointer);
13871 </programlisting>
13872
13873 </sect1>
13874
13875 <!-- ----------------------------------------------------------------- -->
13876 <sect1 id="sec-GtkHandleBox">
13877 <title>GtkHandleBox</title>
13878
13879 <programlisting role="C">
13880 void GtkHandleBox::child-attached       (GtkHandleBox *,
13881                                          GtkWidget *,
13882                                          gpointer);
13883 void GtkHandleBox::child-detached       (GtkHandleBox *,
13884                                          GtkWidget *,
13885                                          gpointer);
13886 </programlisting>
13887
13888 </sect1>
13889
13890 <!-- ----------------------------------------------------------------- -->
13891 <sect1 id="sec-GtkToggleButton">
13892 <title>GtkToggleButton</title>
13893
13894 <programlisting role="C">
13895 void GtkToggleButton::toggled   (GtkToggleButton *,
13896                                  gpointer);
13897 </programlisting>
13898
13899 </sect1>
13900
13901 <!-- ----------------------------------------------------------------- -->
13902 <sect1 id="sec-GtkMenuItem">
13903 <title>GtkMenuItem</title>
13904
13905 <programlisting role="C">
13906 void GtkMenuItem::activate      (GtkMenuItem *,
13907                                  gpointer);
13908 void GtkMenuItem::activate-item (GtkMenuItem *,
13909                                  gpointer);
13910 </programlisting>
13911
13912 </sect1>
13913
13914 <!-- ----------------------------------------------------------------- -->
13915 <sect1 id="sec-GtkCheckMenuItem">
13916 <title>GtkCheckMenuItem</title>
13917
13918 <programlisting role="C">
13919 void GtkCheckMenuItem::toggled  (GtkCheckMenuItem *,
13920                                  gpointer);
13921 </programlisting>
13922
13923 </sect1>
13924
13925 <!-- ----------------------------------------------------------------- -->
13926 <sect1 id="sec-GtkInputDialog">
13927 <title>GtkInputDialog</title>
13928
13929 <programlisting role="C">
13930 void GtkInputDialog::enable-device      (GtkInputDialog *,
13931                                          ggint,
13932                                          gpointer);
13933 void GtkInputDialog::disable-device     (GtkInputDialog *,
13934                                          ggint,
13935                                          gpointer);
13936 </programlisting>
13937
13938 </sect1>
13939
13940 <!-- ----------------------------------------------------------------- -->
13941 <sect1 id="sec-GtkColorSelection">
13942 <title>GtkColorSelection</title>
13943
13944 <programlisting role="C">
13945 void GtkColorSelection::color-changed   (GtkColorSelection *,
13946                                          gpointer);
13947 </programlisting>
13948
13949 </sect1>
13950
13951 <!-- ----------------------------------------------------------------- -->
13952 <sect1 id="sec-GtkStatusBar">
13953 <title>GtkStatusBar</title>
13954
13955 <programlisting role="C">
13956 void GtkStatusbar::text-pushed  (GtkStatusbar *,
13957                                  gguint,
13958                                  GtkString *,
13959                                  gpointer);
13960 void GtkStatusbar::text-popped  (GtkStatusbar *,
13961                                  gguint,
13962                                  GtkString *,
13963                                  gpointer);
13964 </programlisting>
13965
13966 </sect1>
13967
13968 <!-- ----------------------------------------------------------------- -->
13969 <sect1 id="sec-GtkCurve">
13970 <title>GtkCurve</title>
13971
13972 <programlisting role="C">
13973 void GtkCurve::curve-type-changed       (GtkCurve *,
13974                                          gpointer);
13975 </programlisting>
13976
13977 </sect1>
13978
13979 <!-- ----------------------------------------------------------------- -->
13980 <sect1 id="sec-GtkAdjustment">
13981 <title>GtkAdjustment</title>
13982
13983 <programlisting role="C">
13984 void GtkAdjustment::changed     (GtkAdjustment *,
13985                                  gpointer);
13986 void GtkAdjustment::value-changed       (GtkAdjustment *,
13987                                          gpointer);
13988 </programlisting>
13989
13990 </sect1>
13991 </appendix>
13992
13993 <!-- ***************************************************************** -->
13994 <appendix id="app-GDKEventTypes">
13995 <title>GDK Event Types</title>
13996
13997 <para>The following data types are passed into event handlers by GTK+. For
13998 each data type listed, the signals that use this data type are listed.</para>
13999
14000 <itemizedlist>
14001 <listitem><simpara>  GdkEvent</simpara>
14002           <itemizedlist>
14003           <listitem><simpara>drag_end_event</simpara>
14004           </listitem>
14005           </itemizedlist>
14006 </listitem>
14007
14008 <listitem><simpara>  GdkEventType<</simpara>
14009 </listitem>
14010
14011 <listitem><simpara>  GdkEventAny</simpara>
14012           <itemizedlist>
14013           <listitem><simpara>delete_event</simpara>
14014           </listitem>
14015           <listitem><simpara>destroy_event</simpara>
14016           </listitem>
14017           <listitem><simpara>map_event</simpara>
14018           </listitem>
14019           <listitem><simpara>unmap_event</simpara>
14020           </listitem>
14021           <listitem><simpara>no_expose_event</simpara>
14022           </listitem>
14023           </itemizedlist>
14024 </listitem>
14025
14026 <listitem><simpara>  GdkEventExpose</simpara>
14027           <itemizedlist>
14028           <listitem><simpara>expose_event</simpara>
14029           </listitem>
14030           </itemizedlist>
14031 </listitem>
14032
14033 <listitem><simpara>  GdkEventNoExpose</simpara>
14034 </listitem>
14035
14036 <listitem><simpara>  GdkEventVisibility</simpara>
14037 </listitem>
14038
14039 <listitem><simpara>  GdkEventMotion</simpara>
14040           <itemizedlist>
14041           <listitem><simpara>motion_notify_event</simpara>
14042           </listitem>
14043           </itemizedlist>
14044 </listitem>
14045 <listitem><simpara>  GdkEventButton</simpara>
14046           <itemizedlist>
14047           <listitem><simpara>button_press_event</simpara>
14048           </listitem>
14049           <listitem><simpara>button_release_event</simpara>
14050           </listitem>
14051           </itemizedlist>
14052 </listitem>
14053
14054 <listitem><simpara>  GdkEventKey</simpara>
14055           <itemizedlist>
14056           <listitem><simpara>key_press_event</simpara>
14057           </listitem>
14058           <listitem><simpara>key_release_event</simpara>
14059           </listitem>
14060           </itemizedlist>
14061 </listitem>
14062
14063 <listitem><simpara>  GdkEventCrossing</simpara>
14064           <itemizedlist>
14065           <listitem><simpara>enter_notify_event</simpara>
14066           </listitem>
14067           <listitem><simpara>leave_notify_event</simpara>
14068           </listitem>
14069           </itemizedlist>
14070 </listitem>
14071
14072 <listitem><simpara>  GdkEventFocus</simpara>
14073           <itemizedlist>
14074           <listitem><simpara>focus_in_event</simpara>
14075           </listitem>
14076           <listitem><simpara>focus_out_event</simpara>
14077           </listitem>
14078           </itemizedlist>
14079 </listitem>
14080
14081 <listitem><simpara>  GdkEventConfigure</simpara>
14082           <itemizedlist>
14083           <listitem><simpara>configure_event</simpara>
14084           </listitem>
14085           </itemizedlist>
14086 </listitem>
14087
14088 <listitem><simpara>  GdkEventProperty</simpara>
14089           <itemizedlist>
14090           <listitem><simpara>property_notify_event</simpara>
14091           </listitem>
14092           </itemizedlist>
14093 </listitem>
14094
14095 <listitem><simpara>  GdkEventSelection</simpara>
14096           <itemizedlist>
14097           <listitem><simpara>selection_clear_event</simpara>
14098           </listitem>
14099           <listitem><simpara>selection_request_event</simpara>
14100           </listitem>
14101           <listitem><simpara>selection_notify_event</simpara>
14102           </listitem>
14103           </itemizedlist>
14104 </listitem>
14105
14106 <listitem><simpara>  GdkEventProximity</simpara>
14107           <itemizedlist>
14108           <listitem><simpara>proximity_in_event</simpara>
14109           </listitem>
14110           <listitem><simpara>proximity_out_event</simpara>
14111           </listitem>
14112           </itemizedlist>
14113 </listitem>
14114
14115 <listitem><simpara>  GdkEventDragBegin</simpara>
14116           <itemizedlist>
14117           <listitem><simpara>drag_begin_event</simpara>
14118           </listitem>
14119           </itemizedlist>
14120 </listitem>
14121
14122 <listitem><simpara>  GdkEventDragRequest</simpara>
14123           <itemizedlist>
14124           <listitem><simpara>drag_request_event</simpara>
14125           </listitem>
14126           </itemizedlist>
14127 </listitem>
14128
14129 <listitem><simpara>  GdkEventDropEnter</simpara>
14130           <itemizedlist>
14131           <listitem><simpara>drop_enter_event</simpara>
14132           </listitem>
14133           </itemizedlist>
14134 </listitem>
14135
14136 <listitem><simpara>  GdkEventDropLeave</simpara>
14137           <itemizedlist>
14138           <listitem><simpara>drop_leave_event</simpara>
14139           </listitem>
14140           </itemizedlist>
14141 </listitem>
14142
14143 <listitem><simpara>  GdkEventDropDataAvailable</simpara>
14144           <itemizedlist>
14145           <listitem><simpara>drop_data_available_event</simpara>
14146           </listitem>
14147           </itemizedlist>
14148 </listitem>
14149
14150 <listitem><simpara>  GdkEventClient</simpara>
14151           <itemizedlist>
14152           <listitem><simpara>client_event</simpara>
14153           </listitem>
14154           </itemizedlist>
14155 </listitem>
14156
14157 <listitem><simpara>  GdkEventOther</simpara>
14158           <itemizedlist>
14159           <listitem><simpara>other_event</simpara>
14160           </listitem>
14161           </itemizedlist>
14162 </listitem>
14163 </itemizedlist>
14164
14165 <para>The data type <literal>GdkEventType</literal> is a special data type that is used by
14166 all the other data types as an indicator of the data type being passed
14167 to the signal handler. As you will see below, each of the event data
14168 structures has a member of this type. It is defined as an enumeration
14169 type as follows:</para>
14170
14171 <programlisting role="C">
14172 typedef enum
14173 {
14174   GDK_NOTHING           = -1,
14175   GDK_DELETE            = 0,
14176   GDK_DESTROY           = 1,
14177   GDK_EXPOSE            = 2,
14178   GDK_MOTION_NOTIFY     = 3,
14179   GDK_BUTTON_PRESS      = 4,
14180   GDK_2BUTTON_PRESS     = 5,
14181   GDK_3BUTTON_PRESS     = 6,
14182   GDK_BUTTON_RELEASE    = 7,
14183   GDK_KEY_PRESS         = 8,
14184   GDK_KEY_RELEASE       = 9,
14185   GDK_ENTER_NOTIFY      = 10,
14186   GDK_LEAVE_NOTIFY      = 11,
14187   GDK_FOCUS_CHANGE      = 12,
14188   GDK_CONFIGURE         = 13,
14189   GDK_MAP               = 14,
14190   GDK_UNMAP             = 15,
14191   GDK_PROPERTY_NOTIFY   = 16,
14192   GDK_SELECTION_CLEAR   = 17,
14193   GDK_SELECTION_REQUEST = 18,
14194   GDK_SELECTION_NOTIFY  = 19,
14195   GDK_PROXIMITY_IN      = 20,
14196   GDK_PROXIMITY_OUT     = 21,
14197   GDK_DRAG_BEGIN        = 22,
14198   GDK_DRAG_REQUEST      = 23,
14199   GDK_DROP_ENTER        = 24,
14200   GDK_DROP_LEAVE        = 25,
14201   GDK_DROP_DATA_AVAIL   = 26,
14202   GDK_CLIENT_EVENT      = 27,
14203   GDK_VISIBILITY_NOTIFY = 28,
14204   GDK_NO_EXPOSE         = 29,
14205   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
14206 } GdkEventType;
14207 </programlisting>
14208
14209 <para>The other event type that is different from the others is
14210 <literal>GdkEvent</literal> itself. This is a union of all the other
14211 data types, which allows it to be cast to a specific
14212 event data type within a signal handler.</para>
14213
14214 <!-- Just a big list for now, needs expanding upon - TRG -->
14215 <para>So, the event data types are defined as follows:</para>
14216
14217 <programlisting role="C">
14218 struct _GdkEventAny
14219 {
14220   GdkEventType type;
14221   GdkWindow *window;
14222   gint8 send_event;
14223 };
14224
14225 struct _GdkEventExpose
14226 {
14227   GdkEventType type;
14228   GdkWindow *window;
14229   gint8 send_event;
14230   GdkRectangle area;
14231   gint count; /* If non-zero, how many more events follow. */
14232 };
14233
14234 struct _GdkEventNoExpose
14235 {
14236   GdkEventType type;
14237   GdkWindow *window;
14238   gint8 send_event;
14239   /* XXX: does anyone need the X major_code or minor_code fields? */
14240 };
14241
14242 struct _GdkEventVisibility
14243 {
14244   GdkEventType type;
14245   GdkWindow *window;
14246   gint8 send_event;
14247   GdkVisibilityState state;
14248 };
14249
14250 struct _GdkEventMotion
14251 {
14252   GdkEventType type;
14253   GdkWindow *window;
14254   gint8 send_event;
14255   guint32 time;
14256   gdouble x;
14257   gdouble y;
14258   gdouble pressure;
14259   gdouble xtilt;
14260   gdouble ytilt;
14261   guint state;
14262   gint16 is_hint;
14263   GdkInputSource source;
14264   guint32 deviceid;
14265   gdouble x_root, y_root;
14266 };
14267
14268 struct _GdkEventButton
14269 {
14270   GdkEventType type;
14271   GdkWindow *window;
14272   gint8 send_event;
14273   guint32 time;
14274   gdouble x;
14275   gdouble y;
14276   gdouble pressure;
14277   gdouble xtilt;
14278   gdouble ytilt;
14279   guint state;
14280   guint button;
14281   GdkInputSource source;
14282   guint32 deviceid;
14283   gdouble x_root, y_root;
14284 };
14285
14286 struct _GdkEventKey
14287 {
14288   GdkEventType type;
14289   GdkWindow *window;
14290   gint8 send_event;
14291   guint32 time;
14292   guint state;
14293   guint keyval;
14294   gint length;
14295   gchar *string;
14296 };
14297
14298 struct _GdkEventCrossing
14299 {
14300   GdkEventType type;
14301   GdkWindow *window;
14302   gint8 send_event;
14303   GdkWindow *subwindow;
14304   GdkNotifyType detail;
14305 };
14306
14307 struct _GdkEventFocus
14308 {
14309   GdkEventType type;
14310   GdkWindow *window;
14311   gint8 send_event;
14312   gint16 in;
14313 };
14314
14315 struct _GdkEventConfigure
14316 {
14317   GdkEventType type;
14318   GdkWindow *window;
14319   gint8 send_event;
14320   gint16 x, y;
14321   gint16 width;
14322   gint16 height;
14323 };
14324
14325 struct _GdkEventProperty
14326 {
14327   GdkEventType type;
14328   GdkWindow *window;
14329   gint8 send_event;
14330   GdkAtom atom;
14331   guint32 time;
14332   guint state;
14333 };
14334
14335 struct _GdkEventSelection
14336 {
14337   GdkEventType type;
14338   GdkWindow *window;
14339   gint8 send_event;
14340   GdkAtom selection;
14341   GdkAtom target;
14342   GdkAtom property;
14343   guint32 requestor;
14344   guint32 time;
14345 };
14346
14347 /* This event type will be used pretty rarely. It only is important
14348    for XInput aware programs that are drawing their own cursor */
14349
14350 struct _GdkEventProximity
14351 {
14352   GdkEventType type;
14353   GdkWindow *window;
14354   gint8 send_event;
14355   guint32 time;
14356   GdkInputSource source;
14357   guint32 deviceid;
14358 };
14359
14360 struct _GdkEventDragRequest
14361 {
14362   GdkEventType type;
14363   GdkWindow *window;
14364   gint8 send_event;
14365   guint32 requestor;
14366   union {
14367     struct {
14368       guint protocol_version:4;
14369       guint sendreply:1;
14370       guint willaccept:1;
14371       guint delete_data:1; /* Do *not* delete if link is sent, only
14372                               if data is sent */
14373       guint senddata:1;
14374       guint reserved:22;
14375     } flags;
14376     glong allflags;
14377   } u;
14378   guint8 isdrop; /* This gdk event can be generated by a couple of
14379                     X events - this lets the app know whether the
14380                     drop really occurred or we just set the data */
14381
14382   GdkPoint drop_coords;
14383   gchar *data_type;
14384   guint32 timestamp;
14385 };
14386
14387 struct _GdkEventDragBegin
14388 {
14389   GdkEventType type;
14390   GdkWindow *window;
14391   gint8 send_event;
14392   union {
14393     struct {
14394       guint protocol_version:4;
14395       guint reserved:28;
14396     } flags;
14397     glong allflags;
14398   } u;
14399 };
14400
14401 struct _GdkEventDropEnter
14402 {
14403   GdkEventType type;
14404   GdkWindow *window;
14405   gint8 send_event;
14406   guint32 requestor;
14407   union {
14408     struct {
14409       guint protocol_version:4;
14410       guint sendreply:1;
14411       guint extended_typelist:1;
14412       guint reserved:26;
14413     } flags;
14414     glong allflags;
14415   } u;
14416 };
14417
14418 struct _GdkEventDropLeave
14419 {
14420   GdkEventType type;
14421   GdkWindow *window;
14422   gint8 send_event;
14423   guint32 requestor;
14424   union {
14425     struct {
14426       guint protocol_version:4;
14427       guint reserved:28;
14428     } flags;
14429     glong allflags;
14430   } u;
14431 };
14432
14433 struct _GdkEventDropDataAvailable
14434 {
14435   GdkEventType type;
14436   GdkWindow *window;
14437   gint8 send_event;
14438   guint32 requestor;
14439   union {
14440     struct {
14441       guint protocol_version:4;
14442       guint isdrop:1;
14443       guint reserved:25;
14444     } flags;
14445     glong allflags;
14446   } u;
14447   gchar *data_type; /* MIME type */
14448   gulong data_numbytes;
14449   gpointer data;
14450   guint32 timestamp;
14451   GdkPoint coords;
14452 };
14453
14454 struct _GdkEventClient
14455 {
14456   GdkEventType type;
14457   GdkWindow *window;
14458   gint8 send_event;
14459   GdkAtom message_type;
14460   gushort data_format;
14461   union {
14462     char b[20];
14463     short s[10];
14464     long l[5];
14465   } data;
14466 };
14467
14468 struct _GdkEventOther
14469 {
14470   GdkEventType type;
14471   GdkWindow *window;
14472   gint8 send_event;
14473   GdkXEvent *xevent;
14474 };
14475 </programlisting>
14476
14477 </appendix>
14478
14479 <!-- ***************************************************************** -->
14480 <appendix id="app-CodeExamples">
14481 <title>Code Examples</title>
14482
14483 <para>Below are the code examples that are used in the above text
14484 which are not included in complete form elsewhere.</para>
14485
14486 <!-- ----------------------------------------------------------------- -->
14487 <sect1 id="sec-Tictactoe">
14488 <title>Tictactoe</title>
14489 <!-- ----------------------------------------------------------------- -->
14490 <sect2>
14491 <title>tictactoe.h</title>
14492
14493 <programlisting role="C">
14494 <!-- example-start tictactoe tictactoe.h -->
14495 /* GTK - The GIMP Toolkit
14496  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14497  *
14498  * This library is free software; you can redistribute it and/or
14499  * modify it under the terms of the GNU Library General Public
14500  * License as published by the Free Software Foundation; either
14501  * version 2 of the License, or (at your option) any later version.
14502  *
14503  * This library is distributed in the hope that it will be useful,
14504  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14505  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14506  * Library General Public License for more details.
14507  *
14508  * You should have received a copy of the GNU Library General Public
14509  * License along with this library; if not, write to the
14510  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14511  * Boston, MA 02111-1307, USA.
14512  */
14513 #ifndef __TICTACTOE_H__
14514 #define __TICTACTOE_H__
14515
14516
14517 #include &lt;glib.h&gt;
14518 #include &lt;glib-object.h&gt;
14519 #include &lt;gtk/gtktable.h&gt;
14520
14521
14522 G_BEGIN_DECLS
14523
14524 #define TICTACTOE_TYPE            (tictactoe_get_type ())
14525 #define TICTACTOE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TICTACTOE_TYPE, Tictactoe))
14526 #define TICTACTOE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TICTACTOE_TYPE, TictactoeClass))
14527 #define IS_TICTACTOE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TICTACTOE_TYPE))
14528 #define IS_TICTACTOE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TICTACTOE_TYPE))
14529
14530
14531 typedef struct _Tictactoe       Tictactoe;
14532 typedef struct _TictactoeClass  TictactoeClass;
14533
14534 struct _Tictactoe
14535 {
14536   GtkTable table;
14537   
14538   GtkWidget *buttons[3][3];
14539 };
14540
14541 struct _TictactoeClass
14542 {
14543   GtkTableClass parent_class;
14544
14545   void (* tictactoe) (Tictactoe *ttt);
14546 };
14547
14548 GType          tictactoe_get_type        (void);
14549 GtkWidget*     tictactoe_new             (void);
14550 void           tictactoe_clear           (Tictactoe *ttt);
14551
14552 G_END_DECLS
14553
14554 #endif /* __TICTACTOE_H__ */
14555
14556 <!-- example-end -->
14557 </programlisting>
14558
14559 </sect2>
14560
14561 <!-- ----------------------------------------------------------------- -->
14562 <sect2>
14563 <title>tictactoe.c</title>
14564
14565 <programlisting role="C">
14566 <!-- example-start tictactoe tictactoe.c -->
14567
14568 /* GTK - The GIMP Toolkit
14569  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14570  *
14571  * This library is free software; you can redistribute it and/or
14572  * modify it under the terms of the GNU Library General Public
14573  * License as published by the Free Software Foundation; either
14574  * version 2 of the License, or (at your option) any later version.
14575  *
14576  * This library is distributed in the hope that it will be useful,
14577  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14578  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14579  * Library General Public License for more details.
14580  *
14581  * You should have received a copy of the GNU Library General Public
14582  * License along with this library; if not, write to the
14583  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14584  * Boston, MA 02111-1307, USA.
14585  */
14586 #include &lt;gtk/gtksignal.h&gt;
14587 #include &lt;gtk/gtktable.h&gt;
14588 #include &lt;gtk/gtktogglebutton.h&gt;
14589 #include "tictactoe.h"
14590
14591 enum {
14592   TICTACTOE_SIGNAL,
14593   LAST_SIGNAL
14594 };
14595
14596 static void tictactoe_class_init          (TictactoeClass *klass);
14597 static void tictactoe_init                (Tictactoe      *ttt);
14598 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
14599
14600 static guint tictactoe_signals[LAST_SIGNAL] = { 0 };
14601
14602 GType
14603 tictactoe_get_type (void)
14604 {
14605   static GType ttt_type = 0;
14606
14607   if (!ttt_type)
14608     {
14609       static const GTypeInfo ttt_info =
14610       {
14611         sizeof (TictactoeClass),
14612         NULL, /* base_init */
14613         NULL, /* base_finalize */
14614         (GClassInitFunc) tictactoe_class_init,
14615         NULL, /* class_finalize */
14616         NULL, /* class_data */
14617         sizeof (Tictactoe),
14618         0,
14619         (GInstanceInitFunc) tictactoe_init,
14620       };
14621
14622       ttt_type = g_type_register_static (GTK_TYPE_TABLE, "Tictactoe", &amp;ttt_info, 0);
14623     }
14624
14625   return ttt_type;
14626 }
14627
14628 static void
14629 tictactoe_class_init (TictactoeClass *klass)
14630 {
14631   
14632   tictactoe_signals[TICTACTOE_SIGNAL] = g_signal_new ("tictactoe",
14633                                          G_TYPE_FROM_CLASS (klass),
14634                                          G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
14635                                          G_STRUCT_OFFSET (TictactoeClass, tictactoe),
14636                                          NULL, 
14637                                          NULL,                
14638                                          g_cclosure_marshal_VOID__VOID,
14639                                          G_TYPE_NONE, 0);
14640
14641
14642 }
14643
14644 static void
14645 tictactoe_init (Tictactoe *ttt)
14646 {
14647   gint i,j;
14648   
14649   gtk_table_resize (GTK_TABLE (ttt), 3, 3);
14650   gtk_table_set_homogeneous (GTK_TABLE (ttt), TRUE);
14651
14652   for (i=0;i&lt;3; i++)
14653     for (j=0;j&lt;3; j++)      {
14654         ttt-&gt;buttons[i][j] = gtk_toggle_button_new ();
14655         gtk_table_attach_defaults (GTK_TABLE (ttt), ttt-&gt;buttons[i][j], 
14656                                    i, i+1, j, j+1);
14657         g_signal_connect (G_OBJECT (ttt-&gt;buttons[i][j]), "toggled",
14658                           G_CALLBACK (tictactoe_toggle), (gpointer) ttt);
14659         gtk_widget_set_size_request (ttt-&gt;buttons[i][j], 20, 20);
14660         gtk_widget_show (ttt-&gt;buttons[i][j]);
14661       }
14662 }
14663
14664 GtkWidget*
14665 tictactoe_new ()
14666 {
14667   return GTK_WIDGET (g_object_new (tictactoe_get_type (), NULL));
14668 }
14669
14670 void           
14671 tictactoe_clear (Tictactoe *ttt)
14672 {
14673   int i,j;
14674
14675   for (i = 0; i&lt;3; i++)
14676     for (j = 0; j&lt;3; j++)
14677       {
14678         g_signal_handlers_block_matched (G_OBJECT (ttt-&gt;buttons[i][j]), 
14679                                          G_SIGNAL_MATCH_DATA,
14680                                          0, 0, NULL, NULL, ttt);
14681         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt-&gt;buttons[i][j]),
14682                                       FALSE);
14683         g_signal_handlers_unblock_matched (G_OBJECT (ttt->buttons[i][j]),
14684                                            G_SIGNAL_MATCH_DATA,
14685                                            0, 0, NULL, NULL, ttt);
14686       }
14687 }
14688
14689 static void
14690 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
14691 {
14692   int i,k;
14693
14694   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
14695                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
14696                              { 0, 1, 2 }, { 0, 1, 2 } };
14697   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
14698                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
14699                              { 0, 1, 2 }, { 2, 1, 0 } };
14700
14701   int success, found;
14702
14703   for (k = 0; k&lt;8; k++)
14704     {
14705       success = TRUE;
14706       found = FALSE;
14707
14708       for (i = 0; i&lt;3; i++)
14709         {
14710           success = success &amp;&amp; 
14711             GTK_TOGGLE_BUTTON (ttt-&gt;buttons[rwins[k][i]][cwins[k][i]])-&gt;active;
14712           found = found ||
14713             ttt-&gt;buttons[rwins[k][i]][cwins[k][i]] == widget;
14714         }
14715       
14716       if (success &amp;&amp; found)
14717         {
14718           g_signal_emit (G_OBJECT (ttt), 
14719                          tictactoe_signals[TICTACTOE_SIGNAL], 0);
14720           break;
14721         }
14722     }
14723 }
14724
14725 <!-- example-end -->
14726 </programlisting>
14727
14728 </sect2>
14729
14730 <!-- ----------------------------------------------------------------- -->
14731 <sect2>
14732 <title>ttt_test.c</title>
14733
14734 <programlisting role="C">
14735 <!-- example-start tictactoe ttt_test.c -->
14736
14737 #include &lt;stdlib.h&gt;
14738 #include &lt;gtk/gtk.h&gt;
14739 #include "tictactoe.h"
14740
14741 void win( GtkWidget *widget,
14742           gpointer   data )
14743 {
14744   g_print ("Yay!\n");
14745   tictactoe_clear (TICTACTOE (widget));
14746 }
14747
14748 int main( int   argc,
14749           char *argv[] )
14750 {
14751   GtkWidget *window;
14752   GtkWidget *ttt;
14753   
14754   gtk_init (&amp;argc, &amp;argv);
14755
14756   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
14757   
14758   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
14759   
14760   g_signal_connect (G_OBJECT (window), "destroy",
14761                     G_CALLBACK (exit), NULL);
14762   
14763   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
14764
14765   ttt = tictactoe_new ();
14766   
14767   gtk_container_add (GTK_CONTAINER (window), ttt);
14768   gtk_widget_show (ttt);
14769
14770   /* And attach to its "tictactoe" signal */
14771   g_signal_connect (G_OBJECT (ttt), "tictactoe",
14772                     G_CALLBACK (win), NULL);
14773
14774   gtk_widget_show (window);
14775   
14776   gtk_main ();
14777   
14778   return 0;
14779 }
14780
14781 <!-- example-end -->
14782 </programlisting>
14783
14784 </sect2>
14785 </sect1>
14786
14787 <!-- ----------------------------------------------------------------- -->
14788 <sect1 id="sec-GtkDial">
14789 <title>GtkDial</title>
14790
14791 <!-- ----------------------------------------------------------------- -->
14792 <sect2>
14793 <title>gtkdial.h</title>
14794
14795 <programlisting role="C">
14796 <!-- example-start gtkdial gtkdial.h -->
14797
14798 /* GTK - The GIMP Toolkit
14799  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14800  *
14801  * This library is free software; you can redistribute it and/or
14802  * modify it under the terms of the GNU Library General Public
14803  * License as published by the Free Software Foundation; either
14804  * version 2 of the License, or (at your option) any later version.
14805  *
14806  * This library is distributed in the hope that it will be useful,
14807  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14808  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14809  * Library General Public License for more details.
14810  *
14811  * You should have received a copy of the GNU Library General Public
14812  * License along with this library; if not, write to the
14813  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14814  * Boston, MA 02111-1307, USA.
14815  */
14816 #ifndef __GTK_DIAL_H__
14817 #define __GTK_DIAL_H__
14818
14819
14820 #include &lt;gdk/gdk.h&gt;
14821 #include &lt;gtk/gtkadjustment.h&gt;
14822 #include &lt;gtk/gtkwidget.h&gt;
14823
14824
14825 #ifdef __cplusplus
14826 extern "C" {
14827 #endif /* __cplusplus */
14828
14829
14830 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
14831 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
14832 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
14833
14834
14835 typedef struct _GtkDial        GtkDial;
14836 typedef struct _GtkDialClass   GtkDialClass;
14837
14838 struct _GtkDial
14839 {
14840   GtkWidget widget;
14841
14842   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
14843   guint policy : 2;
14844
14845   /* Button currently pressed or 0 if none */
14846   guint8 button;
14847
14848   /* Dimensions of dial components */
14849   gint radius;
14850   gint pointer_width;
14851
14852   /* ID of update timer, or 0 if none */
14853   guint32 timer;
14854
14855   /* Current angle */
14856   gfloat angle;
14857   gfloat last_angle;
14858
14859   /* Old values from adjustment stored so we know when something changes */
14860   gfloat old_value;
14861   gfloat old_lower;
14862   gfloat old_upper;
14863
14864   /* The adjustment object that stores the data for this dial */
14865   GtkAdjustment *adjustment;
14866 };
14867
14868 struct _GtkDialClass
14869 {
14870   GtkWidgetClass parent_class;
14871 };
14872
14873
14874 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
14875 GtkType        gtk_dial_get_type               (void);
14876 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
14877 void           gtk_dial_set_update_policy      (GtkDial      *dial,
14878                                                 GtkUpdateType  policy);
14879
14880 void           gtk_dial_set_adjustment         (GtkDial      *dial,
14881                                                 GtkAdjustment *adjustment);
14882 #ifdef __cplusplus
14883 }
14884 #endif /* __cplusplus */
14885
14886
14887 #endif /* __GTK_DIAL_H__ */
14888 <!-- example-end -->
14889 </programlisting>
14890
14891 </sect2>
14892
14893 <!-- ----------------------------------------------------------------- -->
14894 <sect2>
14895 <title>gtkdial.c</title>
14896
14897 <programlisting role="C">
14898 <!-- example-start gtkdial gtkdial.c -->
14899
14900 /* GTK - The GIMP Toolkit
14901  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14902  *
14903  * This library is free software; you can redistribute it and/or
14904  * modify it under the terms of the GNU Library General Public
14905  * License as published by the Free Software Foundation; either
14906  * version 2 of the License, or (at your option) any later version.
14907  *
14908  * This library is distributed in the hope that it will be useful,
14909  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14910  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14911  * Library General Public License for more details.
14912  *
14913  * You should have received a copy of the GNU Library General Public
14914  * License along with this library; if not, write to the
14915  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14916  * Boston, MA 02111-1307, USA.
14917  */
14918 #include &lt;math.h&gt;
14919 #include &lt;stdio.h&gt;
14920 #include &lt;gtk/gtkmain.h&gt;
14921 #include &lt;gtk/gtksignal.h&gt;
14922
14923 #include "gtkdial.h"
14924
14925 #define SCROLL_DELAY_LENGTH  300
14926 #define DIAL_DEFAULT_SIZE 100
14927
14928 /* Forward declarations */
14929
14930 static void gtk_dial_class_init               (GtkDialClass     *klass);
14931 static void gtk_dial_init                     (GtkDial          *dial);
14932 static void gtk_dial_destroy                  (GtkObject        *object);
14933 static void gtk_dial_realize                  (GtkWidget        *widget);
14934 static void gtk_dial_size_request             (GtkWidget        *widget,
14935                                                GtkRequisition   *requisition);
14936 static void gtk_dial_size_allocate            (GtkWidget        *widget,
14937                                                GtkAllocation    *allocation);
14938 static gboolean gtk_dial_expose               (GtkWidget        *widget,
14939                                                GdkEventExpose   *event);
14940 static gboolean gtk_dial_button_press         (GtkWidget        *widget,
14941                                                GdkEventButton   *event);
14942 static gboolean gtk_dial_button_release       (GtkWidget        *widget,
14943                                                GdkEventButton   *event);
14944 static gboolean gtk_dial_motion_notify        (GtkWidget        *widget,
14945                                                GdkEventMotion   *event);
14946 static gboolean gtk_dial_timer                (GtkDial          *dial);
14947
14948 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
14949 static void gtk_dial_update                   (GtkDial *dial);
14950 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
14951                                                 gpointer          data);
14952 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
14953                                                 gpointer          data);
14954
14955 /* Local data */
14956
14957 static GtkWidgetClass *parent_class = NULL;
14958
14959 GType
14960 gtk_dial_get_type ()
14961 {
14962   static GType dial_type = 0;
14963
14964   if (!dial_type)
14965     {
14966       static const GTypeInfo dial_info =
14967       {
14968         sizeof (GtkDialClass),
14969         NULL,
14970         NULL,
14971         (GClassInitFunc) gtk_dial_class_init,
14972         NULL,
14973         NULL,
14974         sizeof (GtkDial),
14975         0,
14976         (GInstanceInitFunc) gtk_dial_init,
14977       };
14978
14979       dial_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkDial", &amp;dial_info, 0);
14980     }
14981
14982   return dial_type;
14983 }
14984
14985 static void
14986 gtk_dial_class_init (GtkDialClass *class)
14987 {
14988   GtkObjectClass *object_class;
14989   GtkWidgetClass *widget_class;
14990
14991   object_class = (GtkObjectClass*) class;
14992   widget_class = (GtkWidgetClass*) class;
14993
14994   parent_class = gtk_type_class (gtk_widget_get_type ());
14995
14996   object_class-&gt;destroy = gtk_dial_destroy;
14997
14998   widget_class-&gt;realize = gtk_dial_realize;
14999   widget_class-&gt;expose_event = gtk_dial_expose;
15000   widget_class-&gt;size_request = gtk_dial_size_request;
15001   widget_class-&gt;size_allocate = gtk_dial_size_allocate;
15002   widget_class-&gt;button_press_event = gtk_dial_button_press;
15003   widget_class-&gt;button_release_event = gtk_dial_button_release;
15004   widget_class-&gt;motion_notify_event = gtk_dial_motion_notify;
15005 }
15006
15007 static void
15008 gtk_dial_init (GtkDial *dial)
15009 {
15010   dial-&gt;button = 0;
15011   dial-&gt;policy = GTK_UPDATE_CONTINUOUS;
15012   dial-&gt;timer = 0;
15013   dial-&gt;radius = 0;
15014   dial-&gt;pointer_width = 0;
15015   dial-&gt;angle = 0.0;
15016   dial-&gt;old_value = 0.0;
15017   dial-&gt;old_lower = 0.0;
15018   dial-&gt;old_upper = 0.0;
15019   dial-&gt;adjustment = NULL;
15020 }
15021
15022 GtkWidget*
15023 gtk_dial_new (GtkAdjustment *adjustment)
15024 {
15025   GtkDial *dial;
15026
15027   dial = g_object_new (gtk_dial_get_type (), NULL);
15028
15029   if (!adjustment)
15030     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
15031
15032   gtk_dial_set_adjustment (dial, adjustment);
15033
15034   return GTK_WIDGET (dial);
15035 }
15036
15037 static void
15038 gtk_dial_destroy (GtkObject *object)
15039 {
15040   GtkDial *dial;
15041
15042   g_return_if_fail (object != NULL);
15043   g_return_if_fail (GTK_IS_DIAL (object));
15044
15045   dial = GTK_DIAL (object);
15046
15047   if (dial-&gt;adjustment)
15048     {
15049       g_object_unref (GTK_OBJECT (dial-&gt;adjustment));
15050       dial-&gt;adjustment = NULL;
15051     }
15052
15053   if (GTK_OBJECT_CLASS (parent_class)-&gt;destroy)
15054     (* GTK_OBJECT_CLASS (parent_class)-&gt;destroy) (object);
15055 }
15056
15057 GtkAdjustment*
15058 gtk_dial_get_adjustment (GtkDial *dial)
15059 {
15060   g_return_val_if_fail (dial != NULL, NULL);
15061   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
15062
15063   return dial-&gt;adjustment;
15064 }
15065
15066 void
15067 gtk_dial_set_update_policy (GtkDial      *dial,
15068                              GtkUpdateType  policy)
15069 {
15070   g_return_if_fail (dial != NULL);
15071   g_return_if_fail (GTK_IS_DIAL (dial));
15072
15073   dial-&gt;policy = policy;
15074 }
15075
15076 void
15077 gtk_dial_set_adjustment (GtkDial      *dial,
15078                           GtkAdjustment *adjustment)
15079 {
15080   g_return_if_fail (dial != NULL);
15081   g_return_if_fail (GTK_IS_DIAL (dial));
15082
15083   if (dial-&gt;adjustment)
15084     {
15085       g_signal_handlers_disconnect_by_func (GTK_OBJECT (dial-&gt;adjustment), NULL, (gpointer) dial);
15086       g_object_unref (GTK_OBJECT (dial-&gt;adjustment));
15087     }
15088
15089   dial-&gt;adjustment = adjustment;
15090   g_object_ref (GTK_OBJECT (dial-&gt;adjustment));
15091
15092   g_signal_connect (GTK_OBJECT (adjustment), "changed",
15093                     GTK_SIGNAL_FUNC (gtk_dial_adjustment_changed),
15094                     (gpointer) dial);
15095   g_signal_connect (GTK_OBJECT (adjustment), "value_changed",
15096                     GTK_SIGNAL_FUNC (gtk_dial_adjustment_value_changed),
15097                     (gpointer) dial);
15098
15099   dial-&gt;old_value = adjustment-&gt;value;
15100   dial-&gt;old_lower = adjustment-&gt;lower;
15101   dial-&gt;old_upper = adjustment-&gt;upper;
15102
15103   gtk_dial_update (dial);
15104 }
15105
15106 static void
15107 gtk_dial_realize (GtkWidget *widget)
15108 {
15109   GtkDial *dial;
15110   GdkWindowAttr attributes;
15111   gint attributes_mask;
15112
15113   g_return_if_fail (widget != NULL);
15114   g_return_if_fail (GTK_IS_DIAL (widget));
15115
15116   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
15117   dial = GTK_DIAL (widget);
15118
15119   attributes.x = widget-&gt;allocation.x;
15120   attributes.y = widget-&gt;allocation.y;
15121   attributes.width = widget-&gt;allocation.width;
15122   attributes.height = widget-&gt;allocation.height;
15123   attributes.wclass = GDK_INPUT_OUTPUT;
15124   attributes.window_type = GDK_WINDOW_CHILD;
15125   attributes.event_mask = gtk_widget_get_events (widget) | 
15126     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
15127     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
15128     GDK_POINTER_MOTION_HINT_MASK;
15129   attributes.visual = gtk_widget_get_visual (widget);
15130   attributes.colormap = gtk_widget_get_colormap (widget);
15131
15132   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
15133   widget-&gt;window = gdk_window_new (widget-&gt;parent-&gt;window, &amp;attributes, attributes_mask);
15134
15135   widget-&gt;style = gtk_style_attach (widget-&gt;style, widget-&gt;window);
15136
15137   gdk_window_set_user_data (widget-&gt;window, widget);
15138
15139   gtk_style_set_background (widget-&gt;style, widget-&gt;window, GTK_STATE_ACTIVE);
15140 }
15141
15142 static void 
15143 gtk_dial_size_request (GtkWidget      *widget,
15144                        GtkRequisition *requisition)
15145 {
15146   requisition-&gt;width = DIAL_DEFAULT_SIZE;
15147   requisition-&gt;height = DIAL_DEFAULT_SIZE;
15148 }
15149
15150 static void
15151 gtk_dial_size_allocate (GtkWidget     *widget,
15152                         GtkAllocation *allocation)
15153 {
15154   GtkDial *dial;
15155
15156   g_return_if_fail (widget != NULL);
15157   g_return_if_fail (GTK_IS_DIAL (widget));
15158   g_return_if_fail (allocation != NULL);
15159
15160   widget-&gt;allocation = *allocation;
15161   dial = GTK_DIAL (widget);
15162
15163   if (GTK_WIDGET_REALIZED (widget))
15164     {
15165
15166       gdk_window_move_resize (widget-&gt;window,
15167                               allocation-&gt;x, allocation-&gt;y,
15168                               allocation-&gt;width, allocation-&gt;height);
15169
15170     }
15171   dial-&gt;radius = MIN (allocation-&gt;width, allocation-&gt;height) * 0.45;
15172   dial-&gt;pointer_width = dial-&gt;radius / 5;
15173 }
15174
15175 static gboolean
15176 gtk_dial_expose( GtkWidget      *widget,
15177                  GdkEventExpose *event )
15178 {
15179   GtkDial *dial;
15180   GdkPoint points[6];
15181   gdouble s,c;
15182   gdouble theta, last, increment;
15183   GtkStyle      *blankstyle;
15184   gint xc, yc;
15185   gint upper, lower;
15186   gint tick_length;
15187   gint i, inc;
15188
15189   g_return_val_if_fail (widget != NULL, FALSE);
15190   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15191   g_return_val_if_fail (event != NULL, FALSE);
15192
15193   if (event-&gt;count &gt; 0)
15194     return FALSE;
15195   
15196   dial = GTK_DIAL (widget);
15197
15198 /*  gdk_window_clear_area (widget-&gt;window,
15199                          0, 0,
15200                          widget-&gt;allocation.width,
15201                          widget-&gt;allocation.height);
15202 */
15203   xc = widget-&gt;allocation.width / 2;
15204   yc = widget-&gt;allocation.height / 2;
15205
15206   upper = dial-&gt;adjustment-&gt;upper;
15207   lower = dial-&gt;adjustment-&gt;lower;
15208
15209   /* Erase old pointer */
15210
15211   s = sin (dial-&gt;last_angle);
15212   c = cos (dial-&gt;last_angle);
15213   dial-&gt;last_angle = dial-&gt;angle;
15214
15215   points[0].x = xc + s*dial-&gt;pointer_width/2;
15216   points[0].y = yc + c*dial-&gt;pointer_width/2;
15217   points[1].x = xc + c*dial-&gt;radius;
15218   points[1].y = yc - s*dial-&gt;radius;
15219   points[2].x = xc - s*dial-&gt;pointer_width/2;
15220   points[2].y = yc - c*dial-&gt;pointer_width/2;
15221   points[3].x = xc - c*dial-&gt;radius/10;
15222   points[3].y = yc + s*dial-&gt;radius/10;
15223   points[4].x = points[0].x;
15224   points[4].y = points[0].y;
15225
15226   blankstyle = gtk_style_new ();
15227   blankstyle-&gt;bg_gc[GTK_STATE_NORMAL] =
15228                 widget-&gt;style-&gt;bg_gc[GTK_STATE_NORMAL];
15229   blankstyle-&gt;dark_gc[GTK_STATE_NORMAL] =
15230                 widget-&gt;style-&gt;bg_gc[GTK_STATE_NORMAL];
15231   blankstyle-&gt;light_gc[GTK_STATE_NORMAL] =
15232                 widget-&gt;style-&gt;bg_gc[GTK_STATE_NORMAL];
15233   blankstyle-&gt;black_gc =
15234                 widget-&gt;style-&gt;bg_gc[GTK_STATE_NORMAL];
15235
15236   gtk_paint_polygon (blankstyle,
15237                     widget-&gt;window,
15238                     GTK_STATE_NORMAL,
15239                     GTK_SHADOW_OUT,
15240                     NULL,
15241                     widget,
15242                     NULL,
15243                     points, 5,
15244                     FALSE);
15245
15246   g_object_unref (blankstyle);
15247
15248
15249   /* Draw ticks */
15250
15251   if ((upper - lower) == 0)
15252     return FALSE;
15253
15254   increment = (100*M_PI) / (dial-&gt;radius*dial-&gt;radius);
15255
15256   inc = (upper - lower);
15257
15258   while (inc &lt; 100) inc *= 10;
15259   while (inc &gt;= 1000) inc /= 10;
15260   last = -1;
15261
15262   for (i = 0; i &lt;= inc; i++)
15263     {
15264       theta = ((gfloat)i*M_PI / (18*inc/24.) - M_PI/6.);
15265
15266       if ((theta - last) &lt; (increment))
15267         continue;     
15268       last = theta;
15269
15270       s = sin (theta);
15271       c = cos (theta);
15272
15273       tick_length = (i%(inc/10) == 0) ? dial-&gt;pointer_width : dial-&gt;pointer_width / 2;
15274
15275       gdk_draw_line (widget-&gt;window,
15276                      widget-&gt;style-&gt;fg_gc[widget-&gt;state],
15277                      xc + c*(dial-&gt;radius - tick_length),
15278                      yc - s*(dial-&gt;radius - tick_length),
15279                      xc + c*dial-&gt;radius,
15280                      yc - s*dial-&gt;radius);
15281     }
15282
15283   /* Draw pointer */
15284
15285   s = sin (dial-&gt;angle);
15286   c = cos (dial-&gt;angle);
15287   dial-&gt;last_angle = dial-&gt;angle;
15288
15289   points[0].x = xc + s*dial-&gt;pointer_width/2;
15290   points[0].y = yc + c*dial-&gt;pointer_width/2;
15291   points[1].x = xc + c*dial-&gt;radius;
15292   points[1].y = yc - s*dial-&gt;radius;
15293   points[2].x = xc - s*dial-&gt;pointer_width/2;
15294   points[2].y = yc - c*dial-&gt;pointer_width/2;
15295   points[3].x = xc - c*dial-&gt;radius/10;
15296   points[3].y = yc + s*dial-&gt;radius/10;
15297   points[4].x = points[0].x;
15298   points[4].y = points[0].y;
15299
15300
15301   gtk_paint_polygon (widget-&gt;style,
15302                     widget-&gt;window,
15303                     GTK_STATE_NORMAL,
15304                     GTK_SHADOW_OUT,
15305                     NULL,
15306                     widget,
15307                     NULL,
15308                     points, 5,
15309                     TRUE);
15310
15311   return FALSE;
15312 }
15313
15314 static gboolean
15315 gtk_dial_button_press( GtkWidget      *widget,
15316                        GdkEventButton *event )
15317 {
15318   GtkDial *dial;
15319   gint dx, dy;
15320   double s, c;
15321   double d_parallel;
15322   double d_perpendicular;
15323
15324   g_return_val_if_fail (widget != NULL, FALSE);
15325   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15326   g_return_val_if_fail (event != NULL, FALSE);
15327
15328   dial = GTK_DIAL (widget);
15329
15330   /* Determine if button press was within pointer region - we 
15331      do this by computing the parallel and perpendicular distance of
15332      the point where the mouse was pressed from the line passing through
15333      the pointer */
15334   
15335   dx = event-&gt;x - widget-&gt;allocation.width / 2;
15336   dy = widget-&gt;allocation.height / 2 - event-&gt;y;
15337   
15338   s = sin (dial-&gt;angle);
15339   c = cos (dial-&gt;angle);
15340   
15341   d_parallel = s*dy + c*dx;
15342   d_perpendicular = fabs (s*dx - c*dy);
15343   
15344   if (!dial-&gt;button &amp;&amp;
15345       (d_perpendicular &lt; dial-&gt;pointer_width/2) &amp;&amp;
15346       (d_parallel &gt; - dial-&gt;pointer_width))
15347     {
15348       gtk_grab_add (widget);
15349
15350       dial-&gt;button = event-&gt;button;
15351
15352       gtk_dial_update_mouse (dial, event-&gt;x, event-&gt;y);
15353     }
15354
15355   return FALSE;
15356 }
15357
15358 static gboolean
15359 gtk_dial_button_release( GtkWidget      *widget,
15360                          GdkEventButton *event )
15361 {
15362   GtkDial *dial;
15363
15364   g_return_val_if_fail (widget != NULL, FALSE);
15365   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15366   g_return_val_if_fail (event != NULL, FALSE);
15367
15368   dial = GTK_DIAL (widget);
15369
15370   if (dial-&gt;button == event-&gt;button)
15371     {
15372       gtk_grab_remove (widget);
15373
15374       dial-&gt;button = 0;
15375
15376       if (dial-&gt;policy == GTK_UPDATE_DELAYED)
15377         g_source_remove (dial-&gt;timer);
15378       
15379       if ((dial-&gt;policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
15380           (dial-&gt;old_value != dial-&gt;adjustment-&gt;value))
15381         g_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), "value_changed");
15382     }
15383
15384   return FALSE;
15385 }
15386
15387 static gboolean
15388 gtk_dial_motion_notify( GtkWidget      *widget,
15389                         GdkEventMotion *event )
15390 {
15391   GtkDial *dial;
15392   GdkModifierType mods;
15393   gint x, y, mask;
15394
15395   g_return_val_if_fail (widget != NULL, FALSE);
15396   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15397   g_return_val_if_fail (event != NULL, FALSE);
15398
15399   dial = GTK_DIAL (widget);
15400
15401   if (dial-&gt;button != 0)
15402     {
15403       x = event-&gt;x;
15404       y = event-&gt;y;
15405
15406       if (event-&gt;is_hint || (event-&gt;window != widget-&gt;window))
15407         gdk_window_get_pointer (widget-&gt;window, &amp;x, &amp;y, &amp;mods);
15408
15409       switch (dial-&gt;button)
15410         {
15411         case 1:
15412           mask = GDK_BUTTON1_MASK;
15413           break;
15414         case 2:
15415           mask = GDK_BUTTON2_MASK;
15416           break;
15417         case 3:
15418           mask = GDK_BUTTON3_MASK;
15419           break;
15420         default:
15421           mask = 0;
15422           break;
15423         }
15424
15425       if (mods &amp; mask)
15426         gtk_dial_update_mouse (dial, x,y);
15427     }
15428
15429   return FALSE;
15430 }
15431
15432 static gboolean
15433 gtk_dial_timer( GtkDial *dial )
15434 {
15435   g_return_val_if_fail (dial != NULL, FALSE);
15436   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
15437
15438   if (dial-&gt;policy == GTK_UPDATE_DELAYED)
15439     g_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), "value_changed");
15440
15441   return FALSE;
15442 }
15443
15444 static void
15445 gtk_dial_update_mouse( GtkDial *dial, gint x, gint y )
15446 {
15447   gint xc, yc;
15448   gfloat old_value;
15449
15450   g_return_if_fail (dial != NULL);
15451   g_return_if_fail (GTK_IS_DIAL (dial));
15452
15453   xc = GTK_WIDGET(dial)-&gt;allocation.width / 2;
15454   yc = GTK_WIDGET(dial)-&gt;allocation.height / 2;
15455
15456   old_value = dial-&gt;adjustment-&gt;value;
15457   dial-&gt;angle = atan2(yc-y, x-xc);
15458
15459   if (dial-&gt;angle &lt; -M_PI/2.)
15460     dial-&gt;angle += 2*M_PI;
15461
15462   if (dial-&gt;angle &lt; -M_PI/6)
15463     dial-&gt;angle = -M_PI/6;
15464
15465   if (dial-&gt;angle &gt; 7.*M_PI/6.)
15466     dial-&gt;angle = 7.*M_PI/6.;
15467
15468   dial-&gt;adjustment-&gt;value = dial-&gt;adjustment-&gt;lower + (7.*M_PI/6 - dial-&gt;angle) *
15469     (dial-&gt;adjustment-&gt;upper - dial-&gt;adjustment-&gt;lower) / (4.*M_PI/3.);
15470
15471   if (dial-&gt;adjustment-&gt;value != old_value)
15472     {
15473       if (dial-&gt;policy == GTK_UPDATE_CONTINUOUS)
15474         {
15475           g_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), "value_changed");
15476         }
15477       else
15478         {
15479           gtk_widget_queue_draw (GTK_WIDGET (dial));
15480
15481           if (dial-&gt;policy == GTK_UPDATE_DELAYED)
15482             {
15483               if (dial-&gt;timer)
15484                 g_source_remove (dial-&gt;timer);
15485
15486               dial-&gt;timer = g_timeout_add (SCROLL_DELAY_LENGTH,
15487                                            (GtkFunction) gtk_dial_timer,
15488                                            (gpointer) dial);
15489             }
15490         }
15491     }
15492 }
15493
15494 static void
15495 gtk_dial_update (GtkDial *dial)
15496 {
15497   gfloat new_value;
15498   
15499   g_return_if_fail (dial != NULL);
15500   g_return_if_fail (GTK_IS_DIAL (dial));
15501
15502   new_value = dial-&gt;adjustment-&gt;value;
15503   
15504   if (new_value &lt; dial-&gt;adjustment-&gt;lower)
15505     new_value = dial-&gt;adjustment-&gt;lower;
15506
15507   if (new_value &gt; dial-&gt;adjustment-&gt;upper)
15508     new_value = dial-&gt;adjustment-&gt;upper;
15509
15510   if (new_value != dial-&gt;adjustment-&gt;value)
15511     {
15512       dial-&gt;adjustment-&gt;value = new_value;
15513       g_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), "value_changed");
15514     }
15515
15516   dial-&gt;angle = 7.*M_PI/6. - (new_value - dial-&gt;adjustment-&gt;lower) * 4.*M_PI/3. /
15517     (dial-&gt;adjustment-&gt;upper - dial-&gt;adjustment-&gt;lower);
15518
15519   gtk_widget_queue_draw (GTK_WIDGET (dial));
15520 }
15521
15522 static void
15523 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
15524                               gpointer       data)
15525 {
15526   GtkDial *dial;
15527
15528   g_return_if_fail (adjustment != NULL);
15529   g_return_if_fail (data != NULL);
15530
15531   dial = GTK_DIAL (data);
15532
15533   if ((dial-&gt;old_value != adjustment-&gt;value) ||
15534       (dial-&gt;old_lower != adjustment-&gt;lower) ||
15535       (dial-&gt;old_upper != adjustment-&gt;upper))
15536     {
15537       gtk_dial_update (dial);
15538
15539       dial-&gt;old_value = adjustment-&gt;value;
15540       dial-&gt;old_lower = adjustment-&gt;lower;
15541       dial-&gt;old_upper = adjustment-&gt;upper;
15542     }
15543 }
15544
15545 static void
15546 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
15547                                     gpointer       data)
15548 {
15549   GtkDial *dial;
15550
15551   g_return_if_fail (adjustment != NULL);
15552   g_return_if_fail (data != NULL);
15553
15554   dial = GTK_DIAL (data);
15555
15556   if (dial-&gt;old_value != adjustment-&gt;value)
15557     {
15558       gtk_dial_update (dial);
15559
15560       dial-&gt;old_value = adjustment-&gt;value;
15561     }
15562 }
15563 <!-- example-end -->
15564 </programlisting>
15565
15566 </sect2>
15567
15568 <!-- ----------------------------------------------------------------- -->
15569 <sect2>
15570 <title>dial_test.c</title>
15571
15572 <programlisting role="C">
15573 <!-- example-start gtkdial dial_test.c -->
15574
15575 #include &lt;stdio.h&gt;
15576 #include &lt;stdlib.h&gt;
15577 #include &lt;gtk/gtk.h&gt;
15578 #include "gtkdial.h"
15579
15580 void value_changed( GtkAdjustment *adjustment,
15581                     GtkWidget     *label )
15582 {
15583   char buffer[16];
15584
15585   sprintf(buffer,"%4.2f",adjustment-&gt;value);
15586   gtk_label_set_text (GTK_LABEL (label), buffer);
15587 }
15588
15589 int main( int   argc,
15590           char *argv[])
15591 {
15592   GtkWidget *window;
15593   GtkAdjustment *adjustment;
15594   GtkWidget *dial;
15595   GtkWidget *frame;
15596   GtkWidget *vbox;
15597   GtkWidget *label;
15598   
15599   gtk_init (&amp;argc, &amp;argv);
15600
15601   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15602   
15603   gtk_window_set_title (GTK_WINDOW (window), "Dial");
15604   
15605   g_signal_connect (G_OBJECT (window), "destroy",
15606                     G_CALLBACK (exit), NULL);
15607   
15608   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
15609
15610   vbox = gtk_vbox_new (FALSE, 5);
15611   gtk_container_add (GTK_CONTAINER (window), vbox);
15612   gtk_widget_show (vbox);
15613
15614   frame = gtk_frame_new (NULL);
15615   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
15616   gtk_container_add (GTK_CONTAINER (vbox), frame);
15617   gtk_widget_show (frame); 
15618  
15619   adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 100, 0.01, 0.1, 0));
15620   
15621   dial = gtk_dial_new (adjustment);
15622   gtk_dial_set_update_policy (GTK_DIAL (dial), GTK_UPDATE_DELAYED);
15623   /*  gtk_widget_set_size_request (dial, 100, 100); */
15624   
15625   gtk_container_add (GTK_CONTAINER (frame), dial);
15626   gtk_widget_show (dial);
15627
15628   label = gtk_label_new ("0.00");
15629   gtk_box_pack_end (GTK_BOX (vbox), label, 0, 0, 0);
15630   gtk_widget_show (label);
15631
15632   g_signal_connect (G_OBJECT (adjustment), "value_changed",
15633                     G_CALLBACK (value_changed), (gpointer) label);
15634   
15635   gtk_widget_show (window);
15636   
15637   gtk_main ();
15638   
15639   return 0;
15640 }
15641 <!-- example-end -->
15642 </programlisting>
15643
15644 </sect2>
15645 </sect1>
15646
15647 <!-- ----------------------------------------------------------------- -->
15648 <sect1 id="sec-Scribble">
15649 <title>Scribble</title>
15650
15651 <!-- ----------------------------------------------------------------- -->
15652 <sect2>
15653 <title>scribble-simple.c</title>
15654
15655 <programlisting role="C">
15656 <!-- example-start scribble-simple scribble-simple.c -->
15657
15658 /* GTK - The GIMP Toolkit
15659  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15660  *
15661  * This library is free software; you can redistribute it and/or
15662  * modify it under the terms of the GNU Library General Public
15663  * License as published by the Free Software Foundation; either
15664  * version 2 of the License, or (at your option) any later version.
15665  *
15666  * This library is distributed in the hope that it will be useful,
15667  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15668  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15669  * Library General Public License for more details.
15670  *
15671  * You should have received a copy of the GNU Library General Public
15672  * License along with this library; if not, write to the
15673  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15674  * Boston, MA 02111-1307, USA.
15675  */
15676
15677 #include &lt;stdlib.h&gt;
15678 #include &lt;gtk/gtk.h&gt;
15679
15680 /* Backing pixmap for drawing area */
15681 static GdkPixmap *pixmap = NULL;
15682
15683 /* Create a new backing pixmap of the appropriate size */
15684 static gboolean configure_event( GtkWidget         *widget,
15685                                  GdkEventConfigure *event )
15686 {
15687   if (pixmap)
15688     g_object_unref (pixmap);
15689
15690   pixmap = gdk_pixmap_new (widget-&gt;window,
15691                            widget-&gt;allocation.width,
15692                            widget-&gt;allocation.height,
15693                            -1);
15694   gdk_draw_rectangle (pixmap,
15695                       widget-&gt;style-&gt;white_gc,
15696                       TRUE,
15697                       0, 0,
15698                       widget-&gt;allocation.width,
15699                       widget-&gt;allocation.height);
15700
15701   return TRUE;
15702 }
15703
15704 /* Redraw the screen from the backing pixmap */
15705 static gboolean expose_event( GtkWidget      *widget,
15706                               GdkEventExpose *event )
15707 {
15708   gdk_draw_drawable (widget-&gt;window,
15709                      widget-&gt;style-&gt;fg_gc[GTK_WIDGET_STATE (widget)],
15710                      pixmap,
15711                      event-&gt;area.x, event-&gt;area.y,
15712                      event-&gt;area.x, event-&gt;area.y,
15713                      event-&gt;area.width, event-&gt;area.height);
15714
15715   return FALSE;
15716 }
15717
15718 /* Draw a rectangle on the screen */
15719 static void draw_brush( GtkWidget *widget,
15720                         gdouble    x,
15721                         gdouble    y)
15722 {
15723   GdkRectangle update_rect;
15724
15725   update_rect.x = x - 5;
15726   update_rect.y = y - 5;
15727   update_rect.width = 10;
15728   update_rect.height = 10;
15729   gdk_draw_rectangle (pixmap,
15730                       widget-&gt;style-&gt;black_gc,
15731                       TRUE,
15732                       update_rect.x, update_rect.y,
15733                       update_rect.width, update_rect.height);
15734   gtk_widget_queue_draw_area (widget, 
15735                               update_rect.x, update_rect.y,
15736                               update_rect.width, update_rect.height);
15737 }
15738
15739 static gboolean button_press_event( GtkWidget      *widget,
15740                                     GdkEventButton *event )
15741 {
15742   if (event-&gt;button == 1 &amp;&amp; pixmap != NULL)
15743     draw_brush (widget, event-&gt;x, event-&gt;y);
15744
15745   return TRUE;
15746 }
15747
15748 static gboolean motion_notify_event( GtkWidget *widget,
15749                                      GdkEventMotion *event )
15750 {
15751   int x, y;
15752   GdkModifierType state;
15753
15754   if (event-&gt;is_hint)
15755     gdk_window_get_pointer (event-&gt;window, &amp;x, &amp;y, &amp;state);
15756   else
15757     {
15758       x = event-&gt;x;
15759       y = event-&gt;y;
15760       state = event-&gt;state;
15761     }
15762     
15763   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
15764     draw_brush (widget, x, y);
15765   
15766   return TRUE;
15767 }
15768
15769 void quit ()
15770 {
15771   exit (0);
15772 }
15773
15774 int main( int   argc, 
15775           char *argv[] )
15776 {
15777   GtkWidget *window;
15778   GtkWidget *drawing_area;
15779   GtkWidget *vbox;
15780
15781   GtkWidget *button;
15782
15783   gtk_init (&amp;argc, &amp;argv);
15784
15785   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15786   gtk_widget_set_name (window, "Test Input");
15787
15788   vbox = gtk_vbox_new (FALSE, 0);
15789   gtk_container_add (GTK_CONTAINER (window), vbox);
15790   gtk_widget_show (vbox);
15791
15792   g_signal_connect (G_OBJECT (window), "destroy",
15793                     G_CALLBACK (quit), NULL);
15794
15795   /* Create the drawing area */
15796
15797   drawing_area = gtk_drawing_area_new ();
15798   gtk_widget_set_size_request (GTK_WIDGET (drawing_area), 200, 200);
15799   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
15800
15801   gtk_widget_show (drawing_area);
15802
15803   /* Signals used to handle backing pixmap */
15804
15805   g_signal_connect (G_OBJECT (drawing_area), "expose_event",
15806                     G_CALLBACK (expose_event), NULL);
15807   g_signal_connect (G_OBJECT (drawing_area),"configure_event",
15808                     G_CALLBACK (configure_event), NULL);
15809
15810   /* Event signals */
15811
15812   g_signal_connect (G_OBJECT (drawing_area), "motion_notify_event",
15813                     G_CALLBACK (motion_notify_event), NULL);
15814   g_signal_connect (G_OBJECT (drawing_area), "button_press_event",
15815                     G_CALLBACK (button_press_event), NULL);
15816
15817   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
15818                          | GDK_LEAVE_NOTIFY_MASK
15819                          | GDK_BUTTON_PRESS_MASK
15820                          | GDK_POINTER_MOTION_MASK
15821                          | GDK_POINTER_MOTION_HINT_MASK);
15822
15823   /* .. And a quit button */
15824   button = gtk_button_new_with_label ("Quit");
15825   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
15826
15827   g_signal_connect_swapped (G_OBJECT (button), "clicked",
15828                             G_CALLBACK (gtk_widget_destroy),
15829                             G_OBJECT (window));
15830   gtk_widget_show (button);
15831
15832   gtk_widget_show (window);
15833
15834   gtk_main ();
15835
15836   return 0;
15837 }
15838 <!-- example-end -->
15839 </programlisting>
15840
15841 </sect2>
15842
15843 <!-- ----------------------------------------------------------------- -->
15844 <sect2>
15845 <title>scribble-xinput.c</title>
15846
15847 <programlisting role="C">
15848 <!-- example-start scribble-xinput scribble-xinput.c -->
15849
15850 /* GTK - The GIMP Toolkit
15851  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15852  *
15853  * This library is free software; you can redistribute it and/or
15854  * modify it under the terms of the GNU Library General Public
15855  * License as published by the Free Software Foundation; either
15856  * version 2 of the License, or (at your option) any later version.
15857  *
15858  * This library is distributed in the hope that it will be useful,
15859  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15860  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15861  * Library General Public License for more details.
15862  *
15863  * You should have received a copy of the GNU Library General Public
15864  * License along with this library; if not, write to the
15865  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15866  * Boston, MA 02111-1307, USA.
15867  */
15868
15869 #include &lt;gtk/gtk.h&gt;
15870
15871 /* Backing pixmap for drawing area */
15872 static GdkPixmap *pixmap = NULL;
15873
15874 /* Create a new backing pixmap of the appropriate size */
15875 static gboolean
15876 configure_event (GtkWidget *widget, GdkEventConfigure *event)
15877 {
15878   if (pixmap)
15879      g_object_unref (pixmap);
15880
15881   pixmap = gdk_pixmap_new (widget-&gt;window,
15882                            widget-&gt;allocation.width,
15883                            widget-&gt;allocation.height,
15884                            -1);
15885   gdk_draw_rectangle (pixmap,
15886                       widget-&gt;style-&gt;white_gc,
15887                       TRUE,
15888                       0, 0,
15889                       widget-&gt;allocation.width,
15890                       widget-&gt;allocation.height);
15891
15892   return TRUE;
15893 }
15894
15895 /* Redraw the screen from the backing pixmap */
15896 static gboolean
15897 expose_event (GtkWidget *widget, GdkEventExpose *event)
15898 {
15899   gdk_draw_drawable (widget-&gt;window,
15900                      widget-&gt;style-&gt;fg_gc[GTK_WIDGET_STATE (widget)],
15901                      pixmap,
15902                      event-&gt;area.x, event-&gt;area.y,
15903                      event-&gt;area.x, event-&gt;area.y,
15904                      event-&gt;area.width, event-&gt;area.height);
15905
15906   return FALSE;
15907 }
15908
15909 /* Draw a rectangle on the screen, size depending on pressure,
15910    and color on the type of device */
15911 static void
15912 draw_brush (GtkWidget *widget, GdkInputSource source,
15913             gdouble x, gdouble y, gdouble pressure)
15914 {
15915   GdkGC *gc;
15916   GdkRectangle update_rect;
15917
15918   switch (source)
15919     {
15920     case GDK_SOURCE_MOUSE:
15921       gc = widget-&gt;style-&gt;dark_gc[GTK_WIDGET_STATE (widget)];
15922       break;
15923     case GDK_SOURCE_PEN:
15924       gc = widget-&gt;style-&gt;black_gc;
15925       break;
15926     case GDK_SOURCE_ERASER:
15927       gc = widget-&gt;style-&gt;white_gc;
15928       break;
15929     default:
15930       gc = widget-&gt;style-&gt;light_gc[GTK_WIDGET_STATE (widget)];
15931     }
15932
15933   update_rect.x = x - 10 * pressure;
15934   update_rect.y = y - 10 * pressure;
15935   update_rect.width = 20 * pressure;
15936   update_rect.height = 20 * pressure;
15937   gdk_draw_rectangle (pixmap, gc, TRUE,
15938                       update_rect.x, update_rect.y,
15939                       update_rect.width, update_rect.height);
15940   gtk_widget_queue_draw_area (widget, 
15941                       update_rect.x, update_rect.y,
15942                       update_rect.width, update_rect.height);
15943 }
15944
15945 static void
15946 print_button_press (GdkDevice *device)
15947 {
15948   g_print ("Button press on device '%s'\n", device-&gt;name);
15949 }
15950
15951 static gboolean
15952 button_press_event (GtkWidget *widget, GdkEventButton *event)
15953 {
15954   print_button_press (event-&gt;device);
15955   
15956   if (event-&gt;button == 1 &amp;&amp; pixmap != NULL) {
15957     gdouble pressure;
15958     gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_PRESSURE, &amp;pressure);
15959     draw_brush (widget, event-&gt;device-&gt;source, event-&gt;x, event-&gt;y, pressure);
15960   }
15961
15962   return TRUE;
15963 }
15964
15965 static gboolean
15966 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
15967 {
15968   gdouble x, y;
15969   gdouble pressure;
15970   GdkModifierType state;
15971
15972   if (event-&gt;is_hint) 
15973     {
15974       gdk_device_get_state (event-&gt;device, event-&gt;window, NULL, &amp;state);
15975       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_X, &amp;x);
15976       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_Y, &amp;y);
15977       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_PRESSURE, &amp;pressure);
15978     }
15979   else
15980     {
15981       x = event-&gt;x;
15982       y = event-&gt;y;
15983       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_PRESSURE, &amp;pressure);
15984       state = event-&gt;state;
15985     }
15986     
15987   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
15988     draw_brush (widget, event-&gt;device-&gt;source, x, y, pressure);
15989   
15990   return TRUE;
15991 }
15992
15993 void
15994 input_dialog_destroy (GtkWidget *w, gpointer data)
15995 {
15996   *((GtkWidget **)data) = NULL;
15997 }
15998
15999 void
16000 create_input_dialog ()
16001 {
16002   static GtkWidget *inputd = NULL;
16003
16004   if (!inputd)
16005     {
16006       inputd = gtk_input_dialog_new();
16007
16008       g_signal_connect (G_OBJECT (inputd), "destroy",
16009                         G_CALLBACK (input_dialog_destroy), (gpointer) &amp;inputd);
16010       g_signal_connect_swapped (G_OBJECT (GTK_INPUT_DIALOG (inputd)-&gt;close_button),
16011                                 "clicked",
16012                                 G_CALLBACK (gtk_widget_hide),
16013                                 G_OBJECT (inputd));
16014       gtk_widget_hide (GTK_INPUT_DIALOG (inputd)-&gt;save_button);
16015
16016       gtk_widget_show (inputd);
16017     }
16018   else
16019     {
16020       if (!GTK_WIDGET_MAPPED (inputd))
16021         gtk_widget_show (inputd);
16022       else
16023         gdk_window_raise (inputd-&gt;window);
16024     }
16025 }
16026
16027 void
16028 int
16029 main (int argc, char *argv[])
16030 {
16031   GtkWidget *window;
16032   GtkWidget *drawing_area;
16033   GtkWidget *vbox;
16034
16035   GtkWidget *button;
16036
16037   gtk_init (&amp;argc, &amp;argv);
16038
16039   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
16040   gtk_widget_set_name (window, "Test Input");
16041
16042   vbox = gtk_vbox_new (FALSE, 0);
16043   gtk_container_add (GTK_CONTAINER (window), vbox);
16044   gtk_widget_show (vbox);
16045
16046   g_signal_connect (G_OBJECT (window), "destroy",
16047                     G_CALLBACK (gtk_main_quit), NULL);
16048
16049   /* Create the drawing area */
16050
16051   drawing_area = gtk_drawing_area_new ();
16052   gtk_widget_set_size_request (GTK_WIDGET (drawing_area), 200, 200);
16053   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
16054
16055   gtk_widget_show (drawing_area);
16056
16057   /* Signals used to handle backing pixmap */
16058
16059   g_signal_connect (G_OBJECT (drawing_area), "expose_event",
16060                     G_CALLBACK (expose_event), NULL);
16061   g_signal_connect (G_OBJECT(drawing_area),"configure_event",
16062                     G_CALLBACK (configure_event), NULL);
16063
16064   /* Event signals */
16065
16066   g_signal_connect (G_OBJECT (drawing_area), "motion_notify_event",
16067                     G_CALLBACK (motion_notify_event), NULL);
16068   g_signal_connect (G_OBJECT (drawing_area), "button_press_event",
16069                     G_CALLBACK (button_press_event), NULL);
16070
16071   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
16072                          | GDK_LEAVE_NOTIFY_MASK
16073                          | GDK_BUTTON_PRESS_MASK
16074                          | GDK_POINTER_MOTION_MASK
16075                          | GDK_POINTER_MOTION_HINT_MASK);
16076
16077   /* The following call enables tracking and processing of extension
16078      events for the drawing area */
16079   gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
16080
16081   /* .. And some buttons */
16082   button = gtk_button_new_with_label ("Input Dialog");
16083   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
16084
16085   g_signal_connect (G_OBJECT (button), "clicked",
16086                     G_CALLBACK (create_input_dialog), NULL);
16087   gtk_widget_show (button);
16088
16089   button = gtk_button_new_with_label ("Quit");
16090   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
16091
16092   g_signal_connect_swapped (G_OBJECT (button), "clicked",
16093                             G_CALLBACK (gtk_widget_destroy),
16094                             G_OBJECT (window));
16095   gtk_widget_show (button);
16096
16097   gtk_widget_show (window);
16098
16099   gtk_main ();
16100
16101   return 0;
16102 }
16103 <!-- example-end -->
16104 </programlisting>
16105
16106 </sect2>
16107 </sect1>
16108
16109 </appendix>
16110 </book>