]> Pileus Git - ~andy/gtk/blob - docs/tutorial/gtk_tut.sgml
Style check from David King <dking@youvegotmail.net>
[~andy/gtk] / docs / tutorial / gtk_tut.sgml
1 <!doctype linuxdoc system>
2
3 <!-- This is the tutorial marked up in SGML
4      (just to show how to write a comment)
5 -->
6
7 <article>
8 <title>GTK v1.2 Tutorial
9 <author>
10 Tony Gale <tt><htmlurl url="mailto:gale@gtk.org"
11                               name="&lt;gale@gtk.org&gt;"></tt>,
12 Ian Main <tt><htmlurl url="mailto:imain@gtk.org"
13                               name="&lt;imain@gtk.org&gt;"></tt>
14 <date>April 1st, 1999
15 <abstract>
16 This is a tutorial on how to use GTK (the GIMP Toolkit) through its C
17 interface.
18 </abstract>
19
20 <!-- Table of contents -->
21 <!-- Older versions of this tutorial did not have a table of contents,
22      but the tutorial is now so large that having one is very useful. -->
23 <toc>
24  
25
26 <!-- ***************************************************************** -->
27 <sect>Introduction
28 <!-- ***************************************************************** -->
29 <p>
30 GTK (GIMP Toolkit) is a library for creating graphical user
31 interfaces. It is licensed using the LGPL license, so you can develop
32 open software, free software, or even commercial non-free software
33 using GTK without having to spend anything for licenses or royalties.
34
35 It's called the GIMP toolkit because it was originally written for
36 developing the General Image Manipulation Program (GIMP), but GTK has
37 now been used in a large number of software projects, including the
38 GNU Network Object Model Environment (GNOME) project. GTK is built on
39 top of GDK (GIMP Drawing Kit) which is basically a wrapper around the
40 low-level functions for accessing the underlying windowing functions
41 (Xlib in the case of the X windows system). The primary authors of GTK
42 are:
43
44 <itemize>
45 <item> Peter Mattis   <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
46                            name="petm@xcf.berkeley.edu"></tt>
47 <item> Spencer Kimball <tt><htmlurl url="mailto:spencer@xcf.berkeley.edu"
48                            name="spencer@xcf.berkeley.edu"></tt>
49 <item> Josh MacDonald <tt><htmlurl url="mailto:jmacd@xcf.berkeley.edu"
50                            name="jmacd@xcf.berkeley.edu"></tt>
51 </itemize>
52
53 GTK is essentially an object oriented application programmers
54 interface (API). Although written completely in C, it is implemented
55 using the idea of classes and callback functions (pointers to
56 functions).
57
58 There is also a third component called GLib which contains a few
59 replacements for some standard calls, as well as some additional
60 functions for handling linked lists, etc. The replacement functions
61 are used to increase GTK's portability, as some of the functions
62 implemented here are not available or are nonstandard on other unixes
63 such as g_strerror(). Some also contain enhancements to the libc
64 versions, such as g_malloc that has enhanced debugging utilities.
65
66 This tutorial describes the C interface to GTK. There are GTK
67 bindings for many other languages including C++, Guile, Perl, Python,
68 TOM, Ada95, Objective C, Free Pascal, and Eiffel. If you intend to
69 use another language's bindings to GTK, look at that binding's
70 documentation first. In some cases that documentation may describe
71 some important conventions (which you should know first) and then
72 refer you back to this tutorial. There are also some cross-platform
73 APIs (such as wxWindows and V) which use GTK as one of their target
74 platforms; again, consult their documentation first.
75
76 If you're developing your GTK application in C++, a few extra notes
77 are in order. There's a C++ binding to GTK called GTK--, which
78 provides a more C++-like interface to GTK; you should probably look
79 into this instead. If you don't like that approach for whatever
80 reason, there are two alternatives for using GTK. First, you can use
81 only the C subset of C++ when interfacing with GTK and then use the C
82 interface as described in this tutorial. Second, you can use GTK and
83 C++ together by declaring all callbacks as static functions in C++
84 classes, and again calling GTK using its C interface. If you choose
85 this last approach, you can include as the callback's data value a
86 pointer to the object to be manipulated (the so-called "this" value).
87 Selecting between these options is simply a matter of preference,
88 since in all three approaches you get C++ and GTK. None of these
89 approaches requires the use of a specialized preprocessor, so no
90 matter what you choose you can use standard C++ with GTK.
91
92 This tutorial is an attempt to document as much as possible of GTK,
93 but it is by no means complete. This tutorial assumes a good
94 understanding of C, and how to create C programs. It would be a great
95 benefit for the reader to have previous X programming experience, but
96 it shouldn't be necessary. If you are learning GTK as your first
97 widget set, please comment on how you found this tutorial, and what
98 you had trouble with. There are also C++, Objective C, ADA, Guile and
99 other language bindings available, but I don't follow these.
100
101 This document is a "work in progress". Please look for updates on
102 <htmlurl url="http://www.gtk.org/" name="http://www.gtk.org/">.
103
104 I would very much like to hear of any problems you have learning GTK
105 from this document, and would appreciate input as to how it may be
106 improved. Please see the section on <ref id="sec_Contributing"
107 name="Contributing"> for further information.
108
109 <!-- ***************************************************************** -->
110 <sect>Getting Started
111 <!-- ***************************************************************** -->
112
113 <p>
114 The first thing to do, of course, is download the GTK source and
115 install it. You can always get the latest version from ftp.gtk.org in
116 /pub/gtk. You can also view other sources of GTK information on
117 <htmlurl url="http://www.gtk.org/" name="http://www.gtk.org/">. GTK
118 uses GNU autoconf for configuration. Once untar'd, type ./configure
119 --help to see a list of options.
120
121 The GTK source distribution also contains the complete source to all
122 of the examples used in this tutorial, along with Makefiles to aid
123 compilation.
124
125 To begin our introduction to GTK, we'll start with the simplest
126 program possible. This program will create a 200x200 pixel window and
127 has no way of exiting except to be killed by using the shell.
128
129 <tscreen><verb>
130 /* example-start base base.c */
131
132 #include <gtk/gtk.h>
133
134 int main( int   argc,
135           char *argv[] )
136 {
137     GtkWidget *window;
138     
139     gtk_init (&amp;argc, &amp;argv);
140     
141     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
142     gtk_widget_show  (window);
143     
144     gtk_main ();
145     
146     return(0);
147 }
148 /* example-end */
149 </verb></tscreen>
150
151 You can compile the above program with gcc using:
152 <tscreen><verb>
153 gcc base.c -o base `gtk-config --cflags --libs`
154 </verb></tscreen>
155
156 The meaning of the unusual compilation options is explained below in
157 <ref id="sec_compiling" name="Compiling Hello World">.
158
159 All programs will of course include gtk/gtk.h which declares the
160 variables, functions, structures, etc. that will be used in your GTK
161 application.
162
163 The next line:
164
165 <tscreen><verb>
166 gtk_init (&amp;argc, &amp;argv);
167 </verb></tscreen>
168
169 calls the function gtk_init(gint *argc, gchar ***argv) which will be
170 called in all GTK applications. This sets up a few things for us such
171 as the default visual and color map and then proceeds to call
172 gdk_init(gint *argc, gchar ***argv). This function initializes the
173 library for use, sets up default signal handlers, and checks the
174 arguments passed to your application on the command line, looking for
175 one of the following:
176
177 <itemize>
178 <item> <tt/--gtk-module/
179 <item> <tt/--g-fatal-warnings/
180 <item> <tt/--gtk-debug/
181 <item> <tt/--gtk-no-debug/
182 <item> <tt/--gdk-debug/
183 <item> <tt/--gdk-no-debug/
184 <item> <tt/--display/
185 <item> <tt/--sync/
186 <item> <tt/--no-xshm/
187 <item> <tt/--name/
188 <item> <tt/--class/
189 </itemize>
190
191 It removes these from the argument list, leaving anything it does not
192 recognize for your application to parse or ignore. This creates a set
193 of standard arguments accepted by all GTK applications.
194
195 The next two lines of code create and display a window.
196
197 <tscreen><verb>
198   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
199   gtk_widget_show (window);
200 </verb></tscreen>
201
202 The <tt/GTK_WINDOW_TOPLEVEL/ argument specifies that we want the
203 window to undergo window manager decoration and placement. Rather than
204 create a window of 0x0 size, a window without children is set to
205 200x200 by default so you can still manipulate it.
206
207 The gtk_widget_show() function lets GTK know that we are done setting
208 the attributes of this widget, and that it can display it.
209
210 The last line enters the GTK main processing loop.
211
212 <tscreen><verb>
213   gtk_main ();
214 </verb></tscreen>
215
216 gtk_main() is another call you will see in every GTK application.
217 When control reaches this point, GTK will sleep waiting for X events
218 (such as button or key presses), timeouts, or file IO notifications to
219 occur. In our simple example, however, events are ignored.
220
221 <!-- ----------------------------------------------------------------- -->
222 <sect1>Hello World in GTK
223 <p>
224 Now for a program with a widget (a button).  It's the classic
225 hello world a la GTK.
226
227 <tscreen><verb>
228 /* example-start helloworld helloworld.c */
229
230 #include <gtk/gtk.h>
231
232 /* This is a callback function. The data arguments are ignored
233  * in this example. More on callbacks below. */
234 void hello( GtkWidget *widget,
235             gpointer   data )
236 {
237     g_print ("Hello World\n");
238 }
239
240 gint delete_event( GtkWidget *widget,
241                    GdkEvent  *event,
242                    gpointer   data )
243 {
244     /* If you return FALSE in the "delete_event" signal handler,
245      * GTK will emit the "destroy" signal. Returning TRUE means
246      * you don't want the window to be destroyed.
247      * This is useful for popping up 'are you sure you want to quit?'
248      * type dialogs. */
249
250     g_print ("delete event occurred\n");
251
252     /* Change TRUE to FALSE and the main window will be destroyed with
253      * a "delete_event". */
254
255     return(TRUE);
256 }
257
258 /* Another callback */
259 void destroy( GtkWidget *widget,
260               gpointer   data )
261 {
262     gtk_main_quit();
263 }
264
265 int main( int   argc,
266           char *argv[] )
267 {
268     /* GtkWidget is the storage type for widgets */
269     GtkWidget *window;
270     GtkWidget *button;
271     
272     /* This is called in all GTK applications. Arguments are parsed
273      * from the command line and are returned to the application. */
274     gtk_init(&amp;argc, &amp;argv);
275     
276     /* create a new window */
277     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
278     
279     /* When the window is given the "delete_event" signal (this is given
280      * by the window manager, usually by the "close" option, or on the
281      * titlebar), we ask it to call the delete_event () function
282      * as defined above. The data passed to the callback
283      * function is NULL and is ignored in the callback function. */
284     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
285                         GTK_SIGNAL_FUNC (delete_event), NULL);
286     
287     /* Here we connect the "destroy" event to a signal handler.  
288      * This event occurs when we call gtk_widget_destroy() on the window,
289      * or if we return FALSE in the "delete_event" callback. */
290     gtk_signal_connect (GTK_OBJECT (window), "destroy",
291                         GTK_SIGNAL_FUNC (destroy), NULL);
292     
293     /* Sets the border width of the window. */
294     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
295     
296     /* Creates a new button with the label "Hello World". */
297     button = gtk_button_new_with_label ("Hello World");
298     
299     /* When the button receives the "clicked" signal, it will call the
300      * function hello() passing it NULL as its argument.  The hello()
301      * function is defined above. */
302     gtk_signal_connect (GTK_OBJECT (button), "clicked",
303                         GTK_SIGNAL_FUNC (hello), NULL);
304     
305     /* This will cause the window to be destroyed by calling
306      * gtk_widget_destroy(window) when "clicked".  Again, the destroy
307      * signal could come from here, or the window manager. */
308     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
309                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
310                                GTK_OBJECT (window));
311     
312     /* This packs the button into the window (a gtk container). */
313     gtk_container_add (GTK_CONTAINER (window), button);
314     
315     /* The final step is to display this newly created widget. */
316     gtk_widget_show (button);
317     
318     /* and the window */
319     gtk_widget_show (window);
320     
321     /* All GTK applications must have a gtk_main(). Control ends here
322      * and waits for an event to occur (like a key press or
323      * mouse event). */
324     gtk_main ();
325     
326     return(0);
327 }
328 /* example-end */
329 </verb></tscreen>
330
331 <!-- ----------------------------------------------------------------- -->
332 <sect1>Compiling Hello World <label id="sec_compiling">
333 <p>
334 To compile use:
335
336 <tscreen><verb>
337 gcc -Wall -g helloworld.c -o helloworld `gtk-config --cflags` \
338     `gtk-config --libs`
339 </verb></tscreen>
340
341 This uses the program <tt/gtk-config/, which comes with GTK. This
342 program "knows" what compiler switches are needed to compile programs
343 that use GTK. <tt/gtk-config --cflags/ will output a list of include
344 directories for the compiler to look in, and <tt>gtk-config --libs</>
345 will output the list of libraries for the compiler to link with and
346 the directories to find them in. In the aboce example they could have
347 been combined into a single instance, such as
348 <tt/`gtk-config --cflags --libs`/.
349
350 Note that the type of single quote used in the compile command above
351 is significant.
352
353 The libraries that are usually linked in are:
354 <itemize>
355 <item>The GTK library (-lgtk), the widget library, based on top of GDK.
356 <item>The GDK library (-lgdk), the Xlib wrapper.
357 <item>The gmodule library (-lgmodule), which is used to load run time
358 extensions.
359 <item>The GLib library (-lglib), containing miscellaneous functions;
360 only g_print() is used in this particular example. GTK is built on top
361 of glib so you will always require this library. See the section on
362 <ref id="sec_glib" name="GLib"> for details.
363 <item>The Xlib library (-lX11) which is used by GDK.
364 <item>The Xext library (-lXext). This contains code for shared memory
365 pixmaps and other X extensions.
366 <item>The math library (-lm). This is used by GTK for various purposes.
367 </itemize>
368
369 <!-- ----------------------------------------------------------------- -->
370 <sect1>Theory of Signals and Callbacks
371 <p>
372 Before we look in detail at <em>helloworld</em>, we'll discuss signals
373 and callbacks. GTK is an event driven toolkit, which means it will
374 sleep in gtk_main until an event occurs and control is passed to the
375 appropriate function.
376
377 This passing of control is done using the idea of "signals". (Note
378 that these signals are not the same as the Unix system signals, and
379 are not implemented using them, although the terminology is almost
380 identical.) When an event occurs, such as the press of a mouse button,
381 the appropriate signal will be "emitted" by the widget that was
382 pressed.  This is how GTK does most of its useful work. There are
383 signals that all widgets inherit, such as "destroy", and there are
384 signals that are widget specific, such as "toggled" on a toggle
385 button.
386
387 To make a button perform an action, we set up a signal handler to
388 catch these signals and call the appropriate function. This is done by
389 using a function such as:
390
391 <tscreen><verb>
392 gint gtk_signal_connect( GtkObject     *object,
393                          gchar         *name,
394                          GtkSignalFunc  func,
395                          gpointer       func_data );
396 </verb></tscreen>
397
398 where the first argument is the widget which will be emitting the
399 signal, and the second the name of the signal you wish to catch. The
400 third is the function you wish to be called when it is caught, and the
401 fourth, the data you wish to have passed to this function.
402
403 The function specified in the third argument is called a "callback
404 function", and should generally be of the form
405
406 <tscreen><verb>
407 void callback_func( GtkWidget *widget,
408                     gpointer   callback_data );
409 </verb></tscreen>
410
411 where the first argument will be a pointer to the widget that emitted
412 the signal, and the second a pointer to the data given as the last
413 argument to the gtk_signal_connect() function as shown above.
414
415 Note that the above form for a signal callback function declaration is
416 only a general guide, as some widget specific signals generate
417 different calling parameters. For example, the CList "select_row"
418 signal provides both row and column parameters.
419
420 Another call used in the <em>helloworld</em> example, is:
421
422 <tscreen><verb>
423 gint gtk_signal_connect_object( GtkObject     *object,
424                                 gchar         *name,
425                                 GtkSignalFunc  func,
426                                 GtkObject     *slot_object );
427 </verb></tscreen>
428
429 gtk_signal_connect_object() is the same as gtk_signal_connect() except
430 that the callback function only uses one argument, a pointer to a GTK
431 object. So when using this function to connect signals, the callback
432 should be of the form
433
434 <tscreen><verb>
435 void callback_func( GtkObject *object );
436 </verb></tscreen>
437
438 where the object is usually a widget. We usually don't setup callbacks
439 for gtk_signal_connect_object however. They are usually used to call a
440 GTK function that accepts a single widget or object as an argument, as
441 is the case in our <em>helloworld</em> example.
442
443 The purpose of having two functions to connect signals is simply to
444 allow the callbacks to have a different number of arguments. Many
445 functions in the GTK library accept only a single GtkWidget pointer as
446 an argument, so you want to use the gtk_signal_connect_object() for
447 these, whereas for your functions, you may need to have additional
448 data supplied to the callbacks.
449
450 <!-- ----------------------------------------------------------------- -->
451 <sect1>Events
452 <p>
453 In addition to the signal mechanism described above, there is a set
454 of <em>events</em> that reflect the X event mechanism. Callbacks may
455 also be attached to these events. These events are:
456
457 <itemize>
458 <item> event
459 <item> button_press_event
460 <item> button_release_event
461 <item> motion_notify_event
462 <item> delete_event
463 <item> destroy_event
464 <item> expose_event
465 <item> key_press_event
466 <item> key_release_event
467 <item> enter_notify_event
468 <item> leave_notify_event
469 <item> configure_event
470 <item> focus_in_event
471 <item> focus_out_event
472 <item> map_event
473 <item> unmap_event
474 <item> property_notify_event
475 <item> selection_clear_event
476 <item> selection_request_event
477 <item> selection_notify_event
478 <item> proximity_in_event
479 <item> proximity_out_event
480 <item> drag_begin_event
481 <item> drag_request_event
482 <item> drag_end_event
483 <item> drop_enter_event
484 <item> drop_leave_event
485 <item> drop_data_available_event
486 <item> other_event
487 </itemize>
488
489 In order to connect a callback function to one of these events, you
490 use the function gtk_signal_connect, as described above, using one of
491 the above event names as the <tt/name/ parameter. The callback
492 function for events has a slightly different form than that for
493 signals:
494
495 <tscreen><verb>
496 void callback_func( GtkWidget *widget,
497                     GdkEvent  *event,
498                     gpointer   callback_data );
499 </verb></tscreen>
500
501 GdkEvent is a C <tt/union/ structure whose type will depend upon which
502 of the above events has occurred. In order for us to tell which event
503 has been issued each of the possible alternatives has a <tt/type/
504 parameter which reflects the event being issued. The other components
505 of the event structure will depend upon the type of the
506 event. Possible values for the type are:
507
508 <tscreen><verb>
509   GDK_NOTHING
510   GDK_DELETE
511   GDK_DESTROY
512   GDK_EXPOSE
513   GDK_MOTION_NOTIFY
514   GDK_BUTTON_PRESS
515   GDK_2BUTTON_PRESS
516   GDK_3BUTTON_PRESS
517   GDK_BUTTON_RELEASE
518   GDK_KEY_PRESS
519   GDK_KEY_RELEASE
520   GDK_ENTER_NOTIFY
521   GDK_LEAVE_NOTIFY
522   GDK_FOCUS_CHANGE
523   GDK_CONFIGURE
524   GDK_MAP
525   GDK_UNMAP
526   GDK_PROPERTY_NOTIFY
527   GDK_SELECTION_CLEAR
528   GDK_SELECTION_REQUEST
529   GDK_SELECTION_NOTIFY
530   GDK_PROXIMITY_IN
531   GDK_PROXIMITY_OUT
532   GDK_DRAG_BEGIN
533   GDK_DRAG_REQUEST
534   GDK_DROP_ENTER
535   GDK_DROP_LEAVE
536   GDK_DROP_DATA_AVAIL
537   GDK_CLIENT_EVENT
538   GDK_VISIBILITY_NOTIFY
539   GDK_NO_EXPOSE
540   GDK_OTHER_EVENT       /* Deprecated, use filters instead */
541 </verb></tscreen>
542
543 So, to connect a callback function to one of these events we would use
544 something like:
545
546 <tscreen><verb>
547 gtk_signal_connect( GTK_OBJECT(button), "button_press_event",
548                     GTK_SIGNAL_FUNC(button_press_callback), 
549                     NULL);
550 </verb></tscreen>
551
552 This assumes that <tt/button/ is a Button widget. Now, when the
553 mouse is over the button and a mouse button is pressed, the function
554 <tt/button_press_callback/ will be called. This function may be
555 declared as:
556
557 <tscreen><verb>
558 static gint button_press_callback( GtkWidget      *widget, 
559                                    GdkEventButton *event,
560                                    gpointer        data );
561 </verb></tscreen>
562
563 Note that we can declare the second argument as type
564 <tt/GdkEventButton/ as we know what type of event will occur for this
565 function to be called.
566
567 The value returned from this function indicates whether the event
568 should be propagated further by the GTK event handling
569 mechanism. Returning TRUE indicates that the event has been handled,
570 and that it should not propagate further. Returning FALSE continues
571 the normal event handling.  See the section on
572 <ref id="sec_Adv_Events_and_Signals"
573 name="Advanced Event and Signal Handling"> for more details on this
574 propagation process.
575
576 For details on the GdkEvent data types, see the appendix entitled
577 <ref id="sec_GDK_Event_Types" name="GDK Event Types">.
578
579 <!-- ----------------------------------------------------------------- -->
580 <sect1>Stepping Through Hello World
581 <p>
582 Now that we know the theory behind this, let's clarify by walking
583 through the example <em>helloworld</em> program.
584
585 Here is the callback function that will be called when the button is
586 "clicked". We ignore both the widget and the data in this example, but
587 it is not hard to do things with them. The next example will use the
588 data argument to tell us which button was pressed.
589
590 <tscreen><verb>
591 void hello( GtkWidget *widget,
592             gpointer   data )
593 {
594     g_print ("Hello World\n");
595 }
596 </verb></tscreen>
597
598 The next callback is a bit special. The "delete_event" occurs when the
599 window manager sends this event to the application. We have a choice
600 here as to what to do about these events. We can ignore them, make
601 some sort of response, or simply quit the application.
602
603 The value you return in this callback lets GTK know what action to
604 take.  By returning TRUE, we let it know that we don't want to have
605 the "destroy" signal emitted, keeping our application running. By
606 returning FALSE, we ask that "destroy" be emitted, which in turn will
607 call our "destroy" signal handler.
608
609 <tscreen><verb>
610 gint delete_event( GtkWidget *widget,
611                    GdkEvent  *event,
612                    gpointer   data )
613 {
614     g_print ("delete event occurred\n");
615
616     return (TRUE); 
617 }
618 </verb></tscreen>
619
620 Here is another callback function which causes the program to quit by
621 calling gtk_main_quit(). This function tells GTK that it is to exit
622 from gtk_main when control is returned to it.
623
624 <tscreen><verb>
625 void destroy( GtkWidget *widget,
626               gpointer   data )
627 {
628     gtk_main_quit ();
629 }
630 </verb></tscreen>
631
632 I assume you know about the main() function... yes, as with other
633 applications, all GTK applications will also have one of these.
634
635 <tscreen><verb>
636 int main( int   argc,
637           char *argv[] )
638 {
639 </verb></tscreen>
640
641 This next part declares pointers to a structure of type
642 GtkWidget. These are used below to create a window and a button.
643
644 <tscreen><verb>
645     GtkWidget *window;
646     GtkWidget *button;
647 </verb></tscreen>
648
649 Here is our gtk_init again. As before, this initializes the toolkit,
650 and parses the arguments found on the command line. Any argument it
651 recognizes from the command line, it removes from the list, and
652 modifies argc and argv to make it look like they never existed,
653 allowing your application to parse the remaining arguments.
654
655 <tscreen><verb>
656     gtk_init (&amp;argc, &amp;argv);
657 </verb></tscreen>
658
659 Create a new window. This is fairly straightforward. Memory is
660 allocated for the GtkWidget *window structure so it now points to a
661 valid structure. It sets up a new window, but it is not displayed
662 until we call gtk_widget_show(window) near the end of our program.
663
664 <tscreen><verb>
665     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
666 </verb></tscreen>
667
668 Here are two examples of connecting a signal handler to an object, in
669 this case, the window. Here, the "delete_event" and "destroy" signals
670 are caught. The first is emitted when we use the window manager to
671 kill the window, or when we use the gtk_widget_destroy() call passing
672 in the window widget as the object to destroy. The second is emitted
673 when, in the "delete_event" handler, we return FALSE.
674  
675 The <tt/GTK_OBJECT/ and <tt/GTK_SIGNAL_FUNC/ are macros that perform
676 type casting and checking for us, as well as aid the readability of
677 the code.
678
679 <tscreen><verb>
680     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
681                         GTK_SIGNAL_FUNC (delete_event), NULL);
682     gtk_signal_connect (GTK_OBJECT (window), "destroy",
683                         GTK_SIGNAL_FUNC (destroy), NULL);
684 </verb></tscreen>
685
686 This next function is used to set an attribute of a container object.
687 This just sets the window so it has a blank area along the inside of
688 it 10 pixels wide where no widgets will go. There are other similar
689 functions which we will look at in the section on
690 <ref id="sec_setting_widget_attributes" name="Setting Widget Attributes">
691
692 And again, <tt/GTK_CONTAINER/ is a macro to perform type casting.
693
694 <tscreen><verb>
695     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
696 </verb></tscreen>
697
698 This call creates a new button. It allocates space for a new GtkWidget
699 structure in memory, initializes it, and makes the button pointer
700 point to it. It will have the label "Hello World" on it when
701 displayed.
702
703 <tscreen><verb>
704     button = gtk_button_new_with_label ("Hello World");
705 </verb></tscreen>
706
707 Here, we take this button, and make it do something useful. We attach
708 a signal handler to it so when it emits the "clicked" signal, our
709 hello() function is called. The data is ignored, so we simply pass in
710 NULL to the hello() callback function. Obviously, the "clicked" signal
711 is emitted when we click the button with our mouse pointer.
712
713 <tscreen><verb>
714     gtk_signal_connect (GTK_OBJECT (button), "clicked",
715                         GTK_SIGNAL_FUNC (hello), NULL);
716 </verb></tscreen>
717
718 We are also going to use this button to exit our program. This will
719 illustrate how the "destroy" signal may come from either the window
720 manager, or our program. When the button is "clicked", same as above,
721 it calls the first hello() callback function, and then this one in the
722 order they are set up. You may have as many callback functions as you
723 need, and all will be executed in the order you connected
724 them. Because the gtk_widget_destroy() function accepts only a
725 GtkWidget *widget as an argument, we use the
726 gtk_signal_connect_object() function here instead of straight
727 gtk_signal_connect().
728
729 <tscreen><verb>
730     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
731                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
732                                GTK_OBJECT (window));
733 </verb></tscreen>
734
735 This is a packing call, which will be explained in depth later on in
736 <ref id="sec_packing_widgets" name="Packing Widgets">. But it is
737 fairly easy to understand. It simply tells GTK that the button is to
738 be placed in the window where it will be displayed. Note that a GTK
739 container can only contain one widget. There are other widgets, that
740 are described later, which are designed to layout multiple widgets in
741 various ways.
742  
743 <tscreen><verb>
744     gtk_container_add (GTK_CONTAINER (window), button);
745 </verb></tscreen>
746
747 Now we have everything set up the way we want it to be. With all the
748 signal handlers in place, and the button placed in the window where it
749 should be, we ask GTK to "show" the widgets on the screen. The window
750 widget is shown last so the whole window will pop up at once rather
751 than seeing the window pop up, and then the button form inside of
752 it. Although with such a simple example, you'd never notice.
753
754 <tscreen><verb>
755     gtk_widget_show (button);
756
757     gtk_widget_show (window);
758 </verb></tscreen>
759
760 And of course, we call gtk_main() which waits for events to come from
761 the X server and will call on the widgets to emit signals when these
762 events come.
763
764 <tscreen><verb>
765     gtk_main ();
766 </verb></tscreen>
767
768 And the final return. Control returns here after gtk_quit() is called.
769
770 <tscreen><verb>
771     return (0;
772 </verb></tscreen>
773
774 Now, when we click the mouse button on a GTK button, the widget emits
775 a "clicked" signal. In order for us to use this information, our
776 program sets up a signal handler to catch that signal, which
777 dispatches the function of our choice. In our example, when the button
778 we created is "clicked", the hello() function is called with a NULL
779 argument, and then the next handler for this signal is called. This
780 calls the gtk_widget_destroy() function, passing it the window widget
781 as its argument, destroying the window widget. This causes the window
782 to emit the "destroy" signal, which is caught, and calls our destroy()
783 callback function, which simply exits GTK.
784
785 Another course of events is to use the window manager to kill the
786 window, which will cause the "delete_event" to be emitted. This will
787 call our "delete_event" handler. If we return TRUE here, the window
788 will be left as is and nothing will happen. Returning FALSE will cause
789 GTK to emit the "destroy" signal which of course calls the "destroy"
790 callback, exiting GTK.
791
792 <!-- ***************************************************************** -->
793 <sect>Moving On
794 <!-- ***************************************************************** -->
795
796 <!-- ----------------------------------------------------------------- -->
797 <sect1>Data Types
798 <p>
799 There are a few things you probably noticed in the previous examples
800 that need explaining. The gint, gchar, etc. that you see are typedefs
801 to int and char, respectively, that are part of the GLlib system. This
802 is done to get around that nasty dependency on the size of simple data
803 types when doing calculations.
804
805 A good example is "gint32" which will be typedef'd to a 32 bit integer
806 for any given platform, whether it be the 64 bit alpha, or the 32 bit
807 i386. The typedefs are very straightforward and intuitive. They are
808 all defined in glib/glib.h (which gets included from gtk.h).
809
810 You'll also notice GTK's ability to use GtkWidget when the function
811 calls for an Object. GTK is an object oriented design, and a widget
812 is an object.
813
814 <!-- ----------------------------------------------------------------- -->
815 <sect1>More on Signal Handlers
816 <p>
817 Lets take another look at the gtk_signal_connect declaration.
818
819 <tscreen><verb>
820 gint gtk_signal_connect( GtkObject *object,
821                          gchar *name,
822                          GtkSignalFunc func,
823                          gpointer func_data );
824 </verb></tscreen>
825
826 Notice the gint return value? This is a tag that identifies your
827 callback function. As stated above, you may have as many callbacks per
828 signal and per object as you need, and each will be executed in turn,
829 in the order they were attached.
830
831 This tag allows you to remove this callback from the list by using:
832
833 <tscreen><verb>
834 void gtk_signal_disconnect( GtkObject *object,
835                             gint id );
836 </verb></tscreen>
837
838 So, by passing in the widget you wish to remove the handler from, and
839 the tag returned by one of the signal_connect functions, you can
840 disconnect a signal handler.
841
842 Another function to remove all the signal handers from an object is:
843
844 <tscreen><verb>
845 void gtk_signal_handlers_destroy( GtkObject *object );
846 </verb></tscreen>
847
848 This call is fairly self explanatory. It simply removes all the
849 current signal handlers from the object passed in as the first
850 argument.
851
852 <!-- ----------------------------------------------------------------- -->
853 <sect1>An Upgraded Hello World
854 <p>
855 Let's take a look at a slightly improved <em>helloworld</em> with
856 better examples of callbacks. This will also introduce us to our next
857 topic, packing widgets.
858
859 <tscreen><verb>
860 /* example-start helloworld2 helloworld2.c */
861
862 #include <gtk/gtk.h>
863
864 /* Our new improved callback.  The data passed to this function
865  * is printed to stdout. */
866 void callback( GtkWidget *widget,
867                gpointer   data )
868 {
869     g_print ("Hello again - %s was pressed\n", (char *) data);
870 }
871
872 /* another callback */
873 void delete_event( GtkWidget *widget,
874                    GdkEvent  *event,
875                    gpointer   data )
876 {
877     gtk_main_quit ();
878 }
879
880 int main( int   argc,
881           char *argv[] )
882 {
883     /* GtkWidget is the storage type for widgets */
884     GtkWidget *window;
885     GtkWidget *button;
886     GtkWidget *box1;
887
888     /* This is called in all GTK applications. Arguments are parsed
889      * from the command line and are returned to the application. */
890     gtk_init (&amp;argc, &amp;argv);
891
892     /* Create a new window */
893     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
894
895     /* This is a new call, which just sets the title of our
896      * new window to "Hello Buttons!" */
897     gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
898
899     /* Here we just set a handler for delete_event that immediately
900      * exits GTK. */
901     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
902                         GTK_SIGNAL_FUNC (delete_event), NULL);
903
904     /* Sets the border width of the window. */
905     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
906
907     /* We create a box to pack widgets into.  This is described in detail
908      * in the "packing" section. The box is not really visible, it
909      * is just used as a tool to arrange widgets. */
910     box1 = gtk_hbox_new(FALSE, 0);
911
912     /* Put the box into the main window. */
913     gtk_container_add (GTK_CONTAINER (window), box1);
914
915     /* Creates a new button with the label "Button 1". */
916     button = gtk_button_new_with_label ("Button 1");
917
918     /* Now when the button is clicked, we call the "callback" function
919      * with a pointer to "button 1" as its argument */
920     gtk_signal_connect (GTK_OBJECT (button), "clicked",
921                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
922
923     /* Instead of gtk_container_add, we pack this button into the invisible
924      * box, which has been packed into the window. */
925     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
926
927     /* Always remember this step, this tells GTK that our preparation for
928      * this button is complete, and it can now be displayed. */
929     gtk_widget_show(button);
930
931     /* Do these same steps again to create a second button */
932     button = gtk_button_new_with_label ("Button 2");
933
934     /* Call the same callback function with a different argument,
935      * passing a pointer to "button 2" instead. */
936     gtk_signal_connect (GTK_OBJECT (button), "clicked",
937                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
938
939     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
940
941     /* The order in which we show the buttons is not really important, but I
942      * recommend showing the window last, so it all pops up at once. */
943     gtk_widget_show(button);
944
945     gtk_widget_show(box1);
946
947     gtk_widget_show (window);
948
949     /* Rest in gtk_main and wait for the fun to begin! */
950     gtk_main ();
951
952     return(0);
953 }
954 /* example-end */
955 </verb></tscreen>
956
957 Compile this program using the same linking arguments as our first
958 example.  You'll notice this time there is no easy way to exit the
959 program, you have to use your window manager or command line to kill
960 it. A good exercise for the reader would be to insert a third "Quit"
961 button that will exit the program. You may also wish to play with the
962 options to gtk_box_pack_start() while reading the next section.  Try
963 resizing the window, and observe the behavior.
964
965 Just as a side note, there is another useful define for
966 gtk_window_new() - <tt/GTK_WINDOW_DIALOG/. This interacts with the
967 window manager a little differently and should be used for transient
968 windows.
969
970 <!-- ***************************************************************** -->
971 <sect>Packing Widgets <label id="sec_packing_widgets">
972 <!-- ***************************************************************** -->
973 <p>
974 When creating an application, you'll want to put more than one widget
975 inside a window. Our first <em>helloworld</em> example only used one
976 widget so we could simply use a gtk_container_add call to "pack" the
977 widget into the window. But when you want to put more than one widget
978 into a window, how do you control where that widget is positioned?
979 This is where packing comes in.
980
981 <!-- ----------------------------------------------------------------- -->
982 <sect1>Theory of Packing Boxes
983 <p>
984 Most packing is done by creating boxes as in the example above. These
985 are invisible widget containers that we can pack our widgets into
986 which come in two forms, a horizontal box, and a vertical box. When
987 packing widgets into a horizontal box, the objects are inserted
988 horizontally from left to right or right to left depending on the call
989 used. In a vertical box, widgets are packed from top to bottom or vice
990 versa. You may use any combination of boxes inside or beside other
991 boxes to create the desired effect.
992
993 To create a new horizontal box, we use a call to gtk_hbox_new(), and
994 for vertical boxes, gtk_vbox_new(). The gtk_box_pack_start() and
995 gtk_box_pack_end() functions are used to place objects inside of these
996 containers. The gtk_box_pack_start() function will start at the top
997 and work its way down in a vbox, and pack left to right in an hbox.
998 gtk_box_pack_end() will do the opposite, packing from bottom to top in
999 a vbox, and right to left in an hbox. Using these functions allows us
1000 to right justify or left justify our widgets and may be mixed in any
1001 way to achieve the desired effect. We will use gtk_box_pack_start() in
1002 most of our examples. An object may be another container or a
1003 widget. In fact, many widgets are actually containers themselves,
1004 including the button, but we usually only use a label inside a button.
1005
1006 By using these calls, GTK knows where you want to place your widgets
1007 so it can do automatic resizing and other nifty things. There are also
1008 a number of options as to how your widgets should be packed. As you
1009 can imagine, this method gives us a quite a bit of flexibility when
1010 placing and creating widgets.
1011
1012 <!-- ----------------------------------------------------------------- -->
1013 <sect1>Details of Boxes
1014 <p>
1015 Because of this flexibility, packing boxes in GTK can be confusing at
1016 first. There are a lot of options, and it's not immediately obvious how
1017 they all fit together. In the end, however, there are basically five
1018 different styles.
1019
1020 <? <CENTER> >
1021 <?
1022 <IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528"
1023 HEIGHT="235" ALT="Box Packing Example Image">
1024 >
1025 <? </CENTER> >
1026
1027 Each line contains one horizontal box (hbox) with several buttons. The
1028 call to gtk_box_pack is shorthand for the call to pack each of the
1029 buttons into the hbox. Each of the buttons is packed into the hbox the
1030 same way (i.e., same arguments to the gtk_box_pack_start() function).
1031
1032 This is the declaration of the gtk_box_pack_start function.
1033
1034 <tscreen><verb>
1035 void gtk_box_pack_start( GtkBox    *box,
1036                          GtkWidget *child,
1037                          gint       expand,
1038                          gint       fill,
1039                          gint       padding );
1040 </verb></tscreen>
1041
1042 The first argument is the box you are packing the object into, the
1043 second is the object. The objects will all be buttons for now, so
1044 we'll be packing buttons into boxes.
1045
1046 The expand argument to gtk_box_pack_start() and gtk_box_pack_end()
1047 controls whether the widgets are laid out in the box to fill in all
1048 the extra space in the box so the box is expanded to fill the area
1049 allotted to it (TRUE); or the box is shrunk to just fit the widgets
1050 (FALSE). Setting expand to FALSE will allow you to do right and left
1051 justification of your widgets.  Otherwise, they will all expand to fit
1052 into the box, and the same effect could be achieved by using only one
1053 of gtk_box_pack_start or gtk_box_pack_end.
1054
1055 The fill argument to the gtk_box_pack functions control whether the
1056 extra space is allocated to the objects themselves (TRUE), or as extra
1057 padding in the box around these objects (FALSE). It only has an effect
1058 if the expand argument is also TRUE.
1059
1060 When creating a new box, the function looks like this:
1061
1062 <tscreen><verb>
1063 GtkWidget *gtk_hbox_new (gint homogeneous,
1064                          gint spacing);
1065 </verb></tscreen>
1066
1067 The homogeneous argument to gtk_hbox_new (and the same for
1068 gtk_vbox_new) controls whether each object in the box has the same
1069 size (i.e., the same width in an hbox, or the same height in a
1070 vbox). If it is set, the gtk_box_pack routines function essentially
1071 as if the <tt/expand/ argument was always turned on.
1072
1073 What's the difference between spacing (set when the box is created)
1074 and padding (set when elements are packed)? Spacing is added between
1075 objects, and padding is added on either side of an object. The
1076 following figure should make it clearer:
1077
1078 <? <CENTER> >
1079 <?
1080 <IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509"
1081 HEIGHT="213" VSPACE="15" HSPACE="10"
1082 ALT="Box Packing Example Image">
1083 >
1084 <? </CENTER> >
1085
1086 Here is the code used to create the above images. I've commented it
1087 fairly heavily so I hope you won't have any problems following
1088 it. Compile it yourself and play with it.
1089
1090 <!-- ----------------------------------------------------------------- -->
1091 <sect1>Packing Demonstration Program
1092 <p>
1093 <tscreen><verb>
1094 /* example-start packbox packbox.c */
1095
1096 #include <stdio.h>
1097 #include "gtk/gtk.h"
1098
1099 void delete_event( GtkWidget *widget,
1100                    GdkEvent  *event,
1101                    gpointer   data )
1102 {
1103     gtk_main_quit ();
1104 }
1105
1106 /* Make a new hbox filled with button-labels. Arguments for the 
1107  * variables we're interested are passed in to this function. 
1108  * We do not show the box, but do show everything inside. */
1109 GtkWidget *make_box( gint homogeneous,
1110                      gint spacing,
1111                      gint expand,
1112                      gint fill,
1113                      gint padding ) 
1114 {
1115     GtkWidget *box;
1116     GtkWidget *button;
1117     char padstr[80];
1118     
1119     /* Create a new hbox with the appropriate homogeneous
1120      * and spacing settings */
1121     box = gtk_hbox_new (homogeneous, spacing);
1122     
1123     /* Create a series of buttons with the appropriate settings */
1124     button = gtk_button_new_with_label ("gtk_box_pack");
1125     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1126     gtk_widget_show (button);
1127     
1128     button = gtk_button_new_with_label ("(box,");
1129     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1130     gtk_widget_show (button);
1131     
1132     button = gtk_button_new_with_label ("button,");
1133     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1134     gtk_widget_show (button);
1135     
1136     /* Create a button with the label depending on the value of
1137      * expand. */
1138     if (expand == TRUE)
1139             button = gtk_button_new_with_label ("TRUE,");
1140     else
1141             button = gtk_button_new_with_label ("FALSE,");
1142     
1143     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1144     gtk_widget_show (button);
1145     
1146     /* This is the same as the button creation for "expand"
1147      * above, but uses the shorthand form. */
1148     button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
1149     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1150     gtk_widget_show (button);
1151     
1152     sprintf (padstr, "%d);", padding);
1153     
1154     button = gtk_button_new_with_label (padstr);
1155     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1156     gtk_widget_show (button);
1157     
1158     return box;
1159 }
1160
1161 int main( int   argc,
1162           char *argv[]) 
1163 {
1164     GtkWidget *window;
1165     GtkWidget *button;
1166     GtkWidget *box1;
1167     GtkWidget *box2;
1168     GtkWidget *separator;
1169     GtkWidget *label;
1170     GtkWidget *quitbox;
1171     int which;
1172     
1173     /* Our init, don't forget this! :) */
1174     gtk_init (&amp;argc, &amp;argv);
1175     
1176     if (argc != 2) {
1177         fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n");
1178         /* This just does cleanup in GTK and exits with an exit status of 1. */
1179         gtk_exit (1);
1180     }
1181     
1182     which = atoi (argv[1]);
1183
1184     /* Create our window */
1185     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1186
1187     /* You should always remember to connect the delete_event signal
1188      * to the main window. This is very important for proper intuitive
1189      * behavior */
1190     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1191                         GTK_SIGNAL_FUNC (delete_event), NULL);
1192     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1193     
1194     /* We create a vertical box (vbox) to pack the horizontal boxes into.
1195      * This allows us to stack the horizontal boxes filled with buttons one
1196      * on top of the other in this vbox. */
1197     box1 = gtk_vbox_new (FALSE, 0);
1198     
1199     /* which example to show. These correspond to the pictures above. */
1200     switch (which) {
1201     case 1:
1202         /* create a new label. */
1203         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1204         
1205         /* Align the label to the left side.  We'll discuss this function and 
1206          * others in the section on Widget Attributes. */
1207         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1208
1209         /* Pack the label into the vertical box (vbox box1).  Remember that 
1210          * widgets added to a vbox will be packed one on top of the other in
1211          * order. */
1212         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1213         
1214         /* Show the label */
1215         gtk_widget_show (label);
1216         
1217         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1218          * expand = FALSE, fill = FALSE, padding = 0 */
1219         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1220         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1221         gtk_widget_show (box2);
1222
1223         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1224          * expand = FALSE, fill = FALSE, padding = 0 */
1225         box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
1226         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1227         gtk_widget_show (box2);
1228         
1229         /* Args are: homogeneous, spacing, expand, fill, padding */
1230         box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
1231         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1232         gtk_widget_show (box2);
1233         
1234         /* Creates a separator, we'll learn more about these later, 
1235          * but they are quite simple. */
1236         separator = gtk_hseparator_new ();
1237         
1238         /* Pack the separator into the vbox. Remember each of these
1239          * widgets is being packed into a vbox, so they'll be stacked
1240          * vertically. */
1241         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1242         gtk_widget_show (separator);
1243         
1244         /* Create another new label, and show it. */
1245         label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
1246         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1247         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1248         gtk_widget_show (label);
1249         
1250         /* Args are: homogeneous, spacing, expand, fill, padding */
1251         box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
1252         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1253         gtk_widget_show (box2);
1254         
1255         /* Args are: homogeneous, spacing, expand, fill, padding */
1256         box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
1257         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1258         gtk_widget_show (box2);
1259         
1260         /* Another new separator. */
1261         separator = gtk_hseparator_new ();
1262         /* The last 3 arguments to gtk_box_pack_start are:
1263          * expand, fill, padding. */
1264         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1265         gtk_widget_show (separator);
1266         
1267         break;
1268
1269     case 2:
1270
1271         /* Create a new label, remember box1 is a vbox as created 
1272          * near the beginning of main() */
1273         label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
1274         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1275         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1276         gtk_widget_show (label);
1277         
1278         /* Args are: homogeneous, spacing, expand, fill, padding */
1279         box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
1280         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1281         gtk_widget_show (box2);
1282         
1283         /* Args are: homogeneous, spacing, expand, fill, padding */
1284         box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
1285         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1286         gtk_widget_show (box2);
1287         
1288         separator = gtk_hseparator_new ();
1289         /* The last 3 arguments to gtk_box_pack_start are:
1290          * expand, fill, padding. */
1291         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1292         gtk_widget_show (separator);
1293         
1294         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1295         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1296         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1297         gtk_widget_show (label);
1298         
1299         /* Args are: homogeneous, spacing, expand, fill, padding */
1300         box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
1301         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1302         gtk_widget_show (box2);
1303         
1304         /* Args are: homogeneous, spacing, expand, fill, padding */
1305         box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
1306         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1307         gtk_widget_show (box2);
1308         
1309         separator = gtk_hseparator_new ();
1310         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1311         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1312         gtk_widget_show (separator);
1313         break;
1314     
1315     case 3:
1316
1317         /* This demonstrates the ability to use gtk_box_pack_end() to
1318          * right justify widgets. First, we create a new box as before. */
1319         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1320
1321         /* Create the label that will be put at the end. */
1322         label = gtk_label_new ("end");
1323         /* Pack it using gtk_box_pack_end(), so it is put on the right
1324          * side of the hbox created in the make_box() call. */
1325         gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
1326         /* Show the label. */
1327         gtk_widget_show (label);
1328         
1329         /* Pack box2 into box1 (the vbox remember ? :) */
1330         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1331         gtk_widget_show (box2);
1332         
1333         /* A separator for the bottom. */
1334         separator = gtk_hseparator_new ();
1335         /* This explicitly sets the separator to 400 pixels wide by 5 pixels
1336          * high. This is so the hbox we created will also be 400 pixels wide,
1337          * and the "end" label will be separated from the other labels in the
1338          * hbox. Otherwise, all the widgets in the hbox would be packed as
1339          * close together as possible. */
1340         gtk_widget_set_usize (separator, 400, 5);
1341         /* pack the separator into the vbox (box1) created near the start 
1342          * of main() */
1343         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1344         gtk_widget_show (separator);    
1345     }
1346     
1347     /* Create another new hbox.. remember we can use as many as we need! */
1348     quitbox = gtk_hbox_new (FALSE, 0);
1349     
1350     /* Our quit button. */
1351     button = gtk_button_new_with_label ("Quit");
1352     
1353     /* Setup the signal to terminate the program when the button is clicked */
1354     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1355                                GTK_SIGNAL_FUNC (gtk_main_quit),
1356                                GTK_OBJECT (window));
1357     /* Pack the button into the quitbox.
1358      * The last 3 arguments to gtk_box_pack_start are:
1359      * expand, fill, padding. */
1360     gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
1361     /* pack the quitbox into the vbox (box1) */
1362     gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
1363     
1364     /* Pack the vbox (box1) which now contains all our widgets, into the
1365      * main window. */
1366     gtk_container_add (GTK_CONTAINER (window), box1);
1367     
1368     /* And show everything left */
1369     gtk_widget_show (button);
1370     gtk_widget_show (quitbox);
1371     
1372     gtk_widget_show (box1);
1373     /* Showing the window last so everything pops up at once. */
1374     gtk_widget_show (window);
1375     
1376     /* And of course, our main function. */
1377     gtk_main ();
1378
1379     /* Control returns here when gtk_main_quit() is called, but not when 
1380      * gtk_exit is used. */
1381     
1382     return(0);
1383 }
1384 /* example-end */
1385 </verb></tscreen>
1386
1387 <!-- ----------------------------------------------------------------- -->
1388 <sect1>Packing Using Tables
1389 <p>
1390 Let's take a look at another way of packing - Tables. These can be
1391 extremely useful in certain situations.
1392
1393 Using tables, we create a grid that we can place widgets in. The
1394 widgets may take up as many spaces as we specify.
1395
1396 The first thing to look at, of course, is the gtk_table_new function:
1397
1398 <tscreen><verb>
1399 GtkWidget *gtk_table_new( gint rows,
1400                           gint columns,
1401                           gint homogeneous );
1402 </verb></tscreen>
1403
1404 The first argument is the number of rows to make in the table, while
1405 the second, obviously, is the number of columns.
1406
1407 The homogeneous argument has to do with how the table's boxes are
1408 sized. If homogeneous is TRUE, the table boxes are resized to the size
1409 of the largest widget in the table. If homogeneous is FALSE, the size
1410 of a table boxes is dictated by the tallest widget in its same row,
1411 and the widest widget in its column.
1412
1413 The rows and columns are laid out from 0 to n, where n was the number
1414 specified in the call to gtk_table_new. So, if you specify rows = 2
1415 and columns = 2, the layout would look something like this:
1416
1417 <tscreen><verb>
1418  0          1          2
1419 0+----------+----------+
1420  |          |          |
1421 1+----------+----------+
1422  |          |          |
1423 2+----------+----------+
1424 </verb></tscreen>
1425
1426 Note that the coordinate system starts in the upper left hand corner.
1427 To place a widget into a box, use the following function:
1428
1429 <tscreen><verb>
1430 void gtk_table_attach( GtkTable  *table,
1431                        GtkWidget *child,
1432                        gint       left_attach,
1433                        gint       right_attach,
1434                        gint       top_attach,
1435                        gint       bottom_attach,
1436                        gint       xoptions,
1437                        gint       yoptions,
1438                        gint       xpadding,
1439                        gint       ypadding );
1440 </verb></tscreen>                                      
1441
1442 The first argument ("table") is the table you've created and the
1443 second ("child") the widget you wish to place in the table.
1444
1445 The left and right attach arguments specify where to place the widget,
1446 and how many boxes to use. If you want a button in the lower right
1447 table entry of our 2x2 table, and want it to fill that entry ONLY,
1448 left_attach would be = 1, right_attach = 2, top_attach = 1,
1449 bottom_attach = 2.
1450
1451 Now, if you wanted a widget to take up the whole top row of our 2x2
1452 table, you'd use left_attach = 0, right_attach = 2, top_attach = 0,
1453 bottom_attach = 1.
1454
1455 The xoptions and yoptions are used to specify packing options and may
1456 be bitwise OR'ed together to allow multiple options.
1457
1458 These options are:
1459 <itemize>
1460 <item><tt/GTK_FILL/ - If the table box is larger than the widget, and
1461 <tt/GTK_FILL/ is specified, the widget will expand to use all the room
1462 available.
1463
1464 <item><tt/GTK_SHRINK/ - If the table widget was allocated less space
1465 then was requested (usually by the user resizing the window), then the
1466 widgets would normally just be pushed off the bottom of the window and
1467 disappear. If <tt/GTK_SHRINK/ is specified, the widgets will shrink
1468 with the table.
1469
1470 <item><tt/GTK_EXPAND/ - This will cause the table to expand to use up
1471 any remaining space in the window.
1472 </itemize>
1473
1474 Padding is just like in boxes, creating a clear area around the widget
1475 specified in pixels.
1476
1477 gtk_table_attach() has a LOT of options.  So, there's a shortcut:
1478
1479 <tscreen><verb>
1480 void gtk_table_attach_defaults( GtkTable  *table,
1481                                 GtkWidget *widget,
1482                                 gint       left_attach,
1483                                 gint       right_attach,
1484                                 gint       top_attach,
1485                                 gint       bottom_attach );
1486 </verb></tscreen>
1487
1488 The X and Y options default to <tt/GTK_FILL | GTK_EXPAND/, and X and Y
1489 padding are set to 0. The rest of the arguments are identical to the
1490 previous function.
1491
1492 We also have gtk_table_set_row_spacing() and
1493 gtk_table_set_col_spacing(). These places spacing between the rows at
1494 the specified row or column.
1495
1496 <tscreen><verb>
1497 void gtk_table_set_row_spacing( GtkTable *table,
1498                                 gint      row,
1499                                 gint      spacing );
1500 </verb></tscreen>
1501
1502 and
1503
1504 <tscreen><verb>
1505 void gtk_table_set_col_spacing ( GtkTable *table,
1506                                  gint      column,
1507                                  gint      spacing );
1508 </verb></tscreen>
1509
1510 Note that for columns, the space goes to the right of the column, and
1511 for rows, the space goes below the row.
1512
1513 You can also set a consistent spacing of all rows and/or columns with:
1514
1515 <tscreen><verb>
1516 void gtk_table_set_row_spacings( GtkTable *table,
1517                                  gint      spacing );
1518 </verb></tscreen>
1519
1520 And,
1521
1522 <tscreen><verb>
1523 void gtk_table_set_col_spacings( GtkTable *table,
1524                                  gint      spacing );
1525 </verb></tscreen>
1526
1527 Note that with these calls, the last row and last column do not get
1528 any spacing.
1529
1530 <!-- ----------------------------------------------------------------- -->
1531 <sect1>Table Packing Example
1532 <p>
1533 Here we make a window with three buttons in a 2x2 table.
1534 The first two buttons will be placed in the upper row.
1535 A third, quit button, is placed in the lower row, spanning both columns.
1536 Which means it should look something like this:
1537
1538 <? <CENTER> >
1539 <?
1540 <IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" 
1541 ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120">
1542 >
1543 <? </CENTER> >
1544
1545 Here's the source code:
1546
1547 <tscreen><verb>
1548 /* example-start table table.c */
1549
1550 #include <gtk/gtk.h>
1551
1552 /* Our callback.
1553  * The data passed to this function is printed to stdout */
1554 void callback( GtkWidget *widget,
1555                gpointer   data )
1556 {
1557     g_print ("Hello again - %s was pressed\n", (char *) data);
1558 }
1559
1560 /* This callback quits the program */
1561 void delete_event( GtkWidget *widget,
1562                    GdkEvent  *event,
1563                    gpointer   data )
1564 {
1565     gtk_main_quit ();
1566 }
1567
1568 int main( int   argc,
1569           char *argv[] )
1570 {
1571     GtkWidget *window;
1572     GtkWidget *button;
1573     GtkWidget *table;
1574
1575     gtk_init (&amp;argc, &amp;argv);
1576
1577     /* Create a new window */
1578     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1579
1580     /* Set the window title */
1581     gtk_window_set_title (GTK_WINDOW (window), "Table");
1582
1583     /* Set a handler for delete_event that immediately
1584      * exits GTK. */
1585     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1586                         GTK_SIGNAL_FUNC (delete_event), NULL);
1587
1588     /* Sets the border width of the window. */
1589     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
1590
1591     /* Create a 2x2 table */
1592     table = gtk_table_new (2, 2, TRUE);
1593
1594     /* Put the table in the main window */
1595     gtk_container_add (GTK_CONTAINER (window), table);
1596
1597     /* Create first button */
1598     button = gtk_button_new_with_label ("button 1");
1599
1600     /* When the button is clicked, we call the "callback" function
1601      * with a pointer to "button 1" as its argument */
1602     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1603               GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
1604
1605
1606     /* Insert button 1 into the upper left quadrant of the table */
1607     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);
1608
1609     gtk_widget_show (button);
1610
1611     /* Create second button */
1612
1613     button = gtk_button_new_with_label ("button 2");
1614
1615     /* When the button is clicked, we call the "callback" function
1616      * with a pointer to "button 2" as its argument */
1617     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1618               GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
1619     /* Insert button 2 into the upper right quadrant of the table */
1620     gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);
1621
1622     gtk_widget_show (button);
1623
1624     /* Create "Quit" button */
1625     button = gtk_button_new_with_label ("Quit");
1626
1627     /* When the button is clicked, we call the "delete_event" function
1628      * and the program exits */
1629     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1630                         GTK_SIGNAL_FUNC (delete_event), NULL);
1631
1632     /* Insert the quit button into the both 
1633      * lower quadrants of the table */
1634     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);
1635
1636     gtk_widget_show (button);
1637
1638     gtk_widget_show (table);
1639     gtk_widget_show (window);
1640
1641     gtk_main ();
1642
1643     return 0;
1644 }
1645 /* example-end */
1646 </verb></tscreen>
1647
1648 <!-- ***************************************************************** -->
1649 <sect>Widget Overview
1650 <!-- ***************************************************************** -->
1651 <p>
1652 The general steps to creating a widget in GTK are:
1653 <enum>
1654 <item> gtk_*_new - one of various functions to create a new widget.
1655 These are all detailed in this section.
1656
1657 <item> Connect all signals and events we wish to use to the
1658 appropriate handlers.
1659
1660 <item> Set the attributes of the widget.
1661
1662 <item> Pack the widget into a container using the appropriate call
1663 such as gtk_container_add() or gtk_box_pack_start().
1664
1665 <item> gtk_widget_show() the widget.
1666 </enum>
1667
1668 gtk_widget_show() lets GTK know that we are done setting the
1669 attributes of the widget, and it is ready to be displayed. You may
1670 also use gtk_widget_hide to make it disappear again. The order in
1671 which you show the widgets is not important, but I suggest showing the
1672 window last so the whole window pops up at once rather than seeing the
1673 individual widgets come up on the screen as they're formed. The
1674 children of a widget (a window is a widget too) will not be displayed
1675 until the window itself is shown using the gtk_widget_show() function.
1676
1677 <!-- ----------------------------------------------------------------- -->
1678 <sect1> Casting
1679 <p>
1680 You'll notice as you go on that GTK uses a type casting system. This
1681 is always done using macros that both test the ability to cast the
1682 given item, and perform the cast. Some common ones you will see are:
1683
1684 <tscreen><verb>
1685   GTK_WIDGET(widget)
1686   GTK_OBJECT(object)
1687   GTK_SIGNAL_FUNC(function)
1688   GTK_CONTAINER(container)
1689   GTK_WINDOW(window)
1690   GTK_BOX(box)
1691 </verb></tscreen>
1692
1693 These are all used to cast arguments in functions. You'll see them in the
1694 examples, and can usually tell when to use them simply by looking at the
1695 function's declaration.
1696
1697 As you can see below in the class hierarchy, all GtkWidgets are
1698 derived from the Object base class. This means you can use a widget
1699 in any place the function asks for an object - simply use the
1700 <tt/GTK_OBJECT()/ macro.
1701
1702 For example:
1703
1704 <tscreen><verb>
1705 gtk_signal_connect( GTK_OBJECT(button), "clicked",
1706                     GTK_SIGNAL_FUNC(callback_function), callback_data);
1707 </verb></tscreen> 
1708
1709 This casts the button into an object, and provides a cast for the
1710 function pointer to the callback.
1711
1712 Many widgets are also containers. If you look in the class hierarchy
1713 below, you'll notice that many widgets derive from the Container
1714 class. Any one of these widgets may be used with the
1715 <tt/GTK_CONTAINER/ macro to pass them to functions that ask for
1716 containers.
1717
1718 Unfortunately, these macros are not extensively covered in the
1719 tutorial, but I recommend taking a look through the GTK header
1720 files. It can be very educational. In fact, it's not difficult to
1721 learn how a widget works just by looking at the function declarations.
1722
1723 <!-- ----------------------------------------------------------------- -->
1724 <sect1>Widget Hierarchy
1725 <p>
1726 For your reference, here is the class hierarchy tree used to implement widgets.
1727
1728 <tscreen><verb>
1729  GtkObject
1730   +GtkWidget
1731   | +GtkMisc
1732   | | +GtkLabel
1733   | | | +GtkAccelLabel
1734   | | | `GtkTipsQuery
1735   | | +GtkArrow
1736   | | +GtkImage
1737   | | `GtkPixmap
1738   | +GtkContainer
1739   | | +GtkBin
1740   | | | +GtkAlignment
1741   | | | +GtkFrame
1742   | | | | `GtkAspectFrame
1743   | | | +GtkButton
1744   | | | | +GtkToggleButton
1745   | | | | | `GtkCheckButton
1746   | | | | |   `GtkRadioButton
1747   | | | | `GtkOptionMenu
1748   | | | +GtkItem
1749   | | | | +GtkMenuItem
1750   | | | | | +GtkCheckMenuItem
1751   | | | | | | `GtkRadioMenuItem
1752   | | | | | `GtkTearoffMenuItem
1753   | | | | +GtkListItem
1754   | | | | `GtkTreeItem
1755   | | | +GtkWindow
1756   | | | | +GtkColorSelectionDialog
1757   | | | | +GtkDialog
1758   | | | | | `GtkInputDialog
1759   | | | | +GtkDrawWindow
1760   | | | | +GtkFileSelection
1761   | | | | +GtkFontSelectionDialog
1762   | | | | `GtkPlug
1763   | | | +GtkEventBox
1764   | | | +GtkHandleBox
1765   | | | +GtkScrolledWindow
1766   | | | `GtkViewport
1767   | | +GtkBox
1768   | | | +GtkButtonBox
1769   | | | | +GtkHButtonBox
1770   | | | | `GtkVButtonBox
1771   | | | +GtkVBox
1772   | | | | +GtkColorSelection
1773   | | | | `GtkGammaCurve
1774   | | | `GtkHBox
1775   | | |   +GtkCombo
1776   | | |   `GtkStatusbar
1777   | | +GtkCList
1778   | | | `GtkCTree
1779   | | +GtkFixed
1780   | | +GtkNotebook
1781   | | | `GtkFontSelection
1782   | | +GtkPaned
1783   | | | +GtkHPaned
1784   | | | `GtkVPaned
1785   | | +GtkLayout
1786   | | +GtkList
1787   | | +GtkMenuShell
1788   | | | +GtkMenuBar
1789   | | | `GtkMenu
1790   | | +GtkPacker
1791   | | +GtkSocket
1792   | | +GtkTable
1793   | | +GtkToolbar
1794   | | `GtkTree
1795   | +GtkCalendar
1796   | +GtkDrawingArea
1797   | | `GtkCurve
1798   | +GtkEditable
1799   | | +GtkEntry
1800   | | | `GtkSpinButton
1801   | | `GtkText
1802   | +GtkRuler
1803   | | +GtkHRuler
1804   | | `GtkVRuler
1805   | +GtkRange
1806   | | +GtkScale
1807   | | | +GtkHScale
1808   | | | `GtkVScale
1809   | | `GtkScrollbar
1810   | |   +GtkHScrollbar
1811   | |   `GtkVScrollbar
1812   | +GtkSeparator
1813   | | +GtkHSeparator
1814   | | `GtkVSeparator
1815   | +GtkPreview
1816   | `GtkProgress
1817   |   `GtkProgressBar
1818   +GtkData
1819   | +GtkAdjustment
1820   | `GtkTooltips
1821   `GtkItemFactory
1822 </verb></tscreen>
1823
1824 <!-- ----------------------------------------------------------------- -->
1825 <sect1>Widgets Without Windows
1826 <p>
1827 The following widgets do not have an associated window. If you want to
1828 capture events, you'll have to use the EventBox. See the section on
1829 the <ref id="sec_EventBox" name="EventBox"> widget.
1830
1831 <tscreen><verb>
1832 GtkAlignment
1833 GtkArrow
1834 GtkBin
1835 GtkBox
1836 GtkImage
1837 GtkItem
1838 GtkLabel
1839 GtkPixmap
1840 GtkScrolledWindow
1841 GtkSeparator
1842 GtkTable
1843 GtkAspectFrame
1844 GtkFrame
1845 GtkVBox
1846 GtkHBox
1847 GtkVSeparator
1848 GtkHSeparator
1849 </verb></tscreen>
1850
1851 We'll further our exploration of GTK by examining each widget in turn,
1852 creating a few simple functions to display them. Another good source
1853 is the testgtk.c program that comes with GTK. It can be found in
1854 gtk/testgtk.c.
1855
1856 <!-- ***************************************************************** -->
1857 <sect>The Button Widget
1858 <!-- ***************************************************************** -->
1859
1860 <!-- ----------------------------------------------------------------- -->
1861 <sect1>Normal Buttons
1862 <p>
1863 We've almost seen all there is to see of the button widget. It's
1864 pretty simple. There are however two ways to create a button. You can
1865 use the gtk_button_new_with_label() to create a button with a label,
1866 or use gtk_button_new() to create a blank button. It's then up to you
1867 to pack a label or pixmap into this new button. To do this, create a
1868 new box, and then pack your objects into this box using the usual
1869 gtk_box_pack_start, and then use gtk_container_add to pack the box
1870 into the button.
1871
1872 Here's an example of using gtk_button_new to create a button with a
1873 picture and a label in it. I've broken up the code to create a box
1874 from the rest so you can use it in your programs. There are further
1875 examples of using pixmaps later in the tutorial.
1876
1877 <tscreen><verb>
1878 /* example-start buttons buttons.c */
1879
1880 #include <gtk/gtk.h>
1881
1882 /* Create a new hbox with an image and a label packed into it
1883  * and return the box. */
1884
1885 GtkWidget *xpm_label_box( GtkWidget *parent,
1886                           gchar     *xpm_filename,
1887                           gchar     *label_text )
1888 {
1889     GtkWidget *box1;
1890     GtkWidget *label;
1891     GtkWidget *pixmapwid;
1892     GdkPixmap *pixmap;
1893     GdkBitmap *mask;
1894     GtkStyle *style;
1895
1896     /* Create box for xpm and label */
1897     box1 = gtk_hbox_new (FALSE, 0);
1898     gtk_container_set_border_width (GTK_CONTAINER (box1), 2);
1899
1900     /* Get the style of the button to get the
1901      * background color. */
1902     style = gtk_widget_get_style(parent);
1903
1904     /* Now on to the xpm stuff */
1905     pixmap = gdk_pixmap_create_from_xpm (parent->window, &amp;mask,
1906                                          &amp;style->bg[GTK_STATE_NORMAL],
1907                                          xpm_filename);
1908     pixmapwid = gtk_pixmap_new (pixmap, mask);
1909
1910     /* Create a label for the button */
1911     label = gtk_label_new (label_text);
1912
1913     /* Pack the pixmap and label into the box */
1914     gtk_box_pack_start (GTK_BOX (box1),
1915                         pixmapwid, FALSE, FALSE, 3);
1916
1917     gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);
1918
1919     gtk_widget_show(pixmapwid);
1920     gtk_widget_show(label);
1921
1922     return(box1);
1923 }
1924
1925 /* Our usual callback function */
1926 void callback( GtkWidget *widget,
1927                gpointer   data )
1928 {
1929     g_print ("Hello again - %s was pressed\n", (char *) data);
1930 }
1931
1932
1933 int main( int   argc,
1934           char *argv[] )
1935 {
1936     /* GtkWidget is the storage type for widgets */
1937     GtkWidget *window;
1938     GtkWidget *button;
1939     GtkWidget *box1;
1940
1941     gtk_init (&amp;argc, &amp;argv);
1942
1943     /* Create a new window */
1944     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1945
1946     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
1947
1948     /* It's a good idea to do this for all windows. */
1949     gtk_signal_connect (GTK_OBJECT (window), "destroy",
1950                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1951
1952     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1953                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1954
1955
1956     /* Sets the border width of the window. */
1957     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1958     gtk_widget_realize(window);
1959
1960     /* Create a new button */
1961     button = gtk_button_new ();
1962
1963     /* Connect the "clicked" signal of the button to our callback */
1964     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1965                         GTK_SIGNAL_FUNC (callback), (gpointer) "cool button");
1966
1967     /* This calls our box creating function */
1968     box1 = xpm_label_box(window, "info.xpm", "cool button");
1969
1970     /* Pack and show all our widgets */
1971     gtk_widget_show(box1);
1972
1973     gtk_container_add (GTK_CONTAINER (button), box1);
1974
1975     gtk_widget_show(button);
1976
1977     gtk_container_add (GTK_CONTAINER (window), button);
1978
1979     gtk_widget_show (window);
1980
1981     /* Rest in gtk_main and wait for the fun to begin! */
1982     gtk_main ();
1983
1984     return(0);
1985 }
1986 /* example-end */
1987 </verb></tscreen>
1988
1989 The xpm_label_box function could be used to pack xpm's and labels into
1990 any widget that can be a container.
1991
1992 Notice in <tt/xpm_label_box/ how there is a call to
1993 <tt/gtk_widget_get_style/. Every widget has a "style", consisting of
1994 foreground and background colors for a variety of situations, font
1995 selection, and other graphics data relevant to a widget. These style
1996 values are defaulted in each widget, and are required by many GDK
1997 function calls, such as <tt/gdk_pixmap_create_from_xpm/, which here is
1998 given the "normal" background color. The style data of widgets may
1999 be customized, using <ref id="sec_gtkrc_files" name="GTK's rc files">.
2000
2001 Also notice the call to <tt/gtk_widget_realize/ after setting the
2002 window's border width. This function uses GDK to create the X
2003 windows related to the widget. The function is automatically called
2004 when you invoke <tt/gtk_widget_show/ for a widget, and so has not been
2005 shown in earlier examples. But the call to
2006 <tt/gdk_pixmap_create_from_xpm/ requires that its <tt/window/ argument
2007 refer to a real X window, so it is necessary to realize the widget
2008 before this GDK call.
2009
2010 The Button widget has the following signals:
2011
2012 <itemize>
2013 <item><tt/pressed/ - emitted when pointer button is pressed within
2014 Button widget
2015 <item><tt/released/ - emitted when pointer button is released within
2016 Button widget
2017 <item><tt/clicked/ - emitted when pointer button is pressed and then
2018 released within Button widget
2019 <item><tt/enter/ - emitted when pointer enters Button widget
2020 <item><tt/leave/ - emitted when pointer leaves Button widget
2021 </itemize>
2022
2023 <!-- ----------------------------------------------------------------- -->
2024 <sect1> Toggle Buttons
2025 <p>
2026 Toggle buttons are derived from normal buttons and are very similar,
2027 except they will always be in one of two states, alternated by a
2028 click. They may be depressed, and when you click again, they will pop
2029 back up. Click again, and they will pop back down.
2030
2031 Toggle buttons are the basis for check buttons and radio buttons, as
2032 such, many of the calls used for toggle buttons are inherited by radio
2033 and check buttons. I will point these out when we come to them.
2034
2035 Creating a new toggle button:
2036
2037 <tscreen><verb>
2038 GtkWidget *gtk_toggle_button_new( void );
2039
2040 GtkWidget *gtk_toggle_button_new_with_label( gchar *label );
2041 </verb></tscreen>
2042
2043 As you can imagine, these work identically to the normal button widget
2044 calls. The first creates a blank toggle button, and the second, a
2045 button with a label widget already packed into it.
2046
2047 To retrieve the state of the toggle widget, including radio and check
2048 buttons, we use a construct as shown in our example below. This tests
2049 the state of the toggle, by accessing the <tt/active/ field of the
2050 toggle widget's structure, after first using the
2051 <tt/GTK_TOGGLE_BUTTON/ macro to cast the widget pointer into a toggle
2052 widget pointer. The signal of interest to us emitted by toggle
2053 buttons (the toggle button, check button, and radio button widgets) is
2054 the "toggled" signal. To check the state of these buttons, set up a
2055 signal handler to catch the toggled signal, and access the structure
2056 to determine its state. The callback will look something like:
2057
2058 <tscreen><verb>
2059 void toggle_button_callback (GtkWidget *widget, gpointer data)
2060 {
2061     if (GTK_TOGGLE_BUTTON (widget)->active) 
2062     {
2063         /* If control reaches here, the toggle button is down */
2064     
2065     } else {
2066     
2067         /* If control reaches here, the toggle button is up */
2068     }
2069 }
2070 </verb></tscreen>
2071
2072 To force the state of a toggle button, and its children, the radio and
2073 check buttons, use this function:
2074
2075 <tscreen><verb>
2076 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2077                                   gint             state );
2078 </verb></tscreen>
2079
2080 The above call can be used to set the state of the toggle button, and
2081 its children the radio and check buttons. Passing in your created
2082 button as the first argument, and a TRUE or FALSE for the second state
2083 argument to specify whether it should be down (depressed) or up
2084 (released). Default is up, or FALSE.
2085
2086 Note that when you use the gtk_toggle_button_set_active() function, and
2087 the state is actually changed, it causes the "clicked" signal to be
2088 emitted from the button.
2089
2090 <tscreen><verb>
2091 void gtk_toggle_button_toggled (GtkToggleButton *toggle_button);
2092 </verb></tscreen>
2093
2094 This simply toggles the button, and emits the "toggled" signal.
2095
2096 <!-- ----------------------------------------------------------------- -->
2097 <sect1> Check Buttons
2098 <p>
2099 Check buttons inherit many properties and functions from the the
2100 toggle buttons above, but look a little different. Rather than being
2101 buttons with text inside them, they are small squares with the text to
2102 the right of them. These are often used for toggling options on and
2103 off in applications.
2104
2105 The two creation functions are similar to those of the normal button.
2106
2107 <tscreen><verb>
2108 GtkWidget *gtk_check_button_new( void );
2109
2110 GtkWidget *gtk_check_button_new_with_label ( gchar *label );
2111 </verb></tscreen>
2112
2113 The new_with_label function creates a check button with a label beside
2114 it.
2115
2116 Checking the state of the check button is identical to that of the
2117 toggle button.
2118
2119 <!-- ----------------------------------------------------------------- -->
2120 <sect1> Radio Buttons <label id="sec_Radio_Buttons">
2121 <p>
2122 Radio buttons are similar to check buttons except they are grouped so
2123 that only one may be selected/depressed at a time. This is good for
2124 places in your application where you need to select from a short list
2125 of options.
2126
2127 Creating a new radio button is done with one of these calls:
2128
2129 <tscreen><verb>
2130 GtkWidget *gtk_radio_button_new( GSList *group );
2131
2132 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
2133                                             gchar  *label );
2134 </verb></tscreen>
2135
2136 You'll notice the extra argument to these calls. They require a group
2137 to perform their duty properly. The first call to
2138 gtk_radio_button_new_with_label or gtk_radio_button_new_with_label
2139 should pass NULL as the first argument. Then create a group using:
2140
2141 <tscreen><verb>
2142 GSList *gtk_radio_button_group( GtkRadioButton *radio_button );
2143 </verb></tscreen>
2144
2145 The important thing to remember is that gtk_radio_button_group must be
2146 called for each new button added to the group, with the previous
2147 button passed in as an argument. The result is then passed into the
2148 next call to gtk_radio_button_new or
2149 gtk_radio_button_new_with_label. This allows a chain of buttons to be
2150 established. The example below should make this clear.
2151
2152 You can shorten this slightly by using the following syntax, which
2153 removes the need for a variable to hold the list of buttons. This form
2154 is used in the example to create the third button:
2155
2156 <tscreen><verb>
2157      button2 = gtk_radio_button_new_with_label(
2158                  gtk_radio_button_group (GTK_RADIO_BUTTON (button1)),
2159                  "button2");
2160 </verb></tscreen>
2161
2162 It is also a good idea to explicitly set which button should be the
2163 default depressed button with:
2164
2165 <tscreen><verb>
2166 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2167                                   gint             state );
2168 </verb></tscreen>
2169
2170 This is described in the section on toggle buttons, and works in
2171 exactly the same way.  Once the radio buttons are grouped together,
2172 only one of the group may be active at a time. If the user clicks on
2173 one radio button, and then on another, the first radio button will
2174 first emit a "toggled" signal (to report becoming inactive), and then
2175 the second will emit its "toggled" signal (to report becoming active).
2176
2177 The following example creates a radio button group with three buttons.
2178
2179 <tscreen><verb>
2180 /* example-start radiobuttons radiobuttons.c */
2181
2182 #include <gtk/gtk.h>
2183 #include <glib.h>
2184
2185 void close_application( GtkWidget *widget,
2186                         GdkEvent  *event,
2187                         gpointer   data )
2188 {
2189   gtk_main_quit();
2190 }
2191
2192 int main( int   argc,
2193           char *argv[] )
2194 {
2195     GtkWidget *window = NULL;
2196     GtkWidget *box1;
2197     GtkWidget *box2;
2198     GtkWidget *button;
2199     GtkWidget *separator;
2200     GSList *group;
2201   
2202     gtk_init(&amp;argc,&amp;argv);    
2203       
2204     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2205   
2206     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
2207                         GTK_SIGNAL_FUNC(close_application),
2208                         NULL);
2209
2210     gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
2211     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2212
2213     box1 = gtk_vbox_new (FALSE, 0);
2214     gtk_container_add (GTK_CONTAINER (window), box1);
2215     gtk_widget_show (box1);
2216
2217     box2 = gtk_vbox_new (FALSE, 10);
2218     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2219     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2220     gtk_widget_show (box2);
2221
2222     button = gtk_radio_button_new_with_label (NULL, "button1");
2223     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2224     gtk_widget_show (button);
2225
2226     group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
2227     button = gtk_radio_button_new_with_label(group, "button2");
2228     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2229     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2230     gtk_widget_show (button);
2231
2232     button = gtk_radio_button_new_with_label(
2233                  gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
2234                  "button3");
2235     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2236     gtk_widget_show (button);
2237
2238     separator = gtk_hseparator_new ();
2239     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2240     gtk_widget_show (separator);
2241
2242     box2 = gtk_vbox_new (FALSE, 10);
2243     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2244     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2245     gtk_widget_show (box2);
2246
2247     button = gtk_button_new_with_label ("close");
2248     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2249                                GTK_SIGNAL_FUNC(close_application),
2250                                GTK_OBJECT (window));
2251     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2252     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2253     gtk_widget_grab_default (button);
2254     gtk_widget_show (button);
2255     gtk_widget_show (window);
2256      
2257     gtk_main();
2258
2259     return(0);
2260 }
2261 /* example-end */
2262 </verb></tscreen>
2263
2264 <!-- TODO: check out gtk_radio_button_new_from_widget function - TRG -->
2265
2266 <!-- ***************************************************************** -->
2267 <sect> Adjustments <label id="sec_Adjustment">
2268 <!-- ***************************************************************** -->
2269 <p>
2270 GTK has various widgets that can be visually adjusted by the user
2271 using the mouse or the keyboard, such as the range widgets, described
2272 in the <ref id="sec_Range_Widgets" name="Range Widgets">
2273 section. There are also a few widgets that display some adjustable
2274 portion of a larger area of data, such as the text widget and the
2275 viewport widget.
2276
2277 Obviously, an application needs to be able to react to changes the
2278 user makes in range widgets. One way to do this would be to have each
2279 widget emit its own type of signal when its adjustment changes, and
2280 either pass the new value to the signal handler, or require it to look
2281 inside the widget's data structure in order to ascertain the value.
2282 But you may also want to connect the adjustments of several widgets
2283 together, so that adjusting one adjusts the others. The most obvious
2284 example of this is connecting a scrollbar to a panning viewport or a
2285 scrolling text area. If each widget has its own way of setting or
2286 getting the adjustment value, then the programmer may have to write
2287 their own signal handlers to translate between the output of one
2288 widget's signal and the "input" of another's adjustment setting
2289 function.
2290
2291 GTK solves this problem using the Adjustment object, which is not a
2292 widget but a way for widgets to store and pass adjustment information
2293 in an abstract and flexible form. The most obvious use of Adjustment
2294 is to store the configuration parameters and values of range widgets,
2295 such as scrollbars and scale controls. However, since Adjustments are
2296 derived from Object, they have some special powers beyond those of
2297 normal data structures. Most importantly, they can emit signals, just
2298 like widgets, and these signals can be used not only to allow your
2299 program to react to user input on adjustable widgets, but also to
2300 propagate adjustment values transparently between adjustable widgets.
2301
2302 You will see how adjustments fit in when you see the other widgets
2303 that incorporate them:
2304 <ref id="sec_ProgressBar" name="Progress Bars">,
2305 <ref id="sec_Viewports" name="Viewports">,
2306 <ref id="sec_ScrolledWindow" name="Scrolled Windows">, and others.
2307
2308 <sect1> Creating an Adjustment
2309 <p>
2310 Many of the widgets which use adjustment objects do so automatically,
2311 but some cases will be shown in later examples where you may need to
2312 create one yourself. You create an adjustment using:
2313
2314 <tscreen><verb>
2315 GtkObject *gtk_adjustment_new( gfloat value,
2316                                gfloat lower,
2317                                gfloat upper,
2318                                gfloat step_increment,
2319                                gfloat page_increment,
2320                                gfloat page_size );
2321 </verb></tscreen>
2322
2323 The <tt/value/ argument is the initial value you want to give to the
2324 adjustment, usually corresponding to the topmost or leftmost position
2325 of an adjustable widget. The <tt/lower/ argument specifies the lowest
2326 value which the adjustment can hold. The <tt/step_increment/ argument
2327 specifies the "smaller" of the two increments by which the user can
2328 change the value, while the <tt/page_increment/ is the "larger" one.
2329 The <tt/page_size/ argument usually corresponds somehow to the visible
2330 area of a panning widget. The <tt/upper/ argument is used to represent
2331 the bottom most or right most coordinate in a panning widget's
2332 child. Therefore it is <em/not/ always the largest number that
2333 <tt/value/ can take, since the <tt/page_size/ of such widgets is
2334 usually non-zero.
2335
2336 <!-- ----------------------------------------------------------------- -->
2337 <sect1> Using Adjustments the Easy Way
2338 <p>
2339 The adjustable widgets can be roughly divided into those which use and
2340 require specific units for these values and those which treat them as
2341 arbitrary numbers. The group which treats the values as arbitrary
2342 numbers includes the range widgets (scrollbars and scales, the
2343 progress bar widget, and the spin button widget). These widgets are
2344 all the widgets which are typically "adjusted" directly by the user
2345 with the mouse or keyboard. They will treat the <tt/lower/ and
2346 <tt/upper/ values of an adjustment as a range within which the user
2347 can manipulate the adjustment's <tt/value/. By default, they will only
2348 modify the <tt/value/ of an adjustment.
2349
2350 The other group includes the text widget, the viewport widget, the
2351 compound list widget, and the scrolled window widget. All of these
2352 widgets use pixel values for their adjustments. These are also all
2353 widgets which are typically "adjusted" indirectly using scrollbars.
2354 While all widgets which use adjustments can either create their own
2355 adjustments or use ones you supply, you'll generally want to let this
2356 particular category of widgets create its own adjustments. Usually,
2357 they will eventually override all the values except the <tt/value/
2358 itself in whatever adjustments you give them, but the results are, in
2359 general, undefined (meaning, you'll have to read the source code to
2360 find out, and it may be different from widget to widget).
2361
2362 Now, you're probably thinking, since text widgets and viewports insist
2363 on setting everything except the <tt/value/ of their adjustments,
2364 while scrollbars will <em/only/ touch the adjustment's <tt/value/, if
2365 you <em/share/ an adjustment object between a scrollbar and a text
2366 widget, manipulating the scrollbar will automagically adjust the text
2367 widget?  Of course it will! Just like this:
2368
2369 <tscreen><verb>
2370   /* creates its own adjustments */
2371   text = gtk_text_new (NULL, NULL);
2372   /* uses the newly-created adjustment for the scrollbar as well */
2373   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
2374 </verb></tscreen>
2375
2376 </sect1>
2377 <!-- ----------------------------------------------------------------- -->
2378 <sect1> Adjustment Internals
2379 <p>
2380 Ok, you say, that's nice, but what if I want to create my own handlers
2381 to respond when the user adjusts a range widget or a spin button, and
2382 how do I get at the value of the adjustment in these handlers?  To
2383 answer these questions and more, let's start by taking a look at
2384 <tt>struct _GtkAdjustment</tt> itself:
2385
2386 <tscreen><verb>
2387 struct _GtkAdjustment
2388 {
2389   GtkData data;
2390   
2391   gfloat lower;
2392   gfloat upper;
2393   gfloat value;
2394   gfloat step_increment;
2395   gfloat page_increment;
2396   gfloat page_size;
2397 };     
2398 </verb></tscreen>
2399
2400 The first thing you should know is that there aren't any handy-dandy
2401 macros or accessor functions for getting the <tt/value/ out of an
2402 Adjustment, so you'll have to (horror of horrors) do it like a
2403 <em/real/ C programmer.  Don't worry - the <tt>GTK_ADJUSTMENT
2404 (Object)</tt> macro does run-time type checking (as do all the GTK
2405 type-casting macros, actually).
2406
2407 Since, when you set the <tt/value/ of an adjustment, you generally
2408 want the change to be reflected by every widget that uses this
2409 adjustment, GTK provides this convenience function to do this:
2410
2411 <tscreen><verb>
2412 void gtk_adjustment_set_value( GtkAdjustment *adjustment,
2413                                gfloat         value );
2414 </verb></tscreen>
2415
2416 As mentioned earlier, Adjustment is a subclass of Object just
2417 like all the various widgets, and thus it is able to emit signals.
2418 This is, of course, why updates happen automagically when you share an
2419 adjustment object between a scrollbar and another adjustable widget;
2420 all adjustable widgets connect signal handlers to their adjustment's
2421 <tt/value_changed/ signal, as can your program. Here's the definition
2422 of this signal in <tt/struct _GtkAdjustmentClass/:
2423
2424 <tscreen><verb>
2425   void (* value_changed) (GtkAdjustment *adjustment);
2426 </verb></tscreen>
2427
2428 The various widgets that use the Adjustment object will emit this
2429 signal on an adjustment whenever they change its value. This happens
2430 both when user input causes the slider to move on a range widget, as
2431 well as when the program explicitly changes the value with
2432 <tt/gtk_adjustment_set_value()/. So, for example, if you have a scale
2433 widget, and you want to change the rotation of a picture whenever its
2434 value changes, you would create a callback like this:
2435
2436 <tscreen><verb>
2437 void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
2438 {
2439   set_picture_rotation (picture, adj->value);
2440 ...
2441 </verb></tscreen>
2442
2443 and connect it to the scale widget's adjustment like this:
2444
2445 <tscreen><verb>
2446 gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
2447                     GTK_SIGNAL_FUNC (cb_rotate_picture), picture);
2448 </verb></tscreen>
2449
2450 What about when a widget reconfigures the <tt/upper/ or <tt/lower/
2451 fields of its adjustment, such as when a user adds more text to a text
2452 widget?  In this case, it emits the <tt/changed/ signal, which looks
2453 like this:
2454
2455 <tscreen><verb>
2456   void (* changed)       (GtkAdjustment *adjustment);
2457 </verb></tscreen>
2458
2459 Range widgets typically connect a handler to this signal, which
2460 changes their appearance to reflect the change - for example, the size
2461 of the slider in a scrollbar will grow or shrink in inverse proportion
2462 to the difference between the <tt/lower/ and <tt/upper/ values of its
2463 adjustment.
2464
2465 You probably won't ever need to attach a handler to this signal,
2466 unless you're writing a new type of range widget.  However, if you
2467 change any of the values in a Adjustment directly, you should emit
2468 this signal on it to reconfigure whatever widgets are using it, like
2469 this:
2470
2471 <tscreen><verb>
2472 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2473 </verb></tscreen>
2474
2475 Now go forth and adjust!
2476 </sect1>
2477 </sect>
2478
2479 <!-- ***************************************************************** -->
2480 <sect> Range Widgets<label id="sec_Range_Widgets">
2481 <!-- ***************************************************************** -->
2482
2483 <p>
2484 The category of range widgets includes the ubiquitous scrollbar widget
2485 and the less common "scale" widget. Though these two types of widgets
2486 are generally used for different purposes, they are quite similar in
2487 function and implementation. All range widgets share a set of common
2488 graphic elements, each of which has its own X window and receives
2489 events. They all contain a "trough" and a "slider" (what is sometimes
2490 called a "thumbwheel" in other GUI environments). Dragging the slider
2491 with the pointer moves it back and forth within the trough, while
2492 clicking in the trough advances the slider towards the location of the
2493 click, either completely, or by a designated amount, depending on
2494 which mouse button is used.
2495
2496 As mentioned in <ref id="sec_Adjustment" name="Adjustments"> above,
2497 all range widgets are associated with an adjustment object, from which
2498 they calculate the length of the slider and its position within the
2499 trough. When the user manipulates the slider, the range widget will
2500 change the value of the adjustment.
2501
2502 <!-- ----------------------------------------------------------------- -->
2503 <sect1> Scrollbar Widgets
2504 <p>
2505 These are your standard, run-of-the-mill scrollbars. These should be
2506 used only for scrolling some other widget, such as a list, a text box,
2507 or a viewport (and it's generally easier to use the scrolled window
2508 widget in most cases).  For other purposes, you should use scale
2509 widgets, as they are friendlier and more featureful.
2510
2511 There are separate types for horizontal and vertical scrollbars.
2512 There really isn't much to say about these. You create them with the
2513 following functions, defined in <tt>&lt;gtk/gtkhscrollbar.h&gt;</tt>
2514 and <tt>&lt;gtk/gtkvscrollbar.h&gt;</tt>:
2515
2516 <tscreen><verb>
2517 GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );
2518
2519 GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );
2520 </verb></tscreen>
2521
2522 and that's about it (if you don't believe me, look in the header
2523 files!).  The <tt/adjustment/ argument can either be a pointer to an
2524 existing Adjustment, or NULL, in which case one will be created for
2525 you. Specifying NULL might actually be useful in this case, if you
2526 wish to pass the newly-created adjustment to the constructor function
2527 of some other widget which will configure it for you, such as a text
2528 widget.
2529 </sect1>
2530
2531 <!-- ----------------------------------------------------------------- -->
2532 <sect1> Scale Widgets
2533 <p>
2534 Scale widgets are used to allow the user to visually select and
2535 manipulate a value within a specific range. You might want to use a
2536 scale widget, for example, to adjust the magnification level on a
2537 zoomed preview of a picture, or to control the brightness of a color,
2538 or to specify the number of minutes of inactivity before a screensaver
2539 takes over the screen.
2540
2541 <!-- ----------------------------------------------------------------- -->
2542 <sect2>Creating a Scale Widget
2543 <p>
2544 As with scrollbars, there are separate widget types for horizontal and
2545 vertical scale widgets. (Most programmers seem to favour horizontal
2546 scale widgets.) Since they work essentially the same way, there's no
2547 need to treat them separately here. The following functions, defined
2548 in <tt>&lt;gtk/gtkvscale.h&gt;</tt> and
2549 <tt>&lt;gtk/gtkhscale.h&gt;</tt>, create vertical and horizontal scale
2550 widgets, respectively:
2551
2552 <tscreen>
2553 <verb>
2554 GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );
2555
2556 GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );
2557 </verb>
2558 </tscreen>
2559
2560 The <tt/adjustment/ argument can either be an adjustment which has
2561 already been created with <tt/gtk_adjustment_new()/, or <tt/NULL/, in
2562 which case, an anonymous Adjustment is created with all of its
2563 values set to <tt/0.0/ (which isn't very useful in this case). In
2564 order to avoid confusing yourself, you probably want to create your
2565 adjustment with a <tt/page_size/ of <tt/0.0/ so that its <tt/upper/
2566 value actually corresponds to the highest value the user can select.
2567 (If you're <em/already/ thoroughly confused, read the section on <ref
2568 id="sec_Adjustment" name="Adjustments"> again for an explanation of
2569 what exactly adjustments do and how to create and manipulate them.)
2570
2571 <!-- ----------------------------------------------------------------- -->
2572 <sect2> Functions and Signals (well, functions, at least)
2573 <p>
2574 Scale widgets can display their current value as a number beside the
2575 trough. The default behaviour is to show the value, but you can change
2576 this with this function:
2577
2578 <tscreen><verb>
2579 void gtk_scale_set_draw_value( GtkScale *scale,
2580                                gint      draw_value );
2581 </verb></tscreen>
2582
2583 As you might have guessed, <tt/draw_value/ is either <tt/TRUE/ or
2584 <tt/FALSE/, with predictable consequences for either one.
2585
2586 The value displayed by a scale widget is rounded to one decimal point
2587 by default, as is the <tt/value/ field in its GtkAdjustment. You can
2588 change this with:
2589
2590 <tscreen>
2591 <verb>
2592 void gtk_scale_set_digits( GtkScale *scale,
2593                             gint     digits );
2594 </verb>
2595 </tscreen>
2596
2597 where <tt/digits/ is the number of decimal places you want. You can
2598 set <tt/digits/ to anything you like, but no more than 13 decimal
2599 places will actually be drawn on screen.
2600
2601 Finally, the value can be drawn in different positions
2602 relative to the trough:
2603
2604 <tscreen>
2605 <verb>
2606 void gtk_scale_set_value_pos( GtkScale        *scale,
2607                               GtkPositionType  pos );
2608 </verb>
2609 </tscreen>
2610
2611 The argument <tt/pos/ is of type <tt>GtkPositionType</tt>, which is
2612 defined in <tt>&lt;gtk/gtkenums.h&gt;</tt>, and can take one of the
2613 following values:
2614
2615 <tscreen><verb>
2616   GTK_POS_LEFT
2617   GTK_POS_RIGHT
2618   GTK_POS_TOP
2619   GTK_POS_BOTTOM
2620 </verb></tscreen>
2621
2622 If you position the value on the "side" of the trough (e.g., on the
2623 top or bottom of a horizontal scale widget), then it will follow the
2624 slider up and down the trough.
2625
2626 All the preceding functions are defined in
2627 <tt>&lt;gtk/gtkscale.h&gt;</tt>. The header files for all GTK widgets
2628 are automatically included when you include
2629 <tt>&lt;gtk/gtk.h&gt;</tt>. But you should look over the header files
2630 of all widgets that interest you,
2631
2632 </sect2>
2633 </sect1>
2634
2635 <!-- ----------------------------------------------------------------- -->
2636 <sect1> Common Range Functions <label id="sec_Range_Functions">
2637 <p>
2638 The Range widget class is fairly complicated internally, but, like
2639 all the "base class" widgets, most of its complexity is only
2640 interesting if you want to hack on it. Also, almost all of the
2641 functions and signals it defines are only really used in writing
2642 derived widgets. There are, however, a few useful functions that are
2643 defined in <tt>&lt;gtk/gtkrange.h&gt;</tt> and will work on all range
2644 widgets.
2645
2646 <!-- ----------------------------------------------------------------- -->
2647 <sect2> Setting the Update Policy
2648 <p>
2649 The "update policy" of a range widget defines at what points during
2650 user interaction it will change the <tt/value/ field of its
2651 Adjustment and emit the "value_changed" signal on this
2652 Adjustment. The update policies, defined in
2653 <tt>&lt;gtk/gtkenums.h&gt;</tt> as type <tt>enum GtkUpdateType</tt>,
2654 are:
2655
2656 <itemize>
2657 <item>GTK_UPDATE_POLICY_CONTINUOUS - This is the default. The
2658 "value_changed" signal is emitted continuously, i.e., whenever the
2659 slider is moved by even the tiniest amount.
2660 </item>
2661 <item>GTK_UPDATE_POLICY_DISCONTINUOUS - The "value_changed" signal is
2662 only emitted once the slider has stopped moving and the user has
2663 released the mouse button.
2664 </item>
2665 <item>GTK_UPDATE_POLICY_DELAYED - The "value_changed" signal is emitted
2666 when the user releases the mouse button, or if the slider stops moving
2667 for a short period of time.
2668 </item>
2669 </itemize>
2670
2671 The update policy of a range widget can be set by casting it using the
2672 <tt>GTK_RANGE (Widget)</tt> macro and passing it to this function:
2673
2674 <tscreen><verb>
2675 void gtk_range_set_update_policy( GtkRange      *range,
2676                                   GtkUpdateType  policy) ;
2677 </verb></tscreen>
2678
2679 <!-- ----------------------------------------------------------------- -->
2680 <sect2>Getting and Setting Adjustments
2681 <p>
2682 Getting and setting the adjustment for a range widget "on the fly" is
2683 done, predictably, with:
2684
2685 <tscreen><verb>
2686 GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );
2687
2688 void gtk_range_set_adjustment( GtkRange      *range,
2689                                GtkAdjustment *adjustment );
2690 </verb></tscreen>
2691
2692 <tt/gtk_range_get_adjustment()/ returns a pointer to the adjustment to
2693 which <tt/range/ is connected.
2694
2695 <tt/gtk_range_set_adjustment()/ does absolutely nothing if you pass it
2696 the adjustment that <tt/range/ is already using, regardless of whether
2697 you changed any of its fields or not. If you pass it a new
2698 Adjustment, it will unreference the old one if it exists (possibly
2699 destroying it), connect the appropriate signals to the new one, and
2700 call the private function <tt/gtk_range_adjustment_changed()/, which
2701 will (or at least, is supposed to...) recalculate the size and/or
2702 position of the slider and redraw if necessary. As mentioned in the
2703 section on adjustments, if you wish to reuse the same Adjustment,
2704 when you modify its values directly, you should emit the "changed"
2705 signal on it, like this:
2706
2707 <tscreen><verb>
2708 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2709 </verb></tscreen>
2710 </sect2>
2711 </sect1>
2712
2713 <!-- ----------------------------------------------------------------- -->
2714 <sect1> Key and Mouse bindings
2715 <p>
2716 All of the GTK range widgets react to mouse clicks in more or less
2717 the same way. Clicking button-1 in the trough will cause its
2718 adjustment's <tt/page_increment/ to be added or subtracted from its
2719 <tt/value/, and the slider to be moved accordingly. Clicking mouse
2720 button-2 in the trough will jump the slider to the point at which the
2721 button was clicked. Clicking any button on a scrollbar's arrows will
2722 cause its adjustment's value to change <tt/step_increment/ at a time.
2723
2724 It may take a little while to get used to, but by default, scrollbars
2725 as well as scale widgets can take the keyboard focus in GTK. If you
2726 think your users will find this too confusing, you can always disable
2727 this by unsetting the <tt/GTK_CAN_FOCUS/ flag on the scrollbar, like
2728 this:
2729
2730 <tscreen><verb>
2731 GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS);
2732 </verb></tscreen>
2733
2734 The key bindings (which are, of course, only active when the widget
2735 has focus) are slightly different between horizontal and vertical
2736 range widgets, for obvious reasons. They are also not quite the same
2737 for scale widgets as they are for scrollbars, for somewhat less
2738 obvious reasons (possibly to avoid confusion between the keys for
2739 horizontal and vertical scrollbars in scrolled windows, where both
2740 operate on the same area).
2741
2742 <sect2> Vertical Range Widgets
2743 <p>
2744 All vertical range widgets can be operated with the up and down arrow
2745 keys, as well as with the <tt/Page Up/ and <tt/Page Down/ keys. The
2746 arrows move the slider up and down by <tt/step_increment/, while
2747 <tt/Page Up/ and <tt/Page Down/ move it by <tt/page_increment/.
2748
2749 The user can also move the slider all the way to one end or the other
2750 of the trough using the keyboard. With the VScale widget, this is
2751 done with the <tt/Home/ and <tt/End/ keys, whereas with the
2752 VScrollbar widget, this is done by typing <tt>Control-Page Up</tt>
2753 and <tt>Control-Page Down</tt>.
2754
2755 <!-- ----------------------------------------------------------------- -->
2756 <sect2> Horizontal Range Widgets
2757 <p>
2758 The left and right arrow keys work as you might expect in these
2759 widgets, moving the slider back and forth by <tt/step_increment/. The
2760 <tt/Home/ and <tt/End/ keys move the slider to the ends of the trough.
2761 For the HScale widget, moving the slider by <tt/page_increment/ is
2762 accomplished with <tt>Control-Left</tt> and <tt>Control-Right</tt>,
2763 while for HScrollbar, it's done with <tt>Control-Home</tt> and
2764 <tt>Control-End</tt>.
2765 </sect2>
2766 </sect1>
2767
2768 <!-- ----------------------------------------------------------------- -->
2769 <sect1> Example<label id="sec_Range_Example">
2770 <p>
2771 This example is a somewhat modified version of the "range controls"
2772 test from <tt/testgtk.c/. It basically puts up a window with three
2773 range widgets all connected to the same adjustment, and a couple of
2774 controls for adjusting some of the parameters mentioned above and in
2775 the section on adjustments, so you can see how they affect the way
2776 these widgets work for the user.
2777
2778 <tscreen><verb>
2779 /* example-start rangewidgets rangewidgets.c */
2780
2781 #include <gtk/gtk.h>
2782
2783 GtkWidget *hscale, *vscale;
2784
2785 void cb_pos_menu_select( GtkWidget       *item,
2786                          GtkPositionType  pos )
2787 {
2788     /* Set the value position on both scale widgets */
2789     gtk_scale_set_value_pos (GTK_SCALE (hscale), pos);
2790     gtk_scale_set_value_pos (GTK_SCALE (vscale), pos);
2791 }
2792
2793 void cb_update_menu_select( GtkWidget     *item,
2794                             GtkUpdateType  policy )
2795 {
2796     /* Set the update policy for both scale widgets */
2797     gtk_range_set_update_policy (GTK_RANGE (hscale), policy);
2798     gtk_range_set_update_policy (GTK_RANGE (vscale), policy);
2799 }
2800
2801 void cb_digits_scale( GtkAdjustment *adj )
2802 {
2803     /* Set the number of decimal places to which adj->value is rounded */
2804     gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
2805     gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
2806 }
2807
2808 void cb_page_size( GtkAdjustment *get,
2809                    GtkAdjustment *set )
2810 {
2811     /* Set the page size and page increment size of the sample
2812      * adjustment to the value specified by the "Page Size" scale */
2813     set->page_size = get->value;
2814     set->page_increment = get->value;
2815     /* Now emit the "changed" signal to reconfigure all the widgets that
2816      * are attached to this adjustment */
2817     gtk_signal_emit_by_name (GTK_OBJECT (set), "changed");
2818 }
2819
2820 void cb_draw_value( GtkToggleButton *button )
2821 {
2822     /* Turn the value display on the scale widgets off or on depending
2823      *  on the state of the checkbutton */
2824     gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active);
2825     gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active);  
2826 }
2827
2828 /* Convenience functions */
2829
2830 GtkWidget *make_menu_item( gchar         *name,
2831                            GtkSignalFunc  callback,
2832                            gpointer       data )
2833 {
2834     GtkWidget *item;
2835   
2836     item = gtk_menu_item_new_with_label (name);
2837     gtk_signal_connect (GTK_OBJECT (item), "activate",
2838                         callback, data);
2839     gtk_widget_show (item);
2840
2841     return(item);
2842 }
2843
2844 void scale_set_default_values( GtkScale *scale )
2845 {
2846     gtk_range_set_update_policy (GTK_RANGE (scale),
2847                                  GTK_UPDATE_CONTINUOUS);
2848     gtk_scale_set_digits (scale, 1);
2849     gtk_scale_set_value_pos (scale, GTK_POS_TOP);
2850     gtk_scale_set_draw_value (scale, TRUE);
2851 }
2852
2853 /* makes the sample window */
2854
2855 void create_range_controls( void )
2856 {
2857     GtkWidget *window;
2858     GtkWidget *box1, *box2, *box3;
2859     GtkWidget *button;
2860     GtkWidget *scrollbar;
2861     GtkWidget *separator;
2862     GtkWidget *opt, *menu, *item;
2863     GtkWidget *label;
2864     GtkWidget *scale;
2865     GtkObject *adj1, *adj2;
2866
2867     /* Standard window-creating stuff */
2868     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2869     gtk_signal_connect (GTK_OBJECT (window), "destroy",
2870                         GTK_SIGNAL_FUNC(gtk_main_quit),
2871                         NULL);
2872     gtk_window_set_title (GTK_WINDOW (window), "range controls");
2873
2874     box1 = gtk_vbox_new (FALSE, 0);
2875     gtk_container_add (GTK_CONTAINER (window), box1);
2876     gtk_widget_show (box1);
2877
2878     box2 = gtk_hbox_new (FALSE, 10);
2879     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2880     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2881     gtk_widget_show (box2);
2882
2883     /* value, lower, upper, step_increment, page_increment, page_size */
2884     /* Note that the page_size value only makes a difference for
2885      * scrollbar widgets, and the highest value you'll get is actually
2886      * (upper - page_size). */
2887     adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
2888   
2889     vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1));
2890     scale_set_default_values (GTK_SCALE (vscale));
2891     gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0);
2892     gtk_widget_show (vscale);
2893
2894     box3 = gtk_vbox_new (FALSE, 10);
2895     gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0);
2896     gtk_widget_show (box3);
2897
2898     /* Reuse the same adjustment */
2899     hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1));
2900     gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 30);
2901     scale_set_default_values (GTK_SCALE (hscale));
2902     gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0);
2903     gtk_widget_show (hscale);
2904
2905     /* Reuse the same adjustment again */
2906     scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1));
2907     /* Notice how this causes the scales to always be updated
2908      * continuously when the scrollbar is moved */
2909     gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
2910                                  GTK_UPDATE_CONTINUOUS);
2911     gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0);
2912     gtk_widget_show (scrollbar);
2913
2914     box2 = gtk_hbox_new (FALSE, 10);
2915     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2916     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2917     gtk_widget_show (box2);
2918
2919     /* A checkbutton to control whether the value is displayed or not */
2920     button = gtk_check_button_new_with_label("Display value on scale widgets");
2921     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2922     gtk_signal_connect (GTK_OBJECT (button), "toggled",
2923                         GTK_SIGNAL_FUNC(cb_draw_value), NULL);
2924     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2925     gtk_widget_show (button);
2926   
2927     box2 = gtk_hbox_new (FALSE, 10);
2928     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2929
2930     /* An option menu to change the position of the value */
2931     label = gtk_label_new ("Scale Value Position:");
2932     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2933     gtk_widget_show (label);
2934   
2935     opt = gtk_option_menu_new();
2936     menu = gtk_menu_new();
2937
2938     item = make_menu_item ("Top",
2939                            GTK_SIGNAL_FUNC(cb_pos_menu_select),
2940                            GINT_TO_POINTER (GTK_POS_TOP));
2941     gtk_menu_append (GTK_MENU (menu), item);
2942   
2943     item = make_menu_item ("Bottom", GTK_SIGNAL_FUNC (cb_pos_menu_select), 
2944                            GINT_TO_POINTER (GTK_POS_BOTTOM));
2945     gtk_menu_append (GTK_MENU (menu), item);
2946   
2947     item = make_menu_item ("Left", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2948                            GINT_TO_POINTER (GTK_POS_LEFT));
2949     gtk_menu_append (GTK_MENU (menu), item);
2950   
2951     item = make_menu_item ("Right", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2952                             GINT_TO_POINTER (GTK_POS_RIGHT));
2953     gtk_menu_append (GTK_MENU (menu), item);
2954   
2955     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2956     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2957     gtk_widget_show (opt);
2958
2959     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2960     gtk_widget_show (box2);
2961
2962     box2 = gtk_hbox_new (FALSE, 10);
2963     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2964
2965     /* Yet another option menu, this time for the update policy of the
2966      * scale widgets */
2967     label = gtk_label_new ("Scale Update Policy:");
2968     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2969     gtk_widget_show (label);
2970   
2971     opt = gtk_option_menu_new();
2972     menu = gtk_menu_new();
2973   
2974     item = make_menu_item ("Continuous",
2975                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2976                            GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS));
2977     gtk_menu_append (GTK_MENU (menu), item);
2978   
2979     item = make_menu_item ("Discontinuous",
2980                             GTK_SIGNAL_FUNC (cb_update_menu_select),
2981                             GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS));
2982     gtk_menu_append (GTK_MENU (menu), item);
2983   
2984     item = make_menu_item ("Delayed",
2985                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2986                            GINT_TO_POINTER (GTK_UPDATE_DELAYED));
2987     gtk_menu_append (GTK_MENU (menu), item);
2988   
2989     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2990     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2991     gtk_widget_show (opt);
2992   
2993     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2994     gtk_widget_show (box2);
2995
2996     box2 = gtk_hbox_new (FALSE, 10);
2997     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2998   
2999     /* An HScale widget for adjusting the number of digits on the
3000      * sample scales. */
3001     label = gtk_label_new ("Scale Digits:");
3002     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3003     gtk_widget_show (label);
3004
3005     adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0);
3006     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
3007                         GTK_SIGNAL_FUNC (cb_digits_scale), NULL);
3008     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
3009     gtk_scale_set_digits (GTK_SCALE (scale), 0);
3010     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
3011     gtk_widget_show (scale);
3012
3013     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3014     gtk_widget_show (box2);
3015   
3016     box2 = gtk_hbox_new (FALSE, 10);
3017     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3018   
3019     /* And, one last HScale widget for adjusting the page size of the
3020      * scrollbar. */
3021     label = gtk_label_new ("Scrollbar Page Size:");
3022     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3023     gtk_widget_show (label);
3024
3025     adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0);
3026     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
3027                         GTK_SIGNAL_FUNC (cb_page_size), adj1);
3028     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
3029     gtk_scale_set_digits (GTK_SCALE (scale), 0);
3030     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
3031     gtk_widget_show (scale);
3032
3033     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3034     gtk_widget_show (box2);
3035
3036     separator = gtk_hseparator_new ();
3037     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3038     gtk_widget_show (separator);
3039
3040     box2 = gtk_vbox_new (FALSE, 10);
3041     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3042     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3043     gtk_widget_show (box2);
3044
3045     button = gtk_button_new_with_label ("Quit");
3046     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3047                                GTK_SIGNAL_FUNC(gtk_main_quit),
3048                                NULL);
3049     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3050     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3051     gtk_widget_grab_default (button);
3052     gtk_widget_show (button);
3053
3054     gtk_widget_show (window);
3055 }
3056
3057 int main( int   argc,
3058           char *argv[] )
3059 {
3060     gtk_init(&amp;argc, &amp;argv);
3061
3062     create_range_controls();
3063
3064     gtk_main();
3065
3066     return(0);
3067 }
3068
3069 /* example-end */
3070 </verb></tscreen>
3071
3072 You will notice that the program does not call <tt/gtk_signal_connect/
3073 for the "delete_event", but only for the "destroy" signal. This will
3074 still perform the desired function, because an unhandled
3075 "delete_event" will result in a "destroy" signal being given to the
3076 window.
3077
3078 </sect1>
3079 </sect>
3080
3081 <!-- ***************************************************************** -->
3082 <sect> Miscellaneous Widgets
3083 <!-- ***************************************************************** -->
3084
3085 <!-- ----------------------------------------------------------------- -->
3086 <sect1> Labels
3087 <p>
3088 Labels are used a lot in GTK, and are relatively simple. Labels emit
3089 no signals as they do not have an associated X window. If you need to
3090 catch signals, or do clipping, place it inside a <ref id="sec_EventBox"
3091 name="EventBox"> widget or a Button widget.
3092
3093 To create a new label, use:
3094
3095 <tscreen><verb>
3096 GtkWidget *gtk_label_new( char *str );
3097 </verb></tscreen>
3098
3099 The sole argument is the string you wish the label to display.
3100
3101 To change the label's text after creation, use the function:
3102
3103 <tscreen><verb>
3104 void gtk_label_set_text( GtkLabel *label,
3105                          char     *str );
3106 </verb></tscreen>
3107
3108 The first argument is the label you created previously (cast
3109 using the <tt/GTK_LABEL()/ macro), and the second is the new string.
3110
3111 The space needed for the new string will be automatically adjusted if
3112 needed. You can produce multi-line labels by putting line breaks in
3113 the label string.
3114
3115 To retrieve the current string, use:
3116
3117 <tscreen><verb>
3118 void gtk_label_get( GtkLabel  *label,
3119                     char     **str );
3120 </verb></tscreen>
3121
3122 The first argument is the label you've created, and the second,
3123 the return for the string. Do not free the return string, as it is
3124 used internally by GTK.
3125
3126 The label text can be justified using:
3127
3128 <tscreen><verb>
3129 void gtk_label_set_justify( GtkLabel         *label,
3130                             GtkJustification  jtype );
3131 </verb></tscreen>
3132
3133 Values for <tt/jtype/ are:
3134 <tscreen><verb>
3135   GTK_JUSTIFY_LEFT
3136   GTK_JUSTIFY_RIGHT
3137   GTK_JUSTIFY_CENTER (the default)
3138   GTK_JUSTIFY_FILL
3139 </verb></tscreen>
3140
3141 The label widget is also capable of line wrapping the text
3142 automatically. This can be activated using:
3143
3144 <tscreen><verb>
3145 void gtk_label_set_line_wrap (GtkLabel *label,
3146                               gboolean  wrap);
3147 </verb></tscreen>
3148
3149 The <tt/wrap/ argument takes a TRUE or FALSE value.
3150
3151 If you want your label underlined, then you can set a pattern on the
3152 label:
3153
3154 <tscreen><verb>
3155 void       gtk_label_set_pattern   (GtkLabel          *label,
3156                                     const gchar       *pattern);
3157 </verb></tscreen>
3158
3159 The pattern argument indicates how the underlining should look. It
3160 consists of a string of underscore and space characters. An underscore
3161 indicates that the corresponding character in the label should be
3162 underlined. For example, the string <verb/"__     __"/ would underline the
3163 first two characters and eight and ninth characters.
3164
3165 Below is a short example to illustrate these functions. This example
3166 makes use of the Frame widget to better demonstrate the label
3167 styles. You can ignore this for now as the <ref id="sec_Frames"
3168 name="Frame"> widget is explained later on.
3169
3170 <tscreen><verb>
3171 /* example-start label label.c */
3172
3173 #include <gtk/gtk.h>
3174
3175 int main( int   argc,
3176           char *argv[] )
3177 {
3178   static GtkWidget *window = NULL;
3179   GtkWidget *hbox;
3180   GtkWidget *vbox;
3181   GtkWidget *frame;
3182   GtkWidget *label;
3183
3184   /* Initialise GTK */
3185   gtk_init(&amp;argc, &amp;argv);
3186
3187   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3188   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3189                       GTK_SIGNAL_FUNC(gtk_main_quit),
3190                       NULL);
3191
3192   gtk_window_set_title (GTK_WINDOW (window), "Label");
3193   vbox = gtk_vbox_new (FALSE, 5);
3194   hbox = gtk_hbox_new (FALSE, 5);
3195   gtk_container_add (GTK_CONTAINER (window), hbox);
3196   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3197   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3198   
3199   frame = gtk_frame_new ("Normal Label");
3200   label = gtk_label_new ("This is a Normal label");
3201   gtk_container_add (GTK_CONTAINER (frame), label);
3202   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3203   
3204   frame = gtk_frame_new ("Multi-line Label");
3205   label = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \
3206                          "Third line");
3207   gtk_container_add (GTK_CONTAINER (frame), label);
3208   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3209   
3210   frame = gtk_frame_new ("Left Justified Label");
3211   label = gtk_label_new ("This is a Left-Justified\n" \
3212                          "Multi-line label.\nThird      line");
3213   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3214   gtk_container_add (GTK_CONTAINER (frame), label);
3215   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3216   
3217   frame = gtk_frame_new ("Right Justified Label");
3218   label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \
3219                          "Fourth line, (j/k)");
3220   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3221   gtk_container_add (GTK_CONTAINER (frame), label);
3222   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3223
3224   vbox = gtk_vbox_new (FALSE, 5);
3225   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3226   frame = gtk_frame_new ("Line wrapped label");
3227   label = gtk_label_new ("This is an example of a line-wrapped label.  It " \
3228                          "should not be taking up the entire             " /* big space to test spacing */\
3229                          "width allocated to it, but automatically " \
3230                          "wraps the words to fit.  " \
3231                          "The time has come, for all good men, to come to " \
3232                          "the aid of their party.  " \
3233                          "The sixth sheik's six sheep's sick.\n" \
3234                          "     It supports multiple paragraphs correctly, " \
3235                          "and  correctly   adds "\
3236                          "many          extra  spaces. ");
3237   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3238   gtk_container_add (GTK_CONTAINER (frame), label);
3239   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3240   
3241   frame = gtk_frame_new ("Filled, wrapped label");
3242   label = gtk_label_new ("This is an example of a line-wrapped, filled label.  " \
3243                          "It should be taking "\
3244                          "up the entire              width allocated to it.  " \
3245                          "Here is a sentence to prove "\
3246                          "my point.  Here is another sentence. "\
3247                          "Here comes the sun, do de do de do.\n"\
3248                          "    This is a new paragraph.\n"\
3249                          "    This is another newer, longer, better " \
3250                          "paragraph.  It is coming to an end, "\
3251                          "unfortunately.");
3252   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3253   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3254   gtk_container_add (GTK_CONTAINER (frame), label);
3255   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3256   
3257   frame = gtk_frame_new ("Underlined label");
3258   label = gtk_label_new ("This label is underlined!\n"
3259                          "This one is underlined in quite a funky fashion");
3260   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3261   gtk_label_set_pattern (GTK_LABEL (label),
3262                          "_________________________ _ _________ _ ______     __ _______ ___");
3263   gtk_container_add (GTK_CONTAINER (frame), label);
3264   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3265   
3266   gtk_widget_show_all (window);
3267
3268   gtk_main ();
3269   
3270   return(0);
3271 }
3272 /* example-end */
3273 </verb></tscreen>
3274
3275 <!-- ----------------------------------------------------------------- -->
3276 <sect1> Arrows
3277 <p>
3278 The Arrow widget draws an arrowhead, facing in a number of possible
3279 directions and having a number of possible styles. It can be very
3280 useful when placed on a button in many applications. Like the Label
3281 widget, it emits no signals.
3282
3283 There are only two functions for manipulating an Arrow widget:
3284
3285 <tscreen><verb>
3286 GtkWidget *gtk_arrow_new( GtkArrowType   arrow_type,
3287                           GtkShadowType  shadow_type );
3288
3289 void gtk_arrow_set( GtkArrow      *arrow,
3290                     GtkArrowType   arrow_type,
3291                     GtkShadowType  shadow_type );
3292 </verb></tscreen>
3293
3294 The first creates a new arrow widget with the indicated type and
3295 appearance. The second allows these values to be altered
3296 retrospectively. The <tt/arrow_type/ argument may take one of the
3297 following values:
3298
3299 <tscreen><verb>
3300   GTK_ARROW_UP
3301   GTK_ARROW_DOWN
3302   GTK_ARROW_LEFT
3303   GTK_ARROW_RIGHT
3304 </verb></tscreen>
3305
3306 These values obviously indicate the direction in which the arrow will
3307 point. The <tt/shadow_type/ argument may take one of these values:
3308
3309 <tscreen><verb>
3310   GTK_SHADOW_IN
3311   GTK_SHADOW_OUT (the default)
3312   GTK_SHADOW_ETCHED_IN
3313   GTK_SHADOW_ETCHED_OUT
3314 </verb></tscreen>
3315
3316 Here's a brief example to illustrate their use.
3317
3318 <tscreen><verb>
3319 /* example-start arrow arrow.c */
3320
3321 #include <gtk/gtk.h>
3322
3323 /* Create an Arrow widget with the specified parameters
3324  * and pack it into a button */
3325 GtkWidget *create_arrow_button( GtkArrowType  arrow_type,
3326                                 GtkShadowType shadow_type )
3327 {
3328   GtkWidget *button;
3329   GtkWidget *arrow;
3330
3331   button = gtk_button_new();
3332   arrow = gtk_arrow_new (arrow_type, shadow_type);
3333
3334   gtk_container_add (GTK_CONTAINER (button), arrow);
3335   
3336   gtk_widget_show(button);
3337   gtk_widget_show(arrow);
3338
3339   return(button);
3340 }
3341
3342 int main( int   argc,
3343           char *argv[] )
3344 {
3345   /* GtkWidget is the storage type for widgets */
3346   GtkWidget *window;
3347   GtkWidget *button;
3348   GtkWidget *box;
3349
3350   /* Initialize the toolkit */
3351   gtk_init (&amp;argc, &amp;argv);
3352
3353   /* Create a new window */
3354   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3355
3356   gtk_window_set_title (GTK_WINDOW (window), "Arrow Buttons");
3357
3358   /* It's a good idea to do this for all windows. */
3359   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3360                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
3361
3362   /* Sets the border width of the window. */
3363   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
3364
3365   /* Create a box to hold the arrows/buttons */
3366   box = gtk_hbox_new (FALSE, 0);
3367   gtk_container_set_border_width (GTK_CONTAINER (box), 2);
3368   gtk_container_add (GTK_CONTAINER (window), box);
3369
3370   /* Pack and show all our widgets */
3371   gtk_widget_show(box);
3372
3373   button = create_arrow_button(GTK_ARROW_UP, GTK_SHADOW_IN);
3374   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3375
3376   button = create_arrow_button(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
3377   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3378   
3379   button = create_arrow_button(GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN);
3380   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3381   
3382   button = create_arrow_button(GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT);
3383   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3384   
3385   gtk_widget_show (window);
3386   
3387   /* Rest in gtk_main and wait for the fun to begin! */
3388   gtk_main ();
3389   
3390   return(0);
3391 }
3392 /* example-end */
3393 </verb></tscreen>
3394
3395 <!-- ----------------------------------------------------------------- -->
3396 <sect1>The Tooltips Object
3397 <p>
3398 These are the little text strings that pop up when you leave your
3399 pointer over a button or other widget for a few seconds. They are easy
3400 to use, so I will just explain them without giving an example. If you
3401 want to see some code, take a look at the testgtk.c program
3402 distributed with GTK.
3403
3404 Widgets that do not receive events (widgets that do not have their
3405 own window) will not work with tooltips.
3406
3407 The first call you will use creates a new tooltip. You only need to do
3408 this once for a set of tooltips as the <tt/GtkTooltips/ object this
3409 function returns can be used to create multiple tooltips.
3410
3411 <tscreen><verb>
3412 GtkTooltips *gtk_tooltips_new( void );
3413 </verb></tscreen>
3414
3415 Once you have created a new tooltip, and the widget you wish to use it
3416 on, simply use this call to set it:
3417
3418 <tscreen><verb>
3419 void gtk_tooltips_set_tip( GtkTooltips *tooltips,
3420                            GtkWidget   *widget,
3421                            const gchar *tip_text,
3422                            const gchar *tip_private );
3423 </verb></tscreen>
3424
3425 The first argument is the tooltip you've already created, followed by
3426 the widget you wish to have this tooltip pop up for, and the text you
3427 wish it to say. The last argument is a text string that can be used as
3428 an identifier when using GtkTipsQuery to implement context sensitive
3429 help. For now, you can set it to NULL.
3430
3431 <!-- TODO: sort out what how to do the context sensitive help -->
3432
3433 Here's a short example:
3434
3435 <tscreen><verb>
3436 GtkTooltips *tooltips;
3437 GtkWidget *button;
3438 .
3439 .
3440 .
3441 tooltips = gtk_tooltips_new ();
3442 button = gtk_button_new_with_label ("button 1");
3443 .
3444 .
3445 .
3446 gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);
3447 </verb></tscreen>
3448
3449 There are other calls that can be used with tooltips. I will just list
3450 them with a brief description of what they do.
3451
3452 <tscreen><verb>
3453 void gtk_tooltips_enable( GtkTooltips *tooltips );
3454 </verb></tscreen>
3455
3456 Enable a disabled set of tooltips.
3457
3458 <tscreen><verb>
3459 void gtk_tooltips_disable( GtkTooltips *tooltips );
3460 </verb></tscreen>
3461
3462 Disable an enabled set of tooltips.
3463
3464 <tscreen><verb>
3465 void gtk_tooltips_set_delay( GtkTooltips *tooltips,
3466                              gint         delay );
3467
3468 </verb></tscreen>
3469
3470 Sets how many milliseconds you have to hold your pointer over the
3471 widget before the tooltip will pop up. The default is 500
3472 milliseconds (half a second).
3473
3474 <tscreen><verb>
3475 void gtk_tooltips_set_colors( GtkTooltips *tooltips,
3476                               GdkColor    *background,
3477                               GdkColor    *foreground );
3478 </verb></tscreen>
3479
3480 Set the foreground and background color of the tooltips.
3481
3482 And that's all the functions associated with tooltips. More than
3483 you'll ever want to know :-)
3484
3485 <!-- ----------------------------------------------------------------- -->
3486 <sect1> Progress Bars <label id="sec_ProgressBar">
3487 <p>
3488 Progress bars are used to show the status of an operation. They are
3489 pretty easy to use, as you will see with the code below. But first
3490 lets start out with the calls to create a new progress bar.
3491
3492 There are two ways to create a progress bar, one simple that takes
3493 no arguments, and one that takes an Adjustment object as an
3494 argument. If the former is used, the progress bar creates its own
3495 adjustment object.
3496
3497 <tscreen><verb>
3498 GtkWidget *gtk_progress_bar_new( void );
3499
3500 GtkWidget *gtk_progress_bar_new_with_adjustment( GtkAdjustment *adjustment );
3501 </verb></tscreen>
3502
3503 The second method has the advantage that we can use the adjustment
3504 object to specify our own range parameters for the progress bar.
3505
3506 The adjustment of a progress object can be changed dynamically using:
3507
3508 <tscreen><verb>
3509 void gtk_progress_set_adjustment( GtkProgress   *progress,
3510                                   GtkAdjustment *adjustment );
3511 </verb></tscreen>
3512
3513 Now that the progress bar has been created we can use it.
3514
3515 <tscreen><verb>
3516 void gtk_progress_bar_update( GtkProgressBar *pbar,
3517                               gfloat          percentage );
3518 </verb></tscreen>
3519
3520 The first argument is the progress bar you wish to operate on, and the
3521 second argument is the amount "completed", meaning the amount the
3522 progress bar has been filled from 0-100%. This is passed to the
3523 function as a real number ranging from 0 to 1.
3524
3525 GTK v1.2 has added new functionality to the progress bar that enables
3526 it to display its value in different ways, and to inform the user of
3527 its current value and its range.
3528
3529 A progress bar may be set to one of a number of orientations using the
3530 function
3531
3532 <tscreen><verb>
3533 void gtk_progress_bar_set_orientation( GtkProgressBar *pbar,
3534                                        GtkProgressBarOrientation orientation );
3535 </verb></tscreen>
3536
3537 The <tt/orientation/ argument may take one of the following
3538 values to indicate the direction in which the progress bar moves:
3539
3540 <tscreen><verb>
3541   GTK_PROGRESS_LEFT_TO_RIGHT
3542   GTK_PROGRESS_RIGHT_TO_LEFT
3543   GTK_PROGRESS_BOTTOM_TO_TOP
3544   GTK_PROGRESS_TOP_TO_BOTTOM
3545 </verb></tscreen>
3546
3547 When used as a measure of how far a process has progressed, the
3548 ProgressBar can be set to display its value in either a continuous
3549 or discrete mode. In continuous mode, the progress bar is updated for
3550 each value. In discrete mode, the progress bar is updated in a number
3551 of discrete blocks. The number of blocks is also configurable.
3552
3553 The style of a progress bar can be set using the following function.
3554
3555 <tscreen><verb>
3556 void gtk_progress_bar_set_bar_style( GtkProgressBar      *pbar,
3557                                      GtkProgressBarStyle  style );
3558 </verb></tscreen>
3559
3560 The <tt/style/ parameter can take one of two values:
3561
3562 <tscreen><verb>
3563   GTK_PROGRESS_CONTINUOUS
3564   GTK_PROGRESS_DISCRETE
3565 </verb></tscreen>
3566
3567 The number of discrete blocks can be set by calling
3568
3569 <tscreen><verb>
3570 void gtk_progress_bar_set_discrete_blocks( GtkProgressBar *pbar,
3571                                            guint           blocks );
3572 </verb></tscreen>
3573
3574 As well as indicating the amount of progress that has occured, the
3575 progress bar may be set to just indicate that there is some
3576 activity. This can be useful in situations where progress cannot be
3577 measured against a value range. Activity mode is not effected by the
3578 bar style that is described above, and overrides it. This mode is
3579 either TRUE or FALSE, and is selected by the following function.
3580
3581 <tscreen><verb>
3582 void gtk_progress_set_activity_mode( GtkProgress *progress,
3583                                      guint        activity_mode );
3584 </verb></tscreen>
3585
3586 The step size of the activity indicator, and the number of blocks are
3587 set using the following functions.
3588
3589 <tscreen><verb>
3590 void gtk_progress_bar_set_activity_step( GtkProgressBar *pbar,
3591                                          guint           step );
3592
3593 void gtk_progress_bar_set_activity_blocks( GtkProgressBar *pbar,
3594                                            guint           blocks );
3595 </verb></tscreen>
3596
3597 When in continuous mode, the progress bar can also display a
3598 configurable text string within its trough, using the following
3599 function.
3600
3601 <tscreen><verb>
3602 void gtk_progress_set_format_string( GtkProgress *progress,
3603                                      gchar       *format);
3604 </verb></tscreen>
3605
3606 The <tt/format/ argument is similiar to one that would be used in a C
3607 <tt/printf/ statement. The following directives may be used within the
3608 format string:
3609
3610 <itemize>
3611 <item> %p - percentage
3612 <item> %v - value
3613 <item> %l - lower range value
3614 <item> %u - upper range value
3615 </itemize>
3616
3617 The displaying of this text string can be toggled using:
3618
3619 <tscreen><verb>
3620 void gtk_progress_set_show_text( GtkProgress *progress,
3621                                  gint         show_text );
3622 </verb></tscreen>
3623
3624 The <tt/show_text/ argument is a boolean TRUE/FALSE value. The
3625 appearance of the text can be modified further using:
3626
3627 <tscreen><verb>
3628 void gtk_progress_set_text_alignment( GtkProgress   *progress,
3629                                       gfloat         x_align,
3630                                       gfloat         y_align );
3631 </verb></tscreen>
3632
3633 The <tt/x_align/ and <tt/y_align/ arguments take values between 0.0
3634 and 1.0. Their values indicate the position of the text string within
3635 the trough. Values of 0.0 for both would place the string in the top
3636 left hand corner; values of 0.5 (the default) centres the text, and
3637 values of 1.0 places the text in the lower right hand corner.
3638
3639 The current text setting of a progress object can be retrieved using
3640 the current or a specified adjustment value using the following two
3641 functions. The character string returned by these functions should be
3642 freed by the application (using the g_free() function). These
3643 functions return the formatted string that would be displayed within
3644 the trough.
3645
3646 <tscreen><verb>
3647 gchar *gtk_progress_get_current_text( GtkProgress   *progress );
3648
3649 gchar *gtk_progress_get_text_from_value( GtkProgress *progress,
3650                                          gfloat       value );
3651 </verb></tscreen>
3652
3653 There is yet another way to change the range and value of a progress
3654 object using the following function:
3655
3656 <tscreen><verb>
3657 void gtk_progress_configure( GtkProgress  *progress,
3658                              gfloat        value,
3659                              gfloat        min,
3660                              gfloat        max );
3661 </verb></tscreen>
3662
3663 This function provides quite a simple interface to the range and value
3664 of a progress object.
3665
3666 The remaining functions can be used to get and set the current value
3667 of a progess object in various types and formats:
3668
3669 <tscreen><verb>
3670 void gtk_progress_set_percentage( GtkProgress *progress,
3671                                   gfloat       percentage );
3672
3673 void gtk_progress_set_value( GtkProgress *progress,
3674                              gfloat       value );
3675
3676 gfloat gtk_progress_get_value( GtkProgress *progress );
3677
3678 gfloat gtk_progress_get_current_percentage( GtkProgress *progress );
3679
3680 gfloat gtk_progress_get_percentage_from_value( GtkProgress *progress,
3681                                                gfloat       value );
3682 </verb></tscreen>
3683
3684 These functions are pretty self explanatory. The last function uses
3685 the the adjustment of the specified progess object to compute the
3686 percentage value of the given range value.
3687
3688 Progress Bars are usually used with timeouts or other such functions
3689 (see section on <ref id="sec_timeouts" name="Timeouts, I/O and Idle
3690 Functions">) to give the illusion of multitasking. All will employ the
3691 gtk_progress_bar_update function in the same manner.
3692
3693 Here is an example of the progress bar, updated using timeouts. This
3694 code also shows you how to reset the Progress Bar.
3695
3696 <tscreen><verb>
3697 /* example-start progressbar progressbar.c */
3698
3699 #include <gtk/gtk.h>
3700
3701 typedef struct _ProgressData {
3702     GtkWidget *window;
3703     GtkWidget *pbar;
3704     int timer;
3705 } ProgressData;
3706
3707 /* Update the value of the progress bar so that we get
3708  * some movement */
3709 gint progress_timeout( gpointer data )
3710 {
3711     gfloat new_val;
3712     GtkAdjustment *adj;
3713
3714     /* Calculate the value of the progress bar using the
3715      * value range set in the adjustment object */
3716
3717     new_val = gtk_progress_get_value( GTK_PROGRESS(data) ) + 1;
3718
3719     adj = GTK_PROGRESS (data)->adjustment;
3720     if (new_val > adj->upper)
3721       new_val = adj->lower;
3722
3723     /* Set the new value */
3724     gtk_progress_set_value (GTK_PROGRESS (data), new_val);
3725
3726     /* As this is a timeout function, return TRUE so that it
3727      * continues to get called */
3728     return(TRUE);
3729
3730
3731 /* Callback that toggles the text display within the progress
3732  * bar trough */
3733 void toggle_show_text( GtkWidget    *widget,
3734                        ProgressData *pdata )
3735 {
3736     gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
3737                                 GTK_TOGGLE_BUTTON (widget)->active);
3738 }
3739
3740 /* Callback that toggles the activity mode of the progress
3741  * bar */
3742 void toggle_activity_mode( GtkWidget    *widget,
3743                            ProgressData *pdata )
3744 {
3745     gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
3746                                     GTK_TOGGLE_BUTTON (widget)->active);
3747 }
3748
3749 /* Callback that toggles the continuous mode of the progress
3750  * bar */
3751 void set_continuous_mode( GtkWidget    *widget,
3752                           ProgressData *pdata )
3753 {
3754     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3755                                     GTK_PROGRESS_CONTINUOUS);
3756 }
3757
3758 /* Callback that toggles the discrete mode of the progress
3759  * bar */
3760 void set_discrete_mode( GtkWidget    *widget,
3761                         ProgressData *pdata )
3762 {
3763     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3764                                     GTK_PROGRESS_DISCRETE);
3765 }
3766  
3767 /* Clean up allocated memory and remove the timer */
3768 void destroy_progress( GtkWidget     *widget,
3769                        ProgressData *pdata)
3770 {
3771     gtk_timeout_remove (pdata->timer);
3772     pdata->timer = 0;
3773     pdata->window = NULL;
3774     g_free(pdata);
3775     gtk_main_quit();
3776 }
3777
3778 int main( int   argc,
3779           char *argv[])
3780 {
3781     ProgressData *pdata;
3782     GtkWidget *align;
3783     GtkWidget *separator;
3784     GtkWidget *table;
3785     GtkAdjustment *adj;
3786     GtkWidget *button;
3787     GtkWidget *check;
3788     GtkWidget *vbox;
3789
3790     gtk_init (&amp;argc, &amp;argv);
3791
3792     /* Allocate memory for the data that is passwd to the callbacks */
3793     pdata = g_malloc( sizeof(ProgressData) );
3794   
3795     pdata->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3796     gtk_window_set_policy (GTK_WINDOW (pdata->window), FALSE, FALSE, TRUE);
3797
3798     gtk_signal_connect (GTK_OBJECT (pdata->window), "destroy",
3799                         GTK_SIGNAL_FUNC (destroy_progress),
3800                         pdata);
3801     gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
3802     gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
3803
3804     vbox = gtk_vbox_new (FALSE, 5);
3805     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
3806     gtk_container_add (GTK_CONTAINER (pdata->window), vbox);
3807     gtk_widget_show(vbox);
3808   
3809     /* Create a centering alignment object */
3810     align = gtk_alignment_new (0.5, 0.5, 0, 0);
3811     gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
3812     gtk_widget_show(align);
3813
3814     /* Create a Adjusment object to hold the range of the
3815      * progress bar */
3816     adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 150, 0, 0, 0);
3817
3818     /* Create the GtkProgressBar using the adjustment */
3819     pdata->pbar = gtk_progress_bar_new_with_adjustment (adj);
3820
3821     /* Set the format of the string that can be displayed in the
3822      * trough of the progress bar:
3823      * %p - percentage
3824      * %v - value
3825      * %l - lower range value
3826      * %u - upper range value */
3827     gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
3828                                     "%v from [%l-%u] (=%p%%)");
3829     gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
3830     gtk_widget_show(pdata->pbar);
3831
3832     /* Add a timer callback to update the value of the progress bar */
3833     pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
3834
3835     separator = gtk_hseparator_new ();
3836     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3837     gtk_widget_show(separator);
3838
3839     /* rows, columns, homogeneous */
3840     table = gtk_table_new (2, 3, FALSE);
3841     gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
3842     gtk_widget_show(table);
3843
3844     /* Add a check button to select displaying of the trough text */
3845     check = gtk_check_button_new_with_label ("Show text");
3846     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
3847                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3848                       5, 5);
3849     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3850                         GTK_SIGNAL_FUNC (toggle_show_text),
3851                         pdata);
3852     gtk_widget_show(check);
3853
3854     /* Add a check button to toggle activity mode */
3855     check = gtk_check_button_new_with_label ("Activity mode");
3856     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
3857                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3858                       5, 5);
3859     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3860                         GTK_SIGNAL_FUNC (toggle_activity_mode),
3861                         pdata);
3862     gtk_widget_show(check);
3863
3864     separator = gtk_vseparator_new ();
3865     gtk_table_attach (GTK_TABLE (table), separator, 1, 2, 0, 2,
3866                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3867                       5, 5);
3868     gtk_widget_show(separator);
3869
3870     /* Add a radio button to select continuous display mode */
3871     button = gtk_radio_button_new_with_label (NULL, "Continuous");
3872     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
3873                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3874                       5, 5);
3875     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3876                         GTK_SIGNAL_FUNC (set_continuous_mode),
3877                         pdata);
3878     gtk_widget_show (button);
3879
3880     /* Add a radio button to select discrete display mode */
3881     button = gtk_radio_button_new_with_label(
3882                gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
3883                "Discrete");
3884     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
3885                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3886                       5, 5);
3887     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3888                         GTK_SIGNAL_FUNC (set_discrete_mode),
3889                         pdata);
3890     gtk_widget_show (button);
3891
3892     separator = gtk_hseparator_new ();
3893     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3894     gtk_widget_show(separator);
3895
3896     /* Add a button to exit the program */
3897     button = gtk_button_new_with_label ("close");
3898     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3899                                (GtkSignalFunc) gtk_widget_destroy,
3900                                GTK_OBJECT (pdata->window));
3901     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3902
3903     /* This makes it so the button is the default. */
3904     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3905
3906     /* This grabs this button to be the default button. Simply hitting
3907      * the "Enter" key will cause this button to activate. */
3908     gtk_widget_grab_default (button);
3909     gtk_widget_show(button);
3910
3911     gtk_widget_show (pdata->window);
3912
3913     gtk_main ();
3914     
3915     return(0);
3916 }
3917 /* example-end */
3918 </verb></tscreen>
3919
3920 <!-- ----------------------------------------------------------------- -->
3921 <sect1> Dialogs
3922 <p>
3923 The Dialog widget is very simple, and is actually just a window with a
3924 few things pre-packed into it for you. The structure for a Dialog is:
3925
3926 <tscreen><verb>
3927 struct GtkDialog
3928 {
3929       GtkWindow window;
3930     
3931       GtkWidget *vbox;
3932       GtkWidget *action_area;
3933 };
3934 </verb></tscreen>
3935
3936 So you see, it simply creates a window, and then packs a vbox into the
3937 top, which contains a separator and then an hbox called the
3938 "action_area".
3939
3940 The Dialog widget can be used for pop-up messages to the user, and
3941 other similar tasks. It is really basic, and there is only one
3942 function for the dialog box, which is:
3943
3944 <tscreen><verb>
3945 GtkWidget *gtk_dialog_new( void );
3946 </verb></tscreen>
3947
3948 So to create a new dialog box, use,
3949
3950 <tscreen><verb>
3951     GtkWidget *window;
3952     window = gtk_dialog_new ();
3953 </verb></tscreen>
3954
3955 This will create the dialog box, and it is now up to you to use it.
3956 You could pack a button in the action_area by doing something like this:
3957
3958 <tscreen><verb>
3959     button = ...
3960     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
3961                         button, TRUE, TRUE, 0);
3962     gtk_widget_show (button);
3963 </verb></tscreen>
3964
3965 And you could add to the vbox area by packing, for instance, a label 
3966 in it, try something like this:
3967
3968 <tscreen><verb>
3969     label = gtk_label_new ("Dialogs are groovy");
3970     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
3971                         label, TRUE, TRUE, 0);
3972     gtk_widget_show (label);
3973 </verb></tscreen>
3974
3975 As an example in using the dialog box, you could put two buttons in
3976 the action_area, a Cancel button and an Ok button, and a label in the
3977 vbox area, asking the user a question or giving an error etc. Then
3978 you could attach a different signal to each of the buttons and perform
3979 the operation the user selects.
3980
3981 If the simple functionality provided by the default vertical and
3982 horizontal boxes in the two areas doesn't give you enough control for
3983 your application, then you can simply pack another layout widget into
3984 the boxes provided. For example, you could pack a table into the
3985 vertical box.
3986
3987 <!-- ----------------------------------------------------------------- -->
3988 <sect1> Pixmaps <label id="sec_Pixmaps">
3989 <p>
3990 Pixmaps are data structures that contain pictures. These pictures can
3991 be used in various places, but most commonly as icons on the X
3992 desktop, or as cursors.
3993
3994 A pixmap which only has 2 colors is called a bitmap, and there are a
3995 few additional routines for handling this common special case.
3996
3997 To understand pixmaps, it would help to understand how X window
3998 system works. Under X, applications do not need to be running on the
3999 same computer that is interacting with the user. Instead, the various
4000 applications, called "clients", all communicate with a program which
4001 displays the graphics and handles the keyboard and mouse. This
4002 program which interacts directly with the user is called a "display
4003 server" or "X server." Since the communication might take place over
4004 a network, it's important to keep some information with the X server.
4005 Pixmaps, for example, are stored in the memory of the X server. This
4006 means that once pixmap values are set, they don't need to keep getting
4007 transmitted over the network; instead a command is sent to "display
4008 pixmap number XYZ here." Even if you aren't using X with GTK
4009 currently, using constructs such as Pixmaps will make your programs
4010 work acceptably under X.
4011
4012 To use pixmaps in GTK, we must first build a GdkPixmap structure using
4013 routines from the GDK layer. Pixmaps can either be created from
4014 in-memory data, or from data read from a file. We'll go through each
4015 of the calls to create a pixmap.
4016
4017 <tscreen><verb>
4018 GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window,
4019                                         gchar     *data,
4020                                         gint       width,
4021                                         gint       height );
4022 </verb></tscreen>
4023
4024 This routine is used to create a single-plane pixmap (2 colors) from
4025 data in memory. Each bit of the data represents whether that pixel is
4026 off or on. Width and height are in pixels. The GdkWindow pointer is to
4027 the current window, since a pixmap's resources are meaningful only in
4028 the context of the screen where it is to be displayed.
4029
4030 <tscreen><verb>
4031 GdkPixmap *gdk_pixmap_create_from_data( GdkWindow *window,
4032                                         gchar     *data,
4033                                         gint       width,
4034                                         gint       height,
4035                                         gint       depth,
4036                                         GdkColor  *fg,
4037                                         GdkColor  *bg );
4038 </verb></tscreen>
4039
4040 This is used to create a pixmap of the given depth (number of colors) from
4041 the bitmap data specified. <tt/fg/ and <tt/bg/ are the foreground and
4042 background color to use.
4043
4044 <tscreen><verb>
4045 GdkPixmap *gdk_pixmap_create_from_xpm( GdkWindow   *window,
4046                                        GdkBitmap  **mask,
4047                                        GdkColor    *transparent_color,
4048                                        const gchar *filename );
4049 </verb></tscreen>
4050
4051 XPM format is a readable pixmap representation for the X Window
4052 System. It is widely used and many different utilities are available
4053 for creating image files in this format. The file specified by
4054 filename must contain an image in that format and it is loaded into
4055 the pixmap structure. The mask specifies which bits of the pixmap are
4056 opaque. All other bits are colored using the color specified by
4057 transparent_color. An example using this follows below.
4058
4059 <tscreen><verb>
4060 GdkPixmap *gdk_pixmap_create_from_xpm_d( GdkWindow  *window,
4061                                          GdkBitmap **mask,
4062                                          GdkColor   *transparent_color,
4063                                          gchar     **data );
4064 </verb></tscreen>
4065
4066 Small images can be incorporated into a program as data in the XPM
4067 format. A pixmap is created using this data, instead of reading it
4068 from a file. An example of such data is
4069
4070 <tscreen><verb>
4071 /* XPM */
4072 static const char * xpm_data[] = {
4073 "16 16 3 1",
4074 "       c None",
4075 ".      c #000000000000",
4076 "X      c #FFFFFFFFFFFF",
4077 "                ",
4078 "   ......       ",
4079 "   .XXX.X.      ",
4080 "   .XXX.XX.     ",
4081 "   .XXX.XXX.    ",
4082 "   .XXX.....    ",
4083 "   .XXXXXXX.    ",
4084 "   .XXXXXXX.    ",
4085 "   .XXXXXXX.    ",
4086 "   .XXXXXXX.    ",
4087 "   .XXXXXXX.    ",
4088 "   .XXXXXXX.    ",
4089 "   .XXXXXXX.    ",
4090 "   .........    ",
4091 "                ",
4092 "                "};
4093 </verb></tscreen>
4094
4095 When we're done using a pixmap and not likely to reuse it again soon,
4096 it is a good idea to release the resource using
4097 gdk_pixmap_unref(). Pixmaps should be considered a precious resource,
4098 because they take up memory in the end-user's X server process. Even
4099 though the X client you write may run on a powerful "server" computer,
4100 the user may be running the X server on a small personal computer.
4101
4102 Once we've created a pixmap, we can display it as a GTK widget. We
4103 must create a GTK pixmap widget to contain the GDK pixmap. This is
4104 done using
4105
4106 <tscreen><verb>
4107 GtkWidget *gtk_pixmap_new( GdkPixmap *pixmap,
4108                            GdkBitmap *mask );
4109 </verb></tscreen>
4110
4111 The other pixmap widget calls are
4112
4113 <tscreen><verb>
4114 guint gtk_pixmap_get_type( void );
4115
4116 void  gtk_pixmap_set( GtkPixmap  *pixmap,
4117                       GdkPixmap  *val,
4118                       GdkBitmap  *mask );
4119
4120 void  gtk_pixmap_get( GtkPixmap  *pixmap,
4121                       GdkPixmap **val,
4122                       GdkBitmap **mask);
4123 </verb></tscreen>
4124
4125 gtk_pixmap_set is used to change the pixmap that the widget is currently
4126 managing. Val is the pixmap created using GDK.
4127
4128 The following is an example of using a pixmap in a button.
4129
4130 <tscreen><verb>
4131 /* example-start pixmap pixmap.c */
4132
4133 #include <gtk/gtk.h>
4134
4135
4136 /* XPM data of Open-File icon */
4137 static const char * xpm_data[] = {
4138 "16 16 3 1",
4139 "       c None",
4140 ".      c #000000000000",
4141 "X      c #FFFFFFFFFFFF",
4142 "                ",
4143 "   ......       ",
4144 "   .XXX.X.      ",
4145 "   .XXX.XX.     ",
4146 "   .XXX.XXX.    ",
4147 "   .XXX.....    ",
4148 "   .XXXXXXX.    ",
4149 "   .XXXXXXX.    ",
4150 "   .XXXXXXX.    ",
4151 "   .XXXXXXX.    ",
4152 "   .XXXXXXX.    ",
4153 "   .XXXXXXX.    ",
4154 "   .XXXXXXX.    ",
4155 "   .........    ",
4156 "                ",
4157 "                "};
4158
4159
4160 /* when invoked (via signal delete_event), terminates the application.
4161  */
4162 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4163     gtk_main_quit();
4164 }
4165
4166
4167 /* is invoked when the button is clicked.  It just prints a message.
4168  */
4169 void button_clicked( GtkWidget *widget, gpointer data ) {
4170     printf( "button clicked\n" );
4171 }
4172
4173 int main( int argc, char *argv[] )
4174 {
4175     /* GtkWidget is the storage type for widgets */
4176     GtkWidget *window, *pixmapwid, *button;
4177     GdkPixmap *pixmap;
4178     GdkBitmap *mask;
4179     GtkStyle *style;
4180     
4181     /* create the main window, and attach delete_event signal to terminating
4182        the application */
4183     gtk_init( &amp;argc, &amp;argv );
4184     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4185     gtk_signal_connect( GTK_OBJECT (window), "delete_event",
4186                         GTK_SIGNAL_FUNC (close_application), NULL );
4187     gtk_container_set_border_width( GTK_CONTAINER (window), 10 );
4188     gtk_widget_show( window );
4189
4190     /* now for the pixmap from gdk */
4191     style = gtk_widget_get_style( window );
4192     pixmap = gdk_pixmap_create_from_xpm_d( window->window,  &amp;mask,
4193                                            &amp;style->bg[GTK_STATE_NORMAL],
4194                                            (gchar **)xpm_data );
4195
4196     /* a pixmap widget to contain the pixmap */
4197     pixmapwid = gtk_pixmap_new( pixmap, mask );
4198     gtk_widget_show( pixmapwid );
4199
4200     /* a button to contain the pixmap widget */
4201     button = gtk_button_new();
4202     gtk_container_add( GTK_CONTAINER(button), pixmapwid );
4203     gtk_container_add( GTK_CONTAINER(window), button );
4204     gtk_widget_show( button );
4205
4206     gtk_signal_connect( GTK_OBJECT(button), "clicked",
4207                         GTK_SIGNAL_FUNC(button_clicked), NULL );
4208
4209     /* show the window */
4210     gtk_main ();
4211           
4212     return 0;
4213 }
4214 /* example-end */
4215 </verb></tscreen>
4216
4217 To load a file from an XPM data file called icon0.xpm in the current
4218 directory, we would have created the pixmap thus
4219
4220 <tscreen><verb>
4221     /* load a pixmap from a file */
4222     pixmap = gdk_pixmap_create_from_xpm( window->window, &amp;mask,
4223                                          &amp;style->bg[GTK_STATE_NORMAL],
4224                                          "./icon0.xpm" );
4225     pixmapwid = gtk_pixmap_new( pixmap, mask );
4226     gtk_widget_show( pixmapwid );
4227     gtk_container_add( GTK_CONTAINER(window), pixmapwid );
4228 </verb></tscreen>
4229
4230 A disadvantage of using pixmaps is that the displayed object is always
4231 rectangular, regardless of the image. We would like to create desktops
4232 and applications with icons that have more natural shapes. For
4233 example, for a game interface, we would like to have round buttons to
4234 push. The way to do this is using shaped windows.
4235
4236 A shaped window is simply a pixmap where the background pixels are
4237 transparent. This way, when the background image is multi-colored, we
4238 don't overwrite it with a rectangular, non-matching border around our
4239 icon. The following example displays a full wheelbarrow image on the
4240 desktop.
4241
4242 <tscreen><verb>
4243 /* example-start wheelbarrow wheelbarrow.c */
4244
4245 #include <gtk/gtk.h>
4246
4247 /* XPM */
4248 static char * WheelbarrowFull_xpm[] = {
4249 "48 48 64 1",
4250 "       c None",
4251 ".      c #DF7DCF3CC71B",
4252 "X      c #965875D669A6",
4253 "o      c #71C671C671C6",
4254 "O      c #A699A289A699",
4255 "+      c #965892489658",
4256 "@      c #8E38410330C2",
4257 "#      c #D75C7DF769A6",
4258 "$      c #F7DECF3CC71B",
4259 "%      c #96588A288E38",
4260 "&amp;      c #A69992489E79",
4261 "*      c #8E3886178E38",
4262 "=      c #104008200820",
4263 "-      c #596510401040",
4264 ";      c #C71B30C230C2",
4265 ":      c #C71B9A699658",
4266 ">      c #618561856185",
4267 ",      c #20811C712081",
4268 "<      c #104000000000",
4269 "1      c #861720812081",
4270 "2      c #DF7D4D344103",
4271 "3      c #79E769A671C6",
4272 "4      c #861782078617",
4273 "5      c #41033CF34103",
4274 "6      c #000000000000",
4275 "7      c #49241C711040",
4276 "8      c #492445144924",
4277 "9      c #082008200820",
4278 "0      c #69A618611861",
4279 "q      c #B6DA71C65144",
4280 "w      c #410330C238E3",
4281 "e      c #CF3CBAEAB6DA",
4282 "r      c #71C6451430C2",
4283 "t      c #EFBEDB6CD75C",
4284 "y      c #28A208200820",
4285 "u      c #186110401040",
4286 "i      c #596528A21861",
4287 "p      c #71C661855965",
4288 "a      c #A69996589658",
4289 "s      c #30C228A230C2",
4290 "d      c #BEFBA289AEBA",
4291 "f      c #596545145144",
4292 "g      c #30C230C230C2",
4293 "h      c #8E3882078617",
4294 "j      c #208118612081",
4295 "k      c #38E30C300820",
4296 "l      c #30C2208128A2",
4297 "z      c #38E328A238E3",
4298 "x      c #514438E34924",
4299 "c      c #618555555965",
4300 "v      c #30C2208130C2",
4301 "b      c #38E328A230C2",
4302 "n      c #28A228A228A2",
4303 "m      c #41032CB228A2",
4304 "M      c #104010401040",
4305 "N      c #492438E34103",
4306 "B      c #28A2208128A2",
4307 "V      c #A699596538E3",
4308 "C      c #30C21C711040",
4309 "Z      c #30C218611040",
4310 "A      c #965865955965",
4311 "S      c #618534D32081",
4312 "D      c #38E31C711040",
4313 "F      c #082000000820",
4314 "                                                ",
4315 "          .XoO                                  ",
4316 "         +@#$%o&amp;                                ",
4317 "         *=-;#::o+                              ",
4318 "           >,<12#:34                            ",
4319 "             45671#:X3                          ",
4320 "               +89<02qwo                        ",
4321 "e*                >,67;ro                       ",
4322 "ty>                 459@>+&amp;&amp;                    ",
4323 "$2u+                  ><ipas8*                  ",
4324 "%$;=*                *3:.Xa.dfg>                ",
4325 "Oh$;ya             *3d.a8j,Xe.d3g8+             ",
4326 " Oh$;ka          *3d$a8lz,,xxc:.e3g54           ",
4327 "  Oh$;kO       *pd$%svbzz,sxxxxfX..&amp;wn>         ",
4328 "   Oh$@mO    *3dthwlsslszjzxxxxxxx3:td8M4       ",
4329 "    Oh$@g&amp; *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B*     ",
4330 "     Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5&amp;   ",
4331 "      Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM*  ",
4332 "       OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
4333 "        2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
4334 "        :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
4335 "         +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
4336 "          *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&amp;en",
4337 "           p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
4338 "           OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
4339 "            3206Bwxxszx%et.eaAp77m77mmmf3&amp;eeeg* ",
4340 "             @26MvzxNzvlbwfpdettttttttttt.c,n&amp;  ",
4341 "             *;16=lsNwwNwgsvslbwwvccc3pcfu<o    ",
4342 "              p;<69BvwwsszslllbBlllllllu<5+     ",
4343 "              OS0y6FBlvvvzvzss,u=Blllj=54       ",
4344 "               c1-699Blvlllllu7k96MMMg4         ",
4345 "               *10y8n6FjvllllB<166668           ",
4346 "                S-kg+>666<M<996-y6n<8*          ",
4347 "                p71=4 m69996kD8Z-66698&amp;&amp;        ",
4348 "                &amp;i0ycm6n4 ogk17,0<6666g         ",
4349 "                 N-k-<>     >=01-kuu666>        ",
4350 "                 ,6ky&amp;      &amp;46-10ul,66,        ",
4351 "                 Ou0<>       o66y<ulw<66&amp;       ",
4352 "                  *kk5       >66By7=xu664       ",
4353 "                   <<M4      466lj<Mxu66o       ",
4354 "                   *>>       +66uv,zN666*       ",
4355 "                              566,xxj669        ",
4356 "                              4666FF666>        ",
4357 "                               >966666M         ",
4358 "                                oM6668+         ",
4359 "                                  *4            ",
4360 "                                                ",
4361 "                                                "};
4362
4363
4364 /* When invoked (via signal delete_event), terminates the application */
4365 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4366     gtk_main_quit();
4367 }
4368
4369 int main (int argc, char *argv[])
4370 {
4371     /* GtkWidget is the storage type for widgets */
4372     GtkWidget *window, *pixmap, *fixed;
4373     GdkPixmap *gdk_pixmap;
4374     GdkBitmap *mask;
4375     GtkStyle *style;
4376     GdkGC *gc;
4377     
4378     /* Create the main window, and attach delete_event signal to terminate
4379      * the application.  Note that the main window will not have a titlebar
4380      * since we're making it a popup. */
4381     gtk_init (&amp;argc, &amp;argv);
4382     window = gtk_window_new( GTK_WINDOW_POPUP );
4383     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4384                         GTK_SIGNAL_FUNC (close_application), NULL);
4385     gtk_widget_show (window);
4386
4387     /* Now for the pixmap and the pixmap widget */
4388     style = gtk_widget_get_default_style();
4389     gc = style->black_gc;
4390     gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &amp;mask,
4391                                              &amp;style->bg[GTK_STATE_NORMAL],
4392                                              WheelbarrowFull_xpm );
4393     pixmap = gtk_pixmap_new( gdk_pixmap, mask );
4394     gtk_widget_show( pixmap );
4395
4396     /* To display the pixmap, we use a fixed widget to place the pixmap */
4397     fixed = gtk_fixed_new();
4398     gtk_widget_set_usize( fixed, 200, 200 );
4399     gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
4400     gtk_container_add( GTK_CONTAINER(window), fixed );
4401     gtk_widget_show( fixed );
4402
4403     /* This masks out everything except for the image itself */
4404     gtk_widget_shape_combine_mask( window, mask, 0, 0 );
4405     
4406     /* show the window */
4407     gtk_widget_set_uposition( window, 20, 400 );
4408     gtk_widget_show( window );
4409     gtk_main ();
4410           
4411     return(0);
4412 }
4413 /* example-end */
4414 </verb></tscreen>
4415
4416 To make the wheelbarrow image sensitive, we could attach the button
4417 press event signal to make it do something. The following few lines
4418 would make the picture sensitive to a mouse button being pressed which
4419 makes the application terminate.
4420
4421 <tscreen><verb>
4422     gtk_widget_set_events( window,
4423                           gtk_widget_get_events( window ) |
4424                           GDK_BUTTON_PRESS_MASK );
4425
4426    gtk_signal_connect( GTK_OBJECT(window), "button_press_event",
4427                        GTK_SIGNAL_FUNC(close_application), NULL );
4428 </verb></tscreen>
4429
4430 <!-- ----------------------------------------------------------------- -->
4431 <sect1>Rulers
4432 <p>
4433 Ruler widgets are used to indicate the location of the mouse pointer
4434 in a given window. A window can have a vertical ruler spanning across
4435 the width and a horizontal ruler spanning down the height. A small
4436 triangular indicator on the ruler shows the exact location of the
4437 pointer relative to the ruler.
4438
4439 A ruler must first be created. Horizontal and vertical rulers are
4440 created using
4441
4442 <tscreen><verb>
4443 GtkWidget *gtk_hruler_new( void );    /* horizontal ruler */
4444
4445 GtkWidget *gtk_vruler_new( void );    /* vertical ruler   */
4446 </verb></tscreen>
4447
4448 Once a ruler is created, we can define the unit of measurement. Units
4449 of measure for rulers can be<tt/GTK_PIXELS/, <tt/GTK_INCHES/ or
4450 <tt/GTK_CENTIMETERS/. This is set using
4451
4452 <tscreen><verb>
4453 void gtk_ruler_set_metric( GtkRuler      *ruler,
4454                            GtkMetricType  metric );
4455 </verb></tscreen>
4456
4457 The default measure is <tt/GTK_PIXELS/.
4458
4459 <tscreen><verb>
4460     gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
4461 </verb></tscreen>
4462
4463 Other important characteristics of a ruler are how to mark the units
4464 of scale and where the position indicator is initially placed. These
4465 are set for a ruler using
4466
4467 <tscreen><verb>
4468 void gtk_ruler_set_range( GtkRuler *ruler,
4469                           gfloat    lower,
4470                           gfloat    upper,
4471                           gfloat    position,
4472                           gfloat    max_size );
4473 </verb></tscreen>
4474
4475 The lower and upper arguments define the extent of the ruler, and
4476 max_size is the largest possible number that will be displayed.
4477 Position defines the initial position of the pointer indicator within
4478 the ruler.
4479
4480 A vertical ruler can span an 800 pixel wide window thus
4481
4482 <tscreen><verb>
4483     gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
4484 </verb></tscreen>
4485
4486 The markings displayed on the ruler will be from 0 to 800, with a
4487 number for every 100 pixels. If instead we wanted the ruler to range
4488 from 7 to 16, we would code
4489
4490 <tscreen><verb>
4491     gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
4492 </verb></tscreen>
4493
4494 The indicator on the ruler is a small triangular mark that indicates
4495 the position of the pointer relative to the ruler. If the ruler is
4496 used to follow the mouse pointer, the motion_notify_event signal
4497 should be connected to the motion_notify_event method of the ruler.
4498 To follow all mouse movements within a window area, we would use
4499
4500 <tscreen><verb>
4501 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4502
4503     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4504            (GtkSignalFunc)EVENT_METHOD(ruler, motion_notify_event),
4505            GTK_OBJECT(ruler) );
4506 </verb></tscreen>
4507
4508 The following example creates a drawing area with a horizontal ruler
4509 above it and a vertical ruler to the left of it. The size of the
4510 drawing area is 600 pixels wide by 400 pixels high. The horizontal
4511 ruler spans from 7 to 13 with a mark every 100 pixels, while the
4512 vertical ruler spans from 0 to 400 with a mark every 100 pixels.
4513 Placement of the drawing area and the rulers is done using a table.
4514
4515 <tscreen><verb>
4516 /* example-start rulers rulers.c */
4517
4518 #include <gtk/gtk.h>
4519
4520 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4521
4522 #define XSIZE  600
4523 #define YSIZE  400
4524
4525 /* This routine gets control when the close button is clicked */
4526 void close_application( GtkWidget *widget, GdkEvent *event, gpointer data ) {
4527     gtk_main_quit();
4528 }
4529
4530 /* The main routine */
4531 int main( int argc, char *argv[] ) {
4532     GtkWidget *window, *table, *area, *hrule, *vrule;
4533
4534     /* Initialize GTK and create the main window */
4535     gtk_init( &amp;argc, &amp;argv );
4536
4537     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4538     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4539             GTK_SIGNAL_FUNC( close_application ), NULL);
4540     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
4541
4542     /* Create a table for placing the ruler and the drawing area */
4543     table = gtk_table_new( 3, 2, FALSE );
4544     gtk_container_add( GTK_CONTAINER(window), table );
4545
4546     area = gtk_drawing_area_new();
4547     gtk_drawing_area_size( (GtkDrawingArea *)area, XSIZE, YSIZE );
4548     gtk_table_attach( GTK_TABLE(table), area, 1, 2, 1, 2,
4549                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0 );
4550     gtk_widget_set_events( area, GDK_POINTER_MOTION_MASK |
4551                                  GDK_POINTER_MOTION_HINT_MASK );
4552
4553     /* The horizontal ruler goes on top. As the mouse moves across the
4554      * drawing area, a motion_notify_event is passed to the
4555      * appropriate event handler for the ruler. */
4556     hrule = gtk_hruler_new();
4557     gtk_ruler_set_metric( GTK_RULER(hrule), GTK_PIXELS );
4558     gtk_ruler_set_range( GTK_RULER(hrule), 7, 13, 0, 20 );
4559     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4560                                (GtkSignalFunc)EVENT_METHOD(hrule,
4561                                                         motion_notify_event),
4562                                GTK_OBJECT(hrule) );
4563     /*  GTK_WIDGET_CLASS(GTK_OBJECT(hrule)->klass)->motion_notify_event, */
4564     gtk_table_attach( GTK_TABLE(table), hrule, 1, 2, 0, 1,
4565                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0 );
4566     
4567     /* The vertical ruler goes on the left. As the mouse moves across
4568      * the drawing area, a motion_notify_event is passed to the
4569      * appropriate event handler for the ruler. */
4570     vrule = gtk_vruler_new();
4571     gtk_ruler_set_metric( GTK_RULER(vrule), GTK_PIXELS );
4572     gtk_ruler_set_range( GTK_RULER(vrule), 0, YSIZE, 10, YSIZE );
4573     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4574                                (GtkSignalFunc)
4575                                   GTK_WIDGET_CLASS(GTK_OBJECT(vrule)->klass)->
4576                                                          motion_notify_event,
4577                                GTK_OBJECT(vrule) );
4578     gtk_table_attach( GTK_TABLE(table), vrule, 0, 1, 1, 2,
4579                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );
4580
4581     /* Now show everything */
4582     gtk_widget_show( area );
4583     gtk_widget_show( hrule );
4584     gtk_widget_show( vrule );
4585     gtk_widget_show( table );
4586     gtk_widget_show( window );
4587     gtk_main();
4588
4589     return(0);
4590 }
4591 /* example-end */
4592 </verb></tscreen>
4593
4594 <!-- ----------------------------------------------------------------- -->
4595 <sect1>Statusbars
4596 <p>
4597 Statusbars are simple widgets used to display a text message. They
4598 keep a stack of the messages pushed onto them, so that popping the
4599 current message will re-display the previous text message.
4600
4601 In order to allow different parts of an application to use the same
4602 statusbar to display messages, the statusbar widget issues Context
4603 Identifiers which are used to identify different "users". The message
4604 on top of the stack is the one displayed, no matter what context it is
4605 in. Messages are stacked in last-in-first-out order, not context
4606 identifier order.
4607
4608 A statusbar is created with a call to:
4609
4610 <tscreen><verb>
4611 GtkWidget *gtk_statusbar_new( void );
4612 </verb></tscreen>
4613
4614 A new Context Identifier is requested using a call to the following 
4615 function with a short textual description of the context:
4616
4617 <tscreen><verb>
4618 guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
4619                                     const gchar  *context_description );
4620 </verb></tscreen>
4621
4622 There are three functions that can operate on statusbars:
4623
4624 <tscreen><verb>
4625 guint gtk_statusbar_push( GtkStatusbar *statusbar,
4626                           guint         context_id,
4627                           gchar        *text );
4628
4629 void gtk_statusbar_pop( GtkStatusbar *statusbar)
4630                         guint         context_id );
4631
4632 void gtk_statusbar_remove( GtkStatusbar *statusbar,
4633                            guint         context_id,
4634                            guint         message_id ); 
4635 </verb></tscreen>
4636
4637 The first, gtk_statusbar_push, is used to add a new message to the
4638 statusbar.  It returns a Message Identifier, which can be passed later
4639 to the function gtk_statusbar_remove to remove the message with the
4640 given Message and Context Identifiers from the statusbar's stack.
4641
4642 The function gtk_statusbar_pop removes the message highest in the
4643 stack with the given Context Identifier.
4644
4645 The following example creates a statusbar and two buttons, one for
4646 pushing items onto the statusbar, and one for popping the last item
4647 back off.
4648
4649 <tscreen><verb>
4650 /* example-start statusbar statusbar.c */
4651
4652 #include <gtk/gtk.h>
4653 #include <glib.h>
4654
4655 GtkWidget *status_bar;
4656
4657 void push_item (GtkWidget *widget, gpointer data)
4658 {
4659   static int count = 1;
4660   char buff[20];
4661
4662   g_snprintf(buff, 20, "Item %d", count++);
4663   gtk_statusbar_push( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data), buff);
4664
4665   return;
4666 }
4667
4668 void pop_item (GtkWidget *widget, gpointer data)
4669 {
4670   gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) );
4671   return;
4672 }
4673
4674 int main (int argc, char *argv[])
4675 {
4676
4677     GtkWidget *window;
4678     GtkWidget *vbox;
4679     GtkWidget *button;
4680
4681     gint context_id;
4682
4683     gtk_init (&amp;argc, &amp;argv);
4684
4685     /* create a new window */
4686     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4687     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4688     gtk_window_set_title(GTK_WINDOW (window), "GTK Statusbar Example");
4689     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4690                        (GtkSignalFunc) gtk_exit, NULL);
4691  
4692     vbox = gtk_vbox_new(FALSE, 1);
4693     gtk_container_add(GTK_CONTAINER(window), vbox);
4694     gtk_widget_show(vbox);
4695           
4696     status_bar = gtk_statusbar_new();      
4697     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
4698     gtk_widget_show (status_bar);
4699
4700     context_id = gtk_statusbar_get_context_id(
4701                           GTK_STATUSBAR(status_bar), "Statusbar example");
4702
4703     button = gtk_button_new_with_label("push item");
4704     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4705         GTK_SIGNAL_FUNC (push_item), GINT_TO_POINTER(context_id) );
4706     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4707     gtk_widget_show(button);              
4708
4709     button = gtk_button_new_with_label("pop last item");
4710     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4711         GTK_SIGNAL_FUNC (pop_item), GINT_TO_POINTER(context_id) );
4712     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4713     gtk_widget_show(button);              
4714
4715     /* always display the window as the last step so it all splashes on
4716      * the screen at once. */
4717     gtk_widget_show(window);
4718
4719     gtk_main ();
4720
4721     return 0;
4722 }
4723 /* example-end */
4724 </verb></tscreen>
4725
4726 <!-- ----------------------------------------------------------------- -->
4727 <sect1>Text Entries
4728 <p>
4729 The Entry widget allows text to be typed and displayed in a single line
4730 text box. The text may be set with function calls that allow new text
4731 to replace, prepend or append the current contents of the Entry widget.
4732
4733 There are two functions for creating Entry widgets:
4734
4735 <tscreen><verb>
4736 GtkWidget *gtk_entry_new( void );
4737
4738 GtkWidget *gtk_entry_new_with_max_length( guint16 max );
4739 </verb></tscreen>
4740
4741 The first just creates a new Entry widget, whilst the second creates a
4742 new Entry and sets a limit on the length of the text within the Entry.
4743
4744 There are several functions for altering the text which is currently
4745 within the Entry widget.
4746
4747 <tscreen><verb>
4748 void gtk_entry_set_text( GtkEntry    *entry,
4749                          const gchar *text );
4750
4751 void gtk_entry_append_text( GtkEntry    *entry,
4752                             const gchar *text );
4753
4754 void gtk_entry_prepend_text( GtkEntry    *entry,
4755                              const gchar *text );
4756 </verb></tscreen>
4757
4758 The function gtk_entry_set_text sets the contents of the Entry widget,
4759 replacing the current contents. The functions gtk_entry_append_text
4760 and gtk_entry_prepend_text allow the current contents to be appended
4761 and prepended to.
4762
4763 The next function allows the current insertion point to be set.
4764
4765 <tscreen><verb>
4766 void gtk_entry_set_position( GtkEntry *entry,
4767                              gint      position );
4768 </verb></tscreen>
4769
4770 The contents of the Entry can be retrieved by using a call to the
4771 following function. This is useful in the callback functions described below.
4772
4773 <tscreen><verb>
4774 gchar *gtk_entry_get_text( GtkEntry *entry );
4775 </verb></tscreen>
4776
4777 The value returned by this function is used internally, and must not
4778 be freed using either free() or g_free()
4779
4780 If we don't want the contents of the Entry to be changed by someone typing
4781 into it, we can change its editable state.
4782
4783 <tscreen><verb>
4784 void gtk_entry_set_editable( GtkEntry *entry,
4785                              gboolean  editable );
4786 </verb></tscreen>
4787
4788 The function above allows us to toggle the editable state of the
4789 Entry widget by passing in a TRUE or FALSE value for the <tt/editable/
4790 argument.
4791
4792 If we are using the Entry where we don't want the text entered to be
4793 visible, for example when a password is being entered, we can use the
4794 following function, which also takes a boolean flag.
4795
4796 <tscreen><verb>
4797 void gtk_entry_set_visibility( GtkEntry *entry,
4798                                gboolean  visible );
4799 </verb></tscreen>
4800
4801 A region of the text may be set as selected by using the following
4802 function. This would most often be used after setting some default
4803 text in an Entry, making it easy for the user to remove it.
4804
4805 <tscreen><verb>
4806 void gtk_entry_select_region( GtkEntry *entry,
4807                               gint      start,
4808                               gint      end );
4809 </verb></tscreen>
4810
4811 If we want to catch when the user has entered text, we can connect to
4812 the <tt/activate/ or <tt/changed/ signal. Activate is raised when the
4813 user hits the enter key within the Entry widget. Changed is raised
4814 when the text changes at all, e.g., for every character entered or
4815 removed.
4816
4817 The following code is an example of using an Entry widget.
4818
4819 <tscreen><verb>
4820 /* example-start entry entry.c */
4821
4822 #include <gtk/gtk.h>
4823
4824 void enter_callback(GtkWidget *widget, GtkWidget *entry)
4825 {
4826   gchar *entry_text;
4827   entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
4828   printf("Entry contents: %s\n", entry_text);
4829 }
4830
4831 void entry_toggle_editable (GtkWidget *checkbutton,
4832                                    GtkWidget *entry)
4833 {
4834   gtk_entry_set_editable(GTK_ENTRY(entry),
4835                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4836 }
4837
4838 void entry_toggle_visibility (GtkWidget *checkbutton,
4839                                    GtkWidget *entry)
4840 {
4841   gtk_entry_set_visibility(GTK_ENTRY(entry),
4842                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4843 }
4844
4845 int main (int argc, char *argv[])
4846 {
4847
4848     GtkWidget *window;
4849     GtkWidget *vbox, *hbox;
4850     GtkWidget *entry;
4851     GtkWidget *button;
4852     GtkWidget *check;
4853
4854     gtk_init (&amp;argc, &amp;argv);
4855
4856     /* create a new window */
4857     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4858     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4859     gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
4860     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4861                        (GtkSignalFunc) gtk_exit, NULL);
4862
4863     vbox = gtk_vbox_new (FALSE, 0);
4864     gtk_container_add (GTK_CONTAINER (window), vbox);
4865     gtk_widget_show (vbox);
4866
4867     entry = gtk_entry_new_with_max_length (50);
4868     gtk_signal_connect(GTK_OBJECT(entry), "activate",
4869                        GTK_SIGNAL_FUNC(enter_callback),
4870                        entry);
4871     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
4872     gtk_entry_append_text (GTK_ENTRY (entry), " world");
4873     gtk_entry_select_region (GTK_ENTRY (entry),
4874                              0, GTK_ENTRY(entry)->text_length);
4875     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4876     gtk_widget_show (entry);
4877
4878     hbox = gtk_hbox_new (FALSE, 0);
4879     gtk_container_add (GTK_CONTAINER (vbox), hbox);
4880     gtk_widget_show (hbox);
4881                                   
4882     check = gtk_check_button_new_with_label("Editable");
4883     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4884     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4885                         GTK_SIGNAL_FUNC(entry_toggle_editable), entry);
4886     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4887     gtk_widget_show (check);
4888     
4889     check = gtk_check_button_new_with_label("Visible");
4890     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4891     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4892                         GTK_SIGNAL_FUNC(entry_toggle_visibility), entry);
4893     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4894     gtk_widget_show (check);
4895                                    
4896     button = gtk_button_new_with_label ("Close");
4897     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4898                                GTK_SIGNAL_FUNC(gtk_exit),
4899                                GTK_OBJECT (window));
4900     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4901     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4902     gtk_widget_grab_default (button);
4903     gtk_widget_show (button);
4904     
4905     gtk_widget_show(window);
4906
4907     gtk_main();
4908     return(0);
4909 }
4910 /* example-end */
4911 </verb></tscreen>
4912
4913 <!-- ----------------------------------------------------------------- -->
4914 <sect1>Spin Buttons
4915 <p>
4916 The Spin Button widget is generally used to allow the user to select a
4917 value from a range of numeric values. It consists of a text
4918 entry box with up and down arrow buttons attached to the
4919 side. Selecting one of the buttons causes the value to "spin" up and
4920 down the range of possible values. The entry box may also be edited
4921 directly to enter a specific value.
4922
4923 The Spin Button allows the value to have zero or a number of decimal
4924 places and to be incremented/decremented in configurable steps. The
4925 action of holding down one of the buttons optionally results in an
4926 acceleration of change in the value according to how long it is
4927 depressed.
4928
4929 The Spin Button uses an <ref id="sec_Adjustment" name="Adjustment">
4930 object to hold information about the range of values that the spin
4931 button can take. This makes for a powerful Spin Button widget.
4932
4933 Recall that an adjustment widget is created with the following
4934 function, which illustrates the information that it holds:
4935
4936 <tscreen><verb>
4937 GtkObject *gtk_adjustment_new( gfloat value,
4938                                gfloat lower,
4939                                gfloat upper,
4940                                gfloat step_increment,
4941                                gfloat page_increment,
4942                                gfloat page_size );
4943 </verb></tscreen>
4944
4945 These attributes of an Adjustment are used by the Spin Button in the
4946 following way:
4947
4948 <itemize>
4949 <item> <tt/value/: initial value for the Spin Button
4950 <item> <tt/lower/: lower range value
4951 <item> <tt/upper/: upper range value
4952 <item> <tt/step_increment/: value to increment/decrement when pressing
4953 mouse button 1 on a button
4954 <item> <tt/page_increment/: value to increment/decrement when pressing
4955 mouse button 2 on a button
4956 <item> <tt/page_size/: unused
4957 </itemize>
4958
4959 Additionally, mouse button 3 can be used to jump directly to the
4960 <tt/upper/ or <tt/lower/ values when used to select one of the
4961 buttons. Lets look at how to create a Spin Button:
4962
4963 <tscreen><verb>
4964 GtkWidget *gtk_spin_button_new( GtkAdjustment *adjustment,
4965                                 gfloat         climb_rate,
4966                                 guint          digits );
4967 </verb></tscreen>
4968
4969 The <tt/climb_rate/ argument take a value between 0.0 and 1.0 and
4970 indicates the amount of acceleration that the Spin Button has. The
4971 <tt/digits/ argument specifies the number of decimal places to which
4972 the value will be displayed.
4973
4974 A Spin Button can be reconfigured after creation using the following
4975 function:
4976
4977 <tscreen><verb>
4978 void gtk_spin_button_configure( GtkSpinButton *spin_button,
4979                                 GtkAdjustment *adjustment,
4980                                 gfloat         climb_rate,
4981                                 guint          digits );
4982 </verb></tscreen>
4983
4984 The <tt/spin_button/ argument specifies the Spin Button widget that is
4985 to be reconfigured. The other arguments are as specified above.
4986
4987 The adjustment can be set and retrieved independantly using the
4988 following two functions:
4989
4990 <tscreen><verb>
4991 void gtk_spin_button_set_adjustment( GtkSpinButton  *spin_button,
4992                                      GtkAdjustment  *adjustment );
4993
4994 GtkAdjustment *gtk_spin_button_get_adjustment( GtkSpinButton *spin_button );
4995 </verb></tscreen>
4996
4997 The number of decimal places can also be altered using:
4998
4999 <tscreen><verb>
5000 void gtk_spin_button_set_digits( GtkSpinButton *spin_button,
5001                                  guint          digits) ;
5002 </verb></tscreen>
5003
5004 The value that a Spin Button is currently displaying can be changed
5005 using the following function:
5006
5007 <tscreen><verb>
5008 void gtk_spin_button_set_value( GtkSpinButton *spin_button,
5009                                 gfloat         value );
5010 </verb></tscreen>
5011
5012 The current value of a Spin Button can be retrieved as either a
5013 floating point or integer value with the following functions:
5014
5015 <tscreen><verb>
5016 gfloat gtk_spin_button_get_value_as_float( GtkSpinButton *spin_button );
5017
5018 gint gtk_spin_button_get_value_as_int( GtkSpinButton *spin_button );
5019 </verb></tscreen>
5020
5021 If you want to alter the value of a Spin Value relative to its current
5022 value, then the following function can be used:
5023
5024 <tscreen><verb>
5025 void gtk_spin_button_spin( GtkSpinButton *spin_button,
5026                            GtkSpinType    direction,
5027                            gfloat         increment );
5028 </verb></tscreen>
5029
5030 The <tt/direction/ parameter can take one of the following values:
5031
5032 <tscreen><verb>
5033   GTK_SPIN_STEP_FORWARD
5034   GTK_SPIN_STEP_BACKWARD
5035   GTK_SPIN_PAGE_FORWARD
5036   GTK_SPIN_PAGE_BACKWARD
5037   GTK_SPIN_HOME
5038   GTK_SPIN_END
5039   GTK_SPIN_USER_DEFINED
5040 </verb></tscreen>
5041
5042 This function packs in quite a bit of functionality, which I will
5043 attempt to clearly explain. Many of these settings use values from the
5044 Adjustment object that is associated with a Spin Button.
5045
5046 <tt/GTK_SPIN_STEP_FORWARD/ and <tt/GTK_SPIN_STEP_BACKWARD/ change the
5047 value of the Spin Button by the amount specified by <tt/increment/,
5048 unless <tt/increment/ is equal to 0, in which case the value is
5049 changed by the value of <tt/step_increment/ in theAdjustment.
5050
5051 <tt/GTK_SPIN_PAGE_FORWARD/ and <tt/GTK_SPIN_PAGE_BACKWARD/ simply
5052 alter the value of the Spin Button by <tt/increment/.
5053
5054 <tt/GTK_SPIN_HOME/ sets the value of the Spin Button to the bottom of
5055 the Adjustments range.
5056
5057 <tt/GTK_SPIN_END/ sets the value of the Spin Button to the top of the
5058 Adjustments range.
5059
5060 <tt/GTK_SPIN_USER_DEFINED/ simply alters the value of the Spin Button
5061 by the specified amount.
5062
5063 We move away from functions for setting and retreving the range attributes
5064 of the Spin Button now, and move onto functions that effect the
5065 appearance and behaviour of the Spin Button widget itself.
5066
5067 The first of these functions is used to constrain the text box of the
5068 Spin Button such that it may only contain a numeric value. This
5069 prevents a user from typing anything other than numeric values into
5070 the text box of a Spin Button:
5071
5072 <tscreen><verb>
5073 void gtk_spin_button_set_numeric( GtkSpinButton *spin_button,
5074                                   gboolean       numeric );
5075 </verb></tscreen>
5076
5077 You can set whether a Spin Button will wrap around between the upper
5078 and lower range values with the following function:
5079
5080 <tscreen><verb>
5081 void gtk_spin_button_set_wrap( GtkSpinButton *spin_button,
5082                                gboolean       wrap );
5083 </verb></tscreen>
5084
5085 You can set a Spin Button to round the value to the nearest
5086 <tt/step_increment/, which is set within the Adjustment object used
5087 with the Spin Button. This is accomplished with the following
5088 function:
5089
5090 <tscreen><verb>
5091 void gtk_spin_button_set_snap_to_ticks( GtkSpinButton  *spin_button,
5092                                         gboolean        snap_to_ticks );
5093 </verb></tscreen>
5094
5095 The update policy of a Spin Button can be changed with the following
5096 function:
5097
5098 <tscreen><verb>
5099 void gtk_spin_button_set_update_policy( GtkSpinButton  *spin_button,
5100                                     GtkSpinButtonUpdatePolicy policy );
5101 </verb></tscreen>
5102
5103 <!-- TODO: find out what this does - TRG -->
5104
5105 The possible values of <tt/policy/ are either <tt/GTK_UPDATE_ALWAYS/ or
5106 <tt/GTK_UPDATE_IF_VALID/.
5107  
5108
5109 These policies affect the behavior of a Spin Button when parsing
5110 inserted text and syncing its value with the values of the
5111 Adjustment.
5112
5113 In the case of <tt/GTK_UPDATE_IF_VALID/ the Spin Button only value
5114 gets changed if the text input is a numeric value that is within the
5115 range specified by the Adjustment. Otherwise the text is reset to the
5116 current value.
5117
5118 In case of <tt/GTK_UPDATE_ALWAYS/ we ignore errors while converting
5119 text into a numeric value.
5120
5121 The appearance of the buttons used in a Spin Button can be changed
5122 using the following function:
5123
5124 <tscreen><verb>
5125 void gtk_spin_button_set_shadow_type( GtkSpinButton *spin_button,
5126                                       GtkShadowType  shadow_type );
5127 </verb></tscreen>
5128
5129 As usual, the <tt/shadow_type/ can be one of:
5130
5131 <tscreen><verb>
5132   GTK_SHADOW_IN
5133   GTK_SHADOW_OUT
5134   GTK_SHADOW_ETCHED_IN
5135   GTK_SHADOW_ETCHED_OUT
5136 </verb></tscreen>
5137
5138 Finally, you can explicitly request that a Spin Button update itself:
5139
5140 <tscreen><verb>
5141 void gtk_spin_button_update( GtkSpinButton  *spin_button );
5142 </verb></tscreen>
5143
5144 It's example time again.
5145
5146 <tscreen><verb>
5147 /* example-start spinbutton spinbutton.c */
5148
5149 #include <gtk/gtk.h>
5150
5151 static GtkWidget *spinner1;
5152
5153 void toggle_snap( GtkWidget     *widget,
5154                   GtkSpinButton *spin )
5155 {
5156   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active);
5157 }
5158
5159 void toggle_numeric( GtkWidget *widget,
5160                      GtkSpinButton *spin )
5161 {
5162   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active);
5163 }
5164
5165 void change_digits( GtkWidget *widget,
5166                     GtkSpinButton *spin )
5167 {
5168   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
5169                               gtk_spin_button_get_value_as_int (spin));
5170 }
5171
5172 void get_value( GtkWidget *widget,
5173                 gpointer data )
5174 {
5175   gchar buf[32];
5176   GtkLabel *label;
5177   GtkSpinButton *spin;
5178
5179   spin = GTK_SPIN_BUTTON (spinner1);
5180   label = GTK_LABEL (gtk_object_get_user_data (GTK_OBJECT (widget)));
5181   if (GPOINTER_TO_INT (data) == 1)
5182     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
5183   else
5184     sprintf (buf, "%0.*f", spin->digits,
5185              gtk_spin_button_get_value_as_float (spin));
5186   gtk_label_set_text (label, buf);
5187 }
5188
5189
5190 int main( int   argc,
5191           char *argv[] )
5192 {
5193   GtkWidget *window;
5194   GtkWidget *frame;
5195   GtkWidget *hbox;
5196   GtkWidget *main_vbox;
5197   GtkWidget *vbox;
5198   GtkWidget *vbox2;
5199   GtkWidget *spinner2;
5200   GtkWidget *spinner;
5201   GtkWidget *button;
5202   GtkWidget *label;
5203   GtkWidget *val_label;
5204   GtkAdjustment *adj;
5205
5206   /* Initialise GTK */
5207   gtk_init(&amp;argc, &amp;argv);
5208
5209   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5210
5211   gtk_signal_connect (GTK_OBJECT (window), "destroy",
5212                       GTK_SIGNAL_FUNC (gtk_main_quit),
5213                       NULL);
5214
5215   gtk_window_set_title (GTK_WINDOW (window), "Spin Button");
5216
5217   main_vbox = gtk_vbox_new (FALSE, 5);
5218   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5219   gtk_container_add (GTK_CONTAINER (window), main_vbox);
5220   
5221   frame = gtk_frame_new ("Not accelerated");
5222   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5223   
5224   vbox = gtk_vbox_new (FALSE, 0);
5225   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5226   gtk_container_add (GTK_CONTAINER (frame), vbox);
5227   
5228   /* Day, month, year spinners */
5229   
5230   hbox = gtk_hbox_new (FALSE, 0);
5231   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5232   
5233   vbox2 = gtk_vbox_new (FALSE, 0);
5234   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5235   
5236   label = gtk_label_new ("Day :");
5237   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5238   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5239   
5240   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 31.0, 1.0,
5241                                               5.0, 0.0);
5242   spinner = gtk_spin_button_new (adj, 0, 0);
5243   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5244   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5245                                    GTK_SHADOW_OUT);
5246   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5247   
5248   vbox2 = gtk_vbox_new (FALSE, 0);
5249   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5250   
5251   label = gtk_label_new ("Month :");
5252   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5253   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5254   
5255   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5256                                               5.0, 0.0);
5257   spinner = gtk_spin_button_new (adj, 0, 0);
5258   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5259   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5260                                    GTK_SHADOW_ETCHED_IN);
5261   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5262   
5263   vbox2 = gtk_vbox_new (FALSE, 0);
5264   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5265   
5266   label = gtk_label_new ("Year :");
5267   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5268   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5269   
5270   adj = (GtkAdjustment *) gtk_adjustment_new (1998.0, 0.0, 2100.0,
5271                                               1.0, 100.0, 0.0);
5272   spinner = gtk_spin_button_new (adj, 0, 0);
5273   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), FALSE);
5274   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5275                                    GTK_SHADOW_IN);
5276   gtk_widget_set_usize (spinner, 55, 0);
5277   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5278   
5279   frame = gtk_frame_new ("Accelerated");
5280   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5281   
5282   vbox = gtk_vbox_new (FALSE, 0);
5283   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5284   gtk_container_add (GTK_CONTAINER (frame), vbox);
5285   
5286   hbox = gtk_hbox_new (FALSE, 0);
5287   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5288   
5289   vbox2 = gtk_vbox_new (FALSE, 0);
5290   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5291   
5292   label = gtk_label_new ("Value :");
5293   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5294   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5295   
5296   adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
5297                                               0.5, 100.0, 0.0);
5298   spinner1 = gtk_spin_button_new (adj, 1.0, 2);
5299   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
5300   gtk_widget_set_usize (spinner1, 100, 0);
5301   gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
5302   
5303   vbox2 = gtk_vbox_new (FALSE, 0);
5304   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5305   
5306   label = gtk_label_new ("Digits :");
5307   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5308   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5309   
5310   adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 5, 1, 1, 0);
5311   spinner2 = gtk_spin_button_new (adj, 0.0, 0);
5312   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner2), TRUE);
5313   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
5314                       GTK_SIGNAL_FUNC (change_digits),
5315                       (gpointer) spinner2);
5316   gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
5317   
5318   hbox = gtk_hbox_new (FALSE, 0);
5319   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5320   
5321   button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
5322   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5323                       GTK_SIGNAL_FUNC (toggle_snap),
5324                       spinner1);
5325   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5326   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5327   
5328   button = gtk_check_button_new_with_label ("Numeric only input mode");
5329   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5330                       GTK_SIGNAL_FUNC (toggle_numeric),
5331                       spinner1);
5332   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5333   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5334   
5335   val_label = gtk_label_new ("");
5336   
5337   hbox = gtk_hbox_new (FALSE, 0);
5338   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5339   button = gtk_button_new_with_label ("Value as Int");
5340   gtk_object_set_user_data (GTK_OBJECT (button), val_label);
5341   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5342                       GTK_SIGNAL_FUNC (get_value),
5343                       GINT_TO_POINTER (1));
5344   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5345   
5346   button = gtk_button_new_with_label ("Value as Float");
5347   gtk_object_set_user_data (GTK_OBJECT (button), val_label);
5348   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5349                       GTK_SIGNAL_FUNC (get_value),
5350                       GINT_TO_POINTER (2));
5351   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5352   
5353   gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
5354   gtk_label_set_text (GTK_LABEL (val_label), "0");
5355   
5356   hbox = gtk_hbox_new (FALSE, 0);
5357   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5358   
5359   button = gtk_button_new_with_label ("Close");
5360   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
5361                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
5362                              GTK_OBJECT (window));
5363   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5364
5365   gtk_widget_show_all (window);
5366
5367   /* Enter the event loop */
5368   gtk_main ();
5369     
5370   return(0);
5371 }
5372 /* example-end */
5373 </verb></tscreen>
5374
5375 <!-- ----------------------------------------------------------------- -->
5376 <sect1>Combo Box
5377 <p>
5378 The combo box is another fairly simple widget that is really just a
5379 collection of other widgets. From the user's point of view, the widget
5380 consists of a text entry box and a pull down menu from which the user
5381 can select one of a set of predefined entries. Alternatively, the user
5382 can type a different option directly into the text box.
5383
5384 The following extract from the structure that defines a Combo Box
5385 identifies several of the components:
5386
5387 <tscreen><verb>
5388 struct _GtkCombo { 
5389         GtkHBox hbox; 
5390         GtkWidget *entry; 
5391         GtkWidget *button;
5392         GtkWidget *popup; 
5393         GtkWidget *popwin; 
5394         GtkWidget *list;
5395         ...  };
5396 </verb></tscreen>
5397
5398 As you can see, the Combo Box has two principal parts that you really
5399 care about: an entry and a list.
5400
5401 First off, to create a combo box, use:
5402
5403 <tscreen><verb>
5404 GtkWidget *gtk_combo_new( void );
5405 </verb></tscreen>
5406
5407 Now, if you want to set the string in the entry section of the combo
5408 box, this is done by manipulating the <tt/entry/ widget directly:
5409
5410 <tscreen><verb>
5411     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), "My String.");
5412 </verb></tscreen>
5413
5414 To set the values in the popdown list, one uses the function:
5415
5416 <tscreen><verb>
5417 void gtk_combo_set_popdown_strings( GtkCombo *combo,
5418                                     GList    *strings );
5419 </verb></tscreen>
5420
5421 Before you can do this, you have to assemble a GList of the strings
5422 that you want. GList is a linked list implementation that is part of
5423 <ref id="sec_glib" name="GLib">, a library supporing GTK. For the
5424 moment, the quick and dirty explanation is that you need to set up a
5425 GList pointer, set it equal to NULL, then append strings to it with
5426
5427 <tscreen><verb>
5428 GList *g_list_append( GList *glist, 
5429                       gpointer data );
5430 </verb></tscreen>
5431
5432 It is important that you set the initial GList pointer to NULL. The
5433 value returned from the g_list_append function must be used as the new
5434 pointer to the GList.
5435
5436 Here's a typical code segment for creating a set of options:
5437
5438 <tscreen><verb>
5439     GList *glist=NULL;
5440
5441     glist = g_list_append(glist, "String 1");
5442     glist = g_list_append(glist, "String 2");
5443     glist = g_list_append(glist, "String 3"); 
5444     glist = g_list_append(glist, "String 4");
5445
5446     gtk_combo_set_popdown_strings( GTK_COMBO(combo), glist) ;
5447 </verb></tscreen>
5448
5449 At this point you have a working combo box that has been set up.
5450 There are a few aspects of its behavior that you can change. These
5451 are accomplished with the functions: 
5452
5453 <tscreen><verb>
5454 void gtk_combo_set_use_arrows( GtkCombo *combo,
5455                                gint      val );
5456
5457 void gtk_combo_set_use_arrows_always( GtkCombo *combo,
5458                                       gint      val );
5459
5460 void gtk_combo_set_case_sensitive( GtkCombo *combo,
5461                                    gint      val );
5462 </verb></tscreen>
5463
5464 <tt/gtk_combo_set_use_arrows()/ lets the user change the value in the
5465 entry using the up/down arrow keys. This doesn't bring up the list, but
5466 rather replaces the current text in the entry with the next list entry
5467 (up or down, as your key choice indicates). It does this by searching
5468 in the list for the item corresponding to the current value in the
5469 entry and selecting the previous/next item accordingly. Usually in an
5470 entry the arrow keys are used to change focus (you can do that anyway
5471 using TAB). Note that when the current item is the last of the list
5472 and you press arrow-down it changes the focus (the same applies with
5473 the first item and arrow-up).
5474
5475 If the current value in the entry is not in the list, then the
5476 function of <tt/gtk_combo_set_use_arrows()/ is disabled.
5477
5478 <tt/gtk_combo_set_use_arrows_always()/ similarly allows the use the
5479 the up/down arrow keys to cycle through the choices in the dropdown
5480 list, except that it wraps around the values in the list, completely
5481 disabling the use of the up and down arrow keys for changing focus.
5482
5483 <tt/gtk_combo_set_case_sensitive()/ toggles whether or not GTK
5484 searches for entries in a case sensitive manner. This is used when the
5485 Combo widget is asked to find a value from the list using the current
5486 entry in the text box. This completion can be performed in either a
5487 case sensitive or insensitive manner, depending upon the use of this
5488 function. The Combo widget can also simply complete the current entry
5489 if the user presses the key combination MOD-1 and "Tab". MOD-1 is
5490 often mapped to the "Alt" key, by the <tt/xmodmap/ utility. Note,
5491 however that some window managers also use this key combination, which
5492 will override its use within GTK.
5493
5494 Now that we have a combo box, tailored to look and act how we want it,
5495 all that remains is being able to get data from the combo box. This is
5496 relatively straightforward. The majority of the time, all you are
5497 going to care about getting data from is the entry. The entry is
5498 accessed simply by <tt>GTK_ENTRY(GTK_COMBO(combo)->entry)</tt>. The
5499 two principal things that you are going to want to do with it are
5500 attach to the activate signal, which indicates that the user has
5501 pressed the Return or Enter key, and read the text. The first is
5502 accomplished using something like:
5503
5504 <tscreen><verb>
5505     gtk_signal_connect(GTK_OBJECT(GTK_COMB(combo)->entry), "activate",
5506                        GTK_SIGNAL_FUNC (my_callback_function), my_data);
5507 </verb></tscreen>
5508
5509 Getting the text at any arbitrary time is accomplished by simply using
5510 the entry function:
5511
5512 <tscreen><verb>
5513 gchar *gtk_entry_get_text(GtkEntry *entry);
5514 </verb></tscreen>
5515
5516 Such as:
5517
5518 <tscreen><verb>
5519     char *string;
5520
5521     string = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry));
5522 </verb></tscreen>
5523
5524 That's about all there is to it. There is a function
5525
5526 <tscreen><verb>
5527 void gtk_combo_disable_activate(GtkCombo *combo);
5528 </verb></tscreen>
5529
5530 that will disable the activate signal on the entry widget in the combo
5531 box. Personally, I can't think of why you'd want to use it, but it
5532 does exist.
5533
5534 <!-- There is also a function to set the string on a particular item, void
5535 gtk_combo_set_item_string(GtkCombo *combo, GtkItem *item, const gchar
5536 *item_value), but this requires that you have a pointer to the
5537 appropriate Item. Frankly, I have no idea how to do that.
5538 -->
5539
5540 <!-- ----------------------------------------------------------------- -->
5541 <sect1> Color Selection
5542 <p>
5543 The color selection widget is, not surprisingly, a widget for
5544 interactive selection of colors. This composite widget lets the user
5545 select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
5546 Saturation, Value) triples.  This is done either by adjusting single
5547 values with sliders or entries, or by picking the desired color from a
5548 hue-saturation wheel/value bar.  Optionally, the opacity of the color
5549 can also be set.
5550
5551 The color selection widget currently emits only one signal,
5552 "color_changed", which is emitted whenever the current color in the
5553 widget changes, either when the user changes it or if it's set
5554 explicitly through gtk_color_selection_set_color().
5555
5556 Lets have a look at what the color selection widget has to offer
5557 us. The widget comes in two flavours: gtk_color_selection and
5558 gtk_color_selection_dialog.
5559
5560 <tscreen><verb>
5561 GtkWidget *gtk_color_selection_new( void );
5562 </verb></tscreen>
5563         
5564 You'll probably not be using this constructor directly. It creates an
5565 orphan ColorSelection widget which you'll have to parent
5566 yourself. The ColorSelection widget inherits from the VBox
5567 widget.
5568
5569 <tscreen><verb> 
5570 GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
5571 </verb></tscreen>
5572
5573 This is the most common color selection constructor. It creates a
5574 ColorSelectionDialog. It consists of a Frame containing a
5575 ColorSelection widget, an HSeparator and an HBox with three buttons,
5576 "Ok", "Cancel" and "Help". You can reach these buttons by accessing
5577 the "ok_button", "cancel_button" and "help_button" widgets in the
5578 ColorSelectionDialog structure,
5579 (i.e., <tt>GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button</tt>)).
5580
5581 <tscreen><verb>
5582 void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel, 
5583                                             GtkUpdateType      policy );
5584 </verb></tscreen>
5585
5586 This function sets the update policy. The default policy is
5587 <tt/GTK_UPDATE_CONTINUOUS/ which means that the current color is
5588 updated continuously when the user drags the sliders or presses the
5589 mouse and drags in the hue-saturation wheel or value bar. If you
5590 experience performance problems, you may want to set the policy to
5591 <tt/GTK_UPDATE_DISCONTINUOUS/ or <tt/GTK_UPDATE_DELAYED/.
5592
5593 <tscreen><verb>
5594 void gtk_color_selection_set_opacity( GtkColorSelection *colorsel,
5595                                       gint               use_opacity );
5596 </verb></tscreen>
5597
5598 The color selection widget supports adjusting the opacity of a color
5599 (also known as the alpha channel). This is disabled by
5600 default. Calling this function with use_opacity set to TRUE enables
5601 opacity. Likewise, use_opacity set to FALSE will disable opacity.
5602
5603 <tscreen><verb>
5604 void gtk_color_selection_set_color( GtkColorSelection *colorsel,
5605                                     gdouble           *color );
5606 </verb></tscreen>
5607
5608 You can set the current color explicitly by calling this function with
5609 a pointer to an array of colors (gdouble). The length of the array
5610 depends on whether opacity is enabled or not. Position 0 contains the
5611 red component, 1 is green, 2 is blue and opacity is at position 3
5612 (only if opacity is enabled, see
5613 gtk_color_selection_set_opacity()). All values are between 0.0 and
5614 1.0.
5615
5616 <tscreen><verb>
5617 void gtk_color_selection_get_color( GtkColorSelection *colorsel,
5618                                     gdouble           *color );
5619 </verb></tscreen>
5620
5621 When you need to query the current color, typically when you've
5622 received a "color_changed" signal, you use this function. Color is a
5623 pointer to the array of colors to fill in. See the
5624 gtk_color_selection_set_color() function for the description of this
5625 array.
5626
5627 <!-- Need to do a whole section on DnD - TRG
5628 Drag and drop
5629 -------------
5630
5631 The color sample areas (right under the hue-saturation wheel) supports
5632 drag and drop. The type of drag and drop is "application/x-color". The
5633 message data consists of an array of 4 (or 5 if opacity is enabled)
5634 gdouble values, where the value at position 0 is 0.0 (opacity on) or
5635 1.0 (opacity off) followed by the red, green and blue values at
5636 positions 1,2 and 3 respectively.  If opacity is enabled, the opacity
5637 is passed in the value at position 4.
5638 -->
5639
5640 Here's a simple example demonstrating the use of the
5641 ColorSelectionDialog. The program displays a window containing a
5642 drawing area. Clicking on it opens a color selection dialog, and
5643 changing the color in the color selection dialog changes the
5644 background color.
5645
5646 <tscreen><verb>
5647 /* example-start colorsel colorsel.c */
5648
5649 #include <glib.h>
5650 #include <gdk/gdk.h>
5651 #include <gtk/gtk.h>
5652
5653 GtkWidget *colorseldlg = NULL;
5654 GtkWidget *drawingarea = NULL;
5655
5656 /* Color changed handler */
5657
5658 void color_changed_cb (GtkWidget *widget, GtkColorSelection *colorsel)
5659 {
5660   gdouble color[3];
5661   GdkColor gdk_color;
5662   GdkColormap *colormap;
5663
5664   /* Get drawingarea colormap */
5665
5666   colormap = gdk_window_get_colormap (drawingarea->window);
5667
5668   /* Get current color */
5669
5670   gtk_color_selection_get_color (colorsel,color);
5671
5672   /* Fit to a unsigned 16 bit integer (0..65535) and
5673    * insert into the GdkColor structure */
5674
5675   gdk_color.red = (guint16)(color[0]*65535.0);
5676   gdk_color.green = (guint16)(color[1]*65535.0);
5677   gdk_color.blue = (guint16)(color[2]*65535.0);
5678
5679   /* Allocate color */
5680
5681   gdk_color_alloc (colormap, &amp;gdk_color);
5682
5683   /* Set window background color */
5684
5685   gdk_window_set_background (drawingarea->window, &amp;gdk_color);
5686
5687   /* Clear window */
5688
5689   gdk_window_clear (drawingarea->window);
5690 }
5691
5692 /* Drawingarea event handler */
5693
5694 gint area_event (GtkWidget *widget, GdkEvent *event, gpointer client_data)
5695 {
5696   gint handled = FALSE;
5697   GtkWidget *colorsel;
5698
5699   /* Check if we've received a button pressed event */
5700
5701   if (event->type == GDK_BUTTON_PRESS &amp;&amp; colorseldlg == NULL)
5702     {
5703       /* Yes, we have an event and there's no colorseldlg yet! */
5704
5705       handled = TRUE;
5706
5707       /* Create color selection dialog */
5708
5709       colorseldlg = gtk_color_selection_dialog_new("Select background color");
5710
5711       /* Get the ColorSelection widget */
5712
5713       colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;
5714
5715       /* Connect to the "color_changed" signal, set the client-data
5716        * to the colorsel widget */
5717
5718       gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed",
5719         (GtkSignalFunc)color_changed_cb, (gpointer)colorsel);
5720
5721       /* Show the dialog */
5722
5723       gtk_widget_show(colorseldlg);
5724     }
5725
5726   return handled;
5727 }
5728
5729 /* Close down and exit handler */
5730
5731 void destroy_window (GtkWidget *widget, gpointer client_data)
5732 {
5733   gtk_main_quit ();
5734 }
5735
5736 /* Main */
5737
5738 gint main (gint argc, gchar *argv[])
5739 {
5740   GtkWidget *window;
5741
5742   /* Initialize the toolkit, remove gtk-related commandline stuff */
5743
5744   gtk_init (&amp;argc,&amp;argv);
5745
5746   /* Create toplevel window, set title and policies */
5747
5748   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5749   gtk_window_set_title (GTK_WINDOW(window), "Color selection test");
5750   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, TRUE);
5751
5752   /* Attach to the "delete" and "destroy" events so we can exit */
5753
5754   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
5755     (GtkSignalFunc)destroy_window, (gpointer)window);
5756
5757   gtk_signal_connect (GTK_OBJECT(window), "destroy",
5758     (GtkSignalFunc)destroy_window, (gpointer)window);
5759   
5760   /* Create drawingarea, set size and catch button events */
5761
5762   drawingarea = gtk_drawing_area_new ();
5763
5764   gtk_drawing_area_size (GTK_DRAWING_AREA(drawingarea), 200, 200);
5765
5766   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
5767
5768   gtk_signal_connect (GTK_OBJECT(drawingarea), "event", 
5769     (GtkSignalFunc)area_event, (gpointer)drawingarea);
5770   
5771   /* Add drawingarea to window, then show them both */
5772
5773   gtk_container_add (GTK_CONTAINER(window), drawingarea);
5774
5775   gtk_widget_show (drawingarea);
5776   gtk_widget_show (window);
5777   
5778   /* Enter the gtk main loop (this never returns) */
5779
5780   gtk_main ();
5781
5782   /* Satisfy grumpy compilers */
5783
5784   return(0);
5785 }
5786 /* example-end */
5787 </verb></tscreen>
5788
5789 <!-- ----------------------------------------------------------------- -->
5790 <sect1> File Selections
5791 <p>
5792 The file selection widget is a quick and simple way to display a File
5793 dialog box. It comes complete with Ok, Cancel, and Help buttons, a
5794 great way to cut down on programming time.
5795
5796 To create a new file selection box use:
5797
5798 <tscreen><verb>
5799 GtkWidget *gtk_file_selection_new( gchar *title );
5800 </verb></tscreen>
5801
5802 To set the filename, for example to bring up a specific directory, or
5803 give a default filename, use this function:
5804
5805 <tscreen><verb>
5806 void gtk_file_selection_set_filename( GtkFileSelection *filesel,
5807                                       gchar            *filename );
5808 </verb></tscreen>
5809
5810 To grab the text that the user has entered or clicked on, use this 
5811 function:
5812
5813 <tscreen><verb>
5814 gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel );
5815 </verb></tscreen>
5816
5817 There are also pointers to the widgets contained within the file 
5818 selection widget. These are:
5819
5820 <tscreen><verb>
5821   dir_list
5822   file_list
5823   selection_entry
5824   selection_text
5825   main_vbox
5826   ok_button
5827   cancel_button
5828   help_button
5829 </verb></tscreen>
5830  
5831 Most likely you will want to use the ok_button, cancel_button, and
5832 help_button pointers in signaling their use.
5833
5834 Included here is an example stolen from testgtk.c, modified to run on
5835 its own. As you will see, there is nothing much to creating a file
5836 selection widget. While in this example the Help button appears on the
5837 screen, it does nothing as there is not a signal attached to it.
5838
5839 <tscreen><verb>
5840 /* example-start filesel filesel.c */
5841
5842 #include <gtk/gtk.h>
5843
5844 /* Get the selected filename and print it to the console */
5845 void file_ok_sel (GtkWidget *w, GtkFileSelection *fs)
5846 {
5847     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
5848 }
5849
5850 void destroy (GtkWidget *widget, gpointer data)
5851 {
5852     gtk_main_quit ();
5853 }
5854
5855 int main (int argc, char *argv[])
5856 {
5857     GtkWidget *filew;
5858     
5859     gtk_init (&amp;argc, &amp;argv);
5860     
5861     /* Create a new file selection widget */
5862     filew = gtk_file_selection_new ("File selection");
5863     
5864     gtk_signal_connect (GTK_OBJECT (filew), "destroy",
5865                         (GtkSignalFunc) destroy, &amp;filew);
5866     /* Connect the ok_button to file_ok_sel function */
5867     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
5868                         "clicked", (GtkSignalFunc) file_ok_sel, filew );
5869     
5870     /* Connect the cancel_button to destroy the widget */
5871     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
5872                                             (filew)->cancel_button),
5873                                "clicked", (GtkSignalFunc) gtk_widget_destroy,
5874                                GTK_OBJECT (filew));
5875     
5876     /* Lets set the filename, as if this were a save dialog, and we are giving
5877      a default filename */
5878     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
5879                                      "penguin.png");
5880     
5881     gtk_widget_show(filew);
5882     gtk_main ();
5883     return 0;
5884 }
5885 /* example-end */
5886 </verb></tscreen>
5887
5888 <!-- ***************************************************************** -->
5889 <sect> Container Widgets
5890 <!-- ***************************************************************** -->
5891
5892 <!-- ----------------------------------------------------------------- -->   
5893 <sect1>The EventBox <label id="sec_EventBox">
5894 <p> 
5895 Some GTK widgets don't have associated X windows, so they just draw on
5896 their parents. Because of this, they cannot receive events and if they
5897 are incorrectly sized, they don't clip so you can get messy
5898 overwriting, etc. If you require more from these widgets, the EventBox
5899 is for you.
5900
5901 At first glance, the EventBox widget might appear to be totally
5902 useless. It draws nothing on the screen and responds to no
5903 events. However, it does serve a function - it provides an X window
5904 for its child widget. This is important as many GTK widgets do not
5905 have an associated X window. Not having an X window saves memory and
5906 improves performance, but also has some drawbacks. A widget without an
5907 X window cannot receive events, and does not perform any clipping on
5908 its contents. Although the name <em/EventBox/ emphasizes the
5909 event-handling function, the widget can also be used for clipping.
5910 (and more, see the example below).
5911
5912 To create a new EventBox widget, use:
5913
5914 <tscreen><verb>
5915 GtkWidget *gtk_event_box_new( void );
5916 </verb></tscreen>
5917
5918 A child widget can then be added to this EventBox:
5919
5920 <tscreen><verb>
5921     gtk_container_add( GTK_CONTAINER(event_box), child_widget );
5922 </verb></tscreen>
5923
5924 The following example demonstrates both uses of an EventBox - a label
5925 is created that is clipped to a small box, and set up so that a
5926 mouse-click on the label causes the program to exit. Resizing the
5927 window reveals varying amounts of the label.
5928
5929 <tscreen><verb>
5930 /* example-start eventbox eventbox.c */
5931
5932 #include <gtk/gtk.h>
5933
5934 int 
5935 main (int argc, char *argv[])
5936 {
5937     GtkWidget *window;
5938     GtkWidget *event_box;
5939     GtkWidget *label;
5940     
5941     gtk_init (&amp;argc, &amp;argv);
5942     
5943     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5944     
5945     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
5946     
5947     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5948                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
5949     
5950     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5951     
5952     /* Create an EventBox and add it to our toplevel window */
5953     
5954     event_box = gtk_event_box_new ();
5955     gtk_container_add (GTK_CONTAINER(window), event_box);
5956     gtk_widget_show (event_box);
5957     
5958     /* Create a long label */
5959     
5960     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
5961     gtk_container_add (GTK_CONTAINER (event_box), label);
5962     gtk_widget_show (label);
5963     
5964     /* Clip it short. */
5965     gtk_widget_set_usize (label, 110, 20);
5966     
5967     /* And bind an action to it */
5968     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
5969     gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
5970                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
5971     
5972     /* Yet one more thing you need an X window for ... */
5973     
5974     gtk_widget_realize (event_box);
5975     gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
5976     
5977     gtk_widget_show (window);
5978     
5979     gtk_main ();
5980     
5981     return(0);
5982 }
5983 /* example-end */
5984 </verb></tscreen>
5985
5986 <!-- ----------------------------------------------------------------- -->   
5987 <sect1>The Alignment widget <label id="sec_Alignment">
5988 <p>
5989 The alignment widget allows you to place a widget within its window at
5990 a position and size relative to the size of the Alignment widget
5991 itself. For example, it can be very useful for centering a widget
5992 within the window.
5993
5994 There are only two functions associated with the Alignment widget:
5995
5996 <tscreen><verb>
5997 GtkWidget* gtk_alignment_new( gfloat xalign,
5998                               gfloat yalign,
5999                               gfloat xscale,
6000                               gfloat yscale );
6001
6002 void gtk_alignment_set( GtkAlignment *alignment,
6003                         gfloat        xalign,
6004                         gfloat        yalign,
6005                         gfloat        xscale,
6006                         gfloat        yscale );
6007 </verb></tscreen>
6008
6009 The first function creates a new Alignment widget with the specified
6010 parameters. The second function allows the alignment paramters of an
6011 exisiting Alignment widget to be altered.
6012
6013 All four alignment parameters are floating point numbers which can
6014 range from 0.0 to 1.0. The <tt/xalign/ and <tt/yalign/ arguments
6015 affect the position of the widget placed within the Alignment
6016 widget. The <tt/xscale/ and <tt/yscale/ arguments effect the amount of
6017 space allocated to the widget.
6018
6019 A child widget can be added to this Alignment widget using:
6020
6021 <tscreen><verb>
6022     gtk_container_add( GTK_CONTAINER(alignment), child_widget );
6023 </verb></tscreen>
6024
6025 For an example of using an Alignment widget, refer to the example for
6026 the <ref id="sec_ProgressBar" name="Progress Bar"> widget.
6027
6028 <!-- ----------------------------------------------------------------- -->
6029 <sect1> Fixed Container
6030 <p>
6031 The Fixed container allows you to place widgets at a fixed position
6032 within it's window, relative to it's upper left hand corner. The
6033 position of the widgets can be changed dynamically.
6034
6035 There are only three functions associated with the fixed widget:
6036
6037 <tscreen><verb>
6038 GtkWidget* gtk_fixed_new( void );
6039
6040 void gtk_fixed_put( GtkFixed  *fixed,
6041                     GtkWidget *widget,
6042                     gint16     x,
6043                     gint16     y );
6044
6045 void gtk_fixed_move( GtkFixed  *fixed,
6046                      GtkWidget *widget,
6047                      gint16     x,
6048                      gint16     y );
6049 </verb></tscreen>
6050
6051 The function <tt/gtk_fixed_new/ allows you to create a new Fixed
6052 container.
6053
6054 <tt/gtk_fixed_put/ places <tt/widget/ in the container <tt/fixed/ at
6055 the position specified by <tt/x/ and <tt/y/.
6056
6057 <tt/gtk_fixed_move/ allows the specified widget to be moved to a new
6058 position.
6059
6060 The following example illustrates how to use the Fixed Container.
6061
6062 <tscreen><verb>
6063 /* example-start fixed fixed.c */
6064
6065 #include <gtk/gtk.h>
6066
6067 /* I'm going to be lazy and use some global variables to
6068  * store the position of the widget within the fixed
6069  * container */
6070 gint x=50;
6071 gint y=50;
6072
6073 /* This callback function moves the button to a new position
6074  * in the Fixed container. */
6075 void move_button( GtkWidget *widget,
6076                   GtkWidget *fixed )
6077 {
6078   x = (x+30)%300;
6079   y = (y+50)%300;
6080   gtk_fixed_move( GTK_FIXED(fixed), widget, x, y); 
6081 }
6082
6083 int main( int   argc,
6084           char *argv[] )
6085 {
6086   /* GtkWidget is the storage type for widgets */
6087   GtkWidget *window;
6088   GtkWidget *fixed;
6089   GtkWidget *button;
6090   gint i;
6091
6092   /* Initialise GTK */
6093   gtk_init(&amp;argc, &amp;argv);
6094     
6095   /* Create a new window */
6096   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6097   gtk_window_set_title(GTK_WINDOW(window), "Fixed Container");
6098
6099   /* Here we connect the "destroy" event to a signal handler */ 
6100   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6101                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6102  
6103   /* Sets the border width of the window. */
6104   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6105
6106   /* Create a Fixed Container */
6107   fixed = gtk_fixed_new();
6108   gtk_container_add(GTK_CONTAINER(window), fixed);
6109   gtk_widget_show(fixed);
6110   
6111   for (i = 1 ; i <= 3 ; i++) {
6112     /* Creates a new button with the label "Press me" */
6113     button = gtk_button_new_with_label ("Press me");
6114   
6115     /* When the button receives the "clicked" signal, it will call the
6116      * function move_button() passing it the Fixed Container as its
6117      * argument. */
6118     gtk_signal_connect (GTK_OBJECT (button), "clicked",
6119                         GTK_SIGNAL_FUNC (move_button), fixed);
6120   
6121     /* This packs the button into the fixed containers window. */
6122     gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
6123   
6124     /* The final step is to display this newly created widget. */
6125     gtk_widget_show (button);
6126   }
6127
6128   /* Display the window */
6129   gtk_widget_show (window);
6130     
6131   /* Enter the event loop */
6132   gtk_main ();
6133     
6134   return(0);
6135 }
6136 /* example-end */
6137 </verb></tscreen>
6138
6139 <!-- ----------------------------------------------------------------- -->
6140 <sect1> Layout Container
6141 <p>
6142 The Layout container is similar to the Fixed container except that it
6143 implements an infinite (where infinity is less than 2^32) scrolling
6144 area. The X window system has a limitation where windows can be at
6145 most 32767 pixels wide or tall. The Layout container gets around this
6146 limitation by doing some exotic stuff using window and bit gravities,
6147 so that you can have smooth scrolling even when you have many child
6148 widgets in your scrolling area.
6149
6150 A Layout container is created using:
6151
6152 <tscreen><verb>
6153 GtkWidget *gtk_layout_new( GtkAdjustment *hadjustment,
6154                            GtkAdjustment *vadjustment );
6155 </verb></tscreen>
6156
6157 As you can see, you can optionally specify the Adjustment objects that
6158 the Layout widget will use for its scrolling.
6159
6160 You can add and move widgets in the Layout container using the
6161 following two functions:
6162
6163 <tscreen><verb>
6164 void gtk_layout_put( GtkLayout *layout,
6165                      GtkWidget *widget,
6166                      gint       x,
6167                      gint       y );
6168
6169 void gtk_layout_move( GtkLayout *layout,
6170                       GtkWidget *widget,
6171                       gint       x,
6172                       gint       y );
6173 </verb></tscreen>
6174
6175 The size of the Layout container can be set using the next function:
6176
6177 <tscreen><verb>
6178 void gtk_layout_set_size( GtkLayout *layout,
6179                           guint      width,
6180                           guint      height );
6181 </verb></tscreen>
6182
6183 Layout containers are one of the very few widgets in the GTK widget
6184 set that actively repaint themselves on screen as they are changed
6185 using the above functions (the vast majority of widgets queue
6186 requests which are then processed when control returns to the
6187 <tt/gtk_main()/ function).
6188
6189 When you want to make a large number of changes to a Layout container,
6190 you can use the following two functions to disable and re-enable this
6191 repainting functionality:
6192
6193 <tscreen><verb>
6194 void gtk_layout_freeze( GtkLayout *layout );
6195
6196 void gtk_layout_thaw( GtkLayout *layout );
6197 </verb></tscreen>
6198
6199 The final four functions for use with Layout widgets are for
6200 manipulating the horizontal and vertical adjustment widgets:
6201
6202 <tscreen><verb>
6203 GtkAdjustment* gtk_layout_get_hadjustment( GtkLayout *layout );
6204
6205 GtkAdjustment* gtk_layout_get_vadjustment( GtkLayout *layout );
6206
6207 void gtk_layout_set_hadjustment( GtkLayout     *layout,
6208                                  GtkAdjustment *adjustment );
6209
6210 void gtk_layout_set_vadjustment( GtkLayout     *layout,
6211                                  GtkAdjustment *adjustment);
6212 </verb></tscreen>
6213
6214 <!-- ----------------------------------------------------------------- -->
6215 <sect1> Frames <label id="sec_Frames">
6216 <p>
6217 Frames can be used to enclose one or a group of widgets with a box
6218 which can optionally be labelled. The position of the label and the
6219 style of the box can be altered to suit.
6220
6221 A Frame can be created with the following function:
6222
6223 <tscreen><verb>
6224 GtkWidget *gtk_frame_new( const gchar *label );
6225 </verb></tscreen>
6226
6227 The label is by default placed in the upper left hand corner of the
6228 frame. A value of NULL for the <tt/label/ argument will result in no
6229 label being displayed. The text of the label can be changed using the
6230 next function.
6231
6232 <tscreen><verb>
6233 void gtk_frame_set_label( GtkFrame    *frame,
6234                           const gchar *label );
6235 </verb></tscreen>
6236
6237 The position of the label can be changed using this function:
6238
6239 <tscreen><verb>
6240 void gtk_frame_set_label_align( GtkFrame *frame,
6241                                 gfloat    xalign,
6242                                 gfloat    yalign );
6243 </verb></tscreen>
6244
6245 <tt/xalign/ and <tt/yalign/ take values between 0.0 and 1.0. <tt/xalign/
6246 indicates the position of the label along the top horizontal of the
6247 frame. <tt/yalign/ is not currently used. The default value of xalign
6248 is 0.0 which places the label at the left hand end of the frame.
6249
6250 The next function alters the style of the box that is used to outline
6251 the frame.
6252
6253 <tscreen><verb>
6254 void gtk_frame_set_shadow_type( GtkFrame      *frame,
6255                                 GtkShadowType  type);
6256 </verb></tscreen>
6257
6258 The <tt/type/ argument can take one of the following values:
6259 <tscreen><verb>
6260   GTK_SHADOW_NONE
6261   GTK_SHADOW_IN
6262   GTK_SHADOW_OUT
6263   GTK_SHADOW_ETCHED_IN (the default)
6264   GTK_SHADOW_ETCHED_OUT
6265 </verb></tscreen>
6266
6267 The following code example illustrates the use of the Frame widget.
6268
6269 <tscreen><verb>
6270 /* example-start frame frame.c */
6271
6272 #include <gtk/gtk.h>
6273
6274 int main( int   argc,
6275           char *argv[] )
6276 {
6277   /* GtkWidget is the storage type for widgets */
6278   GtkWidget *window;
6279   GtkWidget *frame;
6280   GtkWidget *button;
6281   gint i;
6282
6283   /* Initialise GTK */
6284   gtk_init(&amp;argc, &amp;argv);
6285     
6286   /* Create a new window */
6287   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6288   gtk_window_set_title(GTK_WINDOW(window), "Frame Example");
6289
6290   /* Here we connect the "destroy" event to a signal handler */ 
6291   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6292                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6293
6294   gtk_widget_set_usize(window, 300, 300);
6295   /* Sets the border width of the window. */
6296   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6297
6298   /* Create a Frame */
6299   frame = gtk_frame_new(NULL);
6300   gtk_container_add(GTK_CONTAINER(window), frame);
6301
6302   /* Set the frame's label */
6303   gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" );
6304
6305   /* Align the label at the right of the frame */
6306   gtk_frame_set_label_align( GTK_FRAME(frame), 1.0, 0.0);
6307
6308   /* Set the style of the frame */
6309   gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
6310
6311   gtk_widget_show(frame);
6312   
6313   /* Display the window */
6314   gtk_widget_show (window);
6315     
6316   /* Enter the event loop */
6317   gtk_main ();
6318     
6319   return(0);
6320 }
6321 /* example-end */
6322
6323 </verb></tscreen>
6324
6325 <!-- ----------------------------------------------------------------- -->   
6326 <sect1> Aspect Frames
6327 <p>
6328 The aspect frame widget is like a frame widget, except that it also
6329 enforces the aspect ratio (that is, the ratio of the width to the
6330 height) of the child widget to have a certain value, adding extra
6331 space if necessary. This is useful, for instance, if you want to
6332 preview a larger image. The size of the preview should vary when the
6333 user resizes the window, but the aspect ratio needs to always match
6334 the original image.
6335   
6336 To create a new aspect frame use:
6337    
6338 <tscreen><verb>
6339 GtkWidget *gtk_aspect_frame_new( const gchar *label,
6340                                  gfloat       xalign,
6341                                  gfloat       yalign,
6342                                  gfloat       ratio,
6343                                  gint         obey_child);
6344 </verb></tscreen>
6345    
6346 <tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
6347 widgets. If <tt/obey_child/ is true, the aspect ratio of a child
6348 widget will match the aspect ratio of the ideal size it requests.
6349 Otherwise, it is given by <tt/ratio/.
6350    
6351 To change the options of an existing aspect frame, you can use:
6352    
6353 <tscreen><verb>
6354 void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
6355                            gfloat          xalign,
6356                            gfloat          yalign,
6357                            gfloat          ratio,
6358                            gint            obey_child);
6359 </verb></tscreen>
6360    
6361 As an example, the following program uses an AspectFrame to present a
6362 drawing area whose aspect ratio will always be 2:1, no matter how the
6363 user resizes the top-level window.
6364    
6365 <tscreen><verb>
6366 /* example-start aspectframe aspectframe.c */
6367
6368 #include <gtk/gtk.h>
6369    
6370 int
6371 main (int argc, char *argv[])
6372 {
6373     GtkWidget *window;
6374     GtkWidget *aspect_frame;
6375     GtkWidget *drawing_area;
6376     gtk_init (&amp;argc, &amp;argv);
6377    
6378     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6379     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
6380     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6381                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6382     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6383    
6384     /* Create an aspect_frame and add it to our toplevel window */
6385    
6386     aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
6387                                          0.5, /* center x */
6388                                          0.5, /* center y */
6389                                          2, /* xsize/ysize = 2 */
6390                                          FALSE /* ignore child's aspect */);
6391    
6392     gtk_container_add (GTK_CONTAINER(window), aspect_frame);
6393     gtk_widget_show (aspect_frame);
6394    
6395     /* Now add a child widget to the aspect frame */
6396    
6397     drawing_area = gtk_drawing_area_new ();
6398    
6399     /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
6400      * window since we are forcing a 2x1 aspect ratio */
6401     gtk_widget_set_usize (drawing_area, 200, 200);
6402     gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
6403     gtk_widget_show (drawing_area);
6404    
6405     gtk_widget_show (window);
6406     gtk_main ();
6407     return 0;
6408 }
6409 /* example-end */
6410 </verb></tscreen>
6411
6412 <!-- ----------------------------------------------------------------- -->   
6413 <sect1> Paned Window Widgets
6414 <p>
6415 The paned window widgets are useful when you want to divide an area
6416 into two parts, with the relative size of the two parts controlled by
6417 the user. A groove is drawn between the two portions with a handle
6418 that the user can drag to change the ratio. The division can either be
6419 horizontal (HPaned) or vertical (VPaned).
6420    
6421 To create a new paned window, call one of:
6422    
6423 <tscreen><verb>
6424 GtkWidget *gtk_hpaned_new (void);
6425
6426 GtkWidget *gtk_vpaned_new (void);
6427 </verb></tscreen>
6428
6429 After creating the paned window widget, you need to add child widgets
6430 to its two halves. To do this, use the functions:
6431    
6432 <tscreen><verb>
6433 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
6434
6435 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
6436 </verb></tscreen>
6437    
6438 <tt/gtk_paned_add1()/ adds the child widget to the left or top half of
6439 the paned window. <tt/gtk_paned_add2()/ adds the child widget to the
6440 right or bottom half of the paned window.
6441
6442 A paned widget can be changed visually using the following two
6443 functions.
6444
6445 <tscreen><verb>
6446 void gtk_paned_set_handle_size( GtkPaned *paned,
6447                                 guint16   size);
6448
6449 void gtk_paned_set_gutter_size( GtkPaned *paned,
6450                                 guint16   size);
6451 </verb></tscreen>
6452
6453 The first of these sets the size of the handle and the second sets the
6454 size of the gutter that is between the two parts of the paned window.
6455
6456 As an example, we will create part of the user interface of an
6457 imaginary email program. A window is divided into two portions
6458 vertically, with the top portion being a list of email messages and
6459 the bottom portion the text of the email message. Most of the program
6460 is pretty straightforward. A couple of points to note: text can't be
6461 added to a Text widget until it is realized. This could be done by
6462 calling <tt/gtk_widget_realize()/, but as a demonstration of an
6463 alternate technique, we connect a handler to the "realize" signal to
6464 add the text. Also, we need to add the <tt/GTK_SHRINK/ option to some
6465 of the items in the table containing the text window and its
6466 scrollbars, so that when the bottom portion is made smaller, the
6467 correct portions shrink instead of being pushed off the bottom of the
6468 window.
6469
6470 <tscreen><verb>
6471 /* example-start paned paned.c */
6472
6473 #include <gtk/gtk.h>
6474    
6475 /* Create the list of "messages" */
6476 GtkWidget *
6477 create_list (void)
6478 {
6479
6480     GtkWidget *scrolled_window;
6481     GtkWidget *list;
6482     GtkWidget *list_item;
6483    
6484     int i;
6485     char buffer[16];
6486    
6487     /* Create a new scrolled window, with scrollbars only if needed */
6488     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6489     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6490                                     GTK_POLICY_AUTOMATIC, 
6491                                     GTK_POLICY_AUTOMATIC);
6492    
6493     /* Create a new list and put it in the scrolled window */
6494     list = gtk_list_new ();
6495     gtk_scrolled_window_add_with_viewport (
6496                GTK_SCROLLED_WINDOW (scrolled_window), list);
6497     gtk_widget_show (list);
6498    
6499     /* Add some messages to the window */
6500     for (i=0; i<10; i++) {
6501
6502         sprintf(buffer,"Message #%d",i);
6503         list_item = gtk_list_item_new_with_label (buffer);
6504         gtk_container_add (GTK_CONTAINER(list), list_item);
6505         gtk_widget_show (list_item);
6506
6507     }
6508    
6509     return scrolled_window;
6510 }
6511    
6512 /* Add some text to our text widget - this is a callback that is invoked
6513 when our window is realized. We could also force our window to be
6514 realized with gtk_widget_realize, but it would have to be part of
6515 a hierarchy first */
6516
6517 void
6518 realize_text (GtkWidget *text, gpointer data)
6519 {
6520     gtk_text_freeze (GTK_TEXT (text));
6521     gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
6522     "From: pathfinder@nasa.gov\n"
6523     "To: mom@nasa.gov\n"
6524     "Subject: Made it!\n"
6525     "\n"
6526     "We just got in this morning. The weather has been\n"
6527     "great - clear but cold, and there are lots of fun sights.\n"
6528     "Sojourner says hi. See you soon.\n"
6529     " -Path\n", -1);
6530    
6531     gtk_text_thaw (GTK_TEXT (text));
6532 }
6533    
6534 /* Create a scrolled text area that displays a "message" */
6535 GtkWidget *
6536 create_text (void)
6537 {
6538     GtkWidget *table;
6539     GtkWidget *text;
6540     GtkWidget *hscrollbar;
6541     GtkWidget *vscrollbar;
6542    
6543     /* Create a table to hold the text widget and scrollbars */
6544     table = gtk_table_new (2, 2, FALSE);
6545    
6546     /* Put a text widget in the upper left hand corner. Note the use of
6547      * GTK_SHRINK in the y direction */
6548     text = gtk_text_new (NULL, NULL);
6549     gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
6550                       GTK_FILL | GTK_EXPAND,
6551                       GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
6552     gtk_widget_show (text);
6553    
6554     /* Put a HScrollbar in the lower left hand corner */
6555     hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
6556     gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
6557                       GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
6558     gtk_widget_show (hscrollbar);
6559    
6560     /* And a VScrollbar in the upper right */
6561     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
6562     gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
6563                       GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
6564     gtk_widget_show (vscrollbar);
6565    
6566     /* Add a handler to put a message in the text widget when it is realized */
6567     gtk_signal_connect (GTK_OBJECT (text), "realize",
6568                         GTK_SIGNAL_FUNC (realize_text), NULL);
6569    
6570     return table;
6571 }
6572    
6573 int
6574 main (int argc, char *argv[])
6575 {
6576     GtkWidget *window;
6577     GtkWidget *vpaned;
6578     GtkWidget *list;
6579     GtkWidget *text;
6580
6581     gtk_init (&amp;argc, &amp;argv);
6582    
6583     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6584     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
6585     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6586                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6587     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6588     gtk_widget_set_usize (GTK_WIDGET(window), 450, 400);
6589
6590     /* create a vpaned widget and add it to our toplevel window */
6591    
6592     vpaned = gtk_vpaned_new ();
6593     gtk_container_add (GTK_CONTAINER(window), vpaned);
6594     gtk_paned_set_handle_size (GTK_PANED(vpaned),
6595                                10);
6596     gtk_paned_set_gutter_size (GTK_PANED(vpaned),
6597                                15);                       
6598     gtk_widget_show (vpaned);
6599    
6600     /* Now create the contents of the two halves of the window */
6601    
6602     list = create_list ();
6603     gtk_paned_add1 (GTK_PANED(vpaned), list);
6604     gtk_widget_show (list);
6605    
6606     text = create_text ();
6607     gtk_paned_add2 (GTK_PANED(vpaned), text);
6608     gtk_widget_show (text);
6609     gtk_widget_show (window);
6610     gtk_main ();
6611     return 0;
6612 }
6613 /* example-end */
6614 </verb></tscreen>
6615
6616 <!-- ----------------------------------------------------------------- -->
6617 <sect1>Viewports <label id="sec_Viewports">
6618 <p>
6619 It is unlikely that you will ever need to use the Viewport widget
6620 directly. You are much more likely to use the
6621 <ref id="sec_ScrolledWindow" name="Scrolled Window"> widget which
6622 itself uses the Viewport.
6623
6624 A viewport widget allows you to place a larger widget within it such
6625 that you can view a part of it at a time. It uses
6626 <ref id="sec_Adjustment" name="Adjustments"> to define the area that
6627 is currently in view.
6628
6629 A Viewport is created with the function
6630
6631 <tscreen><verb>
6632 GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment,
6633                              GtkAdjustment *vadjustment );
6634 </verb></tscreen>
6635
6636 As you can see you can specify the horizontal and vertical Adjustments
6637 that the widget is to use when you create the widget. It will create
6638 its own if you pass NULL as the value of the arguments.
6639
6640 You can get and set the adjustments after the widget has been created
6641 using the following four functions:
6642
6643 <tscreen><verb>
6644 GtkAdjustment *gtk_viewport_get_hadjustment (GtkViewport *viewport );
6645
6646 GtkAdjustment *gtk_viewport_get_vadjustment (GtkViewport *viewport );
6647
6648 void gtk_viewport_set_hadjustment( GtkViewport   *viewport,
6649                                    GtkAdjustment *adjustment );
6650
6651 void gtk_viewport_set_vadjustment( GtkViewport   *viewport,
6652                                    GtkAdjustment *adjustment );
6653 </verb></tscreen>
6654
6655 The only other viewport function is used to alter its appearance:
6656
6657 <tscreen><verb>
6658 void gtk_viewport_set_shadow_type( GtkViewport   *viewport,
6659                                    GtkShadowType  type );
6660 </verb></tscreen>
6661
6662 Possible values for the <tt/type/ parameter are:
6663 <tscreen><verb>
6664   GTK_SHADOW_NONE,
6665   GTK_SHADOW_IN,
6666   GTK_SHADOW_OUT,
6667   GTK_SHADOW_ETCHED_IN,
6668   GTK_SHADOW_ETCHED_OUT
6669 </verb></tscreen>
6670  
6671 <!-- ----------------------------------------------------------------- -->
6672 <sect1>Scrolled Windows <label id="sec_ScrolledWindow">
6673 <p>
6674 Scrolled windows are used to create a scrollable area with another
6675 widget inside it. You may insert any type of widget into a scrolled
6676 window, and it will be accessible regardless of the size by using the
6677 scrollbars.
6678
6679 The following function is used to create a new scrolled window.
6680
6681 <tscreen><verb>
6682 GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
6683                                     GtkAdjustment *vadjustment );
6684 </verb></tscreen>
6685
6686 Where the first argument is the adjustment for the horizontal
6687 direction, and the second, the adjustment for the vertical direction.
6688 These are almost always set to NULL.
6689
6690 <tscreen><verb>
6691 void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
6692                                      GtkPolicyType      hscrollbar_policy,
6693                                      GtkPolicyType      vscrollbar_policy );
6694 </verb></tscreen>
6695
6696 This sets the policy to be used with respect to the scrollbars.
6697 The first argument is the scrolled window you wish to change. The second
6698 sets the policy for the horizontal scrollbar, and the third the policy for 
6699 the vertical scrollbar.
6700
6701 The policy may be one of <tt/GTK_POLICY_AUTOMATIC/ or
6702 <tt/GTK_POLICY_ALWAYS/. <tt/GTK_POLICY_AUTOMATIC/ will automatically
6703 decide whether you need scrollbars, whereas <tt/GTK_POLICY_ALWAYS/
6704 will always leave the scrollbars there.
6705
6706 You can then place your object into the scrolled window using the
6707 following function.
6708
6709 <tscreen><verb>
6710 void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
6711                                             GtkWidget         *child);
6712 </verb></tscreen>
6713
6714 Here is a simple example that packs a table eith 100 toggle buttons
6715 into a scrolled window. I've only commented on the parts that may be
6716 new to you.
6717
6718 <tscreen><verb>
6719 /* example-start scrolledwin scrolledwin.c */
6720
6721 #include <gtk/gtk.h>
6722
6723 void destroy(GtkWidget *widget, gpointer data)
6724 {
6725     gtk_main_quit();
6726 }
6727
6728 int main (int argc, char *argv[])
6729 {
6730     static GtkWidget *window;
6731     GtkWidget *scrolled_window;
6732     GtkWidget *table;
6733     GtkWidget *button;
6734     char buffer[32];
6735     int i, j;
6736     
6737     gtk_init (&amp;argc, &amp;argv);
6738     
6739     /* Create a new dialog window for the scrolled window to be
6740      * packed into.  */
6741     window = gtk_dialog_new ();
6742     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6743                         (GtkSignalFunc) destroy, NULL);
6744     gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
6745     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6746     gtk_widget_set_usize(window, 300, 300);
6747     
6748     /* create a new scrolled window. */
6749     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6750     
6751     gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
6752     
6753     /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
6754      * GTK_POLICY_AUTOMATIC will automatically decide whether you need
6755      * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
6756      * there.  The first one is the horizontal scrollbar, the second, 
6757      * the vertical. */
6758     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6759                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
6760     /* The dialog window is created with a vbox packed into it. */                                                              
6761     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, 
6762                         TRUE, TRUE, 0);
6763     gtk_widget_show (scrolled_window);
6764     
6765     /* create a table of 10 by 10 squares. */
6766     table = gtk_table_new (10, 10, FALSE);
6767     
6768     /* set the spacing to 10 on x and 10 on y */
6769     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
6770     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
6771     
6772     /* pack the table into the scrolled window */
6773     gtk_scrolled_window_add_with_viewport (
6774                    GTK_SCROLLED_WINDOW (scrolled_window), table);
6775     gtk_widget_show (table);
6776     
6777     /* this simply creates a grid of toggle buttons on the table
6778      * to demonstrate the scrolled window. */
6779     for (i = 0; i < 10; i++)
6780        for (j = 0; j < 10; j++) {
6781           sprintf (buffer, "button (%d,%d)\n", i, j);
6782           button = gtk_toggle_button_new_with_label (buffer);
6783           gtk_table_attach_defaults (GTK_TABLE (table), button,
6784                                      i, i+1, j, j+1);
6785           gtk_widget_show (button);
6786        }
6787     
6788     /* Add a "close" button to the bottom of the dialog */
6789     button = gtk_button_new_with_label ("close");
6790     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
6791                                (GtkSignalFunc) gtk_widget_destroy,
6792                                GTK_OBJECT (window));
6793     
6794     /* this makes it so the button is the default. */
6795     
6796     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
6797     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
6798     
6799     /* This grabs this button to be the default button. Simply hitting
6800      * the "Enter" key will cause this button to activate. */
6801     gtk_widget_grab_default (button);
6802     gtk_widget_show (button);
6803     
6804     gtk_widget_show (window);
6805     
6806     gtk_main();
6807     
6808     return(0);
6809 }
6810 /* example-end */
6811 </verb></tscreen>
6812
6813 Try playing with resizing the window. You'll notice how the scrollbars
6814 react. You may also wish to use the gtk_widget_set_usize() call to set
6815 the default size of the window or other widgets.
6816
6817 <!-- ----------------------------------------------------------------- -->   
6818 <sect1>Button Boxes
6819 <p>
6820 Button Boxes are a convenient way to quickly layout a group of
6821 buttons. They come in both horizontal and vertical flavours. You
6822 create a new Button Box with one of the following calls, which create
6823 a horizontal or vertical box, respectively:
6824
6825 <tscreen><verb>
6826 GtkWidget *gtk_hbutton_box_new( void );
6827
6828 GtkWidget *gtk_vbutton_box_new( void );
6829 </verb></tscreen>
6830
6831 The only attributes pertaining to button boxes effect how the buttons
6832 are laid out. You can change the spacing between the buttons with:
6833
6834 <tscreen><verb>
6835 void gtk_hbutton_box_set_spacing_default( gint spacing );
6836
6837 void gtk_vbutton_box_set_spacing_default( gint spacing );
6838 </verb></tscreen>
6839
6840 Similarly, the current spacing values can be queried using:
6841
6842 <tscreen><verb>
6843 gint gtk_hbutton_box_get_spacing_default( void );
6844
6845 gint gtk_vbutton_box_get_spacing_default( void );
6846 </verb></tscreen>
6847
6848 The second attribute that we can access effects the layout of the
6849 buttons within the box. It is set using one of:
6850
6851 <tscreen><verb>
6852 void gtk_hbutton_box_set_layout_default( GtkButtonBoxStyle layout );
6853
6854 void gtk_vbutton_box_set_layout_default( GtkButtonBoxStyle layout );
6855 </verb></tscreen>
6856
6857 The <tt/layout/ argument can take one of the following values:
6858
6859 <tscreen><verb>
6860   GTK_BUTTONBOX_DEFAULT_STYLE
6861   GTK_BUTTONBOX_SPREAD
6862   GTK_BUTTONBOX_EDGE
6863   GTK_BUTTONBOX_START
6864   GTK_BUTTONBOX_END
6865 </verb></tscreen>
6866
6867 The current layout setting can be retrieved using:
6868
6869 <tscreen><verb>
6870 GtkButtonBoxStyle gtk_hbutton_box_get_layout_default( void );
6871
6872 GtkButtonBoxStyle gtk_vbutton_box_get_layout_default( void );
6873 </verb></tscreen>
6874
6875 Buttons are added to a Button Box using the usual function:
6876
6877 <tscreen><verb>
6878     gtk_container_add( GTK_CONTAINER(button_box), child_widget );
6879 </verb></tscreen>
6880
6881 Here's an example that illustrates all the different layout settings
6882 for Button Boxes.
6883
6884 <tscreen><verb>
6885 /* example-start buttonbox buttonbox.c */
6886
6887 #include <gtk/gtk.h>
6888
6889 /* Create a Button Box with the specified parameters */
6890 GtkWidget *create_bbox (gint  horizontal,
6891                         char* title,
6892                         gint  spacing,
6893                         gint  child_w,
6894                         gint  child_h,
6895                         gint  layout)
6896 {
6897   GtkWidget *frame;
6898   GtkWidget *bbox;
6899   GtkWidget *button;
6900
6901   frame = gtk_frame_new (title);
6902
6903   if (horizontal)
6904     bbox = gtk_hbutton_box_new ();
6905   else
6906     bbox = gtk_vbutton_box_new ();
6907
6908   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
6909   gtk_container_add (GTK_CONTAINER (frame), bbox);
6910
6911   /* Set the appearance of the Button Box */
6912   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
6913   gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), spacing);
6914   gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
6915
6916   button = gtk_button_new_with_label ("OK");
6917   gtk_container_add (GTK_CONTAINER (bbox), button);
6918
6919   button = gtk_button_new_with_label ("Cancel");
6920   gtk_container_add (GTK_CONTAINER (bbox), button);
6921
6922   button = gtk_button_new_with_label ("Help");
6923   gtk_container_add (GTK_CONTAINER (bbox), button);
6924
6925   return(frame);
6926 }
6927
6928 int main( int   argc,
6929           char *argv[] )
6930 {
6931   static GtkWidget* window = NULL;
6932   GtkWidget *main_vbox;
6933   GtkWidget *vbox;
6934   GtkWidget *hbox;
6935   GtkWidget *frame_horz;
6936   GtkWidget *frame_vert;
6937
6938   /* Initialize GTK */
6939   gtk_init( &amp;argc, &amp;argv );
6940
6941   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6942   gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
6943
6944   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6945                       GTK_SIGNAL_FUNC(gtk_main_quit),
6946                       NULL);
6947
6948   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6949
6950   main_vbox = gtk_vbox_new (FALSE, 0);
6951   gtk_container_add (GTK_CONTAINER (window), main_vbox);
6952
6953   frame_horz = gtk_frame_new ("Horizontal Button Boxes");
6954   gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
6955
6956   vbox = gtk_vbox_new (FALSE, 0);
6957   gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6958   gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
6959
6960   gtk_box_pack_start (GTK_BOX (vbox),
6961            create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
6962                       TRUE, TRUE, 0);
6963
6964   gtk_box_pack_start (GTK_BOX (vbox),
6965            create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
6966                       TRUE, TRUE, 5);
6967
6968   gtk_box_pack_start (GTK_BOX (vbox),
6969            create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
6970                       TRUE, TRUE, 5);
6971
6972   gtk_box_pack_start (GTK_BOX (vbox),
6973            create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END),
6974                       TRUE, TRUE, 5);
6975
6976   frame_vert = gtk_frame_new ("Vertical Button Boxes");
6977   gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
6978
6979   hbox = gtk_hbox_new (FALSE, 0);
6980   gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
6981   gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
6982
6983   gtk_box_pack_start (GTK_BOX (hbox),
6984            create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD),
6985                       TRUE, TRUE, 0);
6986
6987   gtk_box_pack_start (GTK_BOX (hbox),
6988            create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
6989                       TRUE, TRUE, 5);
6990
6991   gtk_box_pack_start (GTK_BOX (hbox),
6992            create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
6993                       TRUE, TRUE, 5);
6994
6995   gtk_box_pack_start (GTK_BOX (hbox),
6996            create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END),
6997                       TRUE, TRUE, 5);
6998
6999   gtk_widget_show_all (window);
7000
7001   /* Enter the event loop */
7002   gtk_main ();
7003     
7004   return(0);
7005 }
7006 /* example-end */
7007 </verb></tscreen>
7008
7009 <!-- ----------------------------------------------------------------- -->   
7010 <sect1>Toolbar
7011 <p>
7012 Toolbars are usually used to group some number of widgets in order to
7013 simplify customization of their look and layout. Typically a toolbar
7014 consists of buttons with icons, labels and tooltips, but any other
7015 widget can also be put inside a toolbar. Finally, items can be
7016 arranged horizontally or vertically and buttons can be displayed with
7017 icons, labels, or both.
7018
7019 Creating a toolbar is (as one may already suspect) done with the
7020 following function:
7021
7022 <tscreen><verb>
7023 GtkWidget *gtk_toolbar_new( GtkOrientation orientation,
7024                             GtkToolbarStyle  style );
7025 </verb></tscreen>
7026
7027 where orientation may be one of:
7028
7029 <tscreen><verb>
7030   GTK_ORIENTATION_HORIZONTAL    
7031   GTK_ORIENTATION_VERTICAL
7032 </verb></tscreen>
7033
7034 and style one of:
7035
7036 <tscreen><verb>
7037   GTK_TOOLBAR_TEXT
7038   GTK_TOOLBAR_ICONS
7039   GTK_TOOLBAR_BOTH
7040 </verb></tscreen>
7041
7042 The style applies to all the buttons created with the `item' functions
7043 (not to buttons inserted into toolbar as separate widgets).
7044
7045 After creating a toolbar one can append, prepend and insert items
7046 (that means simple text strings) or elements (that means any widget
7047 types) into the toolbar. To describe an item we need a label text, a
7048 tooltip text, a private tooltip text, an icon for the button and a
7049 callback function for it. For example, to append or prepend an item
7050 you may use the following functions:
7051
7052 <tscreen><verb>
7053 GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
7054                                     const char    *text,
7055                                     const char    *tooltip_text,
7056                                     const char    *tooltip_private_text,
7057                                     GtkWidget     *icon,
7058                                     GtkSignalFunc  callback,
7059                                     gpointer       user_data );
7060
7061 GtkWidget *gtk_toolbar_prepend_item( GtkToolbar    *toolbar,
7062                                      const char    *text,
7063                                      const char    *tooltip_text,
7064                                      const char    *tooltip_private_text,
7065                                      GtkWidget     *icon,
7066                                      GtkSignalFunc  callback,
7067                                      gpointer       user_data );
7068 </verb></tscreen>
7069
7070 If you want to use gtk_toolbar_insert_item, the only additional
7071 parameter which must be specified is the position in which the item
7072 should be inserted, thus:
7073
7074 <tscreen><verb>
7075 GtkWidget *gtk_toolbar_insert_item( GtkToolbar    *toolbar,
7076                                     const char    *text,
7077                                     const char    *tooltip_text,
7078                                     const char    *tooltip_private_text,
7079                                     GtkWidget     *icon,
7080                                     GtkSignalFunc  callback,
7081                                     gpointer       user_data,
7082                                     gint           position );
7083 </verb></tscreen>
7084
7085 To simplify adding spaces between toolbar items, you may use the
7086 following functions:
7087
7088 <tscreen><verb>
7089 void gtk_toolbar_append_space( GtkToolbar *toolbar );
7090
7091 void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
7092
7093 void gtk_toolbar_insert_space( GtkToolbar *toolbar,
7094                                gint        position );
7095  
7096 </verb></tscreen>
7097
7098 While the size of the added space can be set globally for a
7099 whole toolbar with the function:
7100
7101 <tscreen><verb>
7102 void gtk_toolbar_set_space_size( GtkToolbar *toolbar,
7103                                  gint        space_size) ;
7104 </verb></tscreen>
7105
7106 If it's required, the orientation of a toolbar and its style can be
7107 changed "on the fly" using the following functions:
7108
7109 <tscreen><verb>
7110 void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
7111                                   GtkOrientation  orientation );
7112
7113 void gtk_toolbar_set_style( GtkToolbar      *toolbar,
7114                             GtkToolbarStyle  style );
7115
7116 void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
7117                                gint        enable );
7118 </verb></tscreen>
7119
7120 Where <tt/orientation/ is one of <tt/GTK_ORIENTATION_HORIZONTAL/ or
7121 <tt/GTK_ORIENTATION_VERTICAL/. The <tt/style/ is used to set
7122 appearance of the toolbar items by using one of
7123 <tt/GTK_TOOLBAR_ICONS/, <tt/GTK_TOOLBAR_TEXT/, or
7124 <tt/GTK_TOOLBAR_BOTH/.
7125
7126 To show some other things that can be done with a toolbar, let's take
7127 the following program (we'll interrupt the listing with some
7128 additional explanations):
7129
7130 <tscreen><verb>
7131 #include <gtk/gtk.h>
7132
7133 #include "gtk.xpm"
7134
7135 /* This function is connected to the Close button or
7136  * closing the window from the WM */
7137 void delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
7138 {
7139   gtk_main_quit ();
7140 }
7141 </verb></tscreen>
7142
7143 The above beginning seems for sure familiar to you if it's not your first
7144 GTK program. There is one additional thing though, we include a nice XPM
7145 picture to serve as an icon for all of the buttons.
7146
7147 <tscreen><verb>
7148 GtkWidget* close_button; /* This button will emit signal to close
7149                           * application */
7150 GtkWidget* tooltips_button; /* to enable/disable tooltips */
7151 GtkWidget* text_button,
7152          * icon_button,
7153          * both_button; /* radio buttons for toolbar style */
7154 GtkWidget* entry; /* a text entry to show packing any widget into
7155                    * toolbar */
7156 </verb></tscreen>
7157
7158 In fact not all of the above widgets are needed here, but to make things
7159 clearer I put them all together.
7160
7161 <tscreen><verb>
7162 /* that's easy... when one of the buttons is toggled, we just
7163  * check which one is active and set the style of the toolbar
7164  * accordingly
7165  * ATTENTION: our toolbar is passed as data to callback ! */
7166 void radio_event (GtkWidget *widget, gpointer data)
7167 {
7168   if (GTK_TOGGLE_BUTTON (text_button)->active) 
7169     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_TEXT);
7170   else if (GTK_TOGGLE_BUTTON (icon_button)->active)
7171     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_ICONS);
7172   else if (GTK_TOGGLE_BUTTON (both_button)->active)
7173     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_BOTH);
7174 }
7175
7176 /* even easier, just check given toggle button and enable/disable 
7177  * tooltips */
7178 void toggle_event (GtkWidget *widget, gpointer data)
7179 {
7180   gtk_toolbar_set_tooltips (GTK_TOOLBAR ( data ),
7181                             GTK_TOGGLE_BUTTON (widget)->active );
7182 }
7183 </verb></tscreen>
7184
7185 The above are just two callback functions that will be called when
7186 one of the buttons on a toolbar is pressed. You should already be
7187 familiar with things like this if you've already used toggle buttons (and
7188 radio buttons).
7189
7190 <tscreen><verb>
7191 int main (int argc, char *argv[])
7192 {
7193   /* Here is our main window (a dialog) and a handle for the handlebox */
7194   GtkWidget* dialog;
7195   GtkWidget* handlebox;
7196
7197   /* Ok, we need a toolbar, an icon with a mask (one for all of 
7198      the buttons) and an icon widget to put this icon in (but 
7199      we'll create a separate widget for each button) */
7200   GtkWidget * toolbar;
7201   GdkPixmap * icon;
7202   GdkBitmap * mask;
7203   GtkWidget * iconw;
7204
7205   /* this is called in all GTK application. */
7206   gtk_init (&amp;argc, &amp;argv);
7207   
7208   /* create a new window with a given title, and nice size */
7209   dialog = gtk_dialog_new ();
7210   gtk_window_set_title ( GTK_WINDOW ( dialog ) , "GTKToolbar Tutorial");
7211   gtk_widget_set_usize( GTK_WIDGET ( dialog ) , 600 , 300 );
7212   GTK_WINDOW ( dialog ) ->allow_shrink = TRUE;
7213
7214   /* typically we quit if someone tries to close us */
7215   gtk_signal_connect ( GTK_OBJECT ( dialog ), "delete_event",
7216                        GTK_SIGNAL_FUNC ( delete_event ), NULL);
7217
7218   /* we need to realize the window because we use pixmaps for 
7219    * items on the toolbar in the context of it */
7220   gtk_widget_realize ( dialog );
7221
7222   /* to make it nice we'll put the toolbar into the handle box, 
7223    * so that it can be detached from the main window */
7224   handlebox = gtk_handle_box_new ();
7225   gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(dialog)->vbox ),
7226                        handlebox, FALSE, FALSE, 5 );
7227 </verb></tscreen>
7228
7229 The above should be similar to any other GTK application. Just
7230 initialization of GTK, creating the window, etc. There is only one
7231 thing that probably needs some explanation: a handle box. A handle box
7232 is just another box that can be used to pack widgets in to. The
7233 difference between it and typical boxes is that it can be detached
7234 from a parent window (or, in fact, the handle box remains in the
7235 parent, but it is reduced to a very small rectangle, while all of its
7236 contents are reparented to a new freely floating window). It is
7237 usually nice to have a detachable toolbar, so these two widgets occur
7238 together quite often.
7239
7240 <tscreen><verb>
7241   /* toolbar will be horizontal, with both icons and text, and
7242    * with 5pxl spaces between items and finally, 
7243    * we'll also put it into our handlebox */
7244   toolbar = gtk_toolbar_new ( GTK_ORIENTATION_HORIZONTAL,
7245                               GTK_TOOLBAR_BOTH );
7246   gtk_container_set_border_width ( GTK_CONTAINER ( toolbar ) , 5 );
7247   gtk_toolbar_set_space_size ( GTK_TOOLBAR ( toolbar ), 5 );
7248   gtk_container_add ( GTK_CONTAINER ( handlebox ) , toolbar );
7249
7250   /* now we create icon with mask: we'll reuse it to create
7251    * icon widgets for toolbar items */
7252   icon = gdk_pixmap_create_from_xpm_d ( dialog->window, &amp;mask,
7253       &amp;dialog->style->white, gtk_xpm );
7254 </verb></tscreen>
7255
7256 Well, what we do above is just a straightforward initialization of
7257 the toolbar widget and creation of a GDK pixmap with its mask. If you
7258 want to know something more about using pixmaps, refer to GDK
7259 documentation or to the <ref id="sec_Pixmaps" name="Pixmaps"> section
7260 earlier in this tutorial.
7261
7262 <tscreen><verb>
7263   /* our first item is <close> button */
7264   iconw = gtk_pixmap_new ( icon, mask ); /* icon widget */
7265   close_button = 
7266     gtk_toolbar_append_item ( GTK_TOOLBAR (toolbar), /* our toolbar */
7267                               "Close",               /* button label */
7268                               "Closes this app",     /* this button's tooltip */
7269                               "Private",             /* tooltip private info */
7270                               iconw,                 /* icon widget */
7271                               GTK_SIGNAL_FUNC (delete_event), /* a signal */
7272                                NULL );
7273   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); /* space after item */
7274 </verb></tscreen>
7275
7276 In the above code you see the simplest case: adding a button to
7277 toolbar.  Just before appending a new item, we have to construct a
7278 pixmap widget to serve as an icon for this item; this step will have
7279 to be repeated for each new item. Just after the item we also add a
7280 space, so the following items will not touch each other. As you see
7281 gtk_toolbar_append_item returns a pointer to our newly created button
7282 widget, so that we can work with it in the normal way.
7283
7284 <tscreen><verb>
7285   /* now, let's make our radio buttons group... */
7286   iconw = gtk_pixmap_new ( icon, mask );
7287   icon_button = gtk_toolbar_append_element(
7288                     GTK_TOOLBAR(toolbar),
7289                     GTK_TOOLBAR_CHILD_RADIOBUTTON, /* a type of element */
7290                     NULL,                          /* pointer to widget */
7291                     "Icon",                        /* label */
7292                     "Only icons in toolbar",       /* tooltip */
7293                     "Private",                     /* tooltip private string */
7294                     iconw,                         /* icon */
7295                     GTK_SIGNAL_FUNC (radio_event), /* signal */
7296                     toolbar);                      /* data for signal */
7297   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7298 </verb></tscreen>
7299
7300 Here we begin creating a radio buttons group. To do this we use
7301 gtk_toolbar_append_element.  In fact, using this function one can also
7302 +add simple items or even spaces (type = <tt/GTK_TOOLBAR_CHILD_SPACE/
7303 or +<tt/GTK_TOOLBAR_CHILD_BUTTON/). In the above case we start
7304 creating a radio group. In creating other radio buttons for this group
7305 a pointer to the previous button in the group is required, so that a
7306 list of buttons can be easily constructed (see the section on <ref
7307 id="sec_Radio_Buttons" name="Radio Buttons"> earlier in this
7308 tutorial).
7309
7310 <tscreen><verb>
7311   /* following radio buttons refer to previous ones */
7312   iconw = gtk_pixmap_new ( icon, mask );
7313   text_button = 
7314     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7315                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
7316                                icon_button,
7317                                "Text",
7318                                "Only texts in toolbar",
7319                                "Private",
7320                                iconw,
7321                                GTK_SIGNAL_FUNC (radio_event),
7322                                toolbar);
7323   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7324                                           
7325   iconw = gtk_pixmap_new ( icon, mask );
7326   both_button = 
7327     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7328                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
7329                                text_button,
7330                                "Both",
7331                                "Icons and text in toolbar",
7332                                "Private",
7333                                iconw,
7334                                GTK_SIGNAL_FUNC (radio_event),
7335                                toolbar);
7336   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7337   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_button),TRUE);
7338 </verb></tscreen>
7339
7340 In the end we have to set the state of one of the buttons manually
7341 (otherwise they all stay in active state, preventing us from switching
7342 between them).
7343
7344 <tscreen><verb>
7345   /* here we have just a simple toggle button */
7346   iconw = gtk_pixmap_new ( icon, mask );
7347   tooltips_button = 
7348     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7349                                GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
7350                                NULL,
7351                                "Tooltips",
7352                                "Toolbar with or without tips",
7353                                "Private",
7354                                iconw,
7355                                GTK_SIGNAL_FUNC (toggle_event),
7356                                toolbar);
7357   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7358   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltips_button),TRUE);
7359 </verb></tscreen>
7360
7361 A toggle button can be created in the obvious way (if one knows how to create
7362 radio buttons already).
7363
7364 <tscreen><verb>
7365   /* to pack a widget into toolbar, we only have to 
7366    * create it and append it with an appropriate tooltip */
7367   entry = gtk_entry_new ();
7368   gtk_toolbar_append_widget( GTK_TOOLBAR (toolbar), 
7369                              entry, 
7370                              "This is just an entry", 
7371                              "Private" );
7372
7373   /* well, it isn't created within thetoolbar, so we must still show it */
7374   gtk_widget_show ( entry );
7375 </verb></tscreen>
7376
7377 As you see, adding any kind of widget to a toolbar is simple. The
7378 one thing you have to remember is that this widget must be shown manually
7379 (contrary to other items which will be shown together with the toolbar).
7380
7381 <tscreen><verb>
7382   /* that's it ! let's show everything. */
7383   gtk_widget_show ( toolbar );
7384   gtk_widget_show (handlebox);
7385   gtk_widget_show ( dialog );
7386
7387   /* rest in gtk_main and wait for the fun to begin! */
7388   gtk_main ();
7389   
7390   return 0;
7391 }
7392 </verb></tscreen>
7393
7394 So, here we are at the end of toolbar tutorial. Of course, to appreciate
7395 it in full you need also this nice XPM icon, so here it is:
7396
7397 <tscreen><verb>
7398 /* XPM */
7399 static char * gtk_xpm[] = {
7400 "32 39 5 1",
7401 ".      c none",
7402 "+      c black",
7403 "@      c #3070E0",
7404 "#      c #F05050",
7405 "$      c #35E035",
7406 "................+...............",
7407 "..............+++++.............",
7408 "............+++++@@++...........",
7409 "..........+++++@@@@@@++.........",
7410 "........++++@@@@@@@@@@++........",
7411 "......++++@@++++++++@@@++.......",
7412 ".....+++@@@+++++++++++@@@++.....",
7413 "...+++@@@@+++@@@@@@++++@@@@+....",
7414 "..+++@@@@+++@@@@@@@@+++@@@@@++..",
7415 ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
7416 ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
7417 ".+##++@@@@+++@@@+++++@@@@@@@@$@.",
7418 ".+###++@@@@+++@@@+++@@@@@++$$$@.",
7419 ".+####+++@@@+++++++@@@@@+@$$$$@.",
7420 ".+#####+++@@@@+++@@@@++@$$$$$$+.",
7421 ".+######++++@@@@@@@++@$$$$$$$$+.",
7422 ".+#######+##+@@@@+++$$$$$$@@$$+.",
7423 ".+###+++##+##+@@++@$$$$$$++$$$+.",
7424 ".+###++++##+##+@@$$$$$$$@+@$$@+.",
7425 ".+###++++++#+++@$$@+@$$@++$$$@+.",
7426 ".+####+++++++#++$$@+@$$++$$$$+..",
7427 ".++####++++++#++$$@+@$++@$$$$+..",
7428 ".+#####+++++##++$$++@+++$$$$$+..",
7429 ".++####+++##+#++$$+++++@$$$$$+..",
7430 ".++####+++####++$$++++++@$$$@+..",
7431 ".+#####++#####++$$+++@++++@$@+..",
7432 ".+#####++#####++$$++@$$@+++$@@..",
7433 ".++####++#####++$$++$$$$$+@$@++.",
7434 ".++####++#####++$$++$$$$$$$$+++.",
7435 ".+++####+#####++$$++$$$$$$$@+++.",
7436 "..+++#########+@$$+@$$$$$$+++...",
7437 "...+++########+@$$$$$$$$@+++....",
7438 ".....+++######+@$$$$$$$+++......",
7439 "......+++#####+@$$$$$@++........",
7440 ".......+++####+@$$$$+++.........",
7441 ".........++###+$$$@++...........",
7442 "..........++##+$@+++............",
7443 "...........+++++++..............",
7444 ".............++++..............."};
7445 </verb></tscreen>
7446
7447 <!-- ----------------------------------------------------------------- -->
7448 <sect1> Notebooks
7449 <p>
7450 The NoteBook Widget is a collection of "pages" that overlap each
7451 other, each page contains different information with only one page
7452 visible at a time. This widget has become more common lately in GUI
7453 programming, and it is a good way to show blocks of similar
7454 information that warrant separation in their display.
7455
7456 The first function call you will need to know, as you can probably
7457 guess by now, is used to create a new notebook widget.
7458
7459 <tscreen><verb>
7460 GtkWidget *gtk_notebook_new( void );
7461 </verb></tscreen>
7462
7463 Once the notebook has been created, there are a number of functions
7464 that operate on the notebook widget. Let's look at them individually.
7465
7466 The first one we will look at is how to position the page indicators.
7467 These page indicators or "tabs" as they are referred to, can be
7468 positioned in four ways: top, bottom, left, or right.
7469
7470 <tscreen><verb>
7471 void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
7472                                GtkPositionType  pos );
7473 </verb></tscreen>
7474
7475 GtkPositionType will be one of the following, which are pretty self
7476 explanatory:
7477 <tscreen><verb>
7478   GTK_POS_LEFT
7479   GTK_POS_RIGHT
7480   GTK_POS_TOP
7481   GTK_POS_BOTTOM
7482 </verb></tscreen>
7483
7484 <tt/GTK_POS_TOP/ is the default.
7485
7486 Next we will look at how to add pages to the notebook. There are three
7487 ways to add pages to the NoteBook. Let's look at the first two
7488 together as they are quite similar.
7489
7490 <tscreen><verb>
7491 void gtk_notebook_append_page( GtkNotebook *notebook,
7492                                GtkWidget   *child,
7493                                GtkWidget   *tab_label );
7494
7495 void gtk_notebook_prepend_page( GtkNotebook *notebook,
7496                                 GtkWidget   *child,
7497                                 GtkWidget   *tab_label );
7498 </verb></tscreen>
7499
7500 These functions add pages to the notebook by inserting them from the
7501 back of the notebook (append), or the front of the notebook (prepend).
7502 <tt/child/ is the widget that is placed within the notebook page, and
7503 <tt/tab_label/ is the label for the page being added. The <tt/child/
7504 widget must be created separately, and is typically a set of options
7505 setup witin one of the other container widgets, such as a table.
7506
7507 The final function for adding a page to the notebook contains all of
7508 the properties of the previous two, but it allows you to specify what
7509 position you want the page to be in the notebook.
7510
7511 <tscreen><verb>
7512 void gtk_notebook_insert_page( GtkNotebook *notebook,
7513                                GtkWidget   *child,
7514                                GtkWidget   *tab_label,
7515                                gint         position );
7516 </verb></tscreen>
7517
7518 The parameters are the same as _append_ and _prepend_ except it
7519 contains an extra parameter, <tt/position/.  This parameter is used to
7520 specify what place this page will be inserted into the first page
7521 having position zero.
7522
7523 Now that we know how to add a page, lets see how we can remove a page
7524 from the notebook.
7525
7526 <tscreen><verb>
7527 void gtk_notebook_remove_page( GtkNotebook *notebook,
7528                                gint         page_num );
7529 </verb></tscreen>
7530
7531 This function takes the page specified by <tt/page_num/ and removes it
7532 from the widget pointed to by <tt/notebook/.
7533
7534 To find out what the current page is in a notebook use the function:
7535
7536 <tscreen><verb>
7537 gint gtk_notebook_get_current_page( GtkNotebook *notebook );
7538 </verb></tscreen>
7539
7540 These next two functions are simple calls to move the notebook page
7541 forward or backward. Simply provide the respective function call with
7542 the notebook widget you wish to operate on. Note: When the NoteBook is
7543 currently on the last page, and gtk_notebook_next_page is called, the
7544 notebook will wrap back to the first page. Likewise, if the NoteBook
7545 is on the first page, and gtk_notebook_prev_page is called, the
7546 notebook will wrap to the last page.
7547
7548 <tscreen><verb>
7549 void gtk_notebook_next_page( GtkNoteBook *notebook );
7550
7551 void gtk_notebook_prev_page( GtkNoteBook *notebook );
7552 </verb></tscreen>
7553
7554 This next function sets the "active" page. If you wish the notebook to
7555 be opened to page 5 for example, you would use this function.  Without
7556 using this function, the notebook defaults to the first page.
7557
7558 <tscreen><verb>
7559 void gtk_notebook_set_page( GtkNotebook *notebook,
7560                             gint         page_num );
7561 </verb></tscreen>
7562
7563 The next two functions add or remove the notebook page tabs and the
7564 notebook border respectively.
7565
7566 <tscreen><verb>
7567 void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
7568                                  gboolean     show_tabs);
7569
7570 void gtk_notebook_set_show_border( GtkNotebook *notebook,
7571                                    gboolean     show_border );
7572 </verb></tscreen>
7573
7574 The next function is useful when the you have a large number of pages,
7575 and the tabs don't fit on the page. It allows the tabs to be scrolled
7576 through using two arrow buttons.
7577
7578 <tscreen><verb>
7579 void gtk_notebook_set_scrollable( GtkNotebook *notebook,
7580                                   gboolean     scrollable );
7581 </verb></tscreen>
7582
7583 <tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
7584 TRUE or FALSE.
7585
7586 Now let's look at an example, it is expanded from the testgtk.c code
7587 that comes with the GTK distribution. This small program creates a
7588 window with a notebook and six buttons. The notebook contains 11
7589 pages, added in three different ways, appended, inserted, and
7590 prepended. The buttons allow you rotate the tab positions, add/remove
7591 the tabs and border, remove a page, change pages in both a forward and
7592 backward manner, and exit the program.
7593
7594 <tscreen><verb>
7595 /* example-start notebook notebook.c */
7596
7597 #include <gtk/gtk.h>
7598
7599 /* This function rotates the position of the tabs */
7600 void rotate_book (GtkButton *button, GtkNotebook *notebook)
7601 {
7602     gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
7603 }
7604
7605 /* Add/Remove the page tabs and the borders */
7606 void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
7607 {
7608     gint tval = FALSE;
7609     gint bval = FALSE;
7610     if (notebook->show_tabs == 0)
7611             tval = TRUE; 
7612     if (notebook->show_border == 0)
7613             bval = TRUE;
7614     
7615     gtk_notebook_set_show_tabs (notebook, tval);
7616     gtk_notebook_set_show_border (notebook, bval);
7617 }
7618
7619 /* Remove a page from the notebook */
7620 void remove_book (GtkButton *button, GtkNotebook *notebook)
7621 {
7622     gint page;
7623     
7624     page = gtk_notebook_get_current_page(notebook);
7625     gtk_notebook_remove_page (notebook, page);
7626     /* Need to refresh the widget -- 
7627      This forces the widget to redraw itself. */
7628     gtk_widget_draw(GTK_WIDGET(notebook), NULL);
7629 }
7630
7631 void delete (GtkWidget *widget, GtkWidget *event, gpointer data)
7632 {
7633     gtk_main_quit ();
7634 }
7635
7636 int main (int argc, char *argv[])
7637 {
7638     GtkWidget *window;
7639     GtkWidget *button;
7640     GtkWidget *table;
7641     GtkWidget *notebook;
7642     GtkWidget *frame;
7643     GtkWidget *label;
7644     GtkWidget *checkbutton;
7645     int i;
7646     char bufferf[32];
7647     char bufferl[32];
7648     
7649     gtk_init (&amp;argc, &amp;argv);
7650     
7651     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7652     
7653     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
7654                         GTK_SIGNAL_FUNC (delete), NULL);
7655     
7656     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7657
7658     table = gtk_table_new(3,6,FALSE);
7659     gtk_container_add (GTK_CONTAINER (window), table);
7660     
7661     /* Create a new notebook, place the position of the tabs */
7662     notebook = gtk_notebook_new ();
7663     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
7664     gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
7665     gtk_widget_show(notebook);
7666     
7667     /* Let's append a bunch of pages to the notebook */
7668     for (i=0; i < 5; i++) {
7669         sprintf(bufferf, "Append Frame %d", i+1);
7670         sprintf(bufferl, "Page %d", i+1);
7671         
7672         frame = gtk_frame_new (bufferf);
7673         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
7674         gtk_widget_set_usize (frame, 100, 75);
7675         gtk_widget_show (frame);
7676         
7677         label = gtk_label_new (bufferf);
7678         gtk_container_add (GTK_CONTAINER (frame), label);
7679         gtk_widget_show (label);
7680         
7681         label = gtk_label_new (bufferl);
7682         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
7683     }
7684       
7685     /* Now let's add a page to a specific spot */
7686     checkbutton = gtk_check_button_new_with_label ("Check me please!");
7687     gtk_widget_set_usize(checkbutton, 100, 75);
7688     gtk_widget_show (checkbutton);
7689    
7690     label = gtk_label_new ("Add page");
7691     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
7692     
7693     /* Now finally let's prepend pages to the notebook */
7694     for (i=0; i < 5; i++) {
7695         sprintf(bufferf, "Prepend Frame %d", i+1);
7696         sprintf(bufferl, "PPage %d", i+1);
7697         
7698         frame = gtk_frame_new (bufferf);
7699         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
7700         gtk_widget_set_usize (frame, 100, 75);
7701         gtk_widget_show (frame);
7702         
7703         label = gtk_label_new (bufferf);
7704         gtk_container_add (GTK_CONTAINER (frame), label);
7705         gtk_widget_show (label);
7706         
7707         label = gtk_label_new (bufferl);
7708         gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
7709     }
7710     
7711     /* Set what page to start at (page 4) */
7712     gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
7713
7714     /* Create a bunch of buttons */
7715     button = gtk_button_new_with_label ("close");
7716     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7717                                GTK_SIGNAL_FUNC (delete), NULL);
7718     gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
7719     gtk_widget_show(button);
7720     
7721     button = gtk_button_new_with_label ("next page");
7722     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7723                                (GtkSignalFunc) gtk_notebook_next_page,
7724                                GTK_OBJECT (notebook));
7725     gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
7726     gtk_widget_show(button);
7727     
7728     button = gtk_button_new_with_label ("prev page");
7729     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7730                                (GtkSignalFunc) gtk_notebook_prev_page,
7731                                GTK_OBJECT (notebook));
7732     gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
7733     gtk_widget_show(button);
7734     
7735     button = gtk_button_new_with_label ("tab position");
7736     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7737                         (GtkSignalFunc) rotate_book,
7738                         GTK_OBJECT(notebook));
7739     gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
7740     gtk_widget_show(button);
7741     
7742     button = gtk_button_new_with_label ("tabs/border on/off");
7743     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7744                         (GtkSignalFunc) tabsborder_book,
7745                         GTK_OBJECT (notebook));
7746     gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
7747     gtk_widget_show(button);
7748     
7749     button = gtk_button_new_with_label ("remove page");
7750     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7751                         (GtkSignalFunc) remove_book,
7752                         GTK_OBJECT(notebook));
7753     gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
7754     gtk_widget_show(button);
7755     
7756     gtk_widget_show(table);
7757     gtk_widget_show(window);
7758     
7759     gtk_main ();
7760     
7761     return(0);
7762 }
7763 /* example-end */
7764 </verb></tscreen>
7765
7766 I hope this helps you on your way with creating notebooks for your
7767 GTK applications.
7768
7769 <!-- ***************************************************************** -->
7770 <sect>CList Widget
7771 <!-- ***************************************************************** -->
7772
7773 <!-- ----------------------------------------------------------------- -->
7774 <p>
7775 The CList widget has replaced the List widget (which is still
7776 available).
7777
7778 The CList widget is a multi-column list widget that is capable of
7779 handling literally thousands of rows of information. Each column can
7780 optionally have a title, which itself is optionally active, allowing
7781 us to bind a function to its selection.
7782
7783 <!-- ----------------------------------------------------------------- -->
7784 <sect1>Creating a CList widget
7785 <p>
7786 Creating a CList is quite straightforward, once you have learned
7787 about widgets in general. It provides the almost standard two ways,
7788 that is the hard way, and the easy way. But before we create it, there
7789 is one thing we should figure out beforehand: how many columns should
7790 it have?
7791
7792 Not all columns have to be visible and can be used to store data that
7793 is related to a certain cell in the list.
7794
7795 <tscreen><verb>
7796 GtkWidget *gtk_clist_new ( gint columns );
7797
7798 GtkWidget *gtk_clist_new_with_titles( gint   columns,
7799                                       gchar *titles[] );
7800 </verb></tscreen>
7801
7802 The first form is very straightforward, the second might require some
7803 explanation. Each column can have a title associated with it, and this
7804 title can be a label or a button that reacts when we click on it. If
7805 we use the second form, we must provide pointers to the title texts,
7806 and the number of pointers should equal the number of columns
7807 specified. Of course we can always use the first form, and manually
7808 add titles later.
7809
7810 Note: The CList widget does not have its own scrollbars and should
7811 be placed within a ScrolledWindow widget if your require this
7812 functionality. This is a change from the GTK 1.0 implementation.
7813
7814 <!-- ----------------------------------------------------------------- -->
7815 <sect1>Modes of operation
7816 <p>
7817 There are several attributes that can be used to alter the behaviour of
7818 a CList. First there is
7819
7820 <tscreen><verb>
7821 void gtk_clist_set_selection_mode( GtkCList         *clist,
7822                                    GtkSelectionMode  mode );
7823 </verb></tscreen>
7824
7825 which, as the name implies, sets the selection mode of the
7826 CList. The first argument is the CList widget, and the second
7827 specifies the cell selection mode (they are defined in gtkenums.h). At
7828 the time of this writing, the following modes are available to us:
7829
7830 <itemize>
7831 <item> <tt/GTK_SELECTION_SINGLE/ - The selection is either NULL or contains
7832 a GList pointer for a single selected item.
7833
7834 <item> <tt/GTK_SELECTION_BROWSE/ - The selection is NULL if the list
7835 contains no widgets or insensitive ones only, otherwise it contains a
7836 GList pointer for one GList structure, and therefore exactly one list
7837 item.
7838
7839 <item> <tt/GTK_SELECTION_MULTIPLE/ - The selection is NULL if no list items
7840 are selected or a GList pointer for the first selected item. That in
7841 turn points to a GList structure for the second selected item and so
7842 on. This is currently the <bf>default</bf> for the CList widget.
7843
7844 <item> <tt/GTK_SELECTION_EXTENDED/ - The selection is always NULL.
7845 </itemize>
7846
7847 Others might be added in later revisions of GTK.
7848
7849 We can also define what the border of the CList widget should look
7850 like. It is done through
7851
7852 <tscreen><verb>
7853 void gtk_clist_set_shadow_type( GtkCList      *clist,
7854                                 GtkShadowType  border );
7855 </verb></tscreen>
7856
7857 The possible values for the second argument are
7858
7859 <tscreen><verb>
7860   GTK_SHADOW_NONE
7861   GTK_SHADOW_IN
7862   GTK_SHADOW_OUT
7863   GTK_SHADOW_ETCHED_IN
7864   GTK_SHADOW_ETCHED_OUT
7865 </verb></tscreen>
7866
7867 <!-- ----------------------------------------------------------------- -->
7868 <sect1>Working with titles
7869 <p>
7870 When you create a CList widget, you will also get a set of title
7871 buttons automatically. They live in the top of the CList window, and
7872 can act either as normal buttons that respond to being pressed, or
7873 they can be passive, in which case they are nothing more than a
7874 title. There are four different calls that aid us in setting the
7875 status of the title buttons.
7876
7877 <tscreen><verb>
7878 void gtk_clist_column_title_active( GtkCList *clist,
7879                                      gint     column );
7880
7881 void gtk_clist_column_title_passive( GtkCList *clist,
7882                                      gint      column );
7883
7884 void gtk_clist_column_titles_active( GtkCList *clist );
7885
7886 void gtk_clist_column_titles_passive( GtkCList *clist );
7887 </verb></tscreen>
7888
7889 An active title is one which acts as a normal button, a passive one is
7890 just a label. The first two calls above will activate/deactivate the
7891 title button above the specific column, while the last two calls
7892 activate/deactivate all title buttons in the supplied clist widget.
7893
7894 But of course there are those cases when we don't want them at all,
7895 and so they can be hidden and shown at will using the following two
7896 calls.
7897
7898 <tscreen><verb>
7899 void gtk_clist_column_titles_show( GtkCList *clist );
7900
7901 void gtk_clist_column_titles_hide( GtkCList *clist );
7902 </verb></tscreen>
7903
7904 For titles to be really useful we need a mechanism to set and change
7905 them, and this is done using
7906
7907 <tscreen><verb>
7908 void gtk_clist_set_column_title( GtkCList *clist,
7909                                  gint      column,
7910                                  gchar    *title );
7911 </verb></tscreen>
7912
7913 Note that only the title of one column can be set at a time, so if all
7914 the titles are known from the beginning, then I really suggest using
7915 gtk_clist_new_with_titles (as described above) to set them. It saves
7916 you coding time, and makes your program smaller. There are some cases
7917 where getting the job done the manual way is better, and that's when
7918 not all titles will be text. CList provides us with title buttons
7919 that can in fact incorporate whole widgets, for example a pixmap. It's
7920 all done through
7921
7922 <tscreen><verb>
7923 void gtk_clist_set_column_widget( GtkCList  *clist,
7924                                   gint       column,
7925                                   GtkWidget *widget );
7926 </verb></tscreen>
7927
7928 which should require no special explanation.
7929
7930 <!-- ----------------------------------------------------------------- -->
7931 <sect1>Manipulating the list itself
7932 <p>
7933 It is possible to change the justification for a column, and it is
7934 done through
7935
7936 <tscreen><verb>
7937 void gtk_clist_set_column_justification( GtkCList         *clist,
7938                                          gint              column,
7939                                          GtkJustification  justification );
7940 </verb></tscreen>
7941
7942 The GtkJustification type can take the following values:
7943
7944 <itemize>
7945 <item><tt/GTK_JUSTIFY_LEFT/ - The text in the column will begin from the
7946 left edge.
7947
7948 <item><tt/GTK_JUSTIFY_RIGHT/ - The text in the column will begin from the
7949 right edge.
7950
7951 <item><tt/GTK_JUSTIFY_CENTER/ - The text is placed in the center of the
7952 column.
7953
7954 <item><tt/GTK_JUSTIFY_FILL/ - The text will use up all available space in
7955 the column. It is normally done by inserting extra blank spaces
7956 between words (or between individual letters if it's a single
7957 word). Much in the same way as any ordinary WYSIWYG text editor.
7958 </itemize>
7959
7960 The next function is a very important one, and should be standard in
7961 the setup of all CList widgets. When the list is created, the width
7962 of the various columns are chosen to match their titles, and since
7963 this is seldom the right width we have to set it using
7964
7965 <tscreen><verb>
7966 void gtk_clist_set_column_width( GtkCList *clist,
7967                                  gint      column,
7968                                  gint      width );
7969 </verb></tscreen>
7970
7971 Note that the width is given in pixels and not letters. The same goes
7972 for the height of the cells in the columns, but as the default value
7973 is the height of the current font this isn't as critical to the
7974 application. Still, it is done through
7975
7976 <tscreen><verb>
7977 void gtk_clist_set_row_height( GtkCList *clist,
7978                                gint      height );
7979 </verb></tscreen>
7980
7981 Again, note that the height is given in pixels.
7982
7983 We can also move the list around without user interaction, however, it
7984 does require that we know what we are looking for. Or in other words,
7985 we need the row and column of the item we want to scroll to.
7986
7987 <tscreen><verb>
7988 void gtk_clist_moveto( GtkCList *clist,
7989                        gint      row,
7990                        gint      column,
7991                        gfloat    row_align,
7992                        gfloat    col_align );
7993 </verb></tscreen>
7994
7995 The gfloat row_align is pretty important to understand. It's a value
7996 between 0.0 and 1.0, where 0.0 means that we should scroll the list so
7997 the row appears at the top, while if the value of row_align is 1.0,
7998 the row will appear at the bottom instead. All other values between
7999 0.0 and 1.0 are also valid and will place the row between the top and
8000 the bottom. The last argument, gfloat col_align works in the same way,
8001 though 0.0 marks left and 1.0 marks right instead.
8002
8003 Depending on the application's needs, we don't have to scroll to an
8004 item that is already visible to us. So how do we know if it is
8005 visible? As usual, there is a function to find that out as well.
8006
8007 <tscreen><verb>
8008 GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
8009                                         gint      row );
8010 </verb></tscreen>
8011
8012 The return value is is one of the following:
8013
8014 <tscreen><verb>
8015   GTK_VISIBILITY_NONE
8016   GTK_VISIBILITY_PARTIAL
8017   GTK_VISIBILITY_FULL
8018 </verb></tscreen>
8019
8020 Note that it will only tell us if a row is visible. Currently there is
8021 no way to determine this for a column. We can get partial information
8022 though, because if the return is <tt/GTK_VISIBILITY_PARTIAL/, then
8023 some of it is hidden, but we don't know if it is the row that is being
8024 cut by the lower edge of the listbox, or if the row has columns that
8025 are outside.
8026
8027 We can also change both the foreground and background colors of a
8028 particular row. This is useful for marking the row selected by the
8029 user, and the two functions that is used to do it are
8030
8031 <tscreen><verb>
8032 void gtk_clist_set_foreground( GtkCList *clist,
8033                                gint      row,
8034                                GdkColor *color );
8035
8036 void gtk_clist_set_background( GtkCList *clist,
8037                                gint      row,
8038                                GdkColor *color );
8039 </verb></tscreen>
8040
8041 Please note that the colors must have been previously allocated.
8042
8043 <!-- ----------------------------------------------------------------- -->
8044 <sect1>Adding rows to the list
8045 <p>
8046 We can add rows in three ways. They can be prepended or appended to
8047 the list using
8048
8049 <tscreen><verb>
8050 gint gtk_clist_prepend( GtkCList *clist,
8051                         gchar    *text[] );
8052
8053 gint gtk_clist_append( GtkCList *clist,
8054                        gchar    *text[] );
8055 </verb></tscreen>
8056
8057 The return value of these two functions indicate the index of the row
8058 that was just added. We can insert a row at a given place using
8059
8060 <tscreen><verb>
8061 void gtk_clist_insert( GtkCList *clist,
8062                        gint      row,
8063                        gchar    *text[] );
8064 </verb></tscreen>
8065
8066 In these calls we have to provide a collection of pointers that are
8067 the texts we want to put in the columns. The number of pointers should
8068 equal the number of columns in the list. If the text[] argument is
8069 NULL, then there will be no text in the columns of the row. This is
8070 useful, for example, if we want to add pixmaps instead (something that
8071 has to be done manually).
8072
8073 Also, please note that the numbering of both rows and columns start at 0.
8074
8075 To remove an individual row we use
8076
8077 <tscreen><verb>
8078 void gtk_clist_remove( GtkCList *clist,
8079                        gint      row );
8080 </verb></tscreen>
8081
8082 There is also a call that removes all rows in the list. This is a lot
8083 faster than calling gtk_clist_remove once for each row, which is the
8084 only alternative.
8085
8086 <tscreen><verb>
8087 void gtk_clist_clear( GtkCList *clist );
8088 </verb></tscreen>
8089
8090 There are also two convenience functions that should be used when a
8091 lot of changes have to be made to the list. This is to prevent the
8092 list flickering while being repeatedly updated, which may be highly
8093 annoying to the user. So instead it is a good idea to freeze the list,
8094 do the updates to it, and finally thaw it which causes the list to be
8095 updated on the screen.
8096
8097 <tscreen><verb>
8098 void gtk_clist_freeze( GtkCList * clist );
8099
8100 void gtk_clist_thaw( GtkCList * clist );
8101 </verb></tscreen>
8102
8103 <!-- ----------------------------------------------------------------- -->
8104 <sect1>Setting text and pixmaps in the cells
8105 <p>
8106 A cell can contain a pixmap, text or both. To set them the following
8107 functions are used.
8108
8109 <tscreen><verb>
8110 void gtk_clist_set_text( GtkCList    *clist,
8111                          gint         row,
8112                          gint         column,
8113                          const gchar *text );
8114
8115 void gtk_clist_set_pixmap( GtkCList  *clist,
8116                            gint       row,
8117                            gint       column,
8118                            GdkPixmap *pixmap,
8119                            GdkBitmap *mask );
8120
8121 void gtk_clist_set_pixtext( GtkCList  *clist,
8122                             gint       row,
8123                             gint       column,
8124                             gchar     *text,
8125                             guint8     spacing,
8126                             GdkPixmap *pixmap,
8127                             GdkBitmap *mask );
8128 </verb></tscreen>
8129
8130 It's quite straightforward. All the calls have the CList as the first
8131 argument, followed by the row and column of the cell, followed by the
8132 data to be set. The <tt/spacing/ argument in gtk_clist_set_pixtext is
8133 the number of pixels between the pixmap and the beginning of the
8134 text. In all cases the data is copied into the widget.
8135
8136 To read back the data, we instead use
8137
8138 <tscreen><verb>
8139 gint gtk_clist_get_text( GtkCList  *clist,
8140                          gint       row,
8141                          gint       column,
8142                          gchar    **text );
8143
8144 gint gtk_clist_get_pixmap( GtkCList   *clist,
8145                            gint        row,
8146                            gint        column,
8147                            GdkPixmap **pixmap,
8148                            GdkBitmap **mask );
8149
8150 gint gtk_clist_get_pixtext( GtkCList   *clist,
8151                             gint        row,
8152                             gint        column,
8153                             gchar     **text,
8154                             guint8     *spacing,
8155                             GdkPixmap **pixmap,
8156                             GdkBitmap **mask );
8157 </verb></tscreen>
8158
8159 The returned pointers are all pointers to the data stored within the
8160 widget, so the referenced data should not be modified or released. It
8161 isn't necessary to read it all back in case you aren't interested. Any
8162 of the pointers that are meant for return values (all except the
8163 clist) can be NULL. So if we want to read back only the text from a
8164 cell that is of type pixtext, then we would do the following, assuming
8165 that clist, row and column already exist:
8166
8167 <tscreen><verb>
8168 gchar *mytext;
8169
8170 gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
8171 </verb></tscreen>
8172
8173 There is one more call that is related to what's inside a cell in the
8174 clist, and that's
8175
8176 <tscreen><verb>
8177 GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
8178                                      gint      row,
8179                                      gint      column );
8180 </verb></tscreen>
8181
8182 which returns the type of data in a cell. The return value is one of
8183
8184 <tscreen><verb>
8185   GTK_CELL_EMPTY
8186   GTK_CELL_TEXT
8187   GTK_CELL_PIXMAP
8188   GTK_CELL_PIXTEXT
8189   GTK_CELL_WIDGET
8190 </verb></tscreen>
8191
8192 There is also a function that will let us set the indentation, both
8193 vertical and horizontal, of a cell. The indentation value is of type
8194 gint, given in pixels, and can be both positive and negative.
8195
8196 <tscreen><verb>
8197 void gtk_clist_set_shift( GtkCList *clist,
8198                           gint      row,
8199                           gint      column,
8200                           gint      vertical,
8201                           gint      horizontal );
8202 </verb></tscreen>
8203
8204 <!-- ----------------------------------------------------------------- -->
8205 <sect1>Storing data pointers
8206 <p>
8207 With a CList it is possible to set a data pointer for a row. This
8208 pointer will not be visible for the user, but is merely a convenience
8209 for the programmer to associate a row with a pointer to some
8210 additional data.
8211
8212 The functions should be fairly self-explanatory by now.
8213
8214 <tscreen><verb>
8215 void gtk_clist_set_row_data( GtkCList *clist,
8216                              gint      row,
8217                              gpointer  data );
8218
8219 void gtk_clist_set_row_data_full( GtkCList         *clist,
8220                                   gint              row,
8221                                   gpointer          data,
8222                                   GtkDestroyNotify  destroy );
8223
8224 gpointer gtk_clist_get_row_data( GtkCList *clist,
8225                                  gint      row );
8226
8227 gint gtk_clist_find_row_from_data( GtkCList *clist,
8228                                    gpointer  data );
8229 </verb></tscreen>
8230
8231 <!-- ----------------------------------------------------------------- -->
8232 <sect1>Working with selections
8233 <p>
8234 There are also functions available that let us force the (un)selection
8235 of a row. These are
8236
8237 <tscreen><verb>
8238 void gtk_clist_select_row( GtkCList *clist,
8239                            gint      row,
8240                            gint      column );
8241
8242 void gtk_clist_unselect_row( GtkCList *clist,
8243                              gint      row,
8244                              gint      column );
8245 </verb></tscreen>
8246
8247 And also a function that will take x and y coordinates (for example,
8248 read from the mousepointer), and map that onto the list, returning the
8249 corresponding row and column.
8250
8251 <tscreen><verb>
8252 gint gtk_clist_get_selection_info( GtkCList *clist,
8253                                    gint      x,
8254                                    gint      y,
8255                                    gint     *row,
8256                                    gint     *column );
8257 </verb></tscreen>
8258
8259 When we detect something of interest (it might be movement of the
8260 pointer, a click somewhere in the list) we can read the pointer
8261 coordinates and find out where in the list the pointer is. Cumbersome?
8262 Luckily, there is a simpler way...
8263
8264 <!-- ----------------------------------------------------------------- -->
8265 <sect1>The signals that bring it together
8266 <p>
8267 As with all other widgets, there are a few signals that can be used. The
8268 CList widget is derived from the Container widget, and so has all the
8269 same signals, but also adds the following:
8270
8271 <itemize>
8272 <item>select_row - This signal will send the following information, in
8273 order: GtkCList *clist, gint row, gint column, GtkEventButton *event
8274
8275 <item>unselect_row - When the user unselects a row, this signal is
8276 activated. It sends the same information as select_row
8277
8278 <item>click_column - Send GtkCList *clist, gint column
8279 </itemize>
8280
8281 So if we want to connect a callback to select_row, the callback
8282 function would be declared like this
8283
8284 <tscreen><verb>
8285 void select_row_callback(GtkWidget *widget,
8286                          gint row,
8287                          gint column,
8288                          GdkEventButton *event,
8289                          gpointer data);
8290 </verb></tscreen>
8291
8292 The callback is connected as usual with
8293
8294 <tscreen><verb>
8295 gtk_signal_connect(GTK_OBJECT( clist),
8296                    "select_row"
8297                    GTK_SIGNAL_FUNC(select_row_callback),
8298                    NULL);
8299 </verb></tscreen>
8300
8301 <!-- ----------------------------------------------------------------- -->
8302 <sect1>A CList example
8303 <p>
8304
8305 <tscreen><verb>
8306 /* example-start clist clist.c */
8307
8308 #include <gtk/gtk.h>
8309
8310 /* User clicked the "Add List" button. */
8311 void button_add_clicked( gpointer data )
8312 {
8313     int indx;
8314  
8315     /* Something silly to add to the list. 4 rows of 2 columns each */
8316     gchar *drink[4][2] = { { "Milk",    "3 Oz" },
8317                            { "Water",   "6 l" },
8318                            { "Carrots", "2" },
8319                            { "Snakes",  "55" } };
8320
8321     /* Here we do the actual adding of the text. It's done once for
8322      * each row.
8323      */
8324     for ( indx=0 ; indx < 4 ; indx++ )
8325         gtk_clist_append( (GtkCList *) data, drink[indx]);
8326
8327     return;
8328 }
8329
8330 /* User clicked the "Clear List" button. */
8331 void button_clear_clicked( gpointer data )
8332 {
8333     /* Clear the list using gtk_clist_clear. This is much faster than
8334      * calling gtk_clist_remove once for each row.
8335      */
8336     gtk_clist_clear( (GtkCList *) data);
8337
8338     return;
8339 }
8340
8341 /* The user clicked the "Hide/Show titles" button. */
8342 void button_hide_show_clicked( gpointer data )
8343 {
8344     /* Just a flag to remember the status. 0 = currently visible */
8345     static short int flag = 0;
8346
8347     if (flag == 0)
8348     {
8349         /* Hide the titles and set the flag to 1 */
8350         gtk_clist_column_titles_hide((GtkCList *) data);
8351         flag++;
8352     }
8353     else
8354     {
8355         /* Show the titles and reset flag to 0 */
8356         gtk_clist_column_titles_show((GtkCList *) data);
8357         flag--;
8358     }
8359
8360     return;
8361 }
8362
8363 /* If we come here, then the user has selected a row in the list. */
8364 void selection_made( GtkWidget      *clist,
8365                      gint            row,
8366                      gint            column,
8367                      GdkEventButton *event,
8368                      gpointer        data )
8369 {
8370     gchar *text;
8371
8372     /* Get the text that is stored in the selected row and column
8373      * which was clicked in. We will receive it as a pointer in the
8374      * argument text.
8375      */
8376     gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
8377
8378     /* Just prints some information about the selected row */
8379     g_print("You selected row %d. More specifically you clicked in "
8380             "column %d, and the text in this cell is %s\n\n",
8381             row, column, text);
8382
8383     return;
8384 }
8385
8386 int main( int    argc,
8387           gchar *argv[] )
8388 {                                  
8389     GtkWidget *window;
8390     GtkWidget *vbox, *hbox;
8391     GtkWidget *clist;
8392     GtkWidget *button_add, *button_clear, *button_hide_show;    
8393     gchar *titles[2] = { "Ingredients", "Amount" };
8394
8395     gtk_init(&amp;argc, &amp;argv);
8396     
8397     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
8398     gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
8399
8400     gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
8401     gtk_signal_connect(GTK_OBJECT(window),
8402                        "destroy",
8403                        GTK_SIGNAL_FUNC(gtk_main_quit),
8404                        NULL);
8405     
8406     vbox=gtk_vbox_new(FALSE, 5);
8407     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
8408     gtk_container_add(GTK_CONTAINER(window), vbox);
8409     gtk_widget_show(vbox);
8410     
8411     /* Create the CList. For this example we use 2 columns */
8412     clist = gtk_clist_new_with_titles( 2, titles);
8413
8414     /* When a selection is made, we want to know about it. The callback
8415      * used is selection_made, and its code can be found further down */
8416     gtk_signal_connect(GTK_OBJECT(clist), "select_row",
8417                        GTK_SIGNAL_FUNC(selection_made),
8418                        NULL);
8419
8420     /* It isn't necessary to shadow the border, but it looks nice :) */
8421     gtk_clist_set_shadow_type (GTK_CLIST(clist), GTK_SHADOW_OUT);
8422
8423     /* What however is important, is that we set the column widths as
8424      * they will never be right otherwise. Note that the columns are
8425      * numbered from 0 and up (to 1 in this case).
8426      */
8427     gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
8428
8429     /* Add the CList widget to the vertical box and show it. */
8430     gtk_box_pack_start(GTK_BOX(vbox), clist, TRUE, TRUE, 0);
8431     gtk_widget_show(clist);
8432
8433     /* Create the buttons and add them to the window. See the button
8434      * tutorial for more examples and comments on this.
8435      */
8436     hbox = gtk_hbox_new(FALSE, 0);
8437     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
8438     gtk_widget_show(hbox);
8439
8440     button_add = gtk_button_new_with_label("Add List");
8441     button_clear = gtk_button_new_with_label("Clear List");
8442     button_hide_show = gtk_button_new_with_label("Hide/Show titles");
8443
8444     gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
8445     gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
8446     gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
8447
8448     /* Connect our callbacks to the three buttons */
8449     gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
8450                               GTK_SIGNAL_FUNC(button_add_clicked),
8451                               (gpointer) clist);
8452     gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
8453                               GTK_SIGNAL_FUNC(button_clear_clicked),
8454                               (gpointer) clist);
8455     gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
8456                               GTK_SIGNAL_FUNC(button_hide_show_clicked),
8457                               (gpointer) clist);
8458
8459     gtk_widget_show(button_add);
8460     gtk_widget_show(button_clear);
8461     gtk_widget_show(button_hide_show);
8462
8463     /* The interface is completely set up so we show the window and
8464      * enter the gtk_main loop.
8465      */
8466     gtk_widget_show(window);
8467     gtk_main();
8468     
8469     return(0);
8470 }
8471 /* example-end */
8472 </verb></tscreen>
8473                     
8474 <!-- ***************************************************************** -->
8475 <sect> Tree Widget <label id="sec_Tree_Widgets">
8476 <!-- ***************************************************************** -->
8477 <p>
8478 The purpose of tree widgets is to display hierarchically-organized
8479 data. The Tree widget itself is a vertical container for widgets of
8480 type TreeItem. Tree itself is not terribly different from
8481 CList - both are derived directly from Container, and the
8482 Container methods work in the same way on Tree widgets as on
8483 CList widgets. The difference is that Tree widgets can be nested
8484 within other Tree widgets. We'll see how to do this shortly.
8485
8486 The Tree widget has its own window, and defaults to a white
8487 background, as does CList. Also, most of the Tree methods work in
8488 the same way as the corresponding CList ones. However, Tree is
8489 not derived from CList, so you cannot use them interchangeably.
8490
8491
8492 <sect1> Creating a Tree
8493 <p>
8494 A Tree is created in the usual way, using:
8495
8496 <tscreen><verb>
8497 GtkWidget *gtk_tree_new( void );
8498 </verb></tscreen>
8499
8500 Like the CList widget, a Tree will simply keep growing as more
8501 items are added to it, as well as when subtrees are expanded.  For
8502 this reason, they are almost always packed into a
8503 ScrolledWindow. You might want to use gtk_widget_set_usize() on the
8504 scrolled window to ensure that it is big enough to see the tree's
8505 items, as the default size for ScrolledWindow is quite small.
8506
8507 Now that you have a tree, you'll probably want to add some items to
8508 it.  <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
8509 explains the gory details of TreeItem. For now, it'll suffice to
8510 create one, using:
8511
8512 <tscreen><verb>
8513 GtkWidget *gtk_tree_item_new_with_label( gchar *label );
8514 </verb></tscreen>
8515
8516 You can then add it to the tree using one of the following (see
8517 <ref id="sec_Tree_Functions" name="Functions and Macros">
8518 below for more options):
8519
8520 <tscreen><verb>
8521 void gtk_tree_append( GtkTree    *tree,
8522                        GtkWidget *tree_item );
8523
8524 void gtk_tree_prepend( GtkTree   *tree,
8525                        GtkWidget *tree_item );
8526 </verb></tscreen>
8527
8528 Note that you must add items to a Tree one at a time - there is no
8529 equivalent to gtk_list_*_items().
8530
8531 <!-- ----------------------------------------------------------------- -->
8532 <sect1> Adding a Subtree
8533 <p>
8534 A subtree is created like any other Tree widget. A subtree is added
8535 to another tree beneath a tree item, using:
8536
8537 <tscreen><verb>
8538 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
8539                                 GtkWidget   *subtree );
8540 </verb></tscreen>
8541
8542 You do not need to call gtk_widget_show() on a subtree before or after
8543 adding it to a TreeItem. However, you <em>must</em> have added the
8544 TreeItem in question to a parent tree before calling
8545 gtk_tree_item_set_subtree(). This is because, technically, the parent
8546 of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
8547 rather the GtkTree which holds that GtkTreeItem.
8548
8549 When you add a subtree to a TreeItem, a plus or minus sign appears
8550 beside it, which the user can click on to "expand" or "collapse" it,
8551 meaning, to show or hide its subtree. TreeItems are collapsed by
8552 default. Note that when you collapse a TreeItem, any selected
8553 items in its subtree remain selected, which may not be what the user
8554 expects.
8555
8556 <!-- ----------------------------------------------------------------- -->
8557 <sect1> Handling the Selection List
8558 <p>
8559 As with CList, the Tree type has a <tt>selection</tt> field, and
8560 it is possible to control the behaviour of the tree (somewhat) by
8561 setting the selection type using:
8562
8563 <tscreen><verb>
8564 void gtk_tree_set_selection_mode( GtkTree          *tree,
8565                                   GtkSelectionMode  mode );
8566 </verb></tscreen>
8567
8568 The semantics associated with the various selection modes are
8569 described in the section on the CList widget. As with the CList
8570 widget, the "select_child", "unselect_child" (not really - see <ref
8571 id="sec_Tree_Signals" name="Signals"> below for an explanation),
8572 and "selection_changed" signals are emitted when list items are
8573 selected or unselected. However, in order to take advantage of these
8574 signals, you need to know <em>which</em> Tree widget they will be
8575 emitted by, and where to find the list of selected items.
8576
8577 This is a source of potential confusion. The best way to explain this
8578 is that though all Tree widgets are created equal, some are more equal
8579 than others. All Tree widgets have their own X window, and can
8580 therefore receive events such as mouse clicks (if their TreeItems or
8581 their children don't catch them first!). However, to make
8582 <tt/GTK_SELECTION_SINGLE/ and <tt/GTK_SELECTION_BROWSE/ selection
8583 types behave in a sane manner, the list of selected items is specific
8584 to the topmost Tree widget in a hierarchy, known as the "root tree".
8585
8586 Thus, accessing the <tt>selection</tt> field directly in an arbitrary
8587 Tree widget is not a good idea unless you <em>know</em> it's the root
8588 tree. Instead, use the <tt/GTK_TREE_SELECTION (Tree)/ macro, which
8589 gives the root tree's selection list as a GList pointer. Of course,
8590 this list can include items that are not in the subtree in question if
8591 the selection type is <tt/GTK_SELECTION_MULTIPLE/.
8592
8593 Finally, the "select_child" (and "unselect_child", in theory) signals
8594 are emitted by all trees, but the "selection_changed" signal is only
8595 emitted by the root tree. Consequently, if you want to handle the
8596 "select_child" signal for a tree and all its subtrees, you will have
8597 to call gtk_signal_connect() for every subtree.
8598
8599 <sect1> Tree Widget Internals
8600 <p>
8601 The Tree's struct definition looks like this:
8602
8603 <tscreen><verb>
8604 struct _GtkTree
8605 {
8606   GtkContainer container;
8607
8608   GList *children;
8609   
8610   GtkTree* root_tree; /* owner of selection list */
8611   GtkWidget* tree_owner;
8612   GList *selection;
8613   guint level;
8614   guint indent_value;
8615   guint current_indent;
8616   guint selection_mode : 2;
8617   guint view_mode : 1;
8618   guint view_line : 1;
8619 };
8620 </verb></tscreen>
8621
8622 The perils associated with accessing the <tt>selection</tt> field
8623 directly have already been mentioned. The other important fields of
8624 the struct can also be accessed with handy macros or class functions.
8625 <tt/GTK_TREE_IS_ROOT_TREE (Tree)/ returns a boolean value which
8626 indicates whether a tree is the root tree in a Tree hierarchy, while
8627 <tt/GTK_TREE_ROOT_TREE (Tree)/ returns the root tree, an object of
8628 type GtkTree (so, remember to cast it using <tt/GTK_WIDGET (Tree)/ if
8629 you want to use one of the gtk_widget_*() functions on it).
8630
8631 Instead of directly accessing the children field of a Tree widget,
8632 it's probably best to cast it using >tt/GTK_CONTAINER (Tree)/, and
8633 pass it to the gtk_container_children() function. This creates a
8634 duplicate of the original list, so it's advisable to free it up using
8635 g_list_free() after you're done with it, or to iterate on it
8636 destructively, like this:
8637
8638 <tscreen><verb>
8639     children = gtk_container_children (GTK_CONTAINER (tree));
8640     while (children) {
8641       do_something_nice (GTK_TREE_ITEM (children->data));
8642       children = g_list_remove_link (children, children);
8643 }
8644 </verb></tscreen>
8645
8646 The <tt>tree_owner</tt> field is defined only in subtrees, where it
8647 points to the TreeItem widget which holds the tree in question.
8648 The <tt>level</tt> field indicates how deeply nested a particular tree
8649 is; root trees have level 0, and each successive level of subtrees has
8650 a level one greater than the parent level. This field is set only
8651 after a Tree widget is actually mapped (i.e. drawn on the screen).
8652
8653 <sect2> Signals<label id="sec_Tree_Signals">
8654 <p>
8655 <tscreen><verb>
8656 void selection_changed( GtkTree *tree );
8657 </verb></tscreen>
8658
8659 This signal will be emitted whenever the <tt>selection</tt> field of a
8660 Tree has changed. This happens when a child of the Tree is
8661 selected or deselected.
8662
8663 <tscreen><verb>
8664 void select_child( GtkTree   *tree,
8665                    GtkWidget *child );
8666 </verb></tscreen>
8667
8668 This signal is emitted when a child of the Tree is about to get
8669 selected. This happens on calls to gtk_tree_select_item(),
8670 gtk_tree_select_child(), on <em>all</em> button presses and calls to
8671 gtk_tree_item_toggle() and gtk_item_toggle().  It may sometimes be
8672 indirectly triggered on other occasions where children get added to or
8673 removed from the Tree.
8674
8675 <tscreen><verb>
8676 void unselect_child (GtkTree   *tree,
8677                      GtkWidget *child);
8678 </verb></tscreen>
8679
8680 This signal is emitted when a child of the Tree is about to get
8681 deselected. As of GTK 1.0.4, this seems to only occur on calls to
8682 gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
8683 other occasions, but <em>not</em> when a button press deselects a
8684 child, nor on emission of the "toggle" signal by gtk_item_toggle().
8685
8686 <sect2> Functions and Macros<label id="sec_Tree_Functions">
8687 <p>
8688 <tscreen><verb>
8689 guint gtk_tree_get_type( void );
8690 </verb></tscreen>
8691
8692 Returns the "GtkTree" type identifier.
8693
8694 <tscreen><verb>
8695 GtkWidget* gtk_tree_new( void );
8696 </verb></tscreen>
8697
8698 Create a new Tree object. The new widget is returned as a pointer to a
8699 GtkWidget object. NULL is returned on failure.
8700
8701 <tscreen><verb>
8702 void gtk_tree_append( GtkTree   *tree,
8703                       GtkWidget *tree_item );
8704 </verb></tscreen>
8705
8706 Append a tree item to a Tree.
8707
8708 <tscreen><verb>
8709 void gtk_tree_prepend( GtkTree   *tree,
8710                        GtkWidget *tree_item );
8711 </verb></tscreen>
8712
8713 Prepend a tree item to a Tree.
8714
8715 <tscreen><verb>
8716 void gtk_tree_insert( GtkTree   *tree,
8717                       GtkWidget *tree_item,
8718                       gint       position );
8719 </verb></tscreen>
8720
8721 Insert a tree item into a Tree at the position in the list
8722 specified by <tt>position.</tt>
8723
8724 <tscreen><verb>
8725 void gtk_tree_remove_items( GtkTree *tree,
8726                             GList   *items );
8727 </verb></tscreen>
8728
8729 Remove a list of items (in the form of a GList *) from a Tree.
8730 Note that removing an item from a tree dereferences (and thus usually)
8731 destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
8732 subtrees in that subtree. If you want to remove only one item, you
8733 can use gtk_container_remove().
8734
8735 <tscreen><verb>
8736 void gtk_tree_clear_items( GtkTree *tree,
8737                            gint     start,
8738                            gint     end );
8739 </verb></tscreen>
8740
8741 Remove the items from position <tt>start</tt> to position <tt>end</tt>
8742 from a Tree. The same warning about dereferencing applies here, as
8743 gtk_tree_clear_items() simply constructs a list and passes it to
8744 gtk_tree_remove_items().
8745
8746 <tscreen><verb>
8747 void gtk_tree_select_item( GtkTree *tree,
8748                            gint     item );
8749 </verb></tscreen>
8750
8751 Emits the "select_item" signal for the child at position
8752 <tt>item</tt>, thus selecting the child (unless you unselect it in a
8753 signal handler).
8754
8755 <tscreen><verb>
8756 void gtk_tree_unselect_item( GtkTree *tree,
8757                              gint     item );
8758 </verb></tscreen>
8759
8760 Emits the "unselect_item" signal for the child at position
8761 <tt>item</tt>, thus unselecting the child.
8762
8763 <tscreen><verb>
8764 void gtk_tree_select_child( GtkTree   *tree,
8765                             GtkWidget *tree_item );
8766 </verb></tscreen>
8767
8768 Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
8769 selecting it.
8770
8771 <tscreen><verb>
8772 void gtk_tree_unselect_child( GtkTree   *tree,
8773                               GtkWidget *tree_item );
8774 </verb></tscreen>
8775
8776 Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
8777 thus unselecting it.
8778
8779 <tscreen><verb>
8780 gint gtk_tree_child_position( GtkTree   *tree,
8781                               GtkWidget *child );
8782 </verb></tscreen>
8783
8784 Returns the position in the tree of <tt>child</tt>, unless
8785 <tt>child</tt> is not in the tree, in which case it returns -1.
8786
8787 <tscreen><verb>
8788 void gtk_tree_set_selection_mode( GtkTree          *tree,
8789                                   GtkSelectionMode  mode );
8790 </verb></tscreen>
8791
8792 Sets the selection mode, which can be one of <tt/GTK_SELECTION_SINGLE/ (the
8793 default), <tt/GTK_SELECTION_BROWSE/, <tt/GTK_SELECTION_MULTIPLE/, or
8794 <tt/GTK_SELECTION_EXTENDED/. This is only defined for root trees, which
8795 makes sense, since the root tree "owns" the selection. Setting it for
8796 subtrees has no effect at all; the value is simply ignored.
8797
8798 <tscreen><verb>
8799 void gtk_tree_set_view_mode( GtkTree         *tree,
8800                              GtkTreeViewMode  mode ); 
8801 </verb></tscreen>
8802
8803 Sets the "view mode", which can be either <tt/GTK_TREE_VIEW_LINE/ (the
8804 default) or <tt/GTK_TREE_VIEW_ITEM/.  The view mode propagates from a
8805 tree to its subtrees, and can't be set exclusively to a subtree (this
8806 is not exactly true - see the example code comments).
8807
8808 The term "view mode" is rather ambiguous - basically, it controls the
8809 way the highlight is drawn when one of a tree's children is selected.
8810 If it's <tt/GTK_TREE_VIEW_LINE/, the entire TreeItem widget is
8811 highlighted, while for <tt/GTK_TREE_VIEW_ITEM/, only the child widget
8812 (i.e., usually the label) is highlighted.
8813
8814 <tscreen><verb>
8815 void gtk_tree_set_view_lines( GtkTree *tree,
8816                               guint    flag );
8817 </verb></tscreen>
8818
8819 Controls whether connecting lines between tree items are drawn.
8820 <tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
8821 which case they aren't.
8822
8823 <tscreen><verb>
8824 GtkTree *GTK_TREE (gpointer obj);
8825 </verb></tscreen>
8826
8827 Cast a generic pointer to "GtkTree *".
8828
8829 <tscreen><verb>
8830 GtkTreeClass *GTK_TREE_CLASS (gpointer class);
8831 </verb></tscreen>
8832
8833 Cast a generic pointer to "GtkTreeClass *".
8834
8835 <tscreen><verb>
8836 gint GTK_IS_TREE (gpointer obj);
8837 </verb></tscreen>
8838
8839 Determine if a generic pointer refers to a "GtkTree" object.
8840
8841 <tscreen><verb>
8842 gint GTK_IS_ROOT_TREE (gpointer obj)
8843 </verb></tscreen>
8844
8845 Determine if a generic pointer refers to a "GtkTree" object
8846 <em>and</em> is a root tree. Though this will accept any pointer, the
8847 results of passing it a pointer that does not refer to a Tree are
8848 undefined and possibly harmful.
8849
8850 <tscreen><verb>
8851 GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
8852 </verb></tscreen>
8853
8854 Return the root tree of a pointer to a "GtkTree" object. The above
8855 warning applies.
8856
8857 <tscreen><verb>
8858 GList *GTK_TREE_SELECTION( gpointer obj)
8859 </verb></tscreen>
8860
8861 Return the selection list of the root tree of a "GtkTree" object. The
8862 above warning applies here, too.
8863
8864 <sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
8865 <p>
8866 The TreeItem widget, like CListItem, is derived from Item,
8867 which in turn is derived from Bin.  Therefore, the item itself is a
8868 generic container holding exactly one child widget, which can be of
8869 any type. The TreeItem widget has a number of extra fields, but
8870 the only one we need be concerned with is the <tt>subtree</tt> field.
8871
8872 The definition for the TreeItem struct looks like this:
8873
8874 <tscreen><verb>
8875 struct _GtkTreeItem
8876 {
8877   GtkItem item;
8878
8879   GtkWidget *subtree;
8880   GtkWidget *pixmaps_box;
8881   GtkWidget *plus_pix_widget, *minus_pix_widget;
8882
8883   GList *pixmaps;               /* pixmap node for this items color depth */
8884
8885   guint expanded : 1;
8886 };
8887 </verb></tscreen>
8888
8889 The <tt>pixmaps_box</tt> field is an EventBox which catches clicks on
8890 the plus/minus symbol which controls expansion and collapsing. The
8891 <tt>pixmaps</tt> field points to an internal data structure. Since
8892 you can always obtain the subtree of a TreeItem in a (relatively)
8893 type-safe manner with the <tt/GTK_TREE_ITEM_SUBTREE (Item)/ macro,
8894 it's probably advisable never to touch the insides of a TreeItem
8895 unless you <em>really</em> know what you're doing.
8896
8897 Since it is directly derived from an Item it can be treated as such by
8898 using the <tt/GTK_ITEM (TreeItem)/ macro. A TreeItem usually holds a
8899 label, so the convenience function gtk_list_item_new_with_label() is
8900 provided. The same effect can be achieved using code like the
8901 following, which is actually copied verbatim from
8902 gtk_tree_item_new_with_label():
8903
8904 <tscreen><verb>
8905 tree_item = gtk_tree_item_new ();
8906 label_widget = gtk_label_new (label);
8907 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
8908
8909 gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
8910 gtk_widget_show (label_widget);
8911 </verb></tscreen>
8912
8913 As one is not forced to add a Label to a TreeItem, you could
8914 also add an HBox or an Arrow, or even a Notebook (though your
8915 app will likely be quite unpopular in this case) to the TreeItem.
8916
8917 If you remove all the items from a subtree, it will be destroyed and
8918 unparented, unless you reference it beforehand, and the TreeItem
8919 which owns it will be collapsed. So, if you want it to stick around,
8920 do something like the following:
8921
8922 <tscreen><verb>
8923 gtk_widget_ref (tree);
8924 owner = GTK_TREE(tree)->tree_owner;
8925 gtk_container_remove (GTK_CONTAINER(tree), item);
8926 if (tree->parent == NULL){
8927   gtk_tree_item_expand (GTK_TREE_ITEM(owner));
8928   gtk_tree_item_set_subtree (GTK_TREE_ITEM(owner), tree);
8929 }
8930 else
8931   gtk_widget_unref (tree);
8932 </verb></tscreen>
8933
8934 Finally, drag-n-drop <em>does</em> work with TreeItems. You just
8935 have to make sure that the TreeItem you want to make into a drag
8936 item or a drop site has not only been added to a Tree, but that
8937 each successive parent widget has a parent itself, all the way back to
8938 a toplevel or dialog window, when you call gtk_widget_dnd_drag_set()
8939 or gtk_widget_dnd_drop_set().  Otherwise, strange things will happen.
8940
8941 <sect2> Signals
8942 <p>
8943 TreeItem inherits the "select", "deselect", and "toggle" signals
8944 from Item. In addition, it adds two signals of its own, "expand"
8945 and "collapse".
8946
8947 <tscreen><verb>
8948 void select( GtkItem *tree_item );
8949 </verb></tscreen>
8950
8951 This signal is emitted when an item is about to be selected, either
8952 after it has been clicked on by the user, or when the program calls
8953 gtk_tree_item_select(), gtk_item_select(), or gtk_tree_select_child().
8954
8955 <tscreen><verb>
8956 void deselect( GtkItem *tree_item );
8957 </verb></tscreen>
8958
8959 This signal is emitted when an item is about to be unselected, either
8960 after it has been clicked on by the user, or when the program calls
8961 gtk_tree_item_deselect() or gtk_item_deselect(). In the case of
8962 TreeItems, it is also emitted by gtk_tree_unselect_child(), and
8963 sometimes gtk_tree_select_child().
8964
8965 <tscreen><verb>
8966 void toggle( GtkItem *tree_item );
8967 </verb></tscreen>
8968
8969 This signal is emitted when the program calls gtk_item_toggle().  The
8970 effect it has when emitted on a TreeItem is to call
8971 gtk_tree_select_child() (and never gtk_tree_unselect_child()) on the
8972 item's parent tree, if the item has a parent tree.  If it doesn't,
8973 then the highlight is reversed on the item.
8974
8975 <tscreen><verb>
8976 void expand( GtkTreeItem *tree_item );
8977 </verb></tscreen>
8978
8979 This signal is emitted when the tree item's subtree is about to be
8980 expanded, that is, when the user clicks on the plus sign next to the
8981 item, or when the program calls gtk_tree_item_expand().
8982
8983 <tscreen><verb>
8984 void collapse( GtkTreeItem *tree_item );
8985 </verb></tscreen>
8986
8987 This signal is emitted when the tree item's subtree is about to be
8988 collapsed, that is, when the user clicks on the minus sign next to the
8989 item, or when the program calls gtk_tree_item_collapse().
8990
8991 <sect2> Functions and Macros
8992 <p>
8993 <tscreen><verb>
8994 guint gtk_tree_item_get_type( void );
8995 </verb></tscreen>
8996
8997 Returns the "GtkTreeItem" type identifier.
8998
8999 <tscreen><verb>
9000 GtkWidget* gtk_tree_item_new( void );
9001 </verb></tscreen>
9002
9003 Create a new TreeItem object. The new widget is returned as a
9004 pointer to a GtkWidget object. NULL is returned on failure.
9005
9006 <tscreen><verb>
9007 GtkWidget* gtk_tree_item_new_with_label (gchar       *label);
9008 </verb></tscreen>
9009
9010 Create a new TreeItem object, having a single GtkLabel as the sole
9011 child. The new widget is returned as a pointer to a GtkWidget
9012 object. NULL is returned on failure.
9013
9014 <tscreen><verb>
9015 void gtk_tree_item_select( GtkTreeItem *tree_item );
9016 </verb></tscreen>
9017
9018 This function is basically a wrapper around a call to
9019 <tt>gtk_item_select (GTK_ITEM (tree_item))</tt> which will emit the
9020 select signal.
9021
9022 <tscreen><verb>
9023 void gtk_tree_item_deselect( GtkTreeItem *tree_item );
9024 </verb></tscreen>
9025
9026 This function is basically a wrapper around a call to
9027 gtk_item_deselect (GTK_ITEM (tree_item)) which will emit the deselect
9028 signal.
9029
9030 <tscreen><verb>
9031 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
9032                                 GtkWidget   *subtree );
9033 </verb></tscreen>
9034
9035 This function adds a subtree to tree_item, showing it if tree_item is
9036 expanded, or hiding it if tree_item is collapsed. Again, remember that
9037 the tree_item must have already been added to a tree for this to work.
9038
9039 <tscreen><verb>
9040 void gtk_tree_item_remove_subtree( GtkTreeItem *tree_item );
9041 </verb></tscreen>
9042
9043 This removes all of tree_item's subtree's children (thus unreferencing
9044 and destroying it, any of its children's subtrees, and so on...), then
9045 removes the subtree itself, and hides the plus/minus sign.
9046
9047 <tscreen><verb>
9048 void gtk_tree_item_expand( GtkTreeItem *tree_item );
9049 </verb></tscreen>
9050
9051 This emits the "expand" signal on tree_item, which expands it.
9052
9053 <tscreen><verb>
9054 void gtk_tree_item_collapse( GtkTreeItem *tree_item );
9055 </verb></tscreen>
9056
9057 This emits the "collapse" signal on tree_item, which collapses it.
9058
9059 <tscreen><verb>
9060 GtkTreeItem *GTK_TREE_ITEM (gpointer obj)
9061 </verb></tscreen>
9062
9063 Cast a generic pointer to "GtkTreeItem *".
9064
9065 <tscreen><verb>
9066 GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj)
9067 </verb></tscreen>
9068
9069 Cast a generic pointer to "GtkTreeItemClass".
9070
9071 <tscreen><verb>
9072 gint GTK_IS_TREE_ITEM (gpointer obj)
9073 </verb></tscreen>
9074
9075 Determine if a generic pointer refers to a "GtkTreeItem" object.
9076  
9077 <tscreen><verb>
9078 GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj)
9079 </verb></tscreen>
9080
9081 Returns a tree item's subtree (<tt/obj/ should point to a
9082 "GtkTreeItem" object).
9083
9084 <sect1> Tree Example
9085 <p>
9086 This is somewhat like the tree example in testgtk.c, but a lot less
9087 complete (although much better commented).  It puts up a window with a
9088 tree, and connects all the signals for the relevant objects, so you
9089 can see when they are emitted.
9090
9091 <tscreen><verb>
9092 /* example-start tree tree.c */
9093
9094 #include <gtk/gtk.h>
9095
9096 /* for all the GtkItem:: and GtkTreeItem:: signals */
9097 static void cb_itemsignal (GtkWidget *item, gchar *signame)
9098 {
9099   gchar *name;
9100   GtkLabel *label;
9101
9102   /* It's a Bin, so it has one child, which we know to be a
9103      label, so get that */
9104   label = GTK_LABEL (GTK_BIN (item)->child);
9105   /* Get the text of the label */
9106   gtk_label_get (label, &amp;name);
9107   /* Get the level of the tree which the item is in */
9108   g_print ("%s called for item %s->%p, level %d\n", signame, name,
9109            item, GTK_TREE (item->parent)->level);
9110 }
9111
9112 /* Note that this is never called */
9113 static void cb_unselect_child (GtkWidget *root_tree, GtkWidget *child,
9114                                GtkWidget *subtree)
9115 {
9116   g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
9117            root_tree, subtree, child);
9118 }
9119
9120 /* Note that this is called every time the user clicks on an item,
9121    whether it is already selected or not. */
9122 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
9123                              GtkWidget *subtree)
9124 {
9125   g_print ("select_child called for root tree %p, subtree %p, child %p\n",
9126            root_tree, subtree, child);
9127 }
9128
9129 static void cb_selection_changed (GtkWidget *tree)
9130 {
9131   GList *i;
9132   
9133   g_print ("selection_change called for tree %p\n", tree);
9134   g_print ("selected objects are:\n");
9135
9136   i = GTK_TREE_SELECTION(tree);
9137   while (i){
9138     gchar *name;
9139     GtkLabel *label;
9140     GtkWidget *item;
9141
9142     /* Get a GtkWidget pointer from the list node */
9143     item = GTK_WIDGET (i->data);
9144     label = GTK_LABEL (GTK_BIN (item)->child);
9145     gtk_label_get (label, &amp;name);
9146     g_print ("\t%s on level %d\n", name, GTK_TREE
9147              (item->parent)->level);
9148     i = i->next;
9149   }
9150 }
9151
9152 int main (int argc, char *argv[])
9153 {
9154   GtkWidget *window, *scrolled_win, *tree;
9155   static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux",
9156                                "Maurice"};
9157   gint i;
9158
9159   gtk_init (&amp;argc, &amp;argv);
9160
9161   /* a generic toplevel window */
9162   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9163   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
9164                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
9165   gtk_container_set_border_width (GTK_CONTAINER(window), 5);
9166
9167   /* A generic scrolled window */
9168   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
9169   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
9170                                   GTK_POLICY_AUTOMATIC,
9171                                   GTK_POLICY_AUTOMATIC);
9172   gtk_widget_set_usize (scrolled_win, 150, 200);
9173   gtk_container_add (GTK_CONTAINER(window), scrolled_win);
9174   gtk_widget_show (scrolled_win);
9175   
9176   /* Create the root tree */
9177   tree = gtk_tree_new();
9178   g_print ("root tree is %p\n", tree);
9179   /* connect all GtkTree:: signals */
9180   gtk_signal_connect (GTK_OBJECT(tree), "select_child",
9181                       GTK_SIGNAL_FUNC(cb_select_child), tree);
9182   gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
9183                       GTK_SIGNAL_FUNC(cb_unselect_child), tree);
9184   gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
9185                       GTK_SIGNAL_FUNC(cb_selection_changed), tree);
9186   /* Add it to the scrolled window */
9187   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
9188                                          tree);
9189   /* Set the selection mode */
9190   gtk_tree_set_selection_mode (GTK_TREE(tree),
9191                                GTK_SELECTION_MULTIPLE);
9192   /* Show it */
9193   gtk_widget_show (tree);
9194
9195   for (i = 0; i < 5; i++){
9196     GtkWidget *subtree, *item;
9197     gint j;
9198
9199     /* Create a tree item */
9200     item = gtk_tree_item_new_with_label (itemnames[i]);
9201     /* Connect all GtkItem:: and GtkTreeItem:: signals */
9202     gtk_signal_connect (GTK_OBJECT(item), "select",
9203                         GTK_SIGNAL_FUNC(cb_itemsignal), "select");
9204     gtk_signal_connect (GTK_OBJECT(item), "deselect",
9205                         GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
9206     gtk_signal_connect (GTK_OBJECT(item), "toggle",
9207                         GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
9208     gtk_signal_connect (GTK_OBJECT(item), "expand",
9209                         GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
9210     gtk_signal_connect (GTK_OBJECT(item), "collapse",
9211                         GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
9212     /* Add it to the parent tree */
9213     gtk_tree_append (GTK_TREE(tree), item);
9214     /* Show it - this can be done at any time */
9215     gtk_widget_show (item);
9216     /* Create this item's subtree */
9217     subtree = gtk_tree_new();
9218     g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item,
9219              subtree);
9220
9221     /* This is still necessary if you want these signals to be called
9222        for the subtree's children.  Note that selection_change will be 
9223        signalled for the root tree regardless. */
9224     gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
9225                         GTK_SIGNAL_FUNC(cb_select_child), subtree);
9226     gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
9227                         GTK_SIGNAL_FUNC(cb_unselect_child), subtree);
9228     /* This has absolutely no effect, because it is completely ignored 
9229        in subtrees */
9230     gtk_tree_set_selection_mode (GTK_TREE(subtree),
9231                                  GTK_SELECTION_SINGLE);
9232     /* Neither does this, but for a rather different reason - the
9233        view_mode and view_line values of a tree are propagated to
9234        subtrees when they are mapped.  So, setting it later on would
9235        actually have a (somewhat unpredictable) effect */
9236     gtk_tree_set_view_mode (GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
9237     /* Set this item's subtree - note that you cannot do this until
9238        AFTER the item has been added to its parent tree! */
9239     gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subtree);
9240
9241     for (j = 0; j < 5; j++){
9242       GtkWidget *subitem;
9243
9244       /* Create a subtree item, in much the same way */
9245       subitem = gtk_tree_item_new_with_label (itemnames[j]);
9246       /* Connect all GtkItem:: and GtkTreeItem:: signals */
9247       gtk_signal_connect (GTK_OBJECT(subitem), "select",
9248                           GTK_SIGNAL_FUNC(cb_itemsignal), "select");
9249       gtk_signal_connect (GTK_OBJECT(subitem), "deselect",
9250                           GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
9251       gtk_signal_connect (GTK_OBJECT(subitem), "toggle",
9252                           GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
9253       gtk_signal_connect (GTK_OBJECT(subitem), "expand",
9254                           GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
9255       gtk_signal_connect (GTK_OBJECT(subitem), "collapse",
9256                           GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
9257       g_print ("-> -> item %s->%p\n", itemnames[j], subitem);
9258       /* Add it to its parent tree */
9259       gtk_tree_append (GTK_TREE(subtree), subitem);
9260       /* Show it */
9261       gtk_widget_show (subitem);
9262     }
9263   }
9264
9265   /* Show the window and loop endlessly */
9266   gtk_widget_show (window);
9267   gtk_main();
9268   return 0;
9269 }
9270 /* example-end */
9271 </verb></tscreen>
9272
9273 <!-- ***************************************************************** -->
9274 <sect>Menu Widget
9275 <!-- ***************************************************************** -->
9276 <p>
9277 There are two ways to create menus: there's the easy way, and there's
9278 the hard way. Both have their uses, but you can usually use the
9279 Itemfactory (the easy way). The "hard" way is to create all the menus
9280 using the calls directly. The easy way is to use the gtk_item_factory
9281 calls. This is much simpler, but there are advantages and
9282 disadvantages to each approach.
9283
9284 The Itemfactory is much easier to use, and to add new menus to,
9285 although writing a few wrapper functions to create menus using the
9286 manual method could go a long way towards usability. With the
9287 Itemfactory, it is not possible to add images or the character '/' to
9288 the menus.
9289
9290 <!-- ----------------------------------------------------------------- -->
9291 <sect1>Manual Menu Creation
9292 <p>
9293 In the true tradition of teaching, we'll show you the hard way
9294 first. <tt>:)</>
9295
9296 There are three widgets that go into making a menubar and submenus:
9297 <itemize>
9298 <item>a menu item, which is what the user wants to select, e.g.,
9299 "Save"
9300 <item>a menu, which acts as a container for the menu items, and
9301 <item>a menubar, which is a container for each of the individual
9302 menus.
9303 </itemize>
9304
9305 This is slightly complicated by the fact that menu item widgets are
9306 used for two different things. They are both the widgets that are
9307 packed into the menu, and the widget that is packed into the menubar,
9308 which, when selected, activates the menu.
9309
9310 Let's look at the functions that are used to create menus and
9311 menubars.  This first function is used to create a new menubar.
9312
9313 <tscreen>
9314 <verb>
9315 GtkWidget *gtk_menu_bar_new( void );
9316 </verb>
9317 </tscreen>
9318
9319 This rather self explanatory function creates a new menubar. You use
9320 gtk_container_add to pack this into a window, or the box_pack
9321 functions to pack it into a box - the same as buttons.
9322
9323 <tscreen><verb>
9324 GtkWidget *gtk_menu_new( void );
9325 </verb></tscreen>
9326
9327 This function returns a pointer to a new menu; it is never actually
9328 shown (with gtk_widget_show), it is just a container for the menu
9329 items. I hope this will become more clear when you look at the
9330 example below.
9331
9332 The next two calls are used to create menu items that are packed into
9333 the menu (and menubar).
9334
9335 <tscreen><verb>
9336 GtkWidget *gtk_menu_item_new( void );
9337 </verb></tscreen>
9338
9339 and
9340
9341 <tscreen><verb>
9342 GtkWidget *gtk_menu_item_new_with_label( const char *label );
9343 </verb></tscreen>
9344
9345 These calls are used to create the menu items that are to be
9346 displayed.  Remember to differentiate between a "menu" as created with
9347 gtk_menu_new and a "menu item" as created by the gtk_menu_item_new
9348 functions. The menu item will be an actual button with an associated
9349 action, whereas a menu will be a container holding menu items.
9350
9351 The gtk_menu_new_with_label and gtk_menu_new functions are just as
9352 you'd expect after reading about the buttons. One creates a new menu
9353 item with a label already packed into it, and the other just creates a
9354 blank menu item.
9355
9356 Once you've created a menu item you have to put it into a menu. This
9357 is done using the function gtk_menu_append. In order to capture when
9358 the item is selected by the user, we need to connect to the
9359 <tt/activate/ signal in the usual way. So, if we wanted to create a
9360 standard <tt/File/ menu, with the options <tt/Open/, <tt/Save/, and
9361 <tt/Quit/, the code would look something like:
9362
9363 <tscreen><verb>
9364     file_menu = gtk_menu_new ();    /* Don't need to show menus */
9365
9366     /* Create the menu items */
9367     open_item = gtk_menu_item_new_with_label ("Open");
9368     save_item = gtk_menu_item_new_with_label ("Save");
9369     quit_item = gtk_menu_item_new_with_label ("Quit");
9370
9371     /* Add them to the menu */
9372     gtk_menu_append (GTK_MENU (file_menu), open_item);
9373     gtk_menu_append (GTK_MENU (file_menu), save_item);
9374     gtk_menu_append (GTK_MENU (file_menu), quit_item);
9375
9376     /* Attach the callback functions to the activate signal */
9377     gtk_signal_connect_object (GTK_OBJECT (open_items), "activate",
9378                                GTK_SIGNAL_FUNC (menuitem_response),
9379                                (gpointer) "file.open");
9380     gtk_signal_connect_object (GTK_OBJECT (save_items), "activate",
9381                                GTK_SIGNAL_FUNC (menuitem_response),
9382                                (gpointer) "file.save");
9383
9384     /* We can attach the Quit menu item to our exit function */
9385     gtk_signal_connect_object (GTK_OBJECT (quit_items), "activate",
9386                                GTK_SIGNAL_FUNC (destroy),
9387                                (gpointer) "file.quit");
9388
9389     /* We do need to show menu items */
9390     gtk_widget_show (open_item);
9391     gtk_widget_show (save_item);
9392     gtk_widget_show (quit_item);
9393 </verb></tscreen>
9394
9395 At this point we have our menu. Now we need to create a menubar and a
9396 menu item for the <tt/File/ entry, to which we add our menu. The code
9397 looks like this:
9398
9399 <tscreen><verb>
9400     menu_bar = gtk_menu_bar_new ();
9401     gtk_container_add (GTK_CONTAINER (window), menu_bar);
9402     gtk_widget_show (menu_bar);
9403
9404     file_item = gtk_menu_item_new_with_label ("File");
9405     gtk_widget_show (file_item);
9406 </verb></tscreen>
9407
9408 Now we need to associate the menu with <tt/file_item/. This is done
9409 with the function
9410
9411 <tscreen>
9412 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
9413                                 GtkWidget   *submenu );
9414 </tscreen>
9415
9416 So, our example would continue with
9417
9418 <tscreen><verb>
9419     gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_item), file_menu);
9420 </verb></tscreen>
9421
9422 All that is left to do is to add the menu to the menubar, which is
9423 accomplished using the function
9424
9425 <tscreen>
9426 void gtk_menu_bar_append( GtkMenuBar *menu_bar,
9427                           GtkWidget  *menu_item );
9428 </tscreen>
9429
9430 which in our case looks like this:
9431
9432 <tscreen><verb>
9433     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), file_item);
9434 </verb></tscreen>
9435
9436 If we wanted the menu right justified on the menubar, such as help
9437 menus often are, we can use the following function (again on
9438 <tt/file_item/ in the current example) before attaching it to the
9439 menubar.
9440
9441 <tscreen><verb>
9442 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
9443 </verb></tscreen>
9444
9445 Here is a summary of the steps needed to create a menu bar with menus
9446 attached:
9447
9448 <itemize>
9449 <item> Create a new menu using gtk_menu_new()
9450 <item> Use multiple calls to gtk_menu_item_new() for each item you
9451 wish to have on your menu. And use gtk_menu_append() to put each of
9452 these new items on to the menu.
9453 <item> Create a menu item using gtk_menu_item_new(). This will be the
9454 root of the menu, the text appearing here will be on the menubar
9455 itself.
9456 <item>Use gtk_menu_item_set_submenu() to attach the menu to the root
9457 menu item (the one created in the above step).
9458 <item> Create a new menubar using gtk_menu_bar_new. This step only
9459 needs to be done once when creating a series of menus on one menu bar.
9460 <item> Use gtk_menu_bar_append() to put the root menu onto the menubar.
9461 </itemize>
9462
9463 Creating a popup menu is nearly the same. The difference is that the
9464 menu is not posted "automatically" by a menubar, but explicitly by
9465 calling the function gtk_menu_popup() from a button-press event, for
9466 example.  Take these steps:
9467
9468 <itemize>
9469 <item>Create an event handling function. It needs to have the
9470 prototype
9471 <tscreen>
9472 static gint handler (GtkWidget *widget,
9473                      GdkEvent  *event);
9474 </tscreen>
9475 and it will use the event to find out where to pop up the menu.
9476 <item>In the event handler, if the event is a mouse button press,
9477 treat <tt>event</tt> as a button event (which it is) and use it as
9478 shown in the sample code to pass information to gtk_menu_popup().
9479 <item>Bind that event handler to a widget with
9480 <tscreen>
9481     gtk_signal_connect_object (GTK_OBJECT (widget), "event",
9482                                GTK_SIGNAL_FUNC (handler),
9483                                GTK_OBJECT (menu));
9484 </tscreen>
9485 where <tt>widget</tt> is the widget you are binding to,
9486 <tt>handler</tt> is the handling function, and <tt>menu</tt> is a menu
9487 created with gtk_menu_new(). This can be a menu which is also posted
9488 by a menu bar, as shown in the sample code.
9489 </itemize>
9490
9491 <!-- ----------------------------------------------------------------- -->
9492 <sect1>Manual Menu Example
9493 <p>
9494 That should about do it. Let's take a look at an example to help clarify.
9495
9496 <tscreen><verb>
9497 /* example-start menu menu.c */
9498
9499 #include <gtk/gtk.h>
9500
9501 static gint button_press (GtkWidget *, GdkEvent *);
9502 static void menuitem_response (gchar *);
9503
9504 int main( int   argc,
9505           char *argv[] )
9506 {
9507
9508     GtkWidget *window;
9509     GtkWidget *menu;
9510     GtkWidget *menu_bar;
9511     GtkWidget *root_menu;
9512     GtkWidget *menu_items;
9513     GtkWidget *vbox;
9514     GtkWidget *button;
9515     char buf[128];
9516     int i;
9517
9518     gtk_init (&amp;argc, &amp;argv);
9519
9520     /* create a new window */
9521     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9522     gtk_widget_set_usize (GTK_WIDGET (window), 200, 100);
9523     gtk_window_set_title (GTK_WINDOW (window), "GTK Menu Test");
9524     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
9525                         (GtkSignalFunc) gtk_main_quit, NULL);
9526
9527     /* Init the menu-widget, and remember -- never
9528      * gtk_show_widget() the menu widget!! 
9529      * This is the menu that holds the menu items, the one that
9530      * will pop up when you click on the "Root Menu" in the app */
9531     menu = gtk_menu_new ();
9532
9533     /* Next we make a little loop that makes three menu-entries for "test-menu".
9534      * Notice the call to gtk_menu_append.  Here we are adding a list of
9535      * menu items to our menu.  Normally, we'd also catch the "clicked"
9536      * signal on each of the menu items and setup a callback for it,
9537      * but it's omitted here to save space. */
9538
9539     for (i = 0; i < 3; i++)
9540         {
9541             /* Copy the names to the buf. */
9542             sprintf (buf, "Test-undermenu - %d", i);
9543
9544             /* Create a new menu-item with a name... */
9545             menu_items = gtk_menu_item_new_with_label (buf);
9546
9547             /* ...and add it to the menu. */
9548             gtk_menu_append (GTK_MENU (menu), menu_items);
9549
9550             /* Do something interesting when the menuitem is selected */
9551             gtk_signal_connect_object (GTK_OBJECT (menu_items), "activate",
9552                 GTK_SIGNAL_FUNC (menuitem_response), (gpointer) g_strdup (buf));
9553
9554             /* Show the widget */
9555             gtk_widget_show (menu_items);
9556         }
9557
9558     /* This is the root menu, and will be the label
9559      * displayed on the menu bar.  There won't be a signal handler attached,
9560      * as it only pops up the rest of the menu when pressed. */
9561     root_menu = gtk_menu_item_new_with_label ("Root Menu");
9562
9563     gtk_widget_show (root_menu);
9564
9565     /* Now we specify that we want our newly created "menu" to be the menu
9566      * for the "root menu" */
9567     gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu);
9568
9569     /* A vbox to put a menu and a button in: */
9570     vbox = gtk_vbox_new (FALSE, 0);
9571     gtk_container_add (GTK_CONTAINER (window), vbox);
9572     gtk_widget_show (vbox);
9573
9574     /* Create a menu-bar to hold the menus and add it to our main window */
9575     menu_bar = gtk_menu_bar_new ();
9576     gtk_box_pack_start (GTK_BOX (vbox), menu_bar, FALSE, FALSE, 2);
9577     gtk_widget_show (menu_bar);
9578
9579     /* Create a button to which to attach menu as a popup */
9580     button = gtk_button_new_with_label ("press me");
9581     gtk_signal_connect_object (GTK_OBJECT (button), "event",
9582         GTK_SIGNAL_FUNC (button_press), GTK_OBJECT (menu));
9583     gtk_box_pack_end (GTK_BOX (vbox), button, TRUE, TRUE, 2);
9584     gtk_widget_show (button);
9585
9586     /* And finally we append the menu-item to the menu-bar -- this is the
9587      * "root" menu-item I have been raving about =) */
9588     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), root_menu);
9589
9590     /* always display the window as the last step so it all splashes on
9591      * the screen at once. */
9592     gtk_widget_show (window);
9593
9594     gtk_main ();
9595
9596     return(0);
9597 }
9598
9599 /* Respond to a button-press by posting a menu passed in as widget.
9600  *
9601  * Note that the "widget" argument is the menu being posted, NOT
9602  * the button that was pressed.
9603  */
9604
9605 static gint button_press (GtkWidget *widget, GdkEvent *event)
9606 {
9607
9608     if (event->type == GDK_BUTTON_PRESS) {
9609         GdkEventButton *bevent = (GdkEventButton *) event; 
9610         gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
9611                         bevent->button, bevent->time);
9612         /* Tell calling code that we have handled this event; the buck
9613          * stops here. */
9614         return TRUE;
9615     }
9616
9617     /* Tell calling code that we have not handled this event; pass it on. */
9618     return FALSE;
9619 }
9620
9621
9622 /* Print a string when a menu item is selected */
9623
9624 static void menuitem_response (gchar *string)
9625 {
9626     printf ("%s\n", string);
9627 }
9628 /* example-end */
9629 </verb></tscreen>
9630
9631 You may also set a menu item to be insensitive and, using an accelerator
9632 table, bind keys to menu functions.
9633
9634 <!-- ----------------------------------------------------------------- -->
9635 <sect1>Using ItemFactory
9636 <p>
9637 Now that we've shown you the hard way, here's how you do it using the
9638 gtk_item_factory calls.
9639
9640 <!-- ----------------------------------------------------------------- -->
9641 <sect1>Item Factory Example
9642 <p>
9643 Here is an example using the GTK item factory.
9644
9645 <tscreen><verb>
9646 /* example-start menu itemfactory.c */
9647
9648 #include <gtk/gtk.h>
9649 #include <strings.h>
9650
9651 /* Obligatory basic callback */
9652 static void print_hello( GtkWidget *w,
9653                          gpointer   data )
9654 {
9655   g_message ("Hello, World!\n");
9656 }
9657
9658 /* This is the GtkItemFactoryEntry structure used to generate new menus.
9659    Item 1: The menu path. The letter after the underscore indicates an
9660            accelerator key once the menu is open.
9661    Item 2: The accelerator key for the entry
9662    Item 3: The callback function.
9663    Item 4: The callback action.  This changes the parameters with
9664            which the function is called.  The default is 0.
9665    Item 5: The item type, used to define what kind of an item it is.
9666            Here are the possible values:
9667
9668            NULL               -> "<Item>"
9669            ""                 -> "<Item>"
9670            "<Title>"          -> create a title item
9671            "<Item>"           -> create a simple item
9672            "<CheckItem>"      -> create a check item
9673            "<ToggleItem>"     -> create a toggle item
9674            "<RadioItem>"      -> create a radio item
9675            <path>             -> path of a radio item to link against
9676            "<Separator>"      -> create a separator
9677            "<Branch>"         -> create an item to hold sub items (optional)
9678            "<LastBranch>"     -> create a right justified branch 
9679 */
9680
9681 static GtkItemFactoryEntry menu_items[] = {
9682   { "/_File",         NULL,         NULL, 0, "<Branch>" },
9683   { "/File/_New",     "<control>N", print_hello, 0, NULL },
9684   { "/File/_Open",    "<control>O", print_hello, 0, NULL },
9685   { "/File/_Save",    "<control>S", print_hello, 0, NULL },
9686   { "/File/Save _As", NULL,         NULL, 0, NULL },
9687   { "/File/sep1",     NULL,         NULL, 0, "<Separator>" },
9688   { "/File/Quit",     "<control>Q", gtk_main_quit, 0, NULL },
9689   { "/_Options",      NULL,         NULL, 0, "<Branch>" },
9690   { "/Options/Test",  NULL,         NULL, 0, NULL },
9691   { "/_Help",         NULL,         NULL, 0, "<LastBranch>" },
9692   { "/_Help/About",   NULL,         NULL, 0, NULL },
9693 };
9694
9695
9696 void get_main_menu( GtkWidget  *window,
9697                     GtkWidget **menubar )
9698 {
9699   GtkItemFactory *item_factory;
9700   GtkAccelGroup *accel_group;
9701   gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
9702
9703   accel_group = gtk_accel_group_new ();
9704
9705   /* This function initializes the item factory.
9706      Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
9707               or GTK_TYPE_OPTION_MENU.
9708      Param 2: The path of the menu.
9709      Param 3: A pointer to a gtk_accel_group.  The item factory sets up
9710               the accelerator table while generating menus.
9711   */
9712
9713   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", 
9714                                        accel_group);
9715
9716   /* This function generates the menu items. Pass the item factory,
9717      the number of items in the array, the array itself, and any
9718      callback data for the the menu items. */
9719   gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
9720
9721   /* Attach the new accelerator group to the window. */
9722   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
9723
9724   if (menubar)
9725     /* Finally, return the actual menu bar created by the item factory. */ 
9726     *menubar = gtk_item_factory_get_widget (item_factory, "<main>");
9727 }
9728
9729 int main( int argc,
9730           char *argv[] )
9731 {
9732   GtkWidget *window;
9733   GtkWidget *main_vbox;
9734   GtkWidget *menubar;
9735   
9736   gtk_init (&amp;argc, &amp;argv);
9737   
9738   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9739   gtk_signal_connect (GTK_OBJECT (window), "destroy", 
9740                       GTK_SIGNAL_FUNC (gtk_main_quit), 
9741                       "WM destroy");
9742   gtk_window_set_title (GTK_WINDOW(window), "Item Factory");
9743   gtk_widget_set_usize (GTK_WIDGET(window), 300, 200);
9744   
9745   main_vbox = gtk_vbox_new (FALSE, 1);
9746   gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
9747   gtk_container_add (GTK_CONTAINER (window), main_vbox);
9748   gtk_widget_show (main_vbox);
9749   
9750   get_main_menu (window, &amp;menubar);
9751   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
9752   gtk_widget_show (menubar);
9753   
9754   gtk_widget_show (window);
9755   gtk_main ();
9756   
9757   return(0);
9758 }
9759 /* example-end */
9760 </verb></tscreen>
9761
9762
9763 For now, there's only this example. An explanation and lots 'o' comments
9764 will follow later.
9765
9766 <!-- ***************************************************************** -->
9767 <sect> Text Widget
9768 <!-- ***************************************************************** -->
9769 <p>
9770 The Text widget allows multiple lines of text to be displayed and
9771 edited. It supports both multi-colored and multi-font text, allowing
9772 them to be mixed in any way we wish. It also has a wide set of key
9773 based text editing commands, which are compatible with Emacs.
9774
9775 The text widget supports full cut-and-paste facilities, including the
9776 use of double- and triple-click to select a word and a whole line,
9777 respectively.
9778
9779 <!-- ----------------------------------------------------------------- -->
9780 <sect1>Creating and Configuring a Text box
9781 <p>
9782 There is only one function for creating a new Text widget.
9783
9784 <tscreen><verb>
9785 GtkWidget *gtk_text_new( GtkAdjustment *hadj,
9786                          GtkAdjustment *vadj );
9787 </verb></tscreen>
9788
9789 The arguments allow us to give the Text widget pointers to Adjustments
9790 that can be used to track the viewing position of the widget. Passing
9791 NULL values to either or both of these arguments will cause the
9792 gtk_text_new function to create its own.
9793
9794 <tscreen><verb>
9795 void gtk_text_set_adjustments( GtkText       *text,
9796                                GtkAdjustment *hadj,
9797                                GtkAdjustment *vadj );
9798 </verb></tscreen>
9799
9800 The above function allows the horizontal and vertical adjustments of a
9801 text widget to be changed at any time.
9802
9803 The text widget will not automatically create its own scrollbars when
9804 the amount of text to be displayed is too long for the display
9805 window. We therefore have to create and add them to the display layout
9806 ourselves.
9807
9808 <tscreen><verb>
9809   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
9810   gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
9811   gtk_widget_show (vscrollbar);
9812 </verb></tscreen>
9813
9814 The above code snippet creates a new vertical scrollbar, and attaches
9815 it to the vertical adjustment of the text widget, <tt/text/. It then
9816 packs it into a box in the normal way.
9817
9818 Note, currently the Text widget does not support horizontal
9819 scrollbars.
9820
9821 There are two main ways in which a Text widget can be used: to allow
9822 the user to edit a body of text, or to allow us to display multiple
9823 lines of text to the user. In order for us to switch between these
9824 modes of operation, the text widget has the following function:
9825
9826 <tscreen><verb>
9827 void gtk_text_set_editable( GtkText *text,
9828                             gint     editable );
9829 </verb></tscreen>
9830
9831 The <tt/editable/ argument is a TRUE or FALSE value that specifies
9832 whether the user is permitted to edit the contents of the Text
9833 widget. When the text widget is editable, it will display a cursor at
9834 the current insertion point.
9835
9836 You are not, however, restricted to just using the text widget in
9837 these two modes. You can toggle the editable state of the text widget
9838 at any time, and can insert text at any time.
9839
9840 The text widget wraps lines of text that are too long to fit onto a
9841 single line of the display window. Its default behaviour is to break
9842 words across line breaks. This can be changed using the next function:
9843
9844 <tscreen><verb>
9845 void gtk_text_set_word_wrap( GtkText *text,
9846                              gint     word_wrap );
9847 </verb></tscreen>
9848
9849 Using this function allows us to specify that the text widget should
9850 wrap long lines on word boundaries. The <tt/word_wrap/ argument is a
9851 TRUE or FALSE value.
9852
9853 <!-- ----------------------------------------------------------------- -->
9854 <sect1>Text Manipulation
9855 <P>
9856 The current insertion point of a Text widget can be set using
9857 <tscreen><verb>
9858 void gtk_text_set_point( GtkText *text,
9859                          guint    index );
9860 </verb></tscreen>
9861
9862 where <tt/index/ is the position to set the insertion point.
9863
9864 Analogous to this is the function for getting the current insertion
9865 point:
9866
9867 <tscreen><verb>
9868 guint gtk_text_get_point( GtkText *text );
9869 </verb></tscreen>
9870
9871 A function that is useful in combination with the above two functions
9872 is
9873
9874 <tscreen><verb>
9875 guint gtk_text_get_length( GtkText *text );
9876 </verb></tscreen>
9877
9878 which returns the current length of the Text widget. The length is the
9879 number of characters that are within the text block of the widget,
9880 including characters such as newline, which marks the end of
9881 lines.
9882
9883 In order to insert text at the current insertion point of a Text
9884 widget, the function gtk_text_insert is used, which also allows us to
9885 specify background and foreground colors and a font for the text.
9886
9887 <tscreen><verb>
9888 void gtk_text_insert( GtkText    *text,
9889                       GdkFont    *font,
9890                       GdkColor   *fore,
9891                       GdkColor   *back,
9892                       const char *chars,
9893                       gint        length );
9894 </verb></tscreen>
9895
9896 Passing a value of <tt/NULL/ in as the value for the foreground color,
9897 background color or font will result in the values set within the
9898 widget style to be used. Using a value of <tt/-1/ for the length
9899 parameter will result in the whole of the text string given being
9900 inserted.
9901
9902 The text widget is one of the few within GTK that redraws itself
9903 dynamically, outside of the gtk_main function. This means that all
9904 changes to the contents of the text widget take effect
9905 immediately. This may be undesirable when performing multiple changes
9906 to the text widget. In order to allow us to perform multiple updates
9907 to the text widget without it continuously redrawing, we can freeze
9908 the widget, which temporarily stops it from automatically redrawing
9909 itself every time it is changed. We can then thaw the widget after our
9910 updates are complete.
9911
9912 The following two functions perform this freeze and thaw action:
9913
9914 <tscreen><verb>
9915 void gtk_text_freeze( GtkText *text );
9916
9917 void gtk_text_thaw( GtkText *text );         
9918 </verb></tscreen>
9919
9920 Text is deleted from the text widget relative to the current insertion
9921 point by the following two functions. The return value is a TRUE or
9922 FALSE indicator of whether the operation was successful.
9923
9924 <tscreen><verb>
9925 gint gtk_text_backward_delete( GtkText *text,
9926                                guint    nchars );
9927
9928 gint gtk_text_forward_delete ( GtkText *text,
9929                                guint    nchars );
9930 </verb></tscreen>
9931
9932 If you want to retrieve the contents of the text widget, then the
9933 macro <tt/GTK_TEXT_INDEX(t, index)/ allows you to retrieve the
9934 character at position <tt/index/ within the text widget <tt/t/.
9935
9936 To retrieve larger blocks of text, we can use the function
9937
9938 <tscreen><verb>
9939 gchar *gtk_editable_get_chars( GtkEditable *editable,
9940                                gint         start_pos,
9941                                gint         end_pos );   
9942 </verb></tscreen>
9943
9944 This is a function of the parent class of the text widget. A value of
9945 -1 as <tt/end_pos/ signifies the end of the text. The index of the
9946 text starts at 0.
9947
9948 The function allocates a new chunk of memory for the text block, so
9949 don't forget to free it with a call to g_free when you have finished
9950 with it.
9951  
9952 <!-- ----------------------------------------------------------------- -->
9953 <sect1>Keyboard Shortcuts
9954 <p>
9955 The text widget has a number of pre-installed keyboard shortcuts for
9956 common editing, motion and selection functions. These are accessed
9957 using Control and Alt key combinations.
9958
9959 In addition to these, holding down the Control key whilst using cursor
9960 key movement will move the cursor by words rather than
9961 characters. Holding down Shift whilst using cursor movement will
9962 extend the selection.
9963
9964 <sect2>Motion Shortcuts
9965 <p>
9966 <itemize>
9967 <item> Ctrl-A   Beginning of line
9968 <item> Ctrl-E   End of line
9969 <item> Ctrl-N   Next Line
9970 <item> Ctrl-P   Previous Line
9971 <item> Ctrl-B   Backward one character
9972 <item> Ctrl-F   Forward one character
9973 <item> Alt-B    Backward one word
9974 <item> Alt-F    Forward one word
9975 </itemize>
9976
9977 <sect2>Editing Shortcuts
9978 <p>
9979 <itemize>
9980 <item> Ctrl-H   Delete Backward Character (Backspace)
9981 <item> Ctrl-D   Delete Forward Character (Delete)
9982 <item> Ctrl-W   Delete Backward Word
9983 <item> Alt-D    Delete Forward Word
9984 <item> Ctrl-K   Delete to end of line
9985 <item> Ctrl-U   Delete line
9986 </itemize>
9987
9988 <sect2>Selection Shortcuts
9989 <p>
9990 <itemize>
9991 <item> Ctrl-X   Cut to clipboard
9992 <item> Ctrl-C   Copy to clipboard
9993 <item> Ctrl-V   Paste from clipboard
9994 </itemize>
9995
9996 <!-- ----------------------------------------------------------------- -->
9997 <sect1>A GtkText Example
9998 <p>
9999 <tscreen><verb>
10000 /* example-start text text.c */
10001
10002 /* text.c */
10003
10004 #include <stdio.h>
10005 #include <gtk/gtk.h>
10006
10007 void text_toggle_editable (GtkWidget *checkbutton,
10008                            GtkWidget *text)
10009 {
10010   gtk_text_set_editable(GTK_TEXT(text),
10011                         GTK_TOGGLE_BUTTON(checkbutton)->active);
10012 }
10013
10014 void text_toggle_word_wrap (GtkWidget *checkbutton,
10015                             GtkWidget *text)
10016 {
10017   gtk_text_set_word_wrap(GTK_TEXT(text),
10018                          GTK_TOGGLE_BUTTON(checkbutton)->active);
10019 }
10020
10021 void close_application( GtkWidget *widget, gpointer data )
10022 {
10023        gtk_main_quit();
10024 }
10025
10026 int main (int argc, char *argv[])
10027 {
10028   GtkWidget *window;
10029   GtkWidget *box1;
10030   GtkWidget *box2;
10031   GtkWidget *hbox;
10032   GtkWidget *button;
10033   GtkWidget *check;
10034   GtkWidget *separator;
10035   GtkWidget *table;
10036   GtkWidget *vscrollbar;
10037   GtkWidget *text;
10038   GdkColormap *cmap;
10039   GdkColor color;
10040   GdkFont *fixed_font;
10041
10042   FILE *infile;
10043
10044   gtk_init (&amp;argc, &amp;argv);
10045  
10046   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10047   gtk_widget_set_usize (window, 600, 500);
10048   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);  
10049   gtk_signal_connect (GTK_OBJECT (window), "destroy",
10050                       GTK_SIGNAL_FUNC(close_application),
10051                       NULL);
10052   gtk_window_set_title (GTK_WINDOW (window), "Text Widget Example");
10053   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10054   
10055   
10056   box1 = gtk_vbox_new (FALSE, 0);
10057   gtk_container_add (GTK_CONTAINER (window), box1);
10058   gtk_widget_show (box1);
10059   
10060   
10061   box2 = gtk_vbox_new (FALSE, 10);
10062   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10063   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
10064   gtk_widget_show (box2);
10065   
10066   
10067   table = gtk_table_new (2, 2, FALSE);
10068   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
10069   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
10070   gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
10071   gtk_widget_show (table);
10072   
10073   /* Create the GtkText widget */
10074   text = gtk_text_new (NULL, NULL);
10075   gtk_text_set_editable (GTK_TEXT (text), TRUE);
10076   gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
10077                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
10078                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
10079   gtk_widget_show (text);
10080
10081   /* Add a vertical scrollbar to the GtkText widget */
10082   vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
10083   gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
10084                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
10085   gtk_widget_show (vscrollbar);
10086
10087   /* Get the system color map and allocate the color red */
10088   cmap = gdk_colormap_get_system();
10089   color.red = 0xffff;
10090   color.green = 0;
10091   color.blue = 0;
10092   if (!gdk_color_alloc(cmap, &amp;color)) {
10093     g_error("couldn't allocate color");
10094   }
10095
10096   /* Load a fixed font */
10097   fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");
10098
10099   /* Realizing a widget creates a window for it,
10100    * ready for us to insert some text */
10101   gtk_widget_realize (text);
10102
10103   /* Freeze the text widget, ready for multiple updates */
10104   gtk_text_freeze (GTK_TEXT (text));
10105   
10106   /* Insert some colored text */
10107   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
10108                    "Supports ", -1);
10109   gtk_text_insert (GTK_TEXT (text), NULL, &amp;color, NULL,
10110                    "colored ", -1);
10111   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
10112                    "text and different ", -1);
10113   gtk_text_insert (GTK_TEXT (text), fixed_font, &amp;text->style->black, NULL,
10114                    "fonts\n\n", -1);
10115   
10116   /* Load the file text.c into the text window */
10117
10118   infile = fopen("text.c", "r");
10119   
10120   if (infile) {
10121     char buffer[1024];
10122     int nchars;
10123     
10124     while (1)
10125       {
10126         nchars = fread(buffer, 1, 1024, infile);
10127         gtk_text_insert (GTK_TEXT (text), fixed_font, NULL,
10128                          NULL, buffer, nchars);
10129         
10130         if (nchars < 1024)
10131           break;
10132       }
10133     
10134     fclose (infile);
10135   }
10136
10137   /* Thaw the text widget, allowing the updates to become visible */  
10138   gtk_text_thaw (GTK_TEXT (text));
10139   
10140   hbox = gtk_hbutton_box_new ();
10141   gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
10142   gtk_widget_show (hbox);
10143
10144   check = gtk_check_button_new_with_label("Editable");
10145   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
10146   gtk_signal_connect (GTK_OBJECT(check), "toggled",
10147                       GTK_SIGNAL_FUNC(text_toggle_editable), text);
10148   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
10149   gtk_widget_show (check);
10150   check = gtk_check_button_new_with_label("Wrap Words");
10151   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
10152   gtk_signal_connect (GTK_OBJECT(check), "toggled",
10153                       GTK_SIGNAL_FUNC(text_toggle_word_wrap), text);
10154   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
10155   gtk_widget_show (check);
10156
10157   separator = gtk_hseparator_new ();
10158   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10159   gtk_widget_show (separator);
10160
10161   box2 = gtk_vbox_new (FALSE, 10);
10162   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10163   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10164   gtk_widget_show (box2);
10165   
10166   button = gtk_button_new_with_label ("close");
10167   gtk_signal_connect (GTK_OBJECT (button), "clicked",
10168                       GTK_SIGNAL_FUNC(close_application),
10169                       NULL);
10170   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10171   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
10172   gtk_widget_grab_default (button);
10173   gtk_widget_show (button);
10174
10175   gtk_widget_show (window);
10176
10177   gtk_main ();
10178   
10179   return(0);       
10180 }
10181 /* example-end */
10182 </verb></tscreen>
10183
10184
10185 <!-- ***************************************************************** -->
10186 <sect> Undocumented Widgets
10187 <!-- ***************************************************************** -->
10188 <p>
10189 These all require authors! :) Please consider contributing to our
10190 tutorial.
10191
10192 If you must use one of these widgets that are undocumented, I strongly
10193 suggest you take a look at their respective header files in the GTK
10194 distribution. GTK's function names are very descriptive. Once you
10195 have an understanding of how things work, it's not difficult to figure
10196 out how to use a widget simply by looking at its function
10197 declarations. This, along with a few examples from others' code, and
10198 it should be no problem.
10199
10200 When you do come to understand all the functions of a new undocumented
10201 widget, please consider writing a tutorial on it so others may benefit
10202 from your time.
10203
10204 <!-- ----------------------------------------------------------------- -->
10205 <sect1> Calendar
10206 <p>
10207 <!-- ----------------------------------------------------------------- -->
10208 <sect1> CTree
10209 <p>
10210 <!-- ----------------------------------------------------------------- -->
10211 <sect1> Curves
10212 <p>
10213 <!-- ----------------------------------------------------------------- -->
10214 <sect1> Drawing Area
10215 <p>
10216 <!-- ----------------------------------------------------------------- -->
10217 <sect1> Font Selection Dialog
10218 <p>
10219 <!-- ----------------------------------------------------------------- -->
10220 <sect1> Gamma Curve
10221 <p>
10222 <!-- ----------------------------------------------------------------- -->
10223 <sect1> Image
10224 <p>
10225 <!-- ----------------------------------------------------------------- -->
10226 <sect1> Packer
10227 <p>
10228 <!-- ----------------------------------------------------------------- -->
10229 <sect1> Plugs and Sockets
10230 <p>
10231 <!-- ----------------------------------------------------------------- -->
10232 <sect1> Preview
10233 <p>
10234
10235 <!--
10236
10237 (This may need to be rewritten to follow the style of the rest of the tutorial)
10238
10239 <tscreen><verb>
10240
10241 Previews serve a number of purposes in GIMP/GTK. The most important one is
10242 this. High quality images may take up to tens of megabytes of memory - easily!
10243 Any operation on an image that big is bound to take a long time. If it takes
10244 you 5-10 trial-and-errors (i.e., 10-20 steps, since you have to revert after
10245 you make an error) to choose the desired modification, it make take you
10246 literally hours to make the right one - if you don't run out of memory
10247 first. People who have spent hours in color darkrooms know the feeling.
10248 Previews to the rescue!
10249
10250 But the annoyance of the delay is not the only issue. Oftentimes it is
10251 helpful to compare the Before and After versions side-by-side or at least
10252 back-to-back. If you're working with big images and 10 second delays,
10253 obtaining the Before and After impressions is, to say the least, difficult.
10254 For 30M images (4"x6", 600dpi, 24 bit) the side-by-side comparison is right
10255 out for most people, while back-to-back is more like back-to-1001, 1002,
10256 ..., 1010-back! Previews to the rescue!
10257
10258 But there's more. Previews allow for side-by-side pre-previews. In other
10259 words, you write a plug-in (e.g., the filterpack simulation) which would have
10260 a number of here's-what-it-would-look-like-if-you-were-to-do-this previews.
10261 An approach like this acts as a sort of a preview palette and is very
10262 effective for subtle changes. Let's go previews!
10263
10264 There's more. For certain plug-ins real-time image-specific human
10265 intervention maybe necessary. In the SuperNova plug-in, for example, the
10266 user is asked to enter the coordinates of the center of the future
10267 supernova. The easiest way to do this, really, is to present the user with a
10268 preview and ask him to interactively select the spot. Let's go previews!
10269
10270 Finally, a couple of misc uses. One can use previews even when not working
10271 with big images. For example, they are useful when rendering complicated
10272 patterns. (Just check out the venerable Diffraction plug-in + many other
10273 ones!) As another example, take a look at the colormap rotation plug-in
10274 (work in progress). You can also use previews for little logos inside you
10275 plug-ins and even for an image of yourself, The Author. Let's go previews!
10276
10277 When Not to Use Previews
10278
10279 Don't use previews for graphs, drawing, etc. GDK is much faster for that. Use
10280 previews only for rendered images!
10281
10282 Let's go previews!
10283
10284 You can stick a preview into just about anything. In a vbox, an hbox, a
10285 table, a button, etc. But they look their best in tight frames around them.
10286 Previews by themselves do not have borders and look flat without them. (Of
10287 course, if the flat look is what you want...) Tight frames provide the
10288 necessary borders.
10289
10290                                [Image][Image]
10291
10292 Previews in many ways are like any other widgets in GTK (whatever that
10293 means) except they possess an additional feature: they need to be filled with
10294 some sort of an image! First, we will deal exclusively with the GTK aspect
10295 of previews and then we'll discuss how to fill them.
10296
10297 GtkWidget *preview!
10298
10299 Without any ado:
10300
10301                               /* Create a preview widget,
10302                               set its size, an show it */
10303 GtkWidget *preview;
10304 preview=gtk_preview_new(GTK_PREVIEW_COLOR)
10305                               /*Other option:
10306                               GTK_PREVIEW_GRAYSCALE);*/
10307 gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT);
10308 gtk_widget_show(preview);
10309 my_preview_rendering_function(preview);
10310
10311 Oh yeah, like I said, previews look good inside frames, so how about:
10312
10313 GtkWidget *create_a_preview(int        Width,
10314                             int        Height,
10315                             int        Colorfulness)
10316 {
10317   GtkWidget *preview;
10318   GtkWidget *frame;
10319   
10320   frame = gtk_frame_new(NULL);
10321   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
10322   gtk_container_set_border_width (GTK_CONTAINER(frame),0);
10323   gtk_widget_show(frame);
10324
10325   preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR
10326                                        :GTK_PREVIEW_GRAYSCALE);
10327   gtk_preview_size (GTK_PREVIEW (preview), Width, Height);
10328   gtk_container_add(GTK_CONTAINER(frame),preview);
10329   gtk_widget_show(preview);
10330
10331   my_preview_rendering_function(preview);
10332   return frame;
10333 }
10334
10335 That's my basic preview. This routine returns the "parent" frame so you can
10336 place it somewhere else in your interface. Of course, you can pass the
10337 parent frame to this routine as a parameter. In many situations, however,
10338 the contents of the preview are changed continually by your application. In
10339 this case you may want to pass a pointer to the preview to a
10340 "create_a_preview()" and thus have control of it later.
10341
10342 One more important note that may one day save you a lot of time. Sometimes
10343 it is desirable to label you preview. For example, you may label the preview
10344 containing the original image as "Original" and the one containing the
10345 modified image as "Less Original". It might occur to you to pack the
10346 preview along with the appropriate label into a vbox. The unexpected caveat
10347 is that if the label is wider than the preview (which may happen for a
10348 variety of reasons unforseeable to you, from the dynamic decision on the
10349 size of the preview to the size of the font) the frame expands and no longer
10350 fits tightly over the preview. The same problem can probably arise in other
10351 situations as well.
10352
10353                                    [Image]
10354
10355 The solution is to place the preview and the label into a 2x1 table and by
10356 attaching them with the following parameters (this is one possible variations
10357 of course. The key is no GTK_FILL in the second attachment):
10358
10359 gtk_table_attach(GTK_TABLE(table),label,0,1,0,1,
10360                  0,
10361                  GTK_EXPAND|GTK_FILL,
10362                  0,0);
10363 gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2,
10364                  GTK_EXPAND,
10365                  GTK_EXPAND,
10366                  0,0);
10367
10368
10369 And here's the result:
10370
10371                                    [Image]
10372
10373 Misc
10374
10375 Making a preview clickable is achieved most easily by placing it in a
10376 button. It also adds a nice border around the preview and you may not even
10377 need to place it in a frame. See the Filter Pack Simulation plug-in for an
10378 example.
10379
10380 This is pretty much it as far as GTK is concerned.
10381
10382 Filling In a Preview
10383
10384 In order to familiarize ourselves with the basics of filling in previews,
10385 let's create the following pattern (contrived by trial and error):
10386
10387                                    [Image]
10388
10389 void
10390 my_preview_rendering_function(GtkWidget     *preview)
10391 {
10392 #define SIZE 100
10393 #define HALF (SIZE/2)
10394
10395   guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */
10396   gint i, j;                             /* Coordinates    */
10397   double r, alpha, x, y;
10398
10399   if (preview==NULL) return; /* I usually add this when I want */
10400                              /* to avoid silly crashes. You    */
10401                              /* should probably make sure that */
10402                              /* everything has been nicely     */
10403                              /* initialized!                   */
10404   for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape?  */
10405                                          /* glib.h contains ABS(x).   */
10406         row[i*3+0] = sqrt(1-r)*255;      /* Define Red                */
10407         row[i*3+1] = 128;                /* Define Green              */
10408         row[i*3+2] = 224;                /* Define Blue               */
10409       }                                  /* "+0" is for alignment!    */
10410       else {
10411         row[i*3+0] = r*255;
10412         row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255;
10413         row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255;
10414       }
10415     }
10416     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE);
10417     /* Insert "row" into "preview" starting at the point with  */
10418     /* coordinates (0,j) first column, j_th row extending SIZE */
10419     /* pixels to the right */
10420   }
10421
10422   free(row); /* save some space */
10423   gtk_widget_draw(preview,NULL); /* what does this do? */
10424   gdk_flush(); /* or this? */
10425 }
10426
10427 Non-GIMP users can have probably seen enough to do a lot of things already.
10428 For the GIMP users I have a few pointers to add.
10429
10430 Image Preview
10431
10432 It is probably wise to keep a reduced version of the image around with just
10433 enough pixels to fill the preview. This is done by selecting every n'th
10434 pixel where n is the ratio of the size of the image to the size of the
10435 preview. All further operations (including filling in the previews) are then
10436 performed on the reduced number of pixels only. The following is my
10437 implementation of reducing the image. (Keep in mind that I've had only basic
10438 C!)
10439
10440 (UNTESTED CODE ALERT!!!)
10441
10442 typedef struct {
10443   gint      width;
10444   gint      height;
10445   gint      bbp;
10446   guchar    *rgb;
10447   guchar    *mask;
10448 } ReducedImage;
10449
10450 enum {
10451   SELECTION_ONLY,
10452   SELECTION_IN_CONTEXT,
10453   ENTIRE_IMAGE
10454 };
10455
10456 ReducedImage *Reduce_The_Image(GDrawable *drawable,
10457                                GDrawable *mask,
10458                                gint LongerSize,
10459                                gint Selection)
10460 {
10461   /* This function reduced the image down to the the selected preview size */
10462   /* The preview size is determine by LongerSize, i.e., the greater of the  */
10463   /* two dimensions. Works for RGB images only!                            */
10464   gint RH, RW;          /* Reduced height and reduced width                */
10465   gint width, height;   /* Width and Height of the area being reduced      */
10466   gint bytes=drawable->bpp;
10467   ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage));
10468
10469   guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B;
10470   gint i, j, whichcol, whichrow, x1, x2, y1, y2;
10471   GPixelRgn srcPR, srcMask;
10472   gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire  */
10473                              /* image.                                     */
10474
10475   gimp_drawable_mask_bounds (drawable->id, &amp;x1, &amp;y1, &amp;x2, &amp;y2);
10476   width  = x2-x1;
10477   height = y2-y1;
10478   /* If there's a SELECTION, we got its bounds!)
10479
10480   if (width != drawable->width &amp;&amp; height != drawable->height)
10481     NoSelectionMade=FALSE;
10482   /* Become aware of whether the user has made an active selection   */
10483   /* This will become important later, when creating a reduced mask. */
10484
10485   /* If we want to preview the entire image, overrule the above!  */
10486   /* Of course, if no selection has been made, this does nothing! */
10487   if (Selection==ENTIRE_IMAGE) {
10488     x1=0;
10489     x2=drawable->width;
10490     y1=0;
10491     y2=drawable->height;
10492   }
10493
10494   /* If we want to preview a selection with some surrounding area we */
10495   /* have to expand it a little bit. Consider it a bit of a riddle. */
10496   if (Selection==SELECTION_IN_CONTEXT) {
10497     x1=MAX(0,                x1-width/2.0);
10498     x2=MIN(drawable->width,  x2+width/2.0);
10499     y1=MAX(0,                y1-height/2.0);
10500     y2=MIN(drawable->height, y2+height/2.0);
10501   }
10502
10503   /* How we can determine the width and the height of the area being */
10504   /* reduced.                                                        */
10505   width  = x2-x1;
10506   height = y2-y1;
10507
10508   /* The lines below determine which dimension is to be the longer   */
10509   /* side. The idea borrowed from the supernova plug-in. I suspect I */
10510   /* could've thought of it myself, but the truth must be told.      */
10511   /* Plagiarism stinks!                                               */
10512   if (width>height) {
10513     RW=LongerSize;
10514     RH=(float) height * (float) LongerSize/ (float) width;
10515   }
10516   else {
10517     RH=LongerSize;
10518     RW=(float)width * (float) LongerSize/ (float) height;
10519   }
10520
10521   /* The entire image is stretched into a string! */
10522   tempRGB   = (guchar *) malloc(RW*RH*bytes);
10523   tempmask  = (guchar *) malloc(RW*RH);
10524
10525   gimp_pixel_rgn_init (&amp;srcPR, drawable, x1, y1, width, height,
10526                        FALSE, FALSE);
10527   gimp_pixel_rgn_init (&amp;srcMask, mask, x1, y1, width, height,
10528                        FALSE, FALSE);
10529
10530   /* Grab enough to save a row of image and a row of mask. */
10531   src_row       = (guchar *) malloc (width*bytes);
10532   src_mask_row  = (guchar *) malloc (width);
10533
10534   for (i=0; i < RH; i++) {
10535     whichrow=(float)i*(float)height/(float)RH;
10536     gimp_pixel_rgn_get_row (&amp;srcPR, src_row, x1, y1+whichrow, width);
10537     gimp_pixel_rgn_get_row (&amp;srcMask, src_mask_row, x1, y1+whichrow, width);
10538
10539     for (j=0; j < RW; j++) {
10540       whichcol=(float)j*(float)width/(float)RW;
10541
10542       /* No selection made = each point is completely selected! */
10543       if (NoSelectionMade)
10544         tempmask[i*RW+j]=255;
10545       else
10546         tempmask[i*RW+j]=src_mask_row[whichcol];
10547
10548       /* Add the row to the one long string which now contains the image! */
10549       tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0];
10550       tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1];
10551       tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2];
10552
10553       /* Hold on to the alpha as well */
10554       if (bytes==4)
10555         tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3];
10556     }
10557   }
10558   temp->bpp=bytes;
10559   temp->width=RW;
10560   temp->height=RH;
10561   temp->rgb=tempRGB;
10562   temp->mask=tempmask;
10563   return temp;
10564 }
10565
10566 The following is a preview function which used the same ReducedImage type!
10567 Note that it uses fakes transparency (if one is present by means of
10568 fake_transparency which is defined as follows:
10569
10570 gint fake_transparency(gint i, gint j)
10571 {
10572   if ( ((i%20)- 10) * ((j%20)- 10)>0   )
10573     return 64;
10574   else
10575     return 196;
10576 }
10577
10578 Now here's the preview function:
10579
10580 void
10581 my_preview_render_function(GtkWidget     *preview,
10582                            gint          changewhat,
10583                            gint          changewhich)
10584 {
10585   gint Inten, bytes=drawable->bpp;
10586   gint i, j, k;
10587   float partial;
10588   gint RW=reduced->width;
10589   gint RH=reduced->height;
10590   guchar *row=malloc(bytes*RW);;
10591
10592
10593   for (i=0; i < RH; i++) {
10594     for (j=0; j < RW; j++) {
10595
10596       row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0];
10597       row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1];
10598       row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2];
10599
10600       if (bytes==4)
10601         for (k=0; k<3; k++) {
10602           float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0;
10603           row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j);
10604         }
10605     }
10606     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW);
10607   }
10608
10609   free(a);
10610   gtk_widget_draw(preview,NULL);
10611   gdk_flush();
10612 }
10613
10614 Applicable Routines
10615
10616 guint           gtk_preview_get_type           (void);
10617 /* No idea */
10618 void            gtk_preview_uninit             (void);
10619 /* No idea */
10620 GtkWidget*      gtk_preview_new                (GtkPreviewType   type);
10621 /* Described above */
10622 void            gtk_preview_size               (GtkPreview      *preview,
10623                                                 gint             width,
10624                                                 gint             height);
10625 /* Allows you to resize an existing preview.    */
10626 /* Apparently there's a bug in GTK which makes  */
10627 /* this process messy. A way to clean up a mess */
10628 /* is to manually resize the window containing  */
10629 /* the preview after resizing the preview.      */
10630
10631 void            gtk_preview_put                (GtkPreview      *preview,
10632                                                 GdkWindow       *window,
10633                                                 GdkGC           *gc,
10634                                                 gint             srcx,
10635                                                 gint             srcy,
10636                                                 gint             destx,
10637                                                 gint             desty,
10638                                                 gint             width,
10639                                                 gint             height);
10640 /* No idea */
10641
10642 void            gtk_preview_put_row            (GtkPreview      *preview,
10643                                                 guchar          *src,
10644                                                 guchar          *dest,
10645                                                 gint             x,
10646                                                 gint             y,
10647                                                 gint             w);
10648 /* No idea */
10649
10650 void            gtk_preview_draw_row           (GtkPreview      *preview,
10651                                                 guchar          *data,
10652                                                 gint             x,
10653                                                 gint             y,
10654                                                 gint             w);
10655 /* Described in the text */
10656
10657 void            gtk_preview_set_expand         (GtkPreview      *preview,
10658                                                 gint             expand);
10659 /* No idea */
10660
10661 /* No clue for any of the below but    */
10662 /* should be standard for most widgets */
10663 void            gtk_preview_set_gamma          (double           gamma);
10664 void            gtk_preview_set_color_cube     (guint            nred_shades,
10665                                                 guint            ngreen_shades,
10666                                                 guint            nblue_shades,
10667                                                 guint            ngray_shades);
10668 void            gtk_preview_set_install_cmap   (gint             install_cmap);
10669 void            gtk_preview_set_reserved       (gint             nreserved);
10670 GdkVisual*      gtk_preview_get_visual         (void);
10671 GdkColormap*    gtk_preview_get_cmap           (void);
10672 GtkPreviewInfo* gtk_preview_get_info           (void);
10673
10674 That's all, folks!
10675
10676 </verb></tscreen>
10677
10678 -->
10679
10680 <!-- ***************************************************************** -->
10681 <sect>Setting Widget Attributes<label id="sec_setting_widget_attributes">
10682 <!-- ***************************************************************** -->
10683 <p>
10684 This describes the functions used to operate on widgets. These can be
10685 used to set style, padding, size, etc.
10686
10687 (Maybe I should make a whole section on accelerators.)
10688
10689 <tscreen><verb>
10690 void gtk_widget_install_accelerator( GtkWidget           *widget,
10691                                      GtkAcceleratorTable *table,
10692                                      gchar               *signal_name,
10693                                      gchar                key,
10694                                      guint8               modifiers );
10695
10696 void gtk_widget_remove_accelerator ( GtkWidget           *widget,
10697                                      GtkAcceleratorTable *table,
10698                                      gchar               *signal_name);
10699
10700 void gtk_widget_activate( GtkWidget *widget );
10701
10702 void gtk_widget_set_name( GtkWidget *widget,
10703                           gchar     *name );
10704
10705 gchar *gtk_widget_get_name( GtkWidget *widget );
10706
10707 void gtk_widget_set_sensitive( GtkWidget *widget,
10708                                gint       sensitive );
10709
10710 void gtk_widget_set_style( GtkWidget *widget,
10711                            GtkStyle  *style );
10712                                            
10713 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
10714
10715 GtkStyle *gtk_widget_get_default_style( void );
10716
10717 void gtk_widget_set_uposition( GtkWidget *widget,
10718                                gint       x,
10719                                gint       y );
10720
10721 void gtk_widget_set_usize( GtkWidget *widget,
10722                            gint       width,
10723                            gint       height );
10724
10725 void gtk_widget_grab_focus( GtkWidget *widget );
10726
10727 void gtk_widget_show( GtkWidget *widget );
10728
10729 void gtk_widget_hide( GtkWidget *widget );
10730 </verb></tscreen>
10731
10732 <!-- ***************************************************************** -->
10733 <sect>Timeouts, IO and Idle Functions<label id="sec_timeouts">
10734 <!-- ***************************************************************** -->
10735
10736 <!-- ----------------------------------------------------------------- -->
10737 <sect1>Timeouts
10738 <p>
10739 You may be wondering how you make GTK do useful work when in gtk_main.
10740 Well, you have several options. Using the following function you can
10741 create a timeout function that will be called every "interval"
10742 milliseconds.
10743
10744 <tscreen><verb>
10745 gint gtk_timeout_add( guint32     interval,
10746                       GtkFunction function,
10747                       gpointer    data );
10748 </verb></tscreen>
10749
10750 The first argument is the number of milliseconds between calls to your
10751 function. The second argument is the function you wish to have called,
10752 and the third, the data passed to this callback function. The return
10753 value is an integer "tag" which may be used to stop the timeout by
10754 calling:
10755
10756 <tscreen><verb>
10757 void gtk_timeout_remove( gint tag );
10758 </verb></tscreen>
10759
10760 You may also stop the timeout function by returning zero or FALSE from
10761 your callback function. Obviously this means if you want your function
10762 to continue to be called, it should return a non-zero value,
10763 i.e., TRUE.
10764
10765 The declaration of your callback should look something like this:
10766
10767 <tscreen><verb>
10768 gint timeout_callback( gpointer data );
10769 </verb></tscreen>
10770
10771 <!-- ----------------------------------------------------------------- -->
10772 <sect1>Monitoring IO
10773 <p>
10774 A nifty feature of GDK (the library that underlies GTK), is the
10775 ability to have it check for data on a file descriptor for you (as
10776 returned by open(2) or socket(2)). This is especially useful for
10777 networking applications. The function:
10778
10779 <tscreen><verb>
10780 gint gdk_input_add( gint              source,
10781                     GdkInputCondition condition,
10782                     GdkInputFunction  function,
10783                     gpointer          data );
10784 </verb></tscreen>
10785
10786 Where the first argument is the file descriptor you wish to have
10787 watched, and the second specifies what you want GDK to look for. This
10788 may be one of:
10789
10790 <itemize>
10791 <item><tt/GDK_INPUT_READ/ - Call your function when there is data
10792 ready for reading on your file descriptor.
10793
10794 <item>><tt/GDK_INPUT_WRITE/ - Call your function when the file
10795 descriptor is ready for writing.
10796 </itemize>
10797
10798 As I'm sure you've figured out already, the third argument is the
10799 function you wish to have called when the above conditions are
10800 satisfied, and the fourth is the data to pass to this function.
10801
10802 The return value is a tag that may be used to stop GDK from monitoring
10803 this file descriptor using the following function.
10804
10805 <tscreen><verb>
10806 void gdk_input_remove( gint tag );
10807 </verb></tscreen>
10808
10809 The callback function should be declared as:
10810
10811 <tscreen><verb>
10812 void input_callback( gpointer          data,
10813                      gint              source, 
10814                      GdkInputCondition condition );
10815 </verb></tscreen>
10816
10817 Where <tt/source/ and <tt/condition/ are as specified above.
10818
10819 <!-- ----------------------------------------------------------------- -->
10820 <sect1>Idle Functions
10821 <p>
10822 <!-- TODO: Need to check on idle priorities - TRG -->
10823 What if you have a function which you want to be called when nothing
10824 else is happening ?
10825
10826 <tscreen><verb>
10827 gint gtk_idle_add( GtkFunction function,
10828                    gpointer    data );
10829 </verb></tscreen>
10830
10831 This causes GTK to call the specified function whenever nothing else
10832 is happening.
10833
10834 <tscreen><verb>
10835 void gtk_idle_remove( gint tag );
10836 </verb></tscreen>
10837
10838 I won't explain the meaning of the arguments as they follow very much
10839 like the ones above. The function pointed to by the first argument to
10840 gtk_idle_add will be called whenever the opportunity arises. As with
10841 the others, returning FALSE will stop the idle function from being
10842 called.
10843
10844 <!-- ***************************************************************** -->
10845 <sect>Advanced Event and Signal Handling<label id="sec_Adv_Events_and_Signals">
10846 <!-- ***************************************************************** -->
10847
10848 <!-- ----------------------------------------------------------------- -->
10849 <sect1>Signal Functions
10850
10851 <!-- ----------------------------------------------------------------- -->
10852 <sect2>Connecting and Disconnecting Signal Handlers
10853 <p>
10854
10855 <tscreen><verb>
10856 guint gtk_signal_connect( GtkObject     *object,
10857                           const gchar   *name,
10858                           GtkSignalFunc  func,
10859                           gpointer       func_data );
10860
10861 guint gtk_signal_connect_after( GtkObject     *object,
10862                                 const gchar   *name,
10863                                 GtkSignalFunc  func,
10864                                 gpointer       func_data );
10865
10866 guint gtk_signal_connect_object( GtkObject     *object,
10867                                  const gchar   *name,
10868                                  GtkSignalFunc  func,
10869                                  GtkObject     *slot_object );
10870
10871 guint gtk_signal_connect_object_after( GtkObject     *object,
10872                                        const gchar   *name,
10873                                        GtkSignalFunc  func,
10874                                        GtkObject     *slot_object );
10875
10876 guint gtk_signal_connect_full( GtkObject          *object,
10877                                const gchar        *name,
10878                                GtkSignalFunc       func,
10879                                GtkCallbackMarshal  marshal,
10880                                gpointer            data,
10881                                GtkDestroyNotify    destroy_func,
10882                                gint                object_signal,
10883                                gint                after );
10884
10885 guint gtk_signal_connect_interp( GtkObject          *object,
10886                                  const gchar        *name,
10887                                  GtkCallbackMarshal  func,
10888                                  gpointer            data,
10889                                  GtkDestroyNotify    destroy_func,
10890                                  gint                after );
10891
10892 void gtk_signal_connect_object_while_alive( GtkObject     *object,
10893                                             const gchar   *signal,
10894                                             GtkSignalFunc  func,
10895                                             GtkObject     *alive_object );
10896
10897 void gtk_signal_connect_while_alive( GtkObject     *object,
10898                                      const gchar   *signal,
10899                                      GtkSignalFunc  func,
10900                                      gpointer       func_data,
10901                                      GtkObject     *alive_object );
10902
10903 void gtk_signal_disconnect( GtkObject *object,
10904                             guint      handler_id );
10905
10906 void gtk_signal_disconnect_by_func( GtkObject     *object,
10907                                     GtkSignalFunc  func,
10908                                     gpointer       data );
10909 </verb></tscreen>
10910
10911 <!-- ----------------------------------------------------------------- -->
10912 <sect2>Blocking and Unblocking Signal Handlers
10913 <p>
10914 <tscreen><verb>
10915 void gtk_signal_handler_block( GtkObject *object,
10916                                guint      handler_id);
10917
10918 void gtk_signal_handler_block_by_func( GtkObject     *object,
10919                                        GtkSignalFunc  func,
10920                                        gpointer       data );
10921
10922 void gtk_signal_handler_block_by_data( GtkObject *object,
10923                                        gpointer   data );
10924
10925 void gtk_signal_handler_unblock( GtkObject *object,
10926                                  guint      handler_id );
10927
10928 void gtk_signal_handler_unblock_by_func( GtkObject     *object,
10929                                          GtkSignalFunc  func,
10930                                          gpointer       data );
10931
10932 void gtk_signal_handler_unblock_by_data( GtkObject *object,
10933                                          gpointer   data );
10934 </verb></tscreen>
10935
10936 <!-- ----------------------------------------------------------------- -->
10937 <sect2>Emitting and Stopping Signals
10938 <p>
10939 <tscreen><verb>
10940 void gtk_signal_emit( GtkObject *object,
10941                       guint      signal_id,
10942                       ... );
10943
10944 void gtk_signal_emit_by_name( GtkObject   *object,
10945                               const gchar *name,
10946                               ... );
10947
10948 void gtk_signal_emitv( GtkObject *object,
10949                        guint      signal_id,
10950                        GtkArg    *params );
10951
10952 void gtk_signal_emitv_by_name( GtkObject   *object,
10953                                const gchar *name,
10954                                GtkArg      *params );
10955
10956 guint gtk_signal_n_emissions( GtkObject *object,
10957                               guint      signal_id );
10958
10959 guint gtk_signal_n_emissions_by_name( GtkObject   *object,
10960                                       const gchar *name );
10961
10962 void gtk_signal_emit_stop( GtkObject *object,
10963                            guint      signal_id );
10964
10965 void gtk_signal_emit_stop_by_name( GtkObject   *object,
10966                                    const gchar *name );
10967 </verb></tscreen>
10968
10969 <!-- ----------------------------------------------------------------- -->
10970 <sect1>Signal Emission and Propagation
10971 <p>
10972 Signal emission is the process whereby GTK runs all handlers for a
10973 specific object and signal.
10974
10975 First, note that the return value from a signal emission is the return
10976 value of the <em>last</em> handler executed. Since event signals are
10977 all of type <tt/GTK_RUN_LAST/, this will be the default (GTK supplied)
10978 handler, unless you connect with gtk_signal_connect_after().
10979
10980 The way an event (say "button_press_event") is handled, is:
10981 <itemize>
10982 <item>Start with the widget where the event occured.
10983
10984 <item>Emit the generic "event" signal. If that signal handler returns
10985 a value of TRUE, stop all processing.
10986
10987 <item>Otherwise, emit a specific, "button_press_event" signal. If that
10988 returns TRUE, stop all processing.
10989
10990 <item>Otherwise, go to the widget's parent, and repeat the above two
10991 steps.
10992
10993 <item>Continue until some signal handler returns TRUE, or until the
10994 top-level widget is reached.
10995 </itemize>
10996
10997 Some consequences of the above are:
10998 <itemize>
10999 <item>Your handler's return value will have no effect if there is a
11000 default handler, unless you connect with gtk_signal_connect_after().
11001
11002 <item>To prevent the default handler from being run, you need to
11003 connect with gtk_signal_connect() and use
11004 gtk_signal_emit_stop_by_name() - the return value only affects whether
11005 the signal is propagated, not the current emission.
11006 </itemize>
11007
11008 <!-- ***************************************************************** -->
11009 <sect>Managing Selections
11010 <!-- ***************************************************************** -->
11011
11012 <!-- ----------------------------------------------------------------- -->
11013 <sect1> Overview
11014 <p>
11015 One type of interprocess communication supported by X and GTK is
11016 <em>selections</em>. A selection identifies a chunk of data, for
11017 instance, a portion of text, selected by the user in some fashion, for
11018 instance, by dragging with the mouse. Only one application on a
11019 display (the <em>owner</em>) can own a particular selection at one
11020 time, so when a selection is claimed by one application, the previous
11021 owner must indicate to the user that selection has been
11022 relinquished. Other applications can request the contents of a
11023 selection in different forms, called <em>targets</em>. There can be
11024 any number of selections, but most X applications only handle one, the
11025 <em>primary selection</em>.
11026
11027 In most cases, it isn't necessary for a GTK application to deal with
11028 selections itself. The standard widgets, such as the Entry widget,
11029 already have the capability to claim the selection when appropriate
11030 (e.g., when the user drags over text), and to retrieve the contents of
11031 the selection owned by another widget or another application (e.g.,
11032 when the user clicks the second mouse button). However, there may be
11033 cases in which you want to give other widgets the ability to supply
11034 the selection, or you wish to retrieve targets not supported by
11035 default.
11036
11037 A fundamental concept needed to understand selection handling is that
11038 of the <em>atom</em>. An atom is an integer that uniquely identifies a
11039 string (on a certain display). Certain atoms are predefined by the X
11040 server, and in some cases there are constants in <tt>gtk.h</tt>
11041 corresponding to these atoms. For instance the constant
11042 <tt>GDK_PRIMARY_SELECTION</tt> corresponds to the string "PRIMARY".
11043 In other cases, you should use the functions
11044 <tt>gdk_atom_intern()</tt>, to get the atom corresponding to a string,
11045 and <tt>gdk_atom_name()</tt>, to get the name of an atom. Both
11046 selections and targets are identified by atoms.
11047
11048 <!-- ----------------------------------------------------------------- -->
11049 <sect1> Retrieving the selection
11050 <p>
11051 Retrieving the selection is an asynchronous process. To start the
11052 process, you call:
11053
11054 <tscreen><verb>
11055 gint gtk_selection_convert( GtkWidget *widget, 
11056                             GdkAtom    selection, 
11057                             GdkAtom    target,
11058                             guint32    time );
11059 </verb</tscreen>
11060
11061 This <em>converts</em> the selection into the form specified by
11062 <tt/target/. If at all possible, the time field should be the time
11063 from the event that triggered the selection. This helps make sure that
11064 events occur in the order that the user requested them. However, if it
11065 is not available (for instance, if the conversion was triggered by a
11066 "clicked" signal), then you can use the constant
11067 <tt>GDK_CURRENT_TIME</tt>.
11068
11069 When the selection owner responds to the request, a
11070 "selection_received" signal is sent to your application. The handler
11071 for this signal receives a pointer to a <tt>GtkSelectionData</tt>
11072 structure, which is defined as:
11073
11074 <tscreen><verb>
11075 struct _GtkSelectionData
11076 {
11077   GdkAtom selection;
11078   GdkAtom target;
11079   GdkAtom type;
11080   gint    format;
11081   guchar *data;
11082   gint    length;
11083 };
11084 </verb></tscreen>
11085
11086 <tt>selection</tt> and <tt>target</tt> are the values you gave in your
11087 <tt>gtk_selection_convert()</tt> call. <tt>type</tt> is an atom that
11088 identifies the type of data returned by the selection owner. Some
11089 possible values are "STRING", a string of latin-1 characters, "ATOM",
11090 a series of atoms, "INTEGER", an integer, etc. Most targets can only
11091 return one type. <tt/format/ gives the length of the units (for
11092 instance characters) in bits. Usually, you don't care about this when
11093 receiving data. <tt>data</tt> is a pointer to the returned data, and
11094 <tt>length</tt> gives the length of the returned data, in bytes. If
11095 <tt>length</tt> is negative, then an error occurred and the selection
11096 could not be retrieved. This might happen if no application owned the
11097 selection, or if you requested a target that the application didn't
11098 support. The buffer is actually guaranteed to be one byte longer than
11099 <tt>length</tt>; the extra byte will always be zero, so it isn't
11100 necessary to make a copy of strings just to null terminate them.
11101
11102 In the following example, we retrieve the special target "TARGETS",
11103 which is a list of all targets into which the selection can be
11104 converted.
11105
11106 <tscreen><verb>
11107 /* example-start selection gettargets.c */
11108
11109 #include <gtk/gtk.h>
11110
11111 void selection_received (GtkWidget *widget, 
11112                          GtkSelectionData *selection_data, 
11113                          gpointer data);
11114
11115 /* Signal handler invoked when user clicks on the "Get Targets" button */
11116 void
11117 get_targets (GtkWidget *widget, gpointer data)
11118 {
11119   static GdkAtom targets_atom = GDK_NONE;
11120
11121   /* Get the atom corresponding to the string "TARGETS" */
11122   if (targets_atom == GDK_NONE)
11123     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
11124
11125   /* And request the "TARGETS" target for the primary selection */
11126   gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
11127                          GDK_CURRENT_TIME);
11128 }
11129
11130 /* Signal handler called when the selections owner returns the data */
11131 void
11132 selection_received (GtkWidget *widget, GtkSelectionData *selection_data, 
11133                     gpointer data)
11134 {
11135   GdkAtom *atoms;
11136   GList *item_list;
11137   int i;
11138
11139   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
11140   if (selection_data->length < 0)
11141     {
11142       g_print ("Selection retrieval failed\n");
11143       return;
11144     }
11145   /* Make sure we got the data in the expected form */
11146   if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
11147     {
11148       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
11149       return;
11150     }
11151   
11152   /* Print out the atoms we received */
11153   atoms = (GdkAtom *)selection_data->data;
11154
11155   item_list = NULL;
11156   for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
11157     {
11158       char *name;
11159       name = gdk_atom_name (atoms[i]);
11160       if (name != NULL)
11161         g_print ("%s\n",name);
11162       else
11163         g_print ("(bad atom)\n");
11164     }
11165
11166   return;
11167 }
11168
11169 int 
11170 main (int argc, char *argv[])
11171 {
11172   GtkWidget *window;
11173   GtkWidget *button;
11174   
11175   gtk_init (&amp;argc, &amp;argv);
11176
11177   /* Create the toplevel window */
11178
11179   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11180   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
11181   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11182
11183   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11184                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11185
11186   /* Create a button the user can click to get targets */
11187
11188   button = gtk_button_new_with_label ("Get Targets");
11189   gtk_container_add (GTK_CONTAINER (window), button);
11190
11191   gtk_signal_connect (GTK_OBJECT(button), "clicked",
11192                       GTK_SIGNAL_FUNC (get_targets), NULL);
11193   gtk_signal_connect (GTK_OBJECT(button), "selection_received",
11194                       GTK_SIGNAL_FUNC (selection_received), NULL);
11195
11196   gtk_widget_show (button);
11197   gtk_widget_show (window);
11198   
11199   gtk_main ();
11200   
11201   return 0;
11202 }
11203 /* example-end */
11204 </verb></tscreen>
11205
11206 <!-- ----------------------------------------------------------------- -->
11207 <sect1> Supplying the selection 
11208 <p>
11209 Supplying the selection is a bit more complicated. You must register 
11210 handlers that will be called when your selection is requested. For
11211 each selection/target pair you will handle, you make a call to:
11212
11213 <tscreen><verb>
11214 void gtk_selection_add_handler( GtkWidget            *widget, 
11215                                 GdkAtom               selection,
11216                                 GdkAtom               target,
11217                                 GtkSelectionFunction  function,
11218                                 GtkRemoveFunction     remove_func,
11219                                 gpointer              data );
11220 </verb></tscreen>
11221
11222 <tt/widget/, <tt/selection/, and <tt/target/ identify the requests
11223 this handler will manage.  <tt/remove_func/, if not
11224 NULL, will be called when the signal handler is removed. This is
11225 useful, for instance, for interpreted languages which need to
11226 keep track of a reference count for <tt/data/.
11227
11228 The callback function has the signature:
11229
11230 <tscreen><verb>
11231 typedef void (*GtkSelectionFunction)( GtkWidget        *widget, 
11232                                       GtkSelectionData *selection_data,
11233                                       gpointer          data );
11234
11235 </verb></tscreen>
11236
11237 The GtkSelectionData is the same as above, but this time, we're
11238 responsible for filling in the fields <tt/type/, <tt/format/,
11239 <tt/data/, and <tt/length/. (The <tt/format/ field is actually
11240 important here - the X server uses it to figure out whether the data
11241 needs to be byte-swapped or not. Usually it will be 8 - <em/i.e./ a
11242 character - or 32 - <em/i.e./ a. integer.) This is done by calling the
11243 function:
11244
11245 <tscreen><verb>
11246 void gtk_selection_data_set( GtkSelectionData *selection_data,
11247                              GdkAtom           type,
11248                              gint              format,
11249                              guchar           *data,
11250                              gint              length );
11251 </verb></tscreen>
11252
11253 This function takes care of properly making a copy of the data so that
11254 you don't have to worry about keeping it around. (You should not fill
11255 in the fields of the GtkSelectionData structure by hand.)
11256
11257 When prompted by the user, you claim ownership of the selection by
11258 calling:
11259
11260 <tscreen><verb>
11261 gint gtk_selection_owner_set( GtkWidget *widget,
11262                               GdkAtom    selection,
11263                               guint32    time );
11264 </verb></tscreen>
11265
11266 If another application claims ownership of the selection, you will
11267 receive a "selection_clear_event".
11268
11269 As an example of supplying the selection, the following program adds
11270 selection functionality to a toggle button. When the toggle button is
11271 depressed, the program claims the primary selection. The only target
11272 supported (aside from certain targets like "TARGETS" supplied by GTK
11273 itself), is the "STRING" target. When this target is requested, a
11274 string representation of the time is returned.
11275
11276 <tscreen><verb>
11277 /* example-start selection setselection.c */
11278
11279 #include <gtk/gtk.h>
11280 #include <time.h>
11281
11282 /* Callback when the user toggles the selection */
11283 void
11284 selection_toggled (GtkWidget *widget, gint *have_selection)
11285 {
11286   if (GTK_TOGGLE_BUTTON(widget)->active)
11287     {
11288       *have_selection = gtk_selection_owner_set (widget,
11289                                                  GDK_SELECTION_PRIMARY,
11290                                                  GDK_CURRENT_TIME);
11291       /* if claiming the selection failed, we return the button to
11292          the out state */
11293       if (!*have_selection)
11294         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
11295     }
11296   else
11297     {
11298       if (*have_selection)
11299         {
11300           /* Before clearing the selection by setting the owner to NULL,
11301              we check if we are the actual owner */
11302           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
11303             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
11304                                      GDK_CURRENT_TIME);
11305           *have_selection = FALSE;
11306         }
11307     }
11308 }
11309
11310 /* Called when another application claims the selection */
11311 gint
11312 selection_clear (GtkWidget *widget, GdkEventSelection *event,
11313                  gint *have_selection)
11314 {
11315   *have_selection = FALSE;
11316   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
11317
11318   return TRUE;
11319 }
11320
11321 /* Supplies the current time as the selection. */
11322 void
11323 selection_handle (GtkWidget *widget, 
11324                   GtkSelectionData *selection_data,
11325                   gpointer data)
11326 {
11327   gchar *timestr;
11328   time_t current_time;
11329
11330   current_time = time (NULL);
11331   timestr = asctime (localtime(&amp;current_time)); 
11332   /* When we return a single string, it should not be null terminated.
11333      That will be done for us */
11334
11335   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
11336                           8, timestr, strlen(timestr));
11337 }
11338
11339 int
11340 main (int argc, char *argv[])
11341 {
11342   GtkWidget *window;
11343
11344   GtkWidget *selection_button;
11345
11346   static int have_selection = FALSE;
11347   
11348   gtk_init (&amp;argc, &amp;argv);
11349
11350   /* Create the toplevel window */
11351
11352   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11353   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
11354   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11355
11356   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11357                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11358
11359   /* Create a toggle button to act as the selection */
11360
11361   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
11362   gtk_container_add (GTK_CONTAINER (window), selection_button);
11363   gtk_widget_show (selection_button);
11364
11365   gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
11366                       GTK_SIGNAL_FUNC (selection_toggled), &amp;have_selection);
11367   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
11368                       GTK_SIGNAL_FUNC (selection_clear), &amp;have_selection);
11369
11370   gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
11371                              GDK_SELECTION_TYPE_STRING,
11372                              selection_handle, NULL);
11373
11374   gtk_widget_show (selection_button);
11375   gtk_widget_show (window);
11376   
11377   gtk_main ();
11378   
11379   return 0;
11380 }
11381 /* example-end */
11382 </verb></tscreen>
11383
11384
11385 <!-- ***************************************************************** -->
11386 <sect>GLib<label id="sec_glib">
11387 <!-- ***************************************************************** -->
11388 <p>
11389 GLib is a lower-level library that provides many useful definitions
11390 and functions available for use when creating GDK and GTK
11391 applications. These include definitions for basic types and their
11392 limits, standard macros, type conversions, byte order, memory
11393 allocation, warnings and assertions, message logging, timers, string
11394 utilities, hook functions, a lexical scanner, dynamic loading of
11395 modules, and automatic string completion. A number of data structures
11396 (and their related operations) are also defined, including memory
11397 chunks, doubly-linked lists, singly-linked lists, hash tables, strings
11398 (which can grow dynamically), string chunks (groups of strings),
11399 arrays (which can grow in size as elements are added), balanced binary
11400 trees, N-ary trees, quarks (a two-way association of a string and a
11401 unique integer identifier), keyed data lists (lists of data elements
11402 accessible by a string or integer id), relations and tuples (tables of
11403 data which can be indexed on any number of fields), and caches.
11404
11405 A summary of some of GLib's capabilities follows; not every function,
11406 data structure, or operation is covered here.  For more complete
11407 information about the GLib routines, see the GLib documentation. One
11408 source of GLib documentation is <htmlurl url="http://www.gtk.org/"
11409 name="http://www.gtk.org/">.
11410
11411 If you are using a language other than C, you should consult your
11412 language's binding documentation. In some cases your language may
11413 have equivalent functionality built-in, while in other cases it may
11414 not.
11415
11416 <!-- ----------------------------------------------------------------- -->
11417 <sect1>Definitions
11418 <p>
11419 Definitions for the extremes of many of the standard types are:
11420
11421 <tscreen><verb>
11422 G_MINFLOAT
11423 G_MAXFLOAT
11424 G_MINDOUBLE
11425 G_MAXDOUBLE
11426 G_MINSHORT
11427 G_MAXSHORT
11428 G_MININT
11429 G_MAXINT
11430 G_MINLONG
11431 G_MAXLONG
11432 </verb></tscreen>
11433
11434 Also, the following typedefs. The ones left unspecified are dynamically set
11435 depending on the architecture. Remember to avoid counting on the size of a
11436 pointer if you want to be portable! E.g., a pointer on an Alpha is 8
11437 bytes, but 4 on Intel 80x86 family CPUs.
11438
11439 <tscreen><verb>
11440 char   gchar;
11441 short  gshort;
11442 long   glong;
11443 int    gint;
11444 char   gboolean;
11445
11446 unsigned char   guchar;
11447 unsigned short  gushort;
11448 unsigned long   gulong;
11449 unsigned int    guint;
11450
11451 float   gfloat;
11452 double  gdouble;
11453 long double gldouble;
11454
11455 void* gpointer;
11456
11457 gint8
11458 guint8
11459 gint16
11460 guint16
11461 gint32
11462 guint32
11463 </verb></tscreen>
11464
11465 <!-- ----------------------------------------------------------------- -->
11466 <sect1>Doubly Linked Lists
11467 <p>
11468 The following functions are used to create, manage, and destroy
11469 standard doubly linked lists. Each element in the list contains a
11470 piece of data, together with pointers which link to the previous and
11471 next elements in the list. This enables easy movement in either
11472 direction through the list. The data item is of type "gpointer",
11473 which means the data can be a pointer to your real data or (through
11474 casting) a numeric value (but do not assume that int and gpointer have
11475 the same size!). These routines internally allocate list elements in
11476 blocks, which is more efficient than allocating elements individually.
11477
11478 There is no function to specifically create a list. Instead, simply
11479 create a variable of type GList* and set its value to NULL; NULL is
11480 considered to be the empty list.
11481
11482 To add elements to a list, use the g_list_append(), g_list_prepend(),
11483 g_list_insert(), or g_list_insert_sorted() routines. In all cases
11484 they accept a pointer to the beginning of the list, and return the
11485 (possibly changed) pointer to the beginning of the list. Thus, for
11486 all of the operations that add or remove elements, be sure to save the
11487 returned value!
11488
11489 <tscreen><verb>
11490 GList *g_list_append( GList    *list,
11491                       gpointer  data );
11492 </verb></tscreen>
11493
11494 This adds a new element (with value <tt/data/) onto the end of the
11495 list.
11496   
11497 <tscreen><verb>    
11498 GList *g_list_prepend( GList    *list,
11499                        gpointer  data );
11500 </verb></tscreen>
11501
11502 This adds a new element (with value <tt/data/) to the beginning of the
11503 list.
11504
11505 <tscreen><verb>         
11506 GList *g_list_insert( GList    *list,
11507                       gpointer  data,
11508                       gint      position );
11509
11510 </verb></tscreen>
11511
11512 This inserts a new element (with value data) into the list at the
11513 given position. If position is 0, this is just like g_list_prepend();
11514 if position is less than 0, this is just like g_list_append().
11515
11516 <tscreen><verb>
11517 GList *g_list_remove( GList    *list,
11518                       gpointer  data );
11519 </verb></tscreen>
11520
11521 This removes the element in the list with the value <tt/data/;
11522 if the element isn't there, the list is unchanged.
11523
11524 <tscreen><verb>
11525 void g_list_free( GList *list );
11526 </verb></tscreen>
11527
11528 This frees all of the memory used by a GList. If the list elements
11529 refer to dynamically-allocated memory, then they should be freed
11530 first.
11531
11532 There are many other GLib functions that support doubly linked lists;
11533 see the glib documentation for more information.  Here are a few of
11534 the more useful functions' signatures:
11535
11536 <tscreen><verb>            
11537 GList *g_list_remove_link( GList *list,
11538                            GList *link );
11539
11540 GList *g_list_reverse( GList *list );
11541
11542 GList *g_list_nth( GList *list,
11543                    gint   n );
11544                            
11545 GList *g_list_find( GList    *list,
11546                     gpointer  data );
11547
11548 GList *g_list_last( GList *list );
11549
11550 GList *g_list_first( GList *list );
11551
11552 gint g_list_length( GList *list );
11553
11554 void g_list_foreach( GList    *list,
11555                      GFunc     func,
11556                      gpointer  user_data );
11557 </verb></tscreen>                                             
11558
11559 <!-- ----------------------------------------------------------------- -->
11560 <sect1>Singly Linked Lists
11561 <p>
11562 Many of the above functions for singly linked lists are identical to the
11563 above. Here is a list of some of their operations:
11564
11565 <tscreen><verb>
11566 GSList *g_slist_append( GSList   *list,
11567                         gpointer  data );
11568                 
11569 GSList *g_slist_prepend( GSList   *list,
11570                          gpointer  data );
11571                              
11572 GSList *g_slist_insert( GSList   *list,
11573                         gpointer  data,
11574                         gint      position );
11575                              
11576 GSList *g_slist_remove( GSList   *list,
11577                         gpointer  data );
11578                              
11579 GSList *g_slist_remove_link( GSList *list,
11580                              GSList *link );
11581                              
11582 GSList *g_slist_reverse( GSList *list );
11583
11584 GSList *g_slist_nth( GSList *list,
11585                      gint    n );
11586                              
11587 GSList *g_slist_find( GSList   *list,
11588                       gpointer  data );
11589                              
11590 GSList *g_slist_last( GSList *list );
11591
11592 gint g_slist_length( GSList *list );
11593
11594 void g_slist_foreach( GSList   *list,
11595                       GFunc     func,
11596                       gpointer  user_data );
11597         
11598 </verb></tscreen>
11599
11600 <!-- ----------------------------------------------------------------- -->
11601 <sect1>Memory Management
11602 <p>
11603 <tscreen><verb>
11604 gpointer g_malloc( gulong size );
11605 </verb></tscreen>
11606
11607 This is a replacement for malloc(). You do not need to check the return
11608 value as it is done for you in this function. If the memory allocation
11609 fails for whatever reasons, your applications will be terminated.
11610
11611 <tscreen><verb>
11612 gpointer g_malloc0( gulong size );
11613 </verb></tscreen>
11614
11615 Same as above, but zeroes the memory before returning a pointer to it.
11616
11617 <tscreen><verb>
11618 gpointer g_realloc( gpointer mem,
11619                     gulong   size );
11620 </verb></tscreen>
11621
11622 Relocates "size" bytes of memory starting at "mem".  Obviously, the
11623 memory should have been previously allocated.
11624
11625 <tscreen><verb>
11626 void g_free( gpointer mem );
11627 </verb></tscreen>
11628
11629 Frees memory. Easy one. If <tt/mem/ is NULL it simply returns.
11630
11631 <tscreen><verb>
11632 void g_mem_profile( void );
11633 </verb></tscreen>
11634
11635 Dumps a profile of used memory, but requires that you add <tt>#define
11636 MEM_PROFILE</tt> to the top of glib/gmem.c and re-make and make install.
11637
11638 <tscreen><verb>
11639 void g_mem_check( gpointer mem );
11640 </verb></tscreen>
11641
11642 Checks that a memory location is valid. Requires you add <tt>#define
11643 MEM_CHECK</tt> to the top of gmem.c and re-make and make install.
11644
11645 <!-- ----------------------------------------------------------------- -->
11646 <sect1>Timers
11647 <p>
11648 Timer functions can be used to time operations (e.g., to see how much
11649 time has elapsed). First, you create a new timer with g_timer_new().
11650 You can then use g_timer_start() to start timing an operation,
11651 g_timer_stop() to stop timing an operation, and g_timer_elapsed() to
11652 determine the elapsed time.
11653
11654 <tscreen><verb>
11655 GTimer *g_timer_new( void );
11656
11657 void g_timer_destroy( GTimer *timer );
11658
11659 void g_timer_start( GTimer  *timer );
11660
11661 void g_timer_stop( GTimer  *timer );
11662
11663 void g_timer_reset( GTimer  *timer );
11664
11665 gdouble g_timer_elapsed( GTimer *timer,
11666                          gulong *microseconds );
11667 </verb></tscreen>                        
11668
11669 <!-- ----------------------------------------------------------------- -->
11670 <sect1>String Handling
11671 <p>
11672 GLib defines a new type called a GString, which is similar to a
11673 standard C string but one that grows automatically. Its string data
11674 is null-terminated. What this gives you is protection from buffer
11675 overflow programming errors within your program. This is a very
11676 important feature, and hence I recommend that you make use of
11677 GStrings. GString itself has a simple public definition:
11678
11679 <tscreen><verb>
11680 struct GString 
11681 {
11682   gchar *str; /* Points to the string's current \0-terminated value. */
11683   gint len; /* Current length */
11684 };
11685 </verb></tscreen>
11686
11687 As you might expect, there are a number of operations you can do with
11688 a GString.
11689
11690 <tscreen><verb>
11691 GString *g_string_new( gchar *init );
11692 </verb></tscreen>
11693
11694 This constructs a GString, copying the string value of <tt/init/
11695 into the GString and returning a pointer to it. NULL may be given as
11696 the argument for an initially empty GString.
11697  
11698 <tscreen><verb>
11699
11700 void g_string_free( GString *string,
11701                     gint     free_segment );
11702 </verb></tscreen>
11703
11704 This frees the memory for the given GString. If <tt/free_segment/ is
11705 TRUE, then this also frees its character data.
11706
11707 <tscreen><verb>
11708                              
11709 GString *g_string_assign( GString     *lval,
11710                           const gchar *rval );
11711 </verb></tscreen>
11712
11713 This copies the characters from rval into lval, destroying the
11714 previous contents of lval. Note that lval will be lengthened as
11715 necessary to hold the string's contents, unlike the standard strcpy()
11716 function.
11717
11718 The rest of these functions should be relatively obvious (the _c
11719 versions accept a character instead of a string):
11720
11721 <tscreen><verb>              
11722 GString *g_string_truncate( GString *string,
11723                             gint     len );
11724                              
11725 GString *g_string_append( GString *string,
11726                           gchar   *val );
11727                             
11728 GString *g_string_append_c( GString *string,
11729                             gchar    c );
11730         
11731 GString *g_string_prepend( GString *string,
11732                            gchar   *val );
11733                              
11734 GString *g_string_prepend_c( GString *string,
11735                              gchar    c );
11736         
11737 void g_string_sprintf( GString *string,
11738                        gchar   *fmt,
11739                        ...);
11740         
11741 void g_string_sprintfa ( GString *string,
11742                          gchar   *fmt,
11743                          ... );
11744 </verb></tscreen>                                                         
11745
11746 <!-- ----------------------------------------------------------------- -->
11747 <sect1>Utility and Error Functions
11748 <p>
11749 <tscreen><verb>
11750 gchar *g_strdup( const gchar *str );
11751 </verb></tscreen>
11752
11753 Replacement strdup function.  Copies the original strings contents to
11754 newly allocated memory, and returns a pointer to it.
11755
11756 <tscreen><verb>
11757 gchar *g_strerror( gint errnum );
11758 </verb></tscreen>
11759
11760 I recommend using this for all error messages.  It's much nicer, and more
11761 portable than perror() or others.  The output is usually of the form:
11762
11763 <tscreen><verb>
11764 program name:function that failed:file or further description:strerror
11765 </verb></tscreen>
11766
11767 Here's an example of one such call used in our hello_world program:
11768
11769 <tscreen><verb>
11770 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
11771 </verb></tscreen>
11772
11773 <tscreen><verb>
11774 void g_error( gchar *format, ... );
11775 </verb></tscreen>
11776
11777 Prints an error message. The format is just like printf, but it
11778 prepends "** ERROR **: " to your message, and exits the program.  
11779 Use only for fatal errors.
11780
11781 <tscreen><verb>
11782 void g_warning( gchar *format, ... );
11783 </verb></tscreen>
11784
11785 Same as above, but prepends "** WARNING **: ", and does not exit the
11786 program.
11787
11788 <tscreen><verb>
11789 void g_message( gchar *format, ... );
11790 </verb></tscreen>
11791
11792 Prints "message: " prepended to the string you pass in.
11793
11794 <tscreen><verb>
11795 void g_print( gchar *format, ... );
11796 </verb></tscreen>
11797
11798 Replacement for printf().
11799
11800 And our last function:
11801
11802 <tscreen><verb>
11803 gchar *g_strsignal( gint signum );
11804 </verb></tscreen>
11805
11806 Prints out the name of the Unix system signal given the signal number.
11807 Useful in generic signal handling functions.
11808
11809 All of the above are more or less just stolen from glib.h.  If anyone cares
11810 to document any function, just send me an email!
11811
11812 <!-- ***************************************************************** -->
11813 <sect>GTK's rc Files <label id="sec_gtkrc_files">
11814 <!-- ***************************************************************** -->
11815 <p>
11816 GTK has its own way of dealing with application defaults, by using rc
11817 files. These can be used to set the colors of just about any widget, and
11818 can also be used to tile pixmaps onto the background of some widgets.  
11819
11820 <!-- ----------------------------------------------------------------- -->
11821 <sect1>Functions For rc Files 
11822 <p>
11823 When your application starts, you should include a call to:
11824
11825 <tscreen><verb>
11826 void gtk_rc_parse( char *filename );
11827 </verb></tscreen>
11828
11829 Passing in the filename of your rc file. This will cause GTK to parse
11830 this file, and use the style settings for the widget types defined
11831 there.
11832
11833 If you wish to have a special set of widgets that can take on a
11834 different style from others, or any other logical division of widgets,
11835 use a call to:
11836
11837 <tscreen><verb>
11838 void gtk_widget_set_name( GtkWidget *widget,
11839                           gchar     *name );
11840 </verb></tscreen>
11841
11842 Passing your newly created widget as the first argument, and the name
11843 you wish to give it as the second. This will allow you to change the
11844 attributes of this widget by name through the rc file.
11845
11846 If we use a call something like this:
11847
11848 <tscreen><verb>
11849 button = gtk_button_new_with_label ("Special Button");
11850 gtk_widget_set_name (button, "special button");
11851 </verb></tscreen>
11852
11853 Then this button is given the name "special button" and may be addressed by
11854 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]
11855
11856 The example rc file below, sets the properties of the main window, and lets
11857 all children of that main window inherit the style described by the "main
11858 button" style.  The code used in the application is:
11859
11860 <tscreen><verb>
11861 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11862 gtk_widget_set_name (window, "main window");
11863 </verb></tscreen>
11864
11865 And then the style is defined in the rc file using:
11866
11867 <tscreen><verb>
11868 widget "main window.*GtkButton*" style "main_button"
11869 </verb></tscreen>
11870
11871 Which sets all the Button widgets in the "main window" to the
11872 "main_buttons" style as defined in the rc file.
11873
11874 As you can see, this is a fairly powerful and flexible system.  Use your
11875 imagination as to how best to take advantage of this.
11876
11877 <!-- ----------------------------------------------------------------- -->
11878 <sect1>GTK's rc File Format
11879 <p>
11880 The format of the GTK file is illustrated in the example below. This is
11881 the testgtkrc file from the GTK distribution, but I've added a
11882 few comments and things. You may wish to include this explanation in
11883 your application to allow the user to fine tune his application.
11884
11885 There are several directives to change the attributes of a widget.
11886
11887 <itemize>
11888 <item>fg - Sets the foreground color of a widget.
11889 <item>bg - Sets the background color of a widget.
11890 <item>bg_pixmap - Sets the background of a widget to a tiled pixmap.
11891 <item>font - Sets the font to be used with the given widget.
11892 </itemize>
11893
11894 In addition to this, there are several states a widget can be in, and you
11895 can set different colors, pixmaps and fonts for each state. These states are:
11896
11897 <itemize>
11898 <item>NORMAL - The normal state of a widget, without the mouse over top of
11899 it, and not being pressed, etc.
11900 <item>PRELIGHT - When the mouse is over top of the widget, colors defined
11901 using this state will be in effect.
11902 <item>ACTIVE - When the widget is pressed or clicked it will be active, and
11903 the attributes assigned by this tag will be in effect.
11904 <item>INSENSITIVE - When a widget is set insensitive, and cannot be
11905 activated, it will take these attributes.
11906 <item>SELECTED - When an object is selected, it takes these attributes.
11907 </itemize>
11908
11909 When using the "fg" and "bg" keywords to set the colors of widgets, the
11910 format is:
11911
11912 <tscreen><verb>
11913 fg[<STATE>] = { Red, Green, Blue }
11914 </verb></tscreen>
11915
11916 Where STATE is one of the above states (PRELIGHT, ACTIVE, etc), and the Red,
11917 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
11918 white. They must be in float form, or they will register as 0, so a straight 
11919 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
11920 doesn't matter if it's not recognized.  Unrecognized values are set to 0.
11921
11922 bg_pixmap is very similar to the above, except the colors are replaced by a
11923 filename.
11924
11925 pixmap_path is a list of paths separated by ":"'s.  These paths will be
11926 searched for any pixmap you specify.
11927
11928 The font directive is simply:
11929 <tscreen><verb>
11930 font = "<font name>"
11931 </verb></tscreen>
11932
11933 The only hard part is figuring out the font string. Using xfontsel or
11934 a similar utility should help.
11935
11936 The "widget_class" sets the style of a class of widgets. These classes are
11937 listed in the widget overview on the class hierarchy.
11938
11939 The "widget" directive sets a specifically named set of widgets to a
11940 given style, overriding any style set for the given widget class.
11941 These widgets are registered inside the application using the
11942 gtk_widget_set_name() call. This allows you to specify the attributes of a
11943 widget on a per widget basis, rather than setting the attributes of an
11944 entire widget class. I urge you to document any of these special widgets so
11945 users may customize them.
11946
11947 When the keyword <tt>parent</> is used as an attribute, the widget will take on
11948 the attributes of its parent in the application.
11949
11950 When defining a style, you may assign the attributes of a previously defined
11951 style to this new one.
11952
11953 <tscreen><verb>
11954 style "main_button" = "button"
11955 {
11956   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
11957   bg[PRELIGHT] = { 0.75, 0, 0 }
11958 }
11959 </verb></tscreen>
11960
11961 This example takes the "button" style, and creates a new "main_button" style
11962 simply by changing the font and prelight background color of the "button"
11963 style.
11964
11965 Of course, many of these attributes don't apply to all widgets. It's a
11966 simple matter of common sense really. Anything that could apply, should.
11967
11968 <!-- ----------------------------------------------------------------- -->
11969 <sect1>Example rc file
11970 <p>
11971
11972 <tscreen><verb>
11973 # pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
11974 #
11975 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
11976 #
11977 # style <name> [= <name>]
11978 # {
11979 #   <option>
11980 # }
11981 #
11982 # widget <widget_set> style <style_name>
11983 # widget_class <widget_class_set> style <style_name>
11984
11985
11986 # Here is a list of all the possible states.  Note that some do not apply to
11987 # certain widgets.
11988 #
11989 # NORMAL - The normal state of a widget, without the mouse over top of
11990 # it, and not being pressed, etc.
11991 #
11992 # PRELIGHT - When the mouse is over top of the widget, colors defined
11993 # using this state will be in effect.
11994 #
11995 # ACTIVE - When the widget is pressed or clicked it will be active, and
11996 # the attributes assigned by this tag will be in effect.
11997 #
11998 # INSENSITIVE - When a widget is set insensitive, and cannot be
11999 # activated, it will take these attributes.
12000 #
12001 # SELECTED - When an object is selected, it takes these attributes.
12002 #
12003 # Given these states, we can set the attributes of the widgets in each of
12004 # these states using the following directives.
12005 #
12006 # fg - Sets the foreground color of a widget.
12007 # fg - Sets the background color of a widget.
12008 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
12009 # font - Sets the font to be used with the given widget.
12010 #
12011
12012 # This sets a style called "button".  The name is not really important, as
12013 # it is assigned to the actual widgets at the bottom of the file.
12014
12015 style "window"
12016 {
12017   #This sets the padding around the window to the pixmap specified.
12018   #bg_pixmap[<STATE>] = "<pixmap filename>"
12019   bg_pixmap[NORMAL] = "warning.xpm"
12020 }
12021
12022 style "scale"
12023 {
12024   #Sets the foreground color (font color) to red when in the "NORMAL"
12025   #state.
12026   
12027   fg[NORMAL] = { 1.0, 0, 0 }
12028   
12029   #Sets the background pixmap of this widget to that of its parent.
12030   bg_pixmap[NORMAL] = "<parent>"
12031 }
12032
12033 style "button"
12034 {
12035   # This shows all the possible states for a button.  The only one that
12036   # doesn't apply is the SELECTED state.
12037   
12038   fg[PRELIGHT] = { 0, 1.0, 1.0 }
12039   bg[PRELIGHT] = { 0, 0, 1.0 }
12040   bg[ACTIVE] = { 1.0, 0, 0 }
12041   fg[ACTIVE] = { 0, 1.0, 0 }
12042   bg[NORMAL] = { 1.0, 1.0, 0 }
12043   fg[NORMAL] = { .99, 0, .99 }
12044   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
12045   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
12046 }
12047
12048 # In this example, we inherit the attributes of the "button" style and then
12049 # override the font and background color when prelit to create a new
12050 # "main_button" style.
12051
12052 style "main_button" = "button"
12053 {
12054   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
12055   bg[PRELIGHT] = { 0.75, 0, 0 }
12056 }
12057
12058 style "toggle_button" = "button"
12059 {
12060   fg[NORMAL] = { 1.0, 0, 0 }
12061   fg[ACTIVE] = { 1.0, 0, 0 }
12062   
12063   # This sets the background pixmap of the toggle_button to that of its
12064   # parent widget (as defined in the application).
12065   bg_pixmap[NORMAL] = "<parent>"
12066 }
12067
12068 style "text"
12069 {
12070   bg_pixmap[NORMAL] = "marble.xpm"
12071   fg[NORMAL] = { 1.0, 1.0, 1.0 }
12072 }
12073
12074 style "ruler"
12075 {
12076   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
12077 }
12078
12079 # pixmap_path "~/.pixmaps"
12080
12081 # These set the widget types to use the styles defined above.
12082 # The widget types are listed in the class hierarchy, but could probably be
12083 # just listed in this document for the users reference.
12084
12085 widget_class "GtkWindow" style "window"
12086 widget_class "GtkDialog" style "window"
12087 widget_class "GtkFileSelection" style "window"
12088 widget_class "*Gtk*Scale" style "scale"
12089 widget_class "*GtkCheckButton*" style "toggle_button"
12090 widget_class "*GtkRadioButton*" style "toggle_button"
12091 widget_class "*GtkButton*" style "button"
12092 widget_class "*Ruler" style "ruler"
12093 widget_class "*GtkText" style "text"
12094
12095 # This sets all the buttons that are children of the "main window" to
12096 # the main_button style.  These must be documented to be taken advantage of.
12097 widget "main window.*GtkButton*" style "main_button"
12098 </verb></tscreen>
12099
12100 <!-- ***************************************************************** -->
12101 <sect>Writing Your Own Widgets 
12102 <!-- ***************************************************************** -->
12103
12104 <!-- ----------------------------------------------------------------- -->
12105 <sect1> Overview
12106 <p>
12107 Although the GTK distribution comes with many types of widgets that
12108 should cover most basic needs, there may come a time when you need to
12109 create your own new widget type. Since GTK uses widget inheritance
12110 extensively, and there is already a widget that is close to what you want,
12111 it is often possible to make a useful new widget type in
12112 just a few lines of code. But before starting work on a new widget, check
12113 around first to make sure that someone has not already written
12114 it. This will prevent duplication of effort and keep the number of
12115 GTK widgets out there to a minimum, which will help keep both the code
12116 and the interface of different applications consistent. As a flip side
12117 to this, once you finish your widget, announce it to the world so
12118 other people can benefit. The best place to do this is probably the
12119 <tt>gtk-list</tt>.
12120
12121 Complete sources for the example widgets are available at the place you 
12122 got this tutorial, or from:
12123
12124 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
12125 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
12126
12127
12128 <!-- ----------------------------------------------------------------- -->
12129 <sect1> The Anatomy Of A Widget
12130 <p>
12131 In order to create a new widget, it is important to have an
12132 understanding of how GTK objects work. This section is just meant as a
12133 brief overview. See the reference documentation for the details. 
12134
12135 GTK widgets are implemented in an object oriented fashion. However,
12136 they are implemented in standard C. This greatly improves portability
12137 and stability over using current generation C++ compilers; however,
12138 it does mean that the widget writer has to pay attention to some of
12139 the implementation details. The information common to all instances of
12140 one class of widgets (e.g., to all Button widgets) is stored in the 
12141 <em>class structure</em>. There is only one copy of this in
12142 which is stored information about the class's signals
12143 (which act like virtual functions in C). To support inheritance, the
12144 first field in the class structure must be a copy of the parent's
12145 class structure. The declaration of the class structure of GtkButtton
12146 looks like:
12147
12148 <tscreen><verb>
12149 struct _GtkButtonClass
12150 {
12151   GtkContainerClass parent_class;
12152
12153   void (* pressed)  (GtkButton *button);
12154   void (* released) (GtkButton *button);
12155   void (* clicked)  (GtkButton *button);
12156   void (* enter)    (GtkButton *button);
12157   void (* leave)    (GtkButton *button);
12158 };
12159 </verb></tscreen>
12160
12161 When a button is treated as a container (for instance, when it is
12162 resized), its class structure can be cast to GtkContainerClass, and
12163 the relevant fields used to handle the signals.
12164
12165 There is also a structure for each widget that is created on a
12166 per-instance basis. This structure has fields to store information that
12167 is different for each instance of the widget. We'll call this
12168 structure the <em>object structure</em>. For the Button class, it looks
12169 like:
12170
12171 <tscreen><verb>
12172 struct _GtkButton
12173 {
12174   GtkContainer container;
12175
12176   GtkWidget *child;
12177
12178   guint in_button : 1;
12179   guint button_down : 1;
12180 };
12181 </verb></tscreen>
12182
12183 Note that, similar to the class structure, the first field is the
12184 object structure of the parent class, so that this structure can be
12185 cast to the parent class' object structure as needed.
12186
12187 <!-- ----------------------------------------------------------------- -->
12188 <sect1> Creating a Composite widget
12189
12190 <!-- ----------------------------------------------------------------- -->
12191 <sect2> Introduction
12192 <p>
12193 One type of widget that you may be interested in creating is a
12194 widget that is merely an aggregate of other GTK widgets. This type of
12195 widget does nothing that couldn't be done without creating new
12196 widgets, but provides a convenient way of packaging user interface
12197 elements for reuse. The FileSelection and ColorSelection widgets in
12198 the standard distribution are examples of this type of widget.
12199
12200 The example widget that we'll create in this section is the Tictactoe
12201 widget, a 3x3 array of toggle buttons which triggers a signal when all
12202 three buttons in a row, column, or on one of the diagonals are
12203 depressed. 
12204
12205 <!-- ----------------------------------------------------------------- -->
12206 <sect2> Choosing a parent class
12207 <p>
12208 The parent class for a composite widget is typically the container
12209 class that holds all of the elements of the composite widget. For
12210 example, the parent class of the FileSelection widget is the
12211 Dialog class. Since our buttons will be arranged in a table, it
12212 might seem natural to make our parent class the Table
12213 class. Unfortunately, this turns out not to work. The creation of a
12214 widget is divided among two functions - a <tt/WIDGETNAME_new()/
12215 function that the user calls, and a <tt/WIDGETNAME_init()/ function
12216 which does the basic work of initializing the widget which is
12217 independent of the arguments passed to the <tt/_new()/
12218 function. Descendant widgets only call the <tt/_init/ function of
12219 their parent widget. But this division of labor doesn't work well for
12220 tables, which when created need to know the number of rows and
12221 columns in the table. Unless we want to duplicate most of the
12222 functionality of <tt/gtk_table_new()/ in our Tictactoe widget, we had
12223 best avoid deriving it from Table. For that reason, we derive it
12224 from VBox instead, and stick our table inside the VBox.
12225
12226 <!-- ----------------------------------------------------------------- -->
12227 <sect2> The header file
12228 <p>
12229 Each widget class has a header file which declares the object and
12230 class structures for that widget, along with public functions. 
12231 A couple of features are worth pointing out. To prevent duplicate
12232 definitions, we wrap the entire header file in:
12233
12234 <tscreen><verb>
12235 #ifndef __TICTACTOE_H__
12236 #define __TICTACTOE_H__
12237 .
12238 .
12239 .
12240 #endif /* __TICTACTOE_H__ */
12241 </verb></tscreen>
12242
12243 And to keep C++ programs that include the header file happy, in:
12244
12245 <tscreen><verb>
12246 #ifdef __cplusplus
12247 extern "C" {
12248 #endif /* __cplusplus */
12249 .
12250 .
12251 .
12252 #ifdef __cplusplus
12253 }
12254 #endif /* __cplusplus */
12255 </verb></tscreen>
12256
12257 Along with the functions and structures, we declare three standard
12258 macros in our header file, <tt/TICTACTOE(obj)/,
12259 <tt/TICTACTOE_CLASS(klass)/, and <tt/IS_TICTACTOE(obj)/, which cast a
12260 pointer into a pointer to the object or class structure, and check
12261 if an object is a Tictactoe widget respectively.
12262
12263 Here is the complete header file:
12264
12265 <tscreen><verb>
12266 /* tictactoe.h */
12267
12268 #ifndef __TICTACTOE_H__
12269 #define __TICTACTOE_H__
12270
12271 #include <gdk/gdk.h>
12272 #include <gtk/gtkvbox.h>
12273
12274 #ifdef __cplusplus
12275 extern "C" {
12276 #endif /* __cplusplus */
12277
12278 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
12279 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
12280 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
12281
12282
12283 typedef struct _Tictactoe       Tictactoe;
12284 typedef struct _TictactoeClass  TictactoeClass;
12285
12286 struct _Tictactoe
12287 {
12288   GtkVBox vbox;
12289   
12290   GtkWidget *buttons[3][3];
12291 };
12292
12293 struct _TictactoeClass
12294 {
12295   GtkVBoxClass parent_class;
12296
12297   void (* tictactoe) (Tictactoe *ttt);
12298 };
12299
12300 guint          tictactoe_get_type        (void);
12301 GtkWidget*     tictactoe_new             (void);
12302 void           tictactoe_clear           (Tictactoe *ttt);
12303
12304 #ifdef __cplusplus
12305 }
12306 #endif /* __cplusplus */
12307
12308 #endif /* __TICTACTOE_H__ */
12309
12310 </verb></tscreen>
12311
12312 <!-- ----------------------------------------------------------------- -->
12313 <sect2> The <tt/_get_type()/ function.
12314 <p>
12315 We now continue on to the implementation of our widget. A core
12316 function for every widget is the function
12317 <tt/WIDGETNAME_get_type()/. This function, when first called, tells
12318 GTK about the widget class, and gets an ID that uniquely identifies
12319 the widget class. Upon subsequent calls, it just returns the ID.
12320
12321 <tscreen><verb>
12322 guint
12323 tictactoe_get_type ()
12324 {
12325   static guint ttt_type = 0;
12326
12327   if (!ttt_type)
12328     {
12329       GtkTypeInfo ttt_info =
12330       {
12331         "Tictactoe",
12332         sizeof (Tictactoe),
12333         sizeof (TictactoeClass),
12334         (GtkClassInitFunc) tictactoe_class_init,
12335         (GtkObjectInitFunc) tictactoe_init,
12336         (GtkArgSetFunc) NULL,
12337         (GtkArgGetFunc) NULL
12338       };
12339
12340       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
12341     }
12342
12343   return ttt_type;
12344 }
12345 </verb></tscreen>
12346
12347 The GtkTypeInfo structure has the following definition:
12348
12349 <tscreen><verb>
12350 struct _GtkTypeInfo
12351 {
12352   gchar *type_name;
12353   guint object_size;
12354   guint class_size;
12355   GtkClassInitFunc class_init_func;
12356   GtkObjectInitFunc object_init_func;
12357   GtkArgSetFunc arg_set_func;
12358   GtkArgGetFunc arg_get_func;
12359 };
12360 </verb></tscreen>
12361
12362 The fields of this structure are pretty self-explanatory. We'll ignore
12363 the <tt/arg_set_func/ and <tt/arg_get_func/ fields here: they have an important, 
12364 but as yet largely
12365 unimplemented, role in allowing widget options to be conveniently set
12366 from interpreted languages. Once GTK has a correctly filled in copy of
12367 this structure, it knows how to create objects of a particular widget
12368 type. 
12369
12370 <!-- ----------------------------------------------------------------- -->
12371 <sect2> The <tt/_class_init()/ function
12372 <p>
12373 The <tt/WIDGETNAME_class_init()/ function initializes the fields of
12374 the widget's class structure, and sets up any signals for the
12375 class. For our Tictactoe widget it looks like:
12376
12377 <tscreen><verb>
12378
12379 enum {
12380   TICTACTOE_SIGNAL,
12381   LAST_SIGNAL
12382 };
12383
12384 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
12385
12386 static void
12387 tictactoe_class_init (TictactoeClass *class)
12388 {
12389   GtkObjectClass *object_class;
12390
12391   object_class = (GtkObjectClass*) class;
12392   
12393   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
12394                                          GTK_RUN_FIRST,
12395                                          object_class->type,
12396                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
12397                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
12398
12399
12400   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
12401
12402   class->tictactoe = NULL;
12403 }
12404 </verb></tscreen>
12405
12406 Our widget has just one signal, the <tt/tictactoe/ signal that is
12407 invoked when a row, column, or diagonal is completely filled in. Not
12408 every composite widget needs signals, so if you are reading this for
12409 the first time, you may want to skip to the next section now, as
12410 things are going to get a bit complicated.
12411
12412 The function:
12413
12414 <tscreen><verb>
12415 gint gtk_signal_new( const gchar         *name,
12416                      GtkSignalRunType     run_type,
12417                      GtkType              object_type,
12418                      gint                 function_offset,
12419                      GtkSignalMarshaller  marshaller,
12420                      GtkType              return_val,
12421                      guint                nparams,
12422                      ...);
12423 </verb></tscreen>
12424
12425 Creates a new signal. The parameters are:
12426
12427 <itemize>
12428 <item> <tt/name/: The name of the signal.
12429 <item> <tt/run_type/: Whether the default handler runs before or after
12430 user handlers. Usually this will be <tt/GTK_RUN_FIRST/, or <tt/GTK_RUN_LAST/,
12431 although there are other possibilities.
12432 <item> <tt/object_type/: The ID of the object that this signal applies
12433 to. (It will also apply to that objects descendants.)
12434 <item> <tt/function_offset/: The offset within the class structure of
12435 a pointer to the default handler.
12436 <item> <tt/marshaller/: A function that is used to invoke the signal
12437 handler. For signal handlers that have no arguments other than the
12438 object that emitted the signal and user data, we can use the
12439 pre-supplied marshaller function <tt/gtk_signal_default_marshaller/.
12440 <item> <tt/return_val/: The type of the return val.
12441 <item> <tt/nparams/: The number of parameters of the signal handler
12442 (other than the two default ones mentioned above)
12443 <item> <tt/.../: The types of the parameters.
12444 </itemize>
12445
12446 When specifying types, the <tt/GtkType/ enumeration is used:
12447
12448 <tscreen><verb>
12449 typedef enum
12450 {
12451   GTK_TYPE_INVALID,
12452   GTK_TYPE_NONE,
12453   GTK_TYPE_CHAR,
12454   GTK_TYPE_BOOL,
12455   GTK_TYPE_INT,
12456   GTK_TYPE_UINT,
12457   GTK_TYPE_LONG,
12458   GTK_TYPE_ULONG,
12459   GTK_TYPE_FLOAT,
12460   GTK_TYPE_DOUBLE,
12461   GTK_TYPE_STRING,
12462   GTK_TYPE_ENUM,
12463   GTK_TYPE_FLAGS,
12464   GTK_TYPE_BOXED,
12465   GTK_TYPE_FOREIGN,
12466   GTK_TYPE_CALLBACK,
12467   GTK_TYPE_ARGS,
12468
12469   GTK_TYPE_POINTER,
12470
12471   /* it'd be great if the next two could be removed eventually */
12472   GTK_TYPE_SIGNAL,
12473   GTK_TYPE_C_CALLBACK,
12474
12475   GTK_TYPE_OBJECT
12476
12477 } GtkFundamentalType;
12478 </verb></tscreen>
12479
12480 <tt/gtk_signal_new()/ returns a unique integer identifier for the
12481 signal, that we store in the <tt/tictactoe_signals/ array, which we
12482 index using an enumeration. (Conventionally, the enumeration elements
12483 are the signal name, uppercased, but here there would be a conflict
12484 with the <tt/TICTACTOE()/ macro, so we called it <tt/TICTACTOE_SIGNAL/
12485 instead.
12486
12487 After creating our signals, we need to tell GTK to associate our
12488 signals with the Tictactoe class. We do that by calling
12489 <tt/gtk_object_class_add_signals()/. We then set the pointer which
12490 points to the default handler for the "tictactoe" signal to NULL,
12491 indicating that there is no default action.
12492
12493 <!-- ----------------------------------------------------------------- -->
12494 <sect2> The <tt/_init()/ function.
12495 <p>
12496 Each widget class also needs a function to initialize the object
12497 structure. Usually, this function has the fairly limited role of
12498 setting the fields of the structure to default values. For composite
12499 widgets, however, this function also creates the component widgets.
12500
12501 <tscreen><verb>
12502 static void
12503 tictactoe_init (Tictactoe *ttt)
12504 {
12505   GtkWidget *table;
12506   gint i,j;
12507   
12508   table = gtk_table_new (3, 3, TRUE);
12509   gtk_container_add (GTK_CONTAINER(ttt), table);
12510   gtk_widget_show (table);
12511
12512   for (i=0;i<3; i++)
12513     for (j=0;j<3; j++)
12514       {
12515         ttt->buttons[i][j] = gtk_toggle_button_new ();
12516         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
12517                                    i, i+1, j, j+1);
12518         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
12519                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
12520         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
12521         gtk_widget_show (ttt->buttons[i][j]);
12522       }
12523 }
12524 </verb></tscreen>
12525
12526 <!-- ----------------------------------------------------------------- -->
12527 <sect2> And the rest...
12528 <p>
12529 There is one more function that every widget (except for base widget
12530 types like Bin that cannot be instantiated) needs to have - the
12531 function that the user calls to create an object of that type. This is
12532 conventionally called <tt/WIDGETNAME_new()/. In some
12533 widgets, though not for the Tictactoe widgets, this function takes
12534 arguments, and does some setup based on the arguments. The other two
12535 functions are specific to the Tictactoe widget. 
12536
12537 <tt/tictactoe_clear()/ is a public function that resets all the
12538 buttons in the widget to the up position. Note the use of
12539 <tt/gtk_signal_handler_block_by_data()/ to keep our signal handler for
12540 button toggles from being triggered unnecessarily.
12541
12542 <tt/tictactoe_toggle()/ is the signal handler that is invoked when the
12543 user clicks on a button. It checks to see if there are any winning
12544 combinations that involve the toggled button, and if so, emits
12545 the "tictactoe" signal.
12546
12547 <tscreen><verb>  
12548 GtkWidget*
12549 tictactoe_new ()
12550 {
12551   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
12552 }
12553
12554 void           
12555 tictactoe_clear (Tictactoe *ttt)
12556 {
12557   int i,j;
12558
12559   for (i=0;i<3;i++)
12560     for (j=0;j<3;j++)
12561       {
12562         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
12563         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
12564                                      FALSE);
12565         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
12566       }
12567 }
12568
12569 static void
12570 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
12571 {
12572   int i,k;
12573
12574   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
12575                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
12576                              { 0, 1, 2 }, { 0, 1, 2 } };
12577   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
12578                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
12579                              { 0, 1, 2 }, { 2, 1, 0 } };
12580
12581   int success, found;
12582
12583   for (k=0; k<8; k++)
12584     {
12585       success = TRUE;
12586       found = FALSE;
12587
12588       for (i=0;i<3;i++)
12589         {
12590           success = success &amp;&amp; 
12591             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
12592           found = found ||
12593             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
12594         }
12595       
12596       if (success &amp;&amp; found)
12597         {
12598           gtk_signal_emit (GTK_OBJECT (ttt), 
12599                            tictactoe_signals[TICTACTOE_SIGNAL]);
12600           break;
12601         }
12602     }
12603 }
12604 </verb></tscreen>
12605
12606 And finally, an example program using our Tictactoe widget:
12607
12608 <tscreen><verb>
12609 #include <gtk/gtk.h>
12610 #include "tictactoe.h"
12611
12612 /* Invoked when a row, column or diagonal is completed */
12613 void
12614 win (GtkWidget *widget, gpointer data)
12615 {
12616   g_print ("Yay!\n");
12617   tictactoe_clear (TICTACTOE (widget));
12618 }
12619
12620 int 
12621 main (int argc, char *argv[])
12622 {
12623   GtkWidget *window;
12624   GtkWidget *ttt;
12625   
12626   gtk_init (&amp;argc, &amp;argv);
12627
12628   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12629   
12630   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
12631   
12632   gtk_signal_connect (GTK_OBJECT (window), "destroy",
12633                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
12634   
12635   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12636
12637   /* Create a new Tictactoe widget */
12638   ttt = tictactoe_new ();
12639   gtk_container_add (GTK_CONTAINER (window), ttt);
12640   gtk_widget_show (ttt);
12641
12642   /* And attach to its "tictactoe" signal */
12643   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
12644                       GTK_SIGNAL_FUNC (win), NULL);
12645
12646   gtk_widget_show (window);
12647   
12648   gtk_main ();
12649   
12650   return 0;
12651 }
12652
12653 </verb></tscreen>
12654
12655 <!-- ----------------------------------------------------------------- -->
12656 <sect1> Creating a widget from scratch.
12657
12658 <!-- ----------------------------------------------------------------- -->
12659 <sect2> Introduction
12660 <p>
12661 In this section, we'll learn more about how widgets display themselves
12662 on the screen and interact with events. As an example of this, we'll
12663 create an analog dial widget with a pointer that the user can drag to
12664 set the value.
12665
12666 <!-- ----------------------------------------------------------------- -->
12667 <sect2> Displaying a widget on the screen
12668 <p>
12669 There are several steps that are involved in displaying on the screen.
12670 After the widget is created with a call to <tt/WIDGETNAME_new()/,
12671 several more functions are needed:
12672
12673 <itemize>
12674 <item> <tt/WIDGETNAME_realize()/ is responsible for creating an X
12675 window for the widget if it has one.
12676 <item> <tt/WIDGETNAME_map()/ is invoked after the user calls
12677 <tt/gtk_widget_show()/. It is responsible for making sure the widget
12678 is actually drawn on the screen (<em/mapped/). For a container class,
12679 it must also make calls to <tt/map()/> functions of any child widgets.
12680 <item> <tt/WIDGETNAME_draw()/ is invoked when <tt/gtk_widget_draw()/
12681 is called for the widget or one of its ancestors. It makes the actual
12682 calls to the drawing functions to draw the widget on the screen. For
12683 container widgets, this function must make calls to
12684 <tt/gtk_widget_draw()/ for its child widgets.
12685 <item> <tt/WIDGETNAME_expose()/ is a handler for expose events for the
12686 widget. It makes the necessary calls to the drawing functions to draw
12687 the exposed portion on the screen. For container widgets, this
12688 function must generate expose events for its child widgets which don't
12689 have their own windows. (If they have their own windows, then X will
12690 generate the necessary expose events.)
12691 </itemize>
12692
12693 You might notice that the last two functions are quite similar - each
12694 is responsible for drawing the widget on the screen. In fact many
12695 types of widgets don't really care about the difference between the
12696 two. The default <tt/draw()/ function in the widget class simply
12697 generates a synthetic expose event for the redrawn area. However, some
12698 types of widgets can save work by distinguishing between the two
12699 functions. For instance, if a widget has multiple X windows, then
12700 since expose events identify the exposed window, it can redraw only
12701 the affected window, which is not possible for calls to <tt/draw()/.
12702
12703 Container widgets, even if they don't care about the difference for
12704 themselves, can't simply use the default <tt/draw()/ function because
12705 their child widgets might care about the difference. However,
12706 it would be wasteful to duplicate the drawing code between the two
12707 functions. The convention is that such widgets have a function called
12708 <tt/WIDGETNAME_paint()/ that does the actual work of drawing the
12709 widget, that is then called by the <tt/draw()/ and <tt/expose()/
12710 functions.
12711
12712 In our example approach, since the dial widget is not a container
12713 widget, and only has a single window, we can take the simplest
12714 approach and use the default <tt/draw()/ function and only implement
12715 an <tt/expose()/ function.
12716
12717 <!-- ----------------------------------------------------------------- -->
12718 <sect2> The origins of the Dial Widget
12719 <p>
12720 Just as all land animals are just variants on the first amphibian that
12721 crawled up out of the mud, GTK widgets tend to start off as variants
12722 of some other, previously written widget. Thus, although this section
12723 is entitled "Creating a Widget from Scratch", the Dial widget really
12724 began with the source code for the Range widget. This was picked as a
12725 starting point because it would be nice if our Dial had the same
12726 interface as the Scale widgets which are just specialized descendants
12727 of the Range widget. So, though the source code is presented below in
12728 finished form, it should not be implied that it was written, <em>ab
12729 initio</em> in this fashion. Also, if you aren't yet familiar with
12730 how scale widgets work from the application writer's point of view, it
12731 would be a good idea to look them over before continuing.
12732
12733 <!-- ----------------------------------------------------------------- -->
12734 <sect2> The Basics
12735 <p>
12736 Quite a bit of our widget should look pretty familiar from the
12737 Tictactoe widget. First, we have a header file:
12738
12739 <tscreen><verb>
12740 /* GTK - The GIMP Toolkit
12741  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
12742  *
12743  * This library is free software; you can redistribute it and/or
12744  * modify it under the terms of the GNU Library General Public
12745  * License as published by the Free Software Foundation; either
12746  * version 2 of the License, or (at your option) any later version.
12747  *
12748  * This library is distributed in the hope that it will be useful,
12749  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12750  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12751  * Library General Public License for more details.
12752  *
12753  * You should have received a copy of the GNU Library General Public
12754  * License along with this library; if not, write to the Free
12755  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
12756  */
12757
12758 #ifndef __GTK_DIAL_H__
12759 #define __GTK_DIAL_H__
12760
12761 #include <gdk/gdk.h>
12762 #include <gtk/gtkadjustment.h>
12763 #include <gtk/gtkwidget.h>
12764
12765
12766 #ifdef __cplusplus
12767 extern "C" {
12768 #endif /* __cplusplus */
12769
12770
12771 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
12772 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
12773 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
12774
12775
12776 typedef struct _GtkDial        GtkDial;
12777 typedef struct _GtkDialClass   GtkDialClass;
12778
12779 struct _GtkDial
12780 {
12781   GtkWidget widget;
12782
12783   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
12784   guint policy : 2;
12785
12786   /* Button currently pressed or 0 if none */
12787   guint8 button;
12788
12789   /* Dimensions of dial components */
12790   gint radius;
12791   gint pointer_width;
12792
12793   /* ID of update timer, or 0 if none */
12794   guint32 timer;
12795
12796   /* Current angle */
12797   gfloat angle;
12798
12799   /* Old values from adjustment stored so we know when something changes */
12800   gfloat old_value;
12801   gfloat old_lower;
12802   gfloat old_upper;
12803
12804   /* The adjustment object that stores the data for this dial */
12805   GtkAdjustment *adjustment;
12806 };
12807
12808 struct _GtkDialClass
12809 {
12810   GtkWidgetClass parent_class;
12811 };
12812
12813
12814 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
12815 guint          gtk_dial_get_type               (void);
12816 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
12817 void           gtk_dial_set_update_policy      (GtkDial      *dial,
12818                                                 GtkUpdateType  policy);
12819
12820 void           gtk_dial_set_adjustment         (GtkDial      *dial,
12821                                                 GtkAdjustment *adjustment);
12822 #ifdef __cplusplus
12823 }
12824 #endif /* __cplusplus */
12825
12826
12827 #endif /* __GTK_DIAL_H__ */
12828 </verb></tscreen>
12829
12830 Since there is quite a bit more going on in this widget than the last
12831 one, we have more fields in the data structure, but otherwise things
12832 are pretty similar.
12833
12834 Next, after including header files and declaring a few constants,
12835 we have some functions to provide information about the widget
12836 and initialize it:
12837
12838 <tscreen><verb>
12839 #include <math.h>
12840 #include <stdio.h>
12841 #include <gtk/gtkmain.h>
12842 #include <gtk/gtksignal.h>
12843
12844 #include "gtkdial.h"
12845
12846 #define SCROLL_DELAY_LENGTH  300
12847 #define DIAL_DEFAULT_SIZE 100
12848
12849 /* Forward declarations */
12850
12851 [ omitted to save space ]
12852
12853 /* Local data */
12854
12855 static GtkWidgetClass *parent_class = NULL;
12856
12857 guint
12858 gtk_dial_get_type ()
12859 {
12860   static guint dial_type = 0;
12861
12862   if (!dial_type)
12863     {
12864       GtkTypeInfo dial_info =
12865       {
12866         "GtkDial",
12867         sizeof (GtkDial),
12868         sizeof (GtkDialClass),
12869         (GtkClassInitFunc) gtk_dial_class_init,
12870         (GtkObjectInitFunc) gtk_dial_init,
12871         (GtkArgSetFunc) NULL,
12872         (GtkArgGetFunc) NULL,
12873       };
12874
12875       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
12876     }
12877
12878   return dial_type;
12879 }
12880
12881 static void
12882 gtk_dial_class_init (GtkDialClass *class)
12883 {
12884   GtkObjectClass *object_class;
12885   GtkWidgetClass *widget_class;
12886
12887   object_class = (GtkObjectClass*) class;
12888   widget_class = (GtkWidgetClass*) class;
12889
12890   parent_class = gtk_type_class (gtk_widget_get_type ());
12891
12892   object_class->destroy = gtk_dial_destroy;
12893
12894   widget_class->realize = gtk_dial_realize;
12895   widget_class->expose_event = gtk_dial_expose;
12896   widget_class->size_request = gtk_dial_size_request;
12897   widget_class->size_allocate = gtk_dial_size_allocate;
12898   widget_class->button_press_event = gtk_dial_button_press;
12899   widget_class->button_release_event = gtk_dial_button_release;
12900   widget_class->motion_notify_event = gtk_dial_motion_notify;
12901 }
12902
12903 static void
12904 gtk_dial_init (GtkDial *dial)
12905 {
12906   dial->button = 0;
12907   dial->policy = GTK_UPDATE_CONTINUOUS;
12908   dial->timer = 0;
12909   dial->radius = 0;
12910   dial->pointer_width = 0;
12911   dial->angle = 0.0;
12912   dial->old_value = 0.0;
12913   dial->old_lower = 0.0;
12914   dial->old_upper = 0.0;
12915   dial->adjustment = NULL;
12916 }
12917
12918 GtkWidget*
12919 gtk_dial_new (GtkAdjustment *adjustment)
12920 {
12921   GtkDial *dial;
12922
12923   dial = gtk_type_new (gtk_dial_get_type ());
12924
12925   if (!adjustment)
12926     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
12927
12928   gtk_dial_set_adjustment (dial, adjustment);
12929
12930   return GTK_WIDGET (dial);
12931 }
12932
12933 static void
12934 gtk_dial_destroy (GtkObject *object)
12935 {
12936   GtkDial *dial;
12937
12938   g_return_if_fail (object != NULL);
12939   g_return_if_fail (GTK_IS_DIAL (object));
12940
12941   dial = GTK_DIAL (object);
12942
12943   if (dial->adjustment)
12944     gtk_object_unref (GTK_OBJECT (dial->adjustment));
12945
12946   if (GTK_OBJECT_CLASS (parent_class)->destroy)
12947     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
12948 }
12949 </verb></tscreen>
12950
12951 Note that this <tt/init()/ function does less than for the Tictactoe
12952 widget, since this is not a composite widget, and the <tt/new()/
12953 function does more, since it now has an argument. Also, note that when
12954 we store a pointer to the Adjustment object, we increment its
12955 reference count, (and correspondingly decrement it when we no longer
12956 use it) so that GTK can keep track of when it can be safely destroyed.
12957
12958 <p>
12959 Also, there are a few function to manipulate the widget's options:
12960
12961 <tscreen><verb>
12962 GtkAdjustment*
12963 gtk_dial_get_adjustment (GtkDial *dial)
12964 {
12965   g_return_val_if_fail (dial != NULL, NULL);
12966   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
12967
12968   return dial->adjustment;
12969 }
12970
12971 void
12972 gtk_dial_set_update_policy (GtkDial      *dial,
12973                              GtkUpdateType  policy)
12974 {
12975   g_return_if_fail (dial != NULL);
12976   g_return_if_fail (GTK_IS_DIAL (dial));
12977
12978   dial->policy = policy;
12979 }
12980
12981 void
12982 gtk_dial_set_adjustment (GtkDial      *dial,
12983                           GtkAdjustment *adjustment)
12984 {
12985   g_return_if_fail (dial != NULL);
12986   g_return_if_fail (GTK_IS_DIAL (dial));
12987
12988   if (dial->adjustment)
12989     {
12990       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
12991       gtk_object_unref (GTK_OBJECT (dial->adjustment));
12992     }
12993
12994   dial->adjustment = adjustment;
12995   gtk_object_ref (GTK_OBJECT (dial->adjustment));
12996
12997   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
12998                       (GtkSignalFunc) gtk_dial_adjustment_changed,
12999                       (gpointer) dial);
13000   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
13001                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
13002                       (gpointer) dial);
13003
13004   dial->old_value = adjustment->value;
13005   dial->old_lower = adjustment->lower;
13006   dial->old_upper = adjustment->upper;
13007
13008   gtk_dial_update (dial);
13009 }
13010 </verb></tscreen>
13011
13012 <sect2> <tt/gtk_dial_realize()/
13013
13014 <p>
13015 Now we come to some new types of functions. First, we have a function
13016 that does the work of creating the X window. Notice that a mask is
13017 passed to the function <tt/gdk_window_new()/ which specifies which fields of
13018 the GdkWindowAttr structure actually have data in them (the remaining
13019 fields will be given default values). Also worth noting is the way the
13020 event mask of the widget is created. We call
13021 <tt/gtk_widget_get_events()/ to retrieve the event mask that the user
13022 has specified for this widget (with <tt/gtk_widget_set_events()/), and
13023 add the events that we are interested in ourselves.
13024
13025 <p>
13026 After creating the window, we set its style and background, and put a
13027 pointer to the widget in the user data field of the GdkWindow. This
13028 last step allows GTK to dispatch events for this window to the correct
13029 widget.
13030
13031 <tscreen><verb>
13032 static void
13033 gtk_dial_realize (GtkWidget *widget)
13034 {
13035   GtkDial *dial;
13036   GdkWindowAttr attributes;
13037   gint attributes_mask;
13038
13039   g_return_if_fail (widget != NULL);
13040   g_return_if_fail (GTK_IS_DIAL (widget));
13041
13042   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
13043   dial = GTK_DIAL (widget);
13044
13045   attributes.x = widget->allocation.x;
13046   attributes.y = widget->allocation.y;
13047   attributes.width = widget->allocation.width;
13048   attributes.height = widget->allocation.height;
13049   attributes.wclass = GDK_INPUT_OUTPUT;
13050   attributes.window_type = GDK_WINDOW_CHILD;
13051   attributes.event_mask = gtk_widget_get_events (widget) | 
13052     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
13053     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
13054     GDK_POINTER_MOTION_HINT_MASK;
13055   attributes.visual = gtk_widget_get_visual (widget);
13056   attributes.colormap = gtk_widget_get_colormap (widget);
13057
13058   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
13059   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
13060
13061   widget->style = gtk_style_attach (widget->style, widget->window);
13062
13063   gdk_window_set_user_data (widget->window, widget);
13064
13065   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
13066 }
13067 </verb></tscreen>
13068
13069 <sect2> Size negotiation
13070
13071 <p>
13072 Before the first time that the window containing a widget is
13073 displayed, and whenever the layout of the window changes, GTK asks
13074 each child widget for its desired size. This request is handled by the
13075 function <tt/gtk_dial_size_request()/. Since our widget isn't a
13076 container widget, and has no real constraints on its size, we just
13077 return a reasonable default value.
13078
13079 <tscreen><verb>
13080 static void 
13081 gtk_dial_size_request (GtkWidget      *widget,
13082                        GtkRequisition *requisition)
13083 {
13084   requisition->width = DIAL_DEFAULT_SIZE;
13085   requisition->height = DIAL_DEFAULT_SIZE;
13086 }
13087 </verb></tscreen>
13088
13089 <p>
13090 After all the widgets have requested an ideal size, the layout of the
13091 window is computed and each child widget is notified of its actual
13092 size. Usually, this will be at least as large as the requested size,
13093 but if for instance the user has resized the window, it may
13094 occasionally be smaller than the requested size. The size notification
13095 is handled by the function <tt/gtk_dial_size_allocate()/. Notice that
13096 as well as computing the sizes of some component pieces for future
13097 use, this routine also does the grunt work of moving the widget's X
13098 window into the new position and size.
13099
13100 <tscreen><verb>
13101 static void
13102 gtk_dial_size_allocate (GtkWidget     *widget,
13103                         GtkAllocation *allocation)
13104 {
13105   GtkDial *dial;
13106
13107   g_return_if_fail (widget != NULL);
13108   g_return_if_fail (GTK_IS_DIAL (widget));
13109   g_return_if_fail (allocation != NULL);
13110
13111   widget->allocation = *allocation;
13112   if (GTK_WIDGET_REALIZED (widget))
13113     {
13114       dial = GTK_DIAL (widget);
13115
13116       gdk_window_move_resize (widget->window,
13117                               allocation->x, allocation->y,
13118                               allocation->width, allocation->height);
13119
13120       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
13121       dial->pointer_width = dial->radius / 5;
13122     }
13123 }
13124 </verb></tscreen>.
13125
13126 <!-- ----------------------------------------------------------------- -->
13127 <sect2> <tt/gtk_dial_expose()/
13128
13129 <p>
13130 As mentioned above, all the drawing of this widget is done in the
13131 handler for expose events. There's not much to remark on here except
13132 the use of the function <tt/gtk_draw_polygon/ to draw the pointer with
13133 three dimensional shading according to the colors stored in the
13134 widget's style.
13135
13136 <tscreen><verb>
13137 static gint
13138 gtk_dial_expose (GtkWidget      *widget,
13139                  GdkEventExpose *event)
13140 {
13141   GtkDial *dial;
13142   GdkPoint points[3];
13143   gdouble s,c;
13144   gdouble theta;
13145   gint xc, yc;
13146   gint tick_length;
13147   gint i;
13148
13149   g_return_val_if_fail (widget != NULL, FALSE);
13150   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13151   g_return_val_if_fail (event != NULL, FALSE);
13152
13153   if (event->count > 0)
13154     return FALSE;
13155   
13156   dial = GTK_DIAL (widget);
13157
13158   gdk_window_clear_area (widget->window,
13159                          0, 0,
13160                          widget->allocation.width,
13161                          widget->allocation.height);
13162
13163   xc = widget->allocation.width/2;
13164   yc = widget->allocation.height/2;
13165
13166   /* Draw ticks */
13167
13168   for (i=0; i<25; i++)
13169     {
13170       theta = (i*M_PI/18. - M_PI/6.);
13171       s = sin(theta);
13172       c = cos(theta);
13173
13174       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
13175       
13176       gdk_draw_line (widget->window,
13177                      widget->style->fg_gc[widget->state],
13178                      xc + c*(dial->radius - tick_length),
13179                      yc - s*(dial->radius - tick_length),
13180                      xc + c*dial->radius,
13181                      yc - s*dial->radius);
13182     }
13183
13184   /* Draw pointer */
13185
13186   s = sin(dial->angle);
13187   c = cos(dial->angle);
13188
13189
13190   points[0].x = xc + s*dial->pointer_width/2;
13191   points[0].y = yc + c*dial->pointer_width/2;
13192   points[1].x = xc + c*dial->radius;
13193   points[1].y = yc - s*dial->radius;
13194   points[2].x = xc - s*dial->pointer_width/2;
13195   points[2].y = yc - c*dial->pointer_width/2;
13196
13197   gtk_draw_polygon (widget->style,
13198                     widget->window,
13199                     GTK_STATE_NORMAL,
13200                     GTK_SHADOW_OUT,
13201                     points, 3,
13202                     TRUE);
13203   
13204   return FALSE;
13205 }
13206 </verb></tscreen>
13207
13208 <!-- ----------------------------------------------------------------- -->
13209 <sect2> Event handling
13210 <p>
13211 The rest of the widget's code handles various types of events, and
13212 isn't too different from what would be found in many GTK
13213 applications. Two types of events can occur - either the user can
13214 click on the widget with the mouse and drag to move the pointer, or
13215 the value of the Adjustment object can change due to some external
13216 circumstance. 
13217
13218 When the user clicks on the widget, we check to see if the click was
13219 appropriately near the pointer, and if so, store the button that the
13220 user clicked with in the <tt/button/ field of the widget
13221 structure, and grab all mouse events with a call to
13222 <tt/gtk_grab_add()/. Subsequent motion of the mouse causes the
13223 value of the control to be recomputed (by the function
13224 <tt/gtk_dial_update_mouse/). Depending on the policy that has been
13225 set, "value_changed" events are either generated instantly
13226 (<tt/GTK_UPDATE_CONTINUOUS/), after a delay in a timer added with
13227 <tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), or only when the
13228 button is released (<tt/GTK_UPDATE_DISCONTINUOUS/).
13229
13230 <tscreen><verb>
13231 static gint
13232 gtk_dial_button_press (GtkWidget      *widget,
13233                        GdkEventButton *event)
13234 {
13235   GtkDial *dial;
13236   gint dx, dy;
13237   double s, c;
13238   double d_parallel;
13239   double d_perpendicular;
13240
13241   g_return_val_if_fail (widget != NULL, FALSE);
13242   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13243   g_return_val_if_fail (event != NULL, FALSE);
13244
13245   dial = GTK_DIAL (widget);
13246
13247   /* Determine if button press was within pointer region - we 
13248      do this by computing the parallel and perpendicular distance of
13249      the point where the mouse was pressed from the line passing through
13250      the pointer */
13251   
13252   dx = event->x - widget->allocation.width / 2;
13253   dy = widget->allocation.height / 2 - event->y;
13254   
13255   s = sin(dial->angle);
13256   c = cos(dial->angle);
13257   
13258   d_parallel = s*dy + c*dx;
13259   d_perpendicular = fabs(s*dx - c*dy);
13260   
13261   if (!dial->button &&
13262       (d_perpendicular < dial->pointer_width/2) &&
13263       (d_parallel > - dial->pointer_width))
13264     {
13265       gtk_grab_add (widget);
13266
13267       dial->button = event->button;
13268
13269       gtk_dial_update_mouse (dial, event->x, event->y);
13270     }
13271
13272   return FALSE;
13273 }
13274
13275 static gint
13276 gtk_dial_button_release (GtkWidget      *widget,
13277                           GdkEventButton *event)
13278 {
13279   GtkDial *dial;
13280
13281   g_return_val_if_fail (widget != NULL, FALSE);
13282   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13283   g_return_val_if_fail (event != NULL, FALSE);
13284
13285   dial = GTK_DIAL (widget);
13286
13287   if (dial->button == event->button)
13288     {
13289       gtk_grab_remove (widget);
13290
13291       dial->button = 0;
13292
13293       if (dial->policy == GTK_UPDATE_DELAYED)
13294         gtk_timeout_remove (dial->timer);
13295       
13296       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
13297           (dial->old_value != dial->adjustment->value))
13298         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13299     }
13300
13301   return FALSE;
13302 }
13303
13304 static gint
13305 gtk_dial_motion_notify (GtkWidget      *widget,
13306                          GdkEventMotion *event)
13307 {
13308   GtkDial *dial;
13309   GdkModifierType mods;
13310   gint x, y, mask;
13311
13312   g_return_val_if_fail (widget != NULL, FALSE);
13313   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13314   g_return_val_if_fail (event != NULL, FALSE);
13315
13316   dial = GTK_DIAL (widget);
13317
13318   if (dial->button != 0)
13319     {
13320       x = event->x;
13321       y = event->y;
13322
13323       if (event->is_hint || (event->window != widget->window))
13324         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
13325
13326       switch (dial->button)
13327         {
13328         case 1:
13329           mask = GDK_BUTTON1_MASK;
13330           break;
13331         case 2:
13332           mask = GDK_BUTTON2_MASK;
13333           break;
13334         case 3:
13335           mask = GDK_BUTTON3_MASK;
13336           break;
13337         default:
13338           mask = 0;
13339           break;
13340         }
13341
13342       if (mods & mask)
13343         gtk_dial_update_mouse (dial, x,y);
13344     }
13345
13346   return FALSE;
13347 }
13348
13349 static gint
13350 gtk_dial_timer (GtkDial *dial)
13351 {
13352   g_return_val_if_fail (dial != NULL, FALSE);
13353   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
13354
13355   if (dial->policy == GTK_UPDATE_DELAYED)
13356     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13357
13358   return FALSE;
13359 }
13360
13361 static void
13362 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
13363 {
13364   gint xc, yc;
13365   gfloat old_value;
13366
13367   g_return_if_fail (dial != NULL);
13368   g_return_if_fail (GTK_IS_DIAL (dial));
13369
13370   xc = GTK_WIDGET(dial)->allocation.width / 2;
13371   yc = GTK_WIDGET(dial)->allocation.height / 2;
13372
13373   old_value = dial->adjustment->value;
13374   dial->angle = atan2(yc-y, x-xc);
13375
13376   if (dial->angle < -M_PI/2.)
13377     dial->angle += 2*M_PI;
13378
13379   if (dial->angle < -M_PI/6)
13380     dial->angle = -M_PI/6;
13381
13382   if (dial->angle > 7.*M_PI/6.)
13383     dial->angle = 7.*M_PI/6.;
13384
13385   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
13386     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
13387
13388   if (dial->adjustment->value != old_value)
13389     {
13390       if (dial->policy == GTK_UPDATE_CONTINUOUS)
13391         {
13392           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13393         }
13394       else
13395         {
13396           gtk_widget_draw (GTK_WIDGET(dial), NULL);
13397
13398           if (dial->policy == GTK_UPDATE_DELAYED)
13399             {
13400               if (dial->timer)
13401                 gtk_timeout_remove (dial->timer);
13402
13403               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
13404                                              (GtkFunction) gtk_dial_timer,
13405                                              (gpointer) dial);
13406             }
13407         }
13408     }
13409 }
13410 </verb></tscreen>
13411
13412 Changes to the Adjustment by external means are communicated to our
13413 widget by the "changed" and "value_changed" signals. The handlers
13414 for these functions call <tt/gtk_dial_update()/ to validate the
13415 arguments, compute the new pointer angle, and redraw the widget (by
13416 calling <tt/gtk_widget_draw()/).
13417
13418 <tscreen><verb>
13419 static void
13420 gtk_dial_update (GtkDial *dial)
13421 {
13422   gfloat new_value;
13423   
13424   g_return_if_fail (dial != NULL);
13425   g_return_if_fail (GTK_IS_DIAL (dial));
13426
13427   new_value = dial->adjustment->value;
13428   
13429   if (new_value < dial->adjustment->lower)
13430     new_value = dial->adjustment->lower;
13431
13432   if (new_value > dial->adjustment->upper)
13433     new_value = dial->adjustment->upper;
13434
13435   if (new_value != dial->adjustment->value)
13436     {
13437       dial->adjustment->value = new_value;
13438       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13439     }
13440
13441   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
13442     (dial->adjustment->upper - dial->adjustment->lower);
13443
13444   gtk_widget_draw (GTK_WIDGET(dial), NULL);
13445 }
13446
13447 static void
13448 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
13449                               gpointer       data)
13450 {
13451   GtkDial *dial;
13452
13453   g_return_if_fail (adjustment != NULL);
13454   g_return_if_fail (data != NULL);
13455
13456   dial = GTK_DIAL (data);
13457
13458   if ((dial->old_value != adjustment->value) ||
13459       (dial->old_lower != adjustment->lower) ||
13460       (dial->old_upper != adjustment->upper))
13461     {
13462       gtk_dial_update (dial);
13463
13464       dial->old_value = adjustment->value;
13465       dial->old_lower = adjustment->lower;
13466       dial->old_upper = adjustment->upper;
13467     }
13468 }
13469
13470 static void
13471 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
13472                                     gpointer       data)
13473 {
13474   GtkDial *dial;
13475
13476   g_return_if_fail (adjustment != NULL);
13477   g_return_if_fail (data != NULL);
13478
13479   dial = GTK_DIAL (data);
13480
13481   if (dial->old_value != adjustment->value)
13482     {
13483       gtk_dial_update (dial);
13484
13485       dial->old_value = adjustment->value;
13486     }
13487 }
13488 </verb></tscreen>
13489
13490 <!-- ----------------------------------------------------------------- -->
13491 <sect2> Possible Enhancements
13492 <p>
13493 The Dial widget as we've described it so far runs about 670 lines of
13494 code. Although that might sound like a fair bit, we've really
13495 accomplished quite a bit with that much code, especially since much of
13496 that length is headers and boilerplate. However, there are quite a few
13497 more enhancements that could be made to this widget:
13498
13499 <itemize>
13500 <item> If you try this widget out, you'll find that there is some
13501 flashing as the pointer is dragged around. This is because the entire
13502 widget is erased every time the pointer is moved before being
13503 redrawn. Often, the best way to handle this problem is to draw to an
13504 offscreen pixmap, then copy the final results onto the screen in one
13505 step. (The ProgressBar widget draws itself in this fashion.)
13506
13507 <item> The user should be able to use the up and down arrow keys to
13508 increase and decrease the value.
13509
13510 <item> It would be nice if the widget had buttons to increase and
13511 decrease the value in small or large steps. Although it would be
13512 possible to use embedded Button widgets for this, we would also like
13513 the buttons to auto-repeat when held down, as the arrows on a
13514 scrollbar do. Most of the code to implement this type of behavior can
13515 be found in the Range widget.
13516
13517 <item> The Dial widget could be made into a container widget with a
13518 single child widget positioned at the bottom between the buttons
13519 mentioned above. The user could then add their choice of a label or
13520 entry widget to display the current value of the dial.
13521
13522 </itemize>
13523
13524 <!-- ----------------------------------------------------------------- -->
13525 <sect1> Learning More
13526
13527 <p>
13528 Only a small part of the many details involved in creating widgets
13529 could be described above. If you want to write your own widgets, the
13530 best source of examples is the GTK source itself. Ask yourself some
13531 questions about the widget you want to write: IS it a Container
13532 widget? Does it have its own window? Is it a modification of an
13533 existing widget? Then find a similar widget, and start making changes.
13534 Good luck!
13535
13536 <!-- ***************************************************************** -->
13537 <sect>Scribble, A Simple Example Drawing Program
13538 <!-- ***************************************************************** -->
13539
13540 <!-- ----------------------------------------------------------------- -->
13541 <sect1> Overview
13542 <p>
13543 In this section, we will build a simple drawing program. In the
13544 process, we will examine how to handle mouse events, how to draw in a
13545 window, and how to do drawing better by using a backing pixmap. After
13546 creating the simple drawing program, we will extend it by adding
13547 support for XInput devices, such as drawing tablets. GTK provides
13548 support routines which makes getting extended information, such as
13549 pressure and tilt, from such devices quite easy.
13550
13551 <!-- ----------------------------------------------------------------- -->
13552 <sect1> Event Handling
13553 <p>
13554 The GTK signals we have already discussed are for high-level actions,
13555 such as a menu item being selected. However, sometimes it is useful to
13556 learn about lower-level occurrences, such as the mouse being moved, or
13557 a key being pressed. There are also GTK signals corresponding to these
13558 low-level <em>events</em>. The handlers for these signals have an
13559 extra parameter which is a pointer to a structure containing
13560 information about the event. For instance, motion event handlers are
13561 passed a pointer to a GdkEventMotion structure which looks (in part)
13562 like:
13563
13564 <tscreen><verb>
13565 struct _GdkEventMotion
13566 {
13567   GdkEventType type;
13568   GdkWindow *window;
13569   guint32 time;
13570   gdouble x;
13571   gdouble y;
13572   ...
13573   guint state;
13574   ...
13575 };
13576 </verb></tscreen>
13577
13578 <tt/type/ will be set to the event type, in this case
13579 <tt/GDK_MOTION_NOTIFY/, window is the window in which the event
13580 occurred. <tt/x/ and <tt/y/ give the coordinates of the event.
13581 <tt/state/ specifies the modifier state when the event
13582 occurred (that is, it specifies which modifier keys and mouse buttons
13583 were pressed). It is the bitwise OR of some of the following:
13584
13585 <tscreen><verb>
13586 GDK_SHIFT_MASK  
13587 GDK_LOCK_MASK   
13588 GDK_CONTROL_MASK
13589 GDK_MOD1_MASK   
13590 GDK_MOD2_MASK   
13591 GDK_MOD3_MASK   
13592 GDK_MOD4_MASK   
13593 GDK_MOD5_MASK   
13594 GDK_BUTTON1_MASK
13595 GDK_BUTTON2_MASK
13596 GDK_BUTTON3_MASK
13597 GDK_BUTTON4_MASK
13598 GDK_BUTTON5_MASK
13599 </verb></tscreen>
13600
13601 As for other signals, to determine what happens when an event occurs
13602 we call <tt>gtk_signal_connect()</tt>. But we also need let GTK
13603 know which events we want to be notified about. To do this, we call
13604 the function:
13605
13606 <tscreen><verb>
13607 void gtk_widget_set_events (GtkWidget *widget,
13608                             gint      events);
13609 </verb></tscreen>
13610
13611 The second field specifies the events we are interested in. It
13612 is the bitwise OR of constants that specify different types
13613 of events. For future reference the event types are:
13614
13615 <tscreen><verb>
13616 GDK_EXPOSURE_MASK
13617 GDK_POINTER_MOTION_MASK
13618 GDK_POINTER_MOTION_HINT_MASK
13619 GDK_BUTTON_MOTION_MASK     
13620 GDK_BUTTON1_MOTION_MASK    
13621 GDK_BUTTON2_MOTION_MASK    
13622 GDK_BUTTON3_MOTION_MASK    
13623 GDK_BUTTON_PRESS_MASK      
13624 GDK_BUTTON_RELEASE_MASK    
13625 GDK_KEY_PRESS_MASK         
13626 GDK_KEY_RELEASE_MASK       
13627 GDK_ENTER_NOTIFY_MASK      
13628 GDK_LEAVE_NOTIFY_MASK      
13629 GDK_FOCUS_CHANGE_MASK      
13630 GDK_STRUCTURE_MASK         
13631 GDK_PROPERTY_CHANGE_MASK   
13632 GDK_PROXIMITY_IN_MASK      
13633 GDK_PROXIMITY_OUT_MASK     
13634 </verb></tscreen>
13635
13636 There are a few subtle points that have to be observed when calling
13637 <tt/gtk_widget_set_events()/. First, it must be called before the X window
13638 for a GTK widget is created. In practical terms, this means you
13639 should call it immediately after creating the widget. Second, the
13640 widget must have an associated X window. For efficiency, many widget
13641 types do not have their own window, but draw in their parent's window.
13642 These widgets are:
13643
13644 <tscreen><verb>
13645 GtkAlignment
13646 GtkArrow
13647 GtkBin
13648 GtkBox
13649 GtkImage
13650 GtkItem
13651 GtkLabel
13652 GtkPixmap
13653 GtkScrolledWindow
13654 GtkSeparator
13655 GtkTable
13656 GtkAspectFrame
13657 GtkFrame
13658 GtkVBox
13659 GtkHBox
13660 GtkVSeparator
13661 GtkHSeparator
13662 </verb></tscreen>
13663
13664 To capture events for these widgets, you need to use an EventBox
13665 widget. See the section on the <ref id="sec_EventBox"
13666 name="EventBox"> widget for details.
13667
13668 For our drawing program, we want to know when the mouse button is
13669 pressed and when the mouse is moved, so we specify
13670 <tt/GDK_POINTER_MOTION_MASK/ and <tt/GDK_BUTTON_PRESS_MASK/. We also
13671 want to know when we need to redraw our window, so we specify
13672 <tt/GDK_EXPOSURE_MASK/. Although we want to be notified via a
13673 Configure event when our window size changes, we don't have to specify
13674 the corresponding <tt/GDK_STRUCTURE_MASK/ flag, because it is
13675 automatically specified for all windows.
13676
13677 It turns out, however, that there is a problem with just specifying
13678 <tt/GDK_POINTER_MOTION_MASK/. This will cause the server to add a new
13679 motion event to the event queue every time the user moves the mouse.
13680 Imagine that it takes us 0.1 seconds to handle a motion event, but the
13681 X server queues a new motion event every 0.05 seconds. We will soon
13682 get way behind the users drawing. If the user draws for 5 seconds,
13683 it will take us another 5 seconds to catch up after they release 
13684 the mouse button! What we would like is to only get one motion
13685 event for each event we process. The way to do this is to 
13686 specify <tt/GDK_POINTER_MOTION_HINT_MASK/. 
13687
13688 When we specify <tt/GDK_POINTER_MOTION_HINT_MASK/, the server sends
13689 us a motion event the first time the pointer moves after entering
13690 our window, or after a button press or release event. Subsequent 
13691 motion events will be suppressed until we explicitly ask for
13692 the position of the pointer using the function:
13693
13694 <tscreen><verb>
13695 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
13696                                           gint            *x,
13697                                           gint            *y,
13698                                           GdkModifierType *mask);
13699 </verb></tscreen>
13700
13701 (There is another function, <tt>gtk_widget_get_pointer()</tt> which
13702 has a simpler interface, but turns out not to be very useful, since
13703 it only retrieves the position of the mouse, not whether the buttons
13704 are pressed.)
13705
13706 The code to set the events for our window then looks like:
13707
13708 <tscreen><verb>
13709   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
13710                       (GtkSignalFunc) expose_event, NULL);
13711   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
13712                       (GtkSignalFunc) configure_event, NULL);
13713   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
13714                       (GtkSignalFunc) motion_notify_event, NULL);
13715   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
13716                       (GtkSignalFunc) button_press_event, NULL);
13717
13718   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
13719                          | GDK_LEAVE_NOTIFY_MASK
13720                          | GDK_BUTTON_PRESS_MASK
13721                          | GDK_POINTER_MOTION_MASK
13722                          | GDK_POINTER_MOTION_HINT_MASK);
13723 </verb></tscreen>
13724
13725 We'll save the "expose_event" and "configure_event" handlers for
13726 later. The "motion_notify_event" and "button_press_event" handlers
13727 are pretty simple:
13728
13729 <tscreen><verb>
13730 static gint
13731 button_press_event (GtkWidget *widget, GdkEventButton *event)
13732 {
13733   if (event->button == 1 &amp;&amp; pixmap != NULL)
13734       draw_brush (widget, event->x, event->y);
13735
13736   return TRUE;
13737 }
13738
13739 static gint
13740 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
13741 {
13742   int x, y;
13743   GdkModifierType state;
13744
13745   if (event->is_hint)
13746     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
13747   else
13748     {
13749       x = event->x;
13750       y = event->y;
13751       state = event->state;
13752     }
13753     
13754   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
13755     draw_brush (widget, x, y);
13756   
13757   return TRUE;
13758 }
13759 </verb></tscreen>
13760
13761 <!-- ----------------------------------------------------------------- -->
13762 <sect1> The DrawingArea Widget, And Drawing
13763 <p>
13764 We now turn to the process of drawing on the screen. The 
13765 widget we use for this is the DrawingArea widget. A drawing area
13766 widget is essentially an X window and nothing more. It is a blank
13767 canvas in which we can draw whatever we like. A drawing area
13768 is created using the call:
13769
13770 <tscreen><verb>
13771 GtkWidget* gtk_drawing_area_new        (void);
13772 </verb></tscreen>
13773
13774 A default size for the widget can be specified by calling:
13775
13776 <tscreen><verb>
13777 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
13778                                         gint                 width,
13779                                         gint                 height);
13780 </verb></tscreen>
13781
13782 This default size can be overridden, as is true for all widgets,
13783 by calling <tt>gtk_widget_set_usize()</tt>, and that, in turn, can
13784 be overridden if the user manually resizes the the window containing
13785 the drawing area.
13786
13787 It should be noted that when we create a DrawingArea widget, we are
13788 <em>completely</em> responsible for drawing the contents. If our
13789 window is obscured then uncovered, we get an exposure event and must
13790 redraw what was previously hidden.
13791
13792 Having to remember everything that was drawn on the screen so we
13793 can properly redraw it can, to say the least, be a nuisance. In
13794 addition, it can be visually distracting if portions of the
13795 window are cleared, then redrawn step by step. The solution to
13796 this problem is to use an offscreen <em>backing pixmap</em>.
13797 Instead of drawing directly to the screen, we draw to an image
13798 stored in server memory but not displayed, then when the image
13799 changes or new portions of the image are displayed, we copy the
13800 relevant portions onto the screen.
13801
13802 To create an offscreen pixmap, we call the function:
13803
13804 <tscreen><verb>
13805 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
13806                                          gint        width,
13807                                          gint        height,
13808                                          gint        depth);
13809 </verb></tscreen>
13810
13811 The <tt>window</tt> parameter specifies a GDK window that this pixmap
13812 takes some of its properties from. <tt>width</tt> and <tt>height</tt>
13813 specify the size of the pixmap. <tt>depth</tt> specifies the <em>color
13814 depth</em>, that is the number of bits per pixel, for the new window.
13815 If the depth is specified as <tt>-1</tt>, it will match the depth
13816 of <tt>window</tt>.
13817
13818 We create the pixmap in our "configure_event" handler. This event
13819 is generated whenever the window changes size, including when it
13820 is originally created.
13821
13822 <tscreen><verb>
13823 /* Backing pixmap for drawing area */
13824 static GdkPixmap *pixmap = NULL;
13825
13826 /* Create a new backing pixmap of the appropriate size */
13827 static gint
13828 configure_event (GtkWidget *widget, GdkEventConfigure *event)
13829 {
13830   if (pixmap)
13831     gdk_pixmap_unref(pixmap);
13832
13833   pixmap = gdk_pixmap_new(widget->window,
13834                           widget->allocation.width,
13835                           widget->allocation.height,
13836                           -1);
13837   gdk_draw_rectangle (pixmap,
13838                       widget->style->white_gc,
13839                       TRUE,
13840                       0, 0,
13841                       widget->allocation.width,
13842                       widget->allocation.height);
13843
13844   return TRUE;
13845 }
13846 </verb></tscreen>
13847
13848 The call to <tt>gdk_draw_rectangle()</tt> clears the pixmap
13849 initially to white. We'll say more about that in a moment.
13850
13851 Our exposure event handler then simply copies the relevant portion
13852 of the pixmap onto the screen (we determine the area we need
13853 to redraw by using the event->area field of the exposure event):
13854
13855 <tscreen><verb>
13856 /* Redraw the screen from the backing pixmap */
13857 static gint
13858 expose_event (GtkWidget *widget, GdkEventExpose *event)
13859 {
13860   gdk_draw_pixmap(widget->window,
13861                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
13862                   pixmap,
13863                   event->area.x, event->area.y,
13864                   event->area.x, event->area.y,
13865                   event->area.width, event->area.height);
13866
13867   return FALSE;
13868 }
13869 </verb></tscreen>
13870
13871 We've now seen how to keep the screen up to date with our pixmap, but
13872 how do we actually draw interesting stuff on our pixmap?  There are a
13873 large number of calls in GTK's GDK library for drawing on
13874 <em>drawables</em>. A drawable is simply something that can be drawn
13875 upon. It can be a window, a pixmap, or a bitmap (a black and white
13876 image).  We've already seen two such calls above,
13877 <tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. The
13878 complete list is:
13879
13880 <tscreen><verb>
13881 gdk_draw_line ()
13882 gdk_draw_rectangle ()
13883 gdk_draw_arc ()
13884 gdk_draw_polygon ()
13885 gdk_draw_string ()
13886 gdk_draw_text ()
13887 gdk_draw_pixmap ()
13888 gdk_draw_bitmap ()
13889 gdk_draw_image ()
13890 gdk_draw_points ()
13891 gdk_draw_segments ()
13892 </verb></tscreen>
13893
13894 See the reference documentation or the header file
13895 <tt>&lt;gdk/gdk.h&gt;</tt> for further details on these functions.
13896 These functions all share the same first two arguments. The first
13897 argument is the drawable to draw upon, the second argument is a
13898 <em>graphics context</em> (GC). 
13899
13900 A graphics context encapsulates information about things such as
13901 foreground and background color and line width. GDK has a full set of
13902 functions for creating and modifying graphics contexts, but to keep
13903 things simple we'll just use predefined graphics contexts. Each widget
13904 has an associated style. (Which can be modified in a gtkrc file, see
13905 the section GTK's rc file.) This, among other things, stores a number
13906 of graphics contexts. Some examples of accessing these graphics
13907 contexts are:
13908
13909 <tscreen><verb>
13910 widget->style->white_gc
13911 widget->style->black_gc
13912 widget->style->fg_gc[GTK_STATE_NORMAL]
13913 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
13914 </verb></tscreen>
13915
13916 The fields <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, and
13917 <tt>light_gc</tt> are indexed by a parameter of type
13918 <tt>GtkStateType</tt> which can take on the values:
13919
13920 <tscreen><verb>
13921 GTK_STATE_NORMAL,
13922 GTK_STATE_ACTIVE,
13923 GTK_STATE_PRELIGHT,
13924 GTK_STATE_SELECTED,
13925 GTK_STATE_INSENSITIVE
13926 </verb></tscreen>
13927
13928 For instance, for <tt/GTK_STATE_SELECTED/ the default foreground
13929 color is white and the default background color, dark blue.
13930
13931 Our function <tt>draw_brush()</tt>, which does the actual drawing
13932 on the screen, is then:
13933
13934 <tscreen><verb>
13935 /* Draw a rectangle on the screen */
13936 static void
13937 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
13938 {
13939   GdkRectangle update_rect;
13940
13941   update_rect.x = x - 5;
13942   update_rect.y = y - 5;
13943   update_rect.width = 10;
13944   update_rect.height = 10;
13945   gdk_draw_rectangle (pixmap,
13946                       widget->style->black_gc,
13947                       TRUE,
13948                       update_rect.x, update_rect.y,
13949                       update_rect.width, update_rect.height);
13950   gtk_widget_draw (widget, &amp;update_rect);
13951 }
13952 </verb></tscreen>
13953
13954 After we draw the rectangle representing the brush onto the pixmap,
13955 we call the function:
13956
13957 <tscreen><verb>
13958 void       gtk_widget_draw                (GtkWidget           *widget,
13959                                            GdkRectangle        *area);
13960 </verb></tscreen>
13961
13962 which notifies X that the area given by the <tt>area</tt> parameter
13963 needs to be updated. X will eventually generate an expose event
13964 (possibly combining the areas passed in several calls to
13965 <tt>gtk_widget_draw()</tt>) which will cause our expose event handler
13966 to copy the relevant portions to the screen.
13967
13968 We have now covered the entire drawing program except for a few
13969 mundane details like creating the main window. The complete
13970 source code is available from the location from which you got
13971 this tutorial, or from:
13972
13973 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
13974 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
13975
13976
13977 <!-- ----------------------------------------------------------------- -->
13978 <sect1> Adding XInput support
13979 <p>
13980 It is now possible to buy quite inexpensive input devices such 
13981 as drawing tablets, which allow drawing with a much greater
13982 ease of artistic expression than does a mouse. The simplest way
13983 to use such devices is simply as a replacement for the mouse,
13984 but that misses out many of the advantages of these devices,
13985 such as:
13986
13987 <itemize>
13988 <item> Pressure sensitivity
13989 <item> Tilt reporting
13990 <item> Sub-pixel positioning
13991 <item> Multiple inputs (for example, a stylus with a point and eraser)
13992 </itemize>
13993
13994 For information about the XInput extension, see the <htmlurl
13995 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
13996 name="XInput-HOWTO">.
13997
13998 If we examine the full definition of, for example, the GdkEventMotion
13999 structure, we see that it has fields to support extended device
14000 information.
14001
14002 <tscreen><verb>
14003 struct _GdkEventMotion
14004 {
14005   GdkEventType type;
14006   GdkWindow *window;
14007   guint32 time;
14008   gdouble x;
14009   gdouble y;
14010   gdouble pressure;
14011   gdouble xtilt;
14012   gdouble ytilt;
14013   guint state;
14014   gint16 is_hint;
14015   GdkInputSource source;
14016   guint32 deviceid;
14017 };
14018 </verb></tscreen>
14019
14020 <tt/pressure/ gives the pressure as a floating point number between
14021 0 and 1. <tt/xtilt/ and <tt/ytilt/ can take on values between 
14022 -1 and 1, corresponding to the degree of tilt in each direction.
14023 <tt/source/ and <tt/deviceid/ specify the device for which the
14024 event occurred in two different ways. <tt/source/ gives some simple
14025 information about the type of device. It can take the enumeration
14026 values:
14027
14028 <tscreen><verb>
14029 GDK_SOURCE_MOUSE
14030 GDK_SOURCE_PEN
14031 GDK_SOURCE_ERASER
14032 GDK_SOURCE_CURSOR
14033 </verb></tscreen>
14034
14035 <tt/deviceid/ specifies a unique numeric ID for the device. This can
14036 be used to find out further information about the device using the
14037 <tt/gdk_input_list_devices()/ call (see below). The special value
14038 <tt/GDK_CORE_POINTER/ is used for the core pointer device. (Usually
14039 the mouse.)
14040
14041 <sect2> Enabling extended device information
14042 <p>
14043 To let GTK know about our interest in the extended device information,
14044 we merely have to add a single line to our program:
14045
14046 <tscreen><verb>
14047 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
14048 </verb></tscreen>
14049
14050 By giving the value <tt/GDK_EXTENSION_EVENTS_CURSOR/ we say that
14051 we are interested in extension events, but only if we don't have
14052 to draw our own cursor. See the section <ref
14053 id="sec_Further_Sophistications" name="Further Sophistications"> below
14054 for more information about drawing the cursor. We could also 
14055 give the values <tt/GDK_EXTENSION_EVENTS_ALL/ if we were willing 
14056 to draw our own cursor, or <tt/GDK_EXTENSION_EVENTS_NONE/ to revert
14057 back to the default condition.
14058
14059 This is not completely the end of the story however. By default,
14060 no extension devices are enabled. We need a mechanism to allow
14061 users to enable and configure their extension devices. GTK provides
14062 the InputDialog widget to automate this process. The following
14063 procedure manages an InputDialog widget. It creates the dialog if
14064 it isn't present, and raises it to the top otherwise.
14065
14066 <tscreen><verb>
14067 void
14068 input_dialog_destroy (GtkWidget *w, gpointer data)
14069 {
14070   *((GtkWidget **)data) = NULL;
14071 }
14072
14073 void
14074 create_input_dialog ()
14075 {
14076   static GtkWidget *inputd = NULL;
14077
14078   if (!inputd)
14079     {
14080       inputd = gtk_input_dialog_new();
14081
14082       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
14083                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
14084       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
14085                                  "clicked",
14086                                  (GtkSignalFunc)gtk_widget_hide,
14087                                  GTK_OBJECT(inputd));
14088       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
14089
14090       gtk_widget_show (inputd);
14091     }
14092   else
14093     {
14094       if (!GTK_WIDGET_MAPPED(inputd))
14095         gtk_widget_show(inputd);
14096       else
14097         gdk_window_raise(inputd->window);
14098     }
14099 }
14100 </verb></tscreen>
14101
14102 (You might want to take note of the way we handle this dialog.  By
14103 connecting to the "destroy" signal, we make sure that we don't keep a
14104 pointer to dialog around after it is destroyed - that could lead to a
14105 segfault.)
14106
14107 The InputDialog has two buttons "Close" and "Save", which by default
14108 have no actions assigned to them. In the above function we make
14109 "Close" hide the dialog, hide the "Save" button, since we don't
14110 implement saving of XInput options in this program.
14111
14112 <sect2> Using extended device information
14113 <p>
14114 Once we've enabled the device, we can just use the extended 
14115 device information in the extra fields of the event structures.
14116 In fact, it is always safe to use this information since these
14117 fields will have reasonable default values even when extended
14118 events are not enabled.
14119
14120 Once change we do have to make is to call
14121 <tt/gdk_input_window_get_pointer()/ instead of
14122 <tt/gdk_window_get_pointer/. This is necessary because
14123 <tt/gdk_window_get_pointer/ doesn't return the extended device
14124 information.
14125
14126 <tscreen><verb>
14127 void gdk_input_window_get_pointer( GdkWindow       *window,
14128                                    guint32         deviceid,
14129                                    gdouble         *x,
14130                                    gdouble         *y,
14131                                    gdouble         *pressure,
14132                                    gdouble         *xtilt,
14133                                    gdouble         *ytilt,
14134                                    GdkModifierType *mask);
14135 </verb></tscreen>
14136
14137 When calling this function, we need to specify the device ID as
14138 well as the window. Usually, we'll get the device ID from the
14139 <tt/deviceid/ field of an event structure. Again, this function
14140 will return reasonable values when extension events are not
14141 enabled. (In this case, <tt/event->deviceid/ will have the value
14142 <tt/GDK_CORE_POINTER/).
14143
14144 So the basic structure of our button-press and motion event handlers
14145 doesn't change much - we just need to add code to deal with the
14146 extended information.
14147
14148 <tscreen><verb>
14149 static gint
14150 button_press_event (GtkWidget *widget, GdkEventButton *event)
14151 {
14152   print_button_press (event->deviceid);
14153   
14154   if (event->button == 1 &amp;&amp; pixmap != NULL)
14155     draw_brush (widget, event->source, event->x, event->y, event->pressure);
14156
14157   return TRUE;
14158 }
14159
14160 static gint
14161 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
14162 {
14163   gdouble x, y;
14164   gdouble pressure;
14165   GdkModifierType state;
14166
14167   if (event->is_hint)
14168     gdk_input_window_get_pointer (event->window, event->deviceid,
14169                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
14170   else
14171     {
14172       x = event->x;
14173       y = event->y;
14174       pressure = event->pressure;
14175       state = event->state;
14176     }
14177     
14178   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
14179     draw_brush (widget, event->source, x, y, pressure);
14180   
14181   return TRUE;
14182 }
14183 </verb></tscreen>
14184
14185 We also need to do something with the new information. Our new
14186 <tt/draw_brush()/ function draws with a different color for
14187 each <tt/event->source/ and changes the brush size depending
14188 on the pressure.
14189
14190 <tscreen><verb>
14191 /* Draw a rectangle on the screen, size depending on pressure,
14192    and color on the type of device */
14193 static void
14194 draw_brush (GtkWidget *widget, GdkInputSource source,
14195             gdouble x, gdouble y, gdouble pressure)
14196 {
14197   GdkGC *gc;
14198   GdkRectangle update_rect;
14199
14200   switch (source)
14201     {
14202     case GDK_SOURCE_MOUSE:
14203       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
14204       break;
14205     case GDK_SOURCE_PEN:
14206       gc = widget->style->black_gc;
14207       break;
14208     case GDK_SOURCE_ERASER:
14209       gc = widget->style->white_gc;
14210       break;
14211     default:
14212       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
14213     }
14214
14215   update_rect.x = x - 10 * pressure;
14216   update_rect.y = y - 10 * pressure;
14217   update_rect.width = 20 * pressure;
14218   update_rect.height = 20 * pressure;
14219   gdk_draw_rectangle (pixmap, gc, TRUE,
14220                       update_rect.x, update_rect.y,
14221                       update_rect.width, update_rect.height);
14222   gtk_widget_draw (widget, &amp;update_rect);
14223 }
14224 </verb></tscreen>
14225
14226 <sect2> Finding out more about a device
14227 <p>
14228 As an example of how to find out more about a device, our program
14229 will print the name of the device that generates each button
14230 press. To find out the name of a device, we call the function:
14231
14232 <tscreen><verb>
14233 GList *gdk_input_list_devices               (void);
14234 </verb></tscreen>
14235
14236 which returns a GList (a linked list type from the GLib library)
14237 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
14238 as:
14239
14240 <tscreen><verb>
14241 struct _GdkDeviceInfo
14242 {
14243   guint32 deviceid;
14244   gchar *name;
14245   GdkInputSource source;
14246   GdkInputMode mode;
14247   gint has_cursor;
14248   gint num_axes;
14249   GdkAxisUse *axes;
14250   gint num_keys;
14251   GdkDeviceKey *keys;
14252 };
14253 </verb></tscreen>
14254
14255 Most of these fields are configuration information that you can ignore
14256 unless you are implementing XInput configuration saving. The fieldwe
14257 are interested in here is <tt/name/ which is simply the name that X
14258 assigns to the device. The other field that isn't configuration
14259 information is <tt/has_cursor/. If <tt/has_cursor/ is false, then we
14260 we need to draw our own cursor. But since we've specified
14261 <tt/GDK_EXTENSION_EVENTS_CURSOR/, we don't have to worry about this.
14262
14263 Our <tt/print_button_press()/ function simply iterates through
14264 the returned list until it finds a match, then prints out
14265 the name of the device.
14266
14267 <tscreen><verb>
14268 static void
14269 print_button_press (guint32 deviceid)
14270 {
14271   GList *tmp_list;
14272
14273   /* gdk_input_list_devices returns an internal list, so we shouldn't
14274      free it afterwards */
14275   tmp_list = gdk_input_list_devices();
14276
14277   while (tmp_list)
14278     {
14279       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
14280
14281       if (info->deviceid == deviceid)
14282         {
14283           printf("Button press on device '%s'\n", info->name);
14284           return;
14285         }
14286
14287       tmp_list = tmp_list->next;
14288     }
14289 }
14290 </verb></tscreen>
14291
14292 That completes the changes to "XInputize" our program. As with
14293 the first version, the complete source is available at the location
14294 from which you got this tutorial, or from:
14295
14296 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
14297 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
14298
14299
14300 <sect2> Further sophistications <label id="sec_Further_Sophistications">
14301 <p>
14302 Although our program now supports XInput quite well, it lacks some
14303 features we would want in a full-featured application. First, the user
14304 probably doesn't want to have to configure their device each time they
14305 run the program, so we should allow them to save the device
14306 configuration. This is done by iterating through the return of
14307 <tt/gdk_input_list_devices()/ and writing out the configuration to a
14308 file.
14309
14310 To restore the state next time the program is run, GDK provides
14311 functions to change device configuration:
14312
14313 <tscreen><verb>
14314 gdk_input_set_extension_events()
14315 gdk_input_set_source()
14316 gdk_input_set_mode()
14317 gdk_input_set_axes()
14318 gdk_input_set_key()
14319 </verb></tscreen>
14320
14321 (The list returned from <tt/gdk_input_list_devices()/ should not be
14322 modified directly.) An example of doing this can be found in the
14323 drawing program gsumi. (Available from <htmlurl
14324 url="http://www.msc.cornell.edu/~otaylor/gsumi/"
14325 name="http://www.msc.cornell.edu/~otaylor/gsumi/">) Eventually, it
14326 would be nice to have a standard way of doing this for all
14327 applications. This probably belongs at a slightly higher level than
14328 GTK, perhaps in the GNOME library.
14329
14330 Another major omission that we have mentioned above is the lack of
14331 cursor drawing. Platforms other than XFree86 currently do not allow
14332 simultaneously using a device as both the core pointer and directly by
14333 an application. See the <url
14334 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
14335 name="XInput-HOWTO"> for more information about this. This means that
14336 applications that want to support the widest audience need to draw
14337 their own cursor.
14338
14339 An application that draws its own cursor needs to do two things:
14340 determine if the current device needs a cursor drawn or not, and
14341 determine if the current device is in proximity. (If the current
14342 device is a drawing tablet, it's a nice touch to make the cursor 
14343 disappear when the stylus is lifted from the tablet. When the
14344 device is touching the stylus, that is called "in proximity.")
14345 The first is done by searching the device list, as we did
14346 to find out the device name. The second is achieved by selecting
14347 "proximity_out" events. An example of drawing one's own cursor is
14348 found in the "testinput" program found in the GTK distribution.
14349
14350 <!-- ***************************************************************** -->
14351 <sect>Tips For Writing GTK Applications
14352 <!-- ***************************************************************** -->
14353 <p>
14354 This section is simply a gathering of wisdom, general style guidelines
14355 and hints to creating good GTK applications. Currently this section
14356 is very short, but I hope it will get longer in future editions of
14357 this tutorial.
14358
14359 Use GNU autoconf and automake! They are your friends :) Automake
14360 examines C files, determines how they depend on each other, and
14361 generates a Makefile so the files can be compiled in the correct
14362 order. Autoconf permits automatic configuration of software
14363 installation, handling a large number of system quirks to increase
14364 portability. I am planning to make a quick intro on them here.
14365
14366 When writing C code, use only C comments (beginning with "/*" and
14367 ending with "*/"), and don't use C++-style comments ("//").  Although
14368 many C compilers understand C++ comments, others don't, and the ANSI C
14369 standard does not require that C++-style comments be processed as
14370 comments.
14371
14372 <!-- ***************************************************************** -->
14373 <sect>Contributing <label id="sec_Contributing">
14374 <!-- ***************************************************************** -->
14375 <p>
14376 This document, like so much other great software out there, was
14377 created for free by volunteers.  If you are at all knowledgeable about
14378 any aspect of GTK that does not already have documentation, please
14379 consider contributing to this document.
14380
14381 If you do decide to contribute, please mail your text to Tony Gale,
14382 <tt><htmlurl url="mailto:gale@gtk.org"
14383 name="gale@gtk.org"></tt>. Also, be aware that the entirety of this
14384 document is free, and any addition by you provide must also be
14385 free. That is, people may use any portion of your examples in their
14386 programs, and copies of this document may be distributed at will, etc.
14387
14388 Thank you.
14389
14390 <!-- ***************************************************************** -->
14391 <sect>Credits
14392 <!-- ***************************************************************** -->
14393 <p>
14394 We would like to thank the following for their contributions to this text.
14395
14396 <itemize>
14397 <item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com"
14398 name="chamele0n@geocities.com"></tt> for the menus tutorial.                          
14399
14400 <item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org"
14401 name="raph@acm.org"></tt>
14402 for hello world ala GTK, widget packing, and general all around wisdom.
14403 He's also generously donated a home for this tutorial.
14404
14405 <item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
14406 name="petm@xcf.berkeley.edu"></tt> for the simplest GTK program.. 
14407 and the ability to make it :)
14408
14409 <item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de"
14410 name="werner.koch@guug.de"></tt> for converting the original plain text to
14411 SGML, and the widget class hierarchy.
14412
14413 <item>Mark Crichton <tt><htmlurl
14414 url="mailto:crichton@expert.cc.purdue.edu"
14415 name="crichton@expert.cc.purdue.edu"></tt> for the menu factory code,
14416 and the table packing tutorial.
14417
14418 <item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu"
14419 name="owt1@cornell.edu"></tt> for the EventBox widget section (and the
14420 patch to the distro).  He's also responsible for the selections code
14421 and tutorial, as well as the sections on writing your own GTK widgets,
14422 and the example application. Thanks a lot Owen for all you help!
14423
14424 <item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu"
14425 name="mvboom42@calvin.edu"></tt> for his wonderful work on the
14426 Notebook, Progress Bar, Dialogs, and File selection widgets.  Thanks a
14427 lot Mark!  You've been a great help.
14428
14429 <item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org"
14430 name="timj@psynet.net"></tt> for his great job on the Lists
14431 Widget. His excellent work on automatically extracting the widget tree
14432 and signal information from GTK. Thanks Tim :)
14433
14434 <item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com"
14435 name="rajat@ix.netcom.com"</tt> for the excellent job on the Pixmap
14436 tutorial.
14437
14438 <item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com"
14439 name="johnsonm@redhat.com"></tt> for info and code for popup menus.
14440
14441 <item>David Huggins-Daines <tt><htmlurl
14442 url="mailto:bn711@freenet.carleton.ca"
14443 name="bn711@freenet.carleton.ca"></tt> for the Range Widgets and Tree
14444 Widget sections.
14445
14446 <item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se"
14447 name="mars@lysator.liu.se"></tt> for the CList section.
14448
14449 <item>David A. Wheeler <tt><htmlurl url="mailto:dwheeler@ida.org"
14450 name="dwheeler@ida.org"></tt> for portions of the text on GLib
14451 and various tutorial fixups and improvements.
14452 The GLib text was in turn based on material developed by Damon Chaplin
14453 <tt><htmlurl url="mailto:DAChaplin@msn.com" name="DAChaplin@msn.com"></tt>
14454
14455 <item>David King for style checking this entire document.
14456 </itemize>
14457
14458 And to all of you who commented on and helped refine this document.
14459
14460 Thanks.
14461
14462 <!-- ***************************************************************** -->
14463 <sect> Tutorial Copyright and Permissions Notice
14464 <!-- ***************************************************************** -->
14465
14466 <p>
14467 The GTK Tutorial is Copyright (C) 1997 Ian Main. 
14468
14469 Copyright (C) 1998-1999 Tony Gale.
14470
14471 Permission is granted to make and distribute verbatim copies of this 
14472 manual provided the copyright notice and this permission notice are 
14473 preserved on all copies.
14474
14475 Permission is granted to copy and distribute modified versions of 
14476 this document under the conditions for verbatim copying, provided that 
14477 this copyright notice is included exactly as in the original,
14478 and that the entire resulting derived work is distributed under 
14479 the terms of a permission notice identical to this one.
14480 <P>Permission is granted to copy and distribute translations of this 
14481 document into another language, under the above conditions for modified 
14482 versions.
14483
14484 If you are intending to incorporate this document into a published 
14485 work, please contact the maintainer, and we will make an effort 
14486 to ensure that you have the most up to date information available.
14487
14488 There is no guarantee that this document lives up to its intended
14489 purpose.  This is simply provided as a free resource.  As such,
14490 the authors and maintainers of the information provided within can
14491 not make any guarantee that the information is even accurate.
14492
14493 <!-- ***************************************************************** -->
14494 <appendix>
14495 <!-- ***************************************************************** -->
14496
14497 <!-- ***************************************************************** -->
14498 <sect> GTK Signals <label id="sec_GTK_Signals">
14499 <!-- ***************************************************************** -->
14500 <p>
14501 As GTK is an object oriented widget set, it has a hierarchy of
14502 inheritance. This inheritance mechanism applies for
14503 signals. Therefore, you should refer to the widget hierarchy tree when
14504 using the signals listed in this section.
14505
14506 <!-- ----------------------------------------------------------------- -->
14507 <sect1>GtkObject
14508 <!-- ----------------------------------------------------------------- -->
14509 <p>
14510 <tscreen><verb>
14511 void GtkObject::destroy (GtkObject *,
14512                          gpointer);
14513 </verb></tscreen>
14514
14515 <!-- ----------------------------------------------------------------- -->
14516 <sect1>GtkWidget
14517 <!-- ----------------------------------------------------------------- -->
14518 <p>
14519 <tscreen><verb>
14520
14521 void GtkWidget::show    (GtkWidget *,
14522                          gpointer);
14523 void GtkWidget::hide    (GtkWidget *,
14524                          gpointer);
14525 void GtkWidget::map     (GtkWidget *,
14526                          gpointer);
14527 void GtkWidget::unmap   (GtkWidget *,
14528                          gpointer);
14529 void GtkWidget::realize (GtkWidget *,
14530                          gpointer);
14531 void GtkWidget::unrealize       (GtkWidget *,
14532                                  gpointer);
14533 void GtkWidget::draw    (GtkWidget *,
14534                          ggpointer,
14535                          gpointer);
14536 void GtkWidget::draw-focus      (GtkWidget *,
14537                                  gpointer);
14538 void GtkWidget::draw-default    (GtkWidget *,
14539                                  gpointer);
14540 void GtkWidget::size-request    (GtkWidget *,
14541                                  ggpointer,
14542                                  gpointer);
14543 void GtkWidget::size-allocate   (GtkWidget *,
14544                                  ggpointer,
14545                                  gpointer);
14546 void GtkWidget::state-changed   (GtkWidget *,
14547                                  GtkStateType,
14548                                  gpointer);
14549 void GtkWidget::parent-set      (GtkWidget *,
14550                                  GtkObject *,
14551                                  gpointer);
14552 void GtkWidget::style-set       (GtkWidget *,
14553                                  GtkStyle *,
14554                                  gpointer);
14555 void GtkWidget::add-accelerator (GtkWidget *,
14556                                  gguint,
14557                                  GtkAccelGroup *,
14558                                  gguint,
14559                                  GdkModifierType,
14560                                  GtkAccelFlags,
14561                                  gpointer);
14562 void GtkWidget::remove-accelerator      (GtkWidget *,
14563                                          GtkAccelGroup *,
14564                                          gguint,
14565                                          GdkModifierType,
14566                                          gpointer);
14567 gboolean GtkWidget::event       (GtkWidget *,
14568                                  GdkEvent *,
14569                                  gpointer);
14570 gboolean GtkWidget::button-press-event  (GtkWidget *,
14571                                          GdkEvent *,
14572                                          gpointer);
14573 gboolean GtkWidget::button-release-event        (GtkWidget *,
14574                                                  GdkEvent *,
14575                                                  gpointer);
14576 gboolean GtkWidget::motion-notify-event (GtkWidget *,
14577                                          GdkEvent *,
14578                                          gpointer);
14579 gboolean GtkWidget::delete-event        (GtkWidget *,
14580                                          GdkEvent *,
14581                                          gpointer);
14582 gboolean GtkWidget::destroy-event       (GtkWidget *,
14583                                          GdkEvent *,
14584                                          gpointer);
14585 gboolean GtkWidget::expose-event        (GtkWidget *,
14586                                          GdkEvent *,
14587                                          gpointer);
14588 gboolean GtkWidget::key-press-event     (GtkWidget *,
14589                                          GdkEvent *,
14590                                          gpointer);
14591 gboolean GtkWidget::key-release-event   (GtkWidget *,
14592                                          GdkEvent *,
14593                                          gpointer);
14594 gboolean GtkWidget::enter-notify-event  (GtkWidget *,
14595                                          GdkEvent *,
14596                                          gpointer);
14597 gboolean GtkWidget::leave-notify-event  (GtkWidget *,
14598                                          GdkEvent *,
14599                                          gpointer);
14600 gboolean GtkWidget::configure-event     (GtkWidget *,
14601                                          GdkEvent *,
14602                                          gpointer);
14603 gboolean GtkWidget::focus-in-event      (GtkWidget *,
14604                                          GdkEvent *,
14605                                          gpointer);
14606 gboolean GtkWidget::focus-out-event     (GtkWidget *,
14607                                          GdkEvent *,
14608                                          gpointer);
14609 gboolean GtkWidget::map-event   (GtkWidget *,
14610                                  GdkEvent *,
14611                                  gpointer);
14612 gboolean GtkWidget::unmap-event (GtkWidget *,
14613                                  GdkEvent *,
14614                                  gpointer);
14615 gboolean GtkWidget::property-notify-event       (GtkWidget *,
14616                                                  GdkEvent *,
14617                                                  gpointer);
14618 gboolean GtkWidget::selection-clear-event       (GtkWidget *,
14619                                                  GdkEvent *,
14620                                                  gpointer);
14621 gboolean GtkWidget::selection-request-event     (GtkWidget *,
14622                                                  GdkEvent *,
14623                                                  gpointer);
14624 gboolean GtkWidget::selection-notify-event      (GtkWidget *,
14625                                                  GdkEvent *,
14626                                                  gpointer);
14627 void GtkWidget::selection-get   (GtkWidget *,
14628                                  GtkSelectionData *,
14629                                  gguint,
14630                                  gpointer);
14631 void GtkWidget::selection-received      (GtkWidget *,
14632                                          GtkSelectionData *,
14633                                          gguint,
14634                                          gpointer);
14635 gboolean GtkWidget::proximity-in-event  (GtkWidget *,
14636                                          GdkEvent *,
14637                                          gpointer);
14638 gboolean GtkWidget::proximity-out-event (GtkWidget *,
14639                                          GdkEvent *,
14640                                          gpointer);
14641 void GtkWidget::drag-begin      (GtkWidget *,
14642                                  GdkDragContext *,
14643                                  gpointer);
14644 void GtkWidget::drag-end        (GtkWidget *,
14645                                  GdkDragContext *,
14646                                  gpointer);
14647 void GtkWidget::drag-data-delete        (GtkWidget *,
14648                                          GdkDragContext *,
14649                                          gpointer);
14650 void GtkWidget::drag-leave      (GtkWidget *,
14651                                  GdkDragContext *,
14652                                  gguint,
14653                                  gpointer);
14654 gboolean GtkWidget::drag-motion (GtkWidget *,
14655                                  GdkDragContext *,
14656                                  ggint,
14657                                  ggint,
14658                                  gguint,
14659                                  gpointer);
14660 gboolean GtkWidget::drag-drop   (GtkWidget *,
14661                                  GdkDragContext *,
14662                                  ggint,
14663                                  ggint,
14664                                  gguint,
14665                                  gpointer);
14666 void GtkWidget::drag-data-get   (GtkWidget *,
14667                                  GdkDragContext *,
14668                                  GtkSelectionData *,
14669                                  gguint,
14670                                  gguint,
14671                                  gpointer);
14672 void GtkWidget::drag-data-received      (GtkWidget *,
14673                                          GdkDragContext *,
14674                                          ggint,
14675                                          ggint,
14676                                          GtkSelectionData *,
14677                                          gguint,
14678                                          gguint,
14679                                          gpointer);
14680 gboolean GtkWidget::client-event        (GtkWidget *,
14681                                          GdkEvent *,
14682                                          gpointer);
14683 gboolean GtkWidget::no-expose-event     (GtkWidget *,
14684                                          GdkEvent *,
14685                                          gpointer);
14686 gboolean GtkWidget::visibility-notify-event     (GtkWidget *,
14687                                                  GdkEvent *,
14688                                                  gpointer);
14689 void GtkWidget::debug-msg       (GtkWidget *,
14690                                  GtkString *,
14691                                  gpointer);
14692 </verb></tscreen>
14693
14694 <!-- ----------------------------------------------------------------- -->
14695 <sect1>GtkData
14696 <!-- ----------------------------------------------------------------- -->
14697 <p>
14698 <tscreen><verb>
14699 void GtkData::disconnect        (GtkData *,
14700                                  gpointer);
14701 </verb></tscreen>
14702
14703 <!-- ----------------------------------------------------------------- -->
14704 <sect1>GtkContainer
14705 <!-- ----------------------------------------------------------------- -->
14706 <p>
14707 <tscreen><verb>
14708 void GtkContainer::add  (GtkContainer *,
14709                          GtkWidget *,
14710                          gpointer);
14711 void GtkContainer::remove       (GtkContainer *,
14712                                  GtkWidget *,
14713                                  gpointer);
14714 void GtkContainer::check-resize (GtkContainer *,
14715                                  gpointer);
14716 GtkDirectionType GtkContainer::focus    (GtkContainer *,
14717                                          GtkDirectionType,
14718                                          gpointer);
14719 void GtkContainer::set-focus-child      (GtkContainer *,
14720                                          GtkWidget *,
14721                                          gpointer);
14722 </verb></tscreen>
14723
14724 <!-- ----------------------------------------------------------------- -->
14725 <sect1>GtkCalendar
14726 <!-- ----------------------------------------------------------------- -->
14727 <p>
14728 <tscreen><verb>
14729 void GtkCalendar::month-changed (GtkCalendar *,
14730                                  gpointer);
14731 void GtkCalendar::day-selected  (GtkCalendar *,
14732                                  gpointer);
14733 void GtkCalendar::day-selected-double-click     (GtkCalendar *,
14734                                                  gpointer);
14735 void GtkCalendar::prev-month    (GtkCalendar *,
14736                                  gpointer);
14737 void GtkCalendar::next-month    (GtkCalendar *,
14738                                  gpointer);
14739 void GtkCalendar::prev-year     (GtkCalendar *,
14740                                  gpointer);
14741 void GtkCalendar::next-year     (GtkCalendar *,
14742                                  gpointer);
14743 </verb></tscreen>
14744
14745 <!-- ----------------------------------------------------------------- -->
14746 <sect1>GtkEditable
14747 <!-- ----------------------------------------------------------------- -->
14748 <p>
14749 <tscreen><verb>
14750 void GtkEditable::changed       (GtkEditable *,
14751                                  gpointer);
14752 void GtkEditable::insert-text   (GtkEditable *,
14753                                  GtkString *,
14754                                  ggint,
14755                                  ggpointer,
14756                                  gpointer);
14757 void GtkEditable::delete-text   (GtkEditable *,
14758                                  ggint,
14759                                  ggint,
14760                                  gpointer);
14761 void GtkEditable::activate      (GtkEditable *,
14762                                  gpointer);
14763 void GtkEditable::set-editable  (GtkEditable *,
14764                                  gboolean,
14765                                  gpointer);
14766 void GtkEditable::move-cursor   (GtkEditable *,
14767                                  ggint,
14768                                  ggint,
14769                                  gpointer);
14770 void GtkEditable::move-word     (GtkEditable *,
14771                                  ggint,
14772                                  gpointer);
14773 void GtkEditable::move-page     (GtkEditable *,
14774                                  ggint,
14775                                  ggint,
14776                                  gpointer);
14777 void GtkEditable::move-to-row   (GtkEditable *,
14778                                  ggint,
14779                                  gpointer);
14780 void GtkEditable::move-to-column        (GtkEditable *,
14781                                          ggint,
14782                                          gpointer);
14783 void GtkEditable::kill-char     (GtkEditable *,
14784                                  ggint,
14785                                  gpointer);
14786 void GtkEditable::kill-word     (GtkEditable *,
14787                                  ggint,
14788                                  gpointer);
14789 void GtkEditable::kill-line     (GtkEditable *,
14790                                  ggint,
14791                                  gpointer);
14792 void GtkEditable::cut-clipboard (GtkEditable *,
14793                                  gpointer);
14794 void GtkEditable::copy-clipboard        (GtkEditable *,
14795                                          gpointer);
14796 void GtkEditable::paste-clipboard       (GtkEditable *,
14797                                          gpointer);
14798 </verb></tscreen>
14799
14800 <!-- ----------------------------------------------------------------- -->
14801 <sect1>GtkTipsQuery
14802 <!-- ----------------------------------------------------------------- -->
14803 <p>
14804 <tscreen><verb>
14805 void GtkTipsQuery::start-query  (GtkTipsQuery *,
14806                                  gpointer);
14807 void GtkTipsQuery::stop-query   (GtkTipsQuery *,
14808                                  gpointer);
14809 void GtkTipsQuery::widget-entered       (GtkTipsQuery *,
14810                                          GtkWidget *,
14811                                          GtkString *,
14812                                          GtkString *,
14813                                          gpointer);
14814 gboolean GtkTipsQuery::widget-selected  (GtkTipsQuery *,
14815                                          GtkWidget *,
14816                                          GtkString *,
14817                                          GtkString *,
14818                                          GdkEvent *,
14819                                          gpointer);
14820 </verb></tscreen>
14821
14822 <!-- ----------------------------------------------------------------- -->
14823 <sect1>GtkCList
14824 <!-- ----------------------------------------------------------------- -->
14825 <p>
14826 <tscreen><verb>
14827 void GtkCList::select-row       (GtkCList *,
14828                                  ggint,
14829                                  ggint,
14830                                  GdkEvent *,
14831                                  gpointer);
14832 void GtkCList::unselect-row     (GtkCList *,
14833                                  ggint,
14834                                  ggint,
14835                                  GdkEvent *,
14836                                  gpointer);
14837 void GtkCList::row-move (GtkCList *,
14838                          ggint,
14839                          ggint,
14840                          gpointer);
14841 void GtkCList::click-column     (GtkCList *,
14842                                  ggint,
14843                                  gpointer);
14844 void GtkCList::resize-column    (GtkCList *,
14845                                  ggint,
14846                                  ggint,
14847                                  gpointer);
14848 void GtkCList::toggle-focus-row (GtkCList *,
14849                                  gpointer);
14850 void GtkCList::select-all       (GtkCList *,
14851                                  gpointer);
14852 void GtkCList::unselect-all     (GtkCList *,
14853                                  gpointer);
14854 void GtkCList::undo-selection   (GtkCList *,
14855                                  gpointer);
14856 void GtkCList::start-selection  (GtkCList *,
14857                                  gpointer);
14858 void GtkCList::end-selection    (GtkCList *,
14859                                  gpointer);
14860 void GtkCList::toggle-add-mode  (GtkCList *,
14861                                  gpointer);
14862 void GtkCList::extend-selection (GtkCList *,
14863                                  GtkScrollType,
14864                                  ggfloat,
14865                                  gboolean,
14866                                  gpointer);
14867 void GtkCList::scroll-vertical  (GtkCList *,
14868                                  GtkScrollType,
14869                                  ggfloat,
14870                                  gpointer);
14871 void GtkCList::scroll-horizontal        (GtkCList *,
14872                                          GtkScrollType,
14873                                          ggfloat,
14874                                          gpointer);
14875 void GtkCList::abort-column-resize      (GtkCList *,
14876                                          gpointer);
14877 </verb></tscreen>
14878
14879 <!-- ----------------------------------------------------------------- -->
14880 <sect1>GtkNotebook
14881 <!-- ----------------------------------------------------------------- -->
14882 <p>
14883 <tscreen><verb>
14884 void GtkNotebook::switch-page   (GtkNotebook *,
14885                                  ggpointer,
14886                                  gguint,
14887                                  gpointer);
14888
14889 </verb></tscreen>
14890
14891 <!-- ----------------------------------------------------------------- -->
14892 <sect1>GtkList
14893 <!-- ----------------------------------------------------------------- -->
14894 <p>
14895 <tscreen><verb>
14896 void GtkList::selection-changed (GtkList *,
14897                                  gpointer);
14898 void GtkList::select-child      (GtkList *,
14899                                  GtkWidget *,
14900                                  gpointer);
14901 void GtkList::unselect-child    (GtkList *,
14902                                  GtkWidget *,
14903                                  gpointer);
14904 </verb></tscreen>
14905
14906 <!-- ----------------------------------------------------------------- -->
14907 <sect1>GtkMenuShell
14908 <!-- ----------------------------------------------------------------- -->
14909 <p>
14910 <tscreen><verb>
14911 void GtkMenuShell::deactivate   (GtkMenuShell *,
14912                                  gpointer);
14913 void GtkMenuShell::selection-done       (GtkMenuShell *,
14914                                          gpointer);
14915 void GtkMenuShell::move-current (GtkMenuShell *,
14916                                  GtkMenuDirectionType,
14917                                  gpointer);
14918 void GtkMenuShell::activate-current     (GtkMenuShell *,
14919                                          gboolean,
14920                                          gpointer);
14921 void GtkMenuShell::cancel       (GtkMenuShell *,
14922                                  gpointer);
14923 </verb></tscreen>
14924
14925 <!-- ----------------------------------------------------------------- -->
14926 <sect1>GtkToolbar
14927 <!-- ----------------------------------------------------------------- -->
14928 <p>
14929 <tscreen><verb>
14930 void GtkToolbar::orientation-changed    (GtkToolbar *,
14931                                          ggint,
14932                                          gpointer);
14933 void GtkToolbar::style-changed  (GtkToolbar *,
14934                                  ggint,
14935                                  gpointer);
14936 </verb></tscreen>
14937
14938 <!-- ----------------------------------------------------------------- -->
14939 <sect1>GtkTree
14940 <!-- ----------------------------------------------------------------- -->
14941 <p>
14942 <tscreen><verb>
14943 void GtkTree::selection-changed (GtkTree *,
14944                                  gpointer);
14945 void GtkTree::select-child      (GtkTree *,
14946                                  GtkWidget *,
14947                                  gpointer);
14948 void GtkTree::unselect-child    (GtkTree *,
14949                                  GtkWidget *,
14950                                  gpointer);
14951 </verb></tscreen>
14952
14953 <!-- ----------------------------------------------------------------- -->
14954 <sect1>GtkButton
14955 <!-- ----------------------------------------------------------------- -->
14956 <p>
14957 <tscreen><verb>
14958 void GtkButton::pressed (GtkButton *,
14959                          gpointer);
14960 void GtkButton::released        (GtkButton *,
14961                                  gpointer);
14962 void GtkButton::clicked (GtkButton *,
14963                          gpointer);
14964 void GtkButton::enter   (GtkButton *,
14965                          gpointer);
14966 void GtkButton::leave   (GtkButton *,
14967                          gpointer);
14968 </verb></tscreen>
14969
14970 <!-- ----------------------------------------------------------------- -->
14971 <sect1>GtkItem
14972 <!-- ----------------------------------------------------------------- -->
14973 <p>
14974 <tscreen><verb>
14975 void GtkItem::select    (GtkItem *,
14976                          gpointer);
14977 void GtkItem::deselect  (GtkItem *,
14978                          gpointer);
14979 void GtkItem::toggle    (GtkItem *,
14980                          gpointer);
14981 </verb></tscreen>
14982
14983 <!-- ----------------------------------------------------------------- -->
14984 <sect1>GtkWindow
14985 <!-- ----------------------------------------------------------------- -->
14986 <p>
14987 <tscreen><verb>
14988 void GtkWindow::set-focus       (GtkWindow *,
14989                                  ggpointer,
14990                                  gpointer);
14991 </verb></tscreen>
14992
14993 <!-- ----------------------------------------------------------------- -->
14994 <sect1>GtkHandleBox
14995 <!-- ----------------------------------------------------------------- -->
14996 <p>
14997 <tscreen><verb>
14998 void GtkHandleBox::child-attached       (GtkHandleBox *,
14999                                          GtkWidget *,
15000                                          gpointer);
15001 void GtkHandleBox::child-detached       (GtkHandleBox *,
15002                                          GtkWidget *,
15003                                          gpointer);
15004 </verb></tscreen>
15005
15006 <!-- ----------------------------------------------------------------- -->
15007 <sect1>GtkToggleButton
15008 <!-- ----------------------------------------------------------------- -->
15009 <p>
15010 <tscreen><verb>
15011 void GtkToggleButton::toggled   (GtkToggleButton *,
15012                                  gpointer);
15013
15014 </verb></tscreen>
15015
15016 <!-- ----------------------------------------------------------------- -->
15017 <sect1>GtkMenuItem
15018 <!-- ----------------------------------------------------------------- -->
15019 <p>
15020 <tscreen><verb>
15021 void GtkMenuItem::activate      (GtkMenuItem *,
15022                                  gpointer);
15023 void GtkMenuItem::activate-item (GtkMenuItem *,
15024                                  gpointer);
15025 </verb></tscreen>
15026
15027 <!-- ----------------------------------------------------------------- -->
15028 <sect1>GtkListItem
15029 <!-- ----------------------------------------------------------------- -->
15030 <p>
15031 <tscreen><verb>
15032 void GtkListItem::toggle-focus-row      (GtkListItem *,
15033                                          gpointer);
15034 void GtkListItem::select-all    (GtkListItem *,
15035                                  gpointer);
15036 void GtkListItem::unselect-all  (GtkListItem *,
15037                                  gpointer);
15038 void GtkListItem::undo-selection        (GtkListItem *,
15039                                          gpointer);
15040 void GtkListItem::start-selection       (GtkListItem *,
15041                                          gpointer);
15042 void GtkListItem::end-selection (GtkListItem *,
15043                                  gpointer);
15044 void GtkListItem::toggle-add-mode       (GtkListItem *,
15045                                          gpointer);
15046 void GtkListItem::extend-selection      (GtkListItem *,
15047                                          GtkEnum,
15048                                          ggfloat,
15049                                          gboolean,
15050                                          gpointer);
15051 void GtkListItem::scroll-vertical       (GtkListItem *,
15052                                          GtkEnum,
15053                                          ggfloat,
15054                                          gpointer);
15055 void GtkListItem::scroll-horizontal     (GtkListItem *,
15056                                          GtkEnum,
15057                                          ggfloat,
15058                                          gpointer);
15059 </verb></tscreen>
15060
15061 <!-- ----------------------------------------------------------------- -->
15062 <sect1>GtkTreeItem
15063 <!-- ----------------------------------------------------------------- -->
15064 <p>
15065 <tscreen><verb>
15066 void GtkTreeItem::collapse      (GtkTreeItem *,
15067                                  gpointer);
15068 void GtkTreeItem::expand        (GtkTreeItem *,
15069                                  gpointer);
15070 </verb></tscreen>
15071
15072 <!-- ----------------------------------------------------------------- -->
15073 <sect1>GtkCheckMenuItem
15074 <!-- ----------------------------------------------------------------- -->
15075 <p>
15076 <tscreen><verb>
15077 void GtkCheckMenuItem::toggled  (GtkCheckMenuItem *,
15078                                  gpointer);
15079 </verb></tscreen>
15080
15081 <!-- ----------------------------------------------------------------- -->
15082 <sect1>GtkInputDialog
15083 <!-- ----------------------------------------------------------------- -->
15084 <p>
15085 <tscreen><verb>
15086 void GtkInputDialog::enable-device      (GtkInputDialog *,
15087                                          ggint,
15088                                          gpointer);
15089 void GtkInputDialog::disable-device     (GtkInputDialog *,
15090                                          ggint,
15091                                          gpointer);
15092 </verb></tscreen>
15093
15094 <!-- ----------------------------------------------------------------- -->
15095 <sect1>GtkColorSelection
15096 <!-- ----------------------------------------------------------------- -->
15097 <p>
15098 <tscreen><verb>
15099 void GtkColorSelection::color-changed   (GtkColorSelection *,
15100                                          gpointer);
15101 </verb></tscreen>
15102
15103 <!-- ----------------------------------------------------------------- -->
15104 <sect1>GtkStatusBar
15105 <!-- ----------------------------------------------------------------- -->
15106 <p>
15107 <tscreen><verb>
15108 void GtkStatusbar::text-pushed  (GtkStatusbar *,
15109                                  gguint,
15110                                  GtkString *,
15111                                  gpointer);
15112 void GtkStatusbar::text-popped  (GtkStatusbar *,
15113                                  gguint,
15114                                  GtkString *,
15115                                  gpointer);
15116 </verb></tscreen>
15117
15118 <!-- ----------------------------------------------------------------- -->
15119 <sect1>GtkCTree
15120 <!-- ----------------------------------------------------------------- -->
15121 <p>
15122 <tscreen><verb>
15123 void GtkCTree::tree-select-row  (GtkCTree *,
15124                                  GtkCTreeNode *,
15125                                  ggint,
15126                                  gpointer);
15127 void GtkCTree::tree-unselect-row        (GtkCTree *,
15128                                          GtkCTreeNode *,
15129                                          ggint,
15130                                          gpointer);
15131 void GtkCTree::tree-expand      (GtkCTree *,
15132                                  GtkCTreeNode *,
15133                                  gpointer);
15134 void GtkCTree::tree-collapse    (GtkCTree *,
15135                                  ggpointer,
15136                                  gpointer);
15137 void GtkCTree::tree-move        (GtkCTree *,
15138                                  GtkCTreeNode *,
15139                                  GtkCTreeNode *,
15140                                  GtkCTreeNode *,
15141                                  gpointer);
15142 void GtkCTree::change-focus-row-expansion       (GtkCTree *,
15143                                                  GtkCTreeExpansionType,
15144                                                  gpointer);
15145 </verb></tscreen>
15146
15147 <!-- ----------------------------------------------------------------- -->
15148 <sect1>GtkCurve
15149 <!-- ----------------------------------------------------------------- -->
15150 <p>
15151 <tscreen><verb>
15152 void GtkCurve::curve-type-changed       (GtkCurve *,
15153                                          gpointer);
15154 </verb></tscreen>
15155
15156 <!-- ----------------------------------------------------------------- -->
15157 <sect1>GtkAdjustment
15158 <!-- ----------------------------------------------------------------- -->
15159 <p>
15160 <tscreen><verb>
15161 void GtkAdjustment::changed     (GtkAdjustment *,
15162                                  gpointer);
15163 void GtkAdjustment::value-changed       (GtkAdjustment *,
15164                                          gpointer);
15165 </verb></tscreen>
15166
15167 <!-- ***************************************************************** -->
15168 <sect> GDK Event Types<label id="sec_GDK_Event_Types">
15169 <!-- ***************************************************************** -->
15170 <p>
15171 The following data types are passed into event handlers by GTK+. For
15172 each data type listed, the signals that use this data type are listed.
15173
15174 <itemize>
15175 <item>  GdkEvent
15176           <itemize>
15177           <item>drag_end_event
15178           </itemize>
15179
15180 <item>  GdkEventType
15181
15182 <item>  GdkEventAny
15183           <itemize>
15184           <item>delete_event
15185           <item>destroy_event
15186           <item>map_event
15187           <item>unmap_event
15188           <item>no_expose_event
15189           </itemize>
15190
15191 <item>  GdkEventExpose
15192           <itemize>
15193           <item>expose_event
15194           </itemize>
15195
15196 <item>  GdkEventNoExpose
15197
15198 <item>  GdkEventVisibility
15199
15200 <item>  GdkEventMotion
15201           <itemize>
15202           <item>motion_notify_event
15203           </itemize>
15204
15205 <item>  GdkEventButton
15206           <itemize>
15207           <item>button_press_event
15208           <item>button_release_event
15209           </itemize>
15210
15211 <item>  GdkEventKey
15212           <itemize>
15213           <item>key_press_event
15214           <item>key_release_event
15215           </itemize>
15216
15217 <item>  GdkEventCrossing
15218           <itemize>
15219           <item>enter_notify_event
15220           <item>leave_notify_event
15221           </itemize>
15222
15223 <item>  GdkEventFocus
15224           <itemize>
15225           <item>focus_in_event
15226           <item>focus_out_event
15227           </itemize>
15228
15229 <item>  GdkEventConfigure
15230           <itemize>
15231           <item>configure_event
15232           </itemize>
15233
15234 <item>  GdkEventProperty
15235           <itemize>
15236           <item>property_notify_event
15237           </itemize>
15238
15239 <item>  GdkEventSelection
15240           <itemize>
15241           <item>selection_clear_event
15242           <item>selection_request_event
15243           <item>selection_notify_event
15244           </itemize>
15245
15246 <item>  GdkEventProximity
15247           <itemize>
15248           <item>proximity_in_event
15249           <item>proximity_out_event
15250           </itemize>
15251
15252 <item>  GdkEventDragBegin
15253           <itemize>
15254           <item>drag_begin_event
15255           </itemize>
15256
15257 <item>  GdkEventDragRequest
15258           <itemize>
15259           <item>drag_request_event
15260           </itemize>
15261
15262 <item>  GdkEventDropEnter
15263           <itemize>
15264           <item>drop_enter_event
15265           </itemize>
15266
15267 <item>  GdkEventDropLeave
15268           <itemize>
15269           <item>drop_leave_event
15270           </itemize>
15271
15272 <item>  GdkEventDropDataAvailable
15273           <itemize>
15274           <item>drop_data_available_event
15275           </itemize>
15276
15277 <item>  GdkEventClient
15278           <itemize>
15279           <item>client_event
15280           </itemize>
15281
15282 <item>  GdkEventOther
15283           <itemize>
15284           <item>other_event
15285           </itemize>
15286 </itemize>
15287
15288 The data type <tt/GdkEventType/ is a special data type that is used by
15289 all the other data types as an indicator of the data type being passed
15290 to the signal handler. As you will see below, each of the event data
15291 structures has a member of this type. It is defined as an enumeration
15292 type as follows:
15293
15294 <tscreen><verb>
15295 typedef enum
15296 {
15297   GDK_NOTHING           = -1,
15298   GDK_DELETE            = 0,
15299   GDK_DESTROY           = 1,
15300   GDK_EXPOSE            = 2,
15301   GDK_MOTION_NOTIFY     = 3,
15302   GDK_BUTTON_PRESS      = 4,
15303   GDK_2BUTTON_PRESS     = 5,
15304   GDK_3BUTTON_PRESS     = 6,
15305   GDK_BUTTON_RELEASE    = 7,
15306   GDK_KEY_PRESS         = 8,
15307   GDK_KEY_RELEASE       = 9,
15308   GDK_ENTER_NOTIFY      = 10,
15309   GDK_LEAVE_NOTIFY      = 11,
15310   GDK_FOCUS_CHANGE      = 12,
15311   GDK_CONFIGURE         = 13,
15312   GDK_MAP               = 14,
15313   GDK_UNMAP             = 15,
15314   GDK_PROPERTY_NOTIFY   = 16,
15315   GDK_SELECTION_CLEAR   = 17,
15316   GDK_SELECTION_REQUEST = 18,
15317   GDK_SELECTION_NOTIFY  = 19,
15318   GDK_PROXIMITY_IN      = 20,
15319   GDK_PROXIMITY_OUT     = 21,
15320   GDK_DRAG_BEGIN        = 22,
15321   GDK_DRAG_REQUEST      = 23,
15322   GDK_DROP_ENTER        = 24,
15323   GDK_DROP_LEAVE        = 25,
15324   GDK_DROP_DATA_AVAIL   = 26,
15325   GDK_CLIENT_EVENT      = 27,
15326   GDK_VISIBILITY_NOTIFY = 28,
15327   GDK_NO_EXPOSE         = 29,
15328   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
15329 } GdkEventType;
15330 </verb></tscreen>
15331
15332 The other event type that is different from the others is
15333 <tt/GdkEvent/ itself. This is a union of all the other
15334 data types, which allows it to be cast to a specific
15335 event data type within a signal handler.
15336
15337 <!-- Just a big list for now, needs expanding upon - TRG -->
15338 So, the event data types are defined as follows:
15339
15340 <tscreen><verb>
15341 struct _GdkEventAny
15342 {
15343   GdkEventType type;
15344   GdkWindow *window;
15345   gint8 send_event;
15346 };
15347
15348 struct _GdkEventExpose
15349 {
15350   GdkEventType type;
15351   GdkWindow *window;
15352   gint8 send_event;
15353   GdkRectangle area;
15354   gint count; /* If non-zero, how many more events follow. */
15355 };
15356
15357 struct _GdkEventNoExpose
15358 {
15359   GdkEventType type;
15360   GdkWindow *window;
15361   gint8 send_event;
15362   /* XXX: does anyone need the X major_code or minor_code fields? */
15363 };
15364
15365 struct _GdkEventVisibility
15366 {
15367   GdkEventType type;
15368   GdkWindow *window;
15369   gint8 send_event;
15370   GdkVisibilityState state;
15371 };
15372
15373 struct _GdkEventMotion
15374 {
15375   GdkEventType type;
15376   GdkWindow *window;
15377   gint8 send_event;
15378   guint32 time;
15379   gdouble x;
15380   gdouble y;
15381   gdouble pressure;
15382   gdouble xtilt;
15383   gdouble ytilt;
15384   guint state;
15385   gint16 is_hint;
15386   GdkInputSource source;
15387   guint32 deviceid;
15388   gdouble x_root, y_root;
15389 };
15390
15391 struct _GdkEventButton
15392 {
15393   GdkEventType type;
15394   GdkWindow *window;
15395   gint8 send_event;
15396   guint32 time;
15397   gdouble x;
15398   gdouble y;
15399   gdouble pressure;
15400   gdouble xtilt;
15401   gdouble ytilt;
15402   guint state;
15403   guint button;
15404   GdkInputSource source;
15405   guint32 deviceid;
15406   gdouble x_root, y_root;
15407 };
15408
15409 struct _GdkEventKey
15410 {
15411   GdkEventType type;
15412   GdkWindow *window;
15413   gint8 send_event;
15414   guint32 time;
15415   guint state;
15416   guint keyval;
15417   gint length;
15418   gchar *string;
15419 };
15420
15421 struct _GdkEventCrossing
15422 {
15423   GdkEventType type;
15424   GdkWindow *window;
15425   gint8 send_event;
15426   GdkWindow *subwindow;
15427   GdkNotifyType detail;
15428 };
15429
15430 struct _GdkEventFocus
15431 {
15432   GdkEventType type;
15433   GdkWindow *window;
15434   gint8 send_event;
15435   gint16 in;
15436 };
15437
15438 struct _GdkEventConfigure
15439 {
15440   GdkEventType type;
15441   GdkWindow *window;
15442   gint8 send_event;
15443   gint16 x, y;
15444   gint16 width;
15445   gint16 height;
15446 };
15447
15448 struct _GdkEventProperty
15449 {
15450   GdkEventType type;
15451   GdkWindow *window;
15452   gint8 send_event;
15453   GdkAtom atom;
15454   guint32 time;
15455   guint state;
15456 };
15457
15458 struct _GdkEventSelection
15459 {
15460   GdkEventType type;
15461   GdkWindow *window;
15462   gint8 send_event;
15463   GdkAtom selection;
15464   GdkAtom target;
15465   GdkAtom property;
15466   guint32 requestor;
15467   guint32 time;
15468 };
15469
15470 /* This event type will be used pretty rarely. It only is important
15471    for XInput aware programs that are drawing their own cursor */
15472
15473 struct _GdkEventProximity
15474 {
15475   GdkEventType type;
15476   GdkWindow *window;
15477   gint8 send_event;
15478   guint32 time;
15479   GdkInputSource source;
15480   guint32 deviceid;
15481 };
15482
15483 struct _GdkEventDragRequest
15484 {
15485   GdkEventType type;
15486   GdkWindow *window;
15487   gint8 send_event;
15488   guint32 requestor;
15489   union {
15490     struct {
15491       guint protocol_version:4;
15492       guint sendreply:1;
15493       guint willaccept:1;
15494       guint delete_data:1; /* Do *not* delete if link is sent, only
15495                               if data is sent */
15496       guint senddata:1;
15497       guint reserved:22;
15498     } flags;
15499     glong allflags;
15500   } u;
15501   guint8 isdrop; /* This gdk event can be generated by a couple of
15502                     X events - this lets the app know whether the
15503                     drop really occurred or we just set the data */
15504
15505   GdkPoint drop_coords;
15506   gchar *data_type;
15507   guint32 timestamp;
15508 };
15509
15510 struct _GdkEventDragBegin
15511 {
15512   GdkEventType type;
15513   GdkWindow *window;
15514   gint8 send_event;
15515   union {
15516     struct {
15517       guint protocol_version:4;
15518       guint reserved:28;
15519     } flags;
15520     glong allflags;
15521   } u;
15522 };
15523
15524 struct _GdkEventDropEnter
15525 {
15526   GdkEventType type;
15527   GdkWindow *window;
15528   gint8 send_event;
15529   guint32 requestor;
15530   union {
15531     struct {
15532       guint protocol_version:4;
15533       guint sendreply:1;
15534       guint extended_typelist:1;
15535       guint reserved:26;
15536     } flags;
15537     glong allflags;
15538   } u;
15539 };
15540
15541 struct _GdkEventDropLeave
15542 {
15543   GdkEventType type;
15544   GdkWindow *window;
15545   gint8 send_event;
15546   guint32 requestor;
15547   union {
15548     struct {
15549       guint protocol_version:4;
15550       guint reserved:28;
15551     } flags;
15552     glong allflags;
15553   } u;
15554 };
15555
15556 struct _GdkEventDropDataAvailable
15557 {
15558   GdkEventType type;
15559   GdkWindow *window;
15560   gint8 send_event;
15561   guint32 requestor;
15562   union {
15563     struct {
15564       guint protocol_version:4;
15565       guint isdrop:1;
15566       guint reserved:25;
15567     } flags;
15568     glong allflags;
15569   } u;
15570   gchar *data_type; /* MIME type */
15571   gulong data_numbytes;
15572   gpointer data;
15573   guint32 timestamp;
15574   GdkPoint coords;
15575 };
15576
15577 struct _GdkEventClient
15578 {
15579   GdkEventType type;
15580   GdkWindow *window;
15581   gint8 send_event;
15582   GdkAtom message_type;
15583   gushort data_format;
15584   union {
15585     char b[20];
15586     short s[10];
15587     long l[5];
15588   } data;
15589 };
15590
15591 struct _GdkEventOther
15592 {
15593   GdkEventType type;
15594   GdkWindow *window;
15595   gint8 send_event;
15596   GdkXEvent *xevent;
15597 };
15598 </verb></tscreen>
15599
15600 <!-- ***************************************************************** -->
15601 <sect> Code Examples
15602 <!-- ***************************************************************** -->
15603 <p>
15604 Below are the code examples that are used in the above text
15605 which are not included in complete form elsewhere.
15606
15607 <!-- ----------------------------------------------------------------- -->
15608 <sect1>Tictactoe
15609 <!-- ----------------------------------------------------------------- -->
15610 <sect2>tictactoe.h
15611 <p>
15612 <tscreen><verb>
15613 /* example-start tictactoe tictactoe.h */
15614
15615 /* GTK - The GIMP Toolkit
15616  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15617  *
15618  * This library is free software; you can redistribute it and/or
15619  * modify it under the terms of the GNU Library General Public
15620  * License as published by the Free Software Foundation; either
15621  * version 2 of the License, or (at your option) any later version.
15622  *
15623  * This library is distributed in the hope that it will be useful,
15624  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15625  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15626  * Library General Public License for more details.
15627  *
15628  * You should have received a copy of the GNU Library General Public
15629  * License along with this library; if not, write to the
15630  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15631  * Boston, MA 02111-1307, USA.
15632  */
15633 #ifndef __TICTACTOE_H__
15634 #define __TICTACTOE_H__
15635
15636
15637 #include <gdk/gdk.h>
15638 #include <gtk/gtkvbox.h>
15639
15640
15641 #ifdef __cplusplus
15642 extern "C" {
15643 #endif /* __cplusplus */
15644
15645 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
15646 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
15647 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
15648
15649
15650 typedef struct _Tictactoe       Tictactoe;
15651 typedef struct _TictactoeClass  TictactoeClass;
15652
15653 struct _Tictactoe
15654 {
15655   GtkVBox vbox;
15656   
15657   GtkWidget *buttons[3][3];
15658 };
15659
15660 struct _TictactoeClass
15661 {
15662   GtkVBoxClass parent_class;
15663
15664   void (* tictactoe) (Tictactoe *ttt);
15665 };
15666
15667 guint          tictactoe_get_type        (void);
15668 GtkWidget*     tictactoe_new             (void);
15669 void           tictactoe_clear           (Tictactoe *ttt);
15670
15671 #ifdef __cplusplus
15672 }
15673 #endif /* __cplusplus */
15674
15675 #endif /* __TICTACTOE_H__ */
15676
15677 /* example-end */
15678 </verb></tscreen>
15679
15680 <!-- ----------------------------------------------------------------- -->
15681 <sect2>tictactoe.c
15682 <p>
15683 <tscreen><verb>
15684 /* example-start tictactoe tictactoe.c */
15685
15686 /* GTK - The GIMP Toolkit
15687  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15688  *
15689  * This library is free software; you can redistribute it and/or
15690  * modify it under the terms of the GNU Library General Public
15691  * License as published by the Free Software Foundation; either
15692  * version 2 of the License, or (at your option) any later version.
15693  *
15694  * This library is distributed in the hope that it will be useful,
15695  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15696  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15697  * Library General Public License for more details.
15698  *
15699  * You should have received a copy of the GNU Library General Public
15700  * License along with this library; if not, write to the
15701  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15702  * Boston, MA 02111-1307, USA.
15703  */
15704 #include "gtk/gtksignal.h"
15705 #include "gtk/gtktable.h"
15706 #include "gtk/gtktogglebutton.h"
15707 #include "tictactoe.h"
15708
15709 enum {
15710   TICTACTOE_SIGNAL,
15711   LAST_SIGNAL
15712 };
15713
15714 static void tictactoe_class_init          (TictactoeClass *klass);
15715 static void tictactoe_init                (Tictactoe      *ttt);
15716 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
15717
15718 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
15719
15720 guint
15721 tictactoe_get_type ()
15722 {
15723   static guint ttt_type = 0;
15724
15725   if (!ttt_type)
15726     {
15727       GtkTypeInfo ttt_info =
15728       {
15729         "Tictactoe",
15730         sizeof (Tictactoe),
15731         sizeof (TictactoeClass),
15732         (GtkClassInitFunc) tictactoe_class_init,
15733         (GtkObjectInitFunc) tictactoe_init,
15734         (GtkArgSetFunc) NULL,
15735         (GtkArgGetFunc) NULL
15736       };
15737
15738       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
15739     }
15740
15741   return ttt_type;
15742 }
15743
15744 static void
15745 tictactoe_class_init (TictactoeClass *class)
15746 {
15747   GtkObjectClass *object_class;
15748
15749   object_class = (GtkObjectClass*) class;
15750   
15751   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
15752                                          GTK_RUN_FIRST,
15753                                          object_class->type,
15754                                          GTK_SIGNAL_OFFSET (TictactoeClass,
15755                                                             tictactoe),
15756                                          gtk_signal_default_marshaller,
15757                                          GTK_TYPE_NONE, 0);
15758
15759
15760   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
15761
15762   class->tictactoe = NULL;
15763 }
15764
15765 static void
15766 tictactoe_init (Tictactoe *ttt)
15767 {
15768   GtkWidget *table;
15769   gint i,j;
15770   
15771   table = gtk_table_new (3, 3, TRUE);
15772   gtk_container_add (GTK_CONTAINER(ttt), table);
15773   gtk_widget_show (table);
15774
15775   for (i=0;i<3; i++)
15776     for (j=0;j<3; j++)
15777       {
15778         ttt->buttons[i][j] = gtk_toggle_button_new ();
15779         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
15780                                    i, i+1, j, j+1);
15781         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
15782                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
15783         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
15784         gtk_widget_show (ttt->buttons[i][j]);
15785       }
15786 }
15787
15788 GtkWidget*
15789 tictactoe_new ()
15790 {
15791   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
15792 }
15793
15794 void           
15795 tictactoe_clear (Tictactoe *ttt)
15796 {
15797   int i,j;
15798
15799   for (i=0;i<3;i++)
15800     for (j=0;j<3;j++)
15801       {
15802         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
15803         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
15804                                      FALSE);
15805         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
15806       }
15807 }
15808
15809 static void
15810 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
15811 {
15812   int i,k;
15813
15814   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
15815                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
15816                              { 0, 1, 2 }, { 0, 1, 2 } };
15817   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
15818                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
15819                              { 0, 1, 2 }, { 2, 1, 0 } };
15820
15821   int success, found;
15822
15823   for (k=0; k<8; k++)
15824     {
15825       success = TRUE;
15826       found = FALSE;
15827
15828       for (i=0;i<3;i++)
15829         {
15830           success = success &amp;&amp; 
15831             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
15832           found = found ||
15833             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
15834         }
15835       
15836       if (success &amp;&amp; found)
15837         {
15838           gtk_signal_emit (GTK_OBJECT (ttt), 
15839                            tictactoe_signals[TICTACTOE_SIGNAL]);
15840           break;
15841         }
15842     }
15843 }
15844
15845 /* example-end */
15846 </verb></tscreen>
15847
15848 <!-- ----------------------------------------------------------------- -->
15849 <sect2>ttt_test.c
15850 <p>
15851 <tscreen><verb>
15852 /* example-start tictactoe ttt_test.c */
15853
15854 #include <gtk/gtk.h>
15855 #include "tictactoe.h"
15856
15857 void
15858 win (GtkWidget *widget, gpointer data)
15859 {
15860   g_print ("Yay!\n");
15861   tictactoe_clear (TICTACTOE (widget));
15862 }
15863
15864 int 
15865 main (int argc, char *argv[])
15866 {
15867   GtkWidget *window;
15868   GtkWidget *ttt;
15869   
15870   gtk_init (&amp;argc, &amp;argv);
15871
15872   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15873   
15874   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
15875   
15876   gtk_signal_connect (GTK_OBJECT (window), "destroy",
15877                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
15878   
15879   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
15880
15881   ttt = tictactoe_new ();
15882   
15883   gtk_container_add (GTK_CONTAINER (window), ttt);
15884   gtk_widget_show (ttt);
15885
15886   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
15887                       GTK_SIGNAL_FUNC (win), NULL);
15888
15889   gtk_widget_show (window);
15890   
15891   gtk_main ();
15892   
15893   return 0;
15894 }
15895
15896 /* example-end */
15897 </verb></tscreen>
15898
15899 <!-- ----------------------------------------------------------------- -->
15900 <sect1> GtkDial
15901
15902 <!-- ----------------------------------------------------------------- -->
15903 <sect2> gtkdial.h
15904 <p>
15905 <tscreen><verb>
15906 /* example-start gtkdial gtkdial.h */
15907
15908 /* GTK - The GIMP Toolkit
15909  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15910  *
15911  * This library is free software; you can redistribute it and/or
15912  * modify it under the terms of the GNU Library General Public
15913  * License as published by the Free Software Foundation; either
15914  * version 2 of the License, or (at your option) any later version.
15915  *
15916  * This library is distributed in the hope that it will be useful,
15917  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15918  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15919  * Library General Public License for more details.
15920  *
15921  * You should have received a copy of the GNU Library General Public
15922  * License along with this library; if not, write to the
15923  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15924  * Boston, MA 02111-1307, USA.
15925  */
15926 #ifndef __GTK_DIAL_H__
15927 #define __GTK_DIAL_H__
15928
15929
15930 #include <gdk/gdk.h>
15931 #include <gtk/gtkadjustment.h>
15932 #include <gtk/gtkwidget.h>
15933
15934
15935 #ifdef __cplusplus
15936 extern "C" {
15937 #endif /* __cplusplus */
15938
15939
15940 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
15941 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
15942 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
15943
15944
15945 typedef struct _GtkDial        GtkDial;
15946 typedef struct _GtkDialClass   GtkDialClass;
15947
15948 struct _GtkDial
15949 {
15950   GtkWidget widget;
15951
15952   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
15953   guint policy : 2;
15954
15955   /* Button currently pressed or 0 if none */
15956   guint8 button;
15957
15958   /* Dimensions of dial components */
15959   gint radius;
15960   gint pointer_width;
15961
15962   /* ID of update timer, or 0 if none */
15963   guint32 timer;
15964
15965   /* Current angle */
15966   gfloat angle;
15967
15968   /* Old values from adjustment stored so we know when something changes */
15969   gfloat old_value;
15970   gfloat old_lower;
15971   gfloat old_upper;
15972
15973   /* The adjustment object that stores the data for this dial */
15974   GtkAdjustment *adjustment;
15975 };
15976
15977 struct _GtkDialClass
15978 {
15979   GtkWidgetClass parent_class;
15980 };
15981
15982
15983 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
15984 guint          gtk_dial_get_type               (void);
15985 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
15986 void           gtk_dial_set_update_policy      (GtkDial      *dial,
15987                                                 GtkUpdateType  policy);
15988
15989 void           gtk_dial_set_adjustment         (GtkDial      *dial,
15990                                                 GtkAdjustment *adjustment);
15991 #ifdef __cplusplus
15992 }
15993 #endif /* __cplusplus */
15994
15995
15996 #endif /* __GTK_DIAL_H__ */
15997 /* example-end */
15998 </verb></tscreen>
15999
16000 <!-- ----------------------------------------------------------------- -->
16001 <sect2> gtkdial.c
16002 <p>
16003 <tscreen><verb>
16004 /* example-start gtkdial gtkdial.c */
16005
16006 /* GTK - The GIMP Toolkit
16007  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16008  *
16009  * This library is free software; you can redistribute it and/or
16010  * modify it under the terms of the GNU Library General Public
16011  * License as published by the Free Software Foundation; either
16012  * version 2 of the License, or (at your option) any later version.
16013  *
16014  * This library is distributed in the hope that it will be useful,
16015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16017  * Library General Public License for more details.
16018  *
16019  * You should have received a copy of the GNU Library General Public
16020  * License along with this library; if not, write to the
16021  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16022  * Boston, MA 02111-1307, USA.
16023  */
16024 #include <math.h>
16025 #include <stdio.h>
16026 #include <gtk/gtkmain.h>
16027 #include <gtk/gtksignal.h>
16028
16029 #include "gtkdial.h"
16030
16031 #define SCROLL_DELAY_LENGTH  300
16032 #define DIAL_DEFAULT_SIZE 100
16033
16034 /* Forward declarations */
16035
16036 static void gtk_dial_class_init               (GtkDialClass    *klass);
16037 static void gtk_dial_init                     (GtkDial         *dial);
16038 static void gtk_dial_destroy                  (GtkObject        *object);
16039 static void gtk_dial_realize                  (GtkWidget        *widget);
16040 static void gtk_dial_size_request             (GtkWidget      *widget,
16041                                                GtkRequisition *requisition);
16042 static void gtk_dial_size_allocate            (GtkWidget     *widget,
16043                                                GtkAllocation *allocation);
16044 static gint gtk_dial_expose                   (GtkWidget        *widget,
16045                                                 GdkEventExpose   *event);
16046 static gint gtk_dial_button_press             (GtkWidget        *widget,
16047                                                 GdkEventButton   *event);
16048 static gint gtk_dial_button_release           (GtkWidget        *widget,
16049                                                 GdkEventButton   *event);
16050 static gint gtk_dial_motion_notify            (GtkWidget        *widget,
16051                                                 GdkEventMotion   *event);
16052 static gint gtk_dial_timer                    (GtkDial         *dial);
16053
16054 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
16055 static void gtk_dial_update                   (GtkDial *dial);
16056 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
16057                                                 gpointer          data);
16058 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
16059                                                 gpointer          data);
16060
16061 /* Local data */
16062
16063 static GtkWidgetClass *parent_class = NULL;
16064
16065 guint
16066 gtk_dial_get_type ()
16067 {
16068   static guint dial_type = 0;
16069
16070   if (!dial_type)
16071     {
16072       GtkTypeInfo dial_info =
16073       {
16074         "GtkDial",
16075         sizeof (GtkDial),
16076         sizeof (GtkDialClass),
16077         (GtkClassInitFunc) gtk_dial_class_init,
16078         (GtkObjectInitFunc) gtk_dial_init,
16079         (GtkArgSetFunc) NULL,
16080         (GtkArgGetFunc) NULL,
16081       };
16082
16083       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
16084     }
16085
16086   return dial_type;
16087 }
16088
16089 static void
16090 gtk_dial_class_init (GtkDialClass *class)
16091 {
16092   GtkObjectClass *object_class;
16093   GtkWidgetClass *widget_class;
16094
16095   object_class = (GtkObjectClass*) class;
16096   widget_class = (GtkWidgetClass*) class;
16097
16098   parent_class = gtk_type_class (gtk_widget_get_type ());
16099
16100   object_class->destroy = gtk_dial_destroy;
16101
16102   widget_class->realize = gtk_dial_realize;
16103   widget_class->expose_event = gtk_dial_expose;
16104   widget_class->size_request = gtk_dial_size_request;
16105   widget_class->size_allocate = gtk_dial_size_allocate;
16106   widget_class->button_press_event = gtk_dial_button_press;
16107   widget_class->button_release_event = gtk_dial_button_release;
16108   widget_class->motion_notify_event = gtk_dial_motion_notify;
16109 }
16110
16111 static void
16112 gtk_dial_init (GtkDial *dial)
16113 {
16114   dial->button = 0;
16115   dial->policy = GTK_UPDATE_CONTINUOUS;
16116   dial->timer = 0;
16117   dial->radius = 0;
16118   dial->pointer_width = 0;
16119   dial->angle = 0.0;
16120   dial->old_value = 0.0;
16121   dial->old_lower = 0.0;
16122   dial->old_upper = 0.0;
16123   dial->adjustment = NULL;
16124 }
16125
16126 GtkWidget*
16127 gtk_dial_new (GtkAdjustment *adjustment)
16128 {
16129   GtkDial *dial;
16130
16131   dial = gtk_type_new (gtk_dial_get_type ());
16132
16133   if (!adjustment)
16134     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0,
16135                                                       0.0, 0.0, 0.0);
16136
16137   gtk_dial_set_adjustment (dial, adjustment);
16138
16139   return GTK_WIDGET (dial);
16140 }
16141
16142 static void
16143 gtk_dial_destroy (GtkObject *object)
16144 {
16145   GtkDial *dial;
16146
16147   g_return_if_fail (object != NULL);
16148   g_return_if_fail (GTK_IS_DIAL (object));
16149
16150   dial = GTK_DIAL (object);
16151
16152   if (dial->adjustment)
16153     gtk_object_unref (GTK_OBJECT (dial->adjustment));
16154
16155   if (GTK_OBJECT_CLASS (parent_class)->destroy)
16156     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
16157 }
16158
16159 GtkAdjustment*
16160 gtk_dial_get_adjustment (GtkDial *dial)
16161 {
16162   g_return_val_if_fail (dial != NULL, NULL);
16163   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
16164
16165   return dial->adjustment;
16166 }
16167
16168 void
16169 gtk_dial_set_update_policy (GtkDial      *dial,
16170                              GtkUpdateType  policy)
16171 {
16172   g_return_if_fail (dial != NULL);
16173   g_return_if_fail (GTK_IS_DIAL (dial));
16174
16175   dial->policy = policy;
16176 }
16177
16178 void
16179 gtk_dial_set_adjustment (GtkDial      *dial,
16180                           GtkAdjustment *adjustment)
16181 {
16182   g_return_if_fail (dial != NULL);
16183   g_return_if_fail (GTK_IS_DIAL (dial));
16184
16185   if (dial->adjustment)
16186     {
16187       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment),
16188                                      (gpointer) dial);
16189       gtk_object_unref (GTK_OBJECT (dial->adjustment));
16190     }
16191
16192   dial->adjustment = adjustment;
16193   gtk_object_ref (GTK_OBJECT (dial->adjustment));
16194
16195   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
16196                       (GtkSignalFunc) gtk_dial_adjustment_changed,
16197                       (gpointer) dial);
16198   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
16199                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
16200                       (gpointer) dial);
16201
16202   dial->old_value = adjustment->value;
16203   dial->old_lower = adjustment->lower;
16204   dial->old_upper = adjustment->upper;
16205
16206   gtk_dial_update (dial);
16207 }
16208
16209 static void
16210 gtk_dial_realize (GtkWidget *widget)
16211 {
16212   GtkDial *dial;
16213   GdkWindowAttr attributes;
16214   gint attributes_mask;
16215
16216   g_return_if_fail (widget != NULL);
16217   g_return_if_fail (GTK_IS_DIAL (widget));
16218
16219   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
16220   dial = GTK_DIAL (widget);
16221
16222   attributes.x = widget->allocation.x;
16223   attributes.y = widget->allocation.y;
16224   attributes.width = widget->allocation.width;
16225   attributes.height = widget->allocation.height;
16226   attributes.wclass = GDK_INPUT_OUTPUT;
16227   attributes.window_type = GDK_WINDOW_CHILD;
16228   attributes.event_mask = gtk_widget_get_events (widget) | 
16229     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
16230     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
16231     GDK_POINTER_MOTION_HINT_MASK;
16232   attributes.visual = gtk_widget_get_visual (widget);
16233   attributes.colormap = gtk_widget_get_colormap (widget);
16234
16235   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
16236   widget->window = gdk_window_new (widget->parent->window,
16237                                    &amp;attributes,
16238                                    attributes_mask);
16239
16240   widget->style = gtk_style_attach (widget->style, widget->window);
16241
16242   gdk_window_set_user_data (widget->window, widget);
16243
16244   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
16245 }
16246
16247 static void 
16248 gtk_dial_size_request (GtkWidget      *widget,
16249                        GtkRequisition *requisition)
16250 {
16251   requisition->width = DIAL_DEFAULT_SIZE;
16252   requisition->height = DIAL_DEFAULT_SIZE;
16253 }
16254
16255 static void
16256 gtk_dial_size_allocate (GtkWidget     *widget,
16257                         GtkAllocation *allocation)
16258 {
16259   GtkDial *dial;
16260
16261   g_return_if_fail (widget != NULL);
16262   g_return_if_fail (GTK_IS_DIAL (widget));
16263   g_return_if_fail (allocation != NULL);
16264
16265   widget->allocation = *allocation;
16266   dial = GTK_DIAL (widget);
16267
16268   if (GTK_WIDGET_REALIZED (widget))
16269     {
16270
16271       gdk_window_move_resize (widget->window,
16272                               allocation->x, allocation->y,
16273                               allocation->width, allocation->height);
16274
16275     }
16276   dial->radius = MIN(allocation->width,allocation->height) * 0.45;
16277   dial->pointer_width = dial->radius / 5;
16278 }
16279
16280 static gint
16281 gtk_dial_expose (GtkWidget      *widget,
16282                  GdkEventExpose *event)
16283 {
16284   GtkDial *dial;
16285   GdkPoint points[3];
16286   gdouble s,c;
16287   gdouble theta;
16288   gint xc, yc;
16289   gint tick_length;
16290   gint i;
16291
16292   g_return_val_if_fail (widget != NULL, FALSE);
16293   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16294   g_return_val_if_fail (event != NULL, FALSE);
16295
16296   if (event->count > 0)
16297     return FALSE;
16298   
16299   dial = GTK_DIAL (widget);
16300
16301   gdk_window_clear_area (widget->window,
16302                          0, 0,
16303                          widget->allocation.width,
16304                          widget->allocation.height);
16305
16306   xc = widget->allocation.width/2;
16307   yc = widget->allocation.height/2;
16308
16309   /* Draw ticks */
16310
16311   for (i=0; i<25; i++)
16312     {
16313       theta = (i*M_PI/18. - M_PI/6.);
16314       s = sin(theta);
16315       c = cos(theta);
16316
16317       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
16318       
16319       gdk_draw_line (widget->window,
16320                      widget->style->fg_gc[widget->state],
16321                      xc + c*(dial->radius - tick_length),
16322                      yc - s*(dial->radius - tick_length),
16323                      xc + c*dial->radius,
16324                      yc - s*dial->radius);
16325     }
16326
16327   /* Draw pointer */
16328
16329   s = sin(dial->angle);
16330   c = cos(dial->angle);
16331
16332
16333   points[0].x = xc + s*dial->pointer_width/2;
16334   points[0].y = yc + c*dial->pointer_width/2;
16335   points[1].x = xc + c*dial->radius;
16336   points[1].y = yc - s*dial->radius;
16337   points[2].x = xc - s*dial->pointer_width/2;
16338   points[2].y = yc - c*dial->pointer_width/2;
16339
16340   gtk_draw_polygon (widget->style,
16341                     widget->window,
16342                     GTK_STATE_NORMAL,
16343                     GTK_SHADOW_OUT,
16344                     points, 3,
16345                     TRUE);
16346   
16347   return FALSE;
16348 }
16349
16350 static gint
16351 gtk_dial_button_press (GtkWidget      *widget,
16352                        GdkEventButton *event)
16353 {
16354   GtkDial *dial;
16355   gint dx, dy;
16356   double s, c;
16357   double d_parallel;
16358   double d_perpendicular;
16359
16360   g_return_val_if_fail (widget != NULL, FALSE);
16361   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16362   g_return_val_if_fail (event != NULL, FALSE);
16363
16364   dial = GTK_DIAL (widget);
16365
16366   /* Determine if button press was within pointer region - we 
16367      do this by computing the parallel and perpendicular distance of
16368      the point where the mouse was pressed from the line passing through
16369      the pointer */
16370   
16371   dx = event->x - widget->allocation.width / 2;
16372   dy = widget->allocation.height / 2 - event->y;
16373   
16374   s = sin(dial->angle);
16375   c = cos(dial->angle);
16376   
16377   d_parallel = s*dy + c*dx;
16378   d_perpendicular = fabs(s*dx - c*dy);
16379   
16380   if (!dial->button &amp;&amp;
16381       (d_perpendicular < dial->pointer_width/2) &amp;&amp;
16382       (d_parallel > - dial->pointer_width))
16383     {
16384       gtk_grab_add (widget);
16385
16386       dial->button = event->button;
16387
16388       gtk_dial_update_mouse (dial, event->x, event->y);
16389     }
16390
16391   return FALSE;
16392 }
16393
16394 static gint
16395 gtk_dial_button_release (GtkWidget      *widget,
16396                           GdkEventButton *event)
16397 {
16398   GtkDial *dial;
16399
16400   g_return_val_if_fail (widget != NULL, FALSE);
16401   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16402   g_return_val_if_fail (event != NULL, FALSE);
16403
16404   dial = GTK_DIAL (widget);
16405
16406   if (dial->button == event->button)
16407     {
16408       gtk_grab_remove (widget);
16409
16410       dial->button = 0;
16411
16412       if (dial->policy == GTK_UPDATE_DELAYED)
16413         gtk_timeout_remove (dial->timer);
16414       
16415       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
16416           (dial->old_value != dial->adjustment->value))
16417         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
16418                                  "value_changed");
16419     }
16420
16421   return FALSE;
16422 }
16423
16424 static gint
16425 gtk_dial_motion_notify (GtkWidget      *widget,
16426                          GdkEventMotion *event)
16427 {
16428   GtkDial *dial;
16429   GdkModifierType mods;
16430   gint x, y, mask;
16431
16432   g_return_val_if_fail (widget != NULL, FALSE);
16433   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16434   g_return_val_if_fail (event != NULL, FALSE);
16435
16436   dial = GTK_DIAL (widget);
16437
16438   if (dial->button != 0)
16439     {
16440       x = event->x;
16441       y = event->y;
16442
16443       if (event->is_hint || (event->window != widget->window))
16444         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
16445
16446       switch (dial->button)
16447         {
16448         case 1:
16449           mask = GDK_BUTTON1_MASK;
16450           break;
16451         case 2:
16452           mask = GDK_BUTTON2_MASK;
16453           break;
16454         case 3:
16455           mask = GDK_BUTTON3_MASK;
16456           break;
16457         default:
16458           mask = 0;
16459           break;
16460         }
16461
16462       if (mods &amp; mask)
16463         gtk_dial_update_mouse (dial, x,y);
16464     }
16465
16466   return FALSE;
16467 }
16468
16469 static gint
16470 gtk_dial_timer (GtkDial *dial)
16471 {
16472   g_return_val_if_fail (dial != NULL, FALSE);
16473   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
16474
16475   if (dial->policy == GTK_UPDATE_DELAYED)
16476     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
16477                              "value_changed");
16478
16479   return FALSE;
16480 }
16481
16482 static void
16483 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
16484 {
16485   gint xc, yc;
16486   gfloat old_value;
16487
16488   g_return_if_fail (dial != NULL);
16489   g_return_if_fail (GTK_IS_DIAL (dial));
16490
16491   xc = GTK_WIDGET(dial)->allocation.width / 2;
16492   yc = GTK_WIDGET(dial)->allocation.height / 2;
16493
16494   old_value = dial->adjustment->value;
16495   dial->angle = atan2(yc-y, x-xc);
16496
16497   if (dial->angle < -M_PI/2.)
16498     dial->angle += 2*M_PI;
16499
16500   if (dial->angle < -M_PI/6)
16501     dial->angle = -M_PI/6;
16502
16503   if (dial->angle > 7.*M_PI/6.)
16504     dial->angle = 7.*M_PI/6.;
16505
16506   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
16507     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
16508
16509   if (dial->adjustment->value != old_value)
16510     {
16511       if (dial->policy == GTK_UPDATE_CONTINUOUS)
16512         {
16513           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
16514                                    "value_changed");
16515         }
16516       else
16517         {
16518           gtk_widget_draw (GTK_WIDGET(dial), NULL);
16519
16520           if (dial->policy == GTK_UPDATE_DELAYED)
16521             {
16522               if (dial->timer)
16523                 gtk_timeout_remove (dial->timer);
16524
16525               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
16526                                              (GtkFunction) gtk_dial_timer,
16527                                              (gpointer) dial);
16528             }
16529         }
16530     }
16531 }
16532
16533 static void
16534 gtk_dial_update (GtkDial *dial)
16535 {
16536   gfloat new_value;
16537   
16538   g_return_if_fail (dial != NULL);
16539   g_return_if_fail (GTK_IS_DIAL (dial));
16540
16541   new_value = dial->adjustment->value;
16542   
16543   if (new_value < dial->adjustment->lower)
16544     new_value = dial->adjustment->lower;
16545
16546   if (new_value > dial->adjustment->upper)
16547     new_value = dial->adjustment->upper;
16548
16549   if (new_value != dial->adjustment->value)
16550     {
16551       dial->adjustment->value = new_value;
16552       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
16553     }
16554
16555   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 
16556                               4.*M_PI/3. /
16557     (dial->adjustment->upper - dial->adjustment->lower);
16558
16559   gtk_widget_draw (GTK_WIDGET(dial), NULL);
16560 }
16561
16562 static void
16563 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
16564                               gpointer       data)
16565 {
16566   GtkDial *dial;
16567
16568   g_return_if_fail (adjustment != NULL);
16569   g_return_if_fail (data != NULL);
16570
16571   dial = GTK_DIAL (data);
16572
16573   if ((dial->old_value != adjustment->value) ||
16574       (dial->old_lower != adjustment->lower) ||
16575       (dial->old_upper != adjustment->upper))
16576     {
16577       gtk_dial_update (dial);
16578
16579       dial->old_value = adjustment->value;
16580       dial->old_lower = adjustment->lower;
16581       dial->old_upper = adjustment->upper;
16582     }
16583 }
16584
16585 static void
16586 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
16587                                     gpointer       data)
16588 {
16589   GtkDial *dial;
16590
16591   g_return_if_fail (adjustment != NULL);
16592   g_return_if_fail (data != NULL);
16593
16594   dial = GTK_DIAL (data);
16595
16596   if (dial->old_value != adjustment->value)
16597     {
16598       gtk_dial_update (dial);
16599
16600       dial->old_value = adjustment->value;
16601     }
16602 }
16603 /* example-end */
16604 </verb></tscreen>
16605
16606 <!-- ----------------------------------------------------------------- -->
16607 <sect1> Scribble
16608 <p>
16609 <tscreen><verb>
16610 /* example-start scribble-simple scribble-simple.c */
16611
16612 /* GTK - The GIMP Toolkit
16613  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16614  *
16615  * This library is free software; you can redistribute it and/or
16616  * modify it under the terms of the GNU Library General Public
16617  * License as published by the Free Software Foundation; either
16618  * version 2 of the License, or (at your option) any later version.
16619  *
16620  * This library is distributed in the hope that it will be useful,
16621  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16622  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16623  * Library General Public License for more details.
16624  *
16625  * You should have received a copy of the GNU Library General Public
16626  * License along with this library; if not, write to the
16627  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16628  * Boston, MA 02111-1307, USA.
16629  */
16630
16631 #include <gtk/gtk.h>
16632
16633 /* Backing pixmap for drawing area */
16634 static GdkPixmap *pixmap = NULL;
16635
16636 /* Create a new backing pixmap of the appropriate size */
16637 static gint
16638 configure_event (GtkWidget *widget, GdkEventConfigure *event)
16639 {
16640   if (pixmap)
16641     gdk_pixmap_unref(pixmap);
16642
16643   pixmap = gdk_pixmap_new(widget->window,
16644                           widget->allocation.width,
16645                           widget->allocation.height,
16646                           -1);
16647   gdk_draw_rectangle (pixmap,
16648                       widget->style->white_gc,
16649                       TRUE,
16650                       0, 0,
16651                       widget->allocation.width,
16652                       widget->allocation.height);
16653
16654   return TRUE;
16655 }
16656
16657 /* Redraw the screen from the backing pixmap */
16658 static gint
16659 expose_event (GtkWidget *widget, GdkEventExpose *event)
16660 {
16661   gdk_draw_pixmap(widget->window,
16662                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
16663                   pixmap,
16664                   event->area.x, event->area.y,
16665                   event->area.x, event->area.y,
16666                   event->area.width, event->area.height);
16667
16668   return FALSE;
16669 }
16670
16671 /* Draw a rectangle on the screen */
16672 static void
16673 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
16674 {
16675   GdkRectangle update_rect;
16676
16677   update_rect.x = x - 5;
16678   update_rect.y = y - 5;
16679   update_rect.width = 10;
16680   update_rect.height = 10;
16681   gdk_draw_rectangle (pixmap,
16682                       widget->style->black_gc,
16683                       TRUE,
16684                       update_rect.x, update_rect.y,
16685                       update_rect.width, update_rect.height);
16686   gtk_widget_draw (widget, &amp;update_rect);
16687 }
16688
16689 static gint
16690 button_press_event (GtkWidget *widget, GdkEventButton *event)
16691 {
16692   if (event->button == 1 &amp;&amp; pixmap != NULL)
16693     draw_brush (widget, event->x, event->y);
16694
16695   return TRUE;
16696 }
16697
16698 static gint
16699 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
16700 {
16701   int x, y;
16702   GdkModifierType state;
16703
16704   if (event->is_hint)
16705     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
16706   else
16707     {
16708       x = event->x;
16709       y = event->y;
16710       state = event->state;
16711     }
16712     
16713   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
16714     draw_brush (widget, x, y);
16715   
16716   return TRUE;
16717 }
16718
16719 void
16720 quit ()
16721 {
16722   gtk_exit (0);
16723 }
16724
16725 int
16726 main (int argc, char *argv[])
16727 {
16728   GtkWidget *window;
16729   GtkWidget *drawing_area;
16730   GtkWidget *vbox;
16731
16732   GtkWidget *button;
16733
16734   gtk_init (&amp;argc, &amp;argv);
16735
16736   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
16737   gtk_widget_set_name (window, "Test Input");
16738
16739   vbox = gtk_vbox_new (FALSE, 0);
16740   gtk_container_add (GTK_CONTAINER (window), vbox);
16741   gtk_widget_show (vbox);
16742
16743   gtk_signal_connect (GTK_OBJECT (window), "destroy",
16744                       GTK_SIGNAL_FUNC (quit), NULL);
16745
16746   /* Create the drawing area */
16747
16748   drawing_area = gtk_drawing_area_new ();
16749   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
16750   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
16751
16752   gtk_widget_show (drawing_area);
16753
16754   /* Signals used to handle backing pixmap */
16755
16756   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
16757                       (GtkSignalFunc) expose_event, NULL);
16758   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
16759                       (GtkSignalFunc) configure_event, NULL);
16760
16761   /* Event signals */
16762
16763   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
16764                       (GtkSignalFunc) motion_notify_event, NULL);
16765   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
16766                       (GtkSignalFunc) button_press_event, NULL);
16767
16768   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
16769                          | GDK_LEAVE_NOTIFY_MASK
16770                          | GDK_BUTTON_PRESS_MASK
16771                          | GDK_POINTER_MOTION_MASK
16772                          | GDK_POINTER_MOTION_HINT_MASK);
16773
16774   /* .. And a quit button */
16775   button = gtk_button_new_with_label ("Quit");
16776   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
16777
16778   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
16779                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
16780                              GTK_OBJECT (window));
16781   gtk_widget_show (button);
16782
16783   gtk_widget_show (window);
16784
16785   gtk_main ();
16786
16787   return 0;
16788 }
16789 /* example-end */
16790 </verb></tscreen>
16791
16792 <!-- ***************************************************************** -->
16793 <sect> List Widget
16794 <!-- ***************************************************************** -->
16795 <p>
16796 NOTE: The List widget has been superseded by the CList widget. It is
16797 detailed here just for completeness.
16798
16799 The List widget is designed to act as a vertical container for
16800 widgets that should be of the type ListItem.
16801
16802 A List widget has its own window to receive events and its own
16803 background color which is usually white. As it is directly derived
16804 from a Container it can be treated as such by using the
16805 GTK_CONTAINER(List) macro, see the Container widget for more on
16806 this. One should already be familiar with the usage of a GList and
16807 its related functions g_list_*() to be able to use the List widget
16808 to it full extent.
16809
16810 There is one field inside the structure definition of the List
16811 widget that will be of greater interest to us, this is:
16812
16813 <tscreen><verb>
16814 struct _GtkList
16815 {
16816   ...
16817   GList *selection;
16818   guint selection_mode;
16819   ...
16820 }; 
16821 </verb></tscreen>
16822
16823 The selection field of a List points to a linked list of all items
16824 that are currently selected, or NULL if the selection is empty.  So to
16825 learn about the current selection we read the GTK_LIST()->selection
16826 field, but do not modify it since the internal fields are maintained
16827 by the gtk_list_*() functions.
16828
16829 The selection_mode of the List determines the selection facilities
16830 of a List and therefore the contents of the GTK_LIST()->selection
16831 field. The selection_mode may be one of the following:
16832
16833 <itemize>
16834 <item> <tt/GTK_SELECTION_SINGLE/ - The selection is either NULL
16835                         or contains a GList pointer
16836                         for a single selected item.
16837
16838 <item> <tt/GTK_SELECTION_BROWSE/ -  The selection is NULL if the list
16839                         contains no widgets or insensitive
16840                         ones only, otherwise it contains
16841                         a GList pointer for one GList
16842                         structure, and therefore exactly
16843                         one list item.
16844
16845 <item> <tt/GTK_SELECTION_MULTIPLE/ -  The selection is NULL if no list
16846                         items are selected or a GList pointer
16847                         for the first selected item. That
16848                         in turn points to a GList structure
16849                         for the second selected item and so
16850                         on.
16851
16852 <item> <tt/GTK_SELECTION_EXTENDED/ - The selection is always NULL.
16853 </itemize>
16854
16855 The default is <tt/GTK_SELECTION_MULTIPLE/.
16856
16857 <!-- ----------------------------------------------------------------- -->
16858 <sect1> Signals
16859 <p>
16860 <tscreen><verb>
16861 void selection_changed( GtkList *list );
16862 </verb></tscreen>
16863
16864 This signal will be invoked whenever the selection field of a List
16865 has changed. This happens when a child of thekList got selected or
16866 deselected.
16867
16868 <tscreen><verb>
16869 void select_child( GtkList   *list,
16870                    GtkWidget *child);
16871 </verb></tscreen>
16872
16873 This signal is invoked when a child of the List is about to get
16874 selected. This happens mainly on calls to gtk_list_select_item(),
16875 gtk_list_select_child(), button presses and sometimes indirectly
16876 triggered on some else occasions where children get added to or
16877 removed from the List.
16878
16879 <tscreen><verb>
16880 void unselect_child( GtkList   *list,
16881                      GtkWidget *child );
16882 </verb></tscreen>
16883
16884 This signal is invoked when a child of the List is about to get
16885 deselected. This happens mainly on calls to gtk_list_unselect_item(),
16886 gtk_list_unselect_child(), button presses and sometimes indirectly
16887 triggered on some else occasions where children get added to or
16888 removed from the List.
16889
16890 <!-- ----------------------------------------------------------------- -->
16891 <sect1> Functions
16892 <p>
16893 <tscreen><verb>
16894 guint gtk_list_get_type( void );
16895 </verb></tscreen>
16896
16897 Returns the "GtkList" type identifier.
16898
16899 <tscreen><verb>
16900 GtkWidget *gtk_list_new( void );
16901 </verb></tscreen>
16902
16903 Create a new List object. The new widget is returned as a pointer
16904 to a GtkWidget object. NULL is returned on failure.
16905
16906 <tscreen><verb>
16907 void gtk_list_insert_items( GtkList *list,
16908                             GList   *items,
16909                             gint     position );
16910 </verb></tscreen>
16911
16912 Insert list items into the list, starting at <tt/position/.
16913 <tt/items/ is a doubly linked list where each nodes data pointer is
16914 expected to point to a newly created ListItem. The GList nodes of
16915 <tt/items/ are taken over by the list.
16916
16917 <tscreen><verb>
16918 void gtk_list_append_items( GtkList *list,
16919                             GList   *items);
16920 </verb></tscreen>
16921
16922 Insert list items just like gtk_list_insert_items() at the end of the
16923 list. The GList nodes of <tt/items/ are taken over by the list.
16924
16925 <tscreen><verb>
16926 void gtk_list_prepend_items( GtkList *list,
16927                              GList   *items);
16928 </verb></tscreen>
16929
16930 Insert list items just like gtk_list_insert_items() at the very
16931 beginning of the list. The GList nodes of <tt/items/ are taken over by
16932 the list.
16933
16934 <tscreen><verb>
16935 void gtk_list_remove_items( GtkList *list,
16936                             GList   *items);
16937 </verb></tscreen>
16938
16939 Remove list items from the list. <tt/items/ is a doubly linked list
16940 where each nodes data pointer is expected to point to a direct child
16941 of list. It is the callers responsibility to make a call to
16942 g_list_free(items) afterwards. Also the caller has to destroy the list
16943 items himself.
16944
16945 <tscreen><verb>
16946 void gtk_list_clear_items( GtkList *list,
16947                            gint start,
16948                            gint end );
16949 </verb></tscreen>
16950
16951 Remove and destroy list items from the list. A widget is affected if
16952 its current position within the list is in the range specified by
16953 <tt/start/ and <tt/end/.
16954
16955 <tscreen><verb>
16956 void gtk_list_select_item( GtkList *list,
16957                            gint     item );
16958 </verb></tscreen>
16959
16960 Invoke the select_child signal for a list item specified through its
16961 current position within the list.
16962
16963 <tscreen><verb>
16964 void gtk_list_unselect_item( GtkList *list,
16965                              gint     item);
16966 </verb></tscreen>
16967
16968 Invoke the unselect_child signal for a list item specified through its
16969 current position within the list.
16970
16971 <tscreen><verb>
16972 void gtk_list_select_child( GtkList *list,
16973                             GtkWidget *child);
16974 </verb></tscreen>
16975
16976 Invoke the select_child signal for the specified child.
16977
16978 <tscreen><verb>
16979 void gtk_list_unselect_child( GtkList   *list,
16980                               GtkWidget *child);
16981 </verb></tscreen>
16982
16983 Invoke the unselect_child signal for the specified child.
16984
16985 <tscreen><verb>
16986 gint gtk_list_child_position( GtkList *list,
16987                               GtkWidget *child);
16988 </verb></tscreen>
16989
16990 Return the position of <tt/child/ within the list. "-1" is returned on
16991 failure.
16992
16993 <tscreen><verb>
16994 void gtk_list_set_selection_mode( GtkList         *list,
16995                                   GtkSelectionMode mode );
16996 </verb></tscreen>
16997
16998 Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
16999 GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
17000 GTK_SELECTION_EXTENDED.
17001
17002 <tscreen><verb>
17003 GtkList *GTK_LIST( gpointer obj );
17004 </verb></tscreen>
17005
17006 Cast a generic pointer to "GtkList *".
17007
17008 <tscreen><verb>
17009 GtkListClass *GTK_LIST_CLASS( gpointer class);
17010 </verb></tscreen>
17011
17012 Cast a generic pointer to "GtkListClass *". 
17013
17014 <tscreen><verb>
17015 gint GTK_IS_LIST( gpointer obj);
17016 </verb></tscreen>
17017
17018 Determine if a generic pointer refers to a "GtkList" object.
17019
17020 <!-- ----------------------------------------------------------------- -->
17021 <sect1> Example
17022 <p>
17023 Following is an example program that will print out the changes of the
17024 selection of a List, and lets you "arrest" list items into a prison
17025 by selecting them with the rightmost mouse button.
17026
17027 <tscreen><verb>
17028 /* example-start list list.c */
17029
17030 /* Include the GTK header files
17031  * Include stdio.h, we need that for the printf() function
17032  */
17033 #include        <gtk/gtk.h>
17034 #include        <stdio.h>
17035
17036 /* This is our data identification string to store
17037  * data in list items
17038  */
17039 const gchar *list_item_data_key="list_item_data";
17040
17041
17042 /* prototypes for signal handler that we are going to connect
17043  * to the List widget
17044  */
17045 static void  sigh_print_selection( GtkWidget *gtklist,
17046                                    gpointer   func_data);
17047
17048 static void  sigh_button_event( GtkWidget      *gtklist,
17049                                 GdkEventButton *event,
17050                                 GtkWidget      *frame );
17051
17052
17053 /* Main function to set up the user interface */
17054
17055 gint main (int    argc,
17056            gchar *argv[])
17057 {                                  
17058     GtkWidget *separator;
17059     GtkWidget *window;
17060     GtkWidget *vbox;
17061     GtkWidget *scrolled_window;
17062     GtkWidget *frame;
17063     GtkWidget *gtklist;
17064     GtkWidget *button;
17065     GtkWidget *list_item;
17066     GList *dlist;
17067     guint i;
17068     gchar buffer[64];
17069     
17070     
17071     /* Initialize GTK (and subsequently GDK) */
17072
17073     gtk_init(&amp;argc, &amp;argv);
17074     
17075     
17076     /* Create a window to put all the widgets in
17077      * connect gtk_main_quit() to the "destroy" event of
17078      * the window to handle window manager close-window-events
17079      */
17080     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
17081     gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
17082     gtk_signal_connect(GTK_OBJECT(window),
17083                        "destroy",
17084                        GTK_SIGNAL_FUNC(gtk_main_quit),
17085                        NULL);
17086     
17087     
17088     /* Inside the window we need a box to arrange the widgets
17089      * vertically */
17090     vbox=gtk_vbox_new(FALSE, 5);
17091     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
17092     gtk_container_add(GTK_CONTAINER(window), vbox);
17093     gtk_widget_show(vbox);
17094     
17095     /* This is the scrolled window to put the List widget inside */
17096     scrolled_window=gtk_scrolled_window_new(NULL, NULL);
17097     gtk_widget_set_usize(scrolled_window, 250, 150);
17098     gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
17099     gtk_widget_show(scrolled_window);
17100     
17101     /* Create thekList widget.
17102      * Connect the sigh_print_selection() signal handler
17103      * function to the "selection_changed" signal of the List
17104      * to print out the selected items each time the selection
17105      * has changed */
17106     gtklist=gtk_list_new();
17107     gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
17108                                            gtklist);
17109     gtk_widget_show(gtklist);
17110     gtk_signal_connect(GTK_OBJECT(gtklist),
17111                        "selection_changed",
17112                        GTK_SIGNAL_FUNC(sigh_print_selection),
17113                        NULL);
17114     
17115     /* We create a "Prison" to put a list item in ;) */
17116     frame=gtk_frame_new("Prison");
17117     gtk_widget_set_usize(frame, 200, 50);
17118     gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
17119     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
17120     gtk_container_add(GTK_CONTAINER(vbox), frame);
17121     gtk_widget_show(frame);
17122     
17123     /* Connect the sigh_button_event() signal handler to the List
17124      * which will handle the "arresting" of list items
17125      */
17126     gtk_signal_connect(GTK_OBJECT(gtklist),
17127                        "button_release_event",
17128                        GTK_SIGNAL_FUNC(sigh_button_event),
17129                        frame);
17130     
17131     /* Create a separator */
17132     separator=gtk_hseparator_new();
17133     gtk_container_add(GTK_CONTAINER(vbox), separator);
17134     gtk_widget_show(separator);
17135     
17136     /* Finally create a button and connect its "clicked" signal
17137      * to the destruction of the window */
17138     button=gtk_button_new_with_label("Close");
17139     gtk_container_add(GTK_CONTAINER(vbox), button);
17140     gtk_widget_show(button);
17141     gtk_signal_connect_object(GTK_OBJECT(button),
17142                               "clicked",
17143                               GTK_SIGNAL_FUNC(gtk_widget_destroy),
17144                               GTK_OBJECT(window));
17145     
17146     
17147     /* Now we create 5 list items, each having its own
17148      * label and add them to the List using gtk_container_add()
17149      * Also we query the text string from the label and
17150      * associate it with the list_item_data_key for each list item
17151      */
17152     for (i=0; i<5; i++) {
17153         GtkWidget       *label;
17154         gchar           *string;
17155         
17156         sprintf(buffer, "ListItemContainer with Label #%d", i);
17157         label=gtk_label_new(buffer);
17158         list_item=gtk_list_item_new();
17159         gtk_container_add(GTK_CONTAINER(list_item), label);
17160         gtk_widget_show(label);
17161         gtk_container_add(GTK_CONTAINER(gtklist), list_item);
17162         gtk_widget_show(list_item);
17163         gtk_label_get(GTK_LABEL(label), &amp;string);
17164         gtk_object_set_data(GTK_OBJECT(list_item),
17165                             list_item_data_key,
17166                             string);
17167     }
17168     /* Here, we are creating another 5 labels, this time
17169      * we use gtk_list_item_new_with_label() for the creation
17170      * we can't query the text string from the label because
17171      * we don't have the labels pointer and therefore
17172      * we just associate the list_item_data_key of each
17173      * list item with the same text string.
17174      * For adding of the list items we put them all into a doubly
17175      * linked list (GList), and then add them by a single call to
17176      * gtk_list_append_items().
17177      * Because we use g_list_prepend() to put the items into the
17178      * doubly linked list, their order will be descending (instead
17179      * of ascending when using g_list_append())
17180      */
17181     dlist=NULL;
17182     for (; i<10; i++) {
17183         sprintf(buffer, "List Item with Label %d", i);
17184         list_item=gtk_list_item_new_with_label(buffer);
17185         dlist=g_list_prepend(dlist, list_item);
17186         gtk_widget_show(list_item);
17187         gtk_object_set_data(GTK_OBJECT(list_item),
17188                             list_item_data_key,
17189                             "ListItem with integrated Label");
17190     }
17191     gtk_list_append_items(GTK_LIST(gtklist), dlist);
17192     
17193     /* Finally we want to see the window, don't we? ;) */
17194     gtk_widget_show(window);
17195     
17196     /* Fire up the main event loop of gtk */
17197     gtk_main();
17198     
17199     /* We get here after gtk_main_quit() has been called which
17200      * happens if the main window gets destroyed
17201      */
17202     return(0);
17203 }
17204
17205 /* This is the signal handler that got connected to button
17206  * press/release events of the List
17207  */
17208 void sigh_button_event( GtkWidget      *gtklist,
17209                         GdkEventButton *event,
17210                         GtkWidget      *frame )
17211 {
17212     /* We only do something if the third (rightmost mouse button
17213      * was released
17214      */
17215     if (event->type==GDK_BUTTON_RELEASE &amp;&amp;
17216         event->button==3) {
17217         GList           *dlist, *free_list;
17218         GtkWidget       *new_prisoner;
17219         
17220         /* Fetch the currently selected list item which
17221          * will be our next prisoner ;)
17222          */
17223         dlist=GTK_LIST(gtklist)->selection;
17224         if (dlist)
17225                 new_prisoner=GTK_WIDGET(dlist->data);
17226         else
17227                 new_prisoner=NULL;
17228         
17229         /* Look for already imprisoned list items, we
17230          * will put them back into the list.
17231          * Remember to free the doubly linked list that
17232          * gtk_container_children() returns
17233          */
17234         dlist=gtk_container_children(GTK_CONTAINER(frame));
17235         free_list=dlist;
17236         while (dlist) {
17237             GtkWidget       *list_item;
17238             
17239             list_item=dlist->data;
17240             
17241             gtk_widget_reparent(list_item, gtklist);
17242             
17243             dlist=dlist->next;
17244         }
17245         g_list_free(free_list);
17246         
17247         /* If we have a new prisoner, remove him from the
17248          * List and put him into the frame "Prison".
17249          * We need to unselect the item first.
17250          */
17251         if (new_prisoner) {
17252             GList   static_dlist;
17253             
17254             static_dlist.data=new_prisoner;
17255             static_dlist.next=NULL;
17256             static_dlist.prev=NULL;
17257             
17258             gtk_list_unselect_child(GTK_LIST(gtklist),
17259                                     new_prisoner);
17260             gtk_widget_reparent(new_prisoner, frame);
17261         }
17262     }
17263 }
17264
17265 /* This is the signal handler that gets called if List
17266  * emits the "selection_changed" signal
17267  */
17268 void sigh_print_selection( GtkWidget *gtklist,
17269                            gpointer   func_data)
17270 {
17271     GList   *dlist;
17272     
17273     /* Fetch the doubly linked list of selected items
17274      * of the List, remember to treat this as read-only!
17275      */
17276     dlist=GTK_LIST(gtklist)->selection;
17277     
17278     /* If there are no selected items there is nothing more
17279      * to do than just telling the user so
17280      */
17281     if (!dlist) {
17282         g_print("Selection cleared\n");
17283         return;
17284     }
17285     /* Ok, we got a selection and so we print it
17286      */
17287     g_print("The selection is a ");
17288     
17289     /* Get the list item from the doubly linked list
17290      * and then query the data associated with list_item_data_key.
17291      * We then just print it */
17292     while (dlist) {
17293         GtkObject       *list_item;
17294         gchar           *item_data_string;
17295         
17296         list_item=GTK_OBJECT(dlist->data);
17297         item_data_string=gtk_object_get_data(list_item,
17298                                              list_item_data_key);
17299         g_print("%s ", item_data_string);
17300         
17301         dlist=dlist->next;
17302     }
17303     g_print("\n");
17304 }
17305 /* example-end */
17306 </verb></tscreen>
17307
17308 <!-- ----------------------------------------------------------------- -->
17309 <sect1> List Item Widget
17310 <p>
17311 The ListItem widget is designed to act as a container holding up to
17312 one child, providing functions for selection/deselection just like the
17313 List widget requires them for its children.
17314
17315 A ListItem has its own window to receive events and has its own
17316 background color which is usually white.
17317
17318 As it is directly derived from an Item it can be treated as such by
17319 using the GTK_ITEM(ListItem) macro, see the Item widget for more on
17320 this. Usually a ListItem just holds a label to identify, e.g., a
17321 filename within a List -- therefore the convenience function
17322 gtk_list_item_new_with_label() is provided. The same effect can be
17323 achieved by creating a Label on its own, setting its alignment to
17324 xalign=0 and yalign=0.5 with a subsequent container addition to the
17325 ListItem.
17326
17327 As one is not forced to add a GtkLabel to a GtkListItem, you could
17328 also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
17329
17330 <!-- ----------------------------------------------------------------- -->
17331 <sect1> Signals
17332 <p>
17333 AkListItem does not create new signals on its own, but inherits
17334 the signals of a Item.
17335
17336 <!-- ----------------------------------------------------------------- -->
17337 <sect1> Functions
17338 <p>
17339 <tscreen><verb>
17340 guint gtk_list_item_get_type( void );
17341 </verb></tscreen>
17342
17343 Returns the "GtkListItem" type identifier.
17344
17345 <tscreen><verb>
17346 GtkWidget *gtk_list_item_new( void );
17347 </verb></tscreen>
17348
17349 Create a new ListItem object. The new widget is returned as a
17350 pointer to a GtkWidget object. NULL is returned on failure.
17351
17352 <tscreen><verb>
17353 GtkWidget *gtk_list_item_new_with_label( gchar *label );
17354 </verb></tscreen>
17355
17356 Create a new ListItem object, having a single GtkLabel as the sole
17357 child. The new widget is returned as a pointer to a GtkWidget
17358 object. NULL is returned on failure.
17359
17360 <tscreen><verb>
17361 void gtk_list_item_select( GtkListItem *list_item );
17362 </verb></tscreen>
17363
17364 This function is basically a wrapper around a call to gtk_item_select
17365 (GTK_ITEM (list_item)) which will emit the select signal.  *Note
17366 GtkItem::, for more info.
17367
17368 <tscreen><verb>
17369 void gtk_list_item_deselect( GtkListItem *list_item );
17370 </verb></tscreen>
17371
17372 This function is basically a wrapper around a call to
17373 gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
17374 signal.  *Note GtkItem::, for more info.
17375
17376 <tscreen><verb>
17377 GtkListItem *GTK_LIST_ITEM( gpointer obj );
17378 </verb></tscreen>
17379
17380 Cast a generic pointer to "GtkListItem *".
17381
17382 <tscreen><verb>
17383 GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
17384 </verb></tscreen>
17385
17386 Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
17387 for more info.
17388
17389 <tscreen><verb>
17390 gint GTK_IS_LIST_ITEM( gpointer obj );
17391 </verb></tscreen>
17392
17393 Determine if a generic pointer refers to a `GtkListItem' object.
17394 *Note Standard Macros::, for more info.
17395  
17396 <!-- ----------------------------------------------------------------- -->
17397 <sect1> Example
17398 <p>
17399 Please see the List example on this, which covers the usage of a
17400 ListItem as well.
17401
17402
17403 </article>