]> Pileus Git - ~andy/gtk/blob - docs/tutorial/gtk-tut.sgml
gtk_adjustment_new() should return a GtkAdjustment*
[~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 (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 (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 (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 (button, "clicked",
362                               G_CALLBACK (gtk_widget_destroy),
363                               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 (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. The second is emitted when we use the gtk_widget_destroy() call
828 passing in the window widget as the object to destroy, or when, in the
829 "delete-event" handler, we return FALSE.
830  
831 The <literal>G_CALLBACK</literal> is a macro
832 that performs 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 (window, "delete-event",
837                       G_CALLBACK (delete_event), NULL);
838     g_signal_connect (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 (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 (button, "clicked",
886                               G_CALLBACK (gtk_widget_destroy),
887                               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 (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 (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 (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 (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 (button, "clicked",
1549                               G_CALLBACK (gtk_main_quit),
1550                               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 (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 (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 (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 (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   G_CALLBACK (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. Note that many functions
1926 accept a gpointer so there is no need to cast the type.</para>
1927
1928 <para>For example:</para>
1929
1930 <programlisting role="C">
1931 g_signal_connect( 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   | | | `GtkHBox
2006   | | |   +GtkCombo
2007   | | |   `GtkStatusbar
2008   | | +GtkFixed
2009   | | +GtkPaned
2010   | | | +GtkHPaned
2011   | | | `GtkVPaned
2012   | | +GtkLayout
2013   | | +GtkMenuShell
2014   | | | +GtkMenuBar
2015   | | | `GtkMenu
2016   | | +GtkNotebook
2017   | | +GtkSocket
2018   | | +GtkTable
2019   | | +GtkTextView
2020   | | +GtkToolbar
2021   | | `GtkTreeView
2022   | +GtkCalendar
2023   | +GtkDrawingArea
2024   | +GtkEditable
2025   | | +GtkEntry
2026   | |   `GtkSpinButton
2027   | +GtkRuler
2028   | | +GtkHRuler
2029   | | `GtkVRuler
2030   | +GtkRange
2031   | | +GtkScale
2032   | | | +GtkHScale
2033   | | | `GtkVScale
2034   | | `GtkScrollbar
2035   | |   +GtkHScrollbar
2036   | |   `GtkVScrollbar
2037   | +GtkSeparator
2038   | | +GtkHSeparator
2039   | | `GtkVSeparator
2040   | +GtkInvisible
2041   | +GtkPreview
2042   | `GtkProgressBar
2043   +GtkAdjustment
2044   +GtkCellRenderer
2045   | +GtkCellRendererPixbuf
2046   | +GtkCellRendererText
2047   | +GtkCellRendererToggle
2048   +GtkItemFactory
2049   +GtkTooltips
2050   `GtkTreeViewColumn
2051 </programlisting>
2052
2053 </sect1>
2054
2055 <!-- ----------------------------------------------------------------- -->
2056 <sect1 id="sec-WidgetsWithoutWindows">
2057 <title>Widgets Without Windows</title>
2058
2059 <para>The following widgets do not have an associated window. If you want to
2060 capture events, you'll have to use the EventBox. See the section on
2061 the <link linkend="sec-EventBox">EventBox</link> widget.</para>
2062
2063 <programlisting role="C">
2064 GtkAlignment
2065 GtkArrow
2066 GtkBin
2067 GtkBox
2068 GtkButton
2069 GtkCheckButton
2070 GtkFixed
2071 GtkImage
2072 GtkLabel
2073 GtkMenuItem
2074 GtkNotebook
2075 GtkPaned
2076 GtkRadioButton
2077 GtkRange
2078 GtkScrolledWindow
2079 GtkSeparator
2080 GtkTable
2081 GtkToolbar
2082 GtkAspectFrame
2083 GtkFrame
2084 GtkVBox
2085 GtkHBox
2086 GtkVSeparator
2087 GtkHSeparator
2088 </programlisting>
2089
2090 <para>We'll further our exploration of GTK by examining each widget in turn,
2091 creating a few simple functions to display them. Another good source
2092 is the <literal>testgtk</literal> program that comes with GTK. It can be found in
2093 <filename>tests/testgtk.c</filename>.</para>
2094
2095 </sect1>
2096 </chapter>
2097
2098 <!-- ***************************************************************** -->
2099 <chapter id="ch-ButtonWidget">
2100 <title>The Button Widget</title>
2101
2102 <!-- ----------------------------------------------------------------- -->
2103 <sect1 id="sec-NormalButtons">
2104 <title>Normal Buttons</title>
2105
2106 <para>We've almost seen all there is to see of the button widget. It's
2107 pretty simple. There is however more than one way to create a button. You can
2108 use the gtk_button_new_with_label() or gtk_button_new_with_mnemonic() to create 
2109 a button with a label, use gtk_button_new_from_stock() to create a button
2110 containing the image and text from a stock item or use gtk_button_new() to
2111 create a blank button. It's then up to you to pack a label or pixmap into 
2112 this new button. To do this, create a new box, and then pack your objects into 
2113 this box using the usual gtk_box_pack_start(), and then use gtk_container_add() 
2114 to pack the box into the button.</para>
2115
2116 <para>Here's an example of using gtk_button_new() to create a button with a
2117 image and a label in it. I've broken up the code to create a box from the rest 
2118 so you can use it in your programs. There are further examples of using images 
2119 later in the tutorial.</para>
2120
2121 <para>
2122 <inlinemediaobject>
2123 <imageobject>
2124 <imagedata fileref="images/buttons.png" format="png">
2125 </imageobject>
2126 </inlinemediaobject>
2127 </para>
2128
2129 <programlisting role="C">
2130 <!-- example-start buttons buttons.c -->
2131
2132 #include &lt;stdlib.h&gt;
2133 #include &lt;gtk/gtk.h&gt;
2134
2135 /* Create a new hbox with an image and a label packed into it
2136  * and return the box. */
2137
2138 static GtkWidget *xpm_label_box( gchar     *xpm_filename,
2139                                  gchar     *label_text )
2140 {
2141     GtkWidget *box;
2142     GtkWidget *label;
2143     GtkWidget *image;
2144
2145     /* Create box for image and label */
2146     box = gtk_hbox_new (FALSE, 0);
2147     gtk_container_set_border_width (GTK_CONTAINER (box), 2);
2148
2149     /* Now on to the image stuff */
2150     image = gtk_image_new_from_file (xpm_filename);
2151
2152     /* Create a label for the button */
2153     label = gtk_label_new (label_text);
2154
2155     /* Pack the image and label into the box */
2156     gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 3);
2157     gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 3);
2158
2159     gtk_widget_show (image);
2160     gtk_widget_show (label);
2161
2162     return box;
2163 }
2164
2165 /* Our usual callback function */
2166 static void callback( GtkWidget *widget,
2167                       gpointer   data )
2168 {
2169     g_print ("Hello again - %s was pressed\n", (char *) data);
2170 }
2171
2172 int main( int   argc,
2173           char *argv[] )
2174 {
2175     /* GtkWidget is the storage type for widgets */
2176     GtkWidget *window;
2177     GtkWidget *button;
2178     GtkWidget *box;
2179
2180     gtk_init (&amp;argc, &amp;argv);
2181
2182     /* Create a new window */
2183     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2184
2185     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
2186
2187     /* It's a good idea to do this for all windows. */
2188     g_signal_connect (window, "destroy",
2189                       G_CALLBACK (gtk_main_quit), NULL);
2190
2191     g_signal_connect (window, "delete-event",
2192                       G_CALLBACK (gtk_main_quit), NULL);
2193
2194     /* Sets the border width of the window. */
2195     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
2196
2197     /* Create a new button */
2198     button = gtk_button_new ();
2199
2200     /* Connect the "clicked" signal of the button to our callback */
2201     g_signal_connect (button, "clicked",
2202                       G_CALLBACK (callback), (gpointer) "cool button");
2203
2204     /* This calls our box creating function */
2205     box = xpm_label_box ("info.xpm", "cool button");
2206
2207     /* Pack and show all our widgets */
2208     gtk_widget_show (box);
2209
2210     gtk_container_add (GTK_CONTAINER (button), box);
2211
2212     gtk_widget_show (button);
2213
2214     gtk_container_add (GTK_CONTAINER (window), button);
2215
2216     gtk_widget_show (window);
2217
2218     /* Rest in gtk_main and wait for the fun to begin! */
2219     gtk_main ();
2220
2221     return 0;
2222 }
2223 <!-- example-end -->
2224 </programlisting>
2225
2226 <para>The xpm_label_box() function could be used to pack images and labels into
2227 any widget that can be a container.</para>
2228
2229 <para>The Button widget has the following signals:</para>
2230
2231 <itemizedlist>
2232 <listitem><simpara><literal>pressed</literal> - emitted when pointer button is pressed within
2233 Button widget</simpara>
2234 </listitem>
2235 <listitem><simpara><literal>released</literal> - emitted when pointer button is released within
2236 Button widget</simpara>
2237 </listitem>
2238 <listitem><simpara><literal>clicked</literal> - emitted when pointer button is pressed and then
2239 released within Button widget</simpara>
2240 </listitem>
2241 <listitem><simpara><literal>enter</literal> - emitted when pointer enters Button widget</simpara>
2242 </listitem>
2243 <listitem><simpara><literal>leave</literal> - emitted when pointer leaves Button widget</simpara>
2244 </listitem>
2245 </itemizedlist>
2246
2247 </sect1>
2248
2249 <!-- ----------------------------------------------------------------- -->
2250 <sect1 id="sec-ToggleButtons">
2251 <title>Toggle Buttons</title>
2252
2253 <para>Toggle buttons are derived from normal buttons and are very similar,
2254 except they will always be in one of two states, alternated by a
2255 click. They may be depressed, and when you click again, they will pop
2256 back up. Click again, and they will pop back down.</para>
2257
2258 <para>Toggle buttons are the basis for check buttons and radio buttons, as
2259 such, many of the calls used for toggle buttons are inherited by radio
2260 and check buttons. I will point these out when we come to them.</para>
2261
2262 <para>Creating a new toggle button:</para>
2263
2264 <programlisting role="C">
2265 GtkWidget *gtk_toggle_button_new( void );
2266
2267 GtkWidget *gtk_toggle_button_new_with_label( const gchar *label );
2268
2269 GtkWidget *gtk_toggle_button_new_with_mnemonic( const gchar *label );
2270 </programlisting>
2271
2272 <para>As you can imagine, these work identically to the normal button widget
2273 calls. The first creates a blank toggle button, and the last two, a
2274 button with a label widget already packed into it. The _mnemonic() variant
2275 additionally parses the label for '_'-prefixed mnemonic characters.</para>
2276
2277 <para>To retrieve the state of the toggle widget, including radio and check
2278 buttons, we use a construct as shown in our example below. This tests
2279 the state of the toggle button, by accessing the <literal>active</literal> field of the
2280 toggle widget's structure, after first using the
2281 <literal>GTK_TOGGLE_BUTTON</literal> macro to cast the widget pointer into a toggle
2282 widget pointer. The signal of interest to us emitted by toggle
2283 buttons (the toggle button, check button, and radio button widgets) is
2284 the "toggled" signal. To check the state of these buttons, set up a
2285 signal handler to catch the toggled signal, and access the structure
2286 to determine its state. The callback will look something like:</para>
2287
2288 <programlisting role="C">
2289 void toggle_button_callback (GtkWidget *widget, gpointer data)
2290 {
2291     if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) 
2292     {
2293         /* If control reaches here, the toggle button is down */
2294     
2295     } else {
2296     
2297         /* If control reaches here, the toggle button is up */
2298     }
2299 }
2300 </programlisting>
2301
2302 <para>To force the state of a toggle button, and its children, the radio and
2303 check buttons, use this function:</para>
2304
2305 <programlisting role="C">
2306 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2307                                    gboolean        is_active );
2308 </programlisting>
2309
2310 <para>The above call can be used to set the state of the toggle button, and
2311 its children the radio and check buttons. Passing in your created
2312 button as the first argument, and a TRUE or FALSE for the second state
2313 argument to specify whether it should be down (depressed) or up
2314 (released). Default is up, or FALSE.</para>
2315
2316 <para>Note that when you use the gtk_toggle_button_set_active() function, and
2317 the state is actually changed, it causes the "clicked" and "toggled"
2318 signals to be emitted from the button.</para>
2319
2320 <programlisting role="C">
2321 gboolean gtk_toggle_button_get_active   (GtkToggleButton *toggle_button);
2322 </programlisting>
2323
2324 <para>This returns the current state of the toggle button as a boolean
2325 TRUE/FALSE value.</para>
2326
2327 </sect1>
2328
2329 <!-- ----------------------------------------------------------------- -->
2330 <sect1 id="sec-CheckButtons">
2331 <title>Check Buttons</title>
2332
2333 <para>Check buttons inherit many properties and functions from the the
2334 toggle buttons above, but look a little different. Rather than being
2335 buttons with text inside them, they are small squares with the text to
2336 the right of them. These are often used for toggling options on and
2337 off in applications.</para>
2338
2339 <para>The creation functions are similar to those of the normal button.</para>
2340
2341 <programlisting role="C">
2342 GtkWidget *gtk_check_button_new( void );
2343
2344 GtkWidget *gtk_check_button_new_with_label ( const gchar *label );
2345
2346 GtkWidget *gtk_check_button_new_with_mnemonic ( const gchar *label );
2347 </programlisting>
2348
2349 <para>The gtk_check_button_new_with_label() function creates a check button 
2350 with a label beside it.</para>
2351
2352 <para>Checking the state of the check button is identical to that of the
2353 toggle button.</para>
2354
2355 </sect1>
2356
2357 <!-- ----------------------------------------------------------------- -->
2358 <sect1 id="sec-RadioButtons">
2359 <title>Radio Buttons</title>
2360
2361 <para>Radio buttons are similar to check buttons except they are grouped so
2362 that only one may be selected/depressed at a time. This is good for
2363 places in your application where you need to select from a short list
2364 of options.</para>
2365
2366 <para>Creating a new radio button is done with one of these calls:</para>
2367
2368 <programlisting role="C">
2369 GtkWidget *gtk_radio_button_new( GSList *group );
2370
2371 GtkWidget *gtk_radio_button_new_from_widget( GtkRadioButton *group );
2372
2373 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
2374                                             const gchar  *label );
2375
2376 GtkWidget* gtk_radio_button_new_with_label_from_widget( GtkRadioButton *group,
2377                                                         const gchar    *label );
2378
2379 GtkWidget *gtk_radio_button_new_with_mnemonic( GSList *group,
2380                                                const gchar  *label );
2381
2382 GtkWidget *gtk_radio_button_new_with_mnemonic_from_widget( GtkRadioButton *group,
2383                                                            const gchar  *label );
2384
2385 </programlisting>
2386
2387 <para>You'll notice the extra argument to these calls. They require a group
2388 to perform their duty properly. The first call to gtk_radio_button_new() or 
2389 gtk_radio_button_new_with_label() should pass NULL as the first argument. 
2390 Then create a group using:</para>
2391
2392 <programlisting role="C">
2393 GSList *gtk_radio_button_get_group( GtkRadioButton *radio_button );
2394 </programlisting>
2395
2396 <para>The important thing to remember is that gtk_radio_button_get_group() must be
2397 called for each new button added to the group, with the previous button passed 
2398 in as an argument. The result is then passed into the next call to 
2399 gtk_radio_button_new() or gtk_radio_button_new_with_label(). This allows a
2400 chain of buttons to be established. The example below should make this clear.</para>
2401
2402 <para>You can shorten this slightly by using the following syntax, which
2403 removes the need for a variable to hold the list of buttons:</para>
2404
2405 <programlisting role="C">
2406      button2 = gtk_radio_button_new_with_label(
2407                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button1)),
2408                  "button2");
2409 </programlisting>
2410
2411 <para>
2412 The _from_widget() variants of the creation functions allow you to shorten this
2413 further, by omitting the gtk_radio_button_get_group() call. This form is used 
2414 in the example to create the third button:
2415 </para>
2416
2417 <programlisting role="C">
2418      button2 = gtk_radio_button_new_with_label_from_widget(
2419                  GTK_RADIO_BUTTON (button1), 
2420                  "button2");
2421 </programlisting>
2422
2423 <para>It is also a good idea to explicitly set which button should be the
2424 default depressed button with:</para>
2425
2426 <programlisting role="C">
2427 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2428                                    gboolean        state );
2429 </programlisting>
2430
2431 <para>This is described in the section on toggle buttons, and works in
2432 exactly the same way.  Once the radio buttons are grouped together,
2433 only one of the group may be active at a time. If the user clicks on
2434 one radio button, and then on another, the first radio button will
2435 first emit a "toggled" signal (to report becoming inactive), and then
2436 the second will emit its "toggled" signal (to report becoming active).</para>
2437
2438 <para>The following example creates a radio button group with three buttons.</para>
2439
2440 <para>
2441 <inlinemediaobject>
2442 <imageobject>
2443 <imagedata fileref="images/radiobuttons.png" format="png">
2444 </imageobject>
2445 </inlinemediaobject>
2446 </para>
2447
2448 <programlisting role="C">
2449 <!-- example-start radiobuttons radiobuttons.c -->
2450
2451 #include &lt;glib.h&gt;
2452 #include &lt;gtk/gtk.h&gt;
2453
2454 static gboolean close_application( GtkWidget *widget,
2455                                    GdkEvent  *event,
2456                                    gpointer   data )
2457 {
2458   gtk_main_quit ();
2459   return FALSE;
2460 }
2461
2462 int main( int   argc,
2463           char *argv[] )
2464 {
2465     GtkWidget *window = NULL;
2466     GtkWidget *box1;
2467     GtkWidget *box2;
2468     GtkWidget *button;
2469     GtkWidget *separator;
2470     GSList *group;
2471   
2472     gtk_init (&amp;argc, &amp;argv);    
2473       
2474     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2475   
2476     g_signal_connect (window, "delete-event",
2477                       G_CALLBACK (close_application),
2478                       NULL);
2479
2480     gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
2481     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2482
2483     box1 = gtk_vbox_new (FALSE, 0);
2484     gtk_container_add (GTK_CONTAINER (window), box1);
2485     gtk_widget_show (box1);
2486
2487     box2 = gtk_vbox_new (FALSE, 10);
2488     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2489     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2490     gtk_widget_show (box2);
2491
2492     button = gtk_radio_button_new_with_label (NULL, "button1");
2493     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2494     gtk_widget_show (button);
2495
2496     group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
2497     button = gtk_radio_button_new_with_label (group, "button2");
2498     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2499     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2500     gtk_widget_show (button);
2501
2502     button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (button),
2503                                                           "button3");
2504     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2505     gtk_widget_show (button);
2506
2507     separator = gtk_hseparator_new ();
2508     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2509     gtk_widget_show (separator);
2510
2511     box2 = gtk_vbox_new (FALSE, 10);
2512     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2513     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2514     gtk_widget_show (box2);
2515
2516     button = gtk_button_new_with_label ("close");
2517     g_signal_connect_swapped (button, "clicked",
2518                               G_CALLBACK (close_application),
2519                               window);
2520     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2521     gtk_widget_set_can_default (button, TRUE);
2522     gtk_widget_grab_default (button);
2523     gtk_widget_show (button);
2524     gtk_widget_show (window);
2525      
2526     gtk_main ();
2527
2528     return 0;
2529 }
2530 <!-- example-end -->
2531 </programlisting>
2532
2533 </sect1>
2534 </chapter>
2535
2536 <!-- ***************************************************************** -->
2537 <chapter id="ch-Adjustments">
2538 <title>Adjustments</title>
2539
2540 <para>GTK has various widgets that can be visually adjusted by the user
2541 using the mouse or the keyboard, such as the range widgets, described
2542 in the <link linkend="ch-RangeWidgets">Range Widgets</link>
2543 section. There are also a few widgets that display some adjustable
2544 portion of a larger area of data, such as the text widget and the
2545 viewport widget.</para>
2546
2547 <para>Obviously, an application needs to be able to react to changes the
2548 user makes in range widgets. One way to do this would be to have each
2549 widget emit its own type of signal when its adjustment changes, and
2550 either pass the new value to the signal handler, or require it to look
2551 inside the widget's data structure in order to ascertain the value.
2552 But you may also want to connect the adjustments of several widgets
2553 together, so that adjusting one adjusts the others. The most obvious
2554 example of this is connecting a scrollbar to a panning viewport or a
2555 scrolling text area. If each widget has its own way of setting or
2556 getting the adjustment value, then the programmer may have to write
2557 their own signal handlers to translate between the output of one
2558 widget's signal and the "input" of another's adjustment setting
2559 function.</para>
2560
2561 <para>GTK solves this problem using the Adjustment object, which is not a
2562 widget but a way for widgets to store and pass adjustment information
2563 in an abstract and flexible form. The most obvious use of Adjustment
2564 is to store the configuration parameters and values of range widgets,
2565 such as scrollbars and scale controls. However, since Adjustments are
2566 derived from Object, they have some special powers beyond those of
2567 normal data structures. Most importantly, they can emit signals, just
2568 like widgets, and these signals can be used not only to allow your
2569 program to react to user input on adjustable widgets, but also to
2570 propagate adjustment values transparently between adjustable widgets.</para>
2571
2572 <para>You will see how adjustments fit in when you see the other widgets
2573 that incorporate them:
2574 <link linkend="sec-ProgressBars">Progress Bars</link>,
2575 <link linkend="sec-Viewports">Viewports</link>,
2576 <link linkend="sec-ScrolledWindows">Scrolled Windows</link>, and others.</para>
2577
2578 <!-- ----------------------------------------------------------------- -->
2579 <sect1 id="sec-CreatingAnAdjustment">
2580 <title>Creating an Adjustment</title>
2581
2582 <para>Many of the widgets which use adjustment objects do so automatically,
2583 but some cases will be shown in later examples where you may need to
2584 create one yourself. You create an adjustment using:</para>
2585
2586 <programlisting role="C">
2587 GtkAdjustment *gtk_adjustment_new( gdouble value,
2588                                    gdouble lower,
2589                                    gdouble upper,
2590                                    gdouble step_increment,
2591                                    gdouble page_increment,
2592                                    gdouble page_size );
2593 </programlisting>
2594
2595 <para>The <literal>value</literal> argument is the initial value you want to give to the
2596 adjustment, usually corresponding to the topmost or leftmost position
2597 of an adjustable widget. The <literal>lower</literal> argument specifies the lowest
2598 value which the adjustment can hold. The <literal>step_increment</literal> argument
2599 specifies the "smaller" of the two increments by which the user can
2600 change the value, while the <literal>page_increment</literal> is the "larger" one.
2601 The <literal>page_size</literal> argument usually corresponds somehow to the visible
2602 area of a panning widget. The <literal>upper</literal> argument is used to represent
2603 the bottom most or right most coordinate in a panning widget's
2604 child. Therefore it is <emphasis>not</emphasis> always the largest number that
2605 <literal>value</literal> can take, since the <literal>page_size</literal> of such widgets is
2606 usually non-zero.</para>
2607
2608 </sect1>
2609
2610 <!-- ----------------------------------------------------------------- -->
2611 <sect1 id="sec-UsingAdjustments">
2612 <title>Using Adjustments the Easy Way</title>
2613
2614 <para>The adjustable widgets can be roughly divided into those which use and
2615 require specific units for these values and those which treat them as
2616 arbitrary numbers. The group which treats the values as arbitrary
2617 numbers includes the range widgets (scrollbars and scales, the
2618 progress bar widget, and the spin button widget). These widgets are
2619 all the widgets which are typically "adjusted" directly by the user
2620 with the mouse or keyboard. They will treat the <literal>lower</literal> and
2621 <literal>upper</literal> values of an adjustment as a range within which the user
2622 can manipulate the adjustment's <literal>value</literal>. By default, they will only
2623 modify the <literal>value</literal> of an adjustment.</para>
2624
2625 <para>The other group includes the text widget, the viewport widget, the
2626 compound list widget, and the scrolled window widget. All of these
2627 widgets use pixel values for their adjustments. These are also all
2628 widgets which are typically "adjusted" indirectly using scrollbars.
2629 While all widgets which use adjustments can either create their own
2630 adjustments or use ones you supply, you'll generally want to let this
2631 particular category of widgets create its own adjustments. Usually,
2632 they will eventually override all the values except the <literal>value</literal>
2633 itself in whatever adjustments you give them, but the results are, in
2634 general, undefined (meaning, you'll have to read the source code to
2635 find out, and it may be different from widget to widget).</para>
2636
2637 <para>Now, you're probably thinking, since text widgets and viewports insist
2638 on setting everything except the <literal>value</literal> of their adjustments,
2639 while scrollbars will <emphasis>only</emphasis> touch the adjustment's 
2640 <literal>value</literal>, if you <emphasis>share</emphasis> an adjustment
2641 object between a scrollbar and a text widget, manipulating the scrollbar will 
2642 automagically adjust the viewport widget?  Of course it will! Just like this:</para>
2643
2644 <programlisting role="C">
2645   /* creates its own adjustments */
2646   viewport = gtk_viewport_new (NULL, NULL);
2647   /* uses the newly-created adjustment for the scrollbar as well */
2648   vscrollbar = gtk_vscrollbar_new (gtk_viewport_get_vadjustment (viewport));
2649 </programlisting>
2650
2651 </sect1>
2652
2653 <!-- ----------------------------------------------------------------- -->
2654 <sect1 id="sec-AdjustmentInternals">
2655 <title>Adjustment Internals</title>
2656
2657 <para>Ok, you say, that's nice, but what if I want to create my own handlers
2658 to respond when the user adjusts a range widget or a spin button, and
2659 how do I get at the value of the adjustment in these handlers?  To
2660 answer these questions and more, let's start by taking a look at
2661 <literal>struct _GtkAdjustment</literal> itself:</para>
2662
2663 <programlisting role="C">
2664 struct _GtkAdjustment
2665 {
2666   GtkObject parent_instance;
2667   
2668   gdouble lower;
2669   gdouble upper;
2670   gdouble value;
2671   gdouble step_increment;
2672   gdouble page_increment;
2673   gdouble page_size;
2674 };
2675 </programlisting>
2676
2677 <para>If you don't like to poke directly at struct internals like a 
2678 <emphasis>real</emphasis> C programmer, you can use the following accessor to
2679 inspect the <literal>value</literal> of an adjustment:</para>
2680
2681 <programlisting role="C">
2682 gdouble gtk_adjustment_get_value( GtkAdjustment *adjustment);
2683 </programlisting>
2684
2685 <para>Since, when you set the <literal>value</literal> of an Adjustment, you generally
2686 want the change to be reflected by every widget that uses this
2687 adjustment, GTK provides this convenience function to do this:</para>
2688
2689 <programlisting role="C">
2690 void gtk_adjustment_set_value( GtkAdjustment *adjustment,
2691                                gdouble       value );
2692 </programlisting>
2693
2694 <para>As mentioned earlier, Adjustment is a subclass of Object just
2695 like all the various widgets, and thus it is able to emit signals.
2696 This is, of course, why updates happen automagically when you share an
2697 adjustment object between a scrollbar and another adjustable widget;
2698 all adjustable widgets connect signal handlers to their adjustment's
2699 <literal>value_changed</literal> signal, as can your program. Here's the definition
2700 of this signal in <literal>struct _GtkAdjustmentClass</literal>:</para>
2701
2702 <programlisting role="C">
2703   void (* value_changed) (GtkAdjustment *adjustment);
2704 </programlisting>
2705
2706 <para>The various widgets that use the Adjustment object will emit this
2707 signal on an adjustment whenever they change its value. This happens
2708 both when user input causes the slider to move on a range widget, as
2709 well as when the program explicitly changes the value with
2710 gtk_adjustment_set_value(). So, for example, if you have a scale
2711 widget, and you want to change the rotation of a picture whenever its
2712 value changes, you would create a callback like this:</para>
2713
2714 <programlisting role="C">
2715 void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
2716 {
2717   set_picture_rotation (picture, gtk_adjustment_get_value (adj));
2718 ...
2719 </programlisting>
2720
2721 <para>and connect it to the scale widget's adjustment like this:</para>
2722
2723 <programlisting role="C">
2724 g_signal_connect (adj, "value_changed",
2725                   G_CALLBACK (cb_rotate_picture), picture);
2726 </programlisting>
2727
2728 <para>What about when a widget reconfigures the <literal>upper</literal> or <literal>lower</literal>
2729 fields of its adjustment, such as when a user adds more text to a text
2730 widget?  In this case, it emits the <literal>changed</literal> signal, which looks
2731 like this:</para>
2732
2733 <programlisting role="C">
2734   void (* changed) (GtkAdjustment *adjustment);
2735 </programlisting>
2736
2737 <para>Range widgets typically connect a handler to this signal, which
2738 changes their appearance to reflect the change - for example, the size
2739 of the slider in a scrollbar will grow or shrink in inverse proportion
2740 to the difference between the <literal>lower</literal> and <literal>upper</literal> values of its
2741 adjustment.</para>
2742
2743 <para>You probably won't ever need to attach a handler to this signal,
2744 unless you're writing a new type of range widget.  However, if you
2745 change any of the values in a Adjustment directly, you should emit
2746 this signal on it to reconfigure whatever widgets are using it, like
2747 this:</para>
2748
2749 <programlisting role="C">
2750 g_signal_emit_by_name (adjustment, "changed");
2751 </programlisting>
2752
2753 <para>Now go forth and adjust!</para>
2754
2755 </sect1>
2756 </chapter>
2757
2758 <!-- ***************************************************************** -->
2759 <chapter id="ch-RangeWidgets">
2760 <title>Range Widgets</title>
2761
2762 <para>The category of range widgets includes the ubiquitous scrollbar widget
2763 and the less common scale widget. Though these two types of widgets
2764 are generally used for different purposes, they are quite similar in
2765 function and implementation. All range widgets share a set of common
2766 graphic elements, each of which has its own X window and receives
2767 events. They all contain a "trough" and a "slider" (what is sometimes
2768 called a "thumbwheel" in other GUI environments). Dragging the slider
2769 with the pointer moves it back and forth within the trough, while
2770 clicking in the trough advances the slider towards the location of the
2771 click, either completely, or by a designated amount, depending on
2772 which mouse button is used.</para>
2773
2774 <para>As mentioned in <link linkend="ch-Adjustments">Adjustments</link> above,
2775 all range widgets are associated with an adjustment object, from which
2776 they calculate the length of the slider and its position within the
2777 trough. When the user manipulates the slider, the range widget will
2778 change the value of the adjustment.</para>
2779
2780 <!-- ----------------------------------------------------------------- -->
2781 <sect1 id="sec-ScrollbarWidgets">
2782 <title>Scrollbar Widgets</title>
2783
2784 <para>These are your standard, run-of-the-mill scrollbars. These should be
2785 used only for scrolling some other widget, such as a list, a text box,
2786 or a viewport (and it's generally easier to use the scrolled window
2787 widget in most cases).  For other purposes, you should use scale
2788 widgets, as they are friendlier and more featureful.</para>
2789
2790 <para>There are separate types for horizontal and vertical scrollbars.
2791 There really isn't much to say about these. You create them with the
2792 following functions:</para>
2793
2794 <programlisting role="C">
2795 GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );
2796
2797 GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );
2798 </programlisting>
2799
2800 <para>and that's about it (if you don't believe me, look in the header
2801 files!).  The <literal>adjustment</literal> argument can either be a pointer to an
2802 existing Adjustment, or NULL, in which case one will be created for
2803 you. Specifying NULL might actually be useful in this case, if you
2804 wish to pass the newly-created adjustment to the constructor function
2805 of some other widget which will configure it for you, such as a text
2806 widget.</para>
2807
2808 </sect1>
2809
2810 <!-- ----------------------------------------------------------------- -->
2811 <sect1 id="sec-ScaleWidgets">
2812 <title>Scale Widgets</title>
2813
2814 <para>Scale widgets are used to allow the user to visually select and
2815 manipulate a value within a specific range. You might want to use a
2816 scale widget, for example, to adjust the magnification level on a
2817 zoomed preview of a picture, or to control the brightness of a color,
2818 or to specify the number of minutes of inactivity before a screensaver
2819 takes over the screen.</para>
2820
2821 <!-- ----------------------------------------------------------------- -->
2822 <sect2>
2823 <title>Creating a Scale Widget</title>
2824
2825 <para>As with scrollbars, there are separate widget types for horizontal and
2826 vertical scale widgets. (Most programmers seem to favour horizontal
2827 scale widgets.) Since they work essentially the same way, there's no
2828 need to treat them separately here. The following functions create vertical and 
2829 horizontal scale widgets, respectively:</para>
2830
2831 <programlisting role="C">
2832 GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );
2833
2834 GtkWidget *gtk_vscale_new_with_range( gdouble min,
2835                                       gdouble max,
2836                                       gdouble step );
2837
2838 GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );
2839
2840 GtkWidget *gtk_hscale_new_with_range( gdouble min,
2841                                       gdouble max,
2842                                       gdouble step );
2843 </programlisting>
2844
2845 <para>The <literal>adjustment</literal> argument can either be an adjustment which has
2846 already been created with gtk_adjustment_new(), or NULL, in
2847 which case, an anonymous Adjustment is created with all of its
2848 values set to <literal>0.0</literal> (which isn't very useful in this case). 
2849 In order to avoid confusing yourself, you probably want to create your
2850 adjustment with a <literal>page_size</literal> of <literal>0.0</literal> so 
2851 that its <literal>upper</literal> value actually corresponds to the highest 
2852 value the user can select. The _new_with_range()�variants take care of creating
2853 a suitable adjustment. (If you're <emphasis>already</emphasis> thoroughly
2854 confused, read the section on <link linkend="ch-Adjustments">Adjustments</link> 
2855 again for an explanation of what exactly adjustments do and how to create and 
2856 manipulate them.)</para>
2857
2858 </sect2>
2859
2860 <!-- ----------------------------------------------------------------- -->
2861 <sect2>
2862 <title>Functions and Signals (well, functions, at least)</title>
2863
2864 <para>Scale widgets can display their current value as a number beside the
2865 trough. The default behaviour is to show the value, but you can change
2866 this with this function:</para>
2867
2868 <programlisting role="C">
2869 void gtk_scale_set_draw_value( GtkScale *scale,
2870                                gboolean draw_value );
2871 </programlisting>
2872
2873 <para>As you might have guessed, <literal>draw_value</literal> is either <literal>TRUE</literal> or
2874 <literal>FALSE</literal>, with predictable consequences for either one.</para>
2875
2876 <para>The value displayed by a scale widget is rounded to one decimal point
2877 by default, as is the <literal>value</literal> field in its Adjustment. You can
2878 change this with:</para>
2879
2880 <programlisting role="C">
2881 void gtk_scale_set_digits( GtkScale *scale,
2882                             gint     digits );
2883 </programlisting>
2884
2885 <para>where <literal>digits</literal> is the number of decimal places you want. You can
2886 set <literal>digits</literal> to anything you like, but no more than 13 decimal
2887 places will actually be drawn on screen.</para>
2888
2889 <para>Finally, the value can be drawn in different positions
2890 relative to the trough:</para>
2891
2892 <programlisting role="C">
2893 void gtk_scale_set_value_pos( GtkScale        *scale,
2894                               GtkPositionType  pos );
2895 </programlisting>
2896
2897 <para>The argument <literal>pos</literal> is of type <literal>GtkPositionType</literal>,
2898 which can take one of the following values:</para>
2899
2900 <programlisting role="C">
2901   GTK_POS_LEFT
2902   GTK_POS_RIGHT
2903   GTK_POS_TOP
2904   GTK_POS_BOTTOM
2905 </programlisting>
2906
2907 <para>If you position the value on the "side" of the trough (e.g., on the
2908 top or bottom of a horizontal scale widget), then it will follow the
2909 slider up and down the trough.</para>
2910
2911 <para>All the preceding functions are defined in
2912 <literal>&lt;gtk/gtkscale.h&gt;</literal>. The header files for all GTK widgets
2913 are automatically included when you include
2914 <literal>&lt;gtk/gtk.h&gt;</literal>. But you should look over the header files
2915 of all widgets that interest you, in order to learn more about their functions
2916 and features.</para>
2917
2918 </sect2>
2919 </sect1>
2920
2921 <!-- ----------------------------------------------------------------- -->
2922 <sect1 id="sec-CommonRangeFunctions">
2923 <title>Common Range Functions</title>
2924
2925 <para>The Range widget class is fairly complicated internally, but, like
2926 all the "base class" widgets, most of its complexity is only
2927 interesting if you want to hack on it. Also, almost all of the
2928 functions and signals it defines are only really used in writing
2929 derived widgets. There are, however, a few useful functions that are
2930 defined in <literal>&lt;gtk/gtkrange.h&gt;</literal> and will work on all range
2931 widgets.</para>
2932
2933 <!-- ----------------------------------------------------------------- -->
2934 <sect2>
2935 <title>Setting the Update Policy</title>
2936
2937 <para>The "update policy" of a range widget defines at what points during
2938 user interaction it will change the <literal>value</literal> field of its
2939 Adjustment and emit the "value_changed" signal on this
2940 Adjustment. The update policies, defined in
2941 <literal>&lt;gtk/gtkenums.h&gt;</literal> as type <literal>enum GtkUpdateType</literal>,
2942 are:</para>
2943
2944 <variablelist>
2945 <varlistentry>
2946 <term><literal>GTK_UPDATE_CONTINUOUS</literal></term>
2947 <listitem><para>This is the default. The
2948 "value_changed" signal is emitted continuously, i.e., whenever the
2949 slider is moved by even the tiniest amount.</para>
2950 </listitem>
2951 </varlistentry>
2952 <varlistentry>
2953 <term><literal>GTK_UPDATE_DISCONTINUOUS</literal></term>
2954 <listitem><para>The "value_changed" signal is
2955 only emitted once the slider has stopped moving and the user has
2956 released the mouse button.</para>
2957 </listitem>
2958 </varlistentry>
2959 <varlistentry>
2960 <term><literal>GTK_UPDATE_DELAYED</literal></term>
2961 <listitem><para>The "value_changed" signal is emitted
2962 when the user releases the mouse button, or if the slider stops moving
2963 for a short period of time.</para>
2964 </listitem>
2965 </varlistentry>
2966 </variablelist>
2967
2968 <para>The update policy of a range widget can be set by casting it using the
2969 <literal>GTK_RANGE(widget)</literal> macro and passing it to this function:</para>
2970
2971 <programlisting role="C">
2972 void gtk_range_set_update_policy( GtkRange      *range,
2973                                   GtkUpdateType  policy);
2974 </programlisting>
2975
2976 </sect2>
2977
2978 <!-- ----------------------------------------------------------------- -->
2979 <sect2>
2980 <title>Getting and Setting Adjustments</title>
2981
2982 <para>Getting and setting the adjustment for a range widget "on the fly" is
2983 done, predictably, with:</para>
2984
2985 <programlisting role="C">
2986 GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );
2987
2988 void gtk_range_set_adjustment( GtkRange      *range,
2989                                GtkAdjustment *adjustment );
2990 </programlisting>
2991
2992 <para><literal>gtk_range_get_adjustment()</literal> returns a pointer to the adjustment to
2993 which <literal>range</literal> is connected.</para>
2994
2995 <para><literal>gtk_range_set_adjustment()</literal> does absolutely nothing if you pass it
2996 the adjustment that <literal>range</literal> is already using, regardless of whether
2997 you changed any of its fields or not. If you pass it a new
2998 Adjustment, it will unreference the old one if it exists (possibly
2999 destroying it), connect the appropriate signals to the new one, and
3000 call the private function <literal>gtk_range_adjustment_changed()</literal>, which
3001 will (or at least, is supposed to...) recalculate the size and/or
3002 position of the slider and redraw if necessary. As mentioned in the
3003 section on adjustments, if you wish to reuse the same Adjustment,
3004 when you modify its values directly, you should emit the "changed"
3005 signal on it, like this:</para>
3006
3007 <programlisting role="C">
3008 g_signal_emit_by_name (adjustment, "changed");
3009 </programlisting>
3010
3011 </sect2>
3012 </sect1>
3013
3014 <!-- ----------------------------------------------------------------- -->
3015 <sect1 id="sec-KeyAndMouseBindings">
3016 <title>Key and Mouse bindings</title>
3017
3018 <para>All of the GTK range widgets react to mouse clicks in more or less
3019 the same way. Clicking button-1 in the trough will cause its
3020 adjustment's <literal>page_increment</literal> to be added or subtracted from its
3021 <literal>value</literal>, and the slider to be moved accordingly. Clicking mouse
3022 button-2 in the trough will jump the slider to the point at which the
3023 button was clicked. Clicking button-3 in the trough of a range or any button on 
3024 a scrollbar's arrows will cause its adjustment's value to change by
3025 <literal>step_increment</literal> at a time.</para>
3026
3027 <para>Scrollbars are not focusable, thus have no key bindings. The key bindings
3028 for the other range widgets (which are, of course, only active when the widget 
3029 has focus) are do <emphasis>not</emphasis> differentiate between horizontal and 
3030 vertical range widgets.</para>
3031
3032 <para>All range widgets can be operated with the left, right, up and down arrow
3033 keys, as well as with the <literal>Page Up</literal> and <literal>Page Down</literal> 
3034 keys. The arrows move the slider up and down by <literal>step_increment</literal>, while
3035 <literal>Page Up</literal> and <literal>Page Down</literal> move it by 
3036 <literal>page_increment</literal>.</para>
3037
3038 <para>The user can also move the slider all the way to one end or the other
3039 of the trough using the keyboard. This is done with the <literal>Home</literal> 
3040 and <literal>End</literal> keys.</para>
3041
3042 </sect1>
3043
3044 <!-- ----------------------------------------------------------------- -->
3045 <sect1 id="sec-RangeWidgetsExample">
3046 <title>Example</title>
3047
3048 <para>This example is a somewhat modified version of the "range controls"
3049 test from <filename>testgtk.c</filename>. It basically puts up a window with three
3050 range widgets all connected to the same adjustment, and a couple of
3051 controls for adjusting some of the parameters mentioned above and in
3052 the section on adjustments, so you can see how they affect the way
3053 these widgets work for the user.</para>
3054
3055 <para>
3056 <inlinemediaobject>
3057 <imageobject>
3058 <imagedata fileref="images/rangewidgets.png" format="png">
3059 </imageobject>
3060 </inlinemediaobject>
3061 </para>
3062
3063 <programlisting role="C">
3064 <!-- example-start rangewidgets rangewidgets.c -->
3065
3066 #include &lt;gtk/gtk.h&gt;
3067
3068 GtkWidget *hscale, *vscale;
3069
3070 static void cb_pos_menu_select( GtkWidget       *item,
3071                                 GtkPositionType  pos )
3072 {
3073     /* Set the value position on both scale widgets */
3074     gtk_scale_set_value_pos (GTK_SCALE (hscale), pos);
3075     gtk_scale_set_value_pos (GTK_SCALE (vscale), pos);
3076 }
3077
3078 static void cb_update_menu_select( GtkWidget     *item,
3079                                    GtkUpdateType  policy )
3080 {
3081     /* Set the update policy for both scale widgets */
3082     gtk_range_set_update_policy (GTK_RANGE (hscale), policy);
3083     gtk_range_set_update_policy (GTK_RANGE (vscale), policy);
3084 }
3085
3086 static void cb_digits_scale( GtkAdjustment *adj )
3087 {
3088     /* Set the number of decimal places to which adj->value is rounded */
3089     gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
3090     gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
3091 }
3092
3093 static void cb_page_size( GtkAdjustment *get,
3094                           GtkAdjustment *set )
3095 {
3096     /* Set the page size and page increment size of the sample
3097      * adjustment to the value specified by the "Page Size" scale */
3098     set->page_size = get->value;
3099     set->page_increment = get->value;
3100
3101     /* This sets the adjustment and makes it emit the "changed" signal to 
3102        reconfigure all the widgets that are attached to this signal.  */
3103     gtk_adjustment_set_value (set, CLAMP (set->value,
3104                                           set->lower,
3105                                           (set->upper - set->page_size)));
3106     g_signal_emit_by_name(set, "changed");
3107 }
3108
3109 static void cb_draw_value( GtkToggleButton *button )
3110 {
3111     /* Turn the value display on the scale widgets off or on depending
3112      *  on the state of the checkbutton */
3113     gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active);
3114     gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active);  
3115 }
3116
3117 /* Convenience functions */
3118
3119 static GtkWidget *make_menu_item ( gchar     *name,
3120                                    GCallback  callback,
3121                                    gpointer   data )
3122 {
3123     GtkWidget *item;
3124   
3125     item = gtk_menu_item_new_with_label (name);
3126     g_signal_connect (item, "activate",
3127                       callback, (gpointer) data);
3128     gtk_widget_show (item);
3129
3130     return item;
3131 }
3132
3133 static void scale_set_default_values( GtkScale *scale )
3134 {
3135     gtk_range_set_update_policy (GTK_RANGE (scale),
3136                                  GTK_UPDATE_CONTINUOUS);
3137     gtk_scale_set_digits (scale, 1);
3138     gtk_scale_set_value_pos (scale, GTK_POS_TOP);
3139     gtk_scale_set_draw_value (scale, TRUE);
3140 }
3141
3142 /* makes the sample window */
3143
3144 static void create_range_controls( void )
3145 {
3146     GtkWidget *window;
3147     GtkWidget *box1, *box2, *box3;
3148     GtkWidget *button;
3149     GtkWidget *scrollbar;
3150     GtkWidget *separator;
3151     GtkWidget *opt, *menu, *item;
3152     GtkWidget *label;
3153     GtkWidget *scale;
3154     GtkAdjustment *adj1, *adj2;
3155
3156     /* Standard window-creating stuff */
3157     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3158     g_signal_connect (window, "destroy",
3159                       G_CALLBACK (gtk_main_quit),
3160                       NULL);
3161     gtk_window_set_title (GTK_WINDOW (window), "range controls");
3162
3163     box1 = gtk_vbox_new (FALSE, 0);
3164     gtk_container_add (GTK_CONTAINER (window), box1);
3165     gtk_widget_show (box1);
3166
3167     box2 = gtk_hbox_new (FALSE, 10);
3168     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3169     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3170     gtk_widget_show (box2);
3171
3172     /* value, lower, upper, step_increment, page_increment, page_size */
3173     /* Note that the page_size value only makes a difference for
3174      * scrollbar widgets, and the highest value you'll get is actually
3175      * (upper - page_size). */
3176     adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
3177   
3178     vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1));
3179     scale_set_default_values (GTK_SCALE (vscale));
3180     gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0);
3181     gtk_widget_show (vscale);
3182
3183     box3 = gtk_vbox_new (FALSE, 10);
3184     gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0);
3185     gtk_widget_show (box3);
3186
3187     /* Reuse the same adjustment */
3188     hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1));
3189     gtk_widget_set_size_request (GTK_WIDGET (hscale), 200, -1);
3190     scale_set_default_values (GTK_SCALE (hscale));
3191     gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0);
3192     gtk_widget_show (hscale);
3193
3194     /* Reuse the same adjustment again */
3195     scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1));
3196     /* Notice how this causes the scales to always be updated
3197      * continuously when the scrollbar is moved */
3198     gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
3199                                  GTK_UPDATE_CONTINUOUS);
3200     gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0);
3201     gtk_widget_show (scrollbar);
3202
3203     box2 = gtk_hbox_new (FALSE, 10);
3204     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3205     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3206     gtk_widget_show (box2);
3207
3208     /* A checkbutton to control whether the value is displayed or not */
3209     button = gtk_check_button_new_with_label("Display value on scale widgets");
3210     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
3211     g_signal_connect (button, "toggled",
3212                       G_CALLBACK (cb_draw_value), NULL);
3213     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3214     gtk_widget_show (button);
3215   
3216     box2 = gtk_hbox_new (FALSE, 10);
3217     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3218
3219     /* An option menu to change the position of the value */
3220     label = gtk_label_new ("Scale Value Position:");
3221     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3222     gtk_widget_show (label);
3223   
3224     opt = gtk_option_menu_new ();
3225     menu = gtk_menu_new ();
3226
3227     item = make_menu_item ("Top",
3228                            G_CALLBACK (cb_pos_menu_select),
3229                            GINT_TO_POINTER (GTK_POS_TOP));
3230     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3231   
3232     item = make_menu_item ("Bottom", G_CALLBACK (cb_pos_menu_select), 
3233                            GINT_TO_POINTER (GTK_POS_BOTTOM));
3234     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3235   
3236     item = make_menu_item ("Left", G_CALLBACK (cb_pos_menu_select),
3237                            GINT_TO_POINTER (GTK_POS_LEFT));
3238     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3239   
3240     item = make_menu_item ("Right", G_CALLBACK (cb_pos_menu_select),
3241                            GINT_TO_POINTER (GTK_POS_RIGHT));
3242     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3243   
3244     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
3245     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
3246     gtk_widget_show (opt);
3247
3248     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3249     gtk_widget_show (box2);
3250
3251     box2 = gtk_hbox_new (FALSE, 10);
3252     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3253
3254     /* Yet another option menu, this time for the update policy of the
3255      * scale widgets */
3256     label = gtk_label_new ("Scale Update Policy:");
3257     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3258     gtk_widget_show (label);
3259   
3260     opt = gtk_option_menu_new ();
3261     menu = gtk_menu_new ();
3262   
3263     item = make_menu_item ("Continuous",
3264                            G_CALLBACK (cb_update_menu_select),
3265                            GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS));
3266     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3267   
3268     item = make_menu_item ("Discontinuous",
3269                            G_CALLBACK (cb_update_menu_select),
3270                            GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS));
3271     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3272   
3273     item = make_menu_item ("Delayed",
3274                            G_CALLBACK (cb_update_menu_select),
3275                            GINT_TO_POINTER (GTK_UPDATE_DELAYED));
3276     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
3277   
3278     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
3279     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
3280     gtk_widget_show (opt);
3281   
3282     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3283     gtk_widget_show (box2);
3284
3285     box2 = gtk_hbox_new (FALSE, 10);
3286     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3287   
3288     /* An HScale widget for adjusting the number of digits on the
3289      * sample scales. */
3290     label = gtk_label_new ("Scale Digits:");
3291     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3292     gtk_widget_show (label);
3293
3294     adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0);
3295     g_signal_connect (adj2, "value_changed",
3296                       G_CALLBACK (cb_digits_scale), NULL);
3297     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
3298     gtk_scale_set_digits (GTK_SCALE (scale), 0);
3299     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
3300     gtk_widget_show (scale);
3301
3302     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3303     gtk_widget_show (box2);
3304   
3305     box2 = gtk_hbox_new (FALSE, 10);
3306     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3307   
3308     /* And, one last HScale widget for adjusting the page size of the
3309      * scrollbar. */
3310     label = gtk_label_new ("Scrollbar Page Size:");
3311     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3312     gtk_widget_show (label);
3313
3314     adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0);
3315     g_signal_connect (adj2, "value_changed",
3316                       G_CALLBACK (cb_page_size), (gpointer) adj1);
3317     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
3318     gtk_scale_set_digits (GTK_SCALE (scale), 0);
3319     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
3320     gtk_widget_show (scale);
3321
3322     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3323     gtk_widget_show (box2);
3324
3325     separator = gtk_hseparator_new ();
3326     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3327     gtk_widget_show (separator);
3328
3329     box2 = gtk_vbox_new (FALSE, 10);
3330     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3331     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3332     gtk_widget_show (box2);
3333
3334     button = gtk_button_new_with_label ("Quit");
3335     g_signal_connect_swapped (button, "clicked",
3336                               G_CALLBACK (gtk_main_quit),
3337                               NULL);
3338     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3339     gtk_widget_set_can_default (button, TRUE);
3340     gtk_widget_grab_default (button);
3341     gtk_widget_show (button);
3342
3343     gtk_widget_show (window);
3344 }
3345
3346 int main( int   argc,
3347           char *argv[] )
3348 {
3349     gtk_init (&amp;argc, &amp;argv);
3350
3351     create_range_controls ();
3352
3353     gtk_main ();
3354
3355     return 0;
3356 }
3357
3358 <!-- example-end -->
3359 </programlisting>
3360
3361 <para>You will notice that the program does not call g_signal_connect()
3362 for the "delete-event", but only for the "destroy" signal. This will
3363 still perform the desired function, because an unhandled
3364 "delete-event" will result in a "destroy" signal being given to the
3365 window.</para>
3366
3367 </sect1>
3368 </chapter>
3369
3370 <!-- ***************************************************************** -->
3371 <chapter id="ch-MiscWidgets">
3372 <title>Miscellaneous Widgets</title>
3373
3374 <!-- ----------------------------------------------------------------- -->
3375 <sect1 id="sec-Labels">
3376 <title>Labels</title>
3377
3378 <para>Labels are used a lot in GTK, and are relatively simple. Labels emit
3379 no signals as they do not have an associated X window. If you need to
3380 catch signals, or do clipping, place it inside a <link linkend="sec-EventBox">
3381 EventBox</link> widget or a Button widget.</para>
3382
3383 <para>To create a new label, use:</para>
3384
3385 <programlisting role="C">
3386 GtkWidget *gtk_label_new( const char *str );
3387
3388 GtkWidget *gtk_label_new_with_mnemonic( const char *str );
3389 </programlisting>
3390
3391 <para>The sole argument is the string you wish the label to display.</para>
3392
3393 <para>To change the label's text after creation, use the function:</para>
3394
3395 <programlisting role="C">
3396 void gtk_label_set_text( GtkLabel   *label,
3397                          const char *str );
3398 </programlisting>
3399
3400 <para>The first argument is the label you created previously (cast
3401 using the <literal>GTK_LABEL()</literal> macro), and the second is the new string.</para>
3402
3403 <para>The space needed for the new string will be automatically adjusted if
3404 needed. You can produce multi-line labels by putting line breaks in
3405 the label string.</para>
3406
3407 <para>To retrieve the current string, use:</para>
3408
3409 <programlisting role="C">
3410 const gchar* gtk_label_get_text( GtkLabel  *label );                    
3411 </programlisting>
3412
3413 <para>Do not free the returned string, as it is used internally by GTK.</para>
3414
3415 <para>The label text can be justified using:</para>
3416
3417 <programlisting role="C">
3418 void gtk_label_set_justify( GtkLabel         *label,
3419                             GtkJustification  jtype );
3420 </programlisting>
3421
3422 <para>Values for <literal>jtype</literal> are:</para>
3423 <programlisting role="C">
3424   GTK_JUSTIFY_LEFT
3425   GTK_JUSTIFY_RIGHT
3426   GTK_JUSTIFY_CENTER (the default)
3427   GTK_JUSTIFY_FILL
3428 </programlisting>
3429
3430 <para>The label widget is also capable of line wrapping the text
3431 automatically. This can be activated using:</para>
3432
3433 <programlisting role="C">
3434 void gtk_label_set_line_wrap (GtkLabel *label,
3435                               gboolean  wrap);
3436 </programlisting>
3437
3438 <para>The <literal>wrap</literal> argument takes a TRUE or FALSE value.</para>
3439
3440 <para>If you want your label underlined, then you can set a pattern on the
3441 label:</para>
3442
3443 <programlisting role="C">
3444 void       gtk_label_set_pattern   (GtkLabel          *label,
3445                                     const gchar       *pattern);
3446 </programlisting>
3447
3448 <para>The pattern argument indicates how the underlining should look. It
3449 consists of a string of underscore and space characters. An underscore
3450 indicates that the corresponding character in the label should be
3451 underlined. For example, the string <literal>"__     __"</literal> would underline the
3452 first two characters and eight and ninth characters.</para>
3453
3454 <note><para>If you simply want to have an underlined accelerator ("mnemonic") 
3455 in your label, you should use gtk_label_new_with_mnemonic() or 
3456 gtk_label_set_text_with_mnemonic(), not gtk_label_set_pattern().</para>
3457 </note>
3458
3459 <para>Below is a short example to illustrate these functions. This example
3460 makes use of the Frame widget to better demonstrate the label
3461 styles. You can ignore this for now as the <link linkend="sec-Frames">Frame</link> 
3462 widget is explained later on.</para>
3463
3464 <para>In GTK+ 2.0, label texts can contain markup for font and other text attribute 
3465 changes, and labels may be selectable (for copy-and-paste). These advanced features
3466 won't be explained here.</para>
3467
3468 <para>
3469 <inlinemediaobject>
3470 <imageobject>
3471 <imagedata fileref="images/label.png" format="png">
3472 </imageobject>
3473 </inlinemediaobject>
3474 </para>
3475
3476 <programlisting role="C">
3477 <!-- example-start label label.c -->
3478
3479 #include &lt;gtk/gtk.h&gt;
3480
3481 int main( int   argc,
3482           char *argv[] )
3483 {
3484   static GtkWidget *window = NULL;
3485   GtkWidget *hbox;
3486   GtkWidget *vbox;
3487   GtkWidget *frame;
3488   GtkWidget *label;
3489
3490   /* Initialise GTK */
3491   gtk_init (&amp;argc, &amp;argv);
3492
3493   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3494   g_signal_connect (window, "destroy",
3495                     G_CALLBACK (gtk_main_quit),
3496                     NULL);
3497
3498   gtk_window_set_title (GTK_WINDOW (window), "Label");
3499   vbox = gtk_vbox_new (FALSE, 5);
3500   hbox = gtk_hbox_new (FALSE, 5);
3501   gtk_container_add (GTK_CONTAINER (window), hbox);
3502   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3503   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3504   
3505   frame = gtk_frame_new ("Normal Label");
3506   label = gtk_label_new ("This is a Normal label");
3507   gtk_container_add (GTK_CONTAINER (frame), label);
3508   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3509   
3510   frame = gtk_frame_new ("Multi-line Label");
3511   label = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \
3512                          "Third line");
3513   gtk_container_add (GTK_CONTAINER (frame), label);
3514   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3515   
3516   frame = gtk_frame_new ("Left Justified Label");
3517   label = gtk_label_new ("This is a Left-Justified\n" \
3518                          "Multi-line label.\nThird      line");
3519   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3520   gtk_container_add (GTK_CONTAINER (frame), label);
3521   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3522   
3523   frame = gtk_frame_new ("Right Justified Label");
3524   label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \
3525                          "Fourth line, (j/k)");
3526   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3527   gtk_container_add (GTK_CONTAINER (frame), label);
3528   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3529
3530   vbox = gtk_vbox_new (FALSE, 5);
3531   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3532   frame = gtk_frame_new ("Line wrapped label");
3533   label = gtk_label_new ("This is an example of a line-wrapped label.  It " \
3534                          "should not be taking up the entire             " /* big space to test spacing */\
3535                          "width allocated to it, but automatically " \
3536                          "wraps the words to fit.  " \
3537                          "The time has come, for all good men, to come to " \
3538                          "the aid of their party.  " \
3539                          "The sixth sheik's six sheep's sick.\n" \
3540                          "     It supports multiple paragraphs correctly, " \
3541                          "and  correctly   adds "\
3542                          "many          extra  spaces. ");
3543   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3544   gtk_container_add (GTK_CONTAINER (frame), label);
3545   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3546   
3547   frame = gtk_frame_new ("Filled, wrapped label");
3548   label = gtk_label_new ("This is an example of a line-wrapped, filled label.  " \
3549                          "It should be taking "\
3550                          "up the entire              width allocated to it.  " \
3551                          "Here is a sentence to prove "\
3552                          "my point.  Here is another sentence. "\
3553                          "Here comes the sun, do de do de do.\n"\
3554                          "    This is a new paragraph.\n"\
3555                          "    This is another newer, longer, better " \
3556                          "paragraph.  It is coming to an end, "\
3557                          "unfortunately.");
3558   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3559   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3560   gtk_container_add (GTK_CONTAINER (frame), label);
3561   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3562   
3563   frame = gtk_frame_new ("Underlined label");
3564   label = gtk_label_new ("This label is underlined!\n"
3565                          "This one is underlined in quite a funky fashion");
3566   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3567   gtk_label_set_pattern (GTK_LABEL (label),
3568                          "_________________________ _ _________ _ ______     __ _______ ___");
3569   gtk_container_add (GTK_CONTAINER (frame), label);
3570   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3571   
3572   gtk_widget_show_all (window);
3573
3574   gtk_main ();
3575   
3576   return 0;
3577 }
3578 <!-- example-end -->
3579 </programlisting>
3580
3581 </sect1>
3582
3583 <!-- ----------------------------------------------------------------- -->
3584 <sect1 id="sec-Arrows">
3585 <title>Arrows</title>
3586
3587 <para>The Arrow widget draws an arrowhead, facing in a number of possible
3588 directions and having a number of possible styles. It can be very
3589 useful when placed on a button in many applications. Like the Label
3590 widget, it emits no signals.</para>
3591
3592 <para>There are only two functions for manipulating an Arrow widget:</para>
3593
3594 <programlisting role="C">
3595 GtkWidget *gtk_arrow_new( GtkArrowType   arrow_type,
3596                           GtkShadowType  shadow_type );
3597
3598 void gtk_arrow_set( GtkArrow      *arrow,
3599                     GtkArrowType   arrow_type,
3600                     GtkShadowType  shadow_type );
3601 </programlisting>
3602
3603 <para>The first creates a new arrow widget with the indicated type and
3604 appearance. The second allows these values to be altered
3605 retrospectively. The <literal>arrow_type</literal> argument may take one of the
3606 following values:</para>
3607
3608 <programlisting role="C">
3609   GTK_ARROW_UP
3610   GTK_ARROW_DOWN
3611   GTK_ARROW_LEFT
3612   GTK_ARROW_RIGHT
3613 </programlisting>
3614
3615 <para>These values obviously indicate the direction in which the arrow will
3616 point. The <literal>shadow_type</literal> argument may take one of these values:</para>
3617
3618 <programlisting role="C">
3619   GTK_SHADOW_IN
3620   GTK_SHADOW_OUT (the default)
3621   GTK_SHADOW_ETCHED_IN
3622   GTK_SHADOW_ETCHED_OUT
3623 </programlisting>
3624
3625 <para>Here's a brief example to illustrate their use.</para>
3626
3627 <para>
3628 <inlinemediaobject>
3629 <imageobject>
3630 <imagedata fileref="images/arrow.png" format="png">
3631 </imageobject>
3632 </inlinemediaobject>
3633 </para>
3634
3635 <programlisting role="C">
3636 <!-- example-start arrow arrow.c -->
3637
3638 #include &lt;gtk/gtk.h&gt;
3639
3640 /* Create an Arrow widget with the specified parameters
3641  * and pack it into a button */
3642 static GtkWidget *create_arrow_button( GtkArrowType  arrow_type,
3643                                        GtkShadowType shadow_type )
3644 {
3645   GtkWidget *button;
3646   GtkWidget *arrow;
3647
3648   button = gtk_button_new ();
3649   arrow = gtk_arrow_new (arrow_type, shadow_type);
3650
3651   gtk_container_add (GTK_CONTAINER (button), arrow);
3652   
3653   gtk_widget_show (button);
3654   gtk_widget_show (arrow);
3655
3656   return button;
3657 }
3658
3659 int main( int   argc,
3660           char *argv[] )
3661 {
3662   /* GtkWidget is the storage type for widgets */
3663   GtkWidget *window;
3664   GtkWidget *button;
3665   GtkWidget *box;
3666
3667   /* Initialize the toolkit */
3668   gtk_init (&amp;argc, &amp;argv);
3669
3670   /* Create a new window */
3671   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3672
3673   gtk_window_set_title (GTK_WINDOW (window), "Arrow Buttons");
3674
3675   /* It's a good idea to do this for all windows. */
3676   g_signal_connect (window, "destroy",
3677                     G_CALLBACK (gtk_main_quit), NULL);
3678
3679   /* Sets the border width of the window. */
3680   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
3681
3682   /* Create a box to hold the arrows/buttons */
3683   box = gtk_hbox_new (FALSE, 0);
3684   gtk_container_set_border_width (GTK_CONTAINER (box), 2);
3685   gtk_container_add (GTK_CONTAINER (window), box);
3686
3687   /* Pack and show all our widgets */
3688   gtk_widget_show (box);
3689
3690   button = create_arrow_button (GTK_ARROW_UP, GTK_SHADOW_IN);
3691   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3692
3693   button = create_arrow_button (GTK_ARROW_DOWN, GTK_SHADOW_OUT);
3694   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3695   
3696   button = create_arrow_button (GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN);
3697   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3698   
3699   button = create_arrow_button (GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT);
3700   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3701   
3702   gtk_widget_show (window);
3703   
3704   /* Rest in gtk_main and wait for the fun to begin! */
3705   gtk_main ();
3706   
3707   return 0;
3708 }
3709 <!-- example-end -->
3710 </programlisting>
3711
3712 </sect1>
3713
3714 <!-- ----------------------------------------------------------------- -->
3715 <sect1 id="sec-TheTooltipsObject">
3716 <title>The Tooltips Object</title>
3717
3718 <para>These are the little text strings that pop up when you leave your
3719 pointer over a button or other widget for a few seconds. They are easy
3720 to use, so I will just explain them without giving an example. If you
3721 want to see some code, take a look at the <filename>testgtk.c</filename> program
3722 distributed with GTK.</para>
3723
3724 <para>Widgets that do not receive events (widgets that do not have their
3725 own window) will not work with tooltips.</para>
3726
3727 <para>The first call you will use creates a new tooltip. You only need to do
3728 this once for a set of tooltips as the <literal>GtkTooltips</literal> object this
3729 function returns can be used to create multiple tooltips.</para>
3730
3731 <programlisting role="C">
3732 GtkTooltips *gtk_tooltips_new( void );
3733 </programlisting>
3734
3735 <para>Once you have created a new tooltip, and the widget you wish to use it
3736 on, simply use this call to set it:</para>
3737
3738 <programlisting role="C">
3739 void gtk_tooltips_set_tip( GtkTooltips *tooltips,
3740                            GtkWidget   *widget,
3741                            const gchar *tip_text,
3742                            const gchar *tip_private );
3743 </programlisting>
3744
3745 <para>The first argument is the tooltip you've already created, followed by
3746 the widget you wish to have this tooltip pop up for, and the text you
3747 wish it to say. The last argument is a text string that can be used as
3748 an identifier when using GtkTipsQuery to implement context sensitive
3749 help. For now, you can set it to NULL.</para>
3750
3751 <!-- TODO: sort out what how to do the context sensitive help -->
3752
3753 <para>Here's a short example:</para>
3754
3755 <programlisting role="C">
3756 GtkTooltips *tooltips;
3757 GtkWidget *button;
3758 .
3759 .
3760 .
3761 tooltips = gtk_tooltips_new ();
3762 button = gtk_button_new_with_label ("button 1");
3763 .
3764 .
3765 .
3766 gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);
3767 </programlisting>
3768
3769 <para>There are other calls that can be used with tooltips. I will just list
3770 them with a brief description of what they do.</para>
3771
3772 <programlisting role="C">
3773 void gtk_tooltips_enable( GtkTooltips *tooltips );
3774 </programlisting>
3775
3776 <para>Enable a disabled set of tooltips.</para>
3777
3778 <programlisting role="C">
3779 void gtk_tooltips_disable( GtkTooltips *tooltips );
3780 </programlisting>
3781
3782 <para>Disable an enabled set of tooltips.</para>
3783
3784 <para>And that's all the functions associated with tooltips. More than
3785 you'll ever want to know :-)</para>
3786
3787 </sect1>
3788
3789 <!-- ----------------------------------------------------------------- -->
3790 <sect1 id="sec-ProgressBars">
3791 <title>Progress Bars</title>
3792
3793 <para>Progress bars are used to show the status of an operation. They are
3794 pretty easy to use, as you will see with the code below. But first
3795 lets start out with the calls to create a new progress bar.</para>
3796
3797 <programlisting role="C">
3798 GtkWidget *gtk_progress_bar_new( void );
3799 </programlisting>
3800
3801 <para>Now that the progress bar has been created we can use it.</para>
3802
3803 <programlisting role="C">
3804 void gtk_progress_bar_set_fraction ( GtkProgressBar *pbar,
3805                                      gdouble        fraction );
3806 </programlisting>
3807
3808 <para>The first argument is the progress bar you wish to operate on, and the
3809 second argument is the amount "completed", meaning the amount the
3810 progress bar has been filled from 0-100%. This is passed to the
3811 function as a real number ranging from 0 to 1.</para>
3812
3813 <para>GTK v1.2 has added new functionality to the progress bar that enables
3814 it to display its value in different ways, and to inform the user of
3815 its current value and its range.</para>
3816
3817 <para>A progress bar may be set to one of a number of orientations using the
3818 function</para>
3819
3820 <programlisting role="C">
3821 void gtk_progress_bar_set_orientation( GtkProgressBar *pbar,
3822                                        GtkProgressBarOrientation orientation );
3823 </programlisting>
3824
3825 <para>The <literal>orientation</literal> argument may take one of the following
3826 values to indicate the direction in which the progress bar moves:</para>
3827
3828 <programlisting role="C">
3829   GTK_PROGRESS_LEFT_TO_RIGHT
3830   GTK_PROGRESS_RIGHT_TO_LEFT
3831   GTK_PROGRESS_BOTTOM_TO_TOP
3832   GTK_PROGRESS_TOP_TO_BOTTOM
3833 </programlisting>
3834
3835 <para>As well as indicating the amount of progress that has occured, the
3836 progress bar may be set to just indicate that there is some activity. 
3837 This can be useful in situations where progress cannot be measured against 
3838 a value range. The following function indicates that some progress has been 
3839 made.</para>
3840
3841 <programlisting role="C">
3842 void gtk_progress_bar_pulse ( GtkProgressBar *progress );
3843 </programlisting>
3844
3845 <para>The step size of the activity indicator is set using the following 
3846 function.</para>
3847
3848 <programlisting role="C">
3849 void gtk_progress_bar_set_pulse_step( GtkProgressBar *pbar,
3850                                       gdouble         fraction );
3851 </programlisting>
3852
3853 <para>When not in activity mode, the progress bar can also display a
3854 configurable text string within its trough, using the following
3855 function.</para>
3856
3857 <programlisting role="C">
3858 void gtk_progress_bar_set_text( GtkProgressBar *progress,
3859                                 const gchar    *text );
3860 </programlisting>
3861
3862 <note><para>Note that gtk_progress_set_text() doesn't support the printf()-like formatting
3863 of the GTK+ 1.2 Progressbar.</para></note>
3864
3865 <para>You can turn off the display of the string by calling gtk_progess_bar_set_text()
3866 again with NULL as second argument.</para>
3867
3868 <para>The current text setting of a progressbar can be retrieved with the 
3869 following function. Do not free the returned string.</para>
3870
3871 <programlisting role="C">
3872 const gchar *gtk_progress_bar_get_text( GtkProgressBar *pbar );
3873 </programlisting>
3874
3875 <para>Progress Bars are usually used with timeouts or other such functions
3876 (see section on <link linkend="ch-Timeouts">Timeouts, I/O and Idle Functions</link>) 
3877 to give the illusion of multitasking. All will employ the
3878 gtk_progress_bar_set_fraction() or gtk_progress_bar_pulse() functions in the 
3879 same manner.</para>
3880
3881 <para>Here is an example of the progress bar, updated using timeouts. This
3882 code also shows you how to reset the Progress Bar.</para>
3883
3884 <para>
3885 <inlinemediaobject>
3886 <imageobject>
3887 <imagedata fileref="images/progressbar.png" format="png">
3888 </imageobject>
3889 </inlinemediaobject>
3890 </para>
3891
3892 <programlisting role="C">
3893 <!-- example-start progressbar progressbar.c -->
3894
3895 #include &lt;gtk/gtk.h&gt;
3896
3897 typedef struct _ProgressData {
3898   GtkWidget *window;
3899   GtkWidget *pbar;
3900   int timer;
3901   gboolean activity_mode;
3902 } ProgressData;
3903
3904 /* Update the value of the progress bar so that we get
3905  * some movement */
3906 static gboolean progress_timeout( gpointer data )
3907 {
3908   ProgressData *pdata = (ProgressData *)data;
3909   gdouble new_val;
3910   
3911   if (pdata-&gt;activity_mode) 
3912     gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata-&gt;pbar));
3913   else 
3914     {
3915       /* Calculate the value of the progress bar using the
3916        * value range set in the adjustment object */
3917       
3918       new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata-&gt;pbar)) + 0.01;
3919       
3920       if (new_val &gt; 1.0)
3921         new_val = 0.0;
3922       
3923       /* Set the new value */
3924       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata-&gt;pbar), new_val);
3925     }
3926   
3927   /* As this is a timeout function, return TRUE so that it
3928    * continues to get called */
3929   return TRUE;
3930
3931
3932 /* Callback that toggles the text display within the progress bar trough */
3933 static void toggle_show_text( GtkWidget    *widget,
3934                               ProgressData *pdata )
3935 {
3936   const gchar *text;
3937   
3938   text = gtk_progress_bar_get_text (GTK_PROGRESS_BAR (pdata-&gt;pbar));
3939   if (text &amp;&amp; *text)
3940     gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata-&gt;pbar), "");
3941   else 
3942     gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata-&gt;pbar), "some text");
3943 }
3944
3945 /* Callback that toggles the activity mode of the progress bar */
3946 static void toggle_activity_mode( GtkWidget    *widget,
3947                                   ProgressData *pdata )
3948 {
3949   pdata-&gt;activity_mode = !pdata-&gt;activity_mode;
3950   if (pdata-&gt;activity_mode) 
3951       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata-&gt;pbar));
3952   else
3953       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata-&gt;pbar), 0.0);
3954 }
3955
3956  
3957 /* Callback that toggles the orientation of the progress bar */
3958 static void toggle_orientation( GtkWidget    *widget,
3959                                 ProgressData *pdata )
3960 {
3961   switch (gtk_progress_bar_get_orientation (GTK_PROGRESS_BAR (pdata-&gt;pbar))) {
3962   case GTK_PROGRESS_LEFT_TO_RIGHT:
3963     gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata-&gt;pbar), 
3964                                       GTK_PROGRESS_RIGHT_TO_LEFT);
3965     break;
3966   case GTK_PROGRESS_RIGHT_TO_LEFT:
3967     gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata-&gt;pbar), 
3968                                       GTK_PROGRESS_LEFT_TO_RIGHT);
3969     break;
3970   default:;
3971     /* do nothing */
3972   }
3973 }
3974
3975  
3976 /* Clean up allocated memory and remove the timer */
3977 static void destroy_progress( GtkWidget    *widget,
3978                               ProgressData *pdata)
3979 {
3980     g_source_remove (pdata-&gt;timer);
3981     pdata-&gt;timer = 0;
3982     pdata-&gt;window = NULL;
3983     g_free (pdata);
3984     gtk_main_quit ();
3985 }
3986
3987 int main( int   argc,
3988           char *argv[])
3989 {
3990     ProgressData *pdata;
3991     GtkWidget *align;
3992     GtkWidget *separator;
3993     GtkWidget *table;
3994     GtkWidget *button;
3995     GtkWidget *check;
3996     GtkWidget *vbox;
3997
3998     gtk_init (&amp;argc, &amp;argv);
3999
4000     /* Allocate memory for the data that is passed to the callbacks */
4001     pdata = g_malloc (sizeof (ProgressData));
4002   
4003     pdata-&gt;window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4004     gtk_window_set_resizable (GTK_WINDOW (pdata-&gt;window), TRUE);
4005
4006     g_signal_connect (pdata-&gt;window, "destroy",
4007                       G_CALLBACK (destroy_progress),
4008                       (gpointer) pdata);
4009     gtk_window_set_title (GTK_WINDOW (pdata-&gt;window), "GtkProgressBar");
4010     gtk_container_set_border_width (GTK_CONTAINER (pdata-&gt;window), 0);
4011
4012     vbox = gtk_vbox_new (FALSE, 5);
4013     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
4014     gtk_container_add (GTK_CONTAINER (pdata-&gt;window), vbox);
4015     gtk_widget_show (vbox);
4016   
4017     /* Create a centering alignment object */
4018     align = gtk_alignment_new (0.5, 0.5, 0, 0);
4019     gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
4020     gtk_widget_show (align);
4021
4022     /* Create the GtkProgressBar */
4023     pdata-&gt;pbar = gtk_progress_bar_new ();
4024     pdata-&gt;activity_mode = FALSE;
4025
4026     gtk_container_add (GTK_CONTAINER (align), pdata-&gt;pbar);
4027     gtk_widget_show (pdata-&gt;pbar);
4028
4029     /* Add a timer callback to update the value of the progress bar */
4030     pdata-&gt;timer = g_timeout_add (100, progress_timeout, pdata);
4031
4032     separator = gtk_hseparator_new ();
4033     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
4034     gtk_widget_show (separator);
4035
4036     /* rows, columns, homogeneous */
4037     table = gtk_table_new (2, 3, FALSE);
4038     gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
4039     gtk_widget_show (table);
4040
4041     /* Add a check button to select displaying of the trough text */
4042     check = gtk_check_button_new_with_label ("Show text");
4043     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
4044                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
4045                       5, 5);
4046     g_signal_connect (check, "clicked",
4047                       G_CALLBACK (toggle_show_text),
4048                       pdata);
4049     gtk_widget_show (check);
4050
4051     /* Add a check button to toggle activity mode */
4052     check = gtk_check_button_new_with_label ("Activity mode");
4053     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
4054                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
4055                       5, 5);
4056     g_signal_connect (check, "clicked",
4057                       G_CALLBACK (toggle_activity_mode),
4058                       pdata);
4059     gtk_widget_show (check);
4060
4061     /* Add a check button to toggle orientation */
4062     check = gtk_check_button_new_with_label ("Right to Left");
4063     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 2, 3,
4064                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
4065                       5, 5);
4066     g_signal_connect (check, "clicked",
4067                       G_CALLBACK (toggle_orientation),
4068                       pdata);
4069     gtk_widget_show (check);
4070
4071     /* Add a button to exit the program */
4072     button = gtk_button_new_with_label ("close");
4073     g_signal_connect_swapped (button, "clicked",
4074                               G_CALLBACK (gtk_widget_destroy),
4075                               pdata-&gt;window);
4076     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
4077
4078     /* This makes it so the button is the default. */
4079     gtk_widget_set_can_default (button, TRUE);
4080
4081     /* This grabs this button to be the default button. Simply hitting
4082      * the "Enter" key will cause this button to activate. */
4083     gtk_widget_grab_default (button);
4084     gtk_widget_show (button);
4085
4086     gtk_widget_show (pdata-&gt;window);
4087
4088     gtk_main ();
4089     
4090     return 0;
4091 }
4092 <!-- example-end -->
4093 </programlisting>
4094
4095 </sect1>
4096
4097 <!-- ----------------------------------------------------------------- -->
4098 <sect1 id="sec-Dialogs">
4099 <title>Dialogs</title>
4100
4101 <para>The Dialog widget is very simple, and is actually just a window with a
4102 few things pre-packed into it for you. The structure for a Dialog is:</para>
4103
4104 <programlisting role="C">
4105 struct GtkDialog
4106 {
4107       GtkWindow window;
4108     
4109       GtkWidget *vbox;
4110       GtkWidget *action_area;
4111 };
4112 </programlisting>
4113
4114 <para>So you see, it simply creates a window, and then packs a vbox into the
4115 top, which contains a separator and then an hbox called the
4116 "action_area".</para>
4117
4118 <para>The Dialog widget can be used for pop-up messages to the user, and
4119 other similar tasks. There are two functions to create a new Dialog.</para>
4120
4121 <programlisting role="C">
4122 GtkWidget *gtk_dialog_new( void );
4123
4124 GtkWidget *gtk_dialog_new_with_buttons( const gchar    *title,
4125                                         GtkWindow      *parent,
4126                                         GtkDialogFlags  flags, 
4127                                         const gchar    *first_button_text,
4128                                         ... );
4129 </programlisting>
4130
4131 <para>The first function will create an empty dialog, and it is now up to you to use
4132  it. You could pack a button in the action_area by doing something like this:</para>
4133
4134 <programlisting role="C">
4135     button = ...
4136     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
4137                         button, TRUE, TRUE, 0);
4138     gtk_widget_show (button);
4139 </programlisting>
4140
4141 <para>And you could add to the vbox area by packing, for instance, a label 
4142 in it, try something like this:</para>
4143
4144 <programlisting role="C">
4145     label = gtk_label_new ("Dialogs are groovy");
4146     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
4147                         label, TRUE, TRUE, 0);
4148     gtk_widget_show (label);
4149 </programlisting>
4150
4151 <para>As an example in using the dialog box, you could put two buttons in
4152 the action_area, a Cancel button and an Ok button, and a label in the
4153 vbox area, asking the user a question or giving an error etc. Then
4154 you could attach a different signal to each of the buttons and perform
4155 the operation the user selects.</para>
4156
4157 <para>If the simple functionality provided by the default vertical and
4158 horizontal boxes in the two areas doesn't give you enough control for
4159 your application, then you can simply pack another layout widget into
4160 the boxes provided. For example, you could pack a table into the
4161 vertical box.</para>
4162
4163 <para>The more complicated _new_with_buttons() variant allows to set one or
4164 more of the following flags.</para>
4165
4166 <variablelist>
4167 <varlistentry>
4168 <term><literal>GTK_DIALOG_MODAL</literal></term>
4169 <listitem><para>make the dialog modal.
4170 </para></listitem>
4171 </varlistentry>
4172 <varlistentry>
4173 <term><literal>GTK_DIALOG_DESTROY_WITH_PARENT</literal></term>
4174 <listitem><para>ensures that the dialog window is destroyed together with the specified
4175 parent.</para></listitem>
4176 </varlistentry>
4177 <varlistentry>
4178 <term><literal>GTK_DIALOG_NO_SEPARATOR</literal></term>
4179 <listitem><para>omits the separator between the vbox and the action_area.
4180 </para></listitem>
4181 </varlistentry>
4182 </variablelist>
4183 </sect1>
4184
4185 <!-- ----------------------------------------------------------------- -->
4186 <sect1 id="sec-Rulers">
4187 <title>Rulers</title>
4188
4189 <para>Ruler widgets are used to indicate the location of the mouse pointer
4190 in a given window. A window can have a vertical ruler spanning across
4191 the height and a horizontal ruler spanning down the width. A small
4192 triangular indicator on the ruler shows the exact location of the
4193 pointer relative to the ruler.</para>
4194
4195 <para>A ruler must first be created. Horizontal and vertical rulers are
4196 created using</para>
4197
4198 <programlisting role="C">
4199 GtkWidget *gtk_hruler_new( void );    /* horizontal ruler */
4200
4201 GtkWidget *gtk_vruler_new( void );    /* vertical ruler   */
4202 </programlisting>
4203
4204 <para>Once a ruler is created, we can define the unit of measurement. Units
4205 of measure for rulers can be <literal>GTK_PIXELS</literal>, <literal>GTK_INCHES</literal> or
4206 <literal>GTK_CENTIMETERS</literal>. This is set using</para>
4207
4208 <programlisting role="C">
4209 void gtk_ruler_set_metric( GtkRuler      *ruler,
4210                            GtkMetricType  metric );
4211 </programlisting>
4212
4213 <para>The default measure is <literal>GTK_PIXELS</literal>.</para>
4214
4215 <programlisting role="C">
4216     gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
4217 </programlisting>
4218
4219 <para>Other important characteristics of a ruler are how to mark the units
4220 of scale and where the position indicator is initially placed. These
4221 are set for a ruler using</para>
4222
4223 <programlisting role="C">
4224 void gtk_ruler_set_range( GtkRuler *ruler,
4225                           gdouble   lower,
4226                           gdouble   upper,
4227                           gdouble   position,
4228                           gdouble   max_size );
4229 </programlisting>
4230
4231 <para>The lower and upper arguments define the extent of the ruler, and
4232 max_size is the largest possible number that will be displayed.
4233 Position defines the initial position of the pointer indicator within
4234 the ruler.</para>
4235
4236 <para>A vertical ruler can span an 800 pixel wide window thus</para>
4237
4238 <programlisting role="C">
4239     gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
4240 </programlisting>
4241
4242 <para>The markings displayed on the ruler will be from 0 to 800, with a
4243 number for every 100 pixels. If instead we wanted the ruler to range
4244 from 7 to 16, we would code</para>
4245
4246 <programlisting role="C">
4247     gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
4248 </programlisting>
4249
4250 <para>The indicator on the ruler is a small triangular mark that indicates
4251 the position of the pointer relative to the ruler. If the ruler is
4252 used to follow the mouse pointer, the motion_notify_event signal
4253 should be connected to the motion_notify_event method of the ruler.
4254 To follow all mouse movements within a window area, we would use</para>
4255
4256 <programlisting role="C">
4257 #define EVENT_METHOD(i, x) GTK_WIDGET_GET_CLASS(i)->x
4258
4259     g_signal_connect_swapped (area, "motion_notify_event",
4260            G_CALLBACK (EVENT_METHOD (ruler, motion_notify_event)),
4261            ruler);
4262 </programlisting>
4263
4264 <para>The following example creates a drawing area with a horizontal ruler
4265 above it and a vertical ruler to the left of it. The size of the
4266 drawing area is 600 pixels wide by 400 pixels high. The horizontal
4267 ruler spans from 7 to 13 with a mark every 100 pixels, while the
4268 vertical ruler spans from 0 to 400 with a mark every 100 pixels.
4269 Placement of the drawing area and the rulers is done using a table.</para>
4270
4271 <para>
4272 <inlinemediaobject>
4273 <imageobject>
4274 <imagedata fileref="images/rulers.png" format="png">
4275 </imageobject>
4276 </inlinemediaobject>
4277 </para>
4278
4279 <programlisting role="C">
4280 <!-- example-start rulers rulers.c -->
4281
4282 #include &lt;gtk/gtk.h&gt;
4283
4284 #define EVENT_METHOD(i, x) GTK_WIDGET_GET_CLASS(i)-&gt;x
4285
4286 #define XSIZE  600
4287 #define YSIZE  400
4288
4289 /* This routine gets control when the close button is clicked */
4290 static gboolean close_application( GtkWidget *widget,
4291                                    GdkEvent  *event,
4292                                    gpointer   data )
4293 {
4294     gtk_main_quit ();
4295     return FALSE;
4296 }
4297
4298 /* The main routine */
4299 int main( int   argc,
4300           char *argv[] ) {
4301     GtkWidget *window, *table, *area, *hrule, *vrule;
4302
4303     /* Initialize GTK and create the main window */
4304     gtk_init (&amp;argc, &amp;argv);
4305
4306     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4307     g_signal_connect (window, "delete-event",
4308                       G_CALLBACK (close_application), NULL);
4309     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
4310
4311     /* Create a table for placing the ruler and the drawing area */
4312     table = gtk_table_new (3, 2, FALSE);
4313     gtk_container_add (GTK_CONTAINER (window), table);
4314
4315     area = gtk_drawing_area_new ();
4316     gtk_widget_set_size_request (GTK_WIDGET (area), XSIZE, YSIZE);
4317     gtk_table_attach (GTK_TABLE (table), area, 1, 2, 1, 2,
4318                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0);
4319     gtk_widget_set_events (area, GDK_POINTER_MOTION_MASK |
4320                                  GDK_POINTER_MOTION_HINT_MASK);
4321
4322     /* The horizontal ruler goes on top. As the mouse moves across the
4323      * drawing area, a motion_notify_event is passed to the
4324      * appropriate event handler for the ruler. */
4325     hrule = gtk_hruler_new ();
4326     gtk_ruler_set_metric (GTK_RULER (hrule), GTK_PIXELS);
4327     gtk_ruler_set_range (GTK_RULER (hrule), 7, 13, 0, 20);
4328     g_signal_connect_swapped (area, "motion_notify_event",
4329                               G_CALLBACK (EVENT_METHOD (hrule, motion_notify_event)),
4330                               hrule);
4331     gtk_table_attach (GTK_TABLE (table), hrule, 1, 2, 0, 1,
4332                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0);
4333     
4334     /* The vertical ruler goes on the left. As the mouse moves across
4335      * the drawing area, a motion_notify_event is passed to the
4336      * appropriate event handler for the ruler. */
4337     vrule = gtk_vruler_new ();
4338     gtk_ruler_set_metric (GTK_RULER (vrule), GTK_PIXELS);
4339     gtk_ruler_set_range (GTK_RULER (vrule), 0, YSIZE, 10, YSIZE );
4340     g_signal_connect_swapped (area, "motion_notify_event",
4341                               G_CALLBACK (EVENT_METHOD (vrule, motion_notify_event)),
4342                               vrule);
4343     gtk_table_attach (GTK_TABLE (table), vrule, 0, 1, 1, 2,
4344                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0);
4345
4346     /* Now show everything */
4347     gtk_widget_show (area);
4348     gtk_widget_show (hrule);
4349     gtk_widget_show (vrule);
4350     gtk_widget_show (table);
4351     gtk_widget_show (window);
4352     gtk_main ();
4353
4354     return 0;
4355 }
4356 <!-- example-end -->
4357 </programlisting>
4358
4359 </sect1>
4360
4361 <!-- ----------------------------------------------------------------- -->
4362 <sect1 id="sec-Statusbars">
4363 <title>Statusbars</title>
4364
4365 <para>Statusbars are simple widgets used to display a text message. They
4366 keep a stack of the messages pushed onto them, so that popping the
4367 current message will re-display the previous text message.</para>
4368
4369 <para>In order to allow different parts of an application to use the same
4370 statusbar to display messages, the statusbar widget issues Context
4371 Identifiers which are used to identify different "users". The message
4372 on top of the stack is the one displayed, no matter what context it is
4373 in. Messages are stacked in last-in-first-out order, not context
4374 identifier order.</para>
4375
4376 <para>A statusbar is created with a call to:</para>
4377
4378 <programlisting role="C">
4379 GtkWidget *gtk_statusbar_new( void );
4380 </programlisting>
4381
4382 <para>A new Context Identifier is requested using a call to the following 
4383 function with a short textual description of the context:</para>
4384
4385 <programlisting role="C">
4386 guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
4387                                     const gchar  *context_description );
4388 </programlisting>
4389
4390 <para>There are three functions that can operate on statusbars:</para>
4391
4392 <programlisting role="C">
4393 guint gtk_statusbar_push( GtkStatusbar *statusbar,
4394                           guint         context_id,
4395                           const gchar  *text );
4396
4397 void gtk_statusbar_pop( GtkStatusbar *statusbar)
4398                         guint         context_id );
4399
4400 void gtk_statusbar_remove( GtkStatusbar *statusbar,
4401                            guint         context_id,
4402                            guint         message_id ); 
4403 </programlisting>
4404
4405 <para>The first, gtk_statusbar_push(), is used to add a new message to the
4406 statusbar.  It returns a Message Identifier, which can be passed later
4407 to the function gtk_statusbar_remove to remove the message with the
4408 given Message and Context Identifiers from the statusbar's stack.</para>
4409
4410 <para>The function gtk_statusbar_pop() removes the message highest in the
4411 stack with the given Context Identifier.</para>
4412
4413 <para>In addition to messages, statusbars may also display a resize grip, which 
4414 can be dragged with the mouse to resize the toplevel window containing the statusbar,
4415 similar to dragging the window frame. The following functions control the display
4416 of the resize grip.</para>
4417
4418 <programlisting role="C">
4419 void     gtk_statusbar_set_has_resize_grip( GtkStatusbar *statusbar,
4420                                             gboolean      setting );
4421
4422 gboolean gtk_statusbar_get_has_resize_grip( GtkStatusbar *statusbar );
4423 </programlisting>
4424
4425 <para>The following example creates a statusbar and two buttons, one for
4426 pushing items onto the statusbar, and one for popping the last item
4427 back off.</para>
4428
4429 <para>
4430 <inlinemediaobject>
4431 <imageobject>
4432 <imagedata fileref="images/statusbar.png" format="png">
4433 </imageobject>
4434 </inlinemediaobject>
4435 </para>
4436
4437 <programlisting role="C">
4438 <!-- example-start statusbar statusbar.c -->
4439
4440 #include &lt;stdlib.h&gt;
4441 #include &lt;gtk/gtk.h&gt;
4442 #include &lt;glib.h&gt;
4443
4444 GtkWidget *status_bar;
4445
4446 static void push_item( GtkWidget *widget,
4447                        gpointer   data )
4448 {
4449   static int count = 1;
4450   gchar *buff;
4451
4452   buff = g_strdup_printf ("Item %d", count++);
4453   gtk_statusbar_push (GTK_STATUSBAR (status_bar), GPOINTER_TO_INT (data), buff);
4454   g_free (buff);
4455 }
4456
4457 static void pop_item( GtkWidget *widget,
4458                       gpointer   data )
4459 {
4460   gtk_statusbar_pop (GTK_STATUSBAR (status_bar), GPOINTER_TO_INT (data));
4461 }
4462
4463 int main( int   argc,
4464           char *argv[] )
4465 {
4466
4467     GtkWidget *window;
4468     GtkWidget *vbox;
4469     GtkWidget *button;
4470
4471     gint context_id;
4472
4473     gtk_init (&amp;argc, &amp;argv);
4474
4475     /* create a new window */
4476     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4477     gtk_widget_set_size_request (GTK_WIDGET (window), 200, 100);
4478     gtk_window_set_title (GTK_WINDOW (window), "GTK Statusbar Example");
4479     g_signal_connect (window, "delete-event",
4480                       G_CALLBACK (exit), NULL);
4481  
4482     vbox = gtk_vbox_new (FALSE, 1);
4483     gtk_container_add (GTK_CONTAINER (window), vbox);
4484     gtk_widget_show (vbox);
4485           
4486     status_bar = gtk_statusbar_new ();      
4487     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
4488     gtk_widget_show (status_bar);
4489
4490     context_id = gtk_statusbar_get_context_id(
4491                           GTK_STATUSBAR (status_bar), "Statusbar example");
4492
4493     button = gtk_button_new_with_label ("push item");
4494     g_signal_connect (button, "clicked",
4495                       G_CALLBACK (push_item), GINT_TO_POINTER (context_id));
4496     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 2);
4497     gtk_widget_show (button);              
4498
4499     button = gtk_button_new_with_label ("pop last item");
4500     g_signal_connect (button, "clicked",
4501                       G_CALLBACK (pop_item), GINT_TO_POINTER (context_id));
4502     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 2);
4503     gtk_widget_show (button);
4504
4505     /* always display the window as the last step so it all splashes on
4506      * the screen at once. */
4507     gtk_widget_show (window);
4508
4509     gtk_main ();
4510
4511     return 0;
4512 }
4513 <!-- example-end -->
4514 </programlisting>
4515
4516 </sect1>
4517
4518 <!-- ----------------------------------------------------------------- -->
4519 <sect1 id="sec-TextEntries">
4520 <title>Text Entries</title>
4521
4522 <para>The Entry widget allows text to be typed and displayed in a single line
4523 text box. The text may be set with function calls that allow new text
4524 to replace, prepend or append the current contents of the Entry widget.</para>
4525
4526 <para>Create a new Entry widget with the following function.</para>
4527
4528 <programlisting role="C">
4529 GtkWidget *gtk_entry_new( void );
4530 </programlisting>
4531
4532 <para>The next function alters the text which is currently
4533 within the Entry widget.</para>
4534
4535 <programlisting role="C">
4536 void gtk_entry_set_text( GtkEntry    *entry,
4537                          const gchar *text );
4538 </programlisting>
4539
4540 <para>The function gtk_entry_set_text() sets the contents of the Entry widget,
4541 replacing the current contents. Note that the class Entry implements the Editable
4542 interface (yes, gobject supports Java-like interfaces) which contains some more
4543 functions for manipulating the contents.
4544  </para>
4545
4546 <para>The contents of the Entry can be retrieved by using a call to the
4547 following function. This is useful in the callback functions described below.</para>
4548
4549 <programlisting role="C">
4550 const gchar *gtk_entry_get_text( GtkEntry *entry );
4551 </programlisting>
4552
4553 <para>The value returned by this function is used internally, and must not
4554 be freed using either free() or g_free().</para>
4555
4556 <para>If we don't want the contents of the Entry to be changed by someone typing
4557 into it, we can change its editable state.</para>
4558
4559 <programlisting role="C">
4560 void gtk_editable_set_editable( GtkEditable *entry,
4561                                 gboolean     editable );
4562 </programlisting>
4563
4564 <para>The function above allows us to toggle the editable state of the
4565 Entry widget by passing in a TRUE or FALSE value for the <literal>editable</literal>
4566 argument.</para>
4567
4568 <para>If we are using the Entry where we don't want the text entered to be
4569 visible, for example when a password is being entered, we can use the
4570 following function, which also takes a boolean flag.</para>
4571
4572 <programlisting role="C">
4573 void gtk_entry_set_visibility( GtkEntry *entry,
4574                                gboolean  visible );
4575 </programlisting>
4576
4577 <para>A region of the text may be set as selected by using the following
4578 function. This would most often be used after setting some default
4579 text in an Entry, making it easy for the user to remove it.</para>
4580
4581 <programlisting role="C">
4582 void gtk_editable_select_region( GtkEditable *entry,
4583                                  gint         start,
4584                                  gint         end );
4585 </programlisting>
4586
4587 <para>If we want to catch when the user has entered text, we can connect to
4588 the <literal>activate</literal> or <literal>changed</literal> signal. Activate is raised when the
4589 user hits the enter key within the Entry widget. Changed is raised
4590 when the text changes at all, e.g., for every character entered or
4591 removed.</para>
4592
4593 <para>The following code is an example of using an Entry widget.</para>
4594
4595 <para>
4596 <inlinemediaobject>
4597 <imageobject>
4598 <imagedata fileref="images/entry.png" format="png">
4599 </imageobject>
4600 </inlinemediaobject>
4601 </para>
4602
4603 <programlisting role="C">
4604 <!-- example-start entry entry.c -->
4605
4606 #include &lt;stdio.h&gt;
4607 #include &lt;stdlib.h&gt;
4608 #include &lt;gtk/gtk.h&gt;
4609
4610 static void enter_callback( GtkWidget *widget,
4611                             GtkWidget *entry )
4612 {
4613   const gchar *entry_text;
4614   entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
4615   printf ("Entry contents: %s\n", entry_text);
4616 }
4617
4618 static void entry_toggle_editable( GtkWidget *checkbutton,
4619                                    GtkWidget *entry )
4620 {
4621   gtk_editable_set_editable (GTK_EDITABLE (entry),
4622                              GTK_TOGGLE_BUTTON (checkbutton)-&gt;active);
4623 }
4624
4625 static void entry_toggle_visibility( GtkWidget *checkbutton,
4626                                      GtkWidget *entry )
4627 {
4628   gtk_entry_set_visibility (GTK_ENTRY (entry),
4629                             GTK_TOGGLE_BUTTON (checkbutton)-&gt;active);
4630 }
4631
4632 int main( int   argc,
4633           char *argv[] )
4634 {
4635
4636     GtkWidget *window;
4637     GtkWidget *vbox, *hbox;
4638     GtkWidget *entry;
4639     GtkWidget *button;
4640     GtkWidget *check;
4641     gint tmp_pos;
4642
4643     gtk_init (&amp;argc, &amp;argv);
4644
4645     /* create a new window */
4646     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4647     gtk_widget_set_size_request (GTK_WIDGET (window), 200, 100);
4648     gtk_window_set_title (GTK_WINDOW (window), "GTK Entry");
4649     g_signal_connect (window, "destroy",
4650                       G_CALLBACK (gtk_main_quit), NULL);
4651     g_signal_connect_swapped (window, "delete-event",
4652                               G_CALLBACK (gtk_widget_destroy), 
4653                               window);
4654
4655     vbox = gtk_vbox_new (FALSE, 0);
4656     gtk_container_add (GTK_CONTAINER (window), vbox);
4657     gtk_widget_show (vbox);
4658
4659     entry = gtk_entry_new ();
4660     gtk_entry_set_max_length (GTK_ENTRY (entry), 50);
4661     g_signal_connect (entry, "activate",
4662                       G_CALLBACK (enter_callback),
4663                       entry);
4664     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
4665     tmp_pos = GTK_ENTRY (entry)-&gt;text_length;
4666     gtk_editable_insert_text (GTK_EDITABLE (entry), " world", -1, &amp;tmp_pos);
4667     gtk_editable_select_region (GTK_EDITABLE (entry),
4668                                 0, GTK_ENTRY (entry)-&gt;text_length);
4669     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4670     gtk_widget_show (entry);
4671
4672     hbox = gtk_hbox_new (FALSE, 0);
4673     gtk_container_add (GTK_CONTAINER (vbox), hbox);
4674     gtk_widget_show (hbox);
4675                                   
4676     check = gtk_check_button_new_with_label ("Editable");
4677     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4678     g_signal_connect (check, "toggled",
4679                       G_CALLBACK (entry_toggle_editable), entry);
4680     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
4681     gtk_widget_show (check);
4682     
4683     check = gtk_check_button_new_with_label ("Visible");
4684     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4685     g_signal_connect (check, "toggled",
4686                       G_CALLBACK (entry_toggle_visibility), entry);
4687     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
4688     gtk_widget_show (check);
4689                                    
4690     button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
4691     g_signal_connect_swapped (button, "clicked",
4692                               G_CALLBACK (gtk_widget_destroy),
4693                               window);
4694     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4695     gtk_widget_set_can_default (button, TRUE);
4696     gtk_widget_grab_default (button);
4697     gtk_widget_show (button);
4698     
4699     gtk_widget_show (window);
4700
4701     gtk_main();
4702
4703     return 0;
4704 }
4705 <!-- example-end -->
4706 </programlisting>
4707
4708 </sect1>
4709
4710 <!-- ----------------------------------------------------------------- -->
4711 <sect1 id="sec-SpinButtons">
4712 <title>Spin Buttons</title>
4713
4714 <para>The Spin Button widget is generally used to allow the user to select a
4715 value from a range of numeric values. It consists of a text
4716 entry box with up and down arrow buttons attached to the
4717 side. Selecting one of the buttons causes the value to "spin" up and
4718 down the range of possible values. The entry box may also be edited
4719 directly to enter a specific value.</para>
4720
4721 <para>The Spin Button allows the value to have zero or a number of decimal
4722 places and to be incremented/decremented in configurable steps. The
4723 action of holding down one of the buttons optionally results in an
4724 acceleration of change in the value according to how long it is
4725 depressed.</para>
4726
4727 <para>The Spin Button uses an <link linkend="ch-Adjustments">Adjustment</link>
4728 object to hold information about the range of values that the spin
4729 button can take. This makes for a powerful Spin Button widget.</para>
4730
4731 <para>Recall that an adjustment widget is created with the following
4732 function, which illustrates the information that it holds:</para>
4733
4734 <programlisting role="C">
4735 GtkAdjustment *gtk_adjustment_new( gdouble value,
4736                                    gdouble lower,
4737                                    gdouble upper,
4738                                    gdouble step_increment,
4739                                    gdouble page_increment,
4740                                    gdouble page_size );
4741 </programlisting>
4742
4743 <para>These attributes of an Adjustment are used by the Spin Button in the
4744 following way:</para>
4745
4746 <itemizedlist>
4747 <listitem><simpara> <literal>value</literal>: initial value for the Spin Button</simpara>
4748 </listitem>
4749 <listitem><simpara> <literal>lower</literal>: lower range value</simpara>
4750 </listitem>
4751 <listitem><simpara> <literal>upper</literal>: upper range value</simpara>
4752 </listitem>
4753 <listitem><simpara> <literal>step_increment</literal>: value to increment/decrement when pressing
4754 mouse button 1 on a button</simpara>
4755 </listitem>
4756 <listitem><simpara> <literal>page_increment</literal>: value to increment/decrement when pressing
4757 mouse button 2 on a button</simpara>
4758 </listitem>
4759 <listitem><simpara> <literal>page_size</literal>: unused</simpara>
4760 </listitem>
4761 </itemizedlist>
4762
4763 <para>Additionally, mouse button 3 can be used to jump directly to the
4764 <literal>upper</literal> or <literal>lower</literal> values when used to select one of the
4765 buttons. Lets look at how to create a Spin Button:</para>
4766
4767 <programlisting role="C">
4768 GtkWidget *gtk_spin_button_new( GtkAdjustment *adjustment,
4769                                 gdouble        climb_rate,
4770                                 guint          digits );
4771 </programlisting>
4772
4773 <para>The <literal>climb_rate</literal> argument take a value between 0.0 and 1.0 and
4774 indicates the amount of acceleration that the Spin Button has. The
4775 <literal>digits</literal> argument specifies the number of decimal places to which
4776 the value will be displayed.</para>
4777
4778 <para>A Spin Button can be reconfigured after creation using the following
4779 function:</para>
4780
4781 <programlisting role="C">
4782 void gtk_spin_button_configure( GtkSpinButton *spin_button,
4783                                 GtkAdjustment *adjustment,
4784                                 gdouble        climb_rate,
4785                                 guint          digits );
4786 </programlisting>
4787
4788 <para>The <literal>spin_button</literal> argument specifies the Spin Button widget that is
4789 to be reconfigured. The other arguments are as specified above.</para>
4790
4791 <para>The adjustment can be set and retrieved independantly using the
4792 following two functions:</para>
4793
4794 <programlisting role="C">
4795 void gtk_spin_button_set_adjustment( GtkSpinButton  *spin_button,
4796                                      GtkAdjustment  *adjustment );
4797
4798 GtkAdjustment *gtk_spin_button_get_adjustment( GtkSpinButton *spin_button );
4799 </programlisting>
4800
4801 <para>The number of decimal places can also be altered using:</para>
4802
4803 <programlisting role="C">
4804 void gtk_spin_button_set_digits( GtkSpinButton *spin_button,
4805                                  guint          digits) ;
4806 </programlisting>
4807
4808 <para>The value that a Spin Button is currently displaying can be changed
4809 using the following function:</para>
4810
4811 <programlisting role="C">
4812 void gtk_spin_button_set_value( GtkSpinButton *spin_button,
4813                                 gdouble        value );
4814 </programlisting>
4815
4816 <para>The current value of a Spin Button can be retrieved as either a
4817 floating point or integer value with the following functions:</para>
4818
4819 <programlisting role="C">
4820 gdouble gtk_spin_button_get_value ( GtkSpinButton *spin_button );
4821
4822 gint gtk_spin_button_get_value_as_int( GtkSpinButton *spin_button );
4823 </programlisting>
4824
4825 <para>If you want to alter the value of a Spin Button relative to its current
4826 value, then the following function can be used:</para>
4827
4828 <programlisting role="C">
4829 void gtk_spin_button_spin( GtkSpinButton *spin_button,
4830                            GtkSpinType    direction,
4831                            gdouble        increment );
4832 </programlisting>
4833
4834 <para>The <literal>direction</literal> parameter can take one of the following values:</para>
4835
4836 <programlisting role="C">
4837   GTK_SPIN_STEP_FORWARD
4838   GTK_SPIN_STEP_BACKWARD
4839   GTK_SPIN_PAGE_FORWARD
4840   GTK_SPIN_PAGE_BACKWARD
4841   GTK_SPIN_HOME
4842   GTK_SPIN_END
4843   GTK_SPIN_USER_DEFINED
4844 </programlisting>
4845
4846 <para>This function packs in quite a bit of functionality, which I will
4847 attempt to clearly explain. Many of these settings use values from the
4848 Adjustment object that is associated with a Spin Button.</para>
4849
4850 <para><literal>GTK_SPIN_STEP_FORWARD</literal> and <literal>GTK_SPIN_STEP_BACKWARD</literal> change the
4851 value of the Spin Button by the amount specified by <literal>increment</literal>,
4852 unless <literal>increment</literal> is equal to 0, in which case the value is
4853 changed by the value of <literal>step_increment</literal> in theAdjustment.</para>
4854
4855 <para><literal>GTK_SPIN_PAGE_FORWARD</literal> and <literal>GTK_SPIN_PAGE_BACKWARD</literal> simply
4856 alter the value of the Spin Button by <literal>increment</literal>.</para>
4857
4858 <para><literal>GTK_SPIN_HOME</literal> sets the value of the Spin Button to the bottom of
4859 the Adjustments range.</para>
4860
4861 <para><literal>GTK_SPIN_END</literal> sets the value of the Spin Button to the top of the
4862 Adjustments range.</para>
4863
4864 <para><literal>GTK_SPIN_USER_DEFINED</literal> simply alters the value of the Spin Button
4865 by the specified amount.</para>
4866
4867 <para>We move away from functions for setting and retreving the range attributes
4868 of the Spin Button now, and move onto functions that affect the
4869 appearance and behaviour of the Spin Button widget itself.</para>
4870
4871 <para>The first of these functions is used to constrain the text box of the
4872 Spin Button such that it may only contain a numeric value. This
4873 prevents a user from typing anything other than numeric values into
4874 the text box of a Spin Button:</para>
4875
4876 <programlisting role="C">
4877 void gtk_spin_button_set_numeric( GtkSpinButton *spin_button,
4878                                   gboolean       numeric );
4879 </programlisting>
4880
4881 <para>You can set whether a Spin Button will wrap around between the upper
4882 and lower range values with the following function:</para>
4883
4884 <programlisting role="C">
4885 void gtk_spin_button_set_wrap( GtkSpinButton *spin_button,
4886                                gboolean       wrap );
4887 </programlisting>
4888
4889 <para>You can set a Spin Button to round the value to the nearest
4890 <literal>step_increment</literal>, which is set within the Adjustment object used
4891 with the Spin Button. This is accomplished with the following
4892 function:</para>
4893
4894 <programlisting role="C">
4895 void gtk_spin_button_set_snap_to_ticks( GtkSpinButton  *spin_button,
4896                                         gboolean        snap_to_ticks );
4897 </programlisting>
4898
4899 <para>The update policy of a Spin Button can be changed with the following
4900 function:</para>
4901
4902 <programlisting role="C">
4903 void gtk_spin_button_set_update_policy( GtkSpinButton  *spin_button,
4904                                         GtkSpinButtonUpdatePolicy policy );
4905 </programlisting>
4906
4907 <para>The possible values of <literal>policy</literal> are either <literal>GTK_UPDATE_ALWAYS</literal> or
4908 <literal>GTK_UPDATE_IF_VALID</literal>.</para>
4909
4910 <para>These policies affect the behavior of a Spin Button when parsing
4911 inserted text and syncing its value with the values of the
4912 Adjustment.</para>
4913
4914 <para>In the case of <literal>GTK_UPDATE_IF_VALID</literal> the Spin Button value only
4915 gets changed if the text input is a numeric value that is within the
4916 range specified by the Adjustment. Otherwise the text is reset to the
4917 current value.</para>
4918
4919 <para>In case of <literal>GTK_UPDATE_ALWAYS</literal> we ignore errors while converting
4920 text into a numeric value.</para>
4921
4922 <para>Finally, you can explicitly request that a Spin Button update itself:</para>
4923
4924 <programlisting role="C">
4925 void gtk_spin_button_update( GtkSpinButton  *spin_button );
4926 </programlisting>
4927
4928 <para>It's example time again.</para>
4929
4930 <para>
4931 <inlinemediaobject>
4932 <imageobject>
4933 <imagedata fileref="images/spinbutton.png" format="png">
4934 </imageobject>
4935 </inlinemediaobject>
4936 </para>
4937
4938 <programlisting role="C">
4939 <!-- example-start spinbutton spinbutton.c -->
4940
4941 #include &lt;stdio.h&gt;
4942 #include &lt;gtk/gtk.h&gt;
4943
4944 static GtkWidget *spinner1;
4945
4946 static void toggle_snap( GtkWidget     *widget,
4947                          GtkSpinButton *spin )
4948 {
4949   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)-&gt;active);
4950 }
4951
4952 static void toggle_numeric( GtkWidget *widget,
4953                             GtkSpinButton *spin )
4954 {
4955   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)-&gt;active);
4956 }
4957
4958 static void change_digits( GtkWidget *widget,
4959                            GtkSpinButton *spin )
4960 {
4961   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
4962                               gtk_spin_button_get_value_as_int (spin));
4963 }
4964
4965 static void get_value( GtkWidget *widget,
4966                        gpointer data )
4967 {
4968   gchar *buf;
4969   GtkLabel *label;
4970   GtkSpinButton *spin;
4971
4972   spin = GTK_SPIN_BUTTON (spinner1);
4973   label = GTK_LABEL (g_object_get_data (G_OBJECT (widget), "user_data"));
4974   if (GPOINTER_TO_INT (data) == 1)
4975     buf = g_strdup_printf ("%d", gtk_spin_button_get_value_as_int (spin));
4976   else
4977     buf = g_strdup_printf ("%0.*f", spin-&gt;digits,
4978                            gtk_spin_button_get_value (spin));
4979   gtk_label_set_text (label, buf);
4980   g_free (buf);
4981 }
4982
4983
4984 int main( int   argc,
4985           char *argv[] )
4986 {
4987   GtkWidget *window;
4988   GtkWidget *frame;
4989   GtkWidget *hbox;
4990   GtkWidget *main_vbox;
4991   GtkWidget *vbox;
4992   GtkWidget *vbox2;
4993   GtkWidget *spinner2;
4994   GtkWidget *spinner;
4995   GtkWidget *button;
4996   GtkWidget *label;
4997   GtkWidget *val_label;
4998   GtkAdjustment *adj;
4999
5000   /* Initialise GTK */
5001   gtk_init (&amp;argc, &amp;argv);
5002
5003   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5004
5005   g_signal_connect (window, "destroy",
5006                     G_CALLBACK (gtk_main_quit),
5007                     NULL);
5008
5009   gtk_window_set_title (GTK_WINDOW (window), "Spin Button");
5010
5011   main_vbox = gtk_vbox_new (FALSE, 5);
5012   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5013   gtk_container_add (GTK_CONTAINER (window), main_vbox);
5014   
5015   frame = gtk_frame_new ("Not accelerated");
5016   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5017   
5018   vbox = gtk_vbox_new (FALSE, 0);
5019   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5020   gtk_container_add (GTK_CONTAINER (frame), vbox);
5021   
5022   /* Day, month, year spinners */
5023   
5024   hbox = gtk_hbox_new (FALSE, 0);
5025   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5026   
5027   vbox2 = gtk_vbox_new (FALSE, 0);
5028   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5029   
5030   label = gtk_label_new ("Day :");
5031   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5032   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5033
5034   adj = gtk_adjustment_new (1.0, 1.0, 31.0, 1.0, 5.0, 0.0);
5035   spinner = gtk_spin_button_new (adj, 0, 0);
5036   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5037   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5038   
5039   vbox2 = gtk_vbox_new (FALSE, 0);
5040   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5041   
5042   label = gtk_label_new ("Month :");
5043   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5044   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5045
5046   adj = gtk_adjustment_new (1.0, 1.0, 12.0, 1.0, 5.0, 0.0);
5047   spinner = gtk_spin_button_new (adj, 0, 0);
5048   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5049   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5050   
5051   vbox2 = gtk_vbox_new (FALSE, 0);
5052   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5053   
5054   label = gtk_label_new ("Year :");
5055   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5056   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5057
5058   adj = gtk_adjustment_new (1998.0, 0.0, 2100.0, 1.0, 100.0, 0.0);
5059   spinner = gtk_spin_button_new (adj, 0, 0);
5060   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), FALSE);
5061   gtk_widget_set_size_request (spinner, 55, -1);
5062   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5063   
5064   frame = gtk_frame_new ("Accelerated");
5065   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5066   
5067   vbox = gtk_vbox_new (FALSE, 0);
5068   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5069   gtk_container_add (GTK_CONTAINER (frame), vbox);
5070   
5071   hbox = gtk_hbox_new (FALSE, 0);
5072   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5073   
5074   vbox2 = gtk_vbox_new (FALSE, 0);
5075   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5076   
5077   label = gtk_label_new ("Value :");
5078   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5079   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5080
5081   adj = gtk_adjustment_new (0.0, -10000.0, 10000.0, 0.5, 100.0, 0.0);
5082   spinner1 = gtk_spin_button_new (adj, 1.0, 2);
5083   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
5084   gtk_widget_set_size_request (spinner1, 100, -1);
5085   gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
5086   
5087   vbox2 = gtk_vbox_new (FALSE, 0);
5088   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5089   
5090   label = gtk_label_new ("Digits :");
5091   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5092   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5093
5094   adj = gtk_adjustment_new (2, 1, 5, 1, 1, 0);
5095   spinner2 = gtk_spin_button_new (adj, 0.0, 0);
5096   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner2), TRUE);
5097   g_signal_connect (adj, "value_changed",
5098                     G_CALLBACK (change_digits),
5099                     spinner2);
5100   gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
5101   
5102   hbox = gtk_hbox_new (FALSE, 0);
5103   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5104   
5105   button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
5106   g_signal_connect (button, "clicked",
5107                     G_CALLBACK (toggle_snap),
5108                     spinner1);
5109   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5110   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5111   
5112   button = gtk_check_button_new_with_label ("Numeric only input mode");
5113   g_signal_connect (button, "clicked",
5114                     G_CALLBACK (toggle_numeric),
5115                     spinner1);
5116   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5117   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5118   
5119   val_label = gtk_label_new ("");
5120   
5121   hbox = gtk_hbox_new (FALSE, 0);
5122   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5123   button = gtk_button_new_with_label ("Value as Int");
5124   g_object_set_data (G_OBJECT (button), "user_data", val_label);
5125   g_signal_connect (button, "clicked",
5126                     G_CALLBACK (get_value),
5127                     GINT_TO_POINTER (1));
5128   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5129   
5130   button = gtk_button_new_with_label ("Value as Float");
5131   g_object_set_data (G_OBJECT (button), "user_data", val_label);
5132   g_signal_connect (button, "clicked",
5133                     G_CALLBACK (get_value),
5134                     GINT_TO_POINTER (2));
5135   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5136   
5137   gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
5138   gtk_label_set_text (GTK_LABEL (val_label), "0");
5139   
5140   hbox = gtk_hbox_new (FALSE, 0);
5141   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5142   
5143   button = gtk_button_new_with_label ("Close");
5144   g_signal_connect_swapped (button, "clicked",
5145                             G_CALLBACK (gtk_widget_destroy),
5146                             window);
5147   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5148
5149   gtk_widget_show_all (window);
5150
5151   /* Enter the event loop */
5152   gtk_main ();
5153     
5154   return 0;
5155 }
5156
5157 <!-- example-end -->
5158 </programlisting>
5159
5160 </sect1>
5161
5162 <!-- ----------------------------------------------------------------- -->
5163 <sect1 id="sec-ComboBox">
5164 <title>Combo Box</title>
5165
5166 <para>The combo box is another fairly simple widget that is really just a
5167 collection of other widgets. From the user's point of view, the widget
5168 consists of a text entry box and a pull down menu from which the user
5169 can select one of a set of predefined entries. Alternatively, the user
5170 can type a different option directly into the text box.</para>
5171
5172 <para>The following extract from the structure that defines a Combo Box
5173 identifies several of the components:</para>
5174
5175 <programlisting role="C">
5176 struct _GtkCombo { 
5177         GtkHBox hbox; 
5178         GtkWidget *entry; 
5179         GtkWidget *button;
5180         GtkWidget *popup; 
5181         GtkWidget *popwin; 
5182         GtkWidget *list;
5183         ...  };
5184 </programlisting>
5185
5186 <para>As you can see, the Combo Box has two principal parts that you really
5187 care about: an entry and a list.</para>
5188
5189 <para>First off, to create a combo box, use:</para>
5190
5191 <programlisting role="C">
5192 GtkWidget *gtk_combo_new( void );
5193 </programlisting>
5194
5195 <para>Now, if you want to set the string in the entry section of the combo
5196 box, this is done by manipulating the <literal>entry</literal> widget directly:</para>
5197
5198 <programlisting role="C">
5199     gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo)->entry), "My String.");
5200 </programlisting>
5201
5202 <para>To set the values in the popdown list, one uses the function:</para>
5203
5204 <programlisting role="C">
5205 void gtk_combo_set_popdown_strings( GtkCombo *combo,
5206                                     GList    *strings );
5207 </programlisting>
5208
5209 <para>Before you can do this, you have to assemble a GList of the strings
5210 that you want. GList is a linked list implementation that is part of
5211 <link linkend="ch-GLib">GLib</link>, a library supporting GTK. For the
5212 moment, the quick and dirty explanation is that you need to set up a
5213 GList pointer, set it equal to NULL, then append strings to it with</para>
5214
5215 <programlisting role="C">
5216 GList *g_list_append( GList *glist, 
5217                       gpointer data );
5218 </programlisting>
5219
5220 <para>It is important that you set the initial GList pointer to NULL. The
5221 value returned from the g_list_append() function must be used as the new
5222 pointer to the GList.</para>
5223
5224 <para>Here's a typical code segment for creating a set of options:</para>
5225
5226 <programlisting role="C">
5227     GList *glist = NULL;
5228
5229     glist = g_list_append (glist, "String 1");
5230     glist = g_list_append (glist, "String 2");
5231     glist = g_list_append (glist, "String 3"); 
5232     glist = g_list_append (glist, "String 4");
5233
5234     gtk_combo_set_popdown_strings (GTK_COMBO (combo), glist);
5235     
5236     /* can free glist now, combo takes a copy */
5237 </programlisting>
5238
5239 <para>The combo widget makes a copy of the strings passed to it in the glist
5240 structure. As a result, you need to make sure you free the memory used
5241 by the list if that is appropriate for your application.</para>
5242
5243 <para>At this point you have a working combo box that has been set up.
5244 There are a few aspects of its behavior that you can change. These
5245 are accomplished with the functions: </para>
5246
5247 <programlisting role="C">
5248 void gtk_combo_set_use_arrows( GtkCombo *combo,
5249                                gboolean  val );
5250
5251 void gtk_combo_set_use_arrows_always( GtkCombo *combo,
5252                                       gboolean  val );
5253
5254 void gtk_combo_set_case_sensitive( GtkCombo *combo,
5255                                    gboolean  val );
5256 </programlisting>
5257
5258 <para>gtk_combo_set_use_arrows() lets the user change the value in the
5259 entry using the up/down arrow keys. This doesn't bring up the list, but
5260 rather replaces the current text in the entry with the next list entry
5261 (up or down, as your key choice indicates). It does this by searching
5262 in the list for the item corresponding to the current value in the
5263 entry and selecting the previous/next item accordingly. Usually in an
5264 entry the arrow keys are used to change focus (you can do that anyway
5265 using TAB). Note that when the current item is the last of the list
5266 and you press arrow-down it changes the focus (the same applies with
5267 the first item and arrow-up).</para>
5268
5269 <para>If the current value in the entry is not in the list, then the
5270 function of gtk_combo_set_use_arrows() is disabled.</para>
5271
5272 <para>gtk_combo_set_use_arrows_always() similarly allows the use the
5273 the up/down arrow keys to cycle through the choices in the dropdown
5274 list, except that it wraps around the values in the list, completely
5275 disabling the use of the up and down arrow keys for changing focus.</para>
5276
5277 <para>gtk_combo_set_case_sensitive() toggles whether or not GTK
5278 searches for entries in a case sensitive manner. This is used when the
5279 Combo widget is asked to find a value from the list using the current
5280 entry in the text box. This completion can be performed in either a
5281 case sensitive or insensitive manner, depending upon the use of this
5282 function. The Combo widget can also simply complete the current entry
5283 if the user presses the key combination MOD-1 and "Tab". MOD-1 is
5284 often mapped to the "Alt" key, by the <literal>xmodmap</literal> utility. Note,
5285 however that some window managers also use this key combination, which
5286 will override its use within GTK.</para>
5287
5288 <para>Now that we have a combo box, tailored to look and act how we want it,
5289 all that remains is being able to get data from the combo box. This is
5290 relatively straightforward. The majority of the time, all you are
5291 going to care about getting data from is the entry. The entry is
5292 accessed simply by <literal>GTK_ENTRY (GTK_COMBO (combo)->entry)</literal>. The
5293 two principal things that you are going to want to do with it are
5294 connect to the activate signal, which indicates that the user has
5295 pressed the Return or Enter key, and read the text. The first is
5296 accomplished using something like:</para>
5297
5298 <programlisting role="C">
5299     g_signal_connect (GTK_COMBO (combo)->entry, "activate",
5300                       G_CALLBACK (my_callback_function), my_data);
5301 </programlisting>
5302
5303 <para>Getting the text at any arbitrary time is accomplished by simply using
5304 the entry function:</para>
5305
5306 <programlisting role="C">
5307 gchar *gtk_entry_get_text( GtkEntry *entry );
5308 </programlisting>
5309
5310 <para>Such as:</para>
5311
5312 <programlisting role="C">
5313     gchar *string;
5314
5315     string = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (combo)->entry));
5316 </programlisting>
5317
5318 <para>That's about all there is to it. There is a function</para>
5319
5320 <programlisting role="C">
5321 void gtk_combo_disable_activate( GtkCombo *combo );
5322 </programlisting>
5323
5324 <para>that will disable the activate signal on the entry widget in the combo
5325 box. Personally, I can't think of why you'd want to use it, but it
5326 does exist.</para>
5327
5328 <!-- There is also a function to set the string on a particular item, void
5329 gtk_combo_set_item_string(GtkCombo *combo, GtkItem *item, const gchar
5330 *item_value), but this requires that you have a pointer to the
5331 appropriate Item. Frankly, I have no idea how to do that.
5332 -->
5333
5334 </sect1>
5335
5336 <!-- ----------------------------------------------------------------- -->
5337 <sect1 id="sec-Calendar">
5338 <title>Calendar</title>
5339
5340 <para>The Calendar widget is an effective way to display and retrieve
5341 monthly date related information. It is a very simple widget to create
5342 and work with.</para>
5343
5344 <para>Creating a GtkCalendar widget is a simple as: </para>
5345
5346 <programlisting role="C">
5347 GtkWidget *gtk_calendar_new( void );
5348 </programlisting>
5349
5350 <para>There might be times where you need to change a lot of information
5351 within this widget and the following functions allow you to make
5352 multiple change to a Calendar widget without the user seeing multiple
5353 on-screen updates.</para>
5354
5355 <programlisting role="C">
5356 void gtk_calendar_freeze( GtkCalendar *Calendar );
5357
5358 void gtk_calendar_thaw( GtkCalendar *Calendar );
5359 </programlisting>
5360
5361 <para>They work just like the freeze/thaw functions of every other
5362 widget.</para>
5363
5364 <para>The Calendar widget has a few options that allow you to change the way
5365 the widget both looks and operates by using the function</para>
5366
5367 <programlisting role="C">
5368 void gtk_calendar_set_display_options( GtkCalendar               *calendar,
5369                                        GtkCalendarDisplayOptions  flags );
5370 </programlisting>
5371
5372 <para>The <literal>flags</literal> argument can be formed by combining either of the
5373 following five options using the logical bitwise OR (|) operation:</para>
5374
5375 <variablelist>
5376 <varlistentry>
5377 <term><literal>GTK_CALENDAR_SHOW_HEADING</literal></term>
5378 <listitem><para>this option specifies that the month and year should be shown 
5379 when drawing the calendar.</para>
5380 </listitem>
5381 </varlistentry>
5382 <varlistentry>
5383 <term><literal>GTK_CALENDAR_SHOW_DAY_NAMES</literal></term>
5384 <listitem><para>this option specifies that the three letter descriptions should 
5385 be displayed for each day (eg Mon,Tue, etc.).</para>
5386 </listitem>
5387 </varlistentry>
5388 <varlistentry>
5389 <term><literal>GTK_CALENDAR_NO_MONTH_CHANGE</literal></term>
5390 <listitem><para>this option states that the user
5391 should not and can not change the currently displayed month. This can
5392 be good if you only need to display a particular month such as if you
5393 are displaying 12 calendar widgets for every month in a particular
5394 year.</para>
5395 </listitem>
5396 </varlistentry>
5397 <varlistentry>
5398 <term><literal>GTK_CALENDAR_SHOW_WEEK_NUMBERS</literal></term>
5399 <listitem><para>this option specifies that the
5400 number for each week should be displayed down the left side of the
5401 calendar. (eg. Jan 1 = Week 1,Dec 31 = Week 52).</para>
5402 </listitem>
5403 </varlistentry>
5404 </variablelist>
5405
5406 <para>The following functions are used to set the the currently displayed
5407 date:</para>
5408
5409 <programlisting role="C">
5410 gint gtk_calendar_select_month( GtkCalendar *calendar, 
5411                                 guint        month,
5412                                 guint        year );
5413
5414 void gtk_calendar_select_day( GtkCalendar *calendar,
5415                               guint        day );
5416 </programlisting>
5417
5418 <para>The return value from <literal>gtk_calendar_select_month()</literal> is a boolean
5419 value indicating whether the selection was successful.</para>
5420
5421 <para>With <literal>gtk_calendar_select_day()</literal> the specified day number is
5422 selected within the current month, if that is possible. A
5423 <literal>day</literal> value of 0 will deselect any current selection.</para>
5424
5425 <para>In addition to having a day selected, any number of days in the month
5426 may be "marked". A marked day is highlighted within the calendar
5427 display. The following functions are provided to manipulate marked
5428 days:</para>
5429
5430 <programlisting role="C">
5431 gint gtk_calendar_mark_day( GtkCalendar *calendar,
5432                             guint        day);
5433
5434 gint gtk_calendar_unmark_day( GtkCalendar *calendar,
5435                               guint        day);
5436
5437 void gtk_calendar_clear_marks( GtkCalendar *calendar);
5438 </programlisting>
5439
5440 <para>The currently marked days are stored within an array within the
5441 GtkCalendar structure. This array is 31 elements long so to test
5442 whether a particular day is currently marked, you need to access the
5443 corresponding element of the array (don't forget in C that array
5444 elements are numbered 0 to n-1). For example:</para>
5445
5446 <programlisting role="C">
5447     GtkCalendar *calendar;
5448     calendar = gtk_calendar_new ();
5449
5450     ...
5451
5452     /* Is day 7 marked? */
5453     if (calendar->marked_date[7-1])
5454        /* day is marked */
5455 </programlisting>
5456
5457 <para>Note that marks are persistent across month and year changes.</para>
5458
5459 <para>The final Calendar widget function is used to retrieve the currently
5460 selected date, month and/or year.</para>
5461
5462 <programlisting role="C">
5463 void gtk_calendar_get_date( GtkCalendar *calendar, 
5464                             guint       *year,
5465                             guint       *month,
5466                             guint       *day );
5467 </programlisting>
5468
5469 <para>This function requires you to pass the addresses of <literal>guint</literal>
5470 variables, into which the result will be placed. Passing <literal>NULL</literal> as
5471 a value will result in the corresponding value not being returned.</para>
5472
5473 <para>The Calendar widget can generate a number of signals indicating date
5474 selection and change. The names of these signals are self explanatory,
5475 and are:</para>
5476
5477 <itemizedlist>
5478 <listitem><simpara> <literal>month_changed</literal></simpara>
5479 </listitem>
5480 <listitem><simpara> <literal>day_selected</literal></simpara>
5481 </listitem>
5482 <listitem><simpara> <literal>day_selected_double_click</literal></simpara>
5483 </listitem>
5484 <listitem><simpara> <literal>prev_month</literal></simpara>
5485 </listitem>
5486 <listitem><simpara> <literal>next_month</literal></simpara>
5487 </listitem>
5488 <listitem><simpara> <literal>prev_year</literal></simpara>
5489 </listitem>
5490 <listitem><simpara> <literal>next_year</literal></simpara>
5491 </listitem>
5492 </itemizedlist>
5493
5494 <para>That just leaves us with the need to put all of this together into
5495 example code.</para>
5496
5497 <para>
5498 <inlinemediaobject>
5499 <imageobject>
5500 <imagedata fileref="images/calendar.png" format="png">
5501 </imageobject>
5502 </inlinemediaobject>
5503 </para>
5504
5505 <programlisting role="C">
5506 <!-- example-start calendar calendar.c -->
5507 /*
5508  * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson, Mattias Gr�nlund
5509  * Copyright (C) 2000 Tony Gale
5510  *
5511  * This program is free software; you can redistribute it and/or modify
5512  * it under the terms of the GNU General Public License as published by
5513  * the Free Software Foundation; either version 2 of the License, or
5514  * (at your option) any later version.
5515  *
5516  * This program is distributed in the hope that it will be useful,
5517  * but WITHOUT ANY WARRANTY; without even the implied warranty of
5518  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5519  * GNU General Public License for more details.
5520  *
5521  * You should have received a copy of the GNU General Public License
5522  * along with this program; if not, write to the Free Software
5523  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5524  */
5525
5526 #include &lt;stdio.h&gt;
5527 #include &lt;string.h&gt;
5528 #include &lt;gtk/gtk.h&gt;
5529
5530 #define DEF_PAD 10
5531 #define DEF_PAD_SMALL 5
5532
5533 #define TM_YEAR_BASE 1900
5534
5535 typedef struct _CalendarData {
5536   GtkWidget *flag_checkboxes[5];
5537   gboolean  settings[5];
5538   GtkWidget *font_dialog;
5539   GtkWidget *window;
5540   GtkWidget *prev2_sig;
5541   GtkWidget *prev_sig;
5542   GtkWidget *last_sig;
5543   GtkWidget *month;
5544 } CalendarData;
5545
5546 enum {
5547   calendar_show_header,
5548   calendar_show_days,
5549   calendar_month_change, 
5550   calendar_show_week,
5551   calendar_monday_first
5552 };
5553
5554 /*
5555  * GtkCalendar
5556  */
5557
5558 static void calendar_date_to_string( CalendarData *data,
5559                                      char         *buffer,
5560                                      gint          buff_len )
5561 {
5562   GDate date;
5563   guint year, month, day;
5564
5565   gtk_calendar_get_date (GTK_CALENDAR (data-&gt;window),
5566                          &amp;year, &amp;month, &amp;day);
5567   g_date_set_dmy (&amp;date, day, month + 1, year);
5568   g_date_strftime (buffer, buff_len - 1, "%x", &amp;date);
5569
5570 }
5571
5572 static void calendar_set_signal_strings( char         *sig_str,
5573                                          CalendarData *data )
5574 {
5575   const gchar *prev_sig;
5576
5577   prev_sig = gtk_label_get_text (GTK_LABEL (data-&gt;prev_sig));
5578   gtk_label_set_text (GTK_LABEL (data-&gt;prev2_sig), prev_sig);
5579
5580   prev_sig = gtk_label_get_text (GTK_LABEL (data-&gt;last_sig));
5581   gtk_label_set_text (GTK_LABEL (data-&gt;prev_sig), prev_sig);
5582   gtk_label_set_text (GTK_LABEL (data-&gt;last_sig), sig_str);
5583 }
5584
5585 static void calendar_month_changed( GtkWidget    *widget,
5586                                     CalendarData *data )
5587 {
5588   char buffer[256] = "month_changed: ";
5589
5590   calendar_date_to_string (data, buffer + 15, 256 - 15);
5591   calendar_set_signal_strings (buffer, data);
5592 }
5593
5594 static void calendar_day_selected( GtkWidget    *widget,
5595                                    CalendarData *data )
5596 {
5597   char buffer[256] = "day_selected: ";
5598
5599   calendar_date_to_string (data, buffer + 14, 256 - 14);
5600   calendar_set_signal_strings (buffer, data);
5601 }
5602
5603 static void calendar_day_selected_double_click ( GtkWidget    *widget,
5604                                                  CalendarData *data )
5605 {
5606   char buffer[256] = "day_selected_double_click: ";
5607   guint day;
5608
5609   calendar_date_to_string (data, buffer + 27, 256 - 27);
5610   calendar_set_signal_strings (buffer, data);
5611
5612   gtk_calendar_get_date (GTK_CALENDAR (data-&gt;window),
5613                          NULL, NULL, &amp;day);
5614
5615   if (GTK_CALENDAR (data-&gt;window)-&gt;marked_date[day-1] == 0) {
5616     gtk_calendar_mark_day (GTK_CALENDAR (data-&gt;window), day);
5617   } else { 
5618     gtk_calendar_unmark_day (GTK_CALENDAR (data-&gt;window), day);
5619   }
5620 }
5621
5622 static void calendar_prev_month( GtkWidget    *widget,
5623                                  CalendarData *data )
5624 {
5625   char buffer[256] = "prev_month: ";
5626
5627   calendar_date_to_string (data, buffer + 12, 256 - 12);
5628   calendar_set_signal_strings (buffer, data);
5629 }
5630
5631 static void calendar_next_month( GtkWidget    *widget,
5632                                  CalendarData *data )
5633 {
5634   char buffer[256] = "next_month: ";
5635
5636   calendar_date_to_string (data, buffer + 12, 256 - 12);
5637   calendar_set_signal_strings (buffer, data);
5638 }
5639
5640 static void calendar_prev_year( GtkWidget    *widget,
5641                                 CalendarData *data )
5642 {
5643   char buffer[256] = "prev_year: ";
5644
5645   calendar_date_to_string (data, buffer + 11, 256 - 11);
5646   calendar_set_signal_strings (buffer, data);
5647 }
5648
5649 static void calendar_next_year( GtkWidget    *widget,
5650                                 CalendarData *data )
5651 {
5652   char buffer[256] = "next_year: ";
5653
5654   calendar_date_to_string (data, buffer + 11, 256 - 11);
5655   calendar_set_signal_strings (buffer, data);
5656 }
5657
5658
5659 static void calendar_set_flags( CalendarData *calendar )
5660 {
5661   gint i;
5662   gint options = 0;
5663   for (i = 0;i &lt; 5; i++) 
5664     if (calendar-&gt;settings[i])
5665       {
5666         options = options + (1 &lt;&lt; i);
5667       }
5668   if (calendar-&gt;window)
5669     gtk_calendar_set_display_options (GTK_CALENDAR (calendar-&gt;window), options);
5670 }
5671
5672 static void calendar_toggle_flag( GtkWidget    *toggle,
5673                                   CalendarData *calendar)
5674 {
5675   gint i;
5676   gint j;
5677   j = 0;
5678   for (i = 0; i &lt; 5; i++)
5679     if (calendar-&gt;flag_checkboxes[i] == toggle)
5680       j = i;
5681
5682   calendar-&gt;settings[j] = !calendar-&gt;settings[j];
5683   calendar_set_flags (calendar);
5684   
5685 }
5686
5687 static void calendar_font_selection_ok( GtkWidget    *button,
5688                                         CalendarData *calendar )
5689 {
5690   GtkRcStyle *style;
5691   char *font_name;
5692
5693   if (calendar-&gt;window)
5694     {
5695       font_name = gtk_font_selection_dialog_get_font_name (GTK_FONT_SELECTION_DIALOG (calendar-&gt;font_dialog));
5696       if (font_name) 
5697         {
5698           style = gtk_rc_style_new ();
5699           pango_font_description_free (style-&gt;font_desc);
5700           style-&gt;font_desc = pango_font_description_from_string (font_name);
5701           gtk_widget_modify_style (calendar-&gt;window, style);
5702           g_free (font_name);
5703         }
5704     }
5705
5706   gtk_widget_destroy (calendar-&gt;font_dialog);
5707 }
5708
5709 static void calendar_select_font( GtkWidget    *button,
5710                                   CalendarData *calendar )
5711 {
5712   GtkWidget *window;
5713
5714   if (!calendar-&gt;font_dialog) {
5715     window = gtk_font_selection_dialog_new ("Font Selection Dialog");
5716     g_return_if_fail (GTK_IS_FONT_SELECTION_DIALOG (window));
5717     calendar-&gt;font_dialog = window;
5718     
5719     gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
5720     
5721     g_signal_connect (window, "destroy",
5722                       G_CALLBACK (gtk_widget_destroyed),
5723                       &amp;calendar-&gt;font_dialog);
5724     
5725     g_signal_connect (GTK_FONT_SELECTION_DIALOG (window)-&gt;ok_button,
5726                       "clicked", G_CALLBACK (calendar_font_selection_ok),
5727                       calendar);
5728     g_signal_connect_swapped (GTK_FONT_SELECTION_DIALOG (window)-&gt;cancel_button,
5729                              "clicked", G_CALLBACK (gtk_widget_destroy), 
5730                              calendar-&gt;font_dialog);
5731   }
5732   window = calendar-&gt;font_dialog;
5733   if (!gtk_widget_get_visible (window))
5734     gtk_widget_show (window);
5735   else
5736     gtk_widget_destroy (window);
5737
5738 }
5739
5740 static void create_calendar( void )
5741 {
5742   GtkWidget *window;
5743   GtkWidget *vbox, *vbox2, *vbox3;
5744   GtkWidget *hbox;
5745   GtkWidget *hbbox;
5746   GtkWidget *calendar;
5747   GtkWidget *toggle;
5748   GtkWidget *button;
5749   GtkWidget *frame;
5750   GtkWidget *separator;
5751   GtkWidget *label;
5752   GtkWidget *bbox;
5753   static CalendarData calendar_data;
5754   gint i;
5755   
5756   struct {
5757     char *label;
5758   } flags[] =
5759     {
5760       { "Show Heading" },
5761       { "Show Day Names" },
5762       { "No Month Change" },
5763       { "Show Week Numbers" },
5764       { "Week Start Monday" }
5765     };
5766
5767   
5768   calendar_data.window = NULL;
5769   calendar_data.font_dialog = NULL;
5770
5771   for (i = 0; i &lt; 5; i++) {
5772     calendar_data.settings[i] = 0;
5773   }
5774
5775   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5776   gtk_window_set_title (GTK_WINDOW (window), "GtkCalendar Example");
5777   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
5778   g_signal_connect (window, "destroy",
5779                     G_CALLBACK (gtk_main_quit),
5780                     NULL);
5781   g_signal_connect (window, "delete-event",
5782                     G_CALLBACK (gtk_false),
5783                     NULL);
5784   gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
5785
5786   vbox = gtk_vbox_new (FALSE, DEF_PAD);
5787   gtk_container_add (GTK_CONTAINER (window), vbox);
5788
5789   /*
5790    * The top part of the window, Calendar, flags and fontsel.
5791    */
5792
5793   hbox = gtk_hbox_new (FALSE, DEF_PAD);
5794   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, DEF_PAD);
5795   hbbox = gtk_hbutton_box_new ();
5796   gtk_box_pack_start (GTK_BOX (hbox), hbbox, FALSE, FALSE, DEF_PAD);
5797   gtk_button_box_set_layout (GTK_BUTTON_BOX (hbbox), GTK_BUTTONBOX_SPREAD);
5798   gtk_box_set_spacing (GTK_BOX (hbbox), 5);
5799
5800   /* Calendar widget */
5801   frame = gtk_frame_new ("Calendar");
5802   gtk_box_pack_start(GTK_BOX (hbbox), frame, FALSE, TRUE, DEF_PAD);
5803   calendar=gtk_calendar_new ();
5804   calendar_data.window = calendar;
5805   calendar_set_flags (&amp;calendar_data);
5806   gtk_calendar_mark_day (GTK_CALENDAR (calendar), 19);  
5807   gtk_container_add (GTK_CONTAINER (frame), calendar);
5808   g_signal_connect (calendar, "month_changed", 
5809                     G_CALLBACK (calendar_month_changed),
5810                     &amp;calendar_data);
5811   g_signal_connect (calendar, "day_selected", 
5812                     G_CALLBACK (calendar_day_selected),
5813                     &amp;calendar_data);
5814   g_signal_connect (calendar, "day_selected_double_click", 
5815                     G_CALLBACK (calendar_day_selected_double_click),
5816                     &amp;calendar_data);
5817   g_signal_connect (calendar, "prev_month", 
5818                     G_CALLBACK (calendar_prev_month),
5819                     &amp;calendar_data);
5820   g_signal_connect (calendar, "next_month", 
5821                     G_CALLBACK (calendar_next_month),
5822                     &amp;calendar_data);
5823   g_signal_connect (calendar, "prev_year", 
5824                     G_CALLBACK (calendar_prev_year),
5825                     &amp;calendar_data);
5826   g_signal_connect (calendar, "next_year", 
5827                     G_CALLBACK (calendar_next_year),
5828                     &amp;calendar_data);
5829
5830
5831   separator = gtk_vseparator_new ();
5832   gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, TRUE, 0);
5833
5834   vbox2 = gtk_vbox_new (FALSE, DEF_PAD);
5835   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, DEF_PAD);
5836   
5837   /* Build the Right frame with the flags in */ 
5838
5839   frame = gtk_frame_new ("Flags");
5840   gtk_box_pack_start (GTK_BOX (vbox2), frame, TRUE, TRUE, DEF_PAD);
5841   vbox3 = gtk_vbox_new (TRUE, DEF_PAD_SMALL);
5842   gtk_container_add (GTK_CONTAINER (frame), vbox3);
5843
5844   for (i = 0; i &lt; 5; i++)
5845     {
5846       toggle = gtk_check_button_new_with_label (flags[i].label);
5847       g_signal_connect (toggle,
5848                         "toggled",
5849                         G_CALLBACK (calendar_toggle_flag),
5850                         &amp;calendar_data);
5851       gtk_box_pack_start (GTK_BOX (vbox3), toggle, TRUE, TRUE, 0);
5852       calendar_data.flag_checkboxes[i] = toggle;
5853     }
5854   /* Build the right font-button */ 
5855   button = gtk_button_new_with_label ("Font...");
5856   g_signal_connect (button,
5857                     "clicked",
5858                     G_CALLBACK (calendar_select_font),
5859                     &amp;calendar_data);
5860   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
5861
5862   /*
5863    *  Build the Signal-event part.
5864    */
5865
5866   frame = gtk_frame_new ("Signal events");
5867   gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, DEF_PAD);
5868
5869   vbox2 = gtk_vbox_new (TRUE, DEF_PAD_SMALL);
5870   gtk_container_add (GTK_CONTAINER (frame), vbox2);
5871   
5872   hbox = gtk_hbox_new (FALSE, 3);
5873   gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
5874   label = gtk_label_new ("Signal:");
5875   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5876   calendar_data.last_sig = gtk_label_new ("");
5877   gtk_box_pack_start (GTK_BOX (hbox), calendar_data.last_sig, FALSE, TRUE, 0);
5878
5879   hbox = gtk_hbox_new (FALSE, 3);
5880   gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
5881   label = gtk_label_new ("Previous signal:");
5882   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5883   calendar_data.prev_sig = gtk_label_new ("");
5884   gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev_sig, FALSE, TRUE, 0);
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 ("Second previous signal:");
5889   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5890   calendar_data.prev2_sig = gtk_label_new ("");
5891   gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev2_sig, FALSE, TRUE, 0);
5892
5893   bbox = gtk_hbutton_box_new ();
5894   gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
5895   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
5896
5897   button = gtk_button_new_with_label ("Close");
5898   g_signal_connect (button, "clicked", 
5899                     G_CALLBACK (gtk_main_quit), 
5900                     NULL);
5901   gtk_container_add (GTK_CONTAINER (bbox), button);
5902   gtk_widget_set_can_default (button, TRUE);
5903   gtk_widget_grab_default (button);
5904
5905   gtk_widget_show_all (window);
5906 }
5907
5908
5909 int main (int   argc,
5910           char *argv[])
5911 {
5912   gtk_init (&amp;argc, &amp;argv);
5913
5914   create_calendar ();
5915
5916   gtk_main ();
5917
5918   return 0;
5919 }
5920 <!-- example-end -->
5921 </programlisting>
5922
5923 </sect1>
5924
5925 <!-- ----------------------------------------------------------------- -->
5926 <sect1 id="sec-ColorSelection">
5927 <title>Color Selection</title>
5928
5929 <para>The color selection widget is, not surprisingly, a widget for
5930 interactive selection of colors. This composite widget lets the user
5931 select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
5932 Saturation, Value) triples.  This is done either by adjusting single
5933 values with sliders or entries, or by picking the desired color from a
5934 hue-saturation wheel/value bar.  Optionally, the opacity of the color
5935 can also be set.</para>
5936
5937 <para>The color selection widget currently emits only one signal,
5938 "color_changed", which is emitted whenever the current color in the
5939 widget changes, either when the user changes it or if it's set
5940 explicitly through gtk_color_selection_set_color().</para>
5941
5942 <para>Lets have a look at what the color selection widget has to offer
5943 us. The widget comes in two flavours: GtkColorSelection and
5944 GtkColorSelectionDialog.</para>
5945
5946 <programlisting role="C">
5947 GtkWidget *gtk_color_selection_new( void );
5948 </programlisting>
5949         
5950 <para>You'll probably not be using this constructor directly. It creates an
5951 orphan ColorSelection widget which you'll have to parent
5952 yourself. The ColorSelection widget inherits from the VBox
5953 widget.</para>
5954
5955 <programlisting role="C">
5956 GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
5957 </programlisting>
5958
5959 <para>This is the most common color selection constructor. It creates a
5960 ColorSelectionDialog. It consists of a Frame containing a
5961 ColorSelection widget, an HSeparator and an HBox with three buttons,
5962 "Ok", "Cancel" and "Help". You can reach these buttons by accessing
5963 the "ok_button", "cancel_button" and "help_button" widgets in the
5964 ColorSelectionDialog structure,
5965 (i.e., <literal>GTK_COLOR_SELECTION_DIALOG (colorseldialog)->ok_button</literal>)).</para>
5966
5967 <programlisting role="C">
5968 void gtk_color_selection_set_has_opacity_control( GtkColorSelection *colorsel,
5969                                                   gboolean           has_opacity );
5970 </programlisting>
5971
5972 <para>The color selection widget supports adjusting the opacity of a color
5973 (also known as the alpha channel). This is disabled by
5974 default. Calling this function with has_opacity set to TRUE enables
5975 opacity. Likewise, has_opacity set to FALSE will disable opacity.</para>
5976
5977 <programlisting role="C">
5978 void gtk_color_selection_set_current_color( GtkColorSelection *colorsel,
5979                                             GdkColor          *color );
5980
5981 void gtk_color_selection_set_current_alpha( GtkColorSelection *colorsel,
5982                                             guint16            alpha );
5983 </programlisting>
5984
5985 <para>You can set the current color explicitly by calling 
5986 gtk_color_selection_set_current_color() with a pointer to a GdkColor. 
5987 Setting the opacity (alpha channel) is done with 
5988 gtk_color_selection_set_current_alpha(). The alpha value should be between
5989 0 (fully transparent) and 65535 (fully opaque).
5990 </para>
5991
5992 <programlisting role="C">
5993 void gtk_color_selection_get_current_color( GtkColorSelection *colorsel,
5994                                             GdkColor *color );
5995
5996 void gtk_color_selection_get_current_alpha( GtkColorSelection *colorsel,
5997                                             guint16           *alpha );
5998 </programlisting>
5999
6000 <para>When you need to query the current color, typically when you've
6001 received a "color_changed" signal, you use these functions.</para>
6002
6003 <para><!-- Need to do a whole section on DnD - TRG
6004 Drag and drop
6005 -------------</para>
6006
6007 <para>The color sample areas (right under the hue-saturation wheel) supports
6008 drag and drop. The type of drag and drop is "application/x-color". The
6009 message data consists of an array of 4 (or 5 if opacity is enabled)
6010 gdouble values, where the value at position 0 is 0.0 (opacity on) or
6011 1.0 (opacity off) followed by the red, green and blue values at
6012 positions 1,2 and 3 respectively.  If opacity is enabled, the opacity
6013 is passed in the value at position 4.
6014 --></para>
6015
6016 <para>Here's a simple example demonstrating the use of the
6017 ColorSelectionDialog. The program displays a window containing a
6018 drawing area. Clicking on it opens a color selection dialog, and
6019 changing the color in the color selection dialog changes the
6020 background color.</para>
6021
6022 <para>
6023 <inlinemediaobject>
6024 <imageobject>
6025 <imagedata fileref="images/colorsel.png" format="png">
6026 </imageobject>
6027 </inlinemediaobject>
6028 </para>
6029
6030 <programlisting role="C">
6031 <!-- example-start colorsel colorsel.c -->
6032
6033 #include &lt;glib.h&gt;
6034 #include &lt;gdk/gdk.h&gt;
6035 #include &lt;gtk/gtk.h&gt;
6036
6037 GtkWidget *colorseldlg = NULL;
6038 GtkWidget *drawingarea = NULL;
6039 GdkColor color;
6040
6041 /* Color changed handler */
6042
6043 static void color_changed_cb( GtkWidget         *widget,
6044                               GtkColorSelection *colorsel )
6045 {
6046   GdkColor ncolor;
6047
6048   gtk_color_selection_get_current_color (colorsel, &amp;ncolor);
6049   gtk_widget_modify_bg (drawingarea, GTK_STATE_NORMAL, &amp;ncolor);       
6050 }
6051
6052 /* Drawingarea event handler */
6053
6054 static gboolean area_event( GtkWidget *widget,
6055                             GdkEvent  *event,
6056                             gpointer   client_data )
6057 {
6058   gint handled = FALSE;
6059   gint response;
6060   GtkColorSelection *colorsel;
6061
6062   /* Check if we've received a button pressed event */
6063
6064   if (event-&gt;type == GDK_BUTTON_PRESS)
6065     {
6066       handled = TRUE;
6067
6068        /* Create color selection dialog */
6069       if (colorseldlg == NULL)
6070         colorseldlg = gtk_color_selection_dialog_new ("Select background color");
6071
6072       /* Get the ColorSelection widget */
6073       colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (colorseldlg)-&gt;colorsel);
6074
6075       gtk_color_selection_set_previous_color (colorsel, &amp;color);
6076       gtk_color_selection_set_current_color (colorsel, &amp;color);
6077       gtk_color_selection_set_has_palette (colorsel, TRUE);
6078
6079       /* Connect to the "color_changed" signal, set the client-data
6080        * to the colorsel widget */
6081       g_signal_connect (colorsel, "color_changed",
6082                         G_CALLBACK (color_changed_cb), (gpointer) colorsel);
6083
6084       /* Show the dialog */
6085       response = gtk_dialog_run (GTK_DIALOG (colorseldlg));
6086
6087       if (response == GTK_RESPONSE_OK)
6088         gtk_color_selection_get_current_color (colorsel, &amp;color);
6089       else 
6090         gtk_widget_modify_bg (drawingarea, GTK_STATE_NORMAL, &amp;color);
6091
6092       gtk_widget_hide (colorseldlg);
6093     }
6094
6095   return handled;
6096 }
6097
6098 /* Close down and exit handler */
6099
6100 static gboolean destroy_window( GtkWidget *widget,
6101                                 GdkEvent  *event,
6102                                 gpointer   client_data )
6103 {
6104   gtk_main_quit ();
6105   return TRUE;
6106 }
6107
6108 /* Main */
6109
6110 gint main( gint   argc,
6111            gchar *argv[] )
6112 {
6113   GtkWidget *window;
6114
6115   /* Initialize the toolkit, remove gtk-related commandline stuff */
6116
6117   gtk_init (&amp;argc, &amp;argv);
6118
6119   /* Create toplevel window, set title and policies */
6120
6121   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6122   gtk_window_set_title (GTK_WINDOW (window), "Color selection test");
6123   gtk_window_set_resizable ((GTK_WINDOW (window), TRUE);
6124
6125   /* Attach to the "delete" and "destroy" events so we can exit */
6126
6127   g_signal_connect (window, "delete-event",
6128                     G_CALLBACK (destroy_window), (gpointer) window);
6129   
6130   /* Create drawingarea, set size and catch button events */
6131
6132   drawingarea = gtk_drawing_area_new ();
6133
6134   color.red = 0;
6135   color.blue = 65535;
6136   color.green = 0;
6137   gtk_widget_modify_bg (drawingarea, GTK_STATE_NORMAL, &amp;color);       
6138
6139   gtk_widget_set_size_request (GTK_WIDGET (drawingarea), 200, 200);
6140
6141   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
6142
6143   g_signal_connect (GTK_OBJECT (drawingarea), "event", 
6144                     G_CALLBACK (area_event), (gpointer) drawingarea);
6145   
6146   /* Add drawingarea to window, then show them both */
6147
6148   gtk_container_add (GTK_CONTAINER (window), drawingarea);
6149
6150   gtk_widget_show (drawingarea);
6151   gtk_widget_show (window);
6152   
6153   /* Enter the gtk main loop (this never returns) */
6154
6155   gtk_main ();
6156
6157   /* Satisfy grumpy compilers */
6158
6159   return 0;
6160 }
6161 <!-- example-end -->
6162 </programlisting>
6163
6164 </sect1>
6165
6166 <!-- ----------------------------------------------------------------- -->
6167 <sect1 id="sec-FileSelections">
6168 <title>File Selections</title>
6169
6170 <para>The file selection widget is a quick and simple way to display a File
6171 dialog box. It comes complete with Ok, Cancel, and Help buttons, a
6172 great way to cut down on programming time.</para>
6173
6174 <para>To create a new file selection box use:</para>
6175
6176 <programlisting role="C">
6177 GtkWidget *gtk_file_selection_new( const gchar *title );
6178 </programlisting>
6179
6180 <para>To set the filename, for example to bring up a specific directory, or
6181 give a default filename, use this function:</para>
6182
6183 <programlisting role="C">
6184 void gtk_file_selection_set_filename( GtkFileSelection *filesel,
6185                                       const gchar      *filename );
6186 </programlisting>
6187
6188 <para>To grab the text that the user has entered or clicked on, use this 
6189 function:</para>
6190
6191 <programlisting role="C">
6192 gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel );
6193 </programlisting>
6194
6195 <para>There are also pointers to the widgets contained within the file 
6196 selection widget. These are:</para>
6197
6198 <programlisting role="C">
6199   dir_list
6200   file_list
6201   selection_entry
6202   selection_text
6203   main_vbox
6204   ok_button
6205   cancel_button
6206   help_button
6207 </programlisting>
6208  
6209 <para>Most likely you will want to use the ok_button, cancel_button, and
6210 help_button pointers in signaling their use.</para>
6211
6212 <para>Included here is an example stolen from <filename>testgtk.c</filename>,
6213 modified to run on its own. As you will see, there is nothing much to creating a file
6214 selection widget. While in this example the Help button appears on the
6215 screen, it does nothing as there is not a signal attached to it.</para>
6216
6217 <para>
6218 <inlinemediaobject>
6219 <imageobject>
6220 <imagedata fileref="images/filesel.png" format="png">
6221 </imageobject>
6222 </inlinemediaobject>
6223 </para>
6224
6225 <programlisting role="C">
6226 <!-- example-start filesel filesel.c -->
6227
6228 #include &lt;gtk/gtk.h&gt;
6229
6230 /* Get the selected filename and print it to the console */
6231 static void file_ok_sel( GtkWidget        *w,
6232                          GtkFileSelection *fs )
6233 {
6234     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
6235 }
6236
6237 int main( int   argc,
6238           char *argv[] )
6239 {
6240     GtkWidget *filew;
6241     
6242     gtk_init (&amp;argc, &amp;argv);
6243     
6244     /* Create a new file selection widget */
6245     filew = gtk_file_selection_new ("File selection");
6246     
6247     g_signal_connect (filew, "destroy",
6248                       G_CALLBACK (gtk_main_quit), NULL);
6249     /* Connect the ok_button to file_ok_sel function */
6250     g_signal_connect (GTK_FILE_SELECTION (filew)-&gt;ok_button,
6251                       "clicked", G_CALLBACK (file_ok_sel), (gpointer) filew);
6252     
6253     /* Connect the cancel_button to destroy the widget */
6254     g_signal_connect_swapped (GTK_FILE_SELECTION (filew)-&gt;cancel_button,
6255                               "clicked", G_CALLBACK (gtk_widget_destroy),
6256                               filew);
6257     
6258     /* Lets set the filename, as if this were a save dialog, and we are giving
6259      a default filename */
6260     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
6261                                      "penguin.png");
6262     
6263     gtk_widget_show (filew);
6264     gtk_main ();
6265     return 0;
6266 }
6267 <!-- example-end -->
6268 </programlisting>
6269
6270 </sect1>
6271 </chapter>
6272
6273 <!-- ***************************************************************** -->
6274 <chapter id="ch-ContainerWidgets">
6275 <title>Container Widgets</title>
6276
6277 <!-- ----------------------------------------------------------------- -->   
6278 <sect1 id="sec-EventBox">
6279 <title>The EventBox</title>
6280
6281 <para>Some GTK widgets don't have associated X windows, so they just draw on
6282 their parents. Because of this, they cannot receive events and if they
6283 are incorrectly sized, they don't clip so you can get messy
6284 overwriting, etc. If you require more from these widgets, the EventBox
6285 is for you.</para>
6286
6287 <para>At first glance, the EventBox widget might appear to be totally
6288 useless. It draws nothing on the screen and responds to no
6289 events. However, it does serve a function - it provides an X window
6290 for its child widget. This is important as many GTK widgets do not
6291 have an associated X window. Not having an X window saves memory and
6292 improves performance, but also has some drawbacks. A widget without an
6293 X window cannot receive events, and does not perform any clipping on
6294 its contents. Although the name <emphasis>EventBox</emphasis> emphasizes the
6295 event-handling function, the widget can also be used for clipping.
6296 (and more, see the example below).</para>
6297
6298 <para>To create a new EventBox widget, use:</para>
6299
6300 <programlisting role="C">
6301 GtkWidget *gtk_event_box_new( void );
6302 </programlisting>
6303
6304 <para>A child widget can then be added to this EventBox:</para>
6305
6306 <programlisting role="C">
6307     gtk_container_add (GTK_CONTAINER (event_box), child_widget);
6308 </programlisting>
6309
6310 <para>The following example demonstrates both uses of an EventBox - a label
6311 is created that is clipped to a small box, and set up so that a
6312 mouse-click on the label causes the program to exit. Resizing the
6313 window reveals varying amounts of the label.</para>
6314
6315 <para>
6316 <inlinemediaobject>
6317 <imageobject>
6318 <imagedata fileref="images/eventbox.png" format="png">
6319 </imageobject>
6320 </inlinemediaobject>
6321 </para>
6322
6323 <programlisting role="C">
6324 <!-- example-start eventbox eventbox.c -->
6325
6326 #include &lt;stdlib.h&gt;
6327 #include &lt;gtk/gtk.h&gt;
6328
6329 int main( int argc,
6330           char *argv[] )
6331 {
6332     GtkWidget *window;
6333     GtkWidget *event_box;
6334     GtkWidget *label;
6335     
6336     gtk_init (&amp;argc, &amp;argv);
6337     
6338     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6339     
6340     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
6341     
6342     g_signal_connect (window, "destroy",
6343                       G_CALLBACK (exit), NULL);
6344     
6345     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6346     
6347     /* Create an EventBox and add it to our toplevel window */
6348     
6349     event_box = gtk_event_box_new ();
6350     gtk_container_add (GTK_CONTAINER (window), event_box);
6351     gtk_widget_show (event_box);
6352     
6353     /* Create a long label */
6354     
6355     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
6356     gtk_container_add (GTK_CONTAINER (event_box), label);
6357     gtk_widget_show (label);
6358     
6359     /* Clip it short. */
6360     gtk_widget_set_size_request (label, 110, 20);
6361     
6362     /* And bind an action to it */
6363     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
6364     g_signal_connect (event_box, "button_press_event",
6365                       G_CALLBACK (exit), NULL);
6366     
6367     /* Yet one more thing you need an X window for ... */
6368     
6369     gtk_widget_realize (event_box);
6370     gdk_window_set_cursor (event_box-&gt;window, gdk_cursor_new (GDK_HAND1));
6371     
6372     gtk_widget_show (window);
6373     
6374     gtk_main ();
6375     
6376     return 0;
6377 }
6378 <!-- example-end -->
6379 </programlisting>
6380
6381 </sect1>
6382
6383 <!-- ----------------------------------------------------------------- -->   
6384 <sect1 id="sec-TheAlignmentWidget">
6385 <title>The Alignment widget</title>
6386
6387 <para>The alignment widget allows you to place a widget within its window at
6388 a position and size relative to the size of the Alignment widget
6389 itself. For example, it can be very useful for centering a widget
6390 within the window.</para>
6391
6392 <para>There are only two functions associated with the Alignment widget:</para>
6393
6394 <programlisting role="C">
6395 GtkWidget* gtk_alignment_new( gfloat xalign,
6396                               gfloat yalign,
6397                               gfloat xscale,
6398                               gfloat yscale );
6399
6400 void gtk_alignment_set( GtkAlignment *alignment,
6401                         gfloat        xalign,
6402                         gfloat        yalign,
6403                         gfloat        xscale,
6404                         gfloat        yscale );
6405 </programlisting>
6406
6407 <para>The first function creates a new Alignment widget with the specified
6408 parameters. The second function allows the alignment parameters of an
6409 exisiting Alignment widget to be altered.</para>
6410
6411 <para>All four alignment parameters are floating point numbers which can
6412 range from 0.0 to 1.0. The <literal>xalign</literal> and <literal>yalign</literal> arguments
6413 affect the position of the widget placed within the Alignment
6414 widget. The <literal>xscale</literal> and <literal>yscale</literal> arguments affect the amount of
6415 space allocated to the widget.</para>
6416
6417 <para>A child widget can be added to this Alignment widget using:</para>
6418
6419 <programlisting role="C">
6420     gtk_container_add (GTK_CONTAINER (alignment), child_widget);
6421 </programlisting>
6422
6423 <para>For an example of using an Alignment widget, refer to the example for
6424 the <link linkend="sec-ProgressBars">Progress Bar</link> widget.</para>
6425
6426 </sect1>
6427
6428 <!-- ----------------------------------------------------------------- -->
6429 <sect1 id="sec-FixedContainer">
6430 <title>Fixed Container</title>
6431
6432 <para>The Fixed container allows you to place widgets at a fixed position
6433 within it's window, relative to it's upper left hand corner. The
6434 position of the widgets can be changed dynamically.</para>
6435
6436 <para>There are only a few functions associated with the fixed widget:</para>
6437
6438 <programlisting role="C">
6439 GtkWidget* gtk_fixed_new( void );
6440
6441 void gtk_fixed_put( GtkFixed  *fixed,
6442                     GtkWidget *widget,
6443                     gint       x,
6444                     gint       y );
6445
6446 void gtk_fixed_move( GtkFixed  *fixed,
6447                      GtkWidget *widget,
6448                      gint       x,
6449                      gint       y );
6450 </programlisting>
6451
6452 <para>The function gtk_fixed_new() allows you to create a new Fixed
6453 container.</para>
6454
6455 <para>gtk_fixed_put() places <literal>widget</literal> in the container <literal>fixed</literal> at
6456 the position specified by <literal>x</literal> and <literal>y</literal>.</para>
6457
6458 <para>gtk_fixed_move() allows the specified widget to be moved to a new
6459 position.</para>
6460
6461 <programlisting role="C">
6462 void gtk_widget_set_has_window( GtkWidget  *widget,
6463                                 gboolean    has_window );
6464
6465 gboolean gtk_widget_get_has_window( GtkWidget *widget );
6466 </programlisting>
6467
6468 <para>Normally, Fixed widgets don't have their own X window. Since this is
6469 different from the behaviour of Fixed widgets in earlier releases of GTK, 
6470 the function gtk_widget_set_has_window() allows the creation of Fixed widgets
6471 <emphasis>with</emphasis> their own window. It has to be called before
6472 realizing the widget.</para>
6473
6474 <para>The following example illustrates how to use the Fixed Container.</para>
6475
6476 <para>
6477 <inlinemediaobject>
6478 <imageobject>
6479 <imagedata fileref="images/fixed.png" format="png">
6480 </imageobject>
6481 </inlinemediaobject>
6482 </para>
6483
6484 <programlisting role="C">
6485 <!-- example-start fixed fixed.c -->
6486
6487 #include &lt;gtk/gtk.h&gt;
6488
6489 /* I'm going to be lazy and use some global variables to
6490  * store the position of the widget within the fixed
6491  * container */
6492 gint x = 50;
6493 gint y = 50;
6494
6495 /* This callback function moves the button to a new position
6496  * in the Fixed container. */
6497 static void move_button( GtkWidget *widget,
6498                          GtkWidget *fixed )
6499 {
6500   x = (x + 30) % 300;
6501   y = (y + 50) % 300;
6502   gtk_fixed_move (GTK_FIXED (fixed), widget, x, y); 
6503 }
6504
6505 int main( int   argc,
6506           char *argv[] )
6507 {
6508   /* GtkWidget is the storage type for widgets */
6509   GtkWidget *window;
6510   GtkWidget *fixed;
6511   GtkWidget *button;
6512   gint i;
6513
6514   /* Initialise GTK */
6515   gtk_init (&amp;argc, &amp;argv);
6516     
6517   /* Create a new window */
6518   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6519   gtk_window_set_title (GTK_WINDOW (window), "Fixed Container");
6520
6521   /* Here we connect the "destroy" event to a signal handler */ 
6522   g_signal_connect (window, "destroy",
6523                     G_CALLBACK (gtk_main_quit), NULL);
6524  
6525   /* Sets the border width of the window. */
6526   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6527
6528   /* Create a Fixed Container */
6529   fixed = gtk_fixed_new ();
6530   gtk_container_add (GTK_CONTAINER (window), fixed);
6531   gtk_widget_show (fixed);
6532   
6533   for (i = 1 ; i &lt;= 3 ; i++) {
6534     /* Creates a new button with the label "Press me" */
6535     button = gtk_button_new_with_label ("Press me");
6536   
6537     /* When the button receives the "clicked" signal, it will call the
6538      * function move_button() passing it the Fixed Container as its
6539      * argument. */
6540     g_signal_connect (button, "clicked",
6541                       G_CALLBACK (move_button), (gpointer) fixed);
6542   
6543     /* This packs the button into the fixed containers window. */
6544     gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
6545   
6546     /* The final step is to display this newly created widget. */
6547     gtk_widget_show (button);
6548   }
6549
6550   /* Display the window */
6551   gtk_widget_show (window);
6552     
6553   /* Enter the event loop */
6554   gtk_main ();
6555     
6556   return 0;
6557 }
6558 <!-- example-end -->
6559 </programlisting>
6560
6561 </sect1>
6562
6563 <!-- ----------------------------------------------------------------- -->
6564 <sect1 id="sec-LayoutContainer">
6565 <title>Layout Container</title>
6566
6567 <para>The Layout container is similar to the Fixed container except that it
6568 implements an infinite (where infinity is less than 2^32) scrolling
6569 area. The X window system has a limitation where windows can be at
6570 most 32767 pixels wide or tall. The Layout container gets around this
6571 limitation by doing some exotic stuff using window and bit gravities,
6572 so that you can have smooth scrolling even when you have many child
6573 widgets in your scrolling area.</para>
6574
6575 <para>A Layout container is created using:</para>
6576
6577 <programlisting role="C">
6578 GtkWidget *gtk_layout_new( GtkAdjustment *hadjustment,
6579                            GtkAdjustment *vadjustment );
6580 </programlisting>
6581
6582 <para>As you can see, you can optionally specify the Adjustment objects that
6583 the Layout widget will use for its scrolling.</para>
6584
6585 <para>You can add and move widgets in the Layout container using the
6586 following two functions:</para>
6587
6588 <programlisting role="C">
6589 void gtk_layout_put( GtkLayout *layout,
6590                      GtkWidget *widget,
6591                      gint       x,
6592                      gint       y );
6593
6594 void gtk_layout_move( GtkLayout *layout,
6595                       GtkWidget *widget,
6596                       gint       x,
6597                       gint       y );
6598 </programlisting>
6599
6600 <para>The size of the Layout container can be set using the next function:</para>
6601
6602 <programlisting role="C">
6603 void gtk_layout_set_size( GtkLayout *layout,
6604                           guint      width,
6605                           guint      height );
6606 </programlisting>
6607
6608 <para>The final four functions for use with Layout widgets are for
6609 manipulating the horizontal and vertical adjustment widgets:</para>
6610
6611 <programlisting role="C">
6612 GtkAdjustment* gtk_layout_get_hadjustment( GtkLayout *layout );
6613
6614 GtkAdjustment* gtk_layout_get_vadjustment( GtkLayout *layout );
6615
6616 void gtk_layout_set_hadjustment( GtkLayout     *layout,
6617                                  GtkAdjustment *adjustment );
6618
6619 void gtk_layout_set_vadjustment( GtkLayout     *layout,
6620                                  GtkAdjustment *adjustment);
6621 </programlisting>
6622
6623 </sect1>
6624
6625 <!-- ----------------------------------------------------------------- -->
6626 <sect1 id="sec-Frames">
6627 <title>Frames</title>
6628
6629 <para>Frames can be used to enclose one or a group of widgets with a box
6630 which can optionally be labelled. The position of the label and the
6631 style of the box can be altered to suit.</para>
6632
6633 <para>A Frame can be created with the following function:</para>
6634
6635 <programlisting role="C">
6636 GtkWidget *gtk_frame_new( const gchar *label );
6637 </programlisting>
6638
6639 <para>The label is by default placed in the upper left hand corner of the
6640 frame. A value of NULL for the <literal>label</literal> argument will result in no
6641 label being displayed. The text of the label can be changed using the
6642 next function.</para>
6643
6644 <programlisting role="C">
6645 void gtk_frame_set_label( GtkFrame    *frame,
6646                           const gchar *label );
6647 </programlisting>
6648
6649 <para>The position of the label can be changed using this function:</para>
6650
6651 <programlisting role="C">
6652 void gtk_frame_set_label_align( GtkFrame *frame,
6653                                 gfloat    xalign,
6654                                 gfloat    yalign );
6655 </programlisting>
6656
6657 <para><literal>xalign</literal> and <literal>yalign</literal> take values between 0.0 and 1.0. <literal>xalign</literal>
6658 indicates the position of the label along the top horizontal of the
6659 frame. <literal>yalign</literal> is not currently used. The default value of xalign
6660 is 0.0 which places the label at the left hand end of the frame.</para>
6661
6662 <para>The next function alters the style of the box that is used to outline
6663 the frame.</para>
6664
6665 <programlisting role="C">
6666 void gtk_frame_set_shadow_type( GtkFrame      *frame,
6667                                 GtkShadowType  type);
6668 </programlisting>
6669
6670 <para>The <literal>type</literal> argument can take one of the following values:</para>
6671 <programlisting role="C">
6672   GTK_SHADOW_NONE
6673   GTK_SHADOW_IN
6674   GTK_SHADOW_OUT
6675   GTK_SHADOW_ETCHED_IN (the default)
6676   GTK_SHADOW_ETCHED_OUT
6677 </programlisting>
6678
6679 <para>The following code example illustrates the use of the Frame widget.</para>
6680
6681 <para>
6682 <inlinemediaobject>
6683 <imageobject>
6684 <imagedata fileref="images/frame.png" format="png">
6685 </imageobject>
6686 </inlinemediaobject>
6687 </para>
6688
6689 <programlisting role="C">
6690 <!-- example-start frame frame.c -->
6691
6692 #include &lt;gtk/gtk.h&gt;
6693
6694 int main( int   argc,
6695           char *argv[] )
6696 {
6697   /* GtkWidget is the storage type for widgets */
6698   GtkWidget *window;
6699   GtkWidget *frame;
6700
6701   /* Initialise GTK */
6702   gtk_init (&amp;argc, &amp;argv);
6703     
6704   /* Create a new window */
6705   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6706   gtk_window_set_title (GTK_WINDOW (window), "Frame Example");
6707
6708   /* Here we connect the "destroy" event to a signal handler */ 
6709   g_signal_connect (window, "destroy",
6710                     G_CALLBACK (gtk_main_quit), NULL);
6711
6712   gtk_widget_set_size_request (window, 300, 300);
6713   /* Sets the border width of the window. */
6714   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6715
6716   /* Create a Frame */
6717   frame = gtk_frame_new (NULL);
6718   gtk_container_add (GTK_CONTAINER (window), frame);
6719
6720   /* Set the frame's label */
6721   gtk_frame_set_label (GTK_FRAME (frame), "GTK Frame Widget");
6722
6723   /* Align the label at the right of the frame */
6724   gtk_frame_set_label_align (GTK_FRAME (frame), 1.0, 0.0);
6725
6726   /* Set the style of the frame */
6727   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);
6728
6729   gtk_widget_show (frame);
6730   
6731   /* Display the window */
6732   gtk_widget_show (window);
6733     
6734   /* Enter the event loop */
6735   gtk_main ();
6736     
6737   return 0;
6738 }
6739 <!-- example-end -->
6740 </programlisting>
6741 </sect1>
6742
6743 <!-- ----------------------------------------------------------------- -->   
6744 <sect1 id="sec-AspectFrames">
6745 <title>Aspect Frames</title>
6746
6747 <para>The aspect frame widget is like a frame widget, except that it also
6748 enforces the aspect ratio (that is, the ratio of the width to the
6749 height) of the child widget to have a certain value, adding extra
6750 space if necessary. This is useful, for instance, if you want to
6751 preview a larger image. The size of the preview should vary when the
6752 user resizes the window, but the aspect ratio needs to always match
6753 the original image.</para>
6754   
6755 <para>To create a new aspect frame use:</para>
6756
6757 <programlisting role="C">
6758 GtkWidget *gtk_aspect_frame_new( const gchar *label,
6759                                  gfloat       xalign,
6760                                  gfloat       yalign,
6761                                  gfloat       ratio,
6762                                  gboolean     obey_child);
6763 </programlisting>
6764    
6765 <para><literal>xalign</literal> and <literal>yalign</literal> specify alignment as with Alignment
6766 widgets. If <literal>obey_child</literal> is TRUE, the aspect ratio of a child
6767 widget will match the aspect ratio of the ideal size it requests.
6768 Otherwise, it is given by <literal>ratio</literal>.</para>
6769    
6770 <para>To change the options of an existing aspect frame, you can use:</para>
6771
6772 <programlisting role="C">
6773 void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
6774                            gfloat          xalign,
6775                            gfloat          yalign,
6776                            gfloat          ratio,
6777                            gboolean        obey_child);
6778 </programlisting>
6779    
6780 <para>As an example, the following program uses an AspectFrame to present a
6781 drawing area whose aspect ratio will always be 2:1, no matter how the
6782 user resizes the top-level window.</para>
6783
6784 <para>
6785 <inlinemediaobject>
6786 <imageobject>
6787 <imagedata fileref="images/aspectframe.png" format="png">
6788 </imageobject>
6789 </inlinemediaobject>
6790 </para>
6791
6792 <programlisting role="C">
6793 <!-- example-start aspectframe aspectframe.c -->
6794
6795 #include &lt;gtk/gtk.h&gt;
6796    
6797 int main( int argc,
6798           char *argv[] )
6799 {
6800     GtkWidget *window;
6801     GtkWidget *aspect_frame;
6802     GtkWidget *drawing_area;
6803     gtk_init (&amp;argc, &amp;argv);
6804    
6805     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6806     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
6807     g_signal_connect (window, "destroy",
6808                       G_CALLBACK (gtk_main_quit), NULL);
6809     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6810    
6811     /* Create an aspect_frame and add it to our toplevel window */
6812    
6813     aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
6814                                          0.5, /* center x */
6815                                          0.5, /* center y */
6816                                          2, /* xsize/ysize = 2 */
6817                                          FALSE /* ignore child's aspect */);
6818    
6819     gtk_container_add (GTK_CONTAINER (window), aspect_frame);
6820     gtk_widget_show (aspect_frame);
6821    
6822     /* Now add a child widget to the aspect frame */
6823    
6824     drawing_area = gtk_drawing_area_new ();
6825    
6826     /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
6827      * window since we are forcing a 2x1 aspect ratio */
6828     gtk_widget_set_size_request (drawing_area, 200, 200);
6829     gtk_container_add (GTK_CONTAINER (aspect_frame), drawing_area);
6830     gtk_widget_show (drawing_area);
6831    
6832     gtk_widget_show (window);
6833     gtk_main ();
6834     return 0;
6835 }
6836 <!-- example-end -->
6837 </programlisting>
6838
6839 </sect1>
6840
6841 <!-- ----------------------------------------------------------------- -->   
6842 <sect1 id="sec-PanedWindowWidgets">
6843 <title>Paned Window Widgets</title>
6844
6845 <para>The paned window widgets are useful when you want to divide an area
6846 into two parts, with the relative size of the two parts controlled by
6847 the user. A groove is drawn between the two portions with a handle
6848 that the user can drag to change the ratio. The division can either be
6849 horizontal (HPaned) or vertical (VPaned).</para>
6850    
6851 <para>To create a new paned window, call one of:</para>
6852
6853 <programlisting role="C">
6854 GtkWidget *gtk_hpaned_new (void);
6855
6856 GtkWidget *gtk_vpaned_new (void);
6857 </programlisting>
6858
6859 <para>After creating the paned window widget, you need to add child widgets
6860 to its two halves. To do this, use the functions:</para>
6861
6862 <programlisting role="C">
6863 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
6864
6865 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
6866 </programlisting>
6867
6868 <para><literal>gtk_paned_add1()</literal> adds the child widget to the left or top half of
6869 the paned window. <literal>gtk_paned_add2()</literal> adds the child widget to the
6870 right or bottom half of the paned window.</para>
6871
6872 <para>As an example, we will create part of the user interface of an
6873 imaginary email program. A window is divided into two portions
6874 vertically, with the top portion being a list of email messages and
6875 the bottom portion the text of the email message. Most of the program
6876 is pretty straightforward. A couple of points to note: text can't be
6877 added to a Text widget until it is realized. This could be done by
6878 calling gtk_widget_realize(), but as a demonstration of an
6879 alternate technique, we connect a handler to the "realize" signal to
6880 add the text. Also, we need to add the <literal>GTK_SHRINK</literal> option to some
6881 of the items in the table containing the text window and its
6882 scrollbars, so that when the bottom portion is made smaller, the
6883 correct portions shrink instead of being pushed off the bottom of the
6884 window.</para>
6885
6886 <para>
6887 <inlinemediaobject>
6888 <imageobject>
6889 <imagedata fileref="images/paned.png" format="png">
6890 </imageobject>
6891 </inlinemediaobject>
6892 </para>
6893
6894 <programlisting role="C">
6895 <!-- example-start paned paned.c -->
6896
6897 #include &lt;stdio.h&gt;
6898 #include &lt;gtk/gtk.h&gt;
6899    
6900 /* Create the list of "messages" */
6901 static GtkWidget *create_list( void )
6902 {
6903
6904     GtkWidget *scrolled_window;
6905     GtkWidget *tree_view;
6906     GtkListStore *model;
6907     GtkTreeIter iter;
6908     GtkCellRenderer *cell;
6909     GtkTreeViewColumn *column;
6910
6911     int i;
6912    
6913     /* Create a new scrolled window, with scrollbars only if needed */
6914     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6915     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6916                                     GTK_POLICY_AUTOMATIC, 
6917                                     GTK_POLICY_AUTOMATIC);
6918    
6919     model = gtk_list_store_new (1, G_TYPE_STRING);
6920     tree_view = gtk_tree_view_new ();
6921     gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
6922     gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view), GTK_TREE_MODEL (model));
6923     gtk_widget_show (tree_view);
6924    
6925     /* Add some messages to the window */
6926     for (i = 0; i &lt; 10; i++) {
6927         gchar *msg = g_strdup_printf ("Message #%d", i);
6928         gtk_list_store_append (GTK_LIST_STORE (model), &amp;iter);
6929         gtk_list_store_set (GTK_LIST_STORE (model), 
6930                             &amp;iter,
6931                             0, msg,
6932                             -1);
6933         g_free (msg);
6934     }
6935    
6936     cell = gtk_cell_renderer_text_new ();
6937
6938     column = gtk_tree_view_column_new_with_attributes ("Messages",
6939                                                        cell,
6940                                                        "text", 0,
6941                                                        NULL);
6942   
6943     gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view),
6944                                  GTK_TREE_VIEW_COLUMN (column));
6945
6946     return scrolled_window;
6947 }
6948    
6949 /* Add some text to our text widget - this is a callback that is invoked
6950 when our window is realized. We could also force our window to be
6951 realized with gtk_widget_realize, but it would have to be part of
6952 a hierarchy first */
6953
6954 static void insert_text( GtkTextBuffer *buffer )
6955 {
6956    GtkTextIter iter;
6957  
6958    gtk_text_buffer_get_iter_at_offset (buffer, &amp;iter, 0);
6959
6960    gtk_text_buffer_insert (buffer, &amp;iter,   
6961     "From: pathfinder@nasa.gov\n"
6962     "To: mom@nasa.gov\n"
6963     "Subject: Made it!\n"
6964     "\n"
6965     "We just got in this morning. The weather has been\n"
6966     "great - clear but cold, and there are lots of fun sights.\n"
6967     "Sojourner says hi. See you soon.\n"
6968     " -Path\n", -1);
6969 }
6970    
6971 /* Create a scrolled text area that displays a "message" */
6972 static GtkWidget *create_text( void )
6973 {
6974    GtkWidget *scrolled_window;
6975    GtkWidget *view;
6976    GtkTextBuffer *buffer;
6977
6978    view = gtk_text_view_new ();
6979    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
6980
6981    scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6982    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6983                                    GTK_POLICY_AUTOMATIC,
6984                                    GTK_POLICY_AUTOMATIC);
6985
6986    gtk_container_add (GTK_CONTAINER (scrolled_window), view);
6987    insert_text (buffer);
6988
6989    gtk_widget_show_all (scrolled_window);
6990
6991    return scrolled_window;
6992 }
6993    
6994 int main( int   argc,
6995           char *argv[] )
6996 {
6997     GtkWidget *window;
6998     GtkWidget *vpaned;
6999     GtkWidget *list;
7000     GtkWidget *text;
7001
7002     gtk_init (&amp;argc, &amp;argv);
7003    
7004     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7005     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
7006     g_signal_connect (window, "destroy",
7007                       G_CALLBACK (gtk_main_quit), NULL);
7008     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7009     gtk_widget_set_size_request (GTK_WIDGET (window), 450, 400);
7010
7011     /* create a vpaned widget and add it to our toplevel window */
7012    
7013     vpaned = gtk_vpaned_new ();
7014     gtk_container_add (GTK_CONTAINER (window), vpaned);
7015     gtk_widget_show (vpaned);
7016    
7017     /* Now create the contents of the two halves of the window */
7018    
7019     list = create_list ();
7020     gtk_paned_add1 (GTK_PANED (vpaned), list);
7021     gtk_widget_show (list);
7022    
7023     text = create_text ();
7024     gtk_paned_add2 (GTK_PANED (vpaned), text);
7025     gtk_widget_show (text);
7026     gtk_widget_show (window);
7027
7028     gtk_main ();
7029
7030     return 0;
7031 }
7032 <!-- example-end -->
7033 </programlisting>
7034
7035 </sect1>
7036
7037 <!-- ----------------------------------------------------------------- -->
7038 <sect1 id="sec-Viewports">
7039 <title>Viewports</title>
7040
7041 <para>It is unlikely that you will ever need to use the Viewport widget
7042 directly. You are much more likely to use the
7043 <link linkend="sec-ScrolledWindows">Scrolled Window</link> widget which
7044 itself uses the Viewport.</para>
7045
7046 <para>A viewport widget allows you to place a larger widget within it such
7047 that you can view a part of it at a time. It uses
7048 <link linkend="ch-Adjustments">Adjustments</link> to define the area that
7049 is currently in view.</para>
7050
7051 <para>A Viewport is created with the function</para>
7052
7053 <programlisting role="C">
7054 GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment,
7055                              GtkAdjustment *vadjustment );
7056 </programlisting>
7057
7058 <para>As you can see you can specify the horizontal and vertical Adjustments
7059 that the widget is to use when you create the widget. It will create
7060 its own if you pass NULL as the value of the arguments.</para>
7061
7062 <para>You can get and set the adjustments after the widget has been created
7063 using the following four functions:</para>
7064
7065 <programlisting role="C">
7066 GtkAdjustment *gtk_viewport_get_hadjustment( GtkViewport *viewport );
7067
7068 GtkAdjustment *gtk_viewport_get_vadjustment( GtkViewport *viewport );
7069
7070 void gtk_viewport_set_hadjustment( GtkViewport   *viewport,
7071                                    GtkAdjustment *adjustment );
7072
7073 void gtk_viewport_set_vadjustment( GtkViewport   *viewport,
7074                                    GtkAdjustment *adjustment );
7075 </programlisting>
7076
7077 <para>The only other viewport function is used to alter its appearance:</para>
7078
7079 <programlisting role="C">
7080 void gtk_viewport_set_shadow_type( GtkViewport   *viewport,
7081                                    GtkShadowType  type );
7082 </programlisting>
7083
7084 <para>Possible values for the <literal>type</literal> parameter are:</para>
7085 <programlisting role="C">
7086   GTK_SHADOW_NONE,
7087   GTK_SHADOW_IN,
7088   GTK_SHADOW_OUT,
7089   GTK_SHADOW_ETCHED_IN,
7090   GTK_SHADOW_ETCHED_OUT
7091 </programlisting>
7092  
7093 </sect1>
7094
7095 <!-- ----------------------------------------------------------------- -->
7096 <sect1 id="sec-ScrolledWindows"
7097 <title>Scrolled Windows</title>
7098
7099 <para>Scrolled windows are used to create a scrollable area with another
7100 widget inside it. You may insert any type of widget into a scrolled
7101 window, and it will be accessible regardless of the size by using the
7102 scrollbars.</para>
7103
7104 <para>The following function is used to create a new scrolled window.</para>
7105
7106 <programlisting role="C">
7107 GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
7108                                     GtkAdjustment *vadjustment );
7109 </programlisting>
7110
7111 <para>Where the first argument is the adjustment for the horizontal
7112 direction, and the second, the adjustment for the vertical direction.
7113 These are almost always set to NULL.</para>
7114
7115 <programlisting role="C">
7116 void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
7117                                      GtkPolicyType      hscrollbar_policy,
7118                                      GtkPolicyType      vscrollbar_policy );
7119 </programlisting>
7120
7121 <para>This sets the policy to be used with respect to the scrollbars.
7122 The first argument is the scrolled window you wish to change. The second
7123 sets the policy for the horizontal scrollbar, and the third the policy for 
7124 the vertical scrollbar.</para>
7125
7126 <para>The policy may be one of <literal>GTK_POLICY_AUTOMATIC</literal> or
7127 <literal>GTK_POLICY_ALWAYS</literal>. <literal>GTK_POLICY_AUTOMATIC</literal> will automatically
7128 decide whether you need scrollbars, whereas <literal>GTK_POLICY_ALWAYS</literal>
7129 will always leave the scrollbars there.</para>
7130
7131 <para>You can then place your object into the scrolled window using the
7132 following function.</para>
7133
7134 <programlisting role="C">
7135 void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
7136                                             GtkWidget         *child);
7137 </programlisting>
7138
7139 <para>Here is a simple example that packs a table with 100 toggle buttons
7140 into a scrolled window. I've only commented on the parts that may be
7141 new to you.</para>
7142
7143 <para>
7144 <inlinemediaobject>
7145 <imageobject>
7146 <imagedata fileref="images/scrolledwin.png" format="png">
7147 </imageobject>
7148 </inlinemediaobject>
7149 </para>
7150
7151 <programlisting role="C">
7152 <!-- example-start scrolledwin scrolledwin.c -->
7153
7154 #include &lt;stdio.h&gt;
7155 #include &lt;gtk/gtk.h&gt;
7156
7157 static void destroy( GtkWidget *widget,
7158                      gpointer   data )
7159 {
7160     gtk_main_quit ();
7161 }
7162
7163 int main( int   argc,
7164           char *argv[] )
7165 {
7166     static GtkWidget *window;
7167     GtkWidget *scrolled_window;
7168     GtkWidget *table;
7169     GtkWidget *button;
7170     char buffer[32];
7171     int i, j;
7172     
7173     gtk_init (&amp;argc, &amp;argv);
7174     
7175     /* Create a new dialog window for the scrolled window to be
7176      * packed into.  */
7177     window = gtk_dialog_new ();
7178     g_signal_connect (window, "destroy",
7179                       G_CALLBACK (destroy), NULL);
7180     gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
7181     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7182     gtk_widget_set_size_request (window, 300, 300);
7183     
7184     /* create a new scrolled window. */
7185     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
7186     
7187     gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
7188     
7189     /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
7190      * GTK_POLICY_AUTOMATIC will automatically decide whether you need
7191      * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
7192      * there.  The first one is the horizontal scrollbar, the second, 
7193      * the vertical. */
7194     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
7195                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
7196     /* The dialog window is created with a vbox packed into it. */                                                              
7197     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)-&gt;vbox), scrolled_window, 
7198                         TRUE, TRUE, 0);
7199     gtk_widget_show (scrolled_window);
7200     
7201     /* create a table of 10 by 10 squares. */
7202     table = gtk_table_new (10, 10, FALSE);
7203     
7204     /* set the spacing to 10 on x and 10 on y */
7205     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
7206     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
7207     
7208     /* pack the table into the scrolled window */
7209     gtk_scrolled_window_add_with_viewport (
7210                    GTK_SCROLLED_WINDOW (scrolled_window), table);
7211     gtk_widget_show (table);
7212     
7213     /* this simply creates a grid of toggle buttons on the table
7214      * to demonstrate the scrolled window. */
7215     for (i = 0; i &lt; 10; i++)
7216        for (j = 0; j &lt; 10; j++) {
7217           sprintf (buffer, "button (%d,%d)\n", i, j);
7218           button = gtk_toggle_button_new_with_label (buffer);
7219           gtk_table_attach_defaults (GTK_TABLE (table), button,
7220                                      i, i+1, j, j+1);
7221           gtk_widget_show (button);
7222        }
7223     
7224     /* Add a "close" button to the bottom of the dialog */
7225     button = gtk_button_new_with_label ("close");
7226     g_signal_connect_swapped (button, "clicked",
7227                               G_CALLBACK (gtk_widget_destroy),
7228                               window);
7229     
7230     /* this makes it so the button is the default. */
7231     
7232     gtk_widget_set_can_default (button, TRUE);
7233     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)-&gt;action_area), button, TRUE, TRUE, 0);
7234     
7235     /* This grabs this button to be the default button. Simply hitting
7236      * the "Enter" key will cause this button to activate. */
7237     gtk_widget_grab_default (button);
7238     gtk_widget_show (button);
7239     
7240     gtk_widget_show (window);
7241     
7242     gtk_main();
7243     
7244     return 0;
7245 }
7246 <!-- example-end -->
7247 </programlisting>
7248
7249 <para>Try playing with resizing the window. You'll notice how the scrollbars
7250 react. You may also wish to use the gtk_widget_set_size_request() call to set
7251 the default size of the window or other widgets.</para>
7252
7253 </sect1>
7254
7255 <!-- ----------------------------------------------------------------- -->   
7256 <sect1 id="sec-ButtonBoxes">
7257 <title>Button Boxes</title>
7258
7259 <para>Button Boxes are a convenient way to quickly layout a group of
7260 buttons. They come in both horizontal and vertical flavours. You
7261 create a new Button Box with one of the following calls, which create
7262 a horizontal or vertical box, respectively:</para>
7263
7264 <programlisting role="C">
7265 GtkWidget *gtk_hbutton_box_new( void );
7266
7267 GtkWidget *gtk_vbutton_box_new( void );
7268 </programlisting>
7269
7270 <para>Buttons are added to a Button Box using the usual function:</para>
7271
7272 <programlisting role="C">
7273     gtk_container_add (GTK_CONTAINER (button_box), child_widget);
7274 </programlisting>
7275
7276 <para>Here's an example that illustrates all the different layout settings
7277 for Button Boxes.</para>
7278
7279 <para>
7280 <inlinemediaobject>
7281 <imageobject>
7282 <imagedata fileref="images/buttonbox.png" format="png">
7283 </imageobject>
7284 </inlinemediaobject>
7285 </para>
7286
7287 <programlisting role="C">
7288 <!-- example-start buttonbox buttonbox.c -->
7289
7290 #include &lt;gtk/gtk.h&gt;
7291
7292 /* Create a Button Box with the specified parameters */
7293 static GtkWidget *create_bbox( gint  horizontal,
7294                                char *title,
7295                                gint  spacing,
7296                                gint  child_w,
7297                                gint  child_h,
7298                                gint  layout )
7299 {
7300   GtkWidget *frame;
7301   GtkWidget *bbox;
7302   GtkWidget *button;
7303
7304   frame = gtk_frame_new (title);
7305
7306   if (horizontal)
7307     bbox = gtk_hbutton_box_new ();
7308   else
7309     bbox = gtk_vbutton_box_new ();
7310
7311   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
7312   gtk_container_add (GTK_CONTAINER (frame), bbox);
7313
7314   /* Set the appearance of the Button Box */
7315   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
7316   gtk_box_set_spacing (GTK_BOX (bbox), spacing);
7317
7318   button = gtk_button_new_from_stock (GTK_STOCK_OK);
7319   gtk_container_add (GTK_CONTAINER (bbox), button);
7320
7321   button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
7322   gtk_container_add (GTK_CONTAINER (bbox), button);
7323
7324   button = gtk_button_new_from_stock (GTK_STOCK_HELP);
7325   gtk_container_add (GTK_CONTAINER (bbox), button);
7326
7327   return frame;
7328 }
7329
7330 int main( int   argc,
7331           char *argv[] )
7332 {
7333   static GtkWidget* window = NULL;
7334   GtkWidget *main_vbox;
7335   GtkWidget *vbox;
7336   GtkWidget *hbox;
7337   GtkWidget *frame_horz;
7338   GtkWidget *frame_vert;
7339
7340   /* Initialize GTK */
7341   gtk_init (&amp;argc, &amp;argv);
7342
7343   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7344   gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
7345
7346   g_signal_connect (window, "destroy",
7347                     G_CALLBACK (gtk_main_quit),
7348                     NULL);
7349
7350   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7351
7352   main_vbox = gtk_vbox_new (FALSE, 0);
7353   gtk_container_add (GTK_CONTAINER (window), main_vbox);
7354
7355   frame_horz = gtk_frame_new ("Horizontal Button Boxes");
7356   gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
7357
7358   vbox = gtk_vbox_new (FALSE, 0);
7359   gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
7360   gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
7361
7362   gtk_box_pack_start (GTK_BOX (vbox),
7363            create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
7364                       TRUE, TRUE, 0);
7365
7366   gtk_box_pack_start (GTK_BOX (vbox),
7367            create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
7368                       TRUE, TRUE, 5);
7369
7370   gtk_box_pack_start (GTK_BOX (vbox),
7371            create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
7372                       TRUE, TRUE, 5);
7373
7374   gtk_box_pack_start (GTK_BOX (vbox),
7375            create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END),
7376                       TRUE, TRUE, 5);
7377
7378   frame_vert = gtk_frame_new ("Vertical Button Boxes");
7379   gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
7380
7381   hbox = gtk_hbox_new (FALSE, 0);
7382   gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
7383   gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
7384
7385   gtk_box_pack_start (GTK_BOX (hbox),
7386            create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD),
7387                       TRUE, TRUE, 0);
7388
7389   gtk_box_pack_start (GTK_BOX (hbox),
7390            create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
7391                       TRUE, TRUE, 5);
7392
7393   gtk_box_pack_start (GTK_BOX (hbox),
7394            create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
7395                       TRUE, TRUE, 5);
7396
7397   gtk_box_pack_start (GTK_BOX (hbox),
7398            create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END),
7399                       TRUE, TRUE, 5);
7400
7401   gtk_widget_show_all (window);
7402
7403   /* Enter the event loop */
7404   gtk_main ();
7405     
7406   return 0;
7407 }
7408 <!-- example-end -->
7409 </programlisting>
7410
7411 </sect1>
7412
7413 <!-- ----------------------------------------------------------------- -->   
7414 <sect1 id="sec-Toolbar">
7415 <title>Toolbar</title>
7416
7417 <para>Toolbars are usually used to group some number of widgets in order to
7418 simplify customization of their look and layout. Typically a toolbar
7419 consists of buttons with icons, labels and tooltips, but any other
7420 widget can also be put inside a toolbar. Finally, items can be
7421 arranged horizontally or vertically and buttons can be displayed with
7422 icons, labels, or both.</para>
7423
7424 <para>Creating a toolbar is (as one may already suspect) done with the
7425 following function:</para>
7426
7427 <programlisting role="C">
7428 GtkWidget *gtk_toolbar_new( void );
7429 </programlisting>
7430
7431 <para>After creating a toolbar one can append, prepend and insert items
7432 (that means simple text strings) or elements (that means any widget
7433 types) into the toolbar. To describe an item we need a label text, a
7434 tooltip text, a private tooltip text, an icon for the button and a
7435 callback function for it. For example, to append or prepend an item
7436 you may use the following functions:</para>
7437
7438 <programlisting role="C">
7439 GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
7440                                     const char    *text,
7441                                     const char    *tooltip_text,
7442                                     const char    *tooltip_private_text,
7443                                     GtkWidget     *icon,
7444                                     GtkSignalFunc  callback,
7445                                     gpointer       user_data );
7446
7447 GtkWidget *gtk_toolbar_prepend_item( GtkToolbar    *toolbar,
7448                                      const char    *text,
7449                                      const char    *tooltip_text,
7450                                      const char    *tooltip_private_text,
7451                                      GtkWidget     *icon,
7452                                      GtkSignalFunc  callback,
7453                                      gpointer       user_data );
7454 </programlisting>
7455
7456 <para>If you want to use gtk_toolbar_insert_item(), the only additional
7457 parameter which must be specified is the position in which the item
7458 should be inserted, thus:</para>
7459
7460 <programlisting role="C">
7461 GtkWidget *gtk_toolbar_insert_item( GtkToolbar    *toolbar,
7462                                     const char    *text,
7463                                     const char    *tooltip_text,
7464                                     const char    *tooltip_private_text,
7465                                     GtkWidget     *icon,
7466                                     GtkSignalFunc  callback,
7467                                     gpointer       user_data,
7468                                     gint           position );
7469 </programlisting>
7470
7471 <para>To simplify adding spaces between toolbar items, you may use the
7472 following functions:</para>
7473
7474 <programlisting role="C">
7475 void gtk_toolbar_append_space( GtkToolbar *toolbar );
7476
7477 void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
7478
7479 void gtk_toolbar_insert_space( GtkToolbar *toolbar,
7480                                gint        position );
7481 </programlisting>
7482
7483 <para>If it's required, the orientation of a toolbar and its style can be
7484 changed "on the fly" using the following functions:</para>
7485
7486 <programlisting role="C">
7487 void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
7488                                   GtkOrientation  orientation );
7489
7490 void gtk_toolbar_set_style( GtkToolbar      *toolbar,
7491                             GtkToolbarStyle  style );
7492
7493 void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
7494                                gint        enable );
7495 </programlisting>
7496
7497 <para>Where <literal>orientation</literal> is one of <literal>GTK_ORIENTATION_HORIZONTAL</literal> or
7498 <literal>GTK_ORIENTATION_VERTICAL</literal>. The <literal>style</literal> is used to set
7499 appearance of the toolbar items by using one of
7500 <literal>GTK_TOOLBAR_ICONS</literal>, <literal>GTK_TOOLBAR_TEXT</literal>, or
7501 <literal>GTK_TOOLBAR_BOTH</literal>.</para>
7502
7503 <para>To show some other things that can be done with a toolbar, let's take
7504 the following program (we'll interrupt the listing with some
7505 additional explanations):</para>
7506
7507 <programlisting role="C">
7508 #include &lt;gtk/gtk.h&gt;
7509
7510 /* This function is connected to the Close button or
7511  * closing the window from the WM */
7512 static gboolean delete_event( GtkWidget *widget,
7513                               GdkEvent *event,
7514                               gpointer data )
7515 {
7516   gtk_main_quit ();
7517   return FALSE;
7518 }
7519 </programlisting>
7520
7521 <para>The above beginning seems for sure familiar to you if it's not your first
7522 GTK program. There is one additional thing though, we include a nice XPM
7523 picture to serve as an icon for all of the buttons.</para>
7524
7525 <programlisting role="C">
7526 GtkWidget* close_button; /* This button will emit signal to close
7527                           * application */
7528 GtkWidget* tooltips_button; /* to enable/disable tooltips */
7529 GtkWidget* text_button,
7530          * icon_button,
7531          * both_button; /* radio buttons for toolbar style */
7532 GtkWidget* entry; /* a text entry to show packing any widget into
7533                    * toolbar */
7534 </programlisting>
7535
7536 <para>In fact not all of the above widgets are needed here, but to make things
7537 clearer I put them all together.</para>
7538
7539 <programlisting role="C">
7540 /* that's easy... when one of the buttons is toggled, we just
7541  * check which one is active and set the style of the toolbar
7542  * accordingly
7543  * ATTENTION: our toolbar is passed as data to callback ! */
7544 static void radio_event( GtkWidget *widget,
7545                          gpointer data )
7546 {
7547   if (GTK_TOGGLE_BUTTON (text_button)->active) 
7548     gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_TEXT);
7549   else if (GTK_TOGGLE_BUTTON (icon_button)->active)
7550     gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_ICONS);
7551   else if (GTK_TOGGLE_BUTTON (both_button)->active)
7552     gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH);
7553 }
7554
7555 /* even easier, just check given toggle button and enable/disable 
7556  * tooltips */
7557 static void toggle_event( GtkWidget *widget,
7558                           gpointer   data )
7559 {
7560   gtk_toolbar_set_tooltips (GTK_TOOLBAR (data),
7561                             GTK_TOGGLE_BUTTON (widget)->active );
7562 }
7563 </programlisting>
7564
7565 <para>The above are just two callback functions that will be called when
7566 one of the buttons on a toolbar is pressed. You should already be
7567 familiar with things like this if you've already used toggle buttons (and
7568 radio buttons).</para>
7569
7570 <programlisting role="C">
7571 int main (int argc, char *argv[])
7572 {
7573   /* Here is our main window (a dialog) and a handle for the handlebox */
7574   GtkWidget* dialog;
7575   GtkWidget* handlebox;
7576
7577   /* Ok, we need a toolbar, an icon with a mask (one for all of 
7578      the buttons) and an icon widget to put this icon in (but 
7579      we'll create a separate widget for each button) */
7580   GtkWidget * toolbar;
7581   GtkWidget * iconw;
7582
7583   /* this is called in all GTK application. */
7584   gtk_init (&amp;argc, &amp;argv);
7585   
7586   /* create a new window with a given title, and nice size */
7587   dialog = gtk_dialog_new ();
7588   gtk_window_set_title (GTK_WINDOW (dialog), "GTKToolbar Tutorial");
7589   gtk_widget_set_size_request (GTK_WIDGET (dialog), 600, 300);
7590
7591   /* typically we quit if someone tries to close us */
7592   g_signal_connect (dialog, "delete-event",
7593                     G_CALLBACK (delete_event), NULL);
7594
7595   /* we need to realize the window because we use pixmaps for 
7596    * items on the toolbar in the context of it */
7597   gtk_widget_realize (dialog);
7598
7599   /* to make it nice we'll put the toolbar into the handle box, 
7600    * so that it can be detached from the main window */
7601   handlebox = gtk_handle_box_new ();
7602   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
7603                       handlebox, FALSE, FALSE, 5);
7604 </programlisting>
7605
7606 <para>The above should be similar to any other GTK application. Just
7607 initialization of GTK, creating the window, etc. There is only one
7608 thing that probably needs some explanation: a handle box. A handle box
7609 is just another box that can be used to pack widgets in to. The
7610 difference between it and typical boxes is that it can be detached
7611 from a parent window (or, in fact, the handle box remains in the
7612 parent, but it is reduced to a very small rectangle, while all of its
7613 contents are reparented to a new freely floating window). It is
7614 usually nice to have a detachable toolbar, so these two widgets occur
7615 together quite often.</para>
7616
7617 <programlisting role="C">
7618   /* toolbar will be horizontal, with both icons and text, and
7619    * with 5pxl spaces between items and finally, 
7620    * we'll also put it into our handlebox */
7621   toolbar = gtk_toolbar_new ();
7622   gtk_toolbar_set_orientation (GTK_TOOLBAR (toolbar), GTK_ORIENTATION_HORIZONTAL);
7623   gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH);
7624   gtk_container_set_border_width (GTK_CONTAINER (toolbar), 5);
7625   gtk_toolbar_set_space_size (GTK_TOOLBAR (toolbar), 5);
7626   gtk_container_add (GTK_CONTAINER (handlebox), toolbar);
7627 </programlisting>
7628
7629 <para>Well, what we do above is just a straightforward initialization of
7630 the toolbar widget.</para>
7631
7632 <programlisting role="C">
7633   /* our first item is &lt;close&gt; button */
7634   iconw = gtk_image_new_from_file ("gtk.xpm"); /* icon widget */
7635   close_button = 
7636     gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), /* our toolbar */
7637                              "Close",               /* button label */
7638                              "Closes this app",     /* this button's tooltip */
7639                              "Private",             /* tooltip private info */
7640                              iconw,                 /* icon widget */
7641                              G_CALLBACK (delete_event), /* a signal */
7642                              NULL);
7643   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar)); /* space after item */
7644 </programlisting>
7645
7646 <para>In the above code you see the simplest case: adding a button to
7647 toolbar.  Just before appending a new item, we have to construct an
7648 image widget to serve as an icon for this item; this step will have
7649 to be repeated for each new item. Just after the item we also add a
7650 space, so the following items will not touch each other. As you see
7651 gtk_toolbar_append_item() returns a pointer to our newly created button
7652 widget, so that we can work with it in the normal way.</para>
7653
7654 <programlisting role="C">
7655   /* now, let's make our radio buttons group... */
7656   iconw = gtk_image_new_from_file ("gtk.xpm");
7657   icon_button = gtk_toolbar_append_element (
7658                     GTK_TOOLBAR (toolbar),
7659                     GTK_TOOLBAR_CHILD_RADIOBUTTON, /* a type of element */
7660                     NULL,                          /* pointer to widget */
7661                     "Icon",                        /* label */
7662                     "Only icons in toolbar",       /* tooltip */
7663                     "Private",                     /* tooltip private string */
7664                     iconw,                         /* icon */
7665                     G_CALLBACK (radio_event), /* signal */
7666                     toolbar);                      /* data for signal */
7667   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
7668 </programlisting>
7669
7670 <para>Here we begin creating a radio buttons group. To do this we use
7671 gtk_toolbar_append_element.  In fact, using this function one can also
7672 +add simple items or even spaces (type = <literal>GTK_TOOLBAR_CHILD_SPACE</literal>
7673 or +<literal>GTK_TOOLBAR_CHILD_BUTTON</literal>). In the above case we start
7674 creating a radio group. In creating other radio buttons for this group
7675 a pointer to the previous button in the group is required, so that a
7676 list of buttons can be easily constructed (see the section on <link
7677 linkend="sec-RadioButtons">Radio Buttons</link> earlier in this
7678 tutorial).</para>
7679
7680 <programlisting role="C">
7681   /* following radio buttons refer to previous ones */
7682   iconw = gtk_image_new_from_file ("gtk.xpm");
7683   text_button = 
7684     gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
7685                                 GTK_TOOLBAR_CHILD_RADIOBUTTON,
7686                                 icon_button,
7687                                 "Text",
7688                                 "Only texts in toolbar",
7689                                 "Private",
7690                                 iconw,
7691                                 G_CALLBACK (radio_event),
7692                                 toolbar);
7693   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
7694                                           
7695   iconw = gtk_image_new_from_file ("gtk.xpm");
7696   both_button = 
7697     gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
7698                                 GTK_TOOLBAR_CHILD_RADIOBUTTON,
7699                                 text_button,
7700                                 "Both",
7701                                 "Icons and text in toolbar",
7702                                 "Private",
7703                                 iconw,
7704                                 G_CALLBACK (radio_event),
7705                                 toolbar);
7706   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
7707   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (both_button), TRUE);
7708 </programlisting>
7709
7710 <para>In the end we have to set the state of one of the buttons manually
7711 (otherwise they all stay in active state, preventing us from switching
7712 between them).</para>
7713
7714 <programlisting role="C">
7715   /* here we have just a simple toggle button */
7716   iconw = gtk_image_new_from_file ("gtk.xpm");
7717   tooltips_button = 
7718     gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
7719                                 GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
7720                                 NULL,
7721                                 "Tooltips",
7722                                 "Toolbar with or without tips",
7723                                 "Private",
7724                                 iconw,
7725                                 G_CALLBACK (toggle_event),
7726                                 toolbar);
7727   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
7728   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tooltips_button), TRUE);
7729 </programlisting>
7730
7731 <para>A toggle button can be created in the obvious way (if one knows how to create
7732 radio buttons already).</para>
7733
7734 <programlisting role="C">
7735   /* to pack a widget into toolbar, we only have to 
7736    * create it and append it with an appropriate tooltip */
7737   entry = gtk_entry_new ();
7738   gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), 
7739                              entry, 
7740                              "This is just an entry", 
7741                              "Private");
7742
7743   /* well, it isn't created within the toolbar, so we must still show it */
7744   gtk_widget_show (entry);
7745 </programlisting>
7746
7747 <para>As you see, adding any kind of widget to a toolbar is simple. The
7748 one thing you have to remember is that this widget must be shown manually
7749 (contrary to other items which will be shown together with the toolbar).</para>
7750
7751 <programlisting role="C">
7752   /* that's it ! let's show everything. */
7753   gtk_widget_show (toolbar);
7754   gtk_widget_show (handlebox);
7755   gtk_widget_show (dialog);
7756
7757   /* rest in gtk_main and wait for the fun to begin! */
7758   gtk_main ();
7759   
7760   return 0;
7761 }
7762 </programlisting>
7763
7764 <para>So, here we are at the end of toolbar tutorial. Of course, to appreciate
7765 it in full you need also this nice XPM icon, so here it is:</para>
7766
7767 <programlisting role="C">
7768 /* XPM */
7769 static char * gtk_xpm[] = {
7770 "32 39 5 1",
7771 ".      c none",
7772 "+      c black",
7773 "@      c #3070E0",
7774 "#      c #F05050",
7775 "$      c #35E035",
7776 "................+...............",
7777 "..............+++++.............",
7778 "............+++++@@++...........",
7779 "..........+++++@@@@@@++.........",
7780 "........++++@@@@@@@@@@++........",
7781 "......++++@@++++++++@@@++.......",
7782 ".....+++@@@+++++++++++@@@++.....",
7783 "...+++@@@@+++@@@@@@++++@@@@+....",
7784 "..+++@@@@+++@@@@@@@@+++@@@@@++..",
7785 ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
7786 ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
7787 ".+##++@@@@+++@@@+++++@@@@@@@@$@.",
7788 ".+###++@@@@+++@@@+++@@@@@++$$$@.",
7789 ".+####+++@@@+++++++@@@@@+@$$$$@.",
7790 ".+#####+++@@@@+++@@@@++@$$$$$$+.",
7791 ".+######++++@@@@@@@++@$$$$$$$$+.",
7792 ".+#######+##+@@@@+++$$$$$$@@$$+.",
7793 ".+###+++##+##+@@++@$$$$$$++$$$+.",
7794 ".+###++++##+##+@@$$$$$$$@+@$$@+.",
7795 ".+###++++++#+++@$$@+@$$@++$$$@+.",
7796 ".+####+++++++#++$$@+@$$++$$$$+..",
7797 ".++####++++++#++$$@+@$++@$$$$+..",
7798 ".+#####+++++##++$$++@+++$$$$$+..",
7799 ".++####+++##+#++$$+++++@$$$$$+..",
7800 ".++####+++####++$$++++++@$$$@+..",
7801 ".+#####++#####++$$+++@++++@$@+..",
7802 ".+#####++#####++$$++@$$@+++$@@..",
7803 ".++####++#####++$$++$$$$$+@$@++.",
7804 ".++####++#####++$$++$$$$$$$$+++.",
7805 ".+++####+#####++$$++$$$$$$$@+++.",
7806 "..+++#########+@$$+@$$$$$$+++...",
7807 "...+++########+@$$$$$$$$@+++....",
7808 ".....+++######+@$$$$$$$+++......",
7809 "......+++#####+@$$$$$@++........",
7810 ".......+++####+@$$$$+++.........",
7811 ".........++###+$$$@++...........",
7812 "..........++##+$@+++............",
7813 "...........+++++++..............",
7814 ".............++++..............."};
7815 </programlisting>
7816
7817 </sect1>
7818
7819 <!-- ----------------------------------------------------------------- -->
7820 <sect1 id="sec-Notebooks">
7821 <title>Notebooks</title>
7822
7823 <para>The NoteBook Widget is a collection of "pages" that overlap each
7824 other, each page contains different information with only one page
7825 visible at a time. This widget has become more common lately in GUI
7826 programming, and it is a good way to show blocks of similar
7827 information that warrant separation in their display.</para>
7828
7829 <para>The first function call you will need to know, as you can probably
7830 guess by now, is used to create a new notebook widget.</para>
7831
7832 <programlisting role="C">
7833 GtkWidget *gtk_notebook_new( void );
7834 </programlisting>
7835
7836 <para>Once the notebook has been created, there are a number of functions
7837 that operate on the notebook widget. Let's look at them individually.</para>
7838
7839 <para>The first one we will look at is how to position the page indicators.
7840 These page indicators or "tabs" as they are referred to, can be
7841 positioned in four ways: top, bottom, left, or right.</para>
7842
7843 <programlisting role="C">
7844 void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
7845                                GtkPositionType  pos );
7846 </programlisting>
7847
7848 <para>GtkPositionType will be one of the following, which are pretty self
7849 explanatory:</para>
7850 <programlisting role="C">
7851   GTK_POS_LEFT
7852   GTK_POS_RIGHT
7853   GTK_POS_TOP
7854   GTK_POS_BOTTOM
7855 </programlisting>
7856
7857 <para><literal>GTK_POS_TOP</literal> is the default.</para>
7858
7859 <para>Next we will look at how to add pages to the notebook. There are three
7860 ways to add pages to the NoteBook. Let's look at the first two
7861 together as they are quite similar.</para>
7862
7863 <programlisting role="C">
7864 void gtk_notebook_append_page( GtkNotebook *notebook,
7865                                GtkWidget   *child,
7866                                GtkWidget   *tab_label );
7867
7868 void gtk_notebook_prepend_page( GtkNotebook *notebook,
7869                                 GtkWidget   *child,
7870                                 GtkWidget   *tab_label );
7871 </programlisting>
7872
7873 <para>These functions add pages to the notebook by inserting them from the
7874 back of the notebook (append), or the front of the notebook (prepend).
7875 <literal>child</literal> is the widget that is placed within the notebook page, and
7876 <literal>tab_label</literal> is the label for the page being added. The <literal>child</literal>
7877 widget must be created separately, and is typically a set of options
7878 setup witin one of the other container widgets, such as a table.</para>
7879
7880 <para>The final function for adding a page to the notebook contains all of
7881 the properties of the previous two, but it allows you to specify what
7882 position you want the page to be in the notebook.</para>
7883
7884 <programlisting role="C">
7885 void gtk_notebook_insert_page( GtkNotebook *notebook,
7886                                GtkWidget   *child,
7887                                GtkWidget   *tab_label,
7888                                gint         position );
7889 </programlisting>
7890
7891 <para>The parameters are the same as _append_ and _prepend_ except it
7892 contains an extra parameter, <literal>position</literal>.  This parameter is used to
7893 specify what place this page will be inserted into the first page
7894 having position zero.</para>
7895
7896 <para>Now that we know how to add a page, lets see how we can remove a page
7897 from the notebook.</para>
7898
7899 <programlisting role="C">
7900 void gtk_notebook_remove_page( GtkNotebook *notebook,
7901                                gint         page_num );
7902 </programlisting>
7903
7904 <para>This function takes the page specified by <literal>page_num</literal> and removes it
7905 from the widget pointed to by <literal>notebook</literal>.</para>
7906
7907 <para>To find out what the current page is in a notebook use the function:</para>
7908
7909 <programlisting role="C">
7910 gint gtk_notebook_get_current_page( GtkNotebook *notebook );
7911 </programlisting>
7912
7913 <para>These next two functions are simple calls to move the notebook page
7914 forward or backward. Simply provide the respective function call with
7915 the notebook widget you wish to operate on. Note: When the NoteBook is
7916 currently on the last page, and gtk_notebook_next_page() is called, the
7917 notebook will wrap back to the first page. Likewise, if the NoteBook
7918 is on the first page, and gtk_notebook_prev_page() is called, the
7919 notebook will wrap to the last page.</para>
7920
7921 <programlisting role="C">
7922 void gtk_notebook_next_page( GtkNoteBook *notebook );
7923
7924 void gtk_notebook_prev_page( GtkNoteBook *notebook );
7925 </programlisting>
7926
7927 <para>This next function sets the "active" page. If you wish the notebook to
7928 be opened to page 5 for example, you would use this function.  Without
7929 using this function, the notebook defaults to the first page.</para>
7930
7931 <programlisting role="C">
7932 void gtk_notebook_set_current_page( GtkNotebook *notebook,
7933                                     gint         page_num );
7934 </programlisting>
7935
7936 <para>The next two functions add or remove the notebook page tabs and the
7937 notebook border respectively.</para>
7938
7939 <programlisting role="C">
7940 void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
7941                                  gboolean     show_tabs );
7942
7943 void gtk_notebook_set_show_border( GtkNotebook *notebook,
7944                                    gboolean     show_border );
7945 </programlisting>
7946
7947 <para>The next function is useful when the you have a large number of pages,
7948 and the tabs don't fit on the page. It allows the tabs to be scrolled
7949 through using two arrow buttons.</para>
7950
7951 <programlisting role="C">
7952 void gtk_notebook_set_scrollable( GtkNotebook *notebook,
7953                                   gboolean     scrollable );
7954 </programlisting>
7955
7956 <para><literal>show_tabs</literal>, <literal>show_border</literal> and <literal>scrollable</literal> can be either
7957 TRUE or FALSE.</para>
7958
7959 <para>Now let's look at an example, it is expanded from the 
7960 <filename>testgtk.c</filename> code
7961 that comes with the GTK distribution. This small program creates a
7962 window with a notebook and six buttons. The notebook contains 11
7963 pages, added in three different ways, appended, inserted, and
7964 prepended. The buttons allow you rotate the tab positions, add/remove
7965 the tabs and border, remove a page, change pages in both a forward and
7966 backward manner, and exit the program.</para>
7967
7968 <para>
7969 <inlinemediaobject>
7970 <imageobject>
7971 <imagedata fileref="images/notebook.png" format="png">
7972 </imageobject>
7973 </inlinemediaobject>
7974 </para>
7975
7976 <programlisting role="C">
7977 <!-- example-start notebook notebook.c -->
7978
7979 #include &lt;stdio.h&gt;
7980 #include &lt;gtk/gtk.h&gt;
7981
7982 /* This function rotates the position of the tabs */
7983 static void rotate_book( GtkButton   *button,
7984                          GtkNotebook *notebook )
7985 {
7986     gtk_notebook_set_tab_pos (notebook, (notebook-&gt;tab_pos + 1) % 4);
7987 }
7988
7989 /* Add/Remove the page tabs and the borders */
7990 static void tabsborder_book( GtkButton   *button,
7991                              GtkNotebook *notebook )
7992 {
7993     gint tval = FALSE;
7994     gint bval = FALSE;
7995     if (notebook-&gt;show_tabs == 0)
7996             tval = TRUE; 
7997     if (notebook-&gt;show_border == 0)
7998             bval = TRUE;
7999     
8000     gtk_notebook_set_show_tabs (notebook, tval);
8001     gtk_notebook_set_show_border (notebook, bval);
8002 }
8003
8004 /* Remove a page from the notebook */
8005 static void remove_book( GtkButton   *button,
8006                          GtkNotebook *notebook )
8007 {
8008     gint page;
8009     
8010     page = gtk_notebook_get_current_page (notebook);
8011     gtk_notebook_remove_page (notebook, page);
8012     /* Need to refresh the widget -- 
8013      This forces the widget to redraw itself. */
8014     gtk_widget_queue_draw (GTK_WIDGET (notebook));
8015 }
8016
8017 static gboolean delete( GtkWidget *widget,
8018                         GtkWidget *event,
8019                         gpointer   data )
8020 {
8021     gtk_main_quit ();
8022     return FALSE;
8023 }
8024
8025 int main( int argc,
8026           char *argv[] )
8027 {
8028     GtkWidget *window;
8029     GtkWidget *button;
8030     GtkWidget *table;
8031     GtkWidget *notebook;
8032     GtkWidget *frame;
8033     GtkWidget *label;
8034     GtkWidget *checkbutton;
8035     int i;
8036     char bufferf[32];
8037     char bufferl[32];
8038     
8039     gtk_init (&amp;argc, &amp;argv);
8040     
8041     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8042     
8043     g_signal_connect (window, "delete-event",
8044                       G_CALLBACK (delete), NULL);
8045     
8046     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8047
8048     table = gtk_table_new (3, 6, FALSE);
8049     gtk_container_add (GTK_CONTAINER (window), table);
8050     
8051     /* Create a new notebook, place the position of the tabs */
8052     notebook = gtk_notebook_new ();
8053     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
8054     gtk_table_attach_defaults (GTK_TABLE (table), notebook, 0, 6, 0, 1);
8055     gtk_widget_show (notebook);
8056     
8057     /* Let's append a bunch of pages to the notebook */
8058     for (i = 0; i &lt; 5; i++) {
8059         sprintf(bufferf, "Append Frame %d", i + 1);
8060         sprintf(bufferl, "Page %d", i + 1);
8061         
8062         frame = gtk_frame_new (bufferf);
8063         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
8064         gtk_widget_set_size_request (frame, 100, 75);
8065         gtk_widget_show (frame);
8066         
8067         label = gtk_label_new (bufferf);
8068         gtk_container_add (GTK_CONTAINER (frame), label);
8069         gtk_widget_show (label);
8070         
8071         label = gtk_label_new (bufferl);
8072         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
8073     }
8074       
8075     /* Now let's add a page to a specific spot */
8076     checkbutton = gtk_check_button_new_with_label ("Check me please!");
8077     gtk_widget_set_size_request (checkbutton, 100, 75);
8078     gtk_widget_show (checkbutton);
8079    
8080     label = gtk_label_new ("Add page");
8081     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
8082     
8083     /* Now finally let's prepend pages to the notebook */
8084     for (i = 0; i &lt; 5; i++) {
8085         sprintf (bufferf, "Prepend Frame %d", i + 1);
8086         sprintf (bufferl, "PPage %d", i + 1);
8087         
8088         frame = gtk_frame_new (bufferf);
8089         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
8090         gtk_widget_set_size_request (frame, 100, 75);
8091         gtk_widget_show (frame);
8092         
8093         label = gtk_label_new (bufferf);
8094         gtk_container_add (GTK_CONTAINER (frame), label);
8095         gtk_widget_show (label);
8096         
8097         label = gtk_label_new (bufferl);
8098         gtk_notebook_prepend_page (GTK_NOTEBOOK (notebook), frame, label);
8099     }
8100     
8101     /* Set what page to start at (page 4) */
8102     gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 3);
8103
8104     /* Create a bunch of buttons */
8105     button = gtk_button_new_with_label ("close");
8106     g_signal_connect_swapped (button, "clicked",
8107                               G_CALLBACK (delete), NULL);
8108     gtk_table_attach_defaults (GTK_TABLE (table), button, 0, 1, 1, 2);
8109     gtk_widget_show (button);
8110     
8111     button = gtk_button_new_with_label ("next page");
8112     g_signal_connect_swapped (button, "clicked",
8113                               G_CALLBACK (gtk_notebook_next_page),
8114                               notebook);
8115     gtk_table_attach_defaults (GTK_TABLE (table), button, 1, 2, 1, 2);
8116     gtk_widget_show (button);
8117     
8118     button = gtk_button_new_with_label ("prev page");
8119     g_signal_connect_swapped (button, "clicked",
8120                               G_CALLBACK (gtk_notebook_prev_page),
8121                               notebook);
8122     gtk_table_attach_defaults (GTK_TABLE (table), button, 2, 3, 1, 2);
8123     gtk_widget_show (button);
8124     
8125     button = gtk_button_new_with_label ("tab position");
8126     g_signal_connect (button, "clicked",
8127                       G_CALLBACK (rotate_book),
8128                       notebook);
8129     gtk_table_attach_defaults (GTK_TABLE (table), button, 3, 4, 1, 2);
8130     gtk_widget_show (button);
8131     
8132     button = gtk_button_new_with_label ("tabs/border on/off");
8133     g_signal_connect (button, "clicked",
8134                       G_CALLBACK (tabsborder_book),
8135                       notebook);
8136     gtk_table_attach_defaults (GTK_TABLE (table), button, 4, 5, 1, 2);
8137     gtk_widget_show (button);
8138     
8139     button = gtk_button_new_with_label ("remove page");
8140     g_signal_connect (button, "clicked",
8141                       G_CALLBACK (remove_book),
8142                       notebook);
8143     gtk_table_attach_defaults (GTK_TABLE (table), button, 5, 6, 1, 2);
8144     gtk_widget_show (button);
8145     
8146     gtk_widget_show (table);
8147     gtk_widget_show (window);
8148     
8149     gtk_main ();
8150     
8151     return 0;
8152 }
8153 <!-- example-end -->
8154 </programlisting>
8155
8156 <para>I hope this helps you on your way with creating notebooks for your
8157 GTK applications.</para>
8158
8159 </sect1>
8160 </chapter>
8161
8162 <!-- ***************************************************************** -->
8163 <chapter id="ch-MenuWidget">
8164 <title>Menu Widget</title>
8165
8166 <para>There are two ways to create menus: there's the easy way, and there's
8167 the hard way. Both have their uses, but you can usually use the
8168 Itemfactory (the easy way). The "hard" way is to create all the menus
8169 using the calls directly. The easy way is to use the gtk_item_factory
8170 calls. This is much simpler, but there are advantages and
8171 disadvantages to each approach.</para>
8172
8173 <para>The Itemfactory is much easier to use, and to add new menus to,
8174 although writing a few wrapper functions to create menus using the
8175 manual method could go a long way towards usability. With the
8176 Itemfactory, it is not possible to add images or the character '/' to
8177 the menus.</para>
8178
8179 <!-- ----------------------------------------------------------------- -->
8180 <sect1 id="sec-ManualMenuCreation">
8181 <title>Manual Menu Creation</title>
8182
8183 <para>In the true tradition of teaching, we'll show you the hard way
8184 first. <literal>:)</literal></para>
8185
8186 <para>There are three widgets that go into making a menubar and submenus:</para>
8187
8188 <itemizedlist>
8189 <listitem><simpara>a menu item, which is what the user wants to select, e.g.,
8190 "Save"</simpara>
8191 </listitem>
8192 <listitem><simpara>a menu, which acts as a container for the menu items, and</simpara>
8193 </listitem>
8194 <listitem><simpara>a menubar, which is a container for each of the individual
8195 menus.</simpara>
8196 </listitem>
8197 </itemizedlist>
8198
8199 <para>This is slightly complicated by the fact that menu item widgets are
8200 used for two different things. They are both the widgets that are
8201 packed into the menu, and the widget that is packed into the menubar,
8202 which, when selected, activates the menu.</para>
8203
8204 <para>Let's look at the functions that are used to create menus and
8205 menubars.  This first function is used to create a new menubar.</para>
8206
8207 <programlisting role="C">
8208 GtkWidget *gtk_menu_bar_new( void );
8209 </programlisting>
8210
8211 <para>This rather self explanatory function creates a new menubar. You use
8212 gtk_container_add() to pack this into a window, or the box_pack
8213 functions to pack it into a box - the same as buttons.</para>
8214
8215 <programlisting role="C">
8216 GtkWidget *gtk_menu_new( void );
8217 </programlisting>
8218
8219 <para>This function returns a pointer to a new menu; it is never actually
8220 shown (with gtk_widget_show()), it is just a container for the menu
8221 items. I hope this will become more clear when you look at the
8222 example below.</para>
8223
8224 <para>The next three calls are used to create menu items that are packed into
8225 the menu (and menubar).</para>
8226
8227 <programlisting role="C">
8228 GtkWidget *gtk_menu_item_new( void );
8229
8230 GtkWidget *gtk_menu_item_new_with_label( const char *label );
8231
8232 GtkWidget *gtk_menu_item_new_with_mnemonic( const char *label );
8233 </programlisting>
8234
8235 <para>These calls are used to create the menu items that are to be
8236 displayed.  Remember to differentiate between a "menu" as created with
8237 gtk_menu_new() and a "menu item" as created by the gtk_menu_item_new()
8238 functions. The menu item will be an actual button with an associated
8239 action, whereas a menu will be a container holding menu items.</para>
8240
8241 <para>The gtk_menu_item_new_with_label() and gtk_menu_item_new() functions are just as
8242 you'd expect after reading about the buttons. One creates a new menu
8243 item with a label already packed into it, and the other just creates a
8244 blank menu item.</para>
8245
8246 <para>Once you've created a menu item you have to put it into a menu. This
8247 is done using the function gtk_menu_shelll_append. In order to capture when
8248 the item is selected by the user, we need to connect to the
8249 <literal>activate</literal> signal in the usual way. So, if we wanted to create a
8250 standard <literal>File</literal> menu, with the options <literal>Open</literal>, <literal>Save</literal>, and
8251 <literal>Quit</literal>, the code would look something like:</para>
8252
8253 <programlisting role="C">
8254     file_menu = gtk_menu_new ();    /* Don't need to show menus */
8255
8256     /* Create the menu items */
8257     open_item = gtk_menu_item_new_with_label ("Open");
8258     save_item = gtk_menu_item_new_with_label ("Save");
8259     quit_item = gtk_menu_item_new_with_label ("Quit");
8260
8261     /* Add them to the menu */
8262     gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), open_item);
8263     gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), save_item);
8264     gtk_menu_shell_append (GTK_MENU_SHELL (file_menu), quit_item);
8265
8266     /* Attach the callback functions to the activate signal */
8267     g_signal_connect_swapped (open_item, "activate",
8268                               G_CALLBACK (menuitem_response),
8269                               (gpointer) "file.open");
8270     g_signal_connect_swapped (save_item, "activate",
8271                               G_CALLBACK (menuitem_response),
8272                               (gpointer) "file.save");
8273
8274     /* We can attach the Quit menu item to our exit function */
8275     g_signal_connect_swapped (quit_item, "activate",
8276                               G_CALLBACK (destroy),
8277                               (gpointer) "file.quit");
8278
8279     /* We do need to show menu items */
8280     gtk_widget_show (open_item);
8281     gtk_widget_show (save_item);
8282     gtk_widget_show (quit_item);
8283 </programlisting>
8284
8285 <para>At this point we have our menu. Now we need to create a menubar and a
8286 menu item for the <literal>File</literal> entry, to which we add our menu. The code
8287 looks like this:</para>
8288
8289 <programlisting role="C">
8290     menu_bar = gtk_menu_bar_new ();
8291     gtk_container_add (GTK_CONTAINER (window), menu_bar);
8292     gtk_widget_show (menu_bar);
8293
8294     file_item = gtk_menu_item_new_with_label ("File");
8295     gtk_widget_show (file_item);
8296 </programlisting>
8297
8298 <para>Now we need to associate the menu with <literal>file_item</literal>. This is done
8299 with the function</para>
8300
8301 <programlisting role="C">
8302 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
8303                                 GtkWidget   *submenu );
8304 </programlisting>
8305
8306 <para>So, our example would continue with</para>
8307
8308 <programlisting role="C">
8309     gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_item), file_menu);
8310 </programlisting>
8311
8312 <para>All that is left to do is to add the menu to the menubar, which is
8313 accomplished using the function</para>
8314
8315 <programlisting role="C">
8316 void gtk_menu_bar_append( GtkMenuBar *menu_bar,
8317                           GtkWidget  *menu_item );
8318 </programlisting>
8319
8320 <para>which in our case looks like this:</para>
8321
8322 <programlisting role="C">
8323     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), file_item);
8324 </programlisting>
8325
8326 <para>If we wanted the menu right justified on the menubar, such as help
8327 menus often are, we can use the following function (again on
8328 <literal>file_item</literal> in the current example) before attaching it to the
8329 menubar.</para>
8330
8331 <programlisting role="C">
8332 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
8333 </programlisting>
8334
8335 <para>Here is a summary of the steps needed to create a menu bar with menus
8336 attached:</para>
8337
8338 <itemizedlist>
8339 <listitem><simpara> Create a new menu using gtk_menu_new()</simpara>
8340 </listitem>
8341
8342 <listitem><simpara> Use multiple calls to gtk_menu_item_new() for each item you
8343 wish to have on your menu. And use gtk_menu_shell_append() to put each of
8344 these new items on to the menu.</simpara>
8345 </listitem>
8346
8347 <listitem><simpara> Create a menu item using gtk_menu_item_new(). This will be the
8348 root of the menu, the text appearing here will be on the menubar
8349 itself.</simpara>
8350 </listitem>
8351
8352 <listitem><simpara>Use gtk_menu_item_set_submenu() to attach the menu to the root
8353 menu item (the one created in the above step).</simpara>
8354 </listitem>
8355
8356 <listitem><simpara> Create a new menubar using gtk_menu_bar_new. This step only
8357 needs to be done once when creating a series of menus on one menu bar.</simpara>
8358 </listitem>
8359
8360 <listitem><simpara> Use gtk_menu_bar_append() to put the root menu onto the menubar.</simpara>
8361 </listitem>
8362 </itemizedlist>
8363
8364 <para>Creating a popup menu is nearly the same. The difference is that the
8365 menu is not posted "automatically" by a menubar, but explicitly by
8366 calling the function gtk_menu_popup() from a button-press event, for
8367 example.  Take these steps:</para>
8368
8369 <itemizedlist>
8370 <listitem><simpara>Create an event handling function. It needs to have the
8371 prototype</simpara>
8372 <programlisting role="C">
8373 static gboolean handler( GtkWidget *widget,
8374                          GdkEvent  *event );
8375 </programlisting>
8376 <simpara>and it will use the event to find out where to pop up the menu.</simpara>
8377 </listitem>
8378
8379 <listitem><simpara>In the event handler, if the event is a mouse button press,
8380 treat <literal>event</literal> as a button event (which it is) and use it as
8381 shown in the sample code to pass information to gtk_menu_popup().</simpara>
8382 </listitem>
8383
8384 <listitem><simpara>Bind that event handler to a widget with</simpara>
8385 <programlisting role="C">
8386     g_signal_connect_swapped (widget, "event",
8387                               G_CALLBACK (handler),
8388                               menu);
8389 </programlisting>
8390 <simpara>where <literal>widget</literal> is the widget you are binding to,
8391 <literal>handler</literal> is the handling function, and <literal>menu</literal> is a menu
8392 created with gtk_menu_new(). This can be a menu which is also posted
8393 by a menu bar, as shown in the sample code.</simpara>
8394 </listitem>
8395 </itemizedlist>
8396
8397 </sect1>
8398
8399 <!-- ----------------------------------------------------------------- -->
8400 <sect1 id="sec-ManualMenuExample">
8401 <title>Manual Menu Example</title>
8402
8403 <para>That should about do it. Let's take a look at an example to help clarify.</para>
8404
8405 <para>
8406 <inlinemediaobject>
8407 <imageobject>
8408 <imagedata fileref="images/menu.png" format="png">
8409 </imageobject>
8410 </inlinemediaobject>
8411 </para>
8412
8413 <programlisting role="C">
8414 <!-- example-start menu menu.c -->
8415
8416 #include &lt;stdio.h&gt;
8417 #include &lt;gtk/gtk.h&gt;
8418
8419 static gboolean button_press (GtkWidget *, GdkEvent *);
8420 static void menuitem_response (gchar *);
8421
8422 int main( int   argc,
8423           char *argv[] )
8424 {
8425
8426     GtkWidget *window;
8427     GtkWidget *menu;
8428     GtkWidget *menu_bar;
8429     GtkWidget *root_menu;
8430     GtkWidget *menu_items;
8431     GtkWidget *vbox;
8432     GtkWidget *button;
8433     char buf[128];
8434     int i;
8435
8436     gtk_init (&amp;argc, &amp;argv);
8437
8438     /* create a new window */
8439     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8440     gtk_widget_set_size_request (GTK_WIDGET (window), 200, 100);
8441     gtk_window_set_title (GTK_WINDOW (window), "GTK Menu Test");
8442     g_signal_connect (window, "delete-event",
8443                       G_CALLBACK (gtk_main_quit), NULL);
8444
8445     /* Init the menu-widget, and remember -- never
8446      * gtk_show_widget() the menu widget!! 
8447      * This is the menu that holds the menu items, the one that
8448      * will pop up when you click on the "Root Menu" in the app */
8449     menu = gtk_menu_new ();
8450
8451     /* Next we make a little loop that makes three menu-entries for "test-menu".
8452      * Notice the call to gtk_menu_shell_append.  Here we are adding a list of
8453      * menu items to our menu.  Normally, we'd also catch the "clicked"
8454      * signal on each of the menu items and setup a callback for it,
8455      * but it's omitted here to save space. */
8456
8457     for (i = 0; i &lt; 3; i++)
8458         {
8459             /* Copy the names to the buf. */
8460             sprintf (buf, "Test-undermenu - %d", i);
8461
8462             /* Create a new menu-item with a name... */
8463             menu_items = gtk_menu_item_new_with_label (buf);
8464
8465             /* ...and add it to the menu. */
8466             gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_items);
8467
8468             /* Do something interesting when the menuitem is selected */
8469             g_signal_connect_swapped (menu_items, "activate",
8470                                       G_CALLBACK (menuitem_response), 
8471                                       (gpointer) g_strdup (buf));
8472
8473             /* Show the widget */
8474             gtk_widget_show (menu_items);
8475         }
8476
8477     /* This is the root menu, and will be the label
8478      * displayed on the menu bar.  There won't be a signal handler attached,
8479      * as it only pops up the rest of the menu when pressed. */
8480     root_menu = gtk_menu_item_new_with_label ("Root Menu");
8481
8482     gtk_widget_show (root_menu);
8483
8484     /* Now we specify that we want our newly created "menu" to be the menu
8485      * for the "root menu" */
8486     gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu);
8487
8488     /* A vbox to put a menu and a button in: */
8489     vbox = gtk_vbox_new (FALSE, 0);
8490     gtk_container_add (GTK_CONTAINER (window), vbox);
8491     gtk_widget_show (vbox);
8492
8493     /* Create a menu-bar to hold the menus and add it to our main window */
8494     menu_bar = gtk_menu_bar_new ();
8495     gtk_box_pack_start (GTK_BOX (vbox), menu_bar, FALSE, FALSE, 2);
8496     gtk_widget_show (menu_bar);
8497
8498     /* Create a button to which to attach menu as a popup */
8499     button = gtk_button_new_with_label ("press me");
8500     g_signal_connect_swapped (button, "event",
8501                               G_CALLBACK (button_press), 
8502                               menu);
8503     gtk_box_pack_end (GTK_BOX (vbox), button, TRUE, TRUE, 2);
8504     gtk_widget_show (button);
8505
8506     /* And finally we append the menu-item to the menu-bar -- this is the
8507      * "root" menu-item I have been raving about =) */
8508     gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), root_menu);
8509
8510     /* always display the window as the last step so it all splashes on
8511      * the screen at once. */
8512     gtk_widget_show (window);
8513
8514     gtk_main ();
8515
8516     return 0;
8517 }
8518
8519 /* Respond to a button-press by posting a menu passed in as widget.
8520  *
8521  * Note that the "widget" argument is the menu being posted, NOT
8522  * the button that was pressed.
8523  */
8524
8525 static gboolean button_press( GtkWidget *widget,
8526                               GdkEvent *event )
8527 {
8528
8529     if (event-&gt;type == GDK_BUTTON_PRESS) {
8530         GdkEventButton *bevent = (GdkEventButton *) event; 
8531         gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
8532                         bevent-&gt;button, bevent-&gt;time);
8533         /* Tell calling code that we have handled this event; the buck
8534          * stops here. */
8535         return TRUE;
8536     }
8537
8538     /* Tell calling code that we have not handled this event; pass it on. */
8539     return FALSE;
8540 }
8541
8542
8543 /* Print a string when a menu item is selected */
8544
8545 static void menuitem_response( gchar *string )
8546 {
8547     printf ("%s\n", string);
8548 }
8549 <!-- example-end -->
8550 </programlisting>
8551
8552 <para>You may also set a menu item to be insensitive and, using an accelerator
8553 table, bind keys to menu functions.</para>
8554
8555 </sect1>
8556
8557 <!-- ----------------------------------------------------------------- -->
8558 <sect1 id="sec-UsingItemFactory">
8559 <title>Using ItemFactory</title>
8560
8561 <para>Now that we've shown you the hard way, here's how you do it using the
8562 gtk_item_factory calls.</para>
8563
8564 <para>ItemFactory creates a menu out of an array of ItemFactory entries. This 
8565 means you can define your menu in its simplest form and then create the
8566 menu/menubar widgets with a minimum of function calls.</para>
8567
8568 <!-- ----------------------------------------------------------------- -->
8569 <sect2 id="sec-ItemFactoryEntries">
8570 <title>ItemFactory entries</title>
8571
8572 <para>At the core of ItemFactory is the ItemFactoryEntry. This structure defines
8573 one menu item, and when an array of these entries is defined a whole
8574 menu is formed. The ItemFactory entry struct definition looks like this:</para>
8575
8576 <programlisting role="C">
8577 struct _GtkItemFactoryEntry
8578 {
8579   gchar *path;
8580   gchar *accelerator;
8581
8582   GtkItemFactoryCallback callback;
8583   guint                  callback_action;
8584
8585   gchar          *item_type;
8586 };
8587 </programlisting>
8588
8589 <para>Each field defines part of the menu item.</para>
8590
8591 <para><literal>*path</literal> is a string which defines both the name and the
8592 path of a menu item, for example, "/File/Open" would be the name of a menu
8593 item which would come under the ItemFactory entry with path "/File". Note however
8594 that "/File/Open" would be displayed in the File menu as "Open". Also note
8595 since the forward slashes are used to define the path of the menu,
8596 they cannot be used as part of the name. A letter preceded by an underscore
8597 indicates an accelerator (shortcut) key once the menu is open.</para>
8598
8599 <para>
8600 <literal>*accelerator</literal> is a string that indicates a key combination
8601 that can be used as a shortcut to that menu item. The string can be made up
8602 of either a single character, or a combination of modifier keys with a single
8603 character. It is case insensitive.</para>
8604
8605
8606 <para>The available modifier keys are:</para>
8607
8608 <programlisting role="C">
8609 "&lt;ALT&gt;                             - alt
8610 "&lt;CTL&gt;" or "&lt;CTRL&gt;" or "&lt;CONTROL&gt;" - control
8611 "&lt;MOD1&gt;" to "&lt;MOD5&gt;"               - modn
8612 "&lt;SHFT&gt;" or "&lt;SHIFT&gt;"              - shift
8613 </programlisting>
8614
8615 <para>Examples:</para>
8616 <programlisting role="C">
8617 "&lt;ConTroL&gt;a"
8618 "&lt;SHFT&gt;&lt;ALT&gt;&lt;CONTROL&gt;X"
8619 </programlisting>
8620
8621 <para>
8622 <literal>callback</literal> is the function that is called when the menu item
8623 emits the "activate" signal. The form of the callback is described
8624 in the <link linkend="sec-ItemFactoryCallback">Callback Description</link>
8625 section.</para>
8626
8627 <para>
8628 The value of <literal>callback_action</literal> is passed to the callback
8629 function. It also affects the function prototype, as shown
8630 in the <link linkend="sec-ItemFactoryCallback">Callback Description</link>
8631 section.</para>
8632
8633 <para>
8634 <literal>item_type</literal> is a string that defines what type of widget is
8635 packed into the menu items container. It can be:</para>
8636
8637 <programlisting role="C">
8638 NULL or "" or "&lt;Item&gt;" - create a simple item
8639 "&lt;Title&gt;"              - create a title item
8640 "&lt;CheckItem&gt;"          - create a check item
8641 "&lt;ToggleItem&gt;"         - create a toggle item
8642 "&lt;RadioItem&gt;"          - create a (root) radio item
8643 "Path"                 - create a sister radio item
8644 "&lt;Tearoff&gt;"            - create a tearoff
8645 "&lt;Separator&gt;"          - create a separator
8646 "&lt;Branch&gt;"             - create an item to hold submenus (optional)
8647 "&lt;LastBranch&gt;"         - create a right justified branch
8648 "&lt;StockItem&gt;"          - create a simple item with a stock image. 
8649                                see <filename>gtkstock.h</filename> for builtin stock items
8650  
8651 </programlisting>
8652
8653 <para>Note that &lt;LastBranch&gt; is only useful for one submenu of
8654 a menubar.</para>
8655
8656 <!-- ----------------------------------------------------------------- -->
8657 <sect3 id="sec-ItemFactoryCallback">
8658 <title>Callback Description</title>
8659
8660 <para>
8661 The callback for an ItemFactory entry can take two forms. If
8662 <literal>callback_action</literal> is zero, it is of the following
8663 form:</para>
8664
8665 <programlisting role="C">
8666 void callback( void )
8667 </programlisting>
8668
8669 <para>otherwise it is of the form:</para>
8670
8671 <programlisting role="C">
8672 void callback( gpointer    callback_data,
8673                guint       callback_action,
8674                GtkWidget  *widget )
8675 </programlisting>
8676
8677 <para>
8678 <literal>callback_data</literal> is a pointer to an arbitrary piece of data and
8679 is set during the call to gtk_item_factory_create_items().</para>
8680
8681 <para>
8682 <literal>callback_action</literal> is the same value as
8683 <literal>callback_action</literal> in the ItemFactory entry.</para>
8684
8685 <para>
8686 <literal>*widget</literal> is a pointer to a menu item widget
8687 (described in <link linkend="sec-ManualMenuCreation">Manual Menu Creation</link>).
8688 </para>
8689 </sect3>
8690
8691 <!-- ----------------------------------------------------------------- -->
8692 <sect3 id="sec-ItemFactoryEntryExamples">
8693 <title>ItemFactory entry examples</title>
8694
8695 <para>Creating a simple menu item:</para>
8696
8697 <programlisting role="C">
8698 GtkItemFactoryEntry entry = {"/_File/_Open...", "&lt;CTRL&gt;O", print_hello,
8699                                 0, "&lt;Item&gt;"};
8700 </programlisting>
8701
8702 <para>This will define a new simple menu entry "/File/Open" (displayed as "Open"),
8703 under the menu entry "/File". It has the accelerator (shortcut) control+'O'
8704 that when clicked calls the function print_hello(). print_hello() is of
8705 the form <literal>void print_hello(void)</literal> since the callback_action
8706 field is zero. When displayed the 'O' in "Open" will be underlined and if the
8707 menu item is visible on the screen pressing 'O' will activate the item. Note
8708 that "File/_Open" could also have been used as the path instead of
8709 "/_File/_Open".</para>
8710
8711 <para>Creating an entry with a more complex callback:</para>
8712
8713 <programlisting role="C">
8714 GtkItemFactoryEntry entry = {"/_View/Display _FPS", NULL, print_state,
8715                                 7,"&lt;CheckItem&gt;"};
8716 </programlisting>
8717
8718 <para>This defines a new menu item displayed as "Display FPS" which is under
8719 the menu item "View". When clicked the function print_state() will be called.
8720 Since <literal>callback_action</literal> is not zero print_state() is of the
8721 form:</para>
8722
8723 <programlisting role="C">
8724 void print_state( gpointer    callback_data,
8725                   guint       callback_action,
8726                   GtkWidget  *widget )
8727 </programlisting>
8728
8729 <para>with <literal>callback_action</literal> equal to 7.</para>
8730
8731 <para>Creating a radio button set:</para>
8732
8733 <programlisting role="C">
8734 GtkItemFactoryEntry entry1 = {"/_View/_Low Resolution", NULL, change_resolution,
8735                                 1, "&lt;RadioButton&gt;"};
8736 GtkItemFactoryEntry entry2 = {"/_View/_High Resolution", NULL, change_resolution,
8737                                 2, "/View/Low Resolution"};
8738 </programlisting>
8739
8740 <para><literal>entry1</literal> defines a lone radio button that when toggled
8741 calls the function change_resolution() with the parameter
8742 <literal>callback_action</literal> equal to 1. change_resolution() is of
8743 the form:</para>
8744
8745 <programlisting role="C">
8746 void change_resolution(gpointer    callback_data,
8747                        guint       callback_action,
8748                        GtkWidget  *widget)
8749 </programlisting>
8750
8751 <para><literal>entry2</literal> defines a radio button that belongs to the
8752 radio group that entry1 belongs to. It calls the same function when toggled
8753 but with the parameter <literal>callback_action</literal> equal to 2. Note that
8754 the item_type of <literal>entry2</literal> is the path of entry1
8755 <emphasis>without</emphasis> the accelerators ('_'). If another radio button was
8756 required in the same group then it would be defined in the same way as
8757 <literal>entry2</literal> was with its <literal>item_type</literal> again
8758 equal to "/View/Low Resolution".</para>
8759 </sect3>
8760
8761 <!-- ----------------------------------------------------------------- -->
8762 <sect3 id="sec-ItemFactoryEntryArrays">
8763 <title>ItemFactoryEntry Arrays</title>
8764
8765 <para>An ItemFactoryEntry on it's own however isn't useful. An array of
8766 entries is what's required to define a menu. Below is an example of how
8767 you'd declare this array.</para>
8768
8769 <programlisting role="C">
8770 static GtkItemFactoryEntry entries[] = {
8771   { "/_File",         NULL,      NULL,         0, "&lt;Branch&gt;" },
8772   { "/File/tear1",    NULL,      NULL,         0, "&lt;Tearoff&gt;" },
8773   { "/File/_New",     "&lt;CTRL&gt;N", new_file,     1, "&lt;Item&gt;" },
8774   { "/File/_Open...", "&lt;CTRL&gt;O", open_file,    1, "&lt;Item&gt;" },
8775   { "/File/sep1",     NULL,      NULL,         0, "&lt;Separator&gt;" },
8776   { "/File/_Quit",    "&lt;CTRL&gt;Q", quit_program, 0, "&lt;StockItem&gt;", GTK_STOCK_QUIT } };
8777 </programlisting>
8778 </sect3>
8779 </sect2>
8780
8781 <!-- ----------------------------------------------------------------- -->
8782 <sect2 id="sec-ItemFactoryCreation">
8783 <title>Creating an ItemFactory</title>
8784
8785 <para>An array of GtkItemFactoryEntry items defines a menu. Once this
8786 array is defined then the item factory can be created. The function that
8787 does this is:</para>
8788
8789 <programlisting role="C">
8790 GtkItemFactory* gtk_item_factory_new( GtkType        container_type,
8791                                       const gchar   *path,
8792                                       GtkAccelGroup *accel_group );
8793 </programlisting>
8794
8795 <para><literal>container_type</literal> can be one of:</para>
8796
8797 <programlisting role="C">
8798 GTK_TYPE_MENU
8799 GTK_TYPE_MENU_BAR
8800 GTK_TYPE_OPTION_MENU
8801 </programlisting>
8802
8803 <para><literal>container_type</literal> defines what type of menu
8804 you want, so when you extract it later it is either a menu (for pop-ups
8805 for instance), a menu bar, or an option menu (like a combo box but with
8806 a menu of pull downs).</para>
8807
8808 <para><literal>path</literal> defines the path of the root of the menu.
8809 Basically it is a unique name for the root of the menu, it must be
8810 surrounded by "&lt;&gt;". This is important for the naming of the
8811 accelerators and should be unique. It should be unique both for each
8812 menu and between each program. For example in a program named 'foo', the
8813 main menu should be called "&lt;FooMain&gt;", and a pop-up menu
8814 "&lt;FooImagePopUp&gt;", or similar. What's important is that they're unique.</para>
8815
8816 <para><literal>accel_group</literal> is a pointer to a gtk_accel_group. The
8817 item factory sets up the accelerator table while generating menus. New
8818 accelerator groups are generated by gtk_accel_group_new().</para>
8819
8820 <para>But this is just the first step. To convert the array of GtkItemFactoryEntry
8821 information into widgets the following function is used:</para>
8822
8823 <programlisting role="C">
8824 void gtk_item_factory_create_items( GtkItemFactory      *ifactory,
8825                                     guint                n_entries,
8826                                     GtkItemFactoryEntry *entries,
8827                                     gpointer             callback_data );
8828 </programlisting>
8829
8830 <para><literal>*ifactory</literal> a pointer to the above created item factory.</para>
8831 <para><literal>n_entries</literal> is the number of entries in the
8832 GtkItemFactoryEntry array.</para>
8833 <para><literal>*entries</literal> is a pointer to the GtkItemFactoryEntry array.</para>
8834 <para><literal>callback_data</literal> is what gets passed to all the callback functions
8835 for all the entries with callback_action != 0.</para>
8836
8837 <para>The accelerator group has now been formed, so you'll probably want
8838 to attach it to the window the menu is in:</para>
8839
8840 <programlisting role="C">
8841 void gtk_window_add_accel_group( GtkWindow     *window,
8842                                  GtkAccelGroup *accel_group);
8843 </programlisting>
8844 </sect2>
8845
8846 <!-- ----------------------------------------------------------------- -->
8847 <sect2 id="sec-UsingMenuandItems">
8848 <title>Making use of the menu and its menu items</title>
8849
8850 <para>The last thing to do is make use of the menu. The following function
8851 extracts the relevant widgets from the ItemFactory:</para>
8852
8853 <programlisting role="C">
8854 GtkWidget* gtk_item_factory_get_widget( GtkItemFactory *ifactory,
8855                                         const gchar    *path );
8856 </programlisting>
8857
8858 <para>For instance if an ItemFactory has two entries "/File" and "/File/New",
8859 using a path of "/File" would retrieve a <emphasis>menu</emphasis> widget from the
8860 ItemFactory. Using a path of "/File/New" would retrieve a
8861 <emphasis>menu item</emphasis> widget. This makes it possible to set the initial state
8862 of menu items. For example to set the default radio
8863 item to the one with the path "/Shape/Oval" then the following code would
8864 be used:</para>
8865
8866 <programlisting role="C">
8867 gtk_check_menu_item_set_active(
8868         GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory, "/Shape/Oval")),
8869         TRUE);
8870 </programlisting>
8871
8872 <para>Finally to retrieve the root of the menu use gtk_item_factory_get_item()
8873 with a path of "&lt;main&gt;" (or whatever path was used in
8874 gtk_item_factory_new()). In the case of the ItemFactory being created with
8875 type GTK_TYPE_MENU_BAR this returns a menu bar widget. With type GTK_TYPE_MENU
8876 a menu widget is returned. With type GTK_TYPE_OPTION_MENU an option menu
8877 widget is returned.</para>
8878
8879 <para><emphasis>Remember</emphasis> for an entry defined with path "/_File"
8880 the path here is actually "/File".</para>
8881
8882 <para>Now you have a menubar or menu which can be manipulated in the same
8883 way as shown in the
8884 <link linkend="sec-ManualMenuCreation">Manual Menu Creation</link>
8885 section.</para>
8886 </sect2>
8887 </sect1>
8888
8889 <!-- ----------------------------------------------------------------- -->
8890 <sect1 id="sec-ItemFactoryExample">
8891 <title>Item Factory Example</title>
8892
8893 <para>Here is an example using the GTK item factory.</para>
8894
8895 <programlisting role="C">
8896 <!-- example-start menu itemfactory.c -->
8897
8898 #include &lt;gtk/gtk.h&gt;
8899
8900 /* Obligatory basic callback */
8901 static void print_hello( GtkWidget *w,
8902                          gpointer   data )
8903 {
8904   g_message ("Hello, World!\n");
8905 }
8906
8907 /* For the check button */
8908 static void print_toggle( gpointer   callback_data,
8909                           guint      callback_action,
8910                           GtkWidget *menu_item )
8911 {
8912    g_message ("Check button state - %d\n",
8913               GTK_CHECK_MENU_ITEM (menu_item)-&gt;active);
8914 }
8915
8916 /* For the radio buttons */
8917 static void print_selected( gpointer   callback_data,
8918                             guint      callback_action,
8919                             GtkWidget *menu_item )
8920 {
8921    if(GTK_CHECK_MENU_ITEM(menu_item)-&gt;active)
8922      g_message ("Radio button %d selected\n", callback_action);
8923 }
8924
8925 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
8926 static GtkItemFactoryEntry menu_items[] = {
8927   { "/_File",         NULL,         NULL,           0, "&lt;Branch&gt;" },
8928   { "/File/_New",     "&lt;control&gt;N", print_hello,    0, "&lt;StockItem&gt;", GTK_STOCK_NEW },
8929   { "/File/_Open",    "&lt;control&gt;O", print_hello,    0, "&lt;StockItem&gt;", GTK_STOCK_OPEN },
8930   { "/File/_Save",    "&lt;control&gt;S", print_hello,    0, "&lt;StockItem&gt;", GTK_STOCK_SAVE },
8931   { "/File/Save _As", NULL,         NULL,           0, "&lt;Item&gt;" },
8932   { "/File/sep1",     NULL,         NULL,           0, "&lt;Separator&gt;" },
8933   { "/File/_Quit",    "&lt;CTRL&gt;Q", gtk_main_quit, 0, "&lt;StockItem&gt;", GTK_STOCK_QUIT },
8934   { "/_Options",      NULL,         NULL,           0, "&lt;Branch&gt;" },
8935   { "/Options/tear",  NULL,         NULL,           0, "&lt;Tearoff&gt;" },
8936   { "/Options/Check", NULL,         print_toggle,   1, "&lt;CheckItem&gt;" },
8937   { "/Options/sep",   NULL,         NULL,           0, "&lt;Separator&gt;" },
8938   { "/Options/Rad1",  NULL,         print_selected, 1, "&lt;RadioItem&gt;" },
8939   { "/Options/Rad2",  NULL,         print_selected, 2, "/Options/Rad1" },
8940   { "/Options/Rad3",  NULL,         print_selected, 3, "/Options/Rad1" },
8941   { "/_Help",         NULL,         NULL,           0, "&lt;LastBranch&gt;" },
8942   { "/_Help/About",   NULL,         NULL,           0, "&lt;Item&gt;" },
8943 };
8944
8945 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
8946
8947 /* Returns a menubar widget made from the above menu */
8948 static GtkWidget *get_menubar_menu( GtkWidget  *window )
8949 {
8950   GtkItemFactory *item_factory;
8951   GtkAccelGroup *accel_group;
8952
8953   /* Make an accelerator group (shortcut keys) */
8954   accel_group = gtk_accel_group_new ();
8955
8956   /* Make an ItemFactory (that makes a menubar) */
8957   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "&lt;main&gt;",
8958                                        accel_group);
8959
8960   /* This function generates the menu items. Pass the item factory,
8961      the number of items in the array, the array itself, and any
8962      callback data for the the menu items. */
8963   gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
8964
8965   /* Attach the new accelerator group to the window. */
8966   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
8967
8968   /* Finally, return the actual menu bar created by the item factory. */
8969   return gtk_item_factory_get_widget (item_factory, "&lt;main&gt;");
8970 }
8971
8972 /* Popup the menu when the popup button is pressed */
8973 static gboolean popup_cb( GtkWidget *widget,
8974                           GdkEvent *event,
8975                           GtkWidget *menu )
8976 {
8977    GdkEventButton *bevent = (GdkEventButton *)event;
8978   
8979    /* Only take button presses */
8980    if (event-&gt;type != GDK_BUTTON_PRESS)
8981      return FALSE;
8982   
8983    /* Show the menu */
8984    gtk_menu_popup (GTK_MENU(menu), NULL, NULL,
8985                    NULL, NULL, bevent-&gt;button, bevent-&gt;time);
8986   
8987    return TRUE;
8988 }
8989
8990 /* Same as with get_menubar_menu() but just return a button with a signal to
8991    call a popup menu */
8992 GtkWidget *get_popup_menu( void )
8993 {
8994    GtkItemFactory *item_factory;
8995    GtkWidget *button, *menu;
8996   
8997    /* Same as before but don't bother with the accelerators */
8998    item_factory = gtk_item_factory_new (GTK_TYPE_MENU, "&lt;main&gt;",
8999                                         NULL);
9000    gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
9001    menu = gtk_item_factory_get_widget (item_factory, "&lt;main&gt;");
9002   
9003    /* Make a button to activate the popup menu */
9004    button = gtk_button_new_with_label ("Popup");
9005    /* Make the menu popup when clicked */
9006    g_signal_connect (button,
9007                      "event",
9008                      G_CALLBACK(popup_cb),
9009                      (gpointer) menu);
9010
9011    return button;
9012 }
9013
9014 /* Same again but return an option menu */
9015 GtkWidget *get_option_menu( void )
9016 {
9017    GtkItemFactory *item_factory;
9018    GtkWidget *option_menu;
9019   
9020    /* Same again, not bothering with the accelerators */
9021    item_factory = gtk_item_factory_new (GTK_TYPE_OPTION_MENU, "&lt;main&gt;",
9022                                         NULL);
9023    gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
9024    option_menu = gtk_item_factory_get_widget (item_factory, "&lt;main&gt;");
9025
9026    return option_menu;
9027 }
9028
9029 /* You have to start somewhere */
9030 int main( int argc,
9031           char *argv[] )
9032 {
9033   GtkWidget *window;
9034   GtkWidget *main_vbox;
9035   GtkWidget *menubar, *option_menu, *popup_button;
9036  
9037   /* Initialize GTK */
9038   gtk_init (&amp;argc, &amp;argv);
9039  
9040   /* Make a window */
9041   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9042   g_signal_connect (window, "destroy",
9043                     G_CALLBACK (gtk_main_quit),
9044                     NULL);
9045   gtk_window_set_title (GTK_WINDOW(window), "Item Factory");
9046   gtk_widget_set_size_request (GTK_WIDGET(window), 300, 200);
9047  
9048   /* Make a vbox to put the three menus in */
9049   main_vbox = gtk_vbox_new (FALSE, 1);
9050   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 1);
9051   gtk_container_add (GTK_CONTAINER (window), main_vbox);
9052  
9053   /* Get the three types of menu */
9054   /* Note: all three menus are separately created, so they are not the
9055      same menu */
9056   menubar = get_menubar_menu (window);
9057   popup_button = get_popup_menu ();
9058   option_menu = get_option_menu ();
9059   
9060   /* Pack it all together */
9061   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
9062   gtk_box_pack_end (GTK_BOX (main_vbox), popup_button, FALSE, TRUE, 0);
9063   gtk_box_pack_end (GTK_BOX (main_vbox), option_menu, FALSE, TRUE, 0);
9064
9065   /* Show the widgets */
9066   gtk_widget_show_all (window);
9067   
9068   /* Finished! */
9069   gtk_main ();
9070  
9071   return 0;
9072 }
9073 <!-- example-end -->
9074 </programlisting>
9075
9076 </sect1>
9077 </chapter>
9078
9079 <!-- ***************************************************************** -->
9080 <chapter id="ch-UndocWidgets">
9081 <title>Undocumented Widgets</title>
9082
9083 <para>These all require authors! :) Please consider contributing to our
9084 tutorial.</para>
9085
9086 <para>If you must use one of these widgets that are undocumented, I strongly
9087 suggest you take a look at their respective header files in the GTK
9088 distribution. GTK's function names are very descriptive. Once you
9089 have an understanding of how things work, it's not difficult to figure
9090 out how to use a widget simply by looking at its function
9091 declarations. This, along with a few examples from others' code, and
9092 it should be no problem.</para>
9093
9094 <para>When you do come to understand all the functions of a new undocumented
9095 widget, please consider writing a tutorial on it so others may benefit
9096 from your time.</para>
9097
9098 <!-- ----------------------------------------------------------------- -->
9099 <sect1 id="sec-AccelLabel">
9100 <title>Accel Label</title>
9101
9102 <para></para>
9103
9104 </sect1>
9105
9106 <!-- ----------------------------------------------------------------- -->
9107 <sect1 id="sec-OptionMenu">
9108 <title>Option Menu</title>
9109
9110 <para></para>
9111
9112 </sect1>
9113
9114 <!-- ----------------------------------------------------------------- -->
9115 <sect1 id="sec-MenuItems">
9116 <title>Menu Items</title>
9117
9118 <para></para>
9119
9120 <sect2 id="sec-CheckMenuItem">
9121 <title>Check Menu Item</title>
9122
9123 <para></para>
9124 </sect2>
9125
9126 <sect2 id="sec-RadioMenuItem">
9127 <title>Radio Menu Item</title>
9128
9129 <para></para>
9130 </sect2>
9131
9132 <sect2 id="sec-SeparatorMenuItem">
9133 <title>Separator Menu Item</title>
9134
9135 <para></para>
9136 </sect2>
9137
9138 <sect2 id="sec-TearoffMenuItem">
9139 <title>Tearoff Menu Item</title>
9140
9141 <para></para>
9142 </sect2>
9143 </sect1>
9144
9145 <!-- ----------------------------------------------------------------- -->
9146 <sect1 id="sec-Curves">
9147 <title>Curves</title>
9148
9149 <para></para>
9150
9151 </sect1>
9152
9153 <!-- ----------------------------------------------------------------- -->
9154 <sect1 id="sec-DrawingArea">
9155 <title>Drawing Area</title>
9156
9157 <para></para>
9158
9159 </sect1>
9160
9161 <!-- ----------------------------------------------------------------- -->
9162 <sect1 id="sec-FontSelectionDialog">
9163 <title>Font Selection Dialog</title>
9164
9165 <para></para>
9166
9167 </sect1>
9168
9169 <!-- ----------------------------------------------------------------- -->
9170 <sect1 id="sec-MessageDialog">
9171 <title>Message Dialog</title>
9172
9173 <para></para>
9174
9175 </sect1>
9176
9177 <!-- ----------------------------------------------------------------- -->
9178 <sect1 id="sec-GammaCurve">
9179 <title>Gamma Curve</title>
9180
9181 <para></para>
9182
9183 </sect1>
9184
9185 <!-- ----------------------------------------------------------------- -->
9186 <sect1 id="sec-Image">
9187 <title>Image</title>
9188
9189 <para></para>
9190
9191 </sect1>
9192
9193 <!-- ----------------------------------------------------------------- -->
9194 <sect1 id="sec-PlugsAndSockets">
9195 <title>Plugs and Sockets</title>
9196
9197 <para></para>
9198
9199 </sect1>
9200
9201 <!-- ----------------------------------------------------------------- -->
9202 <sect1 id="sec-TreeView">
9203 <title>Tree View</title>
9204
9205 <para></para>
9206
9207 </sect1>
9208
9209 <!-- ----------------------------------------------------------------- -->
9210 <sect1 id="sec-TextView">
9211 <title>Text View</title>
9212
9213 <para></para>
9214
9215 </sect1>
9216 </chapter>
9217
9218 <!-- ***************************************************************** -->
9219 <chapter id="ch-SettingWidgetAttributes">
9220 <title>Setting Widget Attributes</title>
9221
9222 <para>This describes the functions used to operate on widgets. These can be
9223 used to set style, padding, size, etc.</para>
9224
9225 <para>(Maybe I should make a whole section on accelerators.)</para>
9226
9227 <programlisting role="C">
9228 void gtk_widget_activate( GtkWidget *widget );
9229
9230 void gtk_widget_set_name( GtkWidget *widget,
9231                           gchar     *name );
9232
9233 gchar *gtk_widget_get_name( GtkWidget *widget );
9234
9235 void gtk_widget_set_sensitive( GtkWidget *widget,
9236                                gboolean   sensitive );
9237
9238 void gtk_widget_set_style( GtkWidget *widget,
9239                            GtkStyle  *style );
9240                                            
9241 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
9242
9243 GtkStyle *gtk_widget_get_default_style( void );
9244
9245 void gtk_widget_set_size_request( GtkWidget *widget,
9246                                   gint       width,
9247                                   gint       height );
9248
9249 void gtk_widget_grab_focus( GtkWidget *widget );
9250
9251 void gtk_widget_show( GtkWidget *widget );
9252
9253 void gtk_widget_hide( GtkWidget *widget );
9254 </programlisting>
9255
9256 </chapter>
9257
9258 <!-- ***************************************************************** -->
9259 <chapter id="ch-Timeouts">
9260 <title>Timeouts, IO and Idle Functions</title>
9261
9262 <!-- ----------------------------------------------------------------- -->
9263 <sect1 id="sec-Timeouts">
9264 <title>Timeouts</title>
9265
9266 <para>You may be wondering how you make GTK do useful work when in gtk_main.
9267 Well, you have several options. Using the following function you can
9268 create a timeout function that will be called every "interval"
9269 milliseconds.</para>
9270
9271 <programlisting role="C">
9272 gint g_timeout_add (guint32     interval,
9273                     GtkFunction function,
9274                     gpointer    data);
9275 </programlisting>
9276
9277 <para>The first argument is the number of milliseconds between calls to your
9278 function. The second argument is the function you wish to have called,
9279 and the third, the data passed to this callback function. The return
9280 value is an integer "tag" which may be used to stop the timeout by
9281 calling:</para>
9282
9283 <programlisting role="C">
9284 void g_source_remove (gint tag);
9285 </programlisting>
9286
9287 <para>You may also stop the timeout function by returning zero or FALSE from
9288 your callback function. Obviously this means if you want your function
9289 to continue to be called, it should return a non-zero value,
9290 i.e., TRUE.</para>
9291
9292 <para>The declaration of your callback should look something like this:</para>
9293
9294 <programlisting role="C">
9295 gint timeout_callback (gpointer data);
9296 </programlisting>
9297
9298 </sect1>
9299
9300 <!-- ----------------------------------------------------------------- -->
9301 <sect1 id="sec-MonitoringIO">
9302 <title>Monitoring IO</title>
9303
9304 <para>A nifty feature of GDK (the library that underlies GTK), is the
9305 ability to have it check for data on a file descriptor for you (as
9306 returned by open(2) or socket(2)). This is especially useful for
9307 networking applications. The function:</para>
9308
9309 <programlisting role="C">
9310 gint gdk_input_add( gint              source,
9311                     GdkInputCondition condition,
9312                     GdkInputFunction  function,
9313                     gpointer          data );
9314 </programlisting>
9315
9316 <para>Where the first argument is the file descriptor you wish to have
9317 watched, and the second specifies what you want GDK to look for. This
9318 may be one of:</para>
9319
9320 <itemizedlist>
9321 <listitem><simpara><literal>GDK_INPUT_READ</literal> - Call your function when there is data
9322 ready for reading on your file descriptor.</simpara>
9323 </listitem>
9324
9325 <listitem><simpara><literal>GDK_INPUT_WRITE</literal> - Call your function when the file
9326 descriptor is ready for writing.</simpara>
9327 </listitem>
9328 </itemizedlist>
9329
9330 <para>As I'm sure you've figured out already, the third argument is the
9331 function you wish to have called when the above conditions are
9332 satisfied, and the fourth is the data to pass to this function.</para>
9333
9334 <para>The return value is a tag that may be used to stop GDK from monitoring
9335 this file descriptor using the following function.</para>
9336
9337 <programlisting role="C">
9338 void gdk_input_remove( gint tag );
9339 </programlisting>
9340
9341 <para>The callback function should be declared as:</para>
9342
9343 <programlisting role="C">
9344 void input_callback( gpointer          data,
9345                      gint              source, 
9346                      GdkInputCondition condition );
9347 </programlisting>
9348
9349 <para>Where <literal>source</literal> and <literal>condition</literal> are as specified above.</para>
9350
9351 </sect1>
9352
9353 <!-- ----------------------------------------------------------------- -->
9354 <sect1 id="sec-IdleFunctions">
9355 <title>Idle Functions</title>
9356
9357 <para><!-- TODO: Need to check on idle priorities - TRG -->
9358 What if you have a function which you want to be called when nothing
9359 else is happening ?</para>
9360
9361 <programlisting role="C">
9362 guint g_idle_add( GSourceFunc function,
9363                   gpointer    data );
9364 </programlisting>
9365
9366 <para>This causes GTK to call the specified function whenever nothing else
9367 is happening.</para>
9368
9369 <programlisting role="C">
9370 void g_source_remove( guint tag );
9371 </programlisting>
9372
9373 <para>I won't explain the meaning of the arguments as they follow very much
9374 like the ones above. The function pointed to by the first argument to
9375 g_idle_add will be called whenever the opportunity arises. As with
9376 the others, returning FALSE will stop the idle function from being
9377 called.</para>
9378
9379 </sect1>
9380 </chapter>
9381
9382 <!-- ***************************************************************** -->
9383 <chapter id="ch-AdvancedEventsAndSignals">
9384 <title>Advanced Event and Signal Handling</title>
9385
9386 <!-- ----------------------------------------------------------------- -->
9387 <sect1 id="sec-SignalFunctions">
9388 <title>Signal Functions</title>
9389
9390 <!-- ----------------------------------------------------------------- -->
9391 <sect2>
9392 <title>Connecting and Disconnecting Signal Handlers</title>
9393
9394 <programlisting role="C">
9395 gulong g_signal_connect( GObject     *object,
9396                          const gchar *name,
9397                          GCallback    func,
9398                          gpointer     func_data );
9399
9400 gulong g_signal_connect_after( GObject       *object,
9401                                const gchar   *name,
9402                                GCallback      func,
9403                                gpointer       func_data );
9404
9405 gulong g_signal_connect_swapped( GObject       *object,
9406                                  const gchar   *name,
9407                                  GCallback      func,
9408                                  GObject       *slot_object );
9409
9410 void g_signal_handler_disconnect( GObject *object,
9411                                   gulong   handler_id );
9412
9413 void g_signal_handlers_disconnect_by_func( GObject   *object,
9414                                            GCallback  func,
9415                                            gpointer   data );
9416 </programlisting>
9417
9418 </sect2>
9419
9420 <!-- ----------------------------------------------------------------- -->
9421 <sect2>
9422 <title>Blocking and Unblocking Signal Handlers</title>
9423
9424 <programlisting role="C">
9425 void g_signal_handler_block( GObject *object,
9426                              gulong   handler_id);
9427
9428 void g_signal_handlers_block_by_func( GObject   *object,
9429                                       GCallback  func,
9430                                       gpointer   data );
9431
9432 void g_signal_handler_unblock( GObject *object,
9433                                gulong   handler_id );
9434
9435 void g_signal_handler_unblock_by_func( GObject   *object,
9436                                        GCallback  func,
9437                                        gpointer   data );
9438 </programlisting>
9439
9440 </sect2>
9441
9442 <!-- ----------------------------------------------------------------- -->
9443 <sect2>
9444 <title>Emitting and Stopping Signals</title>
9445
9446 <programlisting role="C">
9447 void g_signal_emit( GObject *object,
9448                     guint      signal_id,
9449                     ... );
9450
9451 void g_signal_emit_by_name( GObject     *object,
9452                             const gchar *name,
9453                             ... );
9454
9455 void g_signal_emitv( const GValue *instance_and_params,
9456                      guint         signal_id,
9457                      GQuark        detail,
9458                      GValue       *return_value );
9459
9460 void g_signal_stop_emission( GObject *object,
9461                              guint    signal_id,
9462                              GQuark   detail );
9463
9464 void g_signal_stop_emission_by_name( GObject   *object,
9465                                      const gchar *detailed_signal );
9466 </programlisting>
9467
9468 </sect2>
9469 </sect1>
9470
9471 <!-- ----------------------------------------------------------------- -->
9472 <sect1 id="sec-SignalEmissionAndPropagation">
9473 <title>Signal Emission and Propagation</title>
9474
9475 <para>Signal emission is the process whereby GTK runs all handlers for a
9476 specific object and signal.</para>
9477
9478 <para>First, note that the return value from a signal emission is the return
9479 value of the <emphasis>last</emphasis> handler executed. Since event signals are
9480 all of type <literal>GTK_RUN_LAST</literal>, this will be the default (GTK supplied)
9481 handler, unless you connect with gtk_signal_connect_after().</para>
9482
9483 <para>The way an event (say "button_press_event") is handled, is:</para>
9484
9485 <itemizedlist>
9486 <listitem><simpara>Start with the widget where the event occured.</simpara>
9487 </listitem>
9488
9489 <listitem><simpara>Emit the generic "event" signal. If that signal handler returns
9490 a value of TRUE, stop all processing.</simpara>
9491 </listitem>
9492
9493 <listitem><simpara>Otherwise, emit a specific, "button_press_event" signal. If that
9494 returns TRUE, stop all processing.</simpara>
9495 </listitem>
9496
9497 <listitem><simpara>Otherwise, go to the widget's parent, and repeat the above two
9498 steps.</simpara>
9499 </listitem>
9500
9501 <listitem><simpara>Continue until some signal handler returns TRUE, or until the
9502 top-level widget is reached.</simpara>
9503 </listitem>
9504 </itemizedlist>
9505
9506 <para>Some consequences of the above are:</para>
9507
9508 <itemizedlist>
9509 <listitem><simpara>Your handler's return value will have no effect if there is a
9510 default handler, unless you connect with gtk_signal_connect_after().</simpara>
9511 </listitem>
9512
9513 <listitem><simpara>To prevent the default handler from being run, you need to
9514 connect with gtk_signal_connect() and use
9515 gtk_signal_emit_stop_by_name() - the return value only affects whether
9516 the signal is propagated, not the current emission.</simpara>
9517 </listitem>
9518 </itemizedlist>
9519
9520 </sect1>
9521 </chapter>
9522
9523 <!-- continue GTK+ 2.0 review here -->
9524
9525 <!-- ***************************************************************** -->
9526 <chapter id="ch-ManagingSelections">
9527 <title>Managing Selections</title>
9528
9529 <!-- ----------------------------------------------------------------- -->
9530 <sect1 id="sec-SelectionsOverview">
9531 <title>Overview</title>
9532
9533 <para>One type of interprocess communication supported by X and GTK is
9534 <emphasis>selections</emphasis>. A selection identifies a chunk of data, for
9535 instance, a portion of text, selected by the user in some fashion, for
9536 instance, by dragging with the mouse. Only one application on a
9537 display (the <emphasis>owner</emphasis>) can own a particular selection at one
9538 time, so when a selection is claimed by one application, the previous
9539 owner must indicate to the user that selection has been
9540 relinquished. Other applications can request the contents of a
9541 selection in different forms, called <emphasis>targets</emphasis>. There can be
9542 any number of selections, but most X applications only handle one, the
9543 <emphasis>primary selection</emphasis>.</para>
9544
9545 <para>In most cases, it isn't necessary for a GTK application to deal with
9546 selections itself. The standard widgets, such as the Entry widget,
9547 already have the capability to claim the selection when appropriate
9548 (e.g., when the user drags over text), and to retrieve the contents of
9549 the selection owned by another widget or another application (e.g.,
9550 when the user clicks the second mouse button). However, there may be
9551 cases in which you want to give other widgets the ability to supply
9552 the selection, or you wish to retrieve targets not supported by
9553 default.</para>
9554
9555 <para>A fundamental concept needed to understand selection handling is that
9556 of the <emphasis>atom</emphasis>. An atom is an integer that uniquely identifies a
9557 string (on a certain display). Certain atoms are predefined by the X
9558 server, and in some cases there are constants in <literal>gtk.h</literal>
9559 corresponding to these atoms. For instance the constant
9560 <literal>GDK_PRIMARY_SELECTION</literal> corresponds to the string "PRIMARY".
9561 In other cases, you should use the functions
9562 <literal>gdk_atom_intern()</literal>, to get the atom corresponding to a string,
9563 and <literal>gdk_atom_name()</literal>, to get the name of an atom. Both
9564 selections and targets are identified by atoms.</para>
9565
9566 </sect1>
9567 <!-- ----------------------------------------------------------------- -->
9568 <sect1 id="sec-RetrievingTheSelection">
9569 <title>Retrieving the selection</title>
9570
9571 <para>Retrieving the selection is an asynchronous process. To start the
9572 process, you call:</para>
9573
9574 <programlisting role="C">
9575 gboolean gtk_selection_convert( GtkWidget *widget, 
9576                                 GdkAtom    selection, 
9577                                 GdkAtom    target,
9578                                 guint32    time );
9579 </programlisting>
9580
9581 <para>This <emphasis>converts</emphasis> the selection into the form specified by
9582 <literal>target</literal>. If at all possible, the time field should be the time
9583 from the event that triggered the selection. This helps make sure that
9584 events occur in the order that the user requested them. However, if it
9585 is not available (for instance, if the conversion was triggered by a
9586 "clicked" signal), then you can use the constant
9587 <literal>GDK_CURRENT_TIME</literal>.</para>
9588
9589 <para>When the selection owner responds to the request, a
9590 "selection_received" signal is sent to your application. The handler
9591 for this signal receives a pointer to a <literal>GtkSelectionData</literal>
9592 structure, which is defined as:</para>
9593
9594 <programlisting role="C">
9595 struct _GtkSelectionData
9596 {
9597   GdkAtom selection;
9598   GdkAtom target;
9599   GdkAtom type;
9600   gint    format;
9601   guchar *data;
9602   gint    length;
9603 };
9604 </programlisting>
9605
9606 <para><literal>selection</literal> and <literal>target</literal> are the values you gave in your
9607 <literal>gtk_selection_convert()</literal> call. <literal>type</literal> is an atom that
9608 identifies the type of data returned by the selection owner. Some
9609 possible values are "STRING", a string of latin-1 characters, "ATOM",
9610 a series of atoms, "INTEGER", an integer, etc. Most targets can only
9611 return one type. <literal>format</literal> gives the length of the units (for
9612 instance characters) in bits. Usually, you don't care about this when
9613 receiving data. <literal>data</literal> is a pointer to the returned data, and
9614 <literal>length</literal> gives the length of the returned data, in bytes. If
9615 <literal>length</literal> is negative, then an error occurred and the selection
9616 could not be retrieved. This might happen if no application owned the
9617 selection, or if you requested a target that the application didn't
9618 support. The buffer is actually guaranteed to be one byte longer than
9619 <literal>length</literal>; the extra byte will always be zero, so it isn't
9620 necessary to make a copy of strings just to nul-terminate them.</para>
9621
9622 <para>In the following example, we retrieve the special target "TARGETS",
9623 which is a list of all targets into which the selection can be
9624 converted.</para>
9625
9626 <programlisting role="C">
9627 <!-- example-start selection gettargets.c -->
9628
9629 #include &lt;stdlib.h&gt;
9630 #include &lt;gtk/gtk.h&gt;
9631
9632 static void selection_received( GtkWidget        *widget, 
9633                                 GtkSelectionData *selection_data, 
9634                                 gpointer          data );
9635
9636 /* Signal handler invoked when user clicks on the "Get Targets" button */
9637 static void get_targets( GtkWidget *widget,
9638                          gpointer data )
9639 {
9640   static GdkAtom targets_atom = GDK_NONE;
9641   GtkWidget *window = (GtkWidget *)data;        
9642
9643   /* Get the atom corresponding to the string "TARGETS" */
9644   if (targets_atom == GDK_NONE)
9645     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
9646
9647   /* And request the "TARGETS" target for the primary selection */
9648   gtk_selection_convert (window, GDK_SELECTION_PRIMARY, targets_atom,
9649                          GDK_CURRENT_TIME);
9650 }
9651
9652 /* Signal handler called when the selections owner returns the data */
9653 static void selection_received( GtkWidget        *widget,
9654                                 GtkSelectionData *selection_data, 
9655                                 gpointer          data )
9656 {
9657   GdkAtom *atoms;
9658   GList *item_list;
9659   int i;
9660
9661   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
9662   if (selection_data-&gt;length &lt; 0)
9663     {
9664       g_print ("Selection retrieval failed\n");
9665       return;
9666     }
9667   /* Make sure we got the data in the expected form */
9668   if (selection_data-&gt;type != GDK_SELECTION_TYPE_ATOM)
9669     {
9670       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
9671       return;
9672     }
9673   
9674   /* Print out the atoms we received */
9675   atoms = (GdkAtom *)selection_data-&gt;data;
9676
9677   item_list = NULL;
9678   for (i = 0; i &lt; selection_data-&gt;length / sizeof(GdkAtom); i++)
9679     {
9680       char *name;
9681       name = gdk_atom_name (atoms[i]);
9682       if (name != NULL)
9683         g_print ("%s\n",name);
9684       else
9685         g_print ("(bad atom)\n");
9686     }
9687
9688   return;
9689 }
9690
9691 int main( int   argc,
9692           char *argv[] )
9693 {
9694   GtkWidget *window;
9695   GtkWidget *button;
9696   
9697   gtk_init (&amp;argc, &amp;argv);
9698
9699   /* Create the toplevel window */
9700
9701   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9702   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
9703   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9704
9705   g_signal_connect (window, "destroy",
9706                     G_CALLBACK (exit), NULL);
9707
9708   /* Create a button the user can click to get targets */
9709
9710   button = gtk_button_new_with_label ("Get Targets");
9711   gtk_container_add (GTK_CONTAINER (window), button);
9712
9713   g_signal_connect (button, "clicked",
9714                     G_CALLBACK (get_targets), (gpointer) window);
9715   g_signal_connect (window, "selection_received",
9716                     G_CALLBACK (selection_received), NULL);
9717
9718   gtk_widget_show (button);
9719   gtk_widget_show (window);
9720   
9721   gtk_main ();
9722   
9723   return 0;
9724 }
9725 <!-- example-end -->
9726 </programlisting>
9727
9728 </sect1>
9729 <!-- ----------------------------------------------------------------- -->
9730 <sect1 id="sec-SupplyingTheSelection">
9731 <title>Supplying the selection</title>
9732
9733 <para>Supplying the selection is a bit more complicated. You must register 
9734 handlers that will be called when your selection is requested. For
9735 each selection/target pair you will handle, you make a call to:</para>
9736
9737 <programlisting role="C">
9738 void gtk_selection_add_target( GtkWidget           *widget, 
9739                                GdkAtom              selection,
9740                                GdkAtom              target,
9741                                guint                info );
9742 </programlisting>
9743
9744 <para><literal>widget</literal>, <literal>selection</literal>, and <literal>target</literal> identify the requests
9745 this handler will manage. When a request for a selection is received,
9746 the "selection_get" signal will be called. <literal>info</literal> can be used as an
9747 enumerator to identify the specific target within the callback function.</para>
9748
9749 <para>The callback function has the signature:</para>
9750
9751 <programlisting role="C">
9752 void  "selection_get"( GtkWidget          *widget,
9753                        GtkSelectionData   *selection_data,
9754                        guint               info,
9755                        guint               time );
9756 </programlisting>
9757
9758 <para>The GtkSelectionData is the same as above, but this time, we're
9759 responsible for filling in the fields <literal>type</literal>, <literal>format</literal>,
9760 <literal>data</literal>, and <literal>length</literal>. (The <literal>format</literal> field is actually
9761 important here - the X server uses it to figure out whether the data
9762 needs to be byte-swapped or not. Usually it will be 8 - <emphasis>i.e.</emphasis> a
9763 character - or 32 - <emphasis>i.e.</emphasis> an integer.) This is done by calling the
9764 function:</para>
9765
9766 <programlisting role="C">
9767 void gtk_selection_data_set( GtkSelectionData *selection_data,
9768                              GdkAtom           type,
9769                              gint              format,
9770                              guchar           *data,
9771                              gint              length );
9772 </programlisting>
9773
9774 <para>This function takes care of properly making a copy of the data so that
9775 you don't have to worry about keeping it around. (You should not fill
9776 in the fields of the GtkSelectionData structure by hand.)</para>
9777
9778 <para>When prompted by the user, you claim ownership of the selection by
9779 calling:</para>
9780
9781 <programlisting role="C">
9782 gboolean gtk_selection_owner_set( GtkWidget *widget,
9783                                   GdkAtom    selection,
9784                                   guint32    time );
9785 </programlisting>
9786
9787 <para>If another application claims ownership of the selection, you will
9788 receive a "selection_clear_event".</para>
9789
9790 <para>As an example of supplying the selection, the following program adds
9791 selection functionality to a toggle button. When the toggle button is
9792 depressed, the program claims the primary selection. The only target
9793 supported (aside from certain targets like "TARGETS" supplied by GTK
9794 itself), is the "STRING" target. When this target is requested, a
9795 string representation of the time is returned.</para>
9796
9797 <programlisting role="C">
9798 <!-- example-start selection setselection.c -->
9799
9800 #include &lt;stdlib.h&gt;
9801 #include &lt;gtk/gtk.h&gt;
9802 #include &lt;time.h&gt;
9803 #include &lt;string.h&gt;
9804
9805 GtkWidget *selection_button;
9806 GtkWidget *selection_widget;
9807
9808 /* Callback when the user toggles the selection */
9809 static void selection_toggled( GtkWidget *widget,
9810                                gint      *have_selection )
9811 {
9812   if (GTK_TOGGLE_BUTTON (widget)-&gt;active)
9813     {
9814       *have_selection = gtk_selection_owner_set (selection_widget,
9815                                                  GDK_SELECTION_PRIMARY,
9816                                                  GDK_CURRENT_TIME);
9817       /* if claiming the selection failed, we return the button to
9818          the out state */
9819       if (!*have_selection)
9820         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
9821     }
9822   else
9823     {
9824       if (*have_selection)
9825         {
9826           /* Before clearing the selection by setting the owner to NULL,
9827              we check if we are the actual owner */
9828           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget-&gt;window)
9829             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
9830                                      GDK_CURRENT_TIME);
9831           *have_selection = FALSE;
9832         }
9833     }
9834 }
9835
9836 /* Called when another application claims the selection */
9837 static gboolean selection_clear( GtkWidget         *widget,
9838                                  GdkEventSelection *event,
9839                                  gint              *have_selection )
9840 {
9841   *have_selection = FALSE;
9842   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (selection_button), FALSE);
9843
9844   return TRUE;
9845 }
9846
9847 /* Supplies the current time as the selection. */
9848 static void selection_handle( GtkWidget        *widget, 
9849                               GtkSelectionData *selection_data,
9850                               guint             info,
9851                               guint             time_stamp,
9852                               gpointer          data )
9853 {
9854   gchar *timestr;
9855   time_t current_time;
9856
9857   current_time = time (NULL);
9858   timestr = asctime (localtime (&amp;current_time)); 
9859   /* When we return a single string, it should not be null terminated.
9860      That will be done for us */
9861
9862   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
9863                           8, timestr, strlen (timestr));
9864 }
9865
9866 int main( int   argc,
9867           char *argv[] )
9868 {
9869   GtkWidget *window;
9870
9871   static int have_selection = FALSE;
9872   
9873   gtk_init (&amp;argc, &amp;argv);
9874
9875   /* Create the toplevel window */
9876
9877   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9878   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
9879   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9880
9881   g_signal_connect (window, "destroy",
9882                     G_CALLBACK (exit), NULL);
9883
9884   /* Create a toggle button to act as the selection */
9885
9886   selection_widget = gtk_invisible_new ();
9887   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
9888   gtk_container_add (GTK_CONTAINER (window), selection_button);
9889   gtk_widget_show (selection_button);
9890
9891   g_signal_connect (selection_button, "toggled",
9892                     G_CALLBACK (selection_toggled), (gpointer) &amp;have_selection);
9893   g_signal_connect (selection_widget, "selection_clear_event",
9894                     G_CALLBACK (selection_clear), (gpointer) &amp;have_selection);
9895
9896   gtk_selection_add_target (selection_widget,
9897                             GDK_SELECTION_PRIMARY,
9898                             GDK_SELECTION_TYPE_STRING,
9899                             1);
9900   g_signal_connect (selection_widget, "selection_get",
9901                     G_CALLBACK (selection_handle), (gpointer) &amp;have_selection);
9902
9903   gtk_widget_show (selection_button);
9904   gtk_widget_show (window);
9905   
9906   gtk_main ();
9907   
9908   return 0;
9909 }
9910 <!-- example-end -->
9911 </programlisting>
9912
9913 </sect1>
9914 </chapter>
9915
9916 <!-- ***************************************************************** -->
9917 <chapter id="ch-DragAngDrop">
9918 <title>Drag-and-drop (DND)</title>
9919
9920 <para>GTK+ has a high level set of functions for doing inter-process
9921 communication via the drag-and-drop system. GTK+ can perform
9922 drag-and-drop on top of the low level Xdnd and Motif drag-and-drop
9923 protocols.</para>
9924
9925 <!-- ----------------------------------------------------------------- -->
9926 <sect1 id="sec-DragAndDropOverview">
9927 <title>Overview</title>
9928
9929 <para>An application capable of GTK+ drag-and-drop first defines and sets up
9930 the GTK+ widget(s) for drag-and-drop. Each widget can be a source
9931 and/or destination for drag-and-drop. Note that these GTK+ widgets must have
9932 an associated X Window, check using gtk_widget_get_has_window (widget).</para>
9933
9934 <para>Source widgets can send out drag data, thus allowing the user to drag
9935 things off of them, while destination widgets can receive drag data.
9936 Drag-and-drop destinations can limit who they accept drag data from,
9937 e.g. the same application or any application (including itself).</para>
9938
9939 <para>Sending and receiving drop data makes use of GTK+ signals.
9940 Dropping an item to a destination widget requires both a data
9941 request (for the source widget) and data received signal handler (for
9942 the target widget). Additional signal handers can be connected if you
9943 want to know when a drag begins (at the very instant it starts), to
9944 when a drop is made, and when the entire drag-and-drop procedure has
9945 ended (successfully or not).</para>
9946
9947 <para>Your application will need to provide data for source widgets when
9948 requested, that involves having a drag data request signal handler. For
9949 destination widgets they will need a drop data received signal
9950 handler. </para>
9951
9952 <para>So a typical drag-and-drop cycle would look as follows:</para>
9953 <orderedlist>
9954 <listitem><simpara> Drag begins.</simpara>
9955 </listitem>
9956 <listitem><simpara> Drag data request (when a drop occurs).</simpara>
9957 </listitem>
9958 <listitem><simpara> Drop data received (may be on same or different
9959 application).</simpara>
9960 </listitem>
9961 <listitem><simpara> Drag data delete (if the drag was a move).</simpara>
9962 </listitem>
9963 <listitem><simpara> Drag-and-drop procedure done.</simpara>
9964 </listitem>
9965 </orderedlist>
9966
9967 <para>There are a few minor steps that go in between here and there, but we
9968 will get into detail about that later.</para>
9969
9970 </sect1>
9971
9972 <!-- ----------------------------------------------------------------- -->
9973 <sect1 id="sec-DragAndDropProperties">
9974 <title>Properties</title>
9975
9976 <para>Drag data has the following properties:</para>
9977
9978 <itemizedlist>
9979 <listitem><simpara> Drag action type (ie GDK_ACTION_COPY, GDK_ACTION_MOVE).</simpara>
9980 </listitem>
9981
9982 <listitem><simpara> Client specified arbitrary drag-and-drop type (a name and number pair).</simpara>
9983 </listitem>
9984
9985 <listitem><simpara> Sent and received data format type.</simpara>
9986 </listitem>
9987 </itemizedlist>
9988
9989 <para>Drag actions are quite obvious, they specify if the widget can
9990 drag with the specified action(s), e.g. GDK_ACTION_COPY and/or
9991 GDK_ACTION_MOVE. A GDK_ACTION_COPY would be a typical drag-and-drop
9992 without the source data being deleted while GDK_ACTION_MOVE would be
9993 just like GDK_ACTION_COPY but the source data will be 'suggested' to be
9994 deleted after the received signal handler is called. There are
9995 additional drag actions including GDK_ACTION_LINK which you may want to
9996 look into when you get to more advanced levels of drag-and-drop.</para>
9997
9998 <para>The client specified arbitrary drag-and-drop type is much more
9999 flexible, because your application will be defining and checking for
10000 that specifically. You will need to set up your destination widgets to
10001 receive certain drag-and-drop types by specifying a name and/or number.
10002 It would be more reliable to use a name since another application may
10003 just happen to use the same number for an entirely different
10004 meaning.</para>
10005
10006 <para>Sent and received data format types (<emphasis>selection
10007 target</emphasis>) come into play only in your request and received
10008 data handler functions. The term <emphasis>selection target</emphasis>
10009 is somewhat misleading. It is a term adapted from GTK+ selection
10010 (cut/copy and paste). What <emphasis>selection target</emphasis>
10011 actually means is the data's format type (i.e. GdkAtom, integer, or
10012 string) that being sent or received. Your request data handler function
10013 needs to specify the type (<emphasis>selection target</emphasis>) of
10014 data that it sends out and your received data handler needs to handle
10015 the type (<emphasis>selection target</emphasis>) of data
10016 received.</para>
10017
10018 </sect1>
10019
10020 <!-- ----------------------------------------------------------------- -->
10021 <sect1 id="sec-DragAndDropFunctions">
10022 <title>Functions</title>
10023
10024 <!-- ----------------------------------------------------------------- -->
10025 <sect2 id="sec-DNDSourceWidgets">
10026 <title>Setting up the source widget</title>
10027
10028 <para>The function <literal>gtk_drag_source_set()</literal> specifies a
10029 set of target types for a drag operation on a widget.</para>
10030
10031 <programlisting role="C">
10032 void gtk_drag_source_set( GtkWidget            *widget,
10033                           GdkModifierType       start_button_mask,
10034                           const GtkTargetEntry *targets,
10035                           gint                  n_targets,
10036                           GdkDragAction         actions );
10037 </programlisting>
10038
10039 <para>The parameters signify the following:</para>
10040 <itemizedlist>
10041 <listitem><simpara><literal>widget</literal> specifies the drag source
10042 widget</simpara>
10043 </listitem>
10044 <listitem><simpara><literal>start_button_mask</literal> specifies a
10045 bitmask of buttons that can start the drag (e.g. GDK_BUTTON1_MASK)</simpara>
10046 </listitem>
10047 <listitem><simpara><literal>targets</literal> specifies a table of
10048 target data types the drag will support</simpara>
10049 </listitem>
10050 <listitem><simpara><literal>n_targets</literal> specifies the number of
10051 targets above</simpara>
10052 </listitem>
10053 <listitem><simpara><literal>actions</literal> specifies a bitmask of
10054 possible actions for a drag from this window</simpara>
10055 </listitem>
10056 </itemizedlist>
10057
10058 <para>The <literal>targets</literal> parameter is an array of the
10059 following structure:</para>
10060
10061 <programlisting role="C">
10062 struct GtkTargetEntry {
10063    gchar *target;
10064    guint  flags;
10065    guint  info;
10066  };
10067 </programlisting>
10068
10069 <para>The fields specify a string representing the drag type, optional
10070 flags and application assigned integer identifier.</para>
10071
10072 <para>If a widget is no longer required to act as a source for
10073 drag-and-drop operations, the function
10074 <literal>gtk_drag_source_unset()</literal> can be used to remove a set
10075 of drag-and-drop target types.</para>
10076
10077 <programlisting role="C">
10078 void gtk_drag_source_unset( GtkWidget *widget );
10079 </programlisting>
10080
10081 </sect2>
10082
10083 <!-- ----------------------------------------------------------------- -->
10084 <sect2 id="sec-SignalsOnSourceWidgets">
10085 <title>Signals on the source widget:</title>
10086
10087 <para>The source widget is sent the following signals during a
10088 drag-and-drop operation.</para>
10089
10090 <table pgwide="1">
10091 <title>Source widget signals</title>
10092 <tgroup cols="2">
10093 <colspec colname="Name" colwidth="150">
10094 <colspec colname="Prototype">
10095 <tbody>
10096 <row>
10097 <entry align="left" valign="middle">drag_begin</entry>
10098 <entry align="left" valign="middle"><literal>void (*drag_begin)(GtkWidget *widget,
10099 GdkDragContext *dc, gpointer data)</literal></entry>
10100 </row>
10101 <row>
10102 <entry align="left" valign="middle">drag_motion</entry>
10103 <entry align="left" valign="middle"><literal>gboolean (*drag_motion)(GtkWidget *widget,
10104 GdkDragContext *dc, gint x, gint y, guint t, gpointer data)</literal></entry>
10105 </row>
10106 <row>
10107 <entry align="left" valign="middle">drag_data_get</entry>
10108 <entry align="left" valign="middle"><literal>void (*drag_data_get)(GtkWidget *widget,
10109 GdkDragContext *dc, GtkSelectionData *selection_data, guint info, guint t, gpointer data)</literal></entry>
10110 </row>
10111 <row>
10112 <entry align="left" valign="middle">drag_data_delete</entry>
10113 <entry align="left" valign="middle"><literal>void (*drag_data_delete)(GtkWidget *widget,
10114 GdkDragContext *dc, gpointer data)</literal></entry>
10115 </row>
10116 <row>
10117 <entry align="left" valign="middle">drag_drop</entry>
10118 <entry align="left" valign="middle"><literal>gboolean (*drag_drop)(GtkWidget *widget,
10119 GdkDragContext *dc, gint x, gint y, guint t, gpointer data)</literal></entry>
10120 </row>
10121 <row>
10122 <entry align="left" valign="middle">drag_end</entry>
10123 <entry align="left" valign="middle"><literal>void (*drag_end)(GtkWidget *widget,
10124 GdkDragContext *dc, gpointer data)</literal></entry>
10125 </row>
10126 </tbody>
10127 </tgroup>
10128 </table>
10129
10130 </sect2>
10131
10132 <!-- ----------------------------------------------------------------- -->
10133 <sect2 id="sec-DNDDestWidgets">
10134 <title>Setting up a destination widget:</title>
10135
10136 <para> <literal> gtk_drag_dest_set()</literal> specifies
10137 that this widget can receive drops and specifies what types of drops it
10138 can receive.</para>
10139
10140 <para> <literal> gtk_drag_dest_unset()</literal> specifies
10141 that the widget can no longer receive drops.</para>
10142
10143 <programlisting role="C">
10144 void gtk_drag_dest_set( GtkWidget            *widget,
10145                         GtkDestDefaults       flags,
10146                         const GtkTargetEntry *targets,
10147                         gint                  n_targets,
10148                         GdkDragAction         actions );
10149
10150 void gtk_drag_dest_unset( GtkWidget *widget );
10151 </programlisting>
10152
10153 </sect2>
10154
10155 <!-- ----------------------------------------------------------------- -->
10156 <sect2 id="sec-SignalsOnDestWidgets">
10157 <title>Signals on the destination widget:</title>
10158
10159 <para>The destination widget is sent the following signals during a
10160 drag-and-drop operation.</para>
10161
10162 <table pgwide="1">
10163 <title>Destination widget signals</title>
10164 <tgroup cols="2">
10165 <colspec colname="Name" colwidth="150">
10166 <colspec colname="Prototype">
10167 <tbody>
10168 <row>
10169 <entry align="left" valign="middle">drag_data_received</entry>
10170 <entry align="left" valign="middle"><literal>void (*drag_data_received)(GtkWidget *widget,
10171 GdkDragContext *dc, gint x, gint y, GtkSelectionData *selection_data, guint info, guint t,
10172 gpointer data)</literal></entry>
10173 </row>
10174 </tbody>
10175 </tgroup>
10176 </table>
10177
10178 </sect2>
10179 </sect1>
10180 </chapter>
10181
10182 <!-- ***************************************************************** -->
10183 <chapter id="ch-GLib">
10184 <title>GLib</title>
10185
10186 <para>GLib is a lower-level library that provides many useful definitions
10187 and functions available for use when creating GDK and GTK
10188 applications. These include definitions for basic types and their
10189 limits, standard macros, type conversions, byte order, memory
10190 allocation, warnings and assertions, message logging, timers, string
10191 utilities, hook functions, a lexical scanner, dynamic loading of
10192 modules, and automatic string completion. A number of data structures
10193 (and their related operations) are also defined, including memory
10194 chunks, doubly-linked lists, singly-linked lists, hash tables, strings
10195 (which can grow dynamically), string chunks (groups of strings),
10196 arrays (which can grow in size as elements are added), balanced binary
10197 trees, N-ary trees, quarks (a two-way association of a string and a
10198 unique integer identifier), keyed data lists (lists of data elements
10199 accessible by a string or integer id), relations and tuples (tables of
10200 data which can be indexed on any number of fields), and caches.</para>
10201
10202 <para>A summary of some of GLib's capabilities follows; not every function,
10203 data structure, or operation is covered here.  For more complete
10204 information about the GLib routines, see the GLib documentation. One
10205 source of GLib documentation is <ulink url="http://www.gtk.org/">http://www.gtk.org/</ulink>.</para>
10206
10207 <para>If you are using a language other than C, you should consult your
10208 language's binding documentation. In some cases your language may
10209 have equivalent functionality built-in, while in other cases it may
10210 not.</para>
10211
10212 <!-- ----------------------------------------------------------------- -->
10213 <sect1 id="sec-Definitions">
10214 <title>Definitions</title>
10215
10216 <para>Definitions for the extremes of many of the standard types are:</para>
10217
10218 <programlisting role="C">
10219 G_MINFLOAT
10220 G_MAXFLOAT
10221 G_MINDOUBLE
10222 G_MAXDOUBLE
10223 G_MINSHORT
10224 G_MAXSHORT
10225 G_MAXUSHORT
10226 G_MININT
10227 G_MAXINT
10228 G_MAXUINT
10229 G_MINLONG
10230 G_MAXLONG
10231 G_MAXULONG
10232 G_MININT64
10233 G_MAXINT64
10234 G_MAXUINT64
10235 </programlisting>
10236
10237 <para>Also, the following typedefs. The ones left unspecified are dynamically set
10238 depending on the architecture. Remember to avoid counting on the size of a
10239 pointer if you want to be portable! E.g., a pointer on an Alpha is 8
10240 bytes, but 4 on Intel 80x86 family CPUs.</para>
10241
10242 <programlisting role="C">
10243 char   gchar;
10244 short  gshort;
10245 long   glong;
10246 int    gint;
10247 int    gboolean;
10248
10249 unsigned char   guchar;
10250 unsigned short  gushort;
10251 unsigned long   gulong;
10252 unsigned int    guint;
10253
10254 float   gfloat;
10255 double  gdouble;
10256
10257 unsigned int  gsize;
10258 signed int    gssize;
10259
10260 void*       gpointer;
10261 const void* gconstpointer;
10262
10263 gint8
10264 guint8
10265 gint16
10266 guint16
10267 gint32
10268 guint32
10269 gint64
10270 guint64
10271 </programlisting>
10272
10273 </sect1>
10274
10275 <!-- ----------------------------------------------------------------- -->
10276 <sect1 id="sec-DoublyLinkedLists">
10277 <title>Doubly Linked Lists</title>
10278
10279 <para>The following functions are used to create, manage, and destroy
10280 standard doubly linked lists. Each element in the list contains a
10281 piece of data, together with pointers which link to the previous and
10282 next elements in the list. This enables easy movement in either
10283 direction through the list. The data item is of type "gpointer",
10284 which means the data can be a pointer to your real data or (through
10285 casting) a numeric value (but do not assume that int and gpointer have
10286 the same size!). These routines internally allocate list elements in
10287 blocks, which is more efficient than allocating elements individually.</para>
10288
10289 <para>There is no function to specifically create a list. Instead, simply
10290 create a variable of type GList* and set its value to NULL; NULL is
10291 considered to be the empty list.</para>
10292
10293 <para>To add elements to a list, use the g_list_append(), g_list_prepend(),
10294 g_list_insert(), or g_list_insert_sorted() routines. In all cases
10295 they accept a pointer to the beginning of the list, and return the
10296 (possibly changed) pointer to the beginning of the list. Thus, for
10297 all of the operations that add or remove elements, be sure to save the
10298 returned value!</para>
10299
10300 <programlisting role="C">
10301 GList *g_list_append( GList    *list,
10302                       gpointer  data );
10303 </programlisting>
10304
10305 <para>This adds a new element (with value <literal>data</literal>) onto the end of the
10306 list.</para>
10307   
10308 <programlisting role="C">
10309 GList *g_list_prepend( GList    *list,
10310                        gpointer  data );
10311 </programlisting>
10312
10313 <para>This adds a new element (with value <literal>data</literal>) to the beginning of the
10314 list.</para>
10315
10316 <programlisting role="C">
10317 GList *g_list_insert( GList    *list,
10318                       gpointer  data,
10319                       gint      position );
10320 </programlisting>
10321
10322 <para>This inserts a new element (with value data) into the list at the
10323 given position. If position is 0, this is just like g_list_prepend();
10324 if position is less than 0, this is just like g_list_append().</para>
10325
10326 <programlisting role="C">
10327 GList *g_list_remove( GList    *list,
10328                       gpointer  data );
10329 </programlisting>
10330
10331 <para>This removes the element in the list with the value <literal>data</literal>;
10332 if the element isn't there, the list is unchanged.</para>
10333
10334 <programlisting role="C">
10335 void g_list_free( GList *list );
10336 </programlisting>
10337
10338 <para>This frees all of the memory used by a GList. If the list elements
10339 refer to dynamically-allocated memory, then they should be freed
10340 first.</para>
10341
10342 <para>There are many other GLib functions that support doubly linked lists;
10343 see the glib documentation for more information.  Here are a few of
10344 the more useful functions' signatures:</para>
10345
10346 <programlisting role="C">  
10347 GList *g_list_remove_link( GList *list,
10348                            GList *link );
10349
10350 GList *g_list_reverse( GList *list );
10351
10352 GList *g_list_nth( GList *list,
10353                    gint   n );
10354                            
10355 GList *g_list_find( GList    *list,
10356                     gpointer  data );
10357
10358 GList *g_list_last( GList *list );
10359
10360 GList *g_list_first( GList *list );
10361
10362 gint g_list_length( GList *list );
10363
10364 void g_list_foreach( GList    *list,
10365                      GFunc     func,
10366                      gpointer  user_data );
10367 </programlisting>
10368
10369 </sect1>
10370
10371 <!-- ----------------------------------------------------------------- -->
10372 <sect1 id="sec-SinglyLinkedLists">
10373 <title>Singly Linked Lists</title>
10374
10375 <para>Many of the above functions for singly linked lists are identical to the
10376 above. Here is a list of some of their operations:</para>
10377
10378 <programlisting role="C">
10379 GSList *g_slist_append( GSList   *list,
10380                         gpointer  data );
10381                 
10382 GSList *g_slist_prepend( GSList   *list,
10383                          gpointer  data );
10384                              
10385 GSList *g_slist_insert( GSList   *list,
10386                         gpointer  data,
10387                         gint      position );
10388                              
10389 GSList *g_slist_remove( GSList   *list,
10390                         gpointer  data );
10391                              
10392 GSList *g_slist_remove_link( GSList *list,
10393                              GSList *link );
10394                              
10395 GSList *g_slist_reverse( GSList *list );
10396
10397 GSList *g_slist_nth( GSList *list,
10398                      gint    n );
10399                              
10400 GSList *g_slist_find( GSList   *list,
10401                       gpointer  data );
10402                              
10403 GSList *g_slist_last( GSList *list );
10404
10405 gint g_slist_length( GSList *list );
10406
10407 void g_slist_foreach( GSList   *list,
10408                       GFunc     func,
10409                       gpointer  user_data );
10410         
10411 </programlisting>
10412
10413 </sect1>
10414
10415 <!-- ----------------------------------------------------------------- -->
10416 <sect1 id="sec-MemoryManagement">
10417 <title>Memory Management</title>
10418
10419 <programlisting role="C">
10420 gpointer g_malloc( gulong size );
10421 </programlisting>
10422
10423 <para>This is a replacement for malloc(). You do not need to check the return
10424 value as it is done for you in this function. If the memory allocation
10425 fails for whatever reasons, your applications will be terminated.</para>
10426
10427 <programlisting role="C">
10428 gpointer g_malloc0( gulong size );
10429 </programlisting>
10430
10431 <para>Same as above, but zeroes the memory before returning a pointer to it.</para>
10432
10433 <programlisting role="C">
10434 gpointer g_realloc( gpointer mem,
10435                     gulong   size );
10436 </programlisting>
10437
10438 <para>Relocates "size" bytes of memory starting at "mem".  Obviously, the
10439 memory should have been previously allocated.</para>
10440
10441 <programlisting role="C">
10442 void g_free( gpointer mem );
10443 </programlisting>
10444
10445 <para>Frees memory. Easy one. If <literal>mem</literal> is NULL it simply returns.</para>
10446
10447 <programlisting role="C">
10448 void g_mem_profile( void );
10449 </programlisting>
10450
10451 <para>Dumps a profile of used memory, but requires that you add <literal>#define
10452 MEM_PROFILE</literal> to the top of glib/gmem.c and re-make and make install.</para>
10453
10454 <programlisting role="C">
10455 void g_mem_check( gpointer mem );
10456 </programlisting>
10457
10458 <para>Checks that a memory location is valid. Requires you add <literal>#define
10459 MEM_CHECK</literal> to the top of gmem.c and re-make and make install.</para>
10460
10461 </sect1>
10462
10463 <!-- ----------------------------------------------------------------- -->
10464 <sect1 id="sec-Timers">
10465 <title>Timers</title>
10466
10467 <para>Timer functions can be used to time operations (e.g., to see how much
10468 time has elapsed). First, you create a new timer with g_timer_new().
10469 You can then use g_timer_start() to start timing an operation,
10470 g_timer_stop() to stop timing an operation, and g_timer_elapsed() to
10471 determine the elapsed time.</para>
10472
10473 <programlisting role="C">
10474 GTimer *g_timer_new( void );
10475
10476 void g_timer_destroy( GTimer *timer );
10477
10478 void g_timer_start( GTimer  *timer );
10479
10480 void g_timer_stop( GTimer  *timer );
10481
10482 void g_timer_reset( GTimer  *timer );
10483
10484 gdouble g_timer_elapsed( GTimer *timer,
10485                          gulong *microseconds );
10486 </programlisting>
10487
10488 </sect1>
10489
10490 <!-- ----------------------------------------------------------------- -->
10491 <sect1 id="sec-StringHandling">
10492 <title>String Handling</title>
10493
10494 <para>GLib defines a new type called a GString, which is similar to a
10495 standard C string but one that grows automatically. Its string data
10496 is null-terminated. What this gives you is protection from buffer
10497 overflow programming errors within your program. This is a very
10498 important feature, and hence I recommend that you make use of
10499 GStrings. GString itself has a simple public definition:</para>
10500
10501 <programlisting role="C">
10502 struct GString 
10503 {
10504   gchar *str; /* Points to the string's current \0-terminated value. */
10505   gint len; /* Current length */
10506 };
10507 </programlisting>
10508
10509 <para>As you might expect, there are a number of operations you can do with
10510 a GString.</para>
10511
10512 <programlisting role="C">
10513 GString *g_string_new( gchar *init );
10514 </programlisting>
10515
10516 <para>This constructs a GString, copying the string value of <literal>init</literal>
10517 into the GString and returning a pointer to it. NULL may be given as
10518 the argument for an initially empty GString.</para>
10519
10520 <programlisting role="C">
10521 void g_string_free( GString *string,
10522                     gint     free_segment );
10523 </programlisting>
10524
10525 <para>This frees the memory for the given GString. If <literal>free_segment</literal> is
10526 TRUE, then this also frees its character data.</para>
10527
10528 <programlisting role="C">            
10529 GString *g_string_assign( GString     *lval,
10530                           const gchar *rval );
10531 </programlisting>
10532
10533 <para>This copies the characters from rval into lval, destroying the
10534 previous contents of lval. Note that lval will be lengthened as
10535 necessary to hold the string's contents, unlike the standard strcpy()
10536 function.</para>
10537
10538 <para>The rest of these functions should be relatively obvious (the _c
10539 versions accept a character instead of a string):</para>
10540              
10541 <programlisting role="C">            
10542 GString *g_string_truncate( GString *string,
10543                             gint     len );
10544                              
10545 GString *g_string_append( GString *string,
10546                           gchar   *val );
10547                             
10548 GString *g_string_append_c( GString *string,
10549                             gchar    c );
10550         
10551 GString *g_string_prepend( GString *string,
10552                            gchar   *val );
10553                              
10554 GString *g_string_prepend_c( GString *string,
10555                              gchar    c );
10556         
10557 void g_string_sprintf( GString *string,
10558                        gchar   *fmt,
10559                        ...);
10560         
10561 void g_string_sprintfa ( GString *string,
10562                          gchar   *fmt,
10563                          ... );
10564 </programlisting>
10565
10566 </sect1>
10567
10568 <!-- ----------------------------------------------------------------- -->
10569 <sect1 id="sec-UtilityAndErrorFunctions">
10570 <title>Utility and Error Functions</title>
10571
10572 <programlisting role="C">
10573 gchar *g_strdup( const gchar *str );
10574 </programlisting>
10575
10576 <para>Replacement strdup function.  Copies the original strings contents to
10577 newly allocated memory, and returns a pointer to it.</para>
10578
10579 <programlisting role="C">
10580 gchar *g_strerror( gint errnum );
10581 </programlisting>
10582
10583 <para>I recommend using this for all error messages.  It's much nicer, and more
10584 portable than perror() or others.  The output is usually of the form:</para>
10585
10586 <programlisting role="C">
10587 program name:function that failed:file or further description:strerror
10588 </programlisting>
10589
10590 <para>Here's an example of one such call used in our hello_world program:</para>
10591
10592 <programlisting role="C">
10593 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
10594 </programlisting>
10595
10596 <programlisting role="C">
10597 void g_error( gchar *format, ... );
10598 </programlisting>
10599
10600 <para>Prints an error message. The format is just like printf, but it
10601 prepends "** ERROR **: " to your message, and exits the program.  
10602 Use only for fatal errors.</para>
10603
10604 <programlisting role="C">
10605 void g_warning( gchar *format, ... );
10606 </programlisting>
10607
10608 <para>Same as above, but prepends "** WARNING **: ", and does not exit the
10609 program.</para>
10610
10611 <programlisting role="C">
10612 void g_message( gchar *format, ... );
10613 </programlisting>
10614
10615 <para>Prints "message: " prepended to the string you pass in.</para>
10616
10617 <programlisting role="C">
10618 void g_print( gchar *format, ... );
10619 </programlisting>
10620
10621 <para>Replacement for printf().</para>
10622
10623 <para>And our last function:</para>
10624
10625 <programlisting role="C">
10626 gchar *g_strsignal( gint signum );
10627 </programlisting>
10628
10629 <para>Prints out the name of the Unix system signal given the signal number.
10630 Useful in generic signal handling functions.</para>
10631
10632 <para>All of the above are more or less just stolen from glib.h.  If anyone cares
10633 to document any function, just send me an email!</para>
10634
10635 </sect1>
10636 </chapter>
10637
10638 <!-- ***************************************************************** -->
10639 <chapter id="ch-GTKRCFiles">
10640 <title>GTK's rc Files</title>
10641
10642 <para>GTK has its own way of dealing with application defaults, by using rc
10643 files. These can be used to set the colors of just about any widget, and
10644 can also be used to tile pixmaps onto the background of some widgets.  </para>
10645
10646 <!-- ----------------------------------------------------------------- -->
10647 <sect1 id="sec-FunctionsForRCFiles">
10648 <title>Functions For rc Files</title>
10649
10650 <para>When your application starts, you should include a call to:</para>
10651
10652 <programlisting role="C">
10653 void gtk_rc_parse( char *filename );
10654 </programlisting>
10655
10656 <para>Passing in the filename of your rc file. This will cause GTK to parse
10657 this file, and use the style settings for the widget types defined
10658 there.</para>
10659
10660 <para>If you wish to have a special set of widgets that can take on a
10661 different style from others, or any other logical division of widgets,
10662 use a call to:</para>
10663
10664 <programlisting role="C">
10665 void gtk_widget_set_name( GtkWidget *widget,
10666                           gchar     *name );
10667 </programlisting>
10668
10669 <para>Passing your newly created widget as the first argument, and the name
10670 you wish to give it as the second. This will allow you to change the
10671 attributes of this widget by name through the rc file.</para>
10672
10673 <para>If we use a call something like this:</para>
10674
10675 <programlisting role="C">
10676 button = gtk_button_new_with_label ("Special Button");
10677 gtk_widget_set_name (button, "special button");
10678 </programlisting>
10679
10680 <para>Then this button is given the name "special button" and may be addressed by
10681 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]</para>
10682
10683 <para>The example rc file below, sets the properties of the main window, and lets
10684 all children of that main window inherit the style described by the "main
10685 button" style.  The code used in the application is:</para>
10686
10687 <programlisting role="C">
10688 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10689 gtk_widget_set_name (window, "main window");
10690 </programlisting>
10691
10692 <para>And then the style is defined in the rc file using:</para>
10693
10694 <programlisting role="C">
10695 widget "main window.*GtkButton*" style "main_button"
10696 </programlisting>
10697
10698 <para>Which sets all the Button widgets in the "main window" to the
10699 "main_buttons" style as defined in the rc file.</para>
10700
10701 <para>As you can see, this is a fairly powerful and flexible system.  Use your
10702 imagination as to how best to take advantage of this.</para>
10703
10704 </sect1>
10705
10706 <!-- ----------------------------------------------------------------- -->
10707 <sect1 id="sec-GTKsRCFileFormat">
10708 <title>GTK's rc File Format</title>
10709
10710 <para>The format of the GTK file is illustrated in the example below. This is
10711 the testgtkrc file from the GTK distribution, but I've added a
10712 few comments and things. You may wish to include this explanation in
10713 your application to allow the user to fine tune his application.</para>
10714
10715 <para>There are several directives to change the attributes of a widget.</para>
10716
10717 <itemizedlist>
10718 <listitem><simpara>fg - Sets the foreground color of a widget.</simpara>
10719 </listitem>
10720 <listitem><simpara>bg - Sets the background color of a widget.</simpara>
10721 </listitem>
10722 <listitem><simpara>bg_pixmap - Sets the background of a widget to a tiled pixmap.</simpara>
10723 </listitem>
10724 <listitem><simpara>font - Sets the font to be used with the given widget.</simpara>
10725 </listitem>
10726 </itemizedlist>
10727
10728 <para>In addition to this, there are several states a widget can be in, and you
10729 can set different colors, pixmaps and fonts for each state. These states are:</para>
10730
10731 <itemizedlist>
10732 <listitem><simpara>NORMAL - The normal state of a widget, without the mouse over top of
10733 it, and not being pressed, etc.</simpara>
10734 </listitem>
10735 <listitem><simpara>PRELIGHT - When the mouse is over top of the widget, colors defined
10736 using this state will be in effect.</simpara>
10737 </listitem>
10738 <listitem><simpara>ACTIVE - When the widget is pressed or clicked it will be active, and
10739 the attributes assigned by this tag will be in effect.</simpara>
10740 </listitem>
10741 <listitem><simpara>INSENSITIVE - When a widget is set insensitive, and cannot be
10742 activated, it will take these attributes.</simpara>
10743 </listitem>
10744 <listitem><simpara>SELECTED - When an object is selected, it takes these attributes.</simpara>
10745 </listitem>
10746 </itemizedlist>
10747
10748 <para>When using the "fg" and "bg" keywords to set the colors of widgets, the
10749 format is:</para>
10750
10751 <programlisting role="C">
10752 fg[&lt;STATE>] = { Red, Green, Blue }
10753 </programlisting>
10754
10755 <para>Where STATE is one of the above states (PRELIGHT, ACTIVE, etc), and the Red,
10756 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
10757 white. They must be in float form, or they will register as 0, so a straight 
10758 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
10759 doesn't matter if it's not recognized.  Unrecognized values are set to 0.</para>
10760
10761 <para>bg_pixmap is very similar to the above, except the colors are replaced by a
10762 filename.</para>
10763
10764 <para>pixmap_path is a list of paths separated by ":"'s.  These paths will be
10765 searched for any pixmap you specify.</para>
10766
10767 <para>The font directive is simply:</para>
10768
10769 <programlisting role="C">
10770 font = "&lt;font name>"
10771 </programlisting>
10772
10773 <para>The only hard part is figuring out the font string. Using xfontsel or
10774 a similar utility should help.</para>
10775
10776 <para>The "widget_class" sets the style of a class of widgets. These classes are
10777 listed in the widget overview on the class hierarchy.</para>
10778
10779 <para>The "widget" directive sets a specifically named set of widgets to a
10780 given style, overriding any style set for the given widget class.
10781 These widgets are registered inside the application using the
10782 gtk_widget_set_name() call. This allows you to specify the attributes of a
10783 widget on a per widget basis, rather than setting the attributes of an
10784 entire widget class. I urge you to document any of these special widgets so
10785 users may customize them.</para>
10786
10787 <para>When the keyword <literal>parent</> is used as an attribute, the widget will take on
10788 the attributes of its parent in the application.</para>
10789
10790 <para>When defining a style, you may assign the attributes of a previously defined
10791 style to this new one.</para>
10792
10793 <programlisting role="C">
10794 style "main_button" = "button"
10795 {
10796   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
10797   bg[PRELIGHT] = { 0.75, 0, 0 }
10798 }
10799 </programlisting>
10800
10801 <para>This example takes the "button" style, and creates a new "main_button" style
10802 simply by changing the font and prelight background color of the "button"
10803 style.</para>
10804
10805 <para>Of course, many of these attributes don't apply to all widgets. It's a
10806 simple matter of common sense really. Anything that could apply, should.</para>
10807
10808 </sect1>
10809
10810 <!-- ----------------------------------------------------------------- -->
10811 <sect1 id="sec-ExampleRCFile">
10812 <title>Example rc file</title>
10813
10814 <programlisting role="C">
10815 # pixmap_path "&lt;dir 1>:&lt;dir 2>:&lt;dir 3>:..."
10816 #
10817 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
10818 #
10819 # style &lt;name> [= &lt;name>]
10820 # {
10821 #   &lt;option>
10822 # }
10823 #
10824 # widget &lt;widget_set> style &lt;style_name>
10825 # widget_class &lt;widget_class_set> style &lt;style_name>
10826
10827 # Here is a list of all the possible states.  Note that some do not apply to
10828 # certain widgets.
10829 #
10830 # NORMAL - The normal state of a widget, without the mouse over top of
10831 # it, and not being pressed, etc.
10832 #
10833 # PRELIGHT - When the mouse is over top of the widget, colors defined
10834 # using this state will be in effect.
10835 #
10836 # ACTIVE - When the widget is pressed or clicked it will be active, and
10837 # the attributes assigned by this tag will be in effect.
10838 #
10839 # INSENSITIVE - When a widget is set insensitive, and cannot be
10840 # activated, it will take these attributes.
10841 #
10842 # SELECTED - When an object is selected, it takes these attributes.
10843 #
10844 # Given these states, we can set the attributes of the widgets in each of
10845 # these states using the following directives.
10846 #
10847 # fg - Sets the foreground color of a widget.
10848 # fg - Sets the background color of a widget.
10849 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
10850 # font - Sets the font to be used with the given widget.
10851 #
10852
10853 # This sets a style called "button".  The name is not really important, as
10854 # it is assigned to the actual widgets at the bottom of the file.
10855
10856 style "window"
10857 {
10858   #This sets the padding around the window to the pixmap specified.
10859   #bg_pixmap[&lt;STATE>] = "&lt;pixmap filename>"
10860   bg_pixmap[NORMAL] = "warning.xpm"
10861 }
10862
10863 style "scale"
10864 {
10865   #Sets the foreground color (font color) to red when in the "NORMAL"
10866   #state.
10867   
10868   fg[NORMAL] = { 1.0, 0, 0 }
10869   
10870   #Sets the background pixmap of this widget to that of its parent.
10871   bg_pixmap[NORMAL] = "&lt;parent>"
10872 }
10873
10874 style "button"
10875 {
10876   # This shows all the possible states for a button.  The only one that
10877   # doesn't apply is the SELECTED state.
10878   
10879   fg[PRELIGHT] = { 0, 1.0, 1.0 }
10880   bg[PRELIGHT] = { 0, 0, 1.0 }
10881   bg[ACTIVE] = { 1.0, 0, 0 }
10882   fg[ACTIVE] = { 0, 1.0, 0 }
10883   bg[NORMAL] = { 1.0, 1.0, 0 }
10884   fg[NORMAL] = { .99, 0, .99 }
10885   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
10886   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
10887 }
10888
10889 # In this example, we inherit the attributes of the "button" style and then
10890 # override the font and background color when prelit to create a new
10891 # "main_button" style.
10892
10893 style "main_button" = "button"
10894 {
10895   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
10896   bg[PRELIGHT] = { 0.75, 0, 0 }
10897 }
10898
10899 style "toggle_button" = "button"
10900 {
10901   fg[NORMAL] = { 1.0, 0, 0 }
10902   fg[ACTIVE] = { 1.0, 0, 0 }
10903   
10904   # This sets the background pixmap of the toggle_button to that of its
10905   # parent widget (as defined in the application).
10906   bg_pixmap[NORMAL] = "&lt;parent>"
10907 }
10908
10909 style "text"
10910 {
10911   bg_pixmap[NORMAL] = "marble.xpm"
10912   fg[NORMAL] = { 1.0, 1.0, 1.0 }
10913 }
10914
10915 style "ruler"
10916 {
10917   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
10918 }
10919
10920 # pixmap_path "~/.pixmaps"
10921
10922 # These set the widget types to use the styles defined above.
10923 # The widget types are listed in the class hierarchy, but could probably be
10924 # just listed in this document for the users reference.
10925
10926 widget_class "GtkWindow" style "window"
10927 widget_class "GtkDialog" style "window"
10928 widget_class "GtkFileSelection" style "window"
10929 widget_class "*Gtk*Scale" style "scale"
10930 widget_class "*GtkCheckButton*" style "toggle_button"
10931 widget_class "*GtkRadioButton*" style "toggle_button"
10932 widget_class "*GtkButton*" style "button"
10933 widget_class "*Ruler" style "ruler"
10934 widget_class "*GtkText" style "text"
10935
10936 # This sets all the buttons that are children of the "main window" to
10937 # the main_button style.  These must be documented to be taken advantage of.
10938 widget "main window.*GtkButton*" style "main_button"
10939 </programlisting>
10940
10941 </sect1>
10942 </chapter>
10943
10944 <!-- ***************************************************************** -->
10945 <chapter id="ch-WritingYourOwnWidgets">
10946 <title>Writing Your Own Widgets</title>
10947
10948 <!-- ----------------------------------------------------------------- -->
10949 <sect1 id="sec-WidgetsOverview">
10950 <title>Overview</title>
10951
10952 <para>Although the GTK distribution comes with many types of widgets that
10953 should cover most basic needs, there may come a time when you need to
10954 create your own new widget type. Since GTK uses widget inheritance
10955 extensively, and there is already a widget that is close to what you want,
10956 it is often possible to make a useful new widget type in
10957 just a few lines of code. But before starting work on a new widget, check
10958 around first to make sure that someone has not already written
10959 it. This will prevent duplication of effort and keep the number of
10960 GTK widgets out there to a minimum, which will help keep both the code
10961 and the interface of different applications consistent. As a flip side
10962 to this, once you finish your widget, announce it to the world so
10963 other people can benefit. The best place to do this is probably the
10964 <literal>gtk-list</literal>.</para>
10965
10966 <para>Complete sources for the example widgets are available at the place you 
10967 got this tutorial, or from:</para>
10968
10969 <para><ulink url="http://www.gtk.org/~otaylor/gtk/tutorial/">http://www.gtk.org/~otaylor/gtk/tutorial/</ulink></para>
10970
10971
10972 </sect1>
10973
10974 <!-- ----------------------------------------------------------------- -->
10975 <sect1 id="sec-TheAnatomyOfAWidget">
10976 <title>The Anatomy Of A Widget</title>
10977
10978 <para>In order to create a new widget, it is important to have an
10979 understanding of how GTK objects work. This section is just meant as a
10980 brief overview. See the reference documentation for the details. </para>
10981
10982 <para>GTK widgets are implemented in an object oriented fashion. However,
10983 they are implemented in standard C. This greatly improves portability
10984 and stability over using current generation C++ compilers; however,
10985 it does mean that the widget writer has to pay attention to some of
10986 the implementation details. The information common to all instances of
10987 one class of widgets (e.g., to all Button widgets) is stored in the 
10988 <emphasis>class structure</emphasis>. There is only one copy of this in
10989 which is stored information about the class's signals
10990 (which act like virtual functions in C). To support inheritance, the
10991 first field in the class structure must be a copy of the parent's
10992 class structure. The declaration of the class structure of GtkButtton
10993 looks like:</para>
10994
10995 <programlisting role="C">
10996 struct _GtkButtonClass
10997 {
10998   GtkContainerClass parent_class;
10999
11000   void (* pressed)  (GtkButton *button);
11001   void (* released) (GtkButton *button);
11002   void (* clicked)  (GtkButton *button);
11003   void (* enter)    (GtkButton *button);
11004   void (* leave)    (GtkButton *button);
11005 };
11006 </programlisting>
11007
11008 <para>When a button is treated as a container (for instance, when it is
11009 resized), its class structure can be cast to GtkContainerClass, and
11010 the relevant fields used to handle the signals.</para>
11011
11012 <para>There is also a structure for each widget that is created on a
11013 per-instance basis. This structure has fields to store information that
11014 is different for each instance of the widget. We'll call this
11015 structure the <emphasis>object structure</emphasis>. For the Button class, it looks
11016 like:</para>
11017
11018 <programlisting role="C">
11019 struct _GtkButton
11020 {
11021   GtkContainer container;
11022
11023   GtkWidget *child;
11024
11025   guint in_button : 1;
11026   guint button_down : 1;
11027 };
11028 </programlisting>
11029
11030 <para>Note that, similar to the class structure, the first field is the
11031 object structure of the parent class, so that this structure can be
11032 cast to the parent class' object structure as needed.</para>
11033
11034 </sect1>
11035
11036 <!-- ----------------------------------------------------------------- -->
11037 <sect1 id="sec-CreatingACompositeWidget">
11038 <title>Creating a Composite widget</title>
11039
11040 <!-- ----------------------------------------------------------------- -->
11041 <sect2>
11042 <title>Introduction</title>
11043
11044 <para>One type of widget that you may be interested in creating is a
11045 widget that is merely an aggregate of other GTK widgets. This type of
11046 widget does nothing that couldn't be done without creating new
11047 widgets, but provides a convenient way of packaging user interface
11048 elements for reuse. The FileSelection and ColorSelection widgets in
11049 the standard distribution are examples of this type of widget.</para>
11050
11051 <para>The example widget that we'll create in this section is the Tictactoe
11052 widget, a 3x3 array of toggle buttons which triggers a signal when all
11053 three buttons in a row, column, or on one of the diagonals are
11054 depressed. </para>
11055
11056 <para><emphasis>Note: the full source code for the Tictactoe example described
11057 below is in the <link linkend="sec-Tictactoe">Code Examples Appendix</link>
11058 </emphasis></para>
11059
11060 <para>
11061 <inlinemediaobject>
11062 <imageobject>
11063 <imagedata fileref="images/tictactoe.png" format="png">
11064 </imageobject>
11065 </inlinemediaobject>
11066 </para>
11067
11068 </sect2>
11069
11070 <!-- ----------------------------------------------------------------- -->
11071 <sect2>
11072 <title>Choosing a parent class</title>
11073
11074 <para>The parent class for a composite widget is typically the container
11075 class that holds all of the elements of the composite widget. For
11076 example, the parent class of the FileSelection widget is the
11077 Dialog class. Since our buttons will be arranged in a table, it
11078 is natural to make our parent class the Table class.</para>
11079
11080 </sect2>
11081
11082 <!-- ----------------------------------------------------------------- -->
11083 <sect2>
11084 <title>The header file</title>
11085
11086 <para>Each GObject class has a header file which declares the object and
11087 class structures for that object, along with public functions. 
11088 A couple of features are worth pointing out. To prevent duplicate
11089 definitions, we wrap the entire header file in:</para>
11090
11091 <programlisting role="C">
11092 #ifndef __TICTACTOE_H__
11093 #define __TICTACTOE_H__
11094 .
11095 .
11096 .
11097 #endif /* __TICTACTOE_H__ */
11098 </programlisting>
11099
11100 <para>And to keep C++ programs that include the header file happy, in:</para>
11101
11102 <programlisting role="C">
11103 #include &lt;glib.h&gt;
11104
11105 G_BEGIN_DECLS
11106 .
11107 .
11108 .
11109 G_END_DECLS
11110 </programlisting>
11111
11112 <para>Along with the functions and structures, we declare five standard
11113 macros in our header file, <literal>TICTACTOE_TYPE</literal>,
11114 <literal>TICTACTOE(obj)</literal>,
11115 <literal>TICTACTOE_CLASS(klass)</literal>,
11116 <literal>IS_TICTACTOE(obj)</literal>, and
11117 <literal>IS_TICTACTOE_CLASS(klass)</literal>, which cast a
11118 pointer into a pointer to the object or class structure, and check
11119 if an object is a Tictactoe widget respectively.</para>
11120
11121 </sect2>
11122
11123 <!-- ----------------------------------------------------------------- -->
11124 <sect2>
11125 <title>The <literal>_get_type()</literal> function</title>
11126
11127 <para>We now continue on to the implementation of our widget. A core
11128 function for every object is the function
11129 <literal>WIDGETNAME_get_type()</literal>. This function, when first called, tells
11130 Glib about the new class, and gets an ID that uniquely identifies
11131 the class. Upon subsequent calls, it just returns the ID.</para>
11132
11133 <programlisting role="C">
11134 GType
11135 tictactoe_get_type (void)
11136 {
11137   static GType ttt_type = 0;
11138
11139   if (!ttt_type)
11140     {
11141       const GTypeInfo ttt_info =
11142       {
11143         sizeof (TictactoeClass),
11144         NULL, /* base_init */
11145         NULL, /* base_finalize */
11146         (GClassInitFunc) tictactoe_class_init,
11147         NULL, /* class_finalize */
11148         NULL, /* class_data */
11149         sizeof (Tictactoe),
11150         0,    /* n_preallocs */
11151         (GInstanceInitFunc) tictactoe_init,
11152       };
11153
11154       ttt_type = g_type_register_static (GTK_TYPE_TABLE,
11155                                          "Tictactoe",
11156                                          &amp;ttt_info,
11157                                          0);
11158     }
11159
11160   return ttt_type;
11161 }
11162 </programlisting>
11163
11164 <para>The GTypeInfo structure has the following definition:</para>
11165
11166 <programlisting role="C">
11167 struct _GTypeInfo
11168 {
11169   /* interface types, classed types, instantiated types */
11170   guint16                class_size;
11171    
11172   GBaseInitFunc          base_init;
11173   GBaseFinalizeFunc      base_finalize;
11174    
11175   /* classed types, instantiated types */
11176   GClassInitFunc         class_init;
11177   GClassFinalizeFunc     class_finalize;
11178   gconstpointer          class_data;
11179    
11180   /* instantiated types */
11181   guint16                instance_size;
11182   guint16                n_preallocs;
11183   GInstanceInitFunc      instance_init;
11184    
11185   /* value handling */
11186   const GTypeValueTable *value_table;
11187 };
11188 </programlisting>
11189
11190 <para>The important fields of this structure are pretty self-explanatory.
11191 We'll ignore the <literal>base_init</literal> and
11192  <literal>base_finalize</literal> as well as the <literal>value_table</literal>
11193 fields here. Once Glib has a correctly filled in copy of
11194 this structure, it knows how to create objects of a particular type. </para>
11195
11196 </sect2>
11197
11198 <!-- ----------------------------------------------------------------- -->
11199 <sect2>
11200 <title>The <literal>_class_init()</literal> function</title>
11201
11202 <para>The <literal>WIDGETNAME_class_init()</literal> function initializes the fields of
11203 the widget's class structure, and sets up any signals for the
11204 class. For our Tictactoe widget it looks like:</para>
11205
11206 <programlisting role="C">
11207 enum {
11208   TICTACTOE_SIGNAL,
11209   LAST_SIGNAL
11210 };
11211
11212
11213 static guint tictactoe_signals[LAST_SIGNAL] = { 0 };
11214
11215 static void
11216 tictactoe_class_init (TictactoeClass *klass)
11217 {
11218   tictactoe_signals[TICTACTOE_SIGNAL] =
11219     g_signal_new ("tictactoe",
11220                   G_TYPE_FROM_CLASS (klass),
11221                   G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
11222                   G_STRUCT_OFFSET (TictactoeClass, tictactoe),
11223                   NULL, NULL,
11224                   g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
11225 }
11226 </programlisting>
11227
11228 <para>Our widget has just one signal, the <literal>tictactoe</literal> signal that is
11229 invoked when a row, column, or diagonal is completely filled in. Not
11230 every composite widget needs signals, so if you are reading this for
11231 the first time, you may want to skip to the next section now, as
11232 things are going to get a bit complicated.</para>
11233
11234 <para>The function:</para>
11235
11236 <programlisting role="C">
11237 guint g_signal_new( const gchar         *signal_name,
11238                     GType                itype,
11239                     GSignalFlags         signal_flags,
11240                     guint                class_offset,
11241                     GSignalAccumulator  *accumulator,
11242                     gpointer             accu_data,
11243                     GSignalCMarshaller  *c_marshaller,
11244                     GType                return_type,
11245                     guint                n_params,
11246                     ...);
11247 </programlisting>
11248
11249 <para>Creates a new signal. The parameters are:</para>
11250
11251 <itemizedlist>
11252 <listitem><simpara> <literal>signal_name</literal>: The name of the signal.</simpara>
11253 </listitem>
11254
11255 <listitem><simpara> <literal>itype</literal>: The ID of the object that this signal applies
11256 to. (It will also apply to that objects descendants.)</simpara>
11257 </listitem>
11258                                                                                 
11259 <listitem><simpara> <literal>signal_flags</literal>: Whether the default handler runs before or after
11260 user handlers and other flags. Usually this will be one of
11261 <literal>G_SIGNAL_RUN_FIRST</literal> or <literal>G_SIGNAL_RUN_LAST</literal>,
11262 although there are other possibilities. The flag
11263 <literal>G_SIGNAL_ACTION</literal> specifies that no extra code needs to
11264 run that performs special pre or post emission adjustments. This means that
11265 the signal can also be emitted from object external code.</simpara>
11266 </listitem>
11267
11268 <listitem><simpara> <literal>class_offset</literal>: The offset within the class structure of
11269 a pointer to the default handler.</simpara>
11270 </listitem>
11271
11272 <listitem><simpara> <literal>accumulator</literal>: For most classes this can
11273 be set to NULL.</simpara></listitem>
11274
11275 <listitem><simpara> <literal>accu_data</literal>: User data that will be handed
11276 to the accumulator function.</simpara></listitem>
11277
11278 <listitem><simpara> <literal>c_marshaller</literal>: A function that is used to invoke the signal
11279 handler. For signal handlers that have no arguments other than the
11280 object that emitted the signal and user data, we can use the
11281 pre-supplied marshaller function <literal>g_cclosure_marshal_VOID__VOID</literal>.</simpara>
11282 </listitem>
11283
11284 <listitem><simpara> <literal>return_type</literal>: The type of the return value.</simpara>
11285 </listitem>
11286
11287 <listitem><simpara> <literal>n_params</literal>: The number of parameters of the signal handler
11288 (other than the two default ones mentioned above)</simpara>
11289 </listitem>
11290
11291 <listitem><simpara> <literal>...</literal>: The types of the parameters.</simpara>
11292 </listitem>
11293 </itemizedlist>
11294
11295 <para>When specifying types, the following standard types can be used:</para>
11296
11297 <programlisting role="C">
11298 G_TYPE_INVALID
11299 G_TYPE_NONE
11300 G_TYPE_INTERFACE
11301 G_TYPE_CHAR
11302 G_TYPE_UCHAR
11303 G_TYPE_BOOLEAN
11304 G_TYPE_INT
11305 G_TYPE_UINT
11306 G_TYPE_LONG
11307 G_TYPE_ULONG
11308 G_TYPE_INT64
11309 G_TYPE_UINT64
11310 G_TYPE_ENUM
11311 G_TYPE_FLAGS
11312 G_TYPE_FLOAT
11313 G_TYPE_DOUBLE
11314 G_TYPE_STRING
11315 G_TYPE_POINTER
11316 G_TYPE_BOXED
11317 G_TYPE_PARAM
11318 G_TYPE_OBJECT
11319 </programlisting>
11320
11321 <para><literal>g_signal_new()</literal> returns a unique integer identifier for the
11322 signal, that we store in the <literal>tictactoe_signals</literal> array, which we
11323 index using an enumeration. (Conventionally, the enumeration elements
11324 are the signal name, uppercased, but here there would be a conflict
11325 with the <literal>TICTACTOE()</literal> macro, so we called it <literal>TICTACTOE_SIGNAL</literal>
11326 instead.</para>
11327
11328 </sect2>
11329
11330 <!-- ----------------------------------------------------------------- -->
11331 <sect2>
11332 <title>The <literal>_init()</literal> function</title>
11333
11334 <para>Each class also needs a function to initialize the object
11335 structure. Usually, this function has the fairly limited role of
11336 setting the fields of the structure to default values. For composite
11337 widgets, however, this function also creates the component widgets.</para>
11338
11339 <programlisting role="C">
11340 static void
11341 tictactoe_init (Tictactoe *ttt)
11342 {
11343   gint i,j;
11344
11345   gtk_table_resize (GTK_TABLE (ttt), 3, 3);
11346   gtk_table_set_homogeneous (GTK_TABLE (ttt), TRUE);
11347
11348   for (i=0;i&lt;3; i++)
11349     for (j=0;j&lt;3; j++)
11350       {
11351         ttt->buttons[i][j] = gtk_toggle_button_new ();
11352         gtk_table_attach_defaults (GTK_TABLE (ttt), ttt->buttons[i][j], 
11353                                    i, i+1, j, j+1);
11354         g_signal_connect (ttt->buttons[i][j], "toggled",
11355                           G_CALLBACK (tictactoe_toggle), ttt);
11356         gtk_widget_set_size_request (ttt->buttons[i][j], 20, 20);
11357         gtk_widget_show (ttt->buttons[i][j]);
11358       }
11359 }
11360 </programlisting>
11361
11362 </sect2>
11363
11364 <!-- ----------------------------------------------------------------- -->
11365 <sect2>
11366 <title>And the rest...</title>
11367
11368 <para>There is one more function that every object (except for abstract
11369 classes like Bin that cannot be instantiated) needs to have - the
11370 function that the user calls to create an object of that type. This is
11371 conventionally called <literal>OBJECTNAME_new()</literal>. In some
11372 widgets, though not for the Tictactoe widgets, this function takes
11373 arguments, and does some setup based on the arguments. The other two
11374 functions are specific to the Tictactoe widget. </para>
11375
11376 <para><literal>tictactoe_clear()</literal> is a public function that resets all the
11377 buttons in the widget to the up position. Note the use of
11378 <literal>g_signal_handlers_block_matched()</literal> to keep our signal handler for
11379 button toggles from being triggered unnecessarily.</para>
11380
11381 <para><literal>tictactoe_toggle()</literal> is the signal handler that is invoked when the
11382 user clicks on a button. It checks to see if there are any winning
11383 combinations that involve the toggled button, and if so, emits
11384 the "tictactoe" signal.</para>
11385
11386 <programlisting role="C">
11387 GtkWidget*
11388 tictactoe_new (void)
11389 {
11390   return GTK_WIDGET ( g_object_new (TICTACTOE_TYPE, NULL));
11391 }
11392
11393 void           
11394 tictactoe_clear (Tictactoe *ttt)
11395 {
11396   int i,j;
11397
11398   for (i=0;i&lt;3;i++)
11399     for (j=0;j&lt;3;j++)
11400       {
11401         g_signal_handlers_block_matched (G_OBJECT (ttt->buttons[i][j]),
11402                                          G_SIGNAL_MATCH_DATA,
11403                                          0, 0, NULL, NULL, ttt);
11404         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
11405                                      FALSE);
11406         g_signal_handlers_unblock_matched (G_OBJECT (ttt->buttons[i][j]),
11407                                            G_SIGNAL_MATCH_DATA,
11408                                            0, 0, NULL, NULL, ttt);
11409       }
11410 }
11411
11412 static void
11413 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
11414 {
11415   int i,k;
11416
11417   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
11418                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
11419                              { 0, 1, 2 }, { 0, 1, 2 } };
11420   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
11421                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
11422                              { 0, 1, 2 }, { 2, 1, 0 } };
11423
11424   int success, found;
11425
11426   for (k=0; k&lt;8; k++)
11427     {
11428       success = TRUE;
11429       found = FALSE;
11430
11431       for (i=0;i&lt;3;i++)
11432         {
11433           success = success &amp;&amp; 
11434             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
11435           found = found ||
11436             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
11437         }
11438       
11439       if (success &amp;&amp; found)
11440         {
11441           g_signal_emit (ttt, 
11442                          tictactoe_signals[TICTACTOE_SIGNAL], 0);
11443           break;
11444         }
11445     }
11446 }
11447 </programlisting>
11448
11449 <para>And finally, an example program using our Tictactoe widget:</para>
11450
11451 <programlisting role="C">
11452 #include &lt;gtk/gtk.h&gt;
11453 #include "tictactoe.h"
11454
11455 /* Invoked when a row, column or diagonal is completed */
11456 void
11457 win (GtkWidget *widget, gpointer data)
11458 {
11459   g_print ("Yay!\n");
11460   tictactoe_clear (TICTACTOE (widget));
11461 }
11462
11463 int 
11464 main (int argc, char *argv[])
11465 {
11466   GtkWidget *window;
11467   GtkWidget *ttt;
11468   
11469   gtk_init (&amp;argc, &amp;argv);
11470
11471   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11472   
11473   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
11474   
11475   g_signal_connect (window, "destroy",
11476                     G_CALLBACK (exit), NULL);
11477   
11478   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11479
11480   /* Create a new Tictactoe widget */
11481   ttt = tictactoe_new ();
11482   gtk_container_add (GTK_CONTAINER (window), ttt);
11483   gtk_widget_show (ttt);
11484
11485   /* And attach to its "tictactoe" signal */
11486   g_signal_connect (ttt, "tictactoe",
11487                     G_CALLBACK (win), NULL);
11488
11489   gtk_widget_show (window);
11490   
11491   gtk_main ();
11492   
11493   return 0;
11494 }
11495 </programlisting>
11496
11497 </sect2>
11498 </sect1>
11499
11500 <!-- ----------------------------------------------------------------- -->
11501 <sect1 id="sec-CreatingAWidgetFromScratch">
11502 <title>Creating a widget from scratch</title>
11503
11504 <!-- ----------------------------------------------------------------- -->
11505 <sect2>
11506 <title>Introduction</title>
11507
11508 <para>In this section, we'll learn more about how widgets display themselves
11509 on the screen and interact with events. As an example of this, we'll
11510 create an analog dial widget with a pointer that the user can drag to
11511 set the value.</para>
11512
11513 <para>
11514 <inlinemediaobject>
11515 <imageobject>
11516 <imagedata fileref="images/gtkdial.png" format="png">
11517 </imageobject>
11518 </inlinemediaobject>
11519 </para>
11520
11521 </sect2>
11522
11523 <!-- ----------------------------------------------------------------- -->
11524 <sect2>
11525 <title>Displaying a widget on the screen</title>
11526
11527 <para>There are several steps that are involved in displaying on the screen.
11528 After the widget is created with a call to <literal>WIDGETNAME_new()</literal>,
11529 several more functions are needed:</para>
11530
11531 <itemizedlist>
11532 <listitem><simpara> <literal>WIDGETNAME_realize()</literal> is responsible for creating an X
11533 window for the widget if it has one.</simpara>
11534 </listitem>
11535 <listitem><simpara> <literal>WIDGETNAME_map()</literal> is invoked after the user calls
11536 <literal>gtk_widget_show()</literal>. It is responsible for making sure the widget
11537 is actually drawn on the screen (<emphasis>mapped</emphasis>). For a container class,
11538 it must also make calls to <literal>map()</literal> functions of any child widgets.</simpara>
11539 </listitem>
11540 <listitem><simpara> <literal>WIDGETNAME_draw()</literal> is invoked when <literal>gtk_widget_draw()</literal>
11541 is called for the widget or one of its ancestors. It makes the actual
11542 calls to the drawing functions to draw the widget on the screen. For
11543 container widgets, this function must make calls to
11544 <literal>gtk_widget_draw()</literal> for its child widgets.</simpara>
11545 </listitem>
11546 <listitem><simpara> <literal>WIDGETNAME_expose()</literal> is a handler for expose events for the
11547 widget. It makes the necessary calls to the drawing functions to draw
11548 the exposed portion on the screen. For container widgets, this
11549 function must generate expose events for its child widgets which don't
11550 have their own windows. (If they have their own windows, then X will
11551 generate the necessary expose events.)</simpara>
11552 </listitem>
11553 </itemizedlist>
11554
11555 <para>You might notice that the last two functions are quite similar - each
11556 is responsible for drawing the widget on the screen. In fact many
11557 types of widgets don't really care about the difference between the
11558 two. The default <literal>draw()</literal> function in the widget class simply
11559 generates a synthetic expose event for the redrawn area. However, some
11560 types of widgets can save work by distinguishing between the two
11561 functions. For instance, if a widget has multiple X windows, then
11562 since expose events identify the exposed window, it can redraw only
11563 the affected window, which is not possible for calls to <literal>draw()</literal>.</para>
11564
11565 <para>Container widgets, even if they don't care about the difference for
11566 themselves, can't simply use the default <literal>draw()</literal> function because
11567 their child widgets might care about the difference. However,
11568 it would be wasteful to duplicate the drawing code between the two
11569 functions. The convention is that such widgets have a function called
11570 <literal>WIDGETNAME_paint()</literal> that does the actual work of drawing the
11571 widget, that is then called by the <literal>draw()</literal> and <literal>expose()</literal>
11572 functions.</para>
11573
11574 <para>In our example approach, since the dial widget is not a container
11575 widget, and only has a single window, we can take the simplest
11576 approach and use the default <literal>draw()</literal> function and only implement
11577 an <literal>expose()</literal> function.</para>
11578
11579 </sect2>
11580
11581 <!-- ----------------------------------------------------------------- -->
11582 <sect2>
11583 <title>The origins of the Dial Widget</title>
11584
11585 <para>Just as all land animals are just variants on the first amphibian that
11586 crawled up out of the mud, GTK widgets tend to start off as variants
11587 of some other, previously written widget. Thus, although this section
11588 is entitled "Creating a Widget from Scratch", the Dial widget really
11589 began with the source code for the Range widget. This was picked as a
11590 starting point because it would be nice if our Dial had the same
11591 interface as the Scale widgets which are just specialized descendants
11592 of the Range widget. So, though the source code is presented below in
11593 finished form, it should not be implied that it was written, <emphasis>ab
11594 initio</emphasis> in this fashion. Also, if you aren't yet familiar with
11595 how scale widgets work from the application writer's point of view, it
11596 would be a good idea to look them over before continuing.</para>
11597
11598 </sect2>
11599
11600 <!-- ----------------------------------------------------------------- -->
11601 <sect2>
11602 <title>The Basics</title>
11603
11604 <para>Quite a bit of our widget should look pretty familiar from the
11605 Tictactoe widget. First, we have a header file:</para>
11606
11607 <programlisting role="C">
11608 /* GTK - The GIMP Toolkit
11609  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
11610  *
11611  * This library is free software; you can redistribute it and/or
11612  * modify it under the terms of the GNU Library General Public
11613  * License as published by the Free Software Foundation; either
11614  * version 2 of the License, or (at your option) any later version.
11615  *
11616  * This library is distributed in the hope that it will be useful,
11617  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11618  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11619  * Library General Public License for more details.
11620  *
11621  * You should have received a copy of the GNU Library General Public
11622  * License along with this library; if not, write to the Free
11623  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
11624  */
11625
11626 #ifndef __GTK_DIAL_H__
11627 #define __GTK_DIAL_H__
11628
11629 #include &lt;gdk/gdk.h&gt;
11630 #include &lt;gtk/gtkadjustment.h&gt;
11631 #include &lt;gtk/gtkwidget.h&gt;
11632
11633
11634 #ifdef __cplusplus
11635 extern "C" {
11636 #endif /* __cplusplus */
11637
11638
11639 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
11640 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
11641 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
11642
11643
11644 typedef struct _GtkDial        GtkDial;
11645 typedef struct _GtkDialClass   GtkDialClass;
11646
11647 struct _GtkDial
11648 {
11649   GtkWidget widget;
11650
11651   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
11652   guint policy : 2;
11653
11654   /* Button currently pressed or 0 if none */
11655   guint8 button;
11656
11657   /* Dimensions of dial components */
11658   gint radius;
11659   gint pointer_width;
11660
11661   /* ID of update timer, or 0 if none */
11662   guint32 timer;
11663
11664   /* Current angle */
11665   gfloat angle;
11666
11667   /* Old values from adjustment stored so we know when something changes */
11668   gfloat old_value;
11669   gfloat old_lower;
11670   gfloat old_upper;
11671
11672   /* The adjustment object that stores the data for this dial */
11673   GtkAdjustment *adjustment;
11674 };
11675
11676 struct _GtkDialClass
11677 {
11678   GtkWidgetClass parent_class;
11679 };
11680
11681
11682 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
11683 GtkType        gtk_dial_get_type               (void);
11684 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
11685 void           gtk_dial_set_update_policy      (GtkDial      *dial,
11686                                                 GtkUpdateType  policy);
11687
11688 void           gtk_dial_set_adjustment         (GtkDial      *dial,
11689                                                 GtkAdjustment *adjustment);
11690 #ifdef __cplusplus
11691 }
11692 #endif /* __cplusplus */
11693
11694
11695 #endif /* __GTK_DIAL_H__ */
11696 </programlisting>
11697
11698 <para>Since there is quite a bit more going on in this widget than the last
11699 one, we have more fields in the data structure, but otherwise things
11700 are pretty similar.</para>
11701
11702 <para>Next, after including header files and declaring a few constants,
11703 we have some functions to provide information about the widget
11704 and initialize it:</para>
11705
11706 <programlisting role="C">
11707 #include &lt;math.h&gt;
11708 #include &lt;stdio.h&gt;
11709 #include &lt;gtk/gtkmain.h&gt;
11710 #include &lt;gtk/gtksignal.h&gt;
11711
11712 #include "gtkdial.h"
11713
11714 #define SCROLL_DELAY_LENGTH  300
11715 #define DIAL_DEFAULT_SIZE 100
11716
11717 /* Forward declarations */
11718
11719 [ omitted to save space ]
11720
11721 /* Local data */
11722
11723 static GtkWidgetClass *parent_class = NULL;
11724
11725 GtkType
11726 gtk_dial_get_type ()
11727 {
11728   static GtkType dial_type = 0;
11729
11730   if (!dial_type)
11731     {
11732       static const GtkTypeInfo dial_info =
11733       {
11734         "GtkDial",
11735         sizeof (GtkDial),
11736         sizeof (GtkDialClass),
11737         (GtkClassInitFunc) gtk_dial_class_init,
11738         (GtkObjectInitFunc) gtk_dial_init,
11739         /* reserved_1 */ NULL,
11740         /* reserved_1 */ NULL,
11741         (GtkClassInitFunc) NULL
11742       };
11743
11744       dial_type = gtk_type_unique (GTK_TYPE_WIDGET, &amp;dial_info);
11745     }
11746
11747   return dial_type;
11748 }
11749
11750 static void
11751 gtk_dial_class_init (GtkDialClass *class)
11752 {
11753   GtkObjectClass *object_class;
11754   GtkWidgetClass *widget_class;
11755
11756   object_class = (GtkObjectClass*) class;
11757   widget_class = (GtkWidgetClass*) class;
11758
11759   parent_class = gtk_type_class (gtk_widget_get_type ());
11760
11761   object_class->destroy = gtk_dial_destroy;
11762
11763   widget_class->realize = gtk_dial_realize;
11764   widget_class->expose_event = gtk_dial_expose;
11765   widget_class->size_request = gtk_dial_size_request;
11766   widget_class->size_allocate = gtk_dial_size_allocate;
11767   widget_class->button_press_event = gtk_dial_button_press;
11768   widget_class->button_release_event = gtk_dial_button_release;
11769   widget_class->motion_notify_event = gtk_dial_motion_notify;
11770 }
11771
11772 static void
11773 gtk_dial_init (GtkDial *dial)
11774 {
11775   dial->button = 0;
11776   dial->policy = GTK_UPDATE_CONTINUOUS;
11777   dial->timer = 0;
11778   dial->radius = 0;
11779   dial->pointer_width = 0;
11780   dial->angle = 0.0;
11781   dial->old_value = 0.0;
11782   dial->old_lower = 0.0;
11783   dial->old_upper = 0.0;
11784   dial->adjustment = NULL;
11785 }
11786
11787 GtkWidget*
11788 gtk_dial_new (GtkAdjustment *adjustment)
11789 {
11790   GtkDial *dial;
11791
11792   dial = gtk_type_new (gtk_dial_get_type ());
11793
11794   if (!adjustment)
11795     adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
11796
11797   gtk_dial_set_adjustment (dial, adjustment);
11798
11799   return GTK_WIDGET (dial);
11800 }
11801
11802 static void
11803 gtk_dial_destroy (GtkObject *object)
11804 {
11805   GtkDial *dial;
11806
11807   g_return_if_fail (object != NULL);
11808   g_return_if_fail (GTK_IS_DIAL (object));
11809
11810   dial = GTK_DIAL (object);
11811
11812   if (dial->adjustment)
11813     gtk_object_unref (GTK_OBJECT (dial->adjustment));
11814
11815   if (GTK_OBJECT_CLASS (parent_class)->destroy)
11816     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
11817 }
11818 </programlisting>
11819
11820 <para>Note that this <literal>init()</literal> function does less than for the Tictactoe
11821 widget, since this is not a composite widget, and the <literal>new()</literal>
11822 function does more, since it now has an argument. Also, note that when
11823 we store a pointer to the Adjustment object, we increment its
11824 reference count, (and correspondingly decrement it when we no longer
11825 use it) so that GTK can keep track of when it can be safely destroyed.</para>
11826
11827 <para>Also, there are a few function to manipulate the widget's options:</para>
11828
11829 <programlisting role="C">
11830 GtkAdjustment*
11831 gtk_dial_get_adjustment (GtkDial *dial)
11832 {
11833   g_return_val_if_fail (dial != NULL, NULL);
11834   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
11835
11836   return dial->adjustment;
11837 }
11838
11839 void
11840 gtk_dial_set_update_policy (GtkDial      *dial,
11841                              GtkUpdateType  policy)
11842 {
11843   g_return_if_fail (dial != NULL);
11844   g_return_if_fail (GTK_IS_DIAL (dial));
11845
11846   dial->policy = policy;
11847 }
11848
11849 void
11850 gtk_dial_set_adjustment (GtkDial      *dial,
11851                           GtkAdjustment *adjustment)
11852 {
11853   g_return_if_fail (dial != NULL);
11854   g_return_if_fail (GTK_IS_DIAL (dial));
11855
11856   if (dial->adjustment)
11857     {
11858       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
11859       gtk_object_unref (GTK_OBJECT (dial->adjustment));
11860     }
11861
11862   dial->adjustment = adjustment;
11863   gtk_object_ref (GTK_OBJECT (dial->adjustment));
11864
11865   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
11866                       (GtkSignalFunc) gtk_dial_adjustment_changed,
11867                       (gpointer) dial);
11868   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
11869                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
11870                       (gpointer) dial);
11871
11872   dial->old_value = adjustment->value;
11873   dial->old_lower = adjustment->lower;
11874   dial->old_upper = adjustment->upper;
11875
11876   gtk_dial_update (dial);
11877 }
11878 </programlisting>
11879
11880 </sect2>
11881
11882 <!-- ----------------------------------------------------------------- -->
11883 <sect2>
11884 <title><literal>gtk_dial_realize()</literal></title>
11885
11886 <para>Now we come to some new types of functions. First, we have a function
11887 that does the work of creating the X window. Notice that a mask is
11888 passed to the function <literal>gdk_window_new()</literal> which specifies which fields of
11889 the GdkWindowAttr structure actually have data in them (the remaining
11890 fields will be given default values). Also worth noting is the way the
11891 event mask of the widget is created. We call
11892 <literal>gtk_widget_get_events()</literal> to retrieve the event mask that the user
11893 has specified for this widget (with <literal>gtk_widget_set_events()</literal>), and
11894 add the events that we are interested in ourselves.</para>
11895
11896 <para>After creating the window, we set its style and background, and put a
11897 pointer to the widget in the user data field of the GdkWindow. This
11898 last step allows GTK to dispatch events for this window to the correct
11899 widget.</para>
11900
11901 <programlisting role="C">
11902 static void
11903 gtk_dial_realize (GtkWidget *widget)
11904 {
11905   GtkDial *dial;
11906   GdkWindowAttr attributes;
11907   gint attributes_mask;
11908
11909   g_return_if_fail (widget != NULL);
11910   g_return_if_fail (GTK_IS_DIAL (widget));
11911
11912   gtk_widget_set_realized (widget, TRUE);
11913   dial = GTK_DIAL (widget);
11914
11915   attributes.x = widget->allocation.x;
11916   attributes.y = widget->allocation.y;
11917   attributes.width = widget->allocation.width;
11918   attributes.height = widget->allocation.height;
11919   attributes.wclass = GDK_INPUT_OUTPUT;
11920   attributes.window_type = GDK_WINDOW_CHILD;
11921   attributes.event_mask = gtk_widget_get_events (widget) | 
11922     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
11923     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
11924     GDK_POINTER_MOTION_HINT_MASK;
11925   attributes.visual = gtk_widget_get_visual (widget);
11926   attributes.colormap = gtk_widget_get_colormap (widget);
11927
11928   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
11929   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &amp;attributes, attributes_mask);
11930
11931   widget->style = gtk_style_attach (widget->style, widget->window);
11932
11933   gdk_window_set_user_data (widget->window, widget);
11934
11935   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
11936 }
11937 </programlisting>
11938
11939 </sect2>
11940
11941 <!-- ----------------------------------------------------------------- -->
11942 <sect2>
11943 <title>Size negotiation</title>
11944
11945 <para>Before the first time that the window containing a widget is
11946 displayed, and whenever the layout of the window changes, GTK asks
11947 each child widget for its desired size. This request is handled by the
11948 function <literal>gtk_dial_size_request()</literal>. Since our widget isn't a
11949 container widget, and has no real constraints on its size, we just
11950 return a reasonable default value.</para>
11951
11952 <programlisting role="C">
11953 static void 
11954 gtk_dial_size_request (GtkWidget      *widget,
11955                        GtkRequisition *requisition)
11956 {
11957   requisition->width = DIAL_DEFAULT_SIZE;
11958   requisition->height = DIAL_DEFAULT_SIZE;
11959 }
11960 </programlisting>
11961
11962 <para>After all the widgets have requested an ideal size, the layout of the
11963 window is computed and each child widget is notified of its actual
11964 size. Usually, this will be at least as large as the requested size,
11965 but if for instance the user has resized the window, it may
11966 occasionally be smaller than the requested size. The size notification
11967 is handled by the function <literal>gtk_dial_size_allocate()</literal>. Notice that
11968 as well as computing the sizes of some component pieces for future
11969 use, this routine also does the grunt work of moving the widget's X
11970 window into the new position and size.</para>
11971
11972 <programlisting role="C">
11973 static void
11974 gtk_dial_size_allocate (GtkWidget     *widget,
11975                         GtkAllocation *allocation)
11976 {
11977   GtkDial *dial;
11978
11979   g_return_if_fail (widget != NULL);
11980   g_return_if_fail (GTK_IS_DIAL (widget));
11981   g_return_if_fail (allocation != NULL);
11982
11983   widget->allocation = *allocation;
11984   if (gtk_widget_get_realized (widget))
11985     {
11986       dial = GTK_DIAL (widget);
11987
11988       gdk_window_move_resize (widget->window,
11989                               allocation->x, allocation->y,
11990                               allocation->width, allocation->height);
11991
11992       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
11993       dial->pointer_width = dial->radius / 5;
11994     }
11995 }
11996 </programlisting>
11997
11998 </sect2>
11999
12000 <!-- ----------------------------------------------------------------- -->
12001 <sect2>
12002 <title><literal>gtk_dial_expose()</literal></title>
12003
12004 <para>As mentioned above, all the drawing of this widget is done in the
12005 handler for expose events. There's not much to remark on here except
12006 the use of the function <literal>gtk_draw_polygon</literal> to draw the pointer with
12007 three dimensional shading according to the colors stored in the
12008 widget's style.</para>
12009
12010 <programlisting role="C">
12011 static gboolean
12012 gtk_dial_expose( GtkWidget      *widget,
12013                  GdkEventExpose *event )
12014 {
12015   GtkDial *dial;
12016   GdkPoint points[3];
12017   gdouble s,c;
12018   gdouble theta;
12019   gint xc, yc;
12020   gint tick_length;
12021   gint i;
12022
12023   g_return_val_if_fail (widget != NULL, FALSE);
12024   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12025   g_return_val_if_fail (event != NULL, FALSE);
12026
12027   if (event->count > 0)
12028     return FALSE;
12029   
12030   dial = GTK_DIAL (widget);
12031
12032   gdk_window_clear_area (widget->window,
12033                          0, 0,
12034                          widget->allocation.width,
12035                          widget->allocation.height);
12036
12037   xc = widget->allocation.width/2;
12038   yc = widget->allocation.height/2;
12039
12040   /* Draw ticks */
12041
12042   for (i=0; i<25; i++)
12043     {
12044       theta = (i*M_PI/18. - M_PI/6.);
12045       s = sin(theta);
12046       c = cos(theta);
12047
12048       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
12049       
12050       gdk_draw_line (widget->window,
12051                      widget->style->fg_gc[widget->state],
12052                      xc + c*(dial->radius - tick_length),
12053                      yc - s*(dial->radius - tick_length),
12054                      xc + c*dial->radius,
12055                      yc - s*dial->radius);
12056     }
12057
12058   /* Draw pointer */
12059
12060   s = sin(dial->angle);
12061   c = cos(dial->angle);
12062
12063
12064   points[0].x = xc + s*dial->pointer_width/2;
12065   points[0].y = yc + c*dial->pointer_width/2;
12066   points[1].x = xc + c*dial->radius;
12067   points[1].y = yc - s*dial->radius;
12068   points[2].x = xc - s*dial->pointer_width/2;
12069   points[2].y = yc - c*dial->pointer_width/2;
12070
12071   gtk_draw_polygon (widget->style,
12072                     widget->window,
12073                     GTK_STATE_NORMAL,
12074                     GTK_SHADOW_OUT,
12075                     points, 3,
12076                     TRUE);
12077   
12078   return FALSE;
12079 }
12080 </programlisting>
12081
12082 </sect2>
12083
12084 <!-- ----------------------------------------------------------------- -->
12085 <sect2>
12086 <title>Event handling</title>
12087
12088 <para>The rest of the widget's code handles various types of events, and
12089 isn't too different from what would be found in many GTK
12090 applications. Two types of events can occur - either the user can
12091 click on the widget with the mouse and drag to move the pointer, or
12092 the value of the Adjustment object can change due to some external
12093 circumstance.</para>
12094
12095 <para>When the user clicks on the widget, we check to see if the click was
12096 appropriately near the pointer, and if so, store the button that the
12097 user clicked with in the <literal>button</literal> field of the widget
12098 structure, and grab all mouse events with a call to
12099 <literal>gtk_grab_add()</literal>. Subsequent motion of the mouse causes the
12100 value of the control to be recomputed (by the function
12101 <literal>gtk_dial_update_mouse</literal>). Depending on the policy that has been
12102 set, "value_changed" events are either generated instantly
12103 (<literal>GTK_UPDATE_CONTINUOUS</literal>), after a delay in a timer added with
12104 <literal>g_timeout_add()</literal> (<literal>GTK_UPDATE_DELAYED</literal>), or only when the
12105 button is released (<literal>GTK_UPDATE_DISCONTINUOUS</literal>).</para>
12106
12107 <programlisting role="C">
12108 static gboolean
12109 gtk_dial_button_press( GtkWidget      *widget,
12110                        GdkEventButton *event )
12111 {
12112   GtkDial *dial;
12113   gint dx, dy;
12114   double s, c;
12115   double d_parallel;
12116   double d_perpendicular;
12117
12118   g_return_val_if_fail (widget != NULL, FALSE);
12119   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12120   g_return_val_if_fail (event != NULL, FALSE);
12121
12122   dial = GTK_DIAL (widget);
12123
12124   /* Determine if button press was within pointer region - we 
12125      do this by computing the parallel and perpendicular distance of
12126      the point where the mouse was pressed from the line passing through
12127      the pointer */
12128   
12129   dx = event->x - widget->allocation.width / 2;
12130   dy = widget->allocation.height / 2 - event->y;
12131   
12132   s = sin(dial->angle);
12133   c = cos(dial->angle);
12134   
12135   d_parallel = s*dy + c*dx;
12136   d_perpendicular = fabs(s*dx - c*dy);
12137   
12138   if (!dial->button &&
12139       (d_perpendicular < dial->pointer_width/2) &&
12140       (d_parallel > - dial->pointer_width))
12141     {
12142       gtk_grab_add (widget);
12143
12144       dial->button = event->button;
12145
12146       gtk_dial_update_mouse (dial, event->x, event->y);
12147     }
12148
12149   return FALSE;
12150 }
12151
12152 static gboolean
12153 gtk_dial_button_release( GtkWidget      *widget,
12154                          GdkEventButton *event )
12155 {
12156   GtkDial *dial;
12157
12158   g_return_val_if_fail (widget != NULL, FALSE);
12159   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12160   g_return_val_if_fail (event != NULL, FALSE);
12161
12162   dial = GTK_DIAL (widget);
12163
12164   if (dial->button == event->button)
12165     {
12166       gtk_grab_remove (widget);
12167
12168       dial->button = 0;
12169
12170       if (dial->policy == GTK_UPDATE_DELAYED)
12171         g_source_remove (dial->timer);
12172       
12173       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
12174           (dial->old_value != dial->adjustment->value))
12175         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12176     }
12177
12178   return FALSE;
12179 }
12180
12181 static gboolean
12182 gtk_dial_motion_notify( GtkWidget      *widget,
12183                         GdkEventMotion *event )
12184 {
12185   GtkDial *dial;
12186   GdkModifierType mods;
12187   gint x, y, mask;
12188
12189   g_return_val_if_fail (widget != NULL, FALSE);
12190   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
12191   g_return_val_if_fail (event != NULL, FALSE);
12192
12193   dial = GTK_DIAL (widget);
12194
12195   if (dial->button != 0)
12196     {
12197       x = event->x;
12198       y = event->y;
12199
12200       if (event->is_hint || (event->window != widget->window))
12201         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
12202
12203       switch (dial->button)
12204         {
12205         case 1:
12206           mask = GDK_BUTTON1_MASK;
12207           break;
12208         case 2:
12209           mask = GDK_BUTTON2_MASK;
12210           break;
12211         case 3:
12212           mask = GDK_BUTTON3_MASK;
12213           break;
12214         default:
12215           mask = 0;
12216           break;
12217         }
12218
12219       if (mods & mask)
12220         gtk_dial_update_mouse (dial, x,y);
12221     }
12222
12223   return FALSE;
12224 }
12225
12226 static gboolean
12227 gtk_dial_timer( GtkDial *dial )
12228 {
12229   g_return_val_if_fail (dial != NULL, FALSE);
12230   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
12231
12232   if (dial->policy == GTK_UPDATE_DELAYED)
12233     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12234
12235   return FALSE;
12236 }
12237
12238 static void
12239 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
12240 {
12241   gint xc, yc;
12242   gfloat old_value;
12243
12244   g_return_if_fail (dial != NULL);
12245   g_return_if_fail (GTK_IS_DIAL (dial));
12246
12247   xc = GTK_WIDGET(dial)->allocation.width / 2;
12248   yc = GTK_WIDGET(dial)->allocation.height / 2;
12249
12250   old_value = dial->adjustment->value;
12251   dial->angle = atan2(yc-y, x-xc);
12252
12253   if (dial->angle < -M_PI/2.)
12254     dial->angle += 2*M_PI;
12255
12256   if (dial->angle < -M_PI/6)
12257     dial->angle = -M_PI/6;
12258
12259   if (dial->angle > 7.*M_PI/6.)
12260     dial->angle = 7.*M_PI/6.;
12261
12262   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
12263     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
12264
12265   if (dial->adjustment->value != old_value)
12266     {
12267       if (dial->policy == GTK_UPDATE_CONTINUOUS)
12268         {
12269           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12270         }
12271       else
12272         {
12273           gtk_widget_draw (GTK_WIDGET(dial), NULL);
12274
12275           if (dial->policy == GTK_UPDATE_DELAYED)
12276             {
12277               if (dial->timer)
12278                 g_source_remove (dial->timer);
12279
12280               dial->timer = g_timeout_add (SCROLL_DELAY_LENGTH,
12281                                            (GtkFunction) gtk_dial_timer,
12282                                            (gpointer) dial);
12283             }
12284         }
12285     }
12286 }
12287 </programlisting>
12288
12289 <para>Changes to the Adjustment by external means are communicated to our
12290 widget by the "changed" and "value_changed" signals. The handlers
12291 for these functions call <literal>gtk_dial_update()</literal> to validate the
12292 arguments, compute the new pointer angle, and redraw the widget (by
12293 calling <literal>gtk_widget_draw()</literal>).</para>
12294
12295 <programlisting role="C">
12296 static void
12297 gtk_dial_update (GtkDial *dial)
12298 {
12299   gfloat new_value;
12300   
12301   g_return_if_fail (dial != NULL);
12302   g_return_if_fail (GTK_IS_DIAL (dial));
12303
12304   new_value = dial->adjustment->value;
12305   
12306   if (new_value < dial->adjustment->lower)
12307     new_value = dial->adjustment->lower;
12308
12309   if (new_value > dial->adjustment->upper)
12310     new_value = dial->adjustment->upper;
12311
12312   if (new_value != dial->adjustment->value)
12313     {
12314       dial->adjustment->value = new_value;
12315       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
12316     }
12317
12318   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
12319     (dial->adjustment->upper - dial->adjustment->lower);
12320
12321   gtk_widget_draw (GTK_WIDGET(dial), NULL);
12322 }
12323
12324 static void
12325 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
12326                               gpointer       data)
12327 {
12328   GtkDial *dial;
12329
12330   g_return_if_fail (adjustment != NULL);
12331   g_return_if_fail (data != NULL);
12332
12333   dial = GTK_DIAL (data);
12334
12335   if ((dial->old_value != adjustment->value) ||
12336       (dial->old_lower != adjustment->lower) ||
12337       (dial->old_upper != adjustment->upper))
12338     {
12339       gtk_dial_update (dial);
12340
12341       dial->old_value = adjustment->value;
12342       dial->old_lower = adjustment->lower;
12343       dial->old_upper = adjustment->upper;
12344     }
12345 }
12346
12347 static void
12348 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
12349                                     gpointer       data)
12350 {
12351   GtkDial *dial;
12352
12353   g_return_if_fail (adjustment != NULL);
12354   g_return_if_fail (data != NULL);
12355
12356   dial = GTK_DIAL (data);
12357
12358   if (dial->old_value != adjustment->value)
12359     {
12360       gtk_dial_update (dial);
12361
12362       dial->old_value = adjustment->value;
12363     }
12364 }
12365 </programlisting>
12366
12367 </sect2>
12368
12369 <!-- ----------------------------------------------------------------- -->
12370 <sect2>
12371 <title>Possible Enhancements</title>
12372
12373 <para>The Dial widget as we've described it so far runs about 670 lines of
12374 code. Although that might sound like a fair bit, we've really
12375 accomplished quite a bit with that much code, especially since much of
12376 that length is headers and boilerplate. However, there are quite a few
12377 more enhancements that could be made to this widget:</para>
12378
12379 <itemizedlist>
12380 <listitem><simpara> If you try this widget out, you'll find that there is some
12381 flashing as the pointer is dragged around. This is because the entire
12382 widget is erased every time the pointer is moved before being
12383 redrawn. Often, the best way to handle this problem is to draw to an
12384 offscreen pixmap, then copy the final results onto the screen in one
12385 step. (The ProgressBar widget draws itself in this fashion.)</simpara>
12386 </listitem>
12387
12388 <listitem><simpara> The user should be able to use the up and down arrow keys to
12389 increase and decrease the value.</simpara>
12390 </listitem>
12391
12392 <listitem><simpara> It would be nice if the widget had buttons to increase and
12393 decrease the value in small or large steps. Although it would be
12394 possible to use embedded Button widgets for this, we would also like
12395 the buttons to auto-repeat when held down, as the arrows on a
12396 scrollbar do. Most of the code to implement this type of behavior can
12397 be found in the Range widget.</simpara>
12398 </listitem>
12399
12400 <listitem><simpara> The Dial widget could be made into a container widget with a
12401 single child widget positioned at the bottom between the buttons
12402 mentioned above. The user could then add their choice of a label or
12403 entry widget to display the current value of the dial.</simpara>
12404 </listitem>
12405 </itemizedlist>
12406
12407 </sect2>
12408 </sect1>
12409
12410 <!-- ----------------------------------------------------------------- -->
12411 <sect1 id="sec-LearningMore">
12412 <title>Learning More</title>
12413
12414 <para>Only a small part of the many details involved in creating widgets
12415 could be described above. If you want to write your own widgets, the
12416 best source of examples is the GTK source itself. Ask yourself some
12417 questions about the widget you want to write: IS it a Container
12418 widget? Does it have its own window? Is it a modification of an
12419 existing widget? Then find a similar widget, and start making changes.
12420 Good luck!</para>
12421
12422 </sect1>
12423 </chapter>
12424
12425 <!-- ***************************************************************** -->
12426 <chapter id="ch-Scribble">
12427 <title>Scribble, A Simple Example Drawing Program</title>
12428
12429 <!-- ----------------------------------------------------------------- -->
12430 <sect1 id="sec-ScribbleOverview">
12431 <title>Overview</title>
12432
12433 <para>In this section, we will build a simple drawing program. In the
12434 process, we will examine how to handle mouse events, how to draw in a
12435 window, and how to do drawing better by using a backing pixmap. After
12436 creating the simple drawing program, we will extend it by adding
12437 support for XInput devices, such as drawing tablets. GTK provides
12438 support routines which makes getting extended information, such as
12439 pressure and tilt, from such devices quite easy.</para>
12440
12441 <para>
12442 <inlinemediaobject>
12443 <imageobject>
12444 <imagedata fileref="images/scribble.png" format="png">
12445 </imageobject>
12446 </inlinemediaobject>
12447 </para>
12448
12449 </sect1>
12450
12451 <!-- ----------------------------------------------------------------- -->
12452 <sect1 id="sec-EventHandling">
12453 <title>Event Handling</title>
12454
12455 <para>The GTK signals we have already discussed are for high-level actions,
12456 such as a menu item being selected. However, sometimes it is useful to
12457 learn about lower-level occurrences, such as the mouse being moved, or
12458 a key being pressed. There are also GTK signals corresponding to these
12459 low-level <emphasis>events</emphasis>. The handlers for these signals have an
12460 extra parameter which is a pointer to a structure containing
12461 information about the event. For instance, motion event handlers are
12462 passed a pointer to a GdkEventMotion structure which looks (in part)
12463 like:</para>
12464
12465 <programlisting role="C">
12466 struct _GdkEventMotion
12467 {
12468   GdkEventType type;
12469   GdkWindow *window;
12470   guint32 time;
12471   gdouble x;
12472   gdouble y;
12473   ...
12474   guint state;
12475   ...
12476 };
12477 </programlisting>
12478
12479 <para><literal>type</literal> will be set to the event type, in this case
12480 <literal>GDK_MOTION_NOTIFY</literal>, window is the window in which the event
12481 occurred. <literal>x</literal> and <literal>y</literal> give the coordinates of the event.
12482 <literal>state</literal> specifies the modifier state when the event
12483 occurred (that is, it specifies which modifier keys and mouse buttons
12484 were pressed). It is the bitwise OR of some of the following:</para>
12485
12486 <programlisting role="C">
12487 GDK_SHIFT_MASK  
12488 GDK_LOCK_MASK   
12489 GDK_CONTROL_MASK
12490 GDK_MOD1_MASK   
12491 GDK_MOD2_MASK   
12492 GDK_MOD3_MASK   
12493 GDK_MOD4_MASK   
12494 GDK_MOD5_MASK   
12495 GDK_BUTTON1_MASK
12496 GDK_BUTTON2_MASK
12497 GDK_BUTTON3_MASK
12498 GDK_BUTTON4_MASK
12499 GDK_BUTTON5_MASK
12500 </programlisting>
12501
12502 <para>As for other signals, to determine what happens when an event occurs
12503 we call <literal>gtk_signal_connect()</literal>. But we also need let GTK
12504 know which events we want to be notified about. To do this, we call
12505 the function:</para>
12506
12507 <programlisting role="C">
12508 void gtk_widget_set_events (GtkWidget *widget,
12509                             gint      events);
12510 </programlisting>
12511
12512 <para>The second field specifies the events we are interested in. It
12513 is the bitwise OR of constants that specify different types
12514 of events. For future reference the event types are:</para>
12515
12516 <programlisting role="C">
12517 GDK_EXPOSURE_MASK
12518 GDK_POINTER_MOTION_MASK
12519 GDK_POINTER_MOTION_HINT_MASK
12520 GDK_BUTTON_MOTION_MASK     
12521 GDK_BUTTON1_MOTION_MASK    
12522 GDK_BUTTON2_MOTION_MASK    
12523 GDK_BUTTON3_MOTION_MASK    
12524 GDK_BUTTON_PRESS_MASK      
12525 GDK_BUTTON_RELEASE_MASK    
12526 GDK_KEY_PRESS_MASK         
12527 GDK_KEY_RELEASE_MASK       
12528 GDK_ENTER_NOTIFY_MASK      
12529 GDK_LEAVE_NOTIFY_MASK      
12530 GDK_FOCUS_CHANGE_MASK      
12531 GDK_STRUCTURE_MASK         
12532 GDK_PROPERTY_CHANGE_MASK   
12533 GDK_PROXIMITY_IN_MASK      
12534 GDK_PROXIMITY_OUT_MASK     
12535 </programlisting>
12536
12537 <para>There are a few subtle points that have to be observed when calling
12538 <literal>gtk_widget_set_events()</literal>. First, it must be called before the X window
12539 for a GTK widget is created. In practical terms, this means you
12540 should call it immediately after creating the widget. Second, the
12541 widget must have an associated X window. For efficiency, many widget
12542 types do not have their own window, but draw in their parent's window.
12543 These widgets are:</para>
12544
12545 <programlisting role="C">
12546 GtkAlignment
12547 GtkArrow
12548 GtkBin
12549 GtkBox
12550 GtkImage
12551 GtkItem
12552 GtkLabel
12553 GtkPixmap
12554 GtkScrolledWindow
12555 GtkSeparator
12556 GtkTable
12557 GtkAspectFrame
12558 GtkFrame
12559 GtkVBox
12560 GtkHBox
12561 GtkVSeparator
12562 GtkHSeparator
12563 </programlisting>
12564
12565 <para>To capture events for these widgets, you need to use an EventBox
12566 widget. See the section on the <link linkend="sec-EventBox">EventBox</link> widget for details.</para>
12567
12568 <para>For our drawing program, we want to know when the mouse button is
12569 pressed and when the mouse is moved, so we specify
12570 <literal>GDK_POINTER_MOTION_MASK</literal> and <literal>GDK_BUTTON_PRESS_MASK</literal>. We also
12571 want to know when we need to redraw our window, so we specify
12572 <literal>GDK_EXPOSURE_MASK</literal>. Although we want to be notified via a
12573 Configure event when our window size changes, we don't have to specify
12574 the corresponding <literal>GDK_STRUCTURE_MASK</literal> flag, because it is
12575 automatically specified for all windows.</para>
12576
12577 <para>It turns out, however, that there is a problem with just specifying
12578 <literal>GDK_POINTER_MOTION_MASK</literal>. This will cause the server to add a new
12579 motion event to the event queue every time the user moves the mouse.
12580 Imagine that it takes us 0.1 seconds to handle a motion event, but the
12581 X server queues a new motion event every 0.05 seconds. We will soon
12582 get way behind the users drawing. If the user draws for 5 seconds,
12583 it will take us another 5 seconds to catch up after they release 
12584 the mouse button! What we would like is to only get one motion
12585 event for each event we process. The way to do this is to 
12586 specify <literal>GDK_POINTER_MOTION_HINT_MASK</literal>. </para>
12587
12588 <para>When we specify <literal>GDK_POINTER_MOTION_HINT_MASK</literal>, the server sends
12589 us a motion event the first time the pointer moves after entering
12590 our window, or after a button press or release event. Subsequent 
12591 motion events will be suppressed until we explicitly ask for
12592 the position of the pointer using the function:</para>
12593
12594 <programlisting role="C">
12595 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
12596                                           gint            *x,
12597                                           gint            *y,
12598                                           GdkModifierType *mask);
12599 </programlisting>
12600
12601 <para>(There is another function, <literal>gtk_widget_get_pointer()</literal> which
12602 has a simpler interface, but turns out not to be very useful, since
12603 it only retrieves the position of the mouse, not whether the buttons
12604 are pressed.)</para>
12605
12606 <para>The code to set the events for our window then looks like:</para>
12607
12608 <programlisting role="C">
12609   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
12610                       (GtkSignalFunc) expose_event, NULL);
12611   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
12612                       (GtkSignalFunc) configure_event, NULL);
12613   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
12614                       (GtkSignalFunc) motion_notify_event, NULL);
12615   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
12616                       (GtkSignalFunc) button_press_event, NULL);
12617
12618   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
12619                          | GDK_LEAVE_NOTIFY_MASK
12620                          | GDK_BUTTON_PRESS_MASK
12621                          | GDK_POINTER_MOTION_MASK
12622                          | GDK_POINTER_MOTION_HINT_MASK);
12623 </programlisting>
12624
12625 <para>We'll save the "expose_event" and "configure_event" handlers for
12626 later. The "motion_notify_event" and "button_press_event" handlers
12627 are pretty simple:</para>
12628
12629 <programlisting role="C">
12630 static gboolean
12631 button_press_event( GtkWidget *widget, GdkEventButton *event )
12632 {
12633   if (event->button == 1 &amp;&amp; pixmap != NULL)
12634       draw_brush (widget, event->x, event->y);
12635
12636   return TRUE;
12637 }
12638
12639 static gboolean
12640 motion_notify_event( GtkWidget *widget, GdkEventMotion *event )
12641 {
12642   int x, y;
12643   GdkModifierType state;
12644
12645   if (event->is_hint)
12646     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
12647   else
12648     {
12649       x = event->x;
12650       y = event->y;
12651       state = event->state;
12652     }
12653     
12654   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
12655     draw_brush (widget, x, y);
12656   
12657   return TRUE;
12658 }
12659 </programlisting>
12660
12661 </sect1>
12662
12663 <!-- ----------------------------------------------------------------- -->
12664 <sect1 id="sec-TheDrawingAreaWidget">
12665 <title>The DrawingArea Widget, And Drawing</title>
12666
12667 <para>We now turn to the process of drawing on the screen. The 
12668 widget we use for this is the DrawingArea widget. A drawing area
12669 widget is essentially an X window and nothing more. It is a blank
12670 canvas in which we can draw whatever we like. A drawing area
12671 is created using the call:</para>
12672
12673 <programlisting role="C">
12674 GtkWidget* gtk_drawing_area_new        (void);
12675 </programlisting>
12676
12677 <para>A default size for the widget can be specified by calling:</para>
12678
12679 <programlisting role="C">
12680 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
12681                                         gint                 width,
12682                                         gint                 height);
12683 </programlisting>
12684
12685 <para>This default size can be overridden, as is true for all widgets,
12686 by calling <literal>gtk_widget_set_size_request()</literal>, and that, in turn, can
12687 be overridden if the user manually resizes the the window containing
12688 the drawing area.</para>
12689
12690 <para>It should be noted that when we create a DrawingArea widget, we are
12691 <emphasis>completely</emphasis> responsible for drawing the contents. If our
12692 window is obscured then uncovered, we get an exposure event and must
12693 redraw what was previously hidden.</para>
12694
12695 <para>Having to remember everything that was drawn on the screen so we
12696 can properly redraw it can, to say the least, be a nuisance. In
12697 addition, it can be visually distracting if portions of the
12698 window are cleared, then redrawn step by step. The solution to
12699 this problem is to use an offscreen <emphasis>backing pixmap</emphasis>.
12700 Instead of drawing directly to the screen, we draw to an image
12701 stored in server memory but not displayed, then when the image
12702 changes or new portions of the image are displayed, we copy the
12703 relevant portions onto the screen.</para>
12704
12705 <para>To create an offscreen pixmap, we call the function:</para>
12706
12707 <programlisting role="C">
12708 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
12709                                          gint        width,
12710                                          gint        height,
12711                                          gint        depth);
12712 </programlisting>
12713
12714 <para>The <literal>window</literal> parameter specifies a GDK window that this pixmap
12715 takes some of its properties from. <literal>width</literal> and <literal>height</literal>
12716 specify the size of the pixmap. <literal>depth</literal> specifies the <emphasis>color
12717 depth</emphasis>, that is the number of bits per pixel, for the new window.
12718 If the depth is specified as <literal>-1</literal>, it will match the depth
12719 of <literal>window</literal>.</para>
12720
12721 <para>We create the pixmap in our "configure_event" handler. This event
12722 is generated whenever the window changes size, including when it
12723 is originally created.</para>
12724
12725 <programlisting role="C">
12726 /* Backing pixmap for drawing area */
12727 static GdkPixmap *pixmap = NULL;
12728
12729 /* Create a new backing pixmap of the appropriate size */
12730 static gboolean
12731 configure_event( GtkWidget *widget, GdkEventConfigure *event )
12732 {
12733   if (pixmap)
12734     g_object_unref(pixmap);
12735
12736   pixmap = gdk_pixmap_new(widget->window,
12737                           widget->allocation.width,
12738                           widget->allocation.height,
12739                           -1);
12740   gdk_draw_rectangle (pixmap,
12741                       widget->style->white_gc,
12742                       TRUE,
12743                       0, 0,
12744                       widget->allocation.width,
12745                       widget->allocation.height);
12746
12747   return TRUE;
12748 }
12749 </programlisting>
12750
12751 <para>The call to <literal>gdk_draw_rectangle()</literal> clears the pixmap
12752 initially to white. We'll say more about that in a moment.</para>
12753
12754 <para>Our exposure event handler then simply copies the relevant portion
12755 of the pixmap onto the screen (we determine the area we need
12756 to redraw by using the event->area field of the exposure event):</para>
12757
12758 <programlisting role="C">
12759 /* Redraw the screen from the backing pixmap */
12760 static gboolean
12761 expose_event( GtkWidget *widget, GdkEventExpose *event )
12762 {
12763   gdk_draw_drawable(widget->window,
12764                     widget->style->fg_gc[gtk_widget_get_state (widget)],
12765                     pixmap,
12766                     event->area.x, event->area.y,
12767                     event->area.x, event->area.y,
12768                     event->area.width, event->area.height);
12769
12770   return FALSE;
12771 }
12772 </programlisting>
12773
12774 <para>We've now seen how to keep the screen up to date with our pixmap, but
12775 how do we actually draw interesting stuff on our pixmap?  There are a
12776 large number of calls in GTK's GDK library for drawing on
12777 <emphasis>drawables</emphasis>. A drawable is simply something that can be drawn
12778 upon. It can be a window, a pixmap, or a bitmap (a black and white
12779 image).  We've already seen two such calls above,
12780 <literal>gdk_draw_rectangle()</literal> and <literal>gdk_draw_drawable()</literal>. The
12781 complete list is:</para>
12782
12783 <programlisting role="C">
12784 gdk_draw_point ()
12785 gdk_draw_line ()
12786 gdk_draw_rectangle ()
12787 gdk_draw_arc ()
12788 gdk_draw_polygon ()
12789 gdk_draw_image ()
12790 gdk_draw_points ()
12791 gdk_draw_segments ()
12792 gdk_draw_lines ()
12793 gdk_draw_pixbuf ()
12794 gdk_draw_glyphs ()
12795 gdk_draw_layout_line ()
12796 gdk_draw_layout ()
12797 gdk_draw_layout_line_with_colors ()
12798 gdk_draw_layout_with_colors ()
12799 gdk_draw_glyphs_transformed ()
12800 gdk_draw_glyphs_trapezoids ()
12801 </programlisting>
12802
12803 <para>See the reference documentation or the header file
12804 <literal>&lt;gdk/gdkdrawable.h&gt;</literal> for further details on these functions.
12805 These functions all share the same first two arguments. The first
12806 argument is the drawable to draw upon, the second argument is a
12807 <emphasis>graphics context</emphasis> (GC).</para>
12808
12809 <para>A graphics context encapsulates information about things such as
12810 foreground and background color and line width. GDK has a full set of
12811 functions for creating and modifying graphics contexts, but to keep
12812 things simple we'll just use predefined graphics contexts. Each widget
12813 has an associated style. (Which can be modified in a gtkrc file, see
12814 the section GTK's rc file.) This, among other things, stores a number
12815 of graphics contexts. Some examples of accessing these graphics
12816 contexts are:</para>
12817
12818 <programlisting role="C">
12819 widget->style->white_gc
12820 widget->style->black_gc
12821 widget->style->fg_gc[GTK_STATE_NORMAL]
12822 widget->style->bg_gc[gtk_widget_get_state(widget)]
12823 </programlisting>
12824
12825 <para>The fields <literal>fg_gc</literal>, <literal>bg_gc</literal>, <literal>dark_gc</literal>, and
12826 <literal>light_gc</literal> are indexed by a parameter of type
12827 <literal>GtkStateType</literal> which can take on the values:</para>
12828
12829 <programlisting role="C">
12830 GTK_STATE_NORMAL,
12831 GTK_STATE_ACTIVE,
12832 GTK_STATE_PRELIGHT,
12833 GTK_STATE_SELECTED,
12834 GTK_STATE_INSENSITIVE
12835 </programlisting>
12836
12837 <para>For instance, for <literal>GTK_STATE_SELECTED</literal> the default foreground
12838 color is white and the default background color, dark blue.</para>
12839
12840 <para>Our function <literal>draw_brush()</literal>, which does the actual drawing
12841 on the screen, is then:</para>
12842
12843 <programlisting role="C">
12844 /* Draw a rectangle on the screen */
12845 static void
12846 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
12847 {
12848   GdkRectangle update_rect;
12849
12850   update_rect.x = x - 5;
12851   update_rect.y = y - 5;
12852   update_rect.width = 10;
12853   update_rect.height = 10;
12854   gdk_draw_rectangle (pixmap,
12855                       widget->style->black_gc,
12856                       TRUE,
12857                       update_rect.x, update_rect.y,
12858                       update_rect.width, update_rect.height);
12859   gtk_widget_queue_draw_area (widget,                 
12860                               update_rect.x, update_rect.y,
12861                               update_rect.width, update_rect.height);
12862 }
12863 </programlisting>
12864
12865 <para>After we draw the rectangle representing the brush onto the pixmap,
12866 we call the function:</para>
12867
12868 <programlisting role="C">
12869 void       gtk_widget_queue_draw_area (GtkWidget           *widget,
12870                                        gint                 x,
12871                                        gint                 y,
12872                                        gint                 width,
12873                                        gint                 height)
12874 </programlisting>
12875
12876 <para>which notifies X that the area given by the <literal>x</literal>, 
12877 <literal>y</literal>, <literal>width</literal> and <literal>height</literal> parameters
12878 needs to be updated. X will eventually generate an expose event
12879 (possibly combining the areas passed in several calls to
12880 <literal>gtk_widget_queue_draw_area()</literal>) which will cause our expose event handler
12881 to copy the relevant portions to the screen.</para>
12882
12883 <para>We have now covered the entire drawing program except for a few
12884 mundane details like creating the main window.</para>
12885
12886 </sect1>
12887
12888 <!-- ----------------------------------------------------------------- -->
12889 <sect1 id="sec-AddingXInputSupport">
12890 <title>Adding XInput support</title>
12891
12892 <para>It is now possible to buy quite inexpensive input devices such 
12893 as drawing tablets, which allow drawing with a much greater
12894 ease of artistic expression than does a mouse. The simplest way
12895 to use such devices is simply as a replacement for the mouse,
12896 but that misses out many of the advantages of these devices,
12897 such as:</para>
12898
12899 <itemizedlist>
12900 <listitem><simpara> Pressure sensitivity</simpara>
12901 </listitem>
12902 <listitem><simpara> Tilt reporting</simpara>
12903 </listitem>
12904 <listitem><simpara> Sub-pixel positioning</simpara>
12905 </listitem>
12906 <listitem><simpara> Multiple inputs (for example, a stylus with a point and eraser)</simpara>
12907 </listitem>
12908 </itemizedlist>
12909
12910 <para>For information about the XInput extension, see the <ulink
12911 url="http://www.gtk.org/~otaylor/xinput/howto/index.html">XInput HOWTO</ulink>.</para>
12912
12913 <para>If we examine the full definition of, for example, the GdkEventMotion
12914 structure, we see that it has fields to support extended device
12915 information.</para>
12916
12917 <programlisting role="C">
12918 struct _GdkEventMotion
12919 {
12920   GdkEventType type;
12921   GdkWindow *window;
12922   guint32 time;
12923   gdouble x;
12924   gdouble y;
12925   gdouble pressure;
12926   gdouble xtilt;
12927   gdouble ytilt;
12928   guint state;
12929   gint16 is_hint;
12930   GdkInputSource source;
12931   guint32 deviceid;
12932 };
12933 </programlisting>
12934
12935 <para><literal>pressure</literal> gives the pressure as a floating point number between
12936 0 and 1. <literal>xtilt</literal> and <literal>ytilt</literal> can take on values between 
12937 -1 and 1, corresponding to the degree of tilt in each direction.
12938 <literal>source</literal> and <literal>deviceid</literal> specify the device for which the
12939 event occurred in two different ways. <literal>source</literal> gives some simple
12940 information about the type of device. It can take the enumeration
12941 values:</para>
12942
12943 <programlisting role="C">
12944 GDK_SOURCE_MOUSE
12945 GDK_SOURCE_PEN
12946 GDK_SOURCE_ERASER
12947 GDK_SOURCE_CURSOR
12948 </programlisting>
12949
12950 <para><literal>deviceid</literal> specifies a unique numeric ID for the device. This can
12951 be used to find out further information about the device using the
12952 <literal>gdk_input_list_devices()</literal> call (see below). The special value
12953 <literal>GDK_CORE_POINTER</literal> is used for the core pointer device. (Usually
12954 the mouse.)</para>
12955
12956 <!-- ----------------------------------------------------------------- -->
12957 <sect2>
12958 <title>Enabling extended device information</title>
12959
12960 <para>To let GTK know about our interest in the extended device information,
12961 we merely have to add a single line to our program:</para>
12962
12963 <programlisting role="C">
12964 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
12965 </programlisting>
12966
12967 <para>By giving the value <literal>GDK_EXTENSION_EVENTS_CURSOR</literal> we say that
12968 we are interested in extension events, but only if we don't have
12969 to draw our own cursor. See the section <link
12970 linkend="sec-FurtherSophistications"> Further Sophistications </link> below
12971 for more information about drawing the cursor. We could also 
12972 give the values <literal>GDK_EXTENSION_EVENTS_ALL</literal> if we were willing 
12973 to draw our own cursor, or <literal>GDK_EXTENSION_EVENTS_NONE</literal> to revert
12974 back to the default condition.</para>
12975
12976 <para>This is not completely the end of the story however. By default,
12977 no extension devices are enabled. We need a mechanism to allow
12978 users to enable and configure their extension devices. GTK provides
12979 the InputDialog widget to automate this process. The following
12980 procedure manages an InputDialog widget. It creates the dialog if
12981 it isn't present, and raises it to the top otherwise.</para>
12982
12983 <programlisting role="C">
12984 void
12985 input_dialog_destroy (GtkWidget *w, gpointer data)
12986 {
12987   *((GtkWidget **)data) = NULL;
12988 }
12989
12990 void
12991 create_input_dialog ()
12992 {
12993   static GtkWidget *inputd = NULL;
12994
12995   if (!inputd)
12996     {
12997       inputd = gtk_input_dialog_new();
12998
12999       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
13000                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
13001       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
13002                                  "clicked",
13003                                  (GtkSignalFunc)gtk_widget_hide,
13004                                  GTK_OBJECT(inputd));
13005       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
13006
13007       gtk_widget_show (inputd);
13008     }
13009   else
13010     {
13011       if (!gtk_widget_get_mapped(inputd))
13012         gtk_widget_show(inputd);
13013       else
13014         gdk_window_raise(inputd->window);
13015     }
13016 }
13017 </programlisting>
13018
13019 <para>(You might want to take note of the way we handle this dialog.  By
13020 connecting to the "destroy" signal, we make sure that we don't keep a
13021 pointer to dialog around after it is destroyed - that could lead to a
13022 segfault.)</para>
13023
13024 <para>The InputDialog has two buttons "Close" and "Save", which by default
13025 have no actions assigned to them. In the above function we make
13026 "Close" hide the dialog, hide the "Save" button, since we don't
13027 implement saving of XInput options in this program.</para>
13028
13029 </sect2>
13030
13031 <!-- ----------------------------------------------------------------- -->
13032 <sect2>
13033 <title>Using extended device information</title>
13034
13035 <para>Once we've enabled the device, we can just use the extended 
13036 device information in the extra fields of the event structures.
13037 In fact, it is always safe to use this information since these
13038 fields will have reasonable default values even when extended
13039 events are not enabled.</para>
13040
13041 <para>Once change we do have to make is to call
13042 <literal>gdk_input_window_get_pointer()</literal> instead of
13043 <literal>gdk_window_get_pointer</literal>. This is necessary because
13044 <literal>gdk_window_get_pointer</literal> doesn't return the extended device
13045 information.</para>
13046
13047 <programlisting role="C">
13048 void gdk_input_window_get_pointer( GdkWindow       *window,
13049                                    guint32         deviceid,
13050                                    gdouble         *x,
13051                                    gdouble         *y,
13052                                    gdouble         *pressure,
13053                                    gdouble         *xtilt,
13054                                    gdouble         *ytilt,
13055                                    GdkModifierType *mask);
13056 </programlisting>
13057
13058 <para>When calling this function, we need to specify the device ID as
13059 well as the window. Usually, we'll get the device ID from the
13060 <literal>deviceid</literal> field of an event structure. Again, this function
13061 will return reasonable values when extension events are not
13062 enabled. (In this case, <literal>event->deviceid</literal> will have the value
13063 <literal>GDK_CORE_POINTER</literal>).</para>
13064
13065 <para>So the basic structure of our button-press and motion event handlers
13066 doesn't change much - we just need to add code to deal with the
13067 extended information.</para>
13068
13069 <programlisting role="C">
13070 static gboolean
13071 button_press_event( GtkWidget *widget, GdkEventButton *event )
13072 {
13073   print_button_press (event->deviceid);
13074   
13075   if (event->button == 1 &amp;&amp; pixmap != NULL)
13076     draw_brush (widget, event->source, event->x, event->y, event->pressure);
13077
13078   return TRUE;
13079 }
13080
13081 static gboolean
13082 motion_notify_event( GtkWidget *widget, GdkEventMotion *event )
13083 {
13084   gdouble x, y;
13085   gdouble pressure;
13086   GdkModifierType state;
13087
13088   if (event->is_hint)
13089     gdk_input_window_get_pointer (event->window, event->deviceid,
13090                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
13091   else
13092     {
13093       x = event->x;
13094       y = event->y;
13095       pressure = event->pressure;
13096       state = event->state;
13097     }
13098     
13099   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
13100     draw_brush (widget, event->source, x, y, pressure);
13101   
13102   return TRUE;
13103 }
13104 </programlisting>
13105
13106 <para>We also need to do something with the new information. Our new
13107 <literal>draw_brush()</literal> function draws with a different color for
13108 each <literal>event->source</literal> and changes the brush size depending
13109 on the pressure.</para>
13110
13111 <programlisting role="C">
13112 /* Draw a rectangle on the screen, size depending on pressure,
13113    and color on the type of device */
13114 static void
13115 draw_brush (GtkWidget *widget, GdkInputSource source,
13116             gdouble x, gdouble y, gdouble pressure)
13117 {
13118   GdkGC *gc;
13119   GdkRectangle update_rect;
13120
13121   switch (source)
13122     {
13123     case GDK_SOURCE_MOUSE:
13124       gc = widget->style->dark_gc[gtk_widget_get_state (widget)];
13125       break;
13126     case GDK_SOURCE_PEN:
13127       gc = widget->style->black_gc;
13128       break;
13129     case GDK_SOURCE_ERASER:
13130       gc = widget->style->white_gc;
13131       break;
13132     default:
13133       gc = widget->style->light_gc[gtk_widget_get_state (widget)];
13134     }
13135
13136   update_rect.x = x - 10 * pressure;
13137   update_rect.y = y - 10 * pressure;
13138   update_rect.width = 20 * pressure;
13139   update_rect.height = 20 * pressure;
13140   gdk_draw_rectangle (pixmap, gc, TRUE,
13141                       update_rect.x, update_rect.y,
13142                       update_rect.width, update_rect.height);
13143   gtk_widget_draw (widget, &amp;update_rect);
13144 }
13145 </programlisting>
13146
13147 </sect2>
13148
13149 <!-- ----------------------------------------------------------------- -->
13150 <sect2>
13151 <title>Finding out more about a device</title>
13152
13153 <para>As an example of how to find out more about a device, our program
13154 will print the name of the device that generates each button
13155 press. To find out the name of a device, we call the function:</para>
13156
13157 <programlisting role="C">
13158 GList *gdk_input_list_devices               (void);
13159 </programlisting>
13160
13161 <para>which returns a GList (a linked list type from the GLib library)
13162 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
13163 as:</para>
13164
13165 <programlisting role="C">
13166 struct _GdkDeviceInfo
13167 {
13168   guint32 deviceid;
13169   gchar *name;
13170   GdkInputSource source;
13171   GdkInputMode mode;
13172   gint has_cursor;
13173   gint num_axes;
13174   GdkAxisUse *axes;
13175   gint num_keys;
13176   GdkDeviceKey *keys;
13177 };
13178 </programlisting>
13179
13180 <para>Most of these fields are configuration information that you can ignore
13181 unless you are implementing XInput configuration saving. The fieldwe
13182 are interested in here is <literal>name</literal> which is simply the name that X
13183 assigns to the device. The other field that isn't configuration
13184 information is <literal>has_cursor</literal>. If <literal>has_cursor</literal> is false, then we
13185 we need to draw our own cursor. But since we've specified
13186 <literal>GDK_EXTENSION_EVENTS_CURSOR</literal>, we don't have to worry about this.</para>
13187
13188 <para>Our <literal>print_button_press()</literal> function simply iterates through
13189 the returned list until it finds a match, then prints out
13190 the name of the device.</para>
13191
13192 <programlisting role="C">
13193 static void
13194 print_button_press (guint32 deviceid)
13195 {
13196   GList *tmp_list;
13197
13198   /* gdk_input_list_devices returns an internal list, so we shouldn't
13199      free it afterwards */
13200   tmp_list = gdk_input_list_devices();
13201
13202   while (tmp_list)
13203     {
13204       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
13205
13206       if (info->deviceid == deviceid)
13207         {
13208           printf("Button press on device '%s'\n", info->name);
13209           return;
13210         }
13211
13212       tmp_list = tmp_list->next;
13213     }
13214 }
13215 </programlisting>
13216
13217 <para>That completes the changes to "XInputize" our program.</para>
13218
13219 </sect2>
13220
13221 <!-- ----------------------------------------------------------------- -->
13222 <sect2 id="sec-FurtherSophistications">
13223 <title>Further sophistications</title>
13224
13225 <para>Although our program now supports XInput quite well, it lacks some
13226 features we would want in a full-featured application. First, the user
13227 probably doesn't want to have to configure their device each time they
13228 run the program, so we should allow them to save the device
13229 configuration. This is done by iterating through the return of
13230 <literal>gdk_input_list_devices()</literal> and writing out the configuration to a
13231 file.</para>
13232
13233 <para>To restore the state next time the program is run, GDK provides
13234 functions to change device configuration:</para>
13235
13236 <programlisting role="C">
13237 gdk_input_set_extension_events()
13238 gdk_input_set_source()
13239 gdk_input_set_mode()
13240 gdk_input_set_axes()
13241 gdk_input_set_key()
13242 </programlisting>
13243
13244 <para>(The list returned from <literal>gdk_input_list_devices()</literal> should not be
13245 modified directly.) An example of doing this can be found in the
13246 drawing program gsumi. (Available from <ulink
13247 url="http://www.msc.cornell.edu/~otaylor/gsumi/">http://www.msc.cornell.edu/~otaylor/gsumi/</ulink>) Eventually, it
13248 would be nice to have a standard way of doing this for all
13249 applications. This probably belongs at a slightly higher level than
13250 GTK, perhaps in the GNOME library.</para>
13251
13252 <para>Another major omission that we have mentioned above is the lack of
13253 cursor drawing. Platforms other than XFree86 currently do not allow
13254 simultaneously using a device as both the core pointer and directly by
13255 an application. See the <ulink
13256 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html">XInput-HOWTO</ulink> for more information about this. This means that
13257 applications that want to support the widest audience need to draw
13258 their own cursor.</para>
13259
13260 <para>An application that draws its own cursor needs to do two things:
13261 determine if the current device needs a cursor drawn or not, and
13262 determine if the current device is in proximity. (If the current
13263 device is a drawing tablet, it's a nice touch to make the cursor 
13264 disappear when the stylus is lifted from the tablet. When the
13265 device is touching the stylus, that is called "in proximity.")
13266 The first is done by searching the device list, as we did
13267 to find out the device name. The second is achieved by selecting
13268 "proximity_out" events. An example of drawing one's own cursor is
13269 found in the "testinput" program found in the GTK distribution.</para>
13270
13271 </sect2>
13272
13273 </sect1>
13274 </chapter>
13275
13276 <!-- ***************************************************************** -->
13277 <chapter id="ch-Tips">
13278 <title>Tips For Writing GTK Applications</title>
13279
13280 <para>This section is simply a gathering of wisdom, general style guidelines
13281 and hints to creating good GTK applications. Currently this section
13282 is very short, but I hope it will get longer in future editions of
13283 this tutorial.</para>
13284
13285 <para>Use GNU autoconf and automake! They are your friends :) Automake
13286 examines C files, determines how they depend on each other, and
13287 generates a Makefile so the files can be compiled in the correct
13288 order. Autoconf permits automatic configuration of software
13289 installation, handling a large number of system quirks to increase
13290 portability. I am planning to make a quick intro on them here.</para>
13291
13292 <para>When writing C code, use only C comments (beginning with "/*" and
13293 ending with "*/"), and don't use C++-style comments ("//").  Although
13294 many C compilers understand C++ comments, others don't, and the ANSI C
13295 standard does not require that C++-style comments be processed as
13296 comments.</para>
13297
13298 </chapter>
13299
13300 <!-- ***************************************************************** -->
13301 <chapter id="ch-Contributing">
13302 <title>Contributing</title>
13303
13304 <para>This document, like so much other great software out there, was
13305 created for free by volunteers.  If you are at all knowledgeable about
13306 any aspect of GTK that does not already have documentation, please
13307 consider contributing to this document.</para>
13308
13309 <para>If you do decide to contribute, please mail your text to Tony Gale,
13310 <literal><ulink url="mailto:gale@gtk.org">gale@gtk.org</ulink></literal>. Also, be aware that the entirety of this
13311 document is free, and any addition by you provide must also be
13312 free. That is, people may use any portion of your examples in their
13313 programs, and copies of this document may be distributed at will, etc.</para>
13314
13315 <para>Thank you.</para>
13316
13317 </chapter>
13318
13319 <!-- ***************************************************************** -->
13320 <chapter id="ch-Credits">
13321 <title>Credits</title>
13322
13323 <para>We would like to thank the following for their contributions to this text.</para>
13324
13325 <itemizedlist>
13326 <listitem><simpara>Bawer Dagdeviren, <literal><ulink url="mailto:chamele0n@geocities.com">chamele0n@geocities.com</ulink></literal> for the menus tutorial.</simpara>
13327 </listitem>
13328
13329 <listitem><simpara>Raph Levien, <literal><ulink url="mailto:raph@acm.org">raph@acm.org</ulink></literal>
13330 for hello world ala GTK, widget packing, and general all around wisdom.
13331 He's also generously donated a home for this tutorial.</simpara>
13332 </listitem>
13333
13334 <listitem><simpara>Peter Mattis, <literal><ulink url="mailto:petm@xcf.berkeley.edu">petm@xcf.berkeley.edu</ulink></literal> for the simplest GTK program.. 
13335 and the ability to make it :)</simpara>
13336 </listitem>
13337
13338 <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
13339 SGML, and the widget class hierarchy.</simpara>
13340 </listitem>
13341
13342 <listitem><simpara>Mark Crichton <literal><ulink
13343 url="mailto:crichton@expert.cc.purdue.edu">crichton@expert.cc.purdue.edu</ulink></literal> for the menu factory code,
13344 and the table packing tutorial.</simpara>
13345 </listitem>
13346
13347 <listitem><simpara>Owen Taylor <literal><ulink url="mailto:owt1@cornell.edu">owt1@cornell.edu</ulink></literal> for the EventBox widget section (and the
13348 patch to the distro).  He's also responsible for the selections code
13349 and tutorial, as well as the sections on writing your own GTK widgets,
13350 and the example application. Thanks a lot Owen for all you help!</simpara>
13351 </listitem>
13352
13353 <listitem><simpara>Mark VanderBoom <literal><ulink url="mailto:mvboom42@calvin.edu">mvboom42@calvin.edu</ulink></literal> for his wonderful work on the
13354 Notebook, Progress Bar, Dialogs, and File selection widgets.  Thanks a
13355 lot Mark!  You've been a great help.</simpara>
13356 </listitem>
13357
13358 <listitem><simpara>Tim Janik <literal><ulink url="mailto:timj@gtk.org">timj@gtk.org</ulink></literal> for his great job on the Lists
13359 Widget. His excellent work on automatically extracting the widget tree
13360 and signal information from GTK. Thanks Tim :)</simpara>
13361 </listitem>
13362
13363 <listitem><simpara>Rajat Datta <literal><ulink url="mailto:rajat@ix.netcom.com">rajat@ix.netcom.com</ulink>
13364 </literal> for the excellent job on the Pixmap
13365 tutorial.</simpara>
13366 </listitem>
13367
13368 <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>
13369 </listitem>
13370
13371 <listitem><simpara>David Huggins-Daines <literal><ulink
13372 url="mailto:bn711@freenet.carleton.ca">bn711@freenet.carleton.ca</ulink></literal> for the Range Widgets and Tree
13373 Widget sections.</simpara>
13374 </listitem>
13375
13376 <listitem><simpara>Stefan Mars <literal><ulink url="mailto:mars@lysator.liu.se">mars@lysator.liu.se</ulink></literal> for the CList section.</simpara>
13377 </listitem>
13378
13379 <listitem><simpara>David A. Wheeler <literal><ulink url="mailto:dwheeler@ida.org">dwheeler@ida.org</ulink></literal> for portions of the text on GLib
13380 and various tutorial fixups and improvements.
13381 The GLib text was in turn based on material developed by Damon Chaplin
13382 <literal><ulink url="mailto:DAChaplin@msn.com">DAChaplin@msn.com</ulink></literal></simpara>
13383 </listitem>
13384
13385 <listitem><simpara>David King for style checking the entire document.</simpara>
13386 </listitem>
13387 </itemizedlist>
13388
13389 <para>And to all of you who commented on and helped refine this document.</para>
13390
13391 <para>Thanks.</para>
13392
13393 </chapter>
13394
13395 <!-- ***************************************************************** -->
13396 <chapter id="ch-Copyright">
13397 <title>Tutorial Copyright and Permissions Notice</title>
13398
13399 <para>The GTK Tutorial is Copyright (C) 1997 Ian Main. </para>
13400
13401 <para>Copyright (C) 1998-2002 Tony Gale.</para>
13402
13403 <para>Permission is granted to make and distribute verbatim copies of this 
13404 manual provided the copyright notice and this permission notice are 
13405 preserved on all copies.</para>
13406
13407 <para>Permission is granted to copy and distribute modified versions of 
13408 this document under the conditions for verbatim copying, provided that 
13409 this copyright notice is included exactly as in the original,
13410 and that the entire resulting derived work is distributed under 
13411 the terms of a permission notice identical to this one.</para>
13412
13413 <para>Permission is granted to copy and distribute translations of this 
13414 document into another language, under the above conditions for modified 
13415 versions.</para>
13416
13417 <para>If you are intending to incorporate this document into a published 
13418 work, please contact the maintainer, and we will make an effort 
13419 to ensure that you have the most up to date information available.</para>
13420
13421 <para>There is no guarantee that this document lives up to its intended
13422 purpose.  This is simply provided as a free resource.  As such,
13423 the authors and maintainers of the information provided within can
13424 not make any guarantee that the information is even accurate.</para>
13425
13426 </chapter>
13427
13428 <!-- ***************************************************************** -->
13429 <!-- ***************************************************************** -->
13430
13431 <!-- ***************************************************************** -->
13432 <appendix id="app-GTKSignals">
13433 <title>GTK Signals</title>
13434
13435 <para>As GTK is an object oriented widget set, it has a hierarchy of
13436 inheritance. This inheritance mechanism applies for
13437 signals. Therefore, you should refer to the widget hierarchy tree when
13438 using the signals listed in this section.</para>
13439
13440 <!-- ----------------------------------------------------------------- -->
13441 <sect1 id="sec-GtkObject">
13442 <title>GtkObject</title>
13443
13444 <programlisting role="C">
13445 void GtkObject::destroy (GtkObject *,
13446                          gpointer);
13447 </programlisting>
13448
13449 </sect1>
13450
13451 <!-- ----------------------------------------------------------------- -->
13452 <sect1 id="sec-GtkWidget">
13453 <title>GtkWidget</title>
13454
13455 <programlisting role="C">
13456 void GtkWidget::show    (GtkWidget *,
13457                          gpointer);
13458 void GtkWidget::hide    (GtkWidget *,
13459                          gpointer);
13460 void GtkWidget::map     (GtkWidget *,
13461                          gpointer);
13462 void GtkWidget::unmap   (GtkWidget *,
13463                          gpointer);
13464 void GtkWidget::realize (GtkWidget *,
13465                          gpointer);
13466 void GtkWidget::unrealize       (GtkWidget *,
13467                                  gpointer);
13468 void GtkWidget::draw    (GtkWidget *,
13469                          ggpointer,
13470                          gpointer);
13471 void GtkWidget::draw-focus      (GtkWidget *,
13472                                  gpointer);
13473 void GtkWidget::draw-default    (GtkWidget *,
13474                                  gpointer);
13475 void GtkWidget::size-request    (GtkWidget *,
13476                                  ggpointer,
13477                                  gpointer);
13478 void GtkWidget::size-allocate   (GtkWidget *,
13479                                  ggpointer,
13480                                  gpointer);
13481 void GtkWidget::state-changed   (GtkWidget *,
13482                                  GtkStateType,
13483                                  gpointer);
13484 void GtkWidget::parent-set      (GtkWidget *,
13485                                  GtkObject *,
13486                                  gpointer);
13487 void GtkWidget::style-set       (GtkWidget *,
13488                                  GtkStyle *,
13489                                  gpointer);
13490 void GtkWidget::add-accelerator (GtkWidget *,
13491                                  gguint,
13492                                  GtkAccelGroup *,
13493                                  gguint,
13494                                  GdkModifierType,
13495                                  GtkAccelFlags,
13496                                  gpointer);
13497 void GtkWidget::remove-accelerator      (GtkWidget *,
13498                                          GtkAccelGroup *,
13499                                          gguint,
13500                                          GdkModifierType,
13501                                          gpointer);
13502 gboolean GtkWidget::event       (GtkWidget *,
13503                                  GdkEvent *,
13504                                  gpointer);
13505 gboolean GtkWidget::button-press-event  (GtkWidget *,
13506                                          GdkEvent *,
13507                                          gpointer);
13508 gboolean GtkWidget::button-release-event        (GtkWidget *,
13509                                                  GdkEvent *,
13510                                                  gpointer);
13511 gboolean GtkWidget::motion-notify-event (GtkWidget *,
13512                                          GdkEvent *,
13513                                          gpointer);
13514 gboolean GtkWidget::delete-event        (GtkWidget *,
13515                                          GdkEvent *,
13516                                          gpointer);
13517 gboolean GtkWidget::destroy-event       (GtkWidget *,
13518                                          GdkEvent *,
13519                                          gpointer);
13520 gboolean GtkWidget::expose-event        (GtkWidget *,
13521                                          GdkEvent *,
13522                                          gpointer);
13523 gboolean GtkWidget::key-press-event     (GtkWidget *,
13524                                          GdkEvent *,
13525                                          gpointer);
13526 gboolean GtkWidget::key-release-event   (GtkWidget *,
13527                                          GdkEvent *,
13528                                          gpointer);
13529 gboolean GtkWidget::enter-notify-event  (GtkWidget *,
13530                                          GdkEvent *,
13531                                          gpointer);
13532 gboolean GtkWidget::leave-notify-event  (GtkWidget *,
13533                                          GdkEvent *,
13534                                          gpointer);
13535 gboolean GtkWidget::configure-event     (GtkWidget *,
13536                                          GdkEvent *,
13537                                          gpointer);
13538 gboolean GtkWidget::focus-in-event      (GtkWidget *,
13539                                          GdkEvent *,
13540                                          gpointer);
13541 gboolean GtkWidget::focus-out-event     (GtkWidget *,
13542                                          GdkEvent *,
13543                                          gpointer);
13544 gboolean GtkWidget::map-event   (GtkWidget *,
13545                                  GdkEvent *,
13546                                  gpointer);
13547 gboolean GtkWidget::unmap-event (GtkWidget *,
13548                                  GdkEvent *,
13549                                  gpointer);
13550 gboolean GtkWidget::property-notify-event       (GtkWidget *,
13551                                                  GdkEvent *,
13552                                                  gpointer);
13553 gboolean GtkWidget::selection-clear-event       (GtkWidget *,
13554                                                  GdkEvent *,
13555                                                  gpointer);
13556 gboolean GtkWidget::selection-request-event     (GtkWidget *,
13557                                                  GdkEvent *,
13558                                                  gpointer);
13559 gboolean GtkWidget::selection-notify-event      (GtkWidget *,
13560                                                  GdkEvent *,
13561                                                  gpointer);
13562 void GtkWidget::selection-get   (GtkWidget *,
13563                                  GtkSelectionData *,
13564                                  gguint,
13565                                  gpointer);
13566 void GtkWidget::selection-received      (GtkWidget *,
13567                                          GtkSelectionData *,
13568                                          gguint,
13569                                          gpointer);
13570 gboolean GtkWidget::proximity-in-event  (GtkWidget *,
13571                                          GdkEvent *,
13572                                          gpointer);
13573 gboolean GtkWidget::proximity-out-event (GtkWidget *,
13574                                          GdkEvent *,
13575                                          gpointer);
13576 void GtkWidget::drag-begin      (GtkWidget *,
13577                                  GdkDragContext *,
13578                                  gpointer);
13579 void GtkWidget::drag-end        (GtkWidget *,
13580                                  GdkDragContext *,
13581                                  gpointer);
13582 void GtkWidget::drag-data-delete        (GtkWidget *,
13583                                          GdkDragContext *,
13584                                          gpointer);
13585 void GtkWidget::drag-leave      (GtkWidget *,
13586                                  GdkDragContext *,
13587                                  gguint,
13588                                  gpointer);
13589 gboolean GtkWidget::drag-motion (GtkWidget *,
13590                                  GdkDragContext *,
13591                                  ggint,
13592                                  ggint,
13593                                  gguint,
13594                                  gpointer);
13595 gboolean GtkWidget::drag-drop   (GtkWidget *,
13596                                  GdkDragContext *,
13597                                  ggint,
13598                                  ggint,
13599                                  gguint,
13600                                  gpointer);
13601 void GtkWidget::drag-data-get   (GtkWidget *,
13602                                  GdkDragContext *,
13603                                  GtkSelectionData *,
13604                                  gguint,
13605                                  gguint,
13606                                  gpointer);
13607 void GtkWidget::drag-data-received      (GtkWidget *,
13608                                          GdkDragContext *,
13609                                          ggint,
13610                                          ggint,
13611                                          GtkSelectionData *,
13612                                          gguint,
13613                                          gguint,
13614                                          gpointer);
13615 gboolean GtkWidget::client-event        (GtkWidget *,
13616                                          GdkEvent *,
13617                                          gpointer);
13618 gboolean GtkWidget::no-expose-event     (GtkWidget *,
13619                                          GdkEvent *,
13620                                          gpointer);
13621 gboolean GtkWidget::visibility-notify-event     (GtkWidget *,
13622                                                  GdkEvent *,
13623                                                  gpointer);
13624 void GtkWidget::debug-msg       (GtkWidget *,
13625                                  GtkString *,
13626                                  gpointer);
13627 </programlisting>
13628
13629 </sect1>
13630
13631 <!-- ----------------------------------------------------------------- -->
13632 <sect1 id="sec-GtkData">
13633 <title>GtkData</title>
13634
13635 <programlisting role="C">
13636 void GtkData::disconnect        (GtkData *,
13637                                  gpointer);
13638 </programlisting>
13639
13640 </sect1>
13641
13642 <!-- ----------------------------------------------------------------- -->
13643 <sect1 id="sec-GtkContainer">
13644 <title>GtkContainer</title>
13645
13646 <programlisting role="C">
13647 void GtkContainer::add  (GtkContainer *,
13648                          GtkWidget *,
13649                          gpointer);
13650 void GtkContainer::remove       (GtkContainer *,
13651                                  GtkWidget *,
13652                                  gpointer);
13653 void GtkContainer::check-resize (GtkContainer *,
13654                                  gpointer);
13655 GtkDirectionType GtkContainer::focus    (GtkContainer *,
13656                                          GtkDirectionType,
13657                                          gpointer);
13658 void GtkContainer::set-focus-child      (GtkContainer *,
13659                                          GtkWidget *,
13660                                          gpointer);
13661 </programlisting>
13662
13663 </sect1>
13664
13665 <!-- ----------------------------------------------------------------- -->
13666 <sect1 id="sec-GtkCalendar">
13667 <title>GtkCalendar</title>
13668
13669 <programlisting role="C">
13670 void GtkCalendar::month-changed (GtkCalendar *,
13671                                  gpointer);
13672 void GtkCalendar::day-selected  (GtkCalendar *,
13673                                  gpointer);
13674 void GtkCalendar::day-selected-double-click     (GtkCalendar *,
13675                                                  gpointer);
13676 void GtkCalendar::prev-month    (GtkCalendar *,
13677                                  gpointer);
13678 void GtkCalendar::next-month    (GtkCalendar *,
13679                                  gpointer);
13680 void GtkCalendar::prev-year     (GtkCalendar *,
13681                                  gpointer);
13682 void GtkCalendar::next-year     (GtkCalendar *,
13683                                  gpointer);
13684 </programlisting>
13685
13686 </sect1>
13687
13688 <!-- ----------------------------------------------------------------- -->
13689 <sect1 id="sec-GtkEditable">
13690 <title>GtkEditable</title>
13691
13692 <programlisting role="C">
13693 void GtkEditable::changed       (GtkEditable *,
13694                                  gpointer);
13695 void GtkEditable::insert-text   (GtkEditable *,
13696                                  GtkString *,
13697                                  ggint,
13698                                  ggpointer,
13699                                  gpointer);
13700 void GtkEditable::delete-text   (GtkEditable *,
13701                                  ggint,
13702                                  ggint,
13703                                  gpointer);
13704 void GtkEditable::activate      (GtkEditable *,
13705                                  gpointer);
13706 void GtkEditable::set-editable  (GtkEditable *,
13707                                  gboolean,
13708                                  gpointer);
13709 void GtkEditable::move-cursor   (GtkEditable *,
13710                                  ggint,
13711                                  ggint,
13712                                  gpointer);
13713 void GtkEditable::move-word     (GtkEditable *,
13714                                  ggint,
13715                                  gpointer);
13716 void GtkEditable::move-page     (GtkEditable *,
13717                                  ggint,
13718                                  ggint,
13719                                  gpointer);
13720 void GtkEditable::move-to-row   (GtkEditable *,
13721                                  ggint,
13722                                  gpointer);
13723 void GtkEditable::move-to-column        (GtkEditable *,
13724                                          ggint,
13725                                          gpointer);
13726 void GtkEditable::kill-char     (GtkEditable *,
13727                                  ggint,
13728                                  gpointer);
13729 void GtkEditable::kill-word     (GtkEditable *,
13730                                  ggint,
13731                                  gpointer);
13732 void GtkEditable::kill-line     (GtkEditable *,
13733                                  ggint,
13734                                  gpointer);
13735 void GtkEditable::cut-clipboard (GtkEditable *,
13736                                  gpointer);
13737 void GtkEditable::copy-clipboard        (GtkEditable *,
13738                                          gpointer);
13739 void GtkEditable::paste-clipboard       (GtkEditable *,
13740                                          gpointer);
13741 </programlisting>
13742
13743 </sect1>
13744
13745 <!-- ----------------------------------------------------------------- -->
13746 <sect1 id="sec-GtkNotebook">
13747 <title>GtkNotebook</title>
13748
13749 <programlisting role="C">
13750 void GtkNotebook::switch-page   (GtkNotebook *,
13751                                  ggpointer,
13752                                  gguint,
13753                                  gpointer);
13754 </programlisting>
13755
13756 </sect1>
13757
13758 <!-- ----------------------------------------------------------------- -->
13759 <sect1 id="sec-GtkList">
13760 <title>GtkList</title>
13761
13762 <programlisting role="C">
13763 void GtkList::selection-changed (GtkList *,
13764                                  gpointer);
13765 void GtkList::select-child      (GtkList *,
13766                                  GtkWidget *,
13767                                  gpointer);
13768 void GtkList::unselect-child    (GtkList *,
13769                                  GtkWidget *,
13770                                  gpointer);
13771 </programlisting>
13772
13773 </sect1>
13774
13775 <!-- ----------------------------------------------------------------- -->
13776 <sect1 id="sec-GtkMenuShell">
13777 <title>GtkMenuShell</title>
13778
13779 <programlisting role="C">
13780 void GtkMenuShell::deactivate   (GtkMenuShell *,
13781                                  gpointer);
13782 void GtkMenuShell::selection-done       (GtkMenuShell *,
13783                                          gpointer);
13784 void GtkMenuShell::move-current (GtkMenuShell *,
13785                                  GtkMenuDirectionType,
13786                                  gpointer);
13787 void GtkMenuShell::activate-current     (GtkMenuShell *,
13788                                          gboolean,
13789                                          gpointer);
13790 void GtkMenuShell::cancel       (GtkMenuShell *,
13791                                  gpointer);
13792 </programlisting>
13793
13794 </sect1>
13795
13796 <!-- ----------------------------------------------------------------- -->
13797 <sect1 id="sec-GtkToolbar">
13798 <title>GtkToolbar</title>
13799
13800 <programlisting role="C">
13801 void GtkToolbar::orientation-changed    (GtkToolbar *,
13802                                          ggint,
13803                                          gpointer);
13804 void GtkToolbar::style-changed  (GtkToolbar *,
13805                                  ggint,
13806                                  gpointer);
13807 </programlisting>
13808
13809 </sect1>
13810
13811 <!-- ----------------------------------------------------------------- -->
13812 <sect1 id="sec-GtkButton">
13813 <title>GtkButton</title>
13814
13815 <programlisting role="C">
13816 void GtkButton::pressed (GtkButton *,
13817                          gpointer);
13818 void GtkButton::released        (GtkButton *,
13819                                  gpointer);
13820 void GtkButton::clicked (GtkButton *,
13821                          gpointer);
13822 void GtkButton::enter   (GtkButton *,
13823                          gpointer);
13824 void GtkButton::leave   (GtkButton *,
13825                          gpointer);
13826 </programlisting>
13827
13828 </sect1>
13829
13830 <!-- ----------------------------------------------------------------- -->
13831 <sect1 id="sec-GtkItem">
13832 <title>GtkItem</title>
13833
13834 <programlisting role="C">
13835 void GtkItem::select    (GtkItem *,
13836                          gpointer);
13837 void GtkItem::deselect  (GtkItem *,
13838                          gpointer);
13839 void GtkItem::toggle    (GtkItem *,
13840                          gpointer);
13841 </programlisting>
13842
13843 </sect1>
13844
13845 <!-- ----------------------------------------------------------------- -->
13846 <sect1 id="sec-GtkWindow">
13847 <title>GtkWindow</title>
13848
13849 <programlisting role="C">
13850 void GtkWindow::set-focus       (GtkWindow *,
13851                                  ggpointer,
13852                                  gpointer);
13853 </programlisting>
13854
13855 </sect1>
13856
13857 <!-- ----------------------------------------------------------------- -->
13858 <sect1 id="sec-GtkHandleBox">
13859 <title>GtkHandleBox</title>
13860
13861 <programlisting role="C">
13862 void GtkHandleBox::child-attached       (GtkHandleBox *,
13863                                          GtkWidget *,
13864                                          gpointer);
13865 void GtkHandleBox::child-detached       (GtkHandleBox *,
13866                                          GtkWidget *,
13867                                          gpointer);
13868 </programlisting>
13869
13870 </sect1>
13871
13872 <!-- ----------------------------------------------------------------- -->
13873 <sect1 id="sec-GtkToggleButton">
13874 <title>GtkToggleButton</title>
13875
13876 <programlisting role="C">
13877 void GtkToggleButton::toggled   (GtkToggleButton *,
13878                                  gpointer);
13879 </programlisting>
13880
13881 </sect1>
13882
13883 <!-- ----------------------------------------------------------------- -->
13884 <sect1 id="sec-GtkMenuItem">
13885 <title>GtkMenuItem</title>
13886
13887 <programlisting role="C">
13888 void GtkMenuItem::activate      (GtkMenuItem *,
13889                                  gpointer);
13890 void GtkMenuItem::activate-item (GtkMenuItem *,
13891                                  gpointer);
13892 </programlisting>
13893
13894 </sect1>
13895
13896 <!-- ----------------------------------------------------------------- -->
13897 <sect1 id="sec-GtkCheckMenuItem">
13898 <title>GtkCheckMenuItem</title>
13899
13900 <programlisting role="C">
13901 void GtkCheckMenuItem::toggled  (GtkCheckMenuItem *,
13902                                  gpointer);
13903 </programlisting>
13904
13905 </sect1>
13906
13907 <!-- ----------------------------------------------------------------- -->
13908 <sect1 id="sec-GtkInputDialog">
13909 <title>GtkInputDialog</title>
13910
13911 <programlisting role="C">
13912 void GtkInputDialog::enable-device      (GtkInputDialog *,
13913                                          ggint,
13914                                          gpointer);
13915 void GtkInputDialog::disable-device     (GtkInputDialog *,
13916                                          ggint,
13917                                          gpointer);
13918 </programlisting>
13919
13920 </sect1>
13921
13922 <!-- ----------------------------------------------------------------- -->
13923 <sect1 id="sec-GtkColorSelection">
13924 <title>GtkColorSelection</title>
13925
13926 <programlisting role="C">
13927 void GtkColorSelection::color-changed   (GtkColorSelection *,
13928                                          gpointer);
13929 </programlisting>
13930
13931 </sect1>
13932
13933 <!-- ----------------------------------------------------------------- -->
13934 <sect1 id="sec-GtkStatusBar">
13935 <title>GtkStatusBar</title>
13936
13937 <programlisting role="C">
13938 void GtkStatusbar::text-pushed  (GtkStatusbar *,
13939                                  gguint,
13940                                  GtkString *,
13941                                  gpointer);
13942 void GtkStatusbar::text-popped  (GtkStatusbar *,
13943                                  gguint,
13944                                  GtkString *,
13945                                  gpointer);
13946 </programlisting>
13947
13948 </sect1>
13949
13950 <!-- ----------------------------------------------------------------- -->
13951 <sect1 id="sec-GtkAdjustment">
13952 <title>GtkAdjustment</title>
13953
13954 <programlisting role="C">
13955 void GtkAdjustment::changed     (GtkAdjustment *,
13956                                  gpointer);
13957 void GtkAdjustment::value-changed       (GtkAdjustment *,
13958                                          gpointer);
13959 </programlisting>
13960
13961 </sect1>
13962 </appendix>
13963
13964 <!-- ***************************************************************** -->
13965 <appendix id="app-GDKEventTypes">
13966 <title>GDK Event Types</title>
13967
13968 <para>The following data types are passed into event handlers by GTK+. For
13969 each data type listed, the signals that use this data type are listed.</para>
13970
13971 <itemizedlist>
13972 <listitem><simpara>  GdkEvent</simpara>
13973           <itemizedlist>
13974           <listitem><simpara>drag_end_event</simpara>
13975           </listitem>
13976           </itemizedlist>
13977 </listitem>
13978
13979 <listitem><simpara>  GdkEventType<</simpara>
13980 </listitem>
13981
13982 <listitem><simpara>  GdkEventAny</simpara>
13983           <itemizedlist>
13984           <listitem><simpara>delete_event</simpara>
13985           </listitem>
13986           <listitem><simpara>destroy_event</simpara>
13987           </listitem>
13988           <listitem><simpara>map_event</simpara>
13989           </listitem>
13990           <listitem><simpara>unmap_event</simpara>
13991           </listitem>
13992           <listitem><simpara>no_expose_event</simpara>
13993           </listitem>
13994           </itemizedlist>
13995 </listitem>
13996
13997 <listitem><simpara>  GdkEventExpose</simpara>
13998           <itemizedlist>
13999           <listitem><simpara>expose_event</simpara>
14000           </listitem>
14001           </itemizedlist>
14002 </listitem>
14003
14004 <listitem><simpara>  GdkEventNoExpose</simpara>
14005 </listitem>
14006
14007 <listitem><simpara>  GdkEventVisibility</simpara>
14008 </listitem>
14009
14010 <listitem><simpara>  GdkEventMotion</simpara>
14011           <itemizedlist>
14012           <listitem><simpara>motion_notify_event</simpara>
14013           </listitem>
14014           </itemizedlist>
14015 </listitem>
14016 <listitem><simpara>  GdkEventButton</simpara>
14017           <itemizedlist>
14018           <listitem><simpara>button_press_event</simpara>
14019           </listitem>
14020           <listitem><simpara>button_release_event</simpara>
14021           </listitem>
14022           </itemizedlist>
14023 </listitem>
14024
14025 <listitem><simpara>  GdkEventKey</simpara>
14026           <itemizedlist>
14027           <listitem><simpara>key_press_event</simpara>
14028           </listitem>
14029           <listitem><simpara>key_release_event</simpara>
14030           </listitem>
14031           </itemizedlist>
14032 </listitem>
14033
14034 <listitem><simpara>  GdkEventCrossing</simpara>
14035           <itemizedlist>
14036           <listitem><simpara>enter_notify_event</simpara>
14037           </listitem>
14038           <listitem><simpara>leave_notify_event</simpara>
14039           </listitem>
14040           </itemizedlist>
14041 </listitem>
14042
14043 <listitem><simpara>  GdkEventFocus</simpara>
14044           <itemizedlist>
14045           <listitem><simpara>focus_in_event</simpara>
14046           </listitem>
14047           <listitem><simpara>focus_out_event</simpara>
14048           </listitem>
14049           </itemizedlist>
14050 </listitem>
14051
14052 <listitem><simpara>  GdkEventConfigure</simpara>
14053           <itemizedlist>
14054           <listitem><simpara>configure_event</simpara>
14055           </listitem>
14056           </itemizedlist>
14057 </listitem>
14058
14059 <listitem><simpara>  GdkEventProperty</simpara>
14060           <itemizedlist>
14061           <listitem><simpara>property_notify_event</simpara>
14062           </listitem>
14063           </itemizedlist>
14064 </listitem>
14065
14066 <listitem><simpara>  GdkEventSelection</simpara>
14067           <itemizedlist>
14068           <listitem><simpara>selection_clear_event</simpara>
14069           </listitem>
14070           <listitem><simpara>selection_request_event</simpara>
14071           </listitem>
14072           <listitem><simpara>selection_notify_event</simpara>
14073           </listitem>
14074           </itemizedlist>
14075 </listitem>
14076
14077 <listitem><simpara>  GdkEventProximity</simpara>
14078           <itemizedlist>
14079           <listitem><simpara>proximity_in_event</simpara>
14080           </listitem>
14081           <listitem><simpara>proximity_out_event</simpara>
14082           </listitem>
14083           </itemizedlist>
14084 </listitem>
14085
14086 <listitem><simpara>  GdkEventDragBegin</simpara>
14087           <itemizedlist>
14088           <listitem><simpara>drag_begin_event</simpara>
14089           </listitem>
14090           </itemizedlist>
14091 </listitem>
14092
14093 <listitem><simpara>  GdkEventDragRequest</simpara>
14094           <itemizedlist>
14095           <listitem><simpara>drag_request_event</simpara>
14096           </listitem>
14097           </itemizedlist>
14098 </listitem>
14099
14100 <listitem><simpara>  GdkEventDropEnter</simpara>
14101           <itemizedlist>
14102           <listitem><simpara>drop_enter_event</simpara>
14103           </listitem>
14104           </itemizedlist>
14105 </listitem>
14106
14107 <listitem><simpara>  GdkEventDropLeave</simpara>
14108           <itemizedlist>
14109           <listitem><simpara>drop_leave_event</simpara>
14110           </listitem>
14111           </itemizedlist>
14112 </listitem>
14113
14114 <listitem><simpara>  GdkEventDropDataAvailable</simpara>
14115           <itemizedlist>
14116           <listitem><simpara>drop_data_available_event</simpara>
14117           </listitem>
14118           </itemizedlist>
14119 </listitem>
14120
14121 <listitem><simpara>  GdkEventClient</simpara>
14122           <itemizedlist>
14123           <listitem><simpara>client_event</simpara>
14124           </listitem>
14125           </itemizedlist>
14126 </listitem>
14127
14128 <listitem><simpara>  GdkEventOther</simpara>
14129           <itemizedlist>
14130           <listitem><simpara>other_event</simpara>
14131           </listitem>
14132           </itemizedlist>
14133 </listitem>
14134 </itemizedlist>
14135
14136 <para>The data type <literal>GdkEventType</literal> is a special data type that is used by
14137 all the other data types as an indicator of the data type being passed
14138 to the signal handler. As you will see below, each of the event data
14139 structures has a member of this type. It is defined as an enumeration
14140 type as follows:</para>
14141
14142 <programlisting role="C">
14143 typedef enum
14144 {
14145   GDK_NOTHING           = -1,
14146   GDK_DELETE            = 0,
14147   GDK_DESTROY           = 1,
14148   GDK_EXPOSE            = 2,
14149   GDK_MOTION_NOTIFY     = 3,
14150   GDK_BUTTON_PRESS      = 4,
14151   GDK_2BUTTON_PRESS     = 5,
14152   GDK_3BUTTON_PRESS     = 6,
14153   GDK_BUTTON_RELEASE    = 7,
14154   GDK_KEY_PRESS         = 8,
14155   GDK_KEY_RELEASE       = 9,
14156   GDK_ENTER_NOTIFY      = 10,
14157   GDK_LEAVE_NOTIFY      = 11,
14158   GDK_FOCUS_CHANGE      = 12,
14159   GDK_CONFIGURE         = 13,
14160   GDK_MAP               = 14,
14161   GDK_UNMAP             = 15,
14162   GDK_PROPERTY_NOTIFY   = 16,
14163   GDK_SELECTION_CLEAR   = 17,
14164   GDK_SELECTION_REQUEST = 18,
14165   GDK_SELECTION_NOTIFY  = 19,
14166   GDK_PROXIMITY_IN      = 20,
14167   GDK_PROXIMITY_OUT     = 21,
14168   GDK_DRAG_BEGIN        = 22,
14169   GDK_DRAG_REQUEST      = 23,
14170   GDK_DROP_ENTER        = 24,
14171   GDK_DROP_LEAVE        = 25,
14172   GDK_DROP_DATA_AVAIL   = 26,
14173   GDK_CLIENT_EVENT      = 27,
14174   GDK_VISIBILITY_NOTIFY = 28,
14175   GDK_NO_EXPOSE         = 29,
14176   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
14177 } GdkEventType;
14178 </programlisting>
14179
14180 <para>The other event type that is different from the others is
14181 <literal>GdkEvent</literal> itself. This is a union of all the other
14182 data types, which allows it to be cast to a specific
14183 event data type within a signal handler.</para>
14184
14185 <!-- Just a big list for now, needs expanding upon - TRG -->
14186 <para>So, the event data types are defined as follows:</para>
14187
14188 <programlisting role="C">
14189 struct _GdkEventAny
14190 {
14191   GdkEventType type;
14192   GdkWindow *window;
14193   gint8 send_event;
14194 };
14195
14196 struct _GdkEventExpose
14197 {
14198   GdkEventType type;
14199   GdkWindow *window;
14200   gint8 send_event;
14201   GdkRectangle area;
14202   gint count; /* If non-zero, how many more events follow. */
14203 };
14204
14205 struct _GdkEventNoExpose
14206 {
14207   GdkEventType type;
14208   GdkWindow *window;
14209   gint8 send_event;
14210   /* XXX: does anyone need the X major_code or minor_code fields? */
14211 };
14212
14213 struct _GdkEventVisibility
14214 {
14215   GdkEventType type;
14216   GdkWindow *window;
14217   gint8 send_event;
14218   GdkVisibilityState state;
14219 };
14220
14221 struct _GdkEventMotion
14222 {
14223   GdkEventType type;
14224   GdkWindow *window;
14225   gint8 send_event;
14226   guint32 time;
14227   gdouble x;
14228   gdouble y;
14229   gdouble pressure;
14230   gdouble xtilt;
14231   gdouble ytilt;
14232   guint state;
14233   gint16 is_hint;
14234   GdkInputSource source;
14235   guint32 deviceid;
14236   gdouble x_root, y_root;
14237 };
14238
14239 struct _GdkEventButton
14240 {
14241   GdkEventType type;
14242   GdkWindow *window;
14243   gint8 send_event;
14244   guint32 time;
14245   gdouble x;
14246   gdouble y;
14247   gdouble pressure;
14248   gdouble xtilt;
14249   gdouble ytilt;
14250   guint state;
14251   guint button;
14252   GdkInputSource source;
14253   guint32 deviceid;
14254   gdouble x_root, y_root;
14255 };
14256
14257 struct _GdkEventKey
14258 {
14259   GdkEventType type;
14260   GdkWindow *window;
14261   gint8 send_event;
14262   guint32 time;
14263   guint state;
14264   guint keyval;
14265   gint length;
14266   gchar *string;
14267 };
14268
14269 struct _GdkEventCrossing
14270 {
14271   GdkEventType type;
14272   GdkWindow *window;
14273   gint8 send_event;
14274   GdkWindow *subwindow;
14275   GdkNotifyType detail;
14276 };
14277
14278 struct _GdkEventFocus
14279 {
14280   GdkEventType type;
14281   GdkWindow *window;
14282   gint8 send_event;
14283   gint16 in;
14284 };
14285
14286 struct _GdkEventConfigure
14287 {
14288   GdkEventType type;
14289   GdkWindow *window;
14290   gint8 send_event;
14291   gint16 x, y;
14292   gint16 width;
14293   gint16 height;
14294 };
14295
14296 struct _GdkEventProperty
14297 {
14298   GdkEventType type;
14299   GdkWindow *window;
14300   gint8 send_event;
14301   GdkAtom atom;
14302   guint32 time;
14303   guint state;
14304 };
14305
14306 struct _GdkEventSelection
14307 {
14308   GdkEventType type;
14309   GdkWindow *window;
14310   gint8 send_event;
14311   GdkAtom selection;
14312   GdkAtom target;
14313   GdkAtom property;
14314   guint32 requestor;
14315   guint32 time;
14316 };
14317
14318 /* This event type will be used pretty rarely. It only is important
14319    for XInput aware programs that are drawing their own cursor */
14320
14321 struct _GdkEventProximity
14322 {
14323   GdkEventType type;
14324   GdkWindow *window;
14325   gint8 send_event;
14326   guint32 time;
14327   GdkInputSource source;
14328   guint32 deviceid;
14329 };
14330
14331 struct _GdkEventDragRequest
14332 {
14333   GdkEventType type;
14334   GdkWindow *window;
14335   gint8 send_event;
14336   guint32 requestor;
14337   union {
14338     struct {
14339       guint protocol_version:4;
14340       guint sendreply:1;
14341       guint willaccept:1;
14342       guint delete_data:1; /* Do *not* delete if link is sent, only
14343                               if data is sent */
14344       guint senddata:1;
14345       guint reserved:22;
14346     } flags;
14347     glong allflags;
14348   } u;
14349   guint8 isdrop; /* This gdk event can be generated by a couple of
14350                     X events - this lets the app know whether the
14351                     drop really occurred or we just set the data */
14352
14353   GdkPoint drop_coords;
14354   gchar *data_type;
14355   guint32 timestamp;
14356 };
14357
14358 struct _GdkEventDragBegin
14359 {
14360   GdkEventType type;
14361   GdkWindow *window;
14362   gint8 send_event;
14363   union {
14364     struct {
14365       guint protocol_version:4;
14366       guint reserved:28;
14367     } flags;
14368     glong allflags;
14369   } u;
14370 };
14371
14372 struct _GdkEventDropEnter
14373 {
14374   GdkEventType type;
14375   GdkWindow *window;
14376   gint8 send_event;
14377   guint32 requestor;
14378   union {
14379     struct {
14380       guint protocol_version:4;
14381       guint sendreply:1;
14382       guint extended_typelist:1;
14383       guint reserved:26;
14384     } flags;
14385     glong allflags;
14386   } u;
14387 };
14388
14389 struct _GdkEventDropLeave
14390 {
14391   GdkEventType type;
14392   GdkWindow *window;
14393   gint8 send_event;
14394   guint32 requestor;
14395   union {
14396     struct {
14397       guint protocol_version:4;
14398       guint reserved:28;
14399     } flags;
14400     glong allflags;
14401   } u;
14402 };
14403
14404 struct _GdkEventDropDataAvailable
14405 {
14406   GdkEventType type;
14407   GdkWindow *window;
14408   gint8 send_event;
14409   guint32 requestor;
14410   union {
14411     struct {
14412       guint protocol_version:4;
14413       guint isdrop:1;
14414       guint reserved:25;
14415     } flags;
14416     glong allflags;
14417   } u;
14418   gchar *data_type; /* MIME type */
14419   gulong data_numbytes;
14420   gpointer data;
14421   guint32 timestamp;
14422   GdkPoint coords;
14423 };
14424
14425 struct _GdkEventClient
14426 {
14427   GdkEventType type;
14428   GdkWindow *window;
14429   gint8 send_event;
14430   GdkAtom message_type;
14431   gushort data_format;
14432   union {
14433     char b[20];
14434     short s[10];
14435     long l[5];
14436   } data;
14437 };
14438
14439 struct _GdkEventOther
14440 {
14441   GdkEventType type;
14442   GdkWindow *window;
14443   gint8 send_event;
14444   GdkXEvent *xevent;
14445 };
14446 </programlisting>
14447
14448 </appendix>
14449
14450 <!-- ***************************************************************** -->
14451 <appendix id="app-CodeExamples">
14452 <title>Code Examples</title>
14453
14454 <para>Below are the code examples that are used in the above text
14455 which are not included in complete form elsewhere.</para>
14456
14457 <!-- ----------------------------------------------------------------- -->
14458 <sect1 id="sec-Tictactoe">
14459 <title>Tictactoe</title>
14460 <!-- ----------------------------------------------------------------- -->
14461 <sect2>
14462 <title>tictactoe.h</title>
14463
14464 <programlisting role="C">
14465 <!-- example-start tictactoe tictactoe.h -->
14466 /* GTK - The GIMP Toolkit
14467  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14468  *
14469  * This library is free software; you can redistribute it and/or
14470  * modify it under the terms of the GNU Library General Public
14471  * License as published by the Free Software Foundation; either
14472  * version 2 of the License, or (at your option) any later version.
14473  *
14474  * This library is distributed in the hope that it will be useful,
14475  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14476  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14477  * Library General Public License for more details.
14478  *
14479  * You should have received a copy of the GNU Library General Public
14480  * License along with this library; if not, write to the
14481  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14482  * Boston, MA 02111-1307, USA.
14483  */
14484 #ifndef __TICTACTOE_H__
14485 #define __TICTACTOE_H__
14486
14487
14488 #include &lt;glib.h&gt;
14489 #include &lt;glib-object.h&gt;
14490 #include &lt;gtk/gtktable.h&gt;
14491
14492
14493 G_BEGIN_DECLS
14494
14495 #define TICTACTOE_TYPE            (tictactoe_get_type ())
14496 #define TICTACTOE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), TICTACTOE_TYPE, Tictactoe))
14497 #define TICTACTOE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), TICTACTOE_TYPE, TictactoeClass))
14498 #define IS_TICTACTOE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TICTACTOE_TYPE))
14499 #define IS_TICTACTOE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TICTACTOE_TYPE))
14500
14501
14502 typedef struct _Tictactoe       Tictactoe;
14503 typedef struct _TictactoeClass  TictactoeClass;
14504
14505 struct _Tictactoe
14506 {
14507   GtkTable table;
14508   
14509   GtkWidget *buttons[3][3];
14510 };
14511
14512 struct _TictactoeClass
14513 {
14514   GtkTableClass parent_class;
14515
14516   void (* tictactoe) (Tictactoe *ttt);
14517 };
14518
14519 GType          tictactoe_get_type        (void);
14520 GtkWidget*     tictactoe_new             (void);
14521 void           tictactoe_clear           (Tictactoe *ttt);
14522
14523 G_END_DECLS
14524
14525 #endif /* __TICTACTOE_H__ */
14526
14527 <!-- example-end -->
14528 </programlisting>
14529
14530 </sect2>
14531
14532 <!-- ----------------------------------------------------------------- -->
14533 <sect2>
14534 <title>tictactoe.c</title>
14535
14536 <programlisting role="C">
14537 <!-- example-start tictactoe tictactoe.c -->
14538
14539 /* GTK - The GIMP Toolkit
14540  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14541  *
14542  * This library is free software; you can redistribute it and/or
14543  * modify it under the terms of the GNU Library General Public
14544  * License as published by the Free Software Foundation; either
14545  * version 2 of the License, or (at your option) any later version.
14546  *
14547  * This library is distributed in the hope that it will be useful,
14548  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14549  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14550  * Library General Public License for more details.
14551  *
14552  * You should have received a copy of the GNU Library General Public
14553  * License along with this library; if not, write to the
14554  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14555  * Boston, MA 02111-1307, USA.
14556  */
14557 #include &lt;gtk/gtksignal.h&gt;
14558 #include &lt;gtk/gtktable.h&gt;
14559 #include &lt;gtk/gtktogglebutton.h&gt;
14560 #include "tictactoe.h"
14561
14562 enum {
14563   TICTACTOE_SIGNAL,
14564   LAST_SIGNAL
14565 };
14566
14567 static void tictactoe_class_init          (TictactoeClass *klass);
14568 static void tictactoe_init                (Tictactoe      *ttt);
14569 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
14570
14571 static guint tictactoe_signals[LAST_SIGNAL] = { 0 };
14572
14573 GType
14574 tictactoe_get_type (void)
14575 {
14576   static GType ttt_type = 0;
14577
14578   if (!ttt_type)
14579     {
14580       const GTypeInfo ttt_info =
14581       {
14582         sizeof (TictactoeClass),
14583         NULL, /* base_init */
14584         NULL, /* base_finalize */
14585         (GClassInitFunc) tictactoe_class_init,
14586         NULL, /* class_finalize */
14587         NULL, /* class_data */
14588         sizeof (Tictactoe),
14589         0,
14590         (GInstanceInitFunc) tictactoe_init,
14591       };
14592
14593       ttt_type = g_type_register_static (GTK_TYPE_TABLE, "Tictactoe", &amp;ttt_info, 0);
14594     }
14595
14596   return ttt_type;
14597 }
14598
14599 static void
14600 tictactoe_class_init (TictactoeClass *klass)
14601 {
14602   
14603   tictactoe_signals[TICTACTOE_SIGNAL] = g_signal_new ("tictactoe",
14604                                          G_TYPE_FROM_CLASS (klass),
14605                                          G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
14606                                          G_STRUCT_OFFSET (TictactoeClass, tictactoe),
14607                                          NULL, 
14608                                          NULL,                
14609                                          g_cclosure_marshal_VOID__VOID,
14610                                          G_TYPE_NONE, 0);
14611
14612
14613 }
14614
14615 static void
14616 tictactoe_init (Tictactoe *ttt)
14617 {
14618   gint i,j;
14619   
14620   gtk_table_resize (GTK_TABLE (ttt), 3, 3);
14621   gtk_table_set_homogeneous (GTK_TABLE (ttt), TRUE);
14622
14623   for (i=0;i&lt;3; i++)
14624     for (j=0;j&lt;3; j++)      {
14625         ttt-&gt;buttons[i][j] = gtk_toggle_button_new ();
14626         gtk_table_attach_defaults (GTK_TABLE (ttt), ttt-&gt;buttons[i][j], 
14627                                    i, i+1, j, j+1);
14628         g_signal_connect (ttt-&gt;buttons[i][j], "toggled",
14629                           G_CALLBACK (tictactoe_toggle), (gpointer) ttt);
14630         gtk_widget_set_size_request (ttt-&gt;buttons[i][j], 20, 20);
14631         gtk_widget_show (ttt-&gt;buttons[i][j]);
14632       }
14633 }
14634
14635 GtkWidget*
14636 tictactoe_new ()
14637 {
14638   return GTK_WIDGET (g_object_new (tictactoe_get_type (), NULL));
14639 }
14640
14641 void           
14642 tictactoe_clear (Tictactoe *ttt)
14643 {
14644   int i,j;
14645
14646   for (i = 0; i&lt;3; i++)
14647     for (j = 0; j&lt;3; j++)
14648       {
14649         g_signal_handlers_block_matched (G_OBJECT (ttt-&gt;buttons[i][j]), 
14650                                          G_SIGNAL_MATCH_DATA,
14651                                          0, 0, NULL, NULL, ttt);
14652         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt-&gt;buttons[i][j]),
14653                                       FALSE);
14654         g_signal_handlers_unblock_matched (G_OBJECT (ttt->buttons[i][j]),
14655                                            G_SIGNAL_MATCH_DATA,
14656                                            0, 0, NULL, NULL, ttt);
14657       }
14658 }
14659
14660 static void
14661 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
14662 {
14663   int i,k;
14664
14665   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
14666                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
14667                              { 0, 1, 2 }, { 0, 1, 2 } };
14668   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
14669                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
14670                              { 0, 1, 2 }, { 2, 1, 0 } };
14671
14672   int success, found;
14673
14674   for (k = 0; k&lt;8; k++)
14675     {
14676       success = TRUE;
14677       found = FALSE;
14678
14679       for (i = 0; i&lt;3; i++)
14680         {
14681           success = success &amp;&amp; 
14682             GTK_TOGGLE_BUTTON (ttt-&gt;buttons[rwins[k][i]][cwins[k][i]])-&gt;active;
14683           found = found ||
14684             ttt-&gt;buttons[rwins[k][i]][cwins[k][i]] == widget;
14685         }
14686       
14687       if (success &amp;&amp; found)
14688         {
14689           g_signal_emit (ttt, 
14690                          tictactoe_signals[TICTACTOE_SIGNAL], 0);
14691           break;
14692         }
14693     }
14694 }
14695
14696 <!-- example-end -->
14697 </programlisting>
14698
14699 </sect2>
14700
14701 <!-- ----------------------------------------------------------------- -->
14702 <sect2>
14703 <title>ttt_test.c</title>
14704
14705 <programlisting role="C">
14706 <!-- example-start tictactoe ttt_test.c -->
14707
14708 #include &lt;stdlib.h&gt;
14709 #include &lt;gtk/gtk.h&gt;
14710 #include "tictactoe.h"
14711
14712 void win( GtkWidget *widget,
14713           gpointer   data )
14714 {
14715   g_print ("Yay!\n");
14716   tictactoe_clear (TICTACTOE (widget));
14717 }
14718
14719 int main( int   argc,
14720           char *argv[] )
14721 {
14722   GtkWidget *window;
14723   GtkWidget *ttt;
14724   
14725   gtk_init (&amp;argc, &amp;argv);
14726
14727   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
14728   
14729   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
14730   
14731   g_signal_connect (window, "destroy",
14732                     G_CALLBACK (exit), NULL);
14733   
14734   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
14735
14736   ttt = tictactoe_new ();
14737   
14738   gtk_container_add (GTK_CONTAINER (window), ttt);
14739   gtk_widget_show (ttt);
14740
14741   /* And attach to its "tictactoe" signal */
14742   g_signal_connect (ttt, "tictactoe",
14743                     G_CALLBACK (win), NULL);
14744
14745   gtk_widget_show (window);
14746   
14747   gtk_main ();
14748   
14749   return 0;
14750 }
14751
14752 <!-- example-end -->
14753 </programlisting>
14754
14755 </sect2>
14756 </sect1>
14757
14758 <!-- ----------------------------------------------------------------- -->
14759 <sect1 id="sec-GtkDial">
14760 <title>GtkDial</title>
14761
14762 <!-- ----------------------------------------------------------------- -->
14763 <sect2>
14764 <title>gtkdial.h</title>
14765
14766 <programlisting role="C">
14767 <!-- example-start gtkdial gtkdial.h -->
14768
14769 /* GTK - The GIMP Toolkit
14770  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14771  *
14772  * This library is free software; you can redistribute it and/or
14773  * modify it under the terms of the GNU Library General Public
14774  * License as published by the Free Software Foundation; either
14775  * version 2 of the License, or (at your option) any later version.
14776  *
14777  * This library is distributed in the hope that it will be useful,
14778  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14779  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14780  * Library General Public License for more details.
14781  *
14782  * You should have received a copy of the GNU Library General Public
14783  * License along with this library; if not, write to the
14784  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14785  * Boston, MA 02111-1307, USA.
14786  */
14787 #ifndef __GTK_DIAL_H__
14788 #define __GTK_DIAL_H__
14789
14790
14791 #include &lt;gdk/gdk.h&gt;
14792 #include &lt;gtk/gtkadjustment.h&gt;
14793 #include &lt;gtk/gtkwidget.h&gt;
14794
14795
14796 #ifdef __cplusplus
14797 extern "C" {
14798 #endif /* __cplusplus */
14799
14800
14801 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
14802 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
14803 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
14804
14805
14806 typedef struct _GtkDial        GtkDial;
14807 typedef struct _GtkDialClass   GtkDialClass;
14808
14809 struct _GtkDial
14810 {
14811   GtkWidget widget;
14812
14813   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
14814   guint policy : 2;
14815
14816   /* Button currently pressed or 0 if none */
14817   guint8 button;
14818
14819   /* Dimensions of dial components */
14820   gint radius;
14821   gint pointer_width;
14822
14823   /* ID of update timer, or 0 if none */
14824   guint32 timer;
14825
14826   /* Current angle */
14827   gfloat angle;
14828   gfloat last_angle;
14829
14830   /* Old values from adjustment stored so we know when something changes */
14831   gfloat old_value;
14832   gfloat old_lower;
14833   gfloat old_upper;
14834
14835   /* The adjustment object that stores the data for this dial */
14836   GtkAdjustment *adjustment;
14837 };
14838
14839 struct _GtkDialClass
14840 {
14841   GtkWidgetClass parent_class;
14842 };
14843
14844
14845 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
14846 GtkType        gtk_dial_get_type               (void);
14847 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
14848 void           gtk_dial_set_update_policy      (GtkDial      *dial,
14849                                                 GtkUpdateType  policy);
14850
14851 void           gtk_dial_set_adjustment         (GtkDial      *dial,
14852                                                 GtkAdjustment *adjustment);
14853 #ifdef __cplusplus
14854 }
14855 #endif /* __cplusplus */
14856
14857
14858 #endif /* __GTK_DIAL_H__ */
14859 <!-- example-end -->
14860 </programlisting>
14861
14862 </sect2>
14863
14864 <!-- ----------------------------------------------------------------- -->
14865 <sect2>
14866 <title>gtkdial.c</title>
14867
14868 <programlisting role="C">
14869 <!-- example-start gtkdial gtkdial.c -->
14870
14871 /* GTK - The GIMP Toolkit
14872  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
14873  *
14874  * This library is free software; you can redistribute it and/or
14875  * modify it under the terms of the GNU Library General Public
14876  * License as published by the Free Software Foundation; either
14877  * version 2 of the License, or (at your option) any later version.
14878  *
14879  * This library is distributed in the hope that it will be useful,
14880  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14881  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14882  * Library General Public License for more details.
14883  *
14884  * You should have received a copy of the GNU Library General Public
14885  * License along with this library; if not, write to the
14886  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14887  * Boston, MA 02111-1307, USA.
14888  */
14889 #include &lt;math.h&gt;
14890 #include &lt;stdio.h&gt;
14891 #include &lt;gtk/gtkmain.h&gt;
14892 #include &lt;gtk/gtksignal.h&gt;
14893
14894 #include "gtkdial.h"
14895
14896 #define SCROLL_DELAY_LENGTH  300
14897 #define DIAL_DEFAULT_SIZE 100
14898
14899 /* Forward declarations */
14900
14901 static void gtk_dial_class_init               (GtkDialClass     *klass);
14902 static void gtk_dial_init                     (GtkDial          *dial);
14903 static void gtk_dial_destroy                  (GtkObject        *object);
14904 static void gtk_dial_realize                  (GtkWidget        *widget);
14905 static void gtk_dial_size_request             (GtkWidget        *widget,
14906                                                GtkRequisition   *requisition);
14907 static void gtk_dial_size_allocate            (GtkWidget        *widget,
14908                                                GtkAllocation    *allocation);
14909 static gboolean gtk_dial_expose               (GtkWidget        *widget,
14910                                                GdkEventExpose   *event);
14911 static gboolean gtk_dial_button_press         (GtkWidget        *widget,
14912                                                GdkEventButton   *event);
14913 static gboolean gtk_dial_button_release       (GtkWidget        *widget,
14914                                                GdkEventButton   *event);
14915 static gboolean gtk_dial_motion_notify        (GtkWidget        *widget,
14916                                                GdkEventMotion   *event);
14917 static gboolean gtk_dial_timer                (GtkDial          *dial);
14918
14919 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
14920 static void gtk_dial_update                   (GtkDial *dial);
14921 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
14922                                                 gpointer          data);
14923 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
14924                                                 gpointer          data);
14925
14926 /* Local data */
14927
14928 static GtkWidgetClass *parent_class = NULL;
14929
14930 GType
14931 gtk_dial_get_type ()
14932 {
14933   static GType dial_type = 0;
14934
14935   if (!dial_type)
14936     {
14937       const GTypeInfo dial_info =
14938       {
14939         sizeof (GtkDialClass),
14940         NULL,
14941         NULL,
14942         (GClassInitFunc) gtk_dial_class_init,
14943         NULL,
14944         NULL,
14945         sizeof (GtkDial),
14946         0,
14947         (GInstanceInitFunc) gtk_dial_init,
14948       };
14949
14950       dial_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkDial", &amp;dial_info, 0);
14951     }
14952
14953   return dial_type;
14954 }
14955
14956 static void
14957 gtk_dial_class_init (GtkDialClass *class)
14958 {
14959   GtkObjectClass *object_class;
14960   GtkWidgetClass *widget_class;
14961
14962   object_class = (GtkObjectClass*) class;
14963   widget_class = (GtkWidgetClass*) class;
14964
14965   parent_class = gtk_type_class (gtk_widget_get_type ());
14966
14967   object_class-&gt;destroy = gtk_dial_destroy;
14968
14969   widget_class-&gt;realize = gtk_dial_realize;
14970   widget_class-&gt;expose_event = gtk_dial_expose;
14971   widget_class-&gt;size_request = gtk_dial_size_request;
14972   widget_class-&gt;size_allocate = gtk_dial_size_allocate;
14973   widget_class-&gt;button_press_event = gtk_dial_button_press;
14974   widget_class-&gt;button_release_event = gtk_dial_button_release;
14975   widget_class-&gt;motion_notify_event = gtk_dial_motion_notify;
14976 }
14977
14978 static void
14979 gtk_dial_init (GtkDial *dial)
14980 {
14981   dial-&gt;button = 0;
14982   dial-&gt;policy = GTK_UPDATE_CONTINUOUS;
14983   dial-&gt;timer = 0;
14984   dial-&gt;radius = 0;
14985   dial-&gt;pointer_width = 0;
14986   dial-&gt;angle = 0.0;
14987   dial-&gt;old_value = 0.0;
14988   dial-&gt;old_lower = 0.0;
14989   dial-&gt;old_upper = 0.0;
14990   dial-&gt;adjustment = NULL;
14991 }
14992
14993 GtkWidget*
14994 gtk_dial_new (GtkAdjustment *adjustment)
14995 {
14996   GtkDial *dial;
14997
14998   dial = g_object_new (gtk_dial_get_type (), NULL);
14999
15000   if (!adjustment)
15001     adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
15002
15003   gtk_dial_set_adjustment (dial, adjustment);
15004
15005   return GTK_WIDGET (dial);
15006 }
15007
15008 static void
15009 gtk_dial_destroy (GtkObject *object)
15010 {
15011   GtkDial *dial;
15012
15013   g_return_if_fail (object != NULL);
15014   g_return_if_fail (GTK_IS_DIAL (object));
15015
15016   dial = GTK_DIAL (object);
15017
15018   if (dial-&gt;adjustment)
15019     {
15020       g_object_unref (GTK_OBJECT (dial-&gt;adjustment));
15021       dial-&gt;adjustment = NULL;
15022     }
15023
15024   if (GTK_OBJECT_CLASS (parent_class)-&gt;destroy)
15025     (* GTK_OBJECT_CLASS (parent_class)-&gt;destroy) (object);
15026 }
15027
15028 GtkAdjustment*
15029 gtk_dial_get_adjustment (GtkDial *dial)
15030 {
15031   g_return_val_if_fail (dial != NULL, NULL);
15032   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
15033
15034   return dial-&gt;adjustment;
15035 }
15036
15037 void
15038 gtk_dial_set_update_policy (GtkDial      *dial,
15039                              GtkUpdateType  policy)
15040 {
15041   g_return_if_fail (dial != NULL);
15042   g_return_if_fail (GTK_IS_DIAL (dial));
15043
15044   dial-&gt;policy = policy;
15045 }
15046
15047 void
15048 gtk_dial_set_adjustment (GtkDial      *dial,
15049                           GtkAdjustment *adjustment)
15050 {
15051   g_return_if_fail (dial != NULL);
15052   g_return_if_fail (GTK_IS_DIAL (dial));
15053
15054   if (dial-&gt;adjustment)
15055     {
15056       g_signal_handlers_disconnect_by_func (GTK_OBJECT (dial-&gt;adjustment), NULL, (gpointer) dial);
15057       g_object_unref (GTK_OBJECT (dial-&gt;adjustment));
15058     }
15059
15060   dial-&gt;adjustment = adjustment;
15061   g_object_ref (GTK_OBJECT (dial-&gt;adjustment));
15062
15063   g_signal_connect (GTK_OBJECT (adjustment), "changed",
15064                     G_CALLBACK (gtk_dial_adjustment_changed),
15065                     (gpointer) dial);
15066   g_signal_connect (GTK_OBJECT (adjustment), "value_changed",
15067                     G_CALLBACK (gtk_dial_adjustment_value_changed),
15068                     (gpointer) dial);
15069
15070   dial-&gt;old_value = adjustment-&gt;value;
15071   dial-&gt;old_lower = adjustment-&gt;lower;
15072   dial-&gt;old_upper = adjustment-&gt;upper;
15073
15074   gtk_dial_update (dial);
15075 }
15076
15077 static void
15078 gtk_dial_realize (GtkWidget *widget)
15079 {
15080   GtkDial *dial;
15081   GdkWindowAttr attributes;
15082   gint attributes_mask;
15083
15084   g_return_if_fail (widget != NULL);
15085   g_return_if_fail (GTK_IS_DIAL (widget));
15086
15087   gtk_widget_set_realized (widget, TRUE);
15088   dial = GTK_DIAL (widget);
15089
15090   attributes.x = widget-&gt;allocation.x;
15091   attributes.y = widget-&gt;allocation.y;
15092   attributes.width = widget-&gt;allocation.width;
15093   attributes.height = widget-&gt;allocation.height;
15094   attributes.wclass = GDK_INPUT_OUTPUT;
15095   attributes.window_type = GDK_WINDOW_CHILD;
15096   attributes.event_mask = gtk_widget_get_events (widget) | 
15097     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
15098     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
15099     GDK_POINTER_MOTION_HINT_MASK;
15100   attributes.visual = gtk_widget_get_visual (widget);
15101   attributes.colormap = gtk_widget_get_colormap (widget);
15102
15103   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
15104   widget-&gt;window = gdk_window_new (widget-&gt;parent-&gt;window, &amp;attributes, attributes_mask);
15105
15106   widget-&gt;style = gtk_style_attach (widget-&gt;style, widget-&gt;window);
15107
15108   gdk_window_set_user_data (widget-&gt;window, widget);
15109
15110   gtk_style_set_background (widget-&gt;style, widget-&gt;window, GTK_STATE_ACTIVE);
15111 }
15112
15113 static void 
15114 gtk_dial_size_request (GtkWidget      *widget,
15115                        GtkRequisition *requisition)
15116 {
15117   requisition-&gt;width = DIAL_DEFAULT_SIZE;
15118   requisition-&gt;height = DIAL_DEFAULT_SIZE;
15119 }
15120
15121 static void
15122 gtk_dial_size_allocate (GtkWidget     *widget,
15123                         GtkAllocation *allocation)
15124 {
15125   GtkDial *dial;
15126
15127   g_return_if_fail (widget != NULL);
15128   g_return_if_fail (GTK_IS_DIAL (widget));
15129   g_return_if_fail (allocation != NULL);
15130
15131   widget-&gt;allocation = *allocation;
15132   dial = GTK_DIAL (widget);
15133
15134   if (gtk_widget_get_realized (widget))
15135     {
15136
15137       gdk_window_move_resize (widget-&gt;window,
15138                               allocation-&gt;x, allocation-&gt;y,
15139                               allocation-&gt;width, allocation-&gt;height);
15140
15141     }
15142   dial-&gt;radius = MIN (allocation-&gt;width, allocation-&gt;height) * 0.45;
15143   dial-&gt;pointer_width = dial-&gt;radius / 5;
15144 }
15145
15146 static gboolean
15147 gtk_dial_expose( GtkWidget      *widget,
15148                  GdkEventExpose *event )
15149 {
15150   GtkDial *dial;
15151   GdkPoint points[6];
15152   gdouble s,c;
15153   gdouble theta, last, increment;
15154   GtkStyle      *blankstyle;
15155   gint xc, yc;
15156   gint upper, lower;
15157   gint tick_length;
15158   gint i, inc;
15159
15160   g_return_val_if_fail (widget != NULL, FALSE);
15161   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15162   g_return_val_if_fail (event != NULL, FALSE);
15163
15164   if (event-&gt;count &gt; 0)
15165     return FALSE;
15166   
15167   dial = GTK_DIAL (widget);
15168
15169 /*  gdk_window_clear_area (widget-&gt;window,
15170                          0, 0,
15171                          widget-&gt;allocation.width,
15172                          widget-&gt;allocation.height);
15173 */
15174   xc = widget-&gt;allocation.width / 2;
15175   yc = widget-&gt;allocation.height / 2;
15176
15177   upper = dial-&gt;adjustment-&gt;upper;
15178   lower = dial-&gt;adjustment-&gt;lower;
15179
15180   /* Erase old pointer */
15181
15182   s = sin (dial-&gt;last_angle);
15183   c = cos (dial-&gt;last_angle);
15184   dial-&gt;last_angle = dial-&gt;angle;
15185
15186   points[0].x = xc + s*dial-&gt;pointer_width/2;
15187   points[0].y = yc + c*dial-&gt;pointer_width/2;
15188   points[1].x = xc + c*dial-&gt;radius;
15189   points[1].y = yc - s*dial-&gt;radius;
15190   points[2].x = xc - s*dial-&gt;pointer_width/2;
15191   points[2].y = yc - c*dial-&gt;pointer_width/2;
15192   points[3].x = xc - c*dial-&gt;radius/10;
15193   points[3].y = yc + s*dial-&gt;radius/10;
15194   points[4].x = points[0].x;
15195   points[4].y = points[0].y;
15196
15197   blankstyle = gtk_style_new ();
15198   blankstyle-&gt;bg_gc[GTK_STATE_NORMAL] =
15199                 widget-&gt;style-&gt;bg_gc[GTK_STATE_NORMAL];
15200   blankstyle-&gt;dark_gc[GTK_STATE_NORMAL] =
15201                 widget-&gt;style-&gt;bg_gc[GTK_STATE_NORMAL];
15202   blankstyle-&gt;light_gc[GTK_STATE_NORMAL] =
15203                 widget-&gt;style-&gt;bg_gc[GTK_STATE_NORMAL];
15204   blankstyle-&gt;black_gc =
15205                 widget-&gt;style-&gt;bg_gc[GTK_STATE_NORMAL];
15206
15207   gtk_paint_polygon (blankstyle,
15208                     widget-&gt;window,
15209                     GTK_STATE_NORMAL,
15210                     GTK_SHADOW_OUT,
15211                     NULL,
15212                     widget,
15213                     NULL,
15214                     points, 5,
15215                     FALSE);
15216
15217   g_object_unref (blankstyle);
15218
15219
15220   /* Draw ticks */
15221
15222   if ((upper - lower) == 0)
15223     return FALSE;
15224
15225   increment = (100*M_PI) / (dial-&gt;radius*dial-&gt;radius);
15226
15227   inc = (upper - lower);
15228
15229   while (inc &lt; 100) inc *= 10;
15230   while (inc &gt;= 1000) inc /= 10;
15231   last = -1;
15232
15233   for (i = 0; i &lt;= inc; i++)
15234     {
15235       theta = ((gfloat)i*M_PI / (18*inc/24.) - M_PI/6.);
15236
15237       if ((theta - last) &lt; (increment))
15238         continue;     
15239       last = theta;
15240
15241       s = sin (theta);
15242       c = cos (theta);
15243
15244       tick_length = (i%(inc/10) == 0) ? dial-&gt;pointer_width : dial-&gt;pointer_width / 2;
15245
15246       gdk_draw_line (widget-&gt;window,
15247                      widget-&gt;style-&gt;fg_gc[widget-&gt;state],
15248                      xc + c*(dial-&gt;radius - tick_length),
15249                      yc - s*(dial-&gt;radius - tick_length),
15250                      xc + c*dial-&gt;radius,
15251                      yc - s*dial-&gt;radius);
15252     }
15253
15254   /* Draw pointer */
15255
15256   s = sin (dial-&gt;angle);
15257   c = cos (dial-&gt;angle);
15258   dial-&gt;last_angle = dial-&gt;angle;
15259
15260   points[0].x = xc + s*dial-&gt;pointer_width/2;
15261   points[0].y = yc + c*dial-&gt;pointer_width/2;
15262   points[1].x = xc + c*dial-&gt;radius;
15263   points[1].y = yc - s*dial-&gt;radius;
15264   points[2].x = xc - s*dial-&gt;pointer_width/2;
15265   points[2].y = yc - c*dial-&gt;pointer_width/2;
15266   points[3].x = xc - c*dial-&gt;radius/10;
15267   points[3].y = yc + s*dial-&gt;radius/10;
15268   points[4].x = points[0].x;
15269   points[4].y = points[0].y;
15270
15271
15272   gtk_paint_polygon (widget-&gt;style,
15273                     widget-&gt;window,
15274                     GTK_STATE_NORMAL,
15275                     GTK_SHADOW_OUT,
15276                     NULL,
15277                     widget,
15278                     NULL,
15279                     points, 5,
15280                     TRUE);
15281
15282   return FALSE;
15283 }
15284
15285 static gboolean
15286 gtk_dial_button_press( GtkWidget      *widget,
15287                        GdkEventButton *event )
15288 {
15289   GtkDial *dial;
15290   gint dx, dy;
15291   double s, c;
15292   double d_parallel;
15293   double d_perpendicular;
15294
15295   g_return_val_if_fail (widget != NULL, FALSE);
15296   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15297   g_return_val_if_fail (event != NULL, FALSE);
15298
15299   dial = GTK_DIAL (widget);
15300
15301   /* Determine if button press was within pointer region - we 
15302      do this by computing the parallel and perpendicular distance of
15303      the point where the mouse was pressed from the line passing through
15304      the pointer */
15305   
15306   dx = event-&gt;x - widget-&gt;allocation.width / 2;
15307   dy = widget-&gt;allocation.height / 2 - event-&gt;y;
15308   
15309   s = sin (dial-&gt;angle);
15310   c = cos (dial-&gt;angle);
15311   
15312   d_parallel = s*dy + c*dx;
15313   d_perpendicular = fabs (s*dx - c*dy);
15314   
15315   if (!dial-&gt;button &amp;&amp;
15316       (d_perpendicular &lt; dial-&gt;pointer_width/2) &amp;&amp;
15317       (d_parallel &gt; - dial-&gt;pointer_width))
15318     {
15319       gtk_grab_add (widget);
15320
15321       dial-&gt;button = event-&gt;button;
15322
15323       gtk_dial_update_mouse (dial, event-&gt;x, event-&gt;y);
15324     }
15325
15326   return FALSE;
15327 }
15328
15329 static gboolean
15330 gtk_dial_button_release( GtkWidget      *widget,
15331                          GdkEventButton *event )
15332 {
15333   GtkDial *dial;
15334
15335   g_return_val_if_fail (widget != NULL, FALSE);
15336   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15337   g_return_val_if_fail (event != NULL, FALSE);
15338
15339   dial = GTK_DIAL (widget);
15340
15341   if (dial-&gt;button == event-&gt;button)
15342     {
15343       gtk_grab_remove (widget);
15344
15345       dial-&gt;button = 0;
15346
15347       if (dial-&gt;policy == GTK_UPDATE_DELAYED)
15348         g_source_remove (dial-&gt;timer);
15349       
15350       if ((dial-&gt;policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
15351           (dial-&gt;old_value != dial-&gt;adjustment-&gt;value))
15352         g_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), "value_changed");
15353     }
15354
15355   return FALSE;
15356 }
15357
15358 static gboolean
15359 gtk_dial_motion_notify( GtkWidget      *widget,
15360                         GdkEventMotion *event )
15361 {
15362   GtkDial *dial;
15363   GdkModifierType mods;
15364   gint x, y, mask;
15365
15366   g_return_val_if_fail (widget != NULL, FALSE);
15367   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
15368   g_return_val_if_fail (event != NULL, FALSE);
15369
15370   dial = GTK_DIAL (widget);
15371
15372   if (dial-&gt;button != 0)
15373     {
15374       x = event-&gt;x;
15375       y = event-&gt;y;
15376
15377       if (event-&gt;is_hint || (event-&gt;window != widget-&gt;window))
15378         gdk_window_get_pointer (widget-&gt;window, &amp;x, &amp;y, &amp;mods);
15379
15380       switch (dial-&gt;button)
15381         {
15382         case 1:
15383           mask = GDK_BUTTON1_MASK;
15384           break;
15385         case 2:
15386           mask = GDK_BUTTON2_MASK;
15387           break;
15388         case 3:
15389           mask = GDK_BUTTON3_MASK;
15390           break;
15391         default:
15392           mask = 0;
15393           break;
15394         }
15395
15396       if (mods &amp; mask)
15397         gtk_dial_update_mouse (dial, x,y);
15398     }
15399
15400   return FALSE;
15401 }
15402
15403 static gboolean
15404 gtk_dial_timer( GtkDial *dial )
15405 {
15406   g_return_val_if_fail (dial != NULL, FALSE);
15407   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
15408
15409   if (dial-&gt;policy == GTK_UPDATE_DELAYED)
15410     g_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), "value_changed");
15411
15412   return FALSE;
15413 }
15414
15415 static void
15416 gtk_dial_update_mouse( GtkDial *dial, gint x, gint y )
15417 {
15418   gint xc, yc;
15419   gfloat old_value;
15420
15421   g_return_if_fail (dial != NULL);
15422   g_return_if_fail (GTK_IS_DIAL (dial));
15423
15424   xc = GTK_WIDGET(dial)-&gt;allocation.width / 2;
15425   yc = GTK_WIDGET(dial)-&gt;allocation.height / 2;
15426
15427   old_value = dial-&gt;adjustment-&gt;value;
15428   dial-&gt;angle = atan2(yc-y, x-xc);
15429
15430   if (dial-&gt;angle &lt; -M_PI/2.)
15431     dial-&gt;angle += 2*M_PI;
15432
15433   if (dial-&gt;angle &lt; -M_PI/6)
15434     dial-&gt;angle = -M_PI/6;
15435
15436   if (dial-&gt;angle &gt; 7.*M_PI/6.)
15437     dial-&gt;angle = 7.*M_PI/6.;
15438
15439   dial-&gt;adjustment-&gt;value = dial-&gt;adjustment-&gt;lower + (7.*M_PI/6 - dial-&gt;angle) *
15440     (dial-&gt;adjustment-&gt;upper - dial-&gt;adjustment-&gt;lower) / (4.*M_PI/3.);
15441
15442   if (dial-&gt;adjustment-&gt;value != old_value)
15443     {
15444       if (dial-&gt;policy == GTK_UPDATE_CONTINUOUS)
15445         {
15446           g_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), "value_changed");
15447         }
15448       else
15449         {
15450           gtk_widget_queue_draw (GTK_WIDGET (dial));
15451
15452           if (dial-&gt;policy == GTK_UPDATE_DELAYED)
15453             {
15454               if (dial-&gt;timer)
15455                 g_source_remove (dial-&gt;timer);
15456
15457               dial-&gt;timer = g_timeout_add (SCROLL_DELAY_LENGTH,
15458                                            (GtkFunction) gtk_dial_timer,
15459                                            (gpointer) dial);
15460             }
15461         }
15462     }
15463 }
15464
15465 static void
15466 gtk_dial_update (GtkDial *dial)
15467 {
15468   gfloat new_value;
15469   
15470   g_return_if_fail (dial != NULL);
15471   g_return_if_fail (GTK_IS_DIAL (dial));
15472
15473   new_value = dial-&gt;adjustment-&gt;value;
15474   
15475   if (new_value &lt; dial-&gt;adjustment-&gt;lower)
15476     new_value = dial-&gt;adjustment-&gt;lower;
15477
15478   if (new_value &gt; dial-&gt;adjustment-&gt;upper)
15479     new_value = dial-&gt;adjustment-&gt;upper;
15480
15481   if (new_value != dial-&gt;adjustment-&gt;value)
15482     {
15483       dial-&gt;adjustment-&gt;value = new_value;
15484       g_signal_emit_by_name (GTK_OBJECT (dial-&gt;adjustment), "value_changed");
15485     }
15486
15487   dial-&gt;angle = 7.*M_PI/6. - (new_value - dial-&gt;adjustment-&gt;lower) * 4.*M_PI/3. /
15488     (dial-&gt;adjustment-&gt;upper - dial-&gt;adjustment-&gt;lower);
15489
15490   gtk_widget_queue_draw (GTK_WIDGET (dial));
15491 }
15492
15493 static void
15494 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
15495                               gpointer       data)
15496 {
15497   GtkDial *dial;
15498
15499   g_return_if_fail (adjustment != NULL);
15500   g_return_if_fail (data != NULL);
15501
15502   dial = GTK_DIAL (data);
15503
15504   if ((dial-&gt;old_value != adjustment-&gt;value) ||
15505       (dial-&gt;old_lower != adjustment-&gt;lower) ||
15506       (dial-&gt;old_upper != adjustment-&gt;upper))
15507     {
15508       gtk_dial_update (dial);
15509
15510       dial-&gt;old_value = adjustment-&gt;value;
15511       dial-&gt;old_lower = adjustment-&gt;lower;
15512       dial-&gt;old_upper = adjustment-&gt;upper;
15513     }
15514 }
15515
15516 static void
15517 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
15518                                     gpointer       data)
15519 {
15520   GtkDial *dial;
15521
15522   g_return_if_fail (adjustment != NULL);
15523   g_return_if_fail (data != NULL);
15524
15525   dial = GTK_DIAL (data);
15526
15527   if (dial-&gt;old_value != adjustment-&gt;value)
15528     {
15529       gtk_dial_update (dial);
15530
15531       dial-&gt;old_value = adjustment-&gt;value;
15532     }
15533 }
15534 <!-- example-end -->
15535 </programlisting>
15536
15537 </sect2>
15538
15539 <!-- ----------------------------------------------------------------- -->
15540 <sect2>
15541 <title>dial_test.c</title>
15542
15543 <programlisting role="C">
15544 <!-- example-start gtkdial dial_test.c -->
15545
15546 #include &lt;stdio.h&gt;
15547 #include &lt;stdlib.h&gt;
15548 #include &lt;gtk/gtk.h&gt;
15549 #include "gtkdial.h"
15550
15551 void value_changed( GtkAdjustment *adjustment,
15552                     GtkWidget     *label )
15553 {
15554   char buffer[16];
15555
15556   sprintf(buffer,"%4.2f",adjustment-&gt;value);
15557   gtk_label_set_text (GTK_LABEL (label), buffer);
15558 }
15559
15560 int main( int   argc,
15561           char *argv[])
15562 {
15563   GtkWidget *window;
15564   GtkAdjustment *adjustment;
15565   GtkWidget *dial;
15566   GtkWidget *frame;
15567   GtkWidget *vbox;
15568   GtkWidget *label;
15569   
15570   gtk_init (&amp;argc, &amp;argv);
15571
15572   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15573   
15574   gtk_window_set_title (GTK_WINDOW (window), "Dial");
15575   
15576   g_signal_connect (window, "destroy",
15577                     G_CALLBACK (exit), NULL);
15578   
15579   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
15580
15581   vbox = gtk_vbox_new (FALSE, 5);
15582   gtk_container_add (GTK_CONTAINER (window), vbox);
15583   gtk_widget_show (vbox);
15584
15585   frame = gtk_frame_new (NULL);
15586   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
15587   gtk_container_add (GTK_CONTAINER (vbox), frame);
15588   gtk_widget_show (frame); 
15589
15590   adjustment = gtk_adjustment_new (0, 0, 100, 0.01, 0.1, 0);
15591
15592   dial = gtk_dial_new (adjustment);
15593   gtk_dial_set_update_policy (GTK_DIAL (dial), GTK_UPDATE_DELAYED);
15594   /*  gtk_widget_set_size_request (dial, 100, 100); */
15595   
15596   gtk_container_add (GTK_CONTAINER (frame), dial);
15597   gtk_widget_show (dial);
15598
15599   label = gtk_label_new ("0.00");
15600   gtk_box_pack_end (GTK_BOX (vbox), label, 0, 0, 0);
15601   gtk_widget_show (label);
15602
15603   g_signal_connect (adjustment, "value_changed",
15604                     G_CALLBACK (value_changed), (gpointer) label);
15605   
15606   gtk_widget_show (window);
15607   
15608   gtk_main ();
15609   
15610   return 0;
15611 }
15612 <!-- example-end -->
15613 </programlisting>
15614
15615 </sect2>
15616 </sect1>
15617
15618 <!-- ----------------------------------------------------------------- -->
15619 <sect1 id="sec-Scribble">
15620 <title>Scribble</title>
15621
15622 <!-- ----------------------------------------------------------------- -->
15623 <sect2>
15624 <title>scribble-simple.c</title>
15625
15626 <programlisting role="C">
15627 <!-- example-start scribble-simple scribble-simple.c -->
15628
15629 /* GTK - The GIMP Toolkit
15630  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15631  *
15632  * This library is free software; you can redistribute it and/or
15633  * modify it under the terms of the GNU Library General Public
15634  * License as published by the Free Software Foundation; either
15635  * version 2 of the License, or (at your option) any later version.
15636  *
15637  * This library is distributed in the hope that it will be useful,
15638  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15639  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15640  * Library General Public License for more details.
15641  *
15642  * You should have received a copy of the GNU Library General Public
15643  * License along with this library; if not, write to the
15644  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15645  * Boston, MA 02111-1307, USA.
15646  */
15647
15648 #include &lt;stdlib.h&gt;
15649 #include &lt;gtk/gtk.h&gt;
15650
15651 /* Backing pixmap for drawing area */
15652 static GdkPixmap *pixmap = NULL;
15653
15654 /* Create a new backing pixmap of the appropriate size */
15655 static gboolean configure_event( GtkWidget         *widget,
15656                                  GdkEventConfigure *event )
15657 {
15658   if (pixmap)
15659     g_object_unref (pixmap);
15660
15661   pixmap = gdk_pixmap_new (widget-&gt;window,
15662                            widget-&gt;allocation.width,
15663                            widget-&gt;allocation.height,
15664                            -1);
15665   gdk_draw_rectangle (pixmap,
15666                       widget-&gt;style-&gt;white_gc,
15667                       TRUE,
15668                       0, 0,
15669                       widget-&gt;allocation.width,
15670                       widget-&gt;allocation.height);
15671
15672   return TRUE;
15673 }
15674
15675 /* Redraw the screen from the backing pixmap */
15676 static gboolean expose_event( GtkWidget      *widget,
15677                               GdkEventExpose *event )
15678 {
15679   gdk_draw_drawable (widget-&gt;window,
15680                      widget-&gt;style-&gt;fg_gc[gtk_widget_get_state (widget)],
15681                      pixmap,
15682                      event-&gt;area.x, event-&gt;area.y,
15683                      event-&gt;area.x, event-&gt;area.y,
15684                      event-&gt;area.width, event-&gt;area.height);
15685
15686   return FALSE;
15687 }
15688
15689 /* Draw a rectangle on the screen */
15690 static void draw_brush( GtkWidget *widget,
15691                         gdouble    x,
15692                         gdouble    y)
15693 {
15694   GdkRectangle update_rect;
15695
15696   update_rect.x = x - 5;
15697   update_rect.y = y - 5;
15698   update_rect.width = 10;
15699   update_rect.height = 10;
15700   gdk_draw_rectangle (pixmap,
15701                       widget-&gt;style-&gt;black_gc,
15702                       TRUE,
15703                       update_rect.x, update_rect.y,
15704                       update_rect.width, update_rect.height);
15705   gtk_widget_queue_draw_area (widget, 
15706                               update_rect.x, update_rect.y,
15707                               update_rect.width, update_rect.height);
15708 }
15709
15710 static gboolean button_press_event( GtkWidget      *widget,
15711                                     GdkEventButton *event )
15712 {
15713   if (event-&gt;button == 1 &amp;&amp; pixmap != NULL)
15714     draw_brush (widget, event-&gt;x, event-&gt;y);
15715
15716   return TRUE;
15717 }
15718
15719 static gboolean motion_notify_event( GtkWidget *widget,
15720                                      GdkEventMotion *event )
15721 {
15722   int x, y;
15723   GdkModifierType state;
15724
15725   if (event-&gt;is_hint)
15726     gdk_window_get_pointer (event-&gt;window, &amp;x, &amp;y, &amp;state);
15727   else
15728     {
15729       x = event-&gt;x;
15730       y = event-&gt;y;
15731       state = event-&gt;state;
15732     }
15733     
15734   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
15735     draw_brush (widget, x, y);
15736   
15737   return TRUE;
15738 }
15739
15740 void quit ()
15741 {
15742   exit (0);
15743 }
15744
15745 int main( int   argc, 
15746           char *argv[] )
15747 {
15748   GtkWidget *window;
15749   GtkWidget *drawing_area;
15750   GtkWidget *vbox;
15751
15752   GtkWidget *button;
15753
15754   gtk_init (&amp;argc, &amp;argv);
15755
15756   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15757   gtk_widget_set_name (window, "Test Input");
15758
15759   vbox = gtk_vbox_new (FALSE, 0);
15760   gtk_container_add (GTK_CONTAINER (window), vbox);
15761   gtk_widget_show (vbox);
15762
15763   g_signal_connect (window, "destroy",
15764                     G_CALLBACK (quit), NULL);
15765
15766   /* Create the drawing area */
15767
15768   drawing_area = gtk_drawing_area_new ();
15769   gtk_widget_set_size_request (GTK_WIDGET (drawing_area), 200, 200);
15770   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
15771
15772   gtk_widget_show (drawing_area);
15773
15774   /* Signals used to handle backing pixmap */
15775
15776   g_signal_connect (drawing_area, "expose_event",
15777                     G_CALLBACK (expose_event), NULL);
15778   g_signal_connect (drawing_area, "configure_event",
15779                     G_CALLBACK (configure_event), NULL);
15780
15781   /* Event signals */
15782
15783   g_signal_connect (drawing_area, "motion_notify_event",
15784                     G_CALLBACK (motion_notify_event), NULL);
15785   g_signal_connect (drawing_area, "button_press_event",
15786                     G_CALLBACK (button_press_event), NULL);
15787
15788   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
15789                          | GDK_LEAVE_NOTIFY_MASK
15790                          | GDK_BUTTON_PRESS_MASK
15791                          | GDK_POINTER_MOTION_MASK
15792                          | GDK_POINTER_MOTION_HINT_MASK);
15793
15794   /* .. And a quit button */
15795   button = gtk_button_new_with_label ("Quit");
15796   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
15797
15798   g_signal_connect_swapped (button, "clicked",
15799                             G_CALLBACK (gtk_widget_destroy),
15800                             window);
15801   gtk_widget_show (button);
15802
15803   gtk_widget_show (window);
15804
15805   gtk_main ();
15806
15807   return 0;
15808 }
15809 <!-- example-end -->
15810 </programlisting>
15811
15812 </sect2>
15813
15814 <!-- ----------------------------------------------------------------- -->
15815 <sect2>
15816 <title>scribble-xinput.c</title>
15817
15818 <programlisting role="C">
15819 <!-- example-start scribble-xinput scribble-xinput.c -->
15820
15821 /* GTK - The GIMP Toolkit
15822  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15823  *
15824  * This library is free software; you can redistribute it and/or
15825  * modify it under the terms of the GNU Library General Public
15826  * License as published by the Free Software Foundation; either
15827  * version 2 of the License, or (at your option) any later version.
15828  *
15829  * This library is distributed in the hope that it will be useful,
15830  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15831  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15832  * Library General Public License for more details.
15833  *
15834  * You should have received a copy of the GNU Library General Public
15835  * License along with this library; if not, write to the
15836  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15837  * Boston, MA 02111-1307, USA.
15838  */
15839
15840 #include &lt;gtk/gtk.h&gt;
15841
15842 /* Backing pixmap for drawing area */
15843 static GdkPixmap *pixmap = NULL;
15844
15845 /* Create a new backing pixmap of the appropriate size */
15846 static gboolean
15847 configure_event (GtkWidget *widget, GdkEventConfigure *event)
15848 {
15849   if (pixmap)
15850      g_object_unref (pixmap);
15851
15852   pixmap = gdk_pixmap_new (widget-&gt;window,
15853                            widget-&gt;allocation.width,
15854                            widget-&gt;allocation.height,
15855                            -1);
15856   gdk_draw_rectangle (pixmap,
15857                       widget-&gt;style-&gt;white_gc,
15858                       TRUE,
15859                       0, 0,
15860                       widget-&gt;allocation.width,
15861                       widget-&gt;allocation.height);
15862
15863   return TRUE;
15864 }
15865
15866 /* Redraw the screen from the backing pixmap */
15867 static gboolean
15868 expose_event (GtkWidget *widget, GdkEventExpose *event)
15869 {
15870   gdk_draw_drawable (widget-&gt;window,
15871                      widget-&gt;style-&gt;fg_gc[gtk_widget_get_state (widget)],
15872                      pixmap,
15873                      event-&gt;area.x, event-&gt;area.y,
15874                      event-&gt;area.x, event-&gt;area.y,
15875                      event-&gt;area.width, event-&gt;area.height);
15876
15877   return FALSE;
15878 }
15879
15880 /* Draw a rectangle on the screen, size depending on pressure,
15881    and color on the type of device */
15882 static void
15883 draw_brush (GtkWidget *widget, GdkInputSource source,
15884             gdouble x, gdouble y, gdouble pressure)
15885 {
15886   GdkGC *gc;
15887   GdkRectangle update_rect;
15888
15889   switch (source)
15890     {
15891     case GDK_SOURCE_MOUSE:
15892       gc = widget-&gt;style-&gt;dark_gc[gtk_widget_get_state (widget)];
15893       break;
15894     case GDK_SOURCE_PEN:
15895       gc = widget-&gt;style-&gt;black_gc;
15896       break;
15897     case GDK_SOURCE_ERASER:
15898       gc = widget-&gt;style-&gt;white_gc;
15899       break;
15900     default:
15901       gc = widget-&gt;style-&gt;light_gc[gtk_widget_get_state (widget)];
15902     }
15903
15904   update_rect.x = x - 10 * pressure;
15905   update_rect.y = y - 10 * pressure;
15906   update_rect.width = 20 * pressure;
15907   update_rect.height = 20 * pressure;
15908   gdk_draw_rectangle (pixmap, gc, TRUE,
15909                       update_rect.x, update_rect.y,
15910                       update_rect.width, update_rect.height);
15911   gtk_widget_queue_draw_area (widget, 
15912                       update_rect.x, update_rect.y,
15913                       update_rect.width, update_rect.height);
15914 }
15915
15916 static void
15917 print_button_press (GdkDevice *device)
15918 {
15919   g_print ("Button press on device '%s'\n", device-&gt;name);
15920 }
15921
15922 static gboolean
15923 button_press_event (GtkWidget *widget, GdkEventButton *event)
15924 {
15925   print_button_press (event-&gt;device);
15926   
15927   if (event-&gt;button == 1 &amp;&amp; pixmap != NULL) {
15928     gdouble pressure;
15929     gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_PRESSURE, &amp;pressure);
15930     draw_brush (widget, event-&gt;device-&gt;source, event-&gt;x, event-&gt;y, pressure);
15931   }
15932
15933   return TRUE;
15934 }
15935
15936 static gboolean
15937 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
15938 {
15939   gdouble x, y;
15940   gdouble pressure;
15941   GdkModifierType state;
15942
15943   if (event-&gt;is_hint) 
15944     {
15945       gdk_device_get_state (event-&gt;device, event-&gt;window, NULL, &amp;state);
15946       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_X, &amp;x);
15947       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_Y, &amp;y);
15948       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_PRESSURE, &amp;pressure);
15949     }
15950   else
15951     {
15952       x = event-&gt;x;
15953       y = event-&gt;y;
15954       gdk_event_get_axis ((GdkEvent *)event, GDK_AXIS_PRESSURE, &amp;pressure);
15955       state = event-&gt;state;
15956     }
15957     
15958   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
15959     draw_brush (widget, event-&gt;device-&gt;source, x, y, pressure);
15960   
15961   return TRUE;
15962 }
15963
15964 void
15965 input_dialog_destroy (GtkWidget *w, gpointer data)
15966 {
15967   *((GtkWidget **)data) = NULL;
15968 }
15969
15970 void
15971 create_input_dialog ()
15972 {
15973   static GtkWidget *inputd = NULL;
15974
15975   if (!inputd)
15976     {
15977       inputd = gtk_input_dialog_new();
15978
15979       g_signal_connect (inputd, "destroy",
15980                         G_CALLBACK (input_dialog_destroy), (gpointer) &amp;inputd);
15981       g_signal_connect_swapped (GTK_INPUT_DIALOG (inputd)-&gt;close_button,
15982                                 "clicked",
15983                                 G_CALLBACK (gtk_widget_hide),
15984                                 inputd);
15985       gtk_widget_hide (GTK_INPUT_DIALOG (inputd)-&gt;save_button);
15986
15987       gtk_widget_show (inputd);
15988     }
15989   else
15990     {
15991       if (!gtk_widget_get_mapped (inputd))
15992         gtk_widget_show (inputd);
15993       else
15994         gdk_window_raise (inputd-&gt;window);
15995     }
15996 }
15997
15998 int
15999 main (int argc, char *argv[])
16000 {
16001   GtkWidget *window;
16002   GtkWidget *drawing_area;
16003   GtkWidget *vbox;
16004
16005   GtkWidget *button;
16006
16007   gtk_init (&amp;argc, &amp;argv);
16008
16009   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
16010   gtk_widget_set_name (window, "Test Input");
16011
16012   vbox = gtk_vbox_new (FALSE, 0);
16013   gtk_container_add (GTK_CONTAINER (window), vbox);
16014   gtk_widget_show (vbox);
16015
16016   g_signal_connect (window, "destroy",
16017                     G_CALLBACK (gtk_main_quit), NULL);
16018
16019   /* Create the drawing area */
16020
16021   drawing_area = gtk_drawing_area_new ();
16022   gtk_widget_set_size_request (GTK_WIDGET (drawing_area), 200, 200);
16023   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
16024
16025   gtk_widget_show (drawing_area);
16026
16027   /* Signals used to handle backing pixmap */
16028
16029   g_signal_connect (drawing_area, "expose_event",
16030                     G_CALLBACK (expose_event), NULL);
16031   g_signal_connect (drawing_area, "configure_event",
16032                     G_CALLBACK (configure_event), NULL);
16033
16034   /* Event signals */
16035
16036   g_signal_connect (drawing_area, "motion_notify_event",
16037                     G_CALLBACK (motion_notify_event), NULL);
16038   g_signal_connect (drawing_area, "button_press_event",
16039                     G_CALLBACK (button_press_event), NULL);
16040
16041   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
16042                          | GDK_LEAVE_NOTIFY_MASK
16043                          | GDK_BUTTON_PRESS_MASK
16044                          | GDK_POINTER_MOTION_MASK
16045                          | GDK_POINTER_MOTION_HINT_MASK);
16046
16047   /* The following call enables tracking and processing of extension
16048      events for the drawing area */
16049   gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
16050
16051   /* .. And some buttons */
16052   button = gtk_button_new_with_label ("Input Dialog");
16053   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
16054
16055   g_signal_connect (button, "clicked",
16056                     G_CALLBACK (create_input_dialog), NULL);
16057   gtk_widget_show (button);
16058
16059   button = gtk_button_new_with_label ("Quit");
16060   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
16061
16062   g_signal_connect_swapped (button, "clicked",
16063                             G_CALLBACK (gtk_widget_destroy),
16064                             window);
16065   gtk_widget_show (button);
16066
16067   gtk_widget_show (window);
16068
16069   gtk_main ();
16070
16071   return 0;
16072 }
16073 <!-- example-end -->
16074 </programlisting>
16075
16076 </sect2>
16077 </sect1>
16078
16079 </appendix>
16080 </book>