]> Pileus Git - ~andy/gtk/blob - docs/tutorial/gtk_tut.sgml
use a scrolled window in the clist example. Minor tutorial fixes.
[~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 10th, 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 = TRUE, 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 *scrolled_window, *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 a scrolled window to pack the CList widget into */
8412     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
8413     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
8414                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
8415
8416     gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);
8417     gtk_widget_show (scrolled_window);
8418
8419     /* Create the CList. For this example we use 2 columns */
8420     clist = gtk_clist_new_with_titles( 2, titles);
8421
8422     /* When a selection is made, we want to know about it. The callback
8423      * used is selection_made, and its code can be found further down */
8424     gtk_signal_connect(GTK_OBJECT(clist), "select_row",
8425                        GTK_SIGNAL_FUNC(selection_made),
8426                        NULL);
8427
8428     /* It isn't necessary to shadow the border, but it looks nice :) */
8429     gtk_clist_set_shadow_type (GTK_CLIST(clist), GTK_SHADOW_OUT);
8430
8431     /* What however is important, is that we set the column widths as
8432      * they will never be right otherwise. Note that the columns are
8433      * numbered from 0 and up (to 1 in this case).
8434      */
8435     gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
8436
8437     /* Add the CList widget to the vertical box and show it. */
8438     gtk_container_add(GTK_CONTAINER(scrolled_window), clist);
8439     gtk_widget_show(clist);
8440
8441     /* Create the buttons and add them to the window. See the button
8442      * tutorial for more examples and comments on this.
8443      */
8444     hbox = gtk_hbox_new(FALSE, 0);
8445     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
8446     gtk_widget_show(hbox);
8447
8448     button_add = gtk_button_new_with_label("Add List");
8449     button_clear = gtk_button_new_with_label("Clear List");
8450     button_hide_show = gtk_button_new_with_label("Hide/Show titles");
8451
8452     gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
8453     gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
8454     gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
8455
8456     /* Connect our callbacks to the three buttons */
8457     gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
8458                               GTK_SIGNAL_FUNC(button_add_clicked),
8459                               (gpointer) clist);
8460     gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
8461                               GTK_SIGNAL_FUNC(button_clear_clicked),
8462                               (gpointer) clist);
8463     gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
8464                               GTK_SIGNAL_FUNC(button_hide_show_clicked),
8465                               (gpointer) clist);
8466
8467     gtk_widget_show(button_add);
8468     gtk_widget_show(button_clear);
8469     gtk_widget_show(button_hide_show);
8470
8471     /* The interface is completely set up so we show the window and
8472      * enter the gtk_main loop.
8473      */
8474     gtk_widget_show(window);
8475     gtk_main();
8476     
8477     return(0);
8478 }
8479 /* example-end */
8480 </verb></tscreen>
8481                     
8482 <!-- ***************************************************************** -->
8483 <sect> Tree Widget <label id="sec_Tree_Widgets">
8484 <!-- ***************************************************************** -->
8485 <p>
8486 The purpose of tree widgets is to display hierarchically-organized
8487 data. The Tree widget itself is a vertical container for widgets of
8488 type TreeItem. Tree itself is not terribly different from
8489 CList - both are derived directly from Container, and the
8490 Container methods work in the same way on Tree widgets as on
8491 CList widgets. The difference is that Tree widgets can be nested
8492 within other Tree widgets. We'll see how to do this shortly.
8493
8494 The Tree widget has its own window, and defaults to a white
8495 background, as does CList. Also, most of the Tree methods work in
8496 the same way as the corresponding CList ones. However, Tree is
8497 not derived from CList, so you cannot use them interchangeably.
8498
8499
8500 <sect1> Creating a Tree
8501 <p>
8502 A Tree is created in the usual way, using:
8503
8504 <tscreen><verb>
8505 GtkWidget *gtk_tree_new( void );
8506 </verb></tscreen>
8507
8508 Like the CList widget, a Tree will simply keep growing as more
8509 items are added to it, as well as when subtrees are expanded.  For
8510 this reason, they are almost always packed into a
8511 ScrolledWindow. You might want to use gtk_widget_set_usize() on the
8512 scrolled window to ensure that it is big enough to see the tree's
8513 items, as the default size for ScrolledWindow is quite small.
8514
8515 Now that you have a tree, you'll probably want to add some items to
8516 it.  <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
8517 explains the gory details of TreeItem. For now, it'll suffice to
8518 create one, using:
8519
8520 <tscreen><verb>
8521 GtkWidget *gtk_tree_item_new_with_label( gchar *label );
8522 </verb></tscreen>
8523
8524 You can then add it to the tree using one of the following (see
8525 <ref id="sec_Tree_Functions" name="Functions and Macros">
8526 below for more options):
8527
8528 <tscreen><verb>
8529 void gtk_tree_append( GtkTree    *tree,
8530                        GtkWidget *tree_item );
8531
8532 void gtk_tree_prepend( GtkTree   *tree,
8533                        GtkWidget *tree_item );
8534 </verb></tscreen>
8535
8536 Note that you must add items to a Tree one at a time - there is no
8537 equivalent to gtk_list_*_items().
8538
8539 <!-- ----------------------------------------------------------------- -->
8540 <sect1> Adding a Subtree
8541 <p>
8542 A subtree is created like any other Tree widget. A subtree is added
8543 to another tree beneath a tree item, using:
8544
8545 <tscreen><verb>
8546 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
8547                                 GtkWidget   *subtree );
8548 </verb></tscreen>
8549
8550 You do not need to call gtk_widget_show() on a subtree before or after
8551 adding it to a TreeItem. However, you <em>must</em> have added the
8552 TreeItem in question to a parent tree before calling
8553 gtk_tree_item_set_subtree(). This is because, technically, the parent
8554 of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
8555 rather the GtkTree which holds that GtkTreeItem.
8556
8557 When you add a subtree to a TreeItem, a plus or minus sign appears
8558 beside it, which the user can click on to "expand" or "collapse" it,
8559 meaning, to show or hide its subtree. TreeItems are collapsed by
8560 default. Note that when you collapse a TreeItem, any selected
8561 items in its subtree remain selected, which may not be what the user
8562 expects.
8563
8564 <!-- ----------------------------------------------------------------- -->
8565 <sect1> Handling the Selection List
8566 <p>
8567 As with CList, the Tree type has a <tt>selection</tt> field, and
8568 it is possible to control the behaviour of the tree (somewhat) by
8569 setting the selection type using:
8570
8571 <tscreen><verb>
8572 void gtk_tree_set_selection_mode( GtkTree          *tree,
8573                                   GtkSelectionMode  mode );
8574 </verb></tscreen>
8575
8576 The semantics associated with the various selection modes are
8577 described in the section on the CList widget. As with the CList
8578 widget, the "select_child", "unselect_child" (not really - see <ref
8579 id="sec_Tree_Signals" name="Signals"> below for an explanation),
8580 and "selection_changed" signals are emitted when list items are
8581 selected or unselected. However, in order to take advantage of these
8582 signals, you need to know <em>which</em> Tree widget they will be
8583 emitted by, and where to find the list of selected items.
8584
8585 This is a source of potential confusion. The best way to explain this
8586 is that though all Tree widgets are created equal, some are more equal
8587 than others. All Tree widgets have their own X window, and can
8588 therefore receive events such as mouse clicks (if their TreeItems or
8589 their children don't catch them first!). However, to make
8590 <tt/GTK_SELECTION_SINGLE/ and <tt/GTK_SELECTION_BROWSE/ selection
8591 types behave in a sane manner, the list of selected items is specific
8592 to the topmost Tree widget in a hierarchy, known as the "root tree".
8593
8594 Thus, accessing the <tt>selection</tt> field directly in an arbitrary
8595 Tree widget is not a good idea unless you <em>know</em> it's the root
8596 tree. Instead, use the <tt/GTK_TREE_SELECTION (Tree)/ macro, which
8597 gives the root tree's selection list as a GList pointer. Of course,
8598 this list can include items that are not in the subtree in question if
8599 the selection type is <tt/GTK_SELECTION_MULTIPLE/.
8600
8601 Finally, the "select_child" (and "unselect_child", in theory) signals
8602 are emitted by all trees, but the "selection_changed" signal is only
8603 emitted by the root tree. Consequently, if you want to handle the
8604 "select_child" signal for a tree and all its subtrees, you will have
8605 to call gtk_signal_connect() for every subtree.
8606
8607 <sect1> Tree Widget Internals
8608 <p>
8609 The Tree's struct definition looks like this:
8610
8611 <tscreen><verb>
8612 struct _GtkTree
8613 {
8614   GtkContainer container;
8615
8616   GList *children;
8617   
8618   GtkTree* root_tree; /* owner of selection list */
8619   GtkWidget* tree_owner;
8620   GList *selection;
8621   guint level;
8622   guint indent_value;
8623   guint current_indent;
8624   guint selection_mode : 2;
8625   guint view_mode : 1;
8626   guint view_line : 1;
8627 };
8628 </verb></tscreen>
8629
8630 The perils associated with accessing the <tt>selection</tt> field
8631 directly have already been mentioned. The other important fields of
8632 the struct can also be accessed with handy macros or class functions.
8633 <tt/GTK_IS_ROOT_TREE (Tree)/ returns a boolean value which
8634 indicates whether a tree is the root tree in a Tree hierarchy, while
8635 <tt/GTK_TREE_ROOT_TREE (Tree)/ returns the root tree, an object of
8636 type GtkTree (so, remember to cast it using <tt/GTK_WIDGET (Tree)/ if
8637 you want to use one of the gtk_widget_*() functions on it).
8638
8639 Instead of directly accessing the children field of a Tree widget,
8640 it's probably best to cast it using >tt/GTK_CONTAINER (Tree)/, and
8641 pass it to the gtk_container_children() function. This creates a
8642 duplicate of the original list, so it's advisable to free it up using
8643 g_list_free() after you're done with it, or to iterate on it
8644 destructively, like this:
8645
8646 <tscreen><verb>
8647     children = gtk_container_children (GTK_CONTAINER (tree));
8648     while (children) {
8649       do_something_nice (GTK_TREE_ITEM (children->data));
8650       children = g_list_remove_link (children, children);
8651 }
8652 </verb></tscreen>
8653
8654 The <tt>tree_owner</tt> field is defined only in subtrees, where it
8655 points to the TreeItem widget which holds the tree in question.
8656 The <tt>level</tt> field indicates how deeply nested a particular tree
8657 is; root trees have level 0, and each successive level of subtrees has
8658 a level one greater than the parent level. This field is set only
8659 after a Tree widget is actually mapped (i.e. drawn on the screen).
8660
8661 <sect2> Signals<label id="sec_Tree_Signals">
8662 <p>
8663 <tscreen><verb>
8664 void selection_changed( GtkTree *tree );
8665 </verb></tscreen>
8666
8667 This signal will be emitted whenever the <tt>selection</tt> field of a
8668 Tree has changed. This happens when a child of the Tree is
8669 selected or deselected.
8670
8671 <tscreen><verb>
8672 void select_child( GtkTree   *tree,
8673                    GtkWidget *child );
8674 </verb></tscreen>
8675
8676 This signal is emitted when a child of the Tree is about to get
8677 selected. This happens on calls to gtk_tree_select_item(),
8678 gtk_tree_select_child(), on <em>all</em> button presses and calls to
8679 gtk_tree_item_toggle() and gtk_item_toggle().  It may sometimes be
8680 indirectly triggered on other occasions where children get added to or
8681 removed from the Tree.
8682
8683 <tscreen><verb>
8684 void unselect_child (GtkTree   *tree,
8685                      GtkWidget *child);
8686 </verb></tscreen>
8687
8688 This signal is emitted when a child of the Tree is about to get
8689 deselected. As of GTK 1.0.4, this seems to only occur on calls to
8690 gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
8691 other occasions, but <em>not</em> when a button press deselects a
8692 child, nor on emission of the "toggle" signal by gtk_item_toggle().
8693
8694 <sect2> Functions and Macros<label id="sec_Tree_Functions">
8695 <p>
8696 <tscreen><verb>
8697 guint gtk_tree_get_type( void );
8698 </verb></tscreen>
8699
8700 Returns the "GtkTree" type identifier.
8701
8702 <tscreen><verb>
8703 GtkWidget* gtk_tree_new( void );
8704 </verb></tscreen>
8705
8706 Create a new Tree object. The new widget is returned as a pointer to a
8707 GtkWidget object. NULL is returned on failure.
8708
8709 <tscreen><verb>
8710 void gtk_tree_append( GtkTree   *tree,
8711                       GtkWidget *tree_item );
8712 </verb></tscreen>
8713
8714 Append a tree item to a Tree.
8715
8716 <tscreen><verb>
8717 void gtk_tree_prepend( GtkTree   *tree,
8718                        GtkWidget *tree_item );
8719 </verb></tscreen>
8720
8721 Prepend a tree item to a Tree.
8722
8723 <tscreen><verb>
8724 void gtk_tree_insert( GtkTree   *tree,
8725                       GtkWidget *tree_item,
8726                       gint       position );
8727 </verb></tscreen>
8728
8729 Insert a tree item into a Tree at the position in the list
8730 specified by <tt>position.</tt>
8731
8732 <tscreen><verb>
8733 void gtk_tree_remove_items( GtkTree *tree,
8734                             GList   *items );
8735 </verb></tscreen>
8736
8737 Remove a list of items (in the form of a GList *) from a Tree.
8738 Note that removing an item from a tree dereferences (and thus usually)
8739 destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
8740 subtrees in that subtree. If you want to remove only one item, you
8741 can use gtk_container_remove().
8742
8743 <tscreen><verb>
8744 void gtk_tree_clear_items( GtkTree *tree,
8745                            gint     start,
8746                            gint     end );
8747 </verb></tscreen>
8748
8749 Remove the items from position <tt>start</tt> to position <tt>end</tt>
8750 from a Tree. The same warning about dereferencing applies here, as
8751 gtk_tree_clear_items() simply constructs a list and passes it to
8752 gtk_tree_remove_items().
8753
8754 <tscreen><verb>
8755 void gtk_tree_select_item( GtkTree *tree,
8756                            gint     item );
8757 </verb></tscreen>
8758
8759 Emits the "select_item" signal for the child at position
8760 <tt>item</tt>, thus selecting the child (unless you unselect it in a
8761 signal handler).
8762
8763 <tscreen><verb>
8764 void gtk_tree_unselect_item( GtkTree *tree,
8765                              gint     item );
8766 </verb></tscreen>
8767
8768 Emits the "unselect_item" signal for the child at position
8769 <tt>item</tt>, thus unselecting the child.
8770
8771 <tscreen><verb>
8772 void gtk_tree_select_child( GtkTree   *tree,
8773                             GtkWidget *tree_item );
8774 </verb></tscreen>
8775
8776 Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
8777 selecting it.
8778
8779 <tscreen><verb>
8780 void gtk_tree_unselect_child( GtkTree   *tree,
8781                               GtkWidget *tree_item );
8782 </verb></tscreen>
8783
8784 Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
8785 thus unselecting it.
8786
8787 <tscreen><verb>
8788 gint gtk_tree_child_position( GtkTree   *tree,
8789                               GtkWidget *child );
8790 </verb></tscreen>
8791
8792 Returns the position in the tree of <tt>child</tt>, unless
8793 <tt>child</tt> is not in the tree, in which case it returns -1.
8794
8795 <tscreen><verb>
8796 void gtk_tree_set_selection_mode( GtkTree          *tree,
8797                                   GtkSelectionMode  mode );
8798 </verb></tscreen>
8799
8800 Sets the selection mode, which can be one of <tt/GTK_SELECTION_SINGLE/ (the
8801 default), <tt/GTK_SELECTION_BROWSE/, <tt/GTK_SELECTION_MULTIPLE/, or
8802 <tt/GTK_SELECTION_EXTENDED/. This is only defined for root trees, which
8803 makes sense, since the root tree "owns" the selection. Setting it for
8804 subtrees has no effect at all; the value is simply ignored.
8805
8806 <tscreen><verb>
8807 void gtk_tree_set_view_mode( GtkTree         *tree,
8808                              GtkTreeViewMode  mode ); 
8809 </verb></tscreen>
8810
8811 Sets the "view mode", which can be either <tt/GTK_TREE_VIEW_LINE/ (the
8812 default) or <tt/GTK_TREE_VIEW_ITEM/.  The view mode propagates from a
8813 tree to its subtrees, and can't be set exclusively to a subtree (this
8814 is not exactly true - see the example code comments).
8815
8816 The term "view mode" is rather ambiguous - basically, it controls the
8817 way the highlight is drawn when one of a tree's children is selected.
8818 If it's <tt/GTK_TREE_VIEW_LINE/, the entire TreeItem widget is
8819 highlighted, while for <tt/GTK_TREE_VIEW_ITEM/, only the child widget
8820 (i.e., usually the label) is highlighted.
8821
8822 <tscreen><verb>
8823 void gtk_tree_set_view_lines( GtkTree *tree,
8824                               guint    flag );
8825 </verb></tscreen>
8826
8827 Controls whether connecting lines between tree items are drawn.
8828 <tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
8829 which case they aren't.
8830
8831 <tscreen><verb>
8832 GtkTree *GTK_TREE (gpointer obj);
8833 </verb></tscreen>
8834
8835 Cast a generic pointer to "GtkTree *".
8836
8837 <tscreen><verb>
8838 GtkTreeClass *GTK_TREE_CLASS (gpointer class);
8839 </verb></tscreen>
8840
8841 Cast a generic pointer to "GtkTreeClass *".
8842
8843 <tscreen><verb>
8844 gint GTK_IS_TREE (gpointer obj);
8845 </verb></tscreen>
8846
8847 Determine if a generic pointer refers to a "GtkTree" object.
8848
8849 <tscreen><verb>
8850 gint GTK_IS_ROOT_TREE (gpointer obj)
8851 </verb></tscreen>
8852
8853 Determine if a generic pointer refers to a "GtkTree" object
8854 <em>and</em> is a root tree. Though this will accept any pointer, the
8855 results of passing it a pointer that does not refer to a Tree are
8856 undefined and possibly harmful.
8857
8858 <tscreen><verb>
8859 GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
8860 </verb></tscreen>
8861
8862 Return the root tree of a pointer to a "GtkTree" object. The above
8863 warning applies.
8864
8865 <tscreen><verb>
8866 GList *GTK_TREE_SELECTION( gpointer obj)
8867 </verb></tscreen>
8868
8869 Return the selection list of the root tree of a "GtkTree" object. The
8870 above warning applies here, too.
8871
8872 <sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
8873 <p>
8874 The TreeItem widget, like CListItem, is derived from Item,
8875 which in turn is derived from Bin.  Therefore, the item itself is a
8876 generic container holding exactly one child widget, which can be of
8877 any type. The TreeItem widget has a number of extra fields, but
8878 the only one we need be concerned with is the <tt>subtree</tt> field.
8879
8880 The definition for the TreeItem struct looks like this:
8881
8882 <tscreen><verb>
8883 struct _GtkTreeItem
8884 {
8885   GtkItem item;
8886
8887   GtkWidget *subtree;
8888   GtkWidget *pixmaps_box;
8889   GtkWidget *plus_pix_widget, *minus_pix_widget;
8890
8891   GList *pixmaps;               /* pixmap node for this items color depth */
8892
8893   guint expanded : 1;
8894 };
8895 </verb></tscreen>
8896
8897 The <tt>pixmaps_box</tt> field is an EventBox which catches clicks on
8898 the plus/minus symbol which controls expansion and collapsing. The
8899 <tt>pixmaps</tt> field points to an internal data structure. Since
8900 you can always obtain the subtree of a TreeItem in a (relatively)
8901 type-safe manner with the <tt/GTK_TREE_ITEM_SUBTREE (Item)/ macro,
8902 it's probably advisable never to touch the insides of a TreeItem
8903 unless you <em>really</em> know what you're doing.
8904
8905 Since it is directly derived from an Item it can be treated as such by
8906 using the <tt/GTK_ITEM (TreeItem)/ macro. A TreeItem usually holds a
8907 label, so the convenience function gtk_list_item_new_with_label() is
8908 provided. The same effect can be achieved using code like the
8909 following, which is actually copied verbatim from
8910 gtk_tree_item_new_with_label():
8911
8912 <tscreen><verb>
8913 tree_item = gtk_tree_item_new ();
8914 label_widget = gtk_label_new (label);
8915 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
8916
8917 gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
8918 gtk_widget_show (label_widget);
8919 </verb></tscreen>
8920
8921 As one is not forced to add a Label to a TreeItem, you could
8922 also add an HBox or an Arrow, or even a Notebook (though your
8923 app will likely be quite unpopular in this case) to the TreeItem.
8924
8925 If you remove all the items from a subtree, it will be destroyed and
8926 unparented, unless you reference it beforehand, and the TreeItem
8927 which owns it will be collapsed. So, if you want it to stick around,
8928 do something like the following:
8929
8930 <tscreen><verb>
8931 gtk_widget_ref (tree);
8932 owner = GTK_TREE(tree)->tree_owner;
8933 gtk_container_remove (GTK_CONTAINER(tree), item);
8934 if (tree->parent == NULL){
8935   gtk_tree_item_expand (GTK_TREE_ITEM(owner));
8936   gtk_tree_item_set_subtree (GTK_TREE_ITEM(owner), tree);
8937 }
8938 else
8939   gtk_widget_unref (tree);
8940 </verb></tscreen>
8941
8942 Finally, drag-n-drop <em>does</em> work with TreeItems. You just
8943 have to make sure that the TreeItem you want to make into a drag
8944 item or a drop site has not only been added to a Tree, but that
8945 each successive parent widget has a parent itself, all the way back to
8946 a toplevel or dialog window, when you call gtk_widget_dnd_drag_set()
8947 or gtk_widget_dnd_drop_set().  Otherwise, strange things will happen.
8948
8949 <sect2> Signals
8950 <p>
8951 TreeItem inherits the "select", "deselect", and "toggle" signals
8952 from Item. In addition, it adds two signals of its own, "expand"
8953 and "collapse".
8954
8955 <tscreen><verb>
8956 void select( GtkItem *tree_item );
8957 </verb></tscreen>
8958
8959 This signal is emitted when an item is about to be selected, either
8960 after it has been clicked on by the user, or when the program calls
8961 gtk_tree_item_select(), gtk_item_select(), or gtk_tree_select_child().
8962
8963 <tscreen><verb>
8964 void deselect( GtkItem *tree_item );
8965 </verb></tscreen>
8966
8967 This signal is emitted when an item is about to be unselected, either
8968 after it has been clicked on by the user, or when the program calls
8969 gtk_tree_item_deselect() or gtk_item_deselect(). In the case of
8970 TreeItems, it is also emitted by gtk_tree_unselect_child(), and
8971 sometimes gtk_tree_select_child().
8972
8973 <tscreen><verb>
8974 void toggle( GtkItem *tree_item );
8975 </verb></tscreen>
8976
8977 This signal is emitted when the program calls gtk_item_toggle().  The
8978 effect it has when emitted on a TreeItem is to call
8979 gtk_tree_select_child() (and never gtk_tree_unselect_child()) on the
8980 item's parent tree, if the item has a parent tree.  If it doesn't,
8981 then the highlight is reversed on the item.
8982
8983 <tscreen><verb>
8984 void expand( GtkTreeItem *tree_item );
8985 </verb></tscreen>
8986
8987 This signal is emitted when the tree item's subtree is about to be
8988 expanded, that is, when the user clicks on the plus sign next to the
8989 item, or when the program calls gtk_tree_item_expand().
8990
8991 <tscreen><verb>
8992 void collapse( GtkTreeItem *tree_item );
8993 </verb></tscreen>
8994
8995 This signal is emitted when the tree item's subtree is about to be
8996 collapsed, that is, when the user clicks on the minus sign next to the
8997 item, or when the program calls gtk_tree_item_collapse().
8998
8999 <sect2> Functions and Macros
9000 <p>
9001 <tscreen><verb>
9002 guint gtk_tree_item_get_type( void );
9003 </verb></tscreen>
9004
9005 Returns the "GtkTreeItem" type identifier.
9006
9007 <tscreen><verb>
9008 GtkWidget* gtk_tree_item_new( void );
9009 </verb></tscreen>
9010
9011 Create a new TreeItem object. The new widget is returned as a
9012 pointer to a GtkWidget object. NULL is returned on failure.
9013
9014 <tscreen><verb>
9015 GtkWidget* gtk_tree_item_new_with_label (gchar       *label);
9016 </verb></tscreen>
9017
9018 Create a new TreeItem object, having a single GtkLabel as the sole
9019 child. The new widget is returned as a pointer to a GtkWidget
9020 object. NULL is returned on failure.
9021
9022 <tscreen><verb>
9023 void gtk_tree_item_select( GtkTreeItem *tree_item );
9024 </verb></tscreen>
9025
9026 This function is basically a wrapper around a call to
9027 <tt>gtk_item_select (GTK_ITEM (tree_item))</tt> which will emit the
9028 select signal.
9029
9030 <tscreen><verb>
9031 void gtk_tree_item_deselect( GtkTreeItem *tree_item );
9032 </verb></tscreen>
9033
9034 This function is basically a wrapper around a call to
9035 gtk_item_deselect (GTK_ITEM (tree_item)) which will emit the deselect
9036 signal.
9037
9038 <tscreen><verb>
9039 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
9040                                 GtkWidget   *subtree );
9041 </verb></tscreen>
9042
9043 This function adds a subtree to tree_item, showing it if tree_item is
9044 expanded, or hiding it if tree_item is collapsed. Again, remember that
9045 the tree_item must have already been added to a tree for this to work.
9046
9047 <tscreen><verb>
9048 void gtk_tree_item_remove_subtree( GtkTreeItem *tree_item );
9049 </verb></tscreen>
9050
9051 This removes all of tree_item's subtree's children (thus unreferencing
9052 and destroying it, any of its children's subtrees, and so on...), then
9053 removes the subtree itself, and hides the plus/minus sign.
9054
9055 <tscreen><verb>
9056 void gtk_tree_item_expand( GtkTreeItem *tree_item );
9057 </verb></tscreen>
9058
9059 This emits the "expand" signal on tree_item, which expands it.
9060
9061 <tscreen><verb>
9062 void gtk_tree_item_collapse( GtkTreeItem *tree_item );
9063 </verb></tscreen>
9064
9065 This emits the "collapse" signal on tree_item, which collapses it.
9066
9067 <tscreen><verb>
9068 GtkTreeItem *GTK_TREE_ITEM (gpointer obj)
9069 </verb></tscreen>
9070
9071 Cast a generic pointer to "GtkTreeItem *".
9072
9073 <tscreen><verb>
9074 GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj)
9075 </verb></tscreen>
9076
9077 Cast a generic pointer to "GtkTreeItemClass".
9078
9079 <tscreen><verb>
9080 gint GTK_IS_TREE_ITEM (gpointer obj)
9081 </verb></tscreen>
9082
9083 Determine if a generic pointer refers to a "GtkTreeItem" object.
9084  
9085 <tscreen><verb>
9086 GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj)
9087 </verb></tscreen>
9088
9089 Returns a tree item's subtree (<tt/obj/ should point to a
9090 "GtkTreeItem" object).
9091
9092 <sect1> Tree Example
9093 <p>
9094 This is somewhat like the tree example in testgtk.c, but a lot less
9095 complete (although much better commented).  It puts up a window with a
9096 tree, and connects all the signals for the relevant objects, so you
9097 can see when they are emitted.
9098
9099 <tscreen><verb>
9100 /* example-start tree tree.c */
9101
9102 #include <gtk/gtk.h>
9103
9104 /* for all the GtkItem:: and GtkTreeItem:: signals */
9105 static void cb_itemsignal (GtkWidget *item, gchar *signame)
9106 {
9107   gchar *name;
9108   GtkLabel *label;
9109
9110   /* It's a Bin, so it has one child, which we know to be a
9111      label, so get that */
9112   label = GTK_LABEL (GTK_BIN (item)->child);
9113   /* Get the text of the label */
9114   gtk_label_get (label, &amp;name);
9115   /* Get the level of the tree which the item is in */
9116   g_print ("%s called for item %s->%p, level %d\n", signame, name,
9117            item, GTK_TREE (item->parent)->level);
9118 }
9119
9120 /* Note that this is never called */
9121 static void cb_unselect_child (GtkWidget *root_tree, GtkWidget *child,
9122                                GtkWidget *subtree)
9123 {
9124   g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
9125            root_tree, subtree, child);
9126 }
9127
9128 /* Note that this is called every time the user clicks on an item,
9129    whether it is already selected or not. */
9130 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
9131                              GtkWidget *subtree)
9132 {
9133   g_print ("select_child called for root tree %p, subtree %p, child %p\n",
9134            root_tree, subtree, child);
9135 }
9136
9137 static void cb_selection_changed (GtkWidget *tree)
9138 {
9139   GList *i;
9140   
9141   g_print ("selection_change called for tree %p\n", tree);
9142   g_print ("selected objects are:\n");
9143
9144   i = GTK_TREE_SELECTION(tree);
9145   while (i){
9146     gchar *name;
9147     GtkLabel *label;
9148     GtkWidget *item;
9149
9150     /* Get a GtkWidget pointer from the list node */
9151     item = GTK_WIDGET (i->data);
9152     label = GTK_LABEL (GTK_BIN (item)->child);
9153     gtk_label_get (label, &amp;name);
9154     g_print ("\t%s on level %d\n", name, GTK_TREE
9155              (item->parent)->level);
9156     i = i->next;
9157   }
9158 }
9159
9160 int main (int argc, char *argv[])
9161 {
9162   GtkWidget *window, *scrolled_win, *tree;
9163   static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux",
9164                                "Maurice"};
9165   gint i;
9166
9167   gtk_init (&amp;argc, &amp;argv);
9168
9169   /* a generic toplevel window */
9170   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9171   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
9172                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
9173   gtk_container_set_border_width (GTK_CONTAINER(window), 5);
9174
9175   /* A generic scrolled window */
9176   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
9177   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
9178                                   GTK_POLICY_AUTOMATIC,
9179                                   GTK_POLICY_AUTOMATIC);
9180   gtk_widget_set_usize (scrolled_win, 150, 200);
9181   gtk_container_add (GTK_CONTAINER(window), scrolled_win);
9182   gtk_widget_show (scrolled_win);
9183   
9184   /* Create the root tree */
9185   tree = gtk_tree_new();
9186   g_print ("root tree is %p\n", tree);
9187   /* connect all GtkTree:: signals */
9188   gtk_signal_connect (GTK_OBJECT(tree), "select_child",
9189                       GTK_SIGNAL_FUNC(cb_select_child), tree);
9190   gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
9191                       GTK_SIGNAL_FUNC(cb_unselect_child), tree);
9192   gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
9193                       GTK_SIGNAL_FUNC(cb_selection_changed), tree);
9194   /* Add it to the scrolled window */
9195   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
9196                                          tree);
9197   /* Set the selection mode */
9198   gtk_tree_set_selection_mode (GTK_TREE(tree),
9199                                GTK_SELECTION_MULTIPLE);
9200   /* Show it */
9201   gtk_widget_show (tree);
9202
9203   for (i = 0; i < 5; i++){
9204     GtkWidget *subtree, *item;
9205     gint j;
9206
9207     /* Create a tree item */
9208     item = gtk_tree_item_new_with_label (itemnames[i]);
9209     /* Connect all GtkItem:: and GtkTreeItem:: signals */
9210     gtk_signal_connect (GTK_OBJECT(item), "select",
9211                         GTK_SIGNAL_FUNC(cb_itemsignal), "select");
9212     gtk_signal_connect (GTK_OBJECT(item), "deselect",
9213                         GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
9214     gtk_signal_connect (GTK_OBJECT(item), "toggle",
9215                         GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
9216     gtk_signal_connect (GTK_OBJECT(item), "expand",
9217                         GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
9218     gtk_signal_connect (GTK_OBJECT(item), "collapse",
9219                         GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
9220     /* Add it to the parent tree */
9221     gtk_tree_append (GTK_TREE(tree), item);
9222     /* Show it - this can be done at any time */
9223     gtk_widget_show (item);
9224     /* Create this item's subtree */
9225     subtree = gtk_tree_new();
9226     g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item,
9227              subtree);
9228
9229     /* This is still necessary if you want these signals to be called
9230        for the subtree's children.  Note that selection_change will be 
9231        signalled for the root tree regardless. */
9232     gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
9233                         GTK_SIGNAL_FUNC(cb_select_child), subtree);
9234     gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
9235                         GTK_SIGNAL_FUNC(cb_unselect_child), subtree);
9236     /* This has absolutely no effect, because it is completely ignored 
9237        in subtrees */
9238     gtk_tree_set_selection_mode (GTK_TREE(subtree),
9239                                  GTK_SELECTION_SINGLE);
9240     /* Neither does this, but for a rather different reason - the
9241        view_mode and view_line values of a tree are propagated to
9242        subtrees when they are mapped.  So, setting it later on would
9243        actually have a (somewhat unpredictable) effect */
9244     gtk_tree_set_view_mode (GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
9245     /* Set this item's subtree - note that you cannot do this until
9246        AFTER the item has been added to its parent tree! */
9247     gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subtree);
9248
9249     for (j = 0; j < 5; j++){
9250       GtkWidget *subitem;
9251
9252       /* Create a subtree item, in much the same way */
9253       subitem = gtk_tree_item_new_with_label (itemnames[j]);
9254       /* Connect all GtkItem:: and GtkTreeItem:: signals */
9255       gtk_signal_connect (GTK_OBJECT(subitem), "select",
9256                           GTK_SIGNAL_FUNC(cb_itemsignal), "select");
9257       gtk_signal_connect (GTK_OBJECT(subitem), "deselect",
9258                           GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
9259       gtk_signal_connect (GTK_OBJECT(subitem), "toggle",
9260                           GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
9261       gtk_signal_connect (GTK_OBJECT(subitem), "expand",
9262                           GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
9263       gtk_signal_connect (GTK_OBJECT(subitem), "collapse",
9264                           GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
9265       g_print ("-> -> item %s->%p\n", itemnames[j], subitem);
9266       /* Add it to its parent tree */
9267       gtk_tree_append (GTK_TREE(subtree), subitem);
9268       /* Show it */
9269       gtk_widget_show (subitem);
9270     }
9271   }
9272
9273   /* Show the window and loop endlessly */
9274   gtk_widget_show (window);
9275   gtk_main();
9276   return 0;
9277 }
9278 /* example-end */
9279 </verb></tscreen>
9280
9281 <!-- ***************************************************************** -->
9282 <sect>Menu Widget
9283 <!-- ***************************************************************** -->
9284 <p>
9285 There are two ways to create menus: there's the easy way, and there's
9286 the hard way. Both have their uses, but you can usually use the
9287 Itemfactory (the easy way). The "hard" way is to create all the menus
9288 using the calls directly. The easy way is to use the gtk_item_factory
9289 calls. This is much simpler, but there are advantages and
9290 disadvantages to each approach.
9291
9292 The Itemfactory is much easier to use, and to add new menus to,
9293 although writing a few wrapper functions to create menus using the
9294 manual method could go a long way towards usability. With the
9295 Itemfactory, it is not possible to add images or the character '/' to
9296 the menus.
9297
9298 <!-- ----------------------------------------------------------------- -->
9299 <sect1>Manual Menu Creation
9300 <p>
9301 In the true tradition of teaching, we'll show you the hard way
9302 first. <tt>:)</>
9303
9304 There are three widgets that go into making a menubar and submenus:
9305 <itemize>
9306 <item>a menu item, which is what the user wants to select, e.g.,
9307 "Save"
9308 <item>a menu, which acts as a container for the menu items, and
9309 <item>a menubar, which is a container for each of the individual
9310 menus.
9311 </itemize>
9312
9313 This is slightly complicated by the fact that menu item widgets are
9314 used for two different things. They are both the widgets that are
9315 packed into the menu, and the widget that is packed into the menubar,
9316 which, when selected, activates the menu.
9317
9318 Let's look at the functions that are used to create menus and
9319 menubars.  This first function is used to create a new menubar.
9320
9321 <tscreen>
9322 <verb>
9323 GtkWidget *gtk_menu_bar_new( void );
9324 </verb>
9325 </tscreen>
9326
9327 This rather self explanatory function creates a new menubar. You use
9328 gtk_container_add to pack this into a window, or the box_pack
9329 functions to pack it into a box - the same as buttons.
9330
9331 <tscreen><verb>
9332 GtkWidget *gtk_menu_new( void );
9333 </verb></tscreen>
9334
9335 This function returns a pointer to a new menu; it is never actually
9336 shown (with gtk_widget_show), it is just a container for the menu
9337 items. I hope this will become more clear when you look at the
9338 example below.
9339
9340 The next two calls are used to create menu items that are packed into
9341 the menu (and menubar).
9342
9343 <tscreen><verb>
9344 GtkWidget *gtk_menu_item_new( void );
9345 </verb></tscreen>
9346
9347 and
9348
9349 <tscreen><verb>
9350 GtkWidget *gtk_menu_item_new_with_label( const char *label );
9351 </verb></tscreen>
9352
9353 These calls are used to create the menu items that are to be
9354 displayed.  Remember to differentiate between a "menu" as created with
9355 gtk_menu_new and a "menu item" as created by the gtk_menu_item_new
9356 functions. The menu item will be an actual button with an associated
9357 action, whereas a menu will be a container holding menu items.
9358
9359 The gtk_menu_new_with_label and gtk_menu_new functions are just as
9360 you'd expect after reading about the buttons. One creates a new menu
9361 item with a label already packed into it, and the other just creates a
9362 blank menu item.
9363
9364 Once you've created a menu item you have to put it into a menu. This
9365 is done using the function gtk_menu_append. In order to capture when
9366 the item is selected by the user, we need to connect to the
9367 <tt/activate/ signal in the usual way. So, if we wanted to create a
9368 standard <tt/File/ menu, with the options <tt/Open/, <tt/Save/, and
9369 <tt/Quit/, the code would look something like:
9370
9371 <tscreen><verb>
9372     file_menu = gtk_menu_new ();    /* Don't need to show menus */
9373
9374     /* Create the menu items */
9375     open_item = gtk_menu_item_new_with_label ("Open");
9376     save_item = gtk_menu_item_new_with_label ("Save");
9377     quit_item = gtk_menu_item_new_with_label ("Quit");
9378
9379     /* Add them to the menu */
9380     gtk_menu_append (GTK_MENU (file_menu), open_item);
9381     gtk_menu_append (GTK_MENU (file_menu), save_item);
9382     gtk_menu_append (GTK_MENU (file_menu), quit_item);
9383
9384     /* Attach the callback functions to the activate signal */
9385     gtk_signal_connect_object (GTK_OBJECT (open_items), "activate",
9386                                GTK_SIGNAL_FUNC (menuitem_response),
9387                                (gpointer) "file.open");
9388     gtk_signal_connect_object (GTK_OBJECT (save_items), "activate",
9389                                GTK_SIGNAL_FUNC (menuitem_response),
9390                                (gpointer) "file.save");
9391
9392     /* We can attach the Quit menu item to our exit function */
9393     gtk_signal_connect_object (GTK_OBJECT (quit_items), "activate",
9394                                GTK_SIGNAL_FUNC (destroy),
9395                                (gpointer) "file.quit");
9396
9397     /* We do need to show menu items */
9398     gtk_widget_show (open_item);
9399     gtk_widget_show (save_item);
9400     gtk_widget_show (quit_item);
9401 </verb></tscreen>
9402
9403 At this point we have our menu. Now we need to create a menubar and a
9404 menu item for the <tt/File/ entry, to which we add our menu. The code
9405 looks like this:
9406
9407 <tscreen><verb>
9408     menu_bar = gtk_menu_bar_new ();
9409     gtk_container_add (GTK_CONTAINER (window), menu_bar);
9410     gtk_widget_show (menu_bar);
9411
9412     file_item = gtk_menu_item_new_with_label ("File");
9413     gtk_widget_show (file_item);
9414 </verb></tscreen>
9415
9416 Now we need to associate the menu with <tt/file_item/. This is done
9417 with the function
9418
9419 <tscreen>
9420 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
9421                                 GtkWidget   *submenu );
9422 </tscreen>
9423
9424 So, our example would continue with
9425
9426 <tscreen><verb>
9427     gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_item), file_menu);
9428 </verb></tscreen>
9429
9430 All that is left to do is to add the menu to the menubar, which is
9431 accomplished using the function
9432
9433 <tscreen>
9434 void gtk_menu_bar_append( GtkMenuBar *menu_bar,
9435                           GtkWidget  *menu_item );
9436 </tscreen>
9437
9438 which in our case looks like this:
9439
9440 <tscreen><verb>
9441     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), file_item);
9442 </verb></tscreen>
9443
9444 If we wanted the menu right justified on the menubar, such as help
9445 menus often are, we can use the following function (again on
9446 <tt/file_item/ in the current example) before attaching it to the
9447 menubar.
9448
9449 <tscreen><verb>
9450 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
9451 </verb></tscreen>
9452
9453 Here is a summary of the steps needed to create a menu bar with menus
9454 attached:
9455
9456 <itemize>
9457 <item> Create a new menu using gtk_menu_new()
9458 <item> Use multiple calls to gtk_menu_item_new() for each item you
9459 wish to have on your menu. And use gtk_menu_append() to put each of
9460 these new items on to the menu.
9461 <item> Create a menu item using gtk_menu_item_new(). This will be the
9462 root of the menu, the text appearing here will be on the menubar
9463 itself.
9464 <item>Use gtk_menu_item_set_submenu() to attach the menu to the root
9465 menu item (the one created in the above step).
9466 <item> Create a new menubar using gtk_menu_bar_new. This step only
9467 needs to be done once when creating a series of menus on one menu bar.
9468 <item> Use gtk_menu_bar_append() to put the root menu onto the menubar.
9469 </itemize>
9470
9471 Creating a popup menu is nearly the same. The difference is that the
9472 menu is not posted "automatically" by a menubar, but explicitly by
9473 calling the function gtk_menu_popup() from a button-press event, for
9474 example.  Take these steps:
9475
9476 <itemize>
9477 <item>Create an event handling function. It needs to have the
9478 prototype
9479 <tscreen>
9480 static gint handler (GtkWidget *widget,
9481                      GdkEvent  *event);
9482 </tscreen>
9483 and it will use the event to find out where to pop up the menu.
9484 <item>In the event handler, if the event is a mouse button press,
9485 treat <tt>event</tt> as a button event (which it is) and use it as
9486 shown in the sample code to pass information to gtk_menu_popup().
9487 <item>Bind that event handler to a widget with
9488 <tscreen>
9489     gtk_signal_connect_object (GTK_OBJECT (widget), "event",
9490                                GTK_SIGNAL_FUNC (handler),
9491                                GTK_OBJECT (menu));
9492 </tscreen>
9493 where <tt>widget</tt> is the widget you are binding to,
9494 <tt>handler</tt> is the handling function, and <tt>menu</tt> is a menu
9495 created with gtk_menu_new(). This can be a menu which is also posted
9496 by a menu bar, as shown in the sample code.
9497 </itemize>
9498
9499 <!-- ----------------------------------------------------------------- -->
9500 <sect1>Manual Menu Example
9501 <p>
9502 That should about do it. Let's take a look at an example to help clarify.
9503
9504 <tscreen><verb>
9505 /* example-start menu menu.c */
9506
9507 #include <gtk/gtk.h>
9508
9509 static gint button_press (GtkWidget *, GdkEvent *);
9510 static void menuitem_response (gchar *);
9511
9512 int main( int   argc,
9513           char *argv[] )
9514 {
9515
9516     GtkWidget *window;
9517     GtkWidget *menu;
9518     GtkWidget *menu_bar;
9519     GtkWidget *root_menu;
9520     GtkWidget *menu_items;
9521     GtkWidget *vbox;
9522     GtkWidget *button;
9523     char buf[128];
9524     int i;
9525
9526     gtk_init (&amp;argc, &amp;argv);
9527
9528     /* create a new window */
9529     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9530     gtk_widget_set_usize (GTK_WIDGET (window), 200, 100);
9531     gtk_window_set_title (GTK_WINDOW (window), "GTK Menu Test");
9532     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
9533                         (GtkSignalFunc) gtk_main_quit, NULL);
9534
9535     /* Init the menu-widget, and remember -- never
9536      * gtk_show_widget() the menu widget!! 
9537      * This is the menu that holds the menu items, the one that
9538      * will pop up when you click on the "Root Menu" in the app */
9539     menu = gtk_menu_new ();
9540
9541     /* Next we make a little loop that makes three menu-entries for "test-menu".
9542      * Notice the call to gtk_menu_append.  Here we are adding a list of
9543      * menu items to our menu.  Normally, we'd also catch the "clicked"
9544      * signal on each of the menu items and setup a callback for it,
9545      * but it's omitted here to save space. */
9546
9547     for (i = 0; i < 3; i++)
9548         {
9549             /* Copy the names to the buf. */
9550             sprintf (buf, "Test-undermenu - %d", i);
9551
9552             /* Create a new menu-item with a name... */
9553             menu_items = gtk_menu_item_new_with_label (buf);
9554
9555             /* ...and add it to the menu. */
9556             gtk_menu_append (GTK_MENU (menu), menu_items);
9557
9558             /* Do something interesting when the menuitem is selected */
9559             gtk_signal_connect_object (GTK_OBJECT (menu_items), "activate",
9560                 GTK_SIGNAL_FUNC (menuitem_response), (gpointer) g_strdup (buf));
9561
9562             /* Show the widget */
9563             gtk_widget_show (menu_items);
9564         }
9565
9566     /* This is the root menu, and will be the label
9567      * displayed on the menu bar.  There won't be a signal handler attached,
9568      * as it only pops up the rest of the menu when pressed. */
9569     root_menu = gtk_menu_item_new_with_label ("Root Menu");
9570
9571     gtk_widget_show (root_menu);
9572
9573     /* Now we specify that we want our newly created "menu" to be the menu
9574      * for the "root menu" */
9575     gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu);
9576
9577     /* A vbox to put a menu and a button in: */
9578     vbox = gtk_vbox_new (FALSE, 0);
9579     gtk_container_add (GTK_CONTAINER (window), vbox);
9580     gtk_widget_show (vbox);
9581
9582     /* Create a menu-bar to hold the menus and add it to our main window */
9583     menu_bar = gtk_menu_bar_new ();
9584     gtk_box_pack_start (GTK_BOX (vbox), menu_bar, FALSE, FALSE, 2);
9585     gtk_widget_show (menu_bar);
9586
9587     /* Create a button to which to attach menu as a popup */
9588     button = gtk_button_new_with_label ("press me");
9589     gtk_signal_connect_object (GTK_OBJECT (button), "event",
9590         GTK_SIGNAL_FUNC (button_press), GTK_OBJECT (menu));
9591     gtk_box_pack_end (GTK_BOX (vbox), button, TRUE, TRUE, 2);
9592     gtk_widget_show (button);
9593
9594     /* And finally we append the menu-item to the menu-bar -- this is the
9595      * "root" menu-item I have been raving about =) */
9596     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), root_menu);
9597
9598     /* always display the window as the last step so it all splashes on
9599      * the screen at once. */
9600     gtk_widget_show (window);
9601
9602     gtk_main ();
9603
9604     return(0);
9605 }
9606
9607 /* Respond to a button-press by posting a menu passed in as widget.
9608  *
9609  * Note that the "widget" argument is the menu being posted, NOT
9610  * the button that was pressed.
9611  */
9612
9613 static gint button_press (GtkWidget *widget, GdkEvent *event)
9614 {
9615
9616     if (event->type == GDK_BUTTON_PRESS) {
9617         GdkEventButton *bevent = (GdkEventButton *) event; 
9618         gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
9619                         bevent->button, bevent->time);
9620         /* Tell calling code that we have handled this event; the buck
9621          * stops here. */
9622         return TRUE;
9623     }
9624
9625     /* Tell calling code that we have not handled this event; pass it on. */
9626     return FALSE;
9627 }
9628
9629
9630 /* Print a string when a menu item is selected */
9631
9632 static void menuitem_response (gchar *string)
9633 {
9634     printf ("%s\n", string);
9635 }
9636 /* example-end */
9637 </verb></tscreen>
9638
9639 You may also set a menu item to be insensitive and, using an accelerator
9640 table, bind keys to menu functions.
9641
9642 <!-- ----------------------------------------------------------------- -->
9643 <sect1>Using ItemFactory
9644 <p>
9645 Now that we've shown you the hard way, here's how you do it using the
9646 gtk_item_factory calls.
9647
9648 <!-- ----------------------------------------------------------------- -->
9649 <sect1>Item Factory Example
9650 <p>
9651 Here is an example using the GTK item factory.
9652
9653 <tscreen><verb>
9654 /* example-start menu itemfactory.c */
9655
9656 #include <gtk/gtk.h>
9657 #include <strings.h>
9658
9659 /* Obligatory basic callback */
9660 static void print_hello( GtkWidget *w,
9661                          gpointer   data )
9662 {
9663   g_message ("Hello, World!\n");
9664 }
9665
9666 /* This is the GtkItemFactoryEntry structure used to generate new menus.
9667    Item 1: The menu path. The letter after the underscore indicates an
9668            accelerator key once the menu is open.
9669    Item 2: The accelerator key for the entry
9670    Item 3: The callback function.
9671    Item 4: The callback action.  This changes the parameters with
9672            which the function is called.  The default is 0.
9673    Item 5: The item type, used to define what kind of an item it is.
9674            Here are the possible values:
9675
9676            NULL               -> "<Item>"
9677            ""                 -> "<Item>"
9678            "<Title>"          -> create a title item
9679            "<Item>"           -> create a simple item
9680            "<CheckItem>"      -> create a check item
9681            "<ToggleItem>"     -> create a toggle item
9682            "<RadioItem>"      -> create a radio item
9683            <path>             -> path of a radio item to link against
9684            "<Separator>"      -> create a separator
9685            "<Branch>"         -> create an item to hold sub items (optional)
9686            "<LastBranch>"     -> create a right justified branch 
9687 */
9688
9689 static GtkItemFactoryEntry menu_items[] = {
9690   { "/_File",         NULL,         NULL, 0, "<Branch>" },
9691   { "/File/_New",     "<control>N", print_hello, 0, NULL },
9692   { "/File/_Open",    "<control>O", print_hello, 0, NULL },
9693   { "/File/_Save",    "<control>S", print_hello, 0, NULL },
9694   { "/File/Save _As", NULL,         NULL, 0, NULL },
9695   { "/File/sep1",     NULL,         NULL, 0, "<Separator>" },
9696   { "/File/Quit",     "<control>Q", gtk_main_quit, 0, NULL },
9697   { "/_Options",      NULL,         NULL, 0, "<Branch>" },
9698   { "/Options/Test",  NULL,         NULL, 0, NULL },
9699   { "/_Help",         NULL,         NULL, 0, "<LastBranch>" },
9700   { "/_Help/About",   NULL,         NULL, 0, NULL },
9701 };
9702
9703
9704 void get_main_menu( GtkWidget  *window,
9705                     GtkWidget **menubar )
9706 {
9707   GtkItemFactory *item_factory;
9708   GtkAccelGroup *accel_group;
9709   gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
9710
9711   accel_group = gtk_accel_group_new ();
9712
9713   /* This function initializes the item factory.
9714      Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
9715               or GTK_TYPE_OPTION_MENU.
9716      Param 2: The path of the menu.
9717      Param 3: A pointer to a gtk_accel_group.  The item factory sets up
9718               the accelerator table while generating menus.
9719   */
9720
9721   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", 
9722                                        accel_group);
9723
9724   /* This function generates the menu items. Pass the item factory,
9725      the number of items in the array, the array itself, and any
9726      callback data for the the menu items. */
9727   gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
9728
9729   /* Attach the new accelerator group to the window. */
9730   gtk_accel_group_attach (accel_group, GTK_OBJECT (window));
9731
9732   if (menubar)
9733     /* Finally, return the actual menu bar created by the item factory. */ 
9734     *menubar = gtk_item_factory_get_widget (item_factory, "<main>");
9735 }
9736
9737 int main( int argc,
9738           char *argv[] )
9739 {
9740   GtkWidget *window;
9741   GtkWidget *main_vbox;
9742   GtkWidget *menubar;
9743   
9744   gtk_init (&amp;argc, &amp;argv);
9745   
9746   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9747   gtk_signal_connect (GTK_OBJECT (window), "destroy", 
9748                       GTK_SIGNAL_FUNC (gtk_main_quit), 
9749                       "WM destroy");
9750   gtk_window_set_title (GTK_WINDOW(window), "Item Factory");
9751   gtk_widget_set_usize (GTK_WIDGET(window), 300, 200);
9752   
9753   main_vbox = gtk_vbox_new (FALSE, 1);
9754   gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
9755   gtk_container_add (GTK_CONTAINER (window), main_vbox);
9756   gtk_widget_show (main_vbox);
9757   
9758   get_main_menu (window, &amp;menubar);
9759   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
9760   gtk_widget_show (menubar);
9761   
9762   gtk_widget_show (window);
9763   gtk_main ();
9764   
9765   return(0);
9766 }
9767 /* example-end */
9768 </verb></tscreen>
9769
9770
9771 For now, there's only this example. An explanation and lots 'o' comments
9772 will follow later.
9773
9774 <!-- ***************************************************************** -->
9775 <sect> Text Widget
9776 <!-- ***************************************************************** -->
9777 <p>
9778 The Text widget allows multiple lines of text to be displayed and
9779 edited. It supports both multi-colored and multi-font text, allowing
9780 them to be mixed in any way we wish. It also has a wide set of key
9781 based text editing commands, which are compatible with Emacs.
9782
9783 The text widget supports full cut-and-paste facilities, including the
9784 use of double- and triple-click to select a word and a whole line,
9785 respectively.
9786
9787 <!-- ----------------------------------------------------------------- -->
9788 <sect1>Creating and Configuring a Text box
9789 <p>
9790 There is only one function for creating a new Text widget.
9791
9792 <tscreen><verb>
9793 GtkWidget *gtk_text_new( GtkAdjustment *hadj,
9794                          GtkAdjustment *vadj );
9795 </verb></tscreen>
9796
9797 The arguments allow us to give the Text widget pointers to Adjustments
9798 that can be used to track the viewing position of the widget. Passing
9799 NULL values to either or both of these arguments will cause the
9800 gtk_text_new function to create its own.
9801
9802 <tscreen><verb>
9803 void gtk_text_set_adjustments( GtkText       *text,
9804                                GtkAdjustment *hadj,
9805                                GtkAdjustment *vadj );
9806 </verb></tscreen>
9807
9808 The above function allows the horizontal and vertical adjustments of a
9809 text widget to be changed at any time.
9810
9811 The text widget will not automatically create its own scrollbars when
9812 the amount of text to be displayed is too long for the display
9813 window. We therefore have to create and add them to the display layout
9814 ourselves.
9815
9816 <tscreen><verb>
9817   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
9818   gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
9819   gtk_widget_show (vscrollbar);
9820 </verb></tscreen>
9821
9822 The above code snippet creates a new vertical scrollbar, and attaches
9823 it to the vertical adjustment of the text widget, <tt/text/. It then
9824 packs it into a box in the normal way.
9825
9826 Note, currently the Text widget does not support horizontal
9827 scrollbars.
9828
9829 There are two main ways in which a Text widget can be used: to allow
9830 the user to edit a body of text, or to allow us to display multiple
9831 lines of text to the user. In order for us to switch between these
9832 modes of operation, the text widget has the following function:
9833
9834 <tscreen><verb>
9835 void gtk_text_set_editable( GtkText *text,
9836                             gint     editable );
9837 </verb></tscreen>
9838
9839 The <tt/editable/ argument is a TRUE or FALSE value that specifies
9840 whether the user is permitted to edit the contents of the Text
9841 widget. When the text widget is editable, it will display a cursor at
9842 the current insertion point.
9843
9844 You are not, however, restricted to just using the text widget in
9845 these two modes. You can toggle the editable state of the text widget
9846 at any time, and can insert text at any time.
9847
9848 The text widget wraps lines of text that are too long to fit onto a
9849 single line of the display window. Its default behaviour is to break
9850 words across line breaks. This can be changed using the next function:
9851
9852 <tscreen><verb>
9853 void gtk_text_set_word_wrap( GtkText *text,
9854                              gint     word_wrap );
9855 </verb></tscreen>
9856
9857 Using this function allows us to specify that the text widget should
9858 wrap long lines on word boundaries. The <tt/word_wrap/ argument is a
9859 TRUE or FALSE value.
9860
9861 <!-- ----------------------------------------------------------------- -->
9862 <sect1>Text Manipulation
9863 <P>
9864 The current insertion point of a Text widget can be set using
9865 <tscreen><verb>
9866 void gtk_text_set_point( GtkText *text,
9867                          guint    index );
9868 </verb></tscreen>
9869
9870 where <tt/index/ is the position to set the insertion point.
9871
9872 Analogous to this is the function for getting the current insertion
9873 point:
9874
9875 <tscreen><verb>
9876 guint gtk_text_get_point( GtkText *text );
9877 </verb></tscreen>
9878
9879 A function that is useful in combination with the above two functions
9880 is
9881
9882 <tscreen><verb>
9883 guint gtk_text_get_length( GtkText *text );
9884 </verb></tscreen>
9885
9886 which returns the current length of the Text widget. The length is the
9887 number of characters that are within the text block of the widget,
9888 including characters such as newline, which marks the end of
9889 lines.
9890
9891 In order to insert text at the current insertion point of a Text
9892 widget, the function gtk_text_insert is used, which also allows us to
9893 specify background and foreground colors and a font for the text.
9894
9895 <tscreen><verb>
9896 void gtk_text_insert( GtkText    *text,
9897                       GdkFont    *font,
9898                       GdkColor   *fore,
9899                       GdkColor   *back,
9900                       const char *chars,
9901                       gint        length );
9902 </verb></tscreen>
9903
9904 Passing a value of <tt/NULL/ in as the value for the foreground color,
9905 background color or font will result in the values set within the
9906 widget style to be used. Using a value of <tt/-1/ for the length
9907 parameter will result in the whole of the text string given being
9908 inserted.
9909
9910 The text widget is one of the few within GTK that redraws itself
9911 dynamically, outside of the gtk_main function. This means that all
9912 changes to the contents of the text widget take effect
9913 immediately. This may be undesirable when performing multiple changes
9914 to the text widget. In order to allow us to perform multiple updates
9915 to the text widget without it continuously redrawing, we can freeze
9916 the widget, which temporarily stops it from automatically redrawing
9917 itself every time it is changed. We can then thaw the widget after our
9918 updates are complete.
9919
9920 The following two functions perform this freeze and thaw action:
9921
9922 <tscreen><verb>
9923 void gtk_text_freeze( GtkText *text );
9924
9925 void gtk_text_thaw( GtkText *text );         
9926 </verb></tscreen>
9927
9928 Text is deleted from the text widget relative to the current insertion
9929 point by the following two functions. The return value is a TRUE or
9930 FALSE indicator of whether the operation was successful.
9931
9932 <tscreen><verb>
9933 gint gtk_text_backward_delete( GtkText *text,
9934                                guint    nchars );
9935
9936 gint gtk_text_forward_delete ( GtkText *text,
9937                                guint    nchars );
9938 </verb></tscreen>
9939
9940 If you want to retrieve the contents of the text widget, then the
9941 macro <tt/GTK_TEXT_INDEX(t, index)/ allows you to retrieve the
9942 character at position <tt/index/ within the text widget <tt/t/.
9943
9944 To retrieve larger blocks of text, we can use the function
9945
9946 <tscreen><verb>
9947 gchar *gtk_editable_get_chars( GtkEditable *editable,
9948                                gint         start_pos,
9949                                gint         end_pos );   
9950 </verb></tscreen>
9951
9952 This is a function of the parent class of the text widget. A value of
9953 -1 as <tt/end_pos/ signifies the end of the text. The index of the
9954 text starts at 0.
9955
9956 The function allocates a new chunk of memory for the text block, so
9957 don't forget to free it with a call to g_free when you have finished
9958 with it.
9959  
9960 <!-- ----------------------------------------------------------------- -->
9961 <sect1>Keyboard Shortcuts
9962 <p>
9963 The text widget has a number of pre-installed keyboard shortcuts for
9964 common editing, motion and selection functions. These are accessed
9965 using Control and Alt key combinations.
9966
9967 In addition to these, holding down the Control key whilst using cursor
9968 key movement will move the cursor by words rather than
9969 characters. Holding down Shift whilst using cursor movement will
9970 extend the selection.
9971
9972 <sect2>Motion Shortcuts
9973 <p>
9974 <itemize>
9975 <item> Ctrl-A   Beginning of line
9976 <item> Ctrl-E   End of line
9977 <item> Ctrl-N   Next Line
9978 <item> Ctrl-P   Previous Line
9979 <item> Ctrl-B   Backward one character
9980 <item> Ctrl-F   Forward one character
9981 <item> Alt-B    Backward one word
9982 <item> Alt-F    Forward one word
9983 </itemize>
9984
9985 <sect2>Editing Shortcuts
9986 <p>
9987 <itemize>
9988 <item> Ctrl-H   Delete Backward Character (Backspace)
9989 <item> Ctrl-D   Delete Forward Character (Delete)
9990 <item> Ctrl-W   Delete Backward Word
9991 <item> Alt-D    Delete Forward Word
9992 <item> Ctrl-K   Delete to end of line
9993 <item> Ctrl-U   Delete line
9994 </itemize>
9995
9996 <sect2>Selection Shortcuts
9997 <p>
9998 <itemize>
9999 <item> Ctrl-X   Cut to clipboard
10000 <item> Ctrl-C   Copy to clipboard
10001 <item> Ctrl-V   Paste from clipboard
10002 </itemize>
10003
10004 <!-- ----------------------------------------------------------------- -->
10005 <sect1>A GtkText Example
10006 <p>
10007 <tscreen><verb>
10008 /* example-start text text.c */
10009
10010 /* text.c */
10011
10012 #include <stdio.h>
10013 #include <gtk/gtk.h>
10014
10015 void text_toggle_editable (GtkWidget *checkbutton,
10016                            GtkWidget *text)
10017 {
10018   gtk_text_set_editable(GTK_TEXT(text),
10019                         GTK_TOGGLE_BUTTON(checkbutton)->active);
10020 }
10021
10022 void text_toggle_word_wrap (GtkWidget *checkbutton,
10023                             GtkWidget *text)
10024 {
10025   gtk_text_set_word_wrap(GTK_TEXT(text),
10026                          GTK_TOGGLE_BUTTON(checkbutton)->active);
10027 }
10028
10029 void close_application( GtkWidget *widget, gpointer data )
10030 {
10031        gtk_main_quit();
10032 }
10033
10034 int main (int argc, char *argv[])
10035 {
10036   GtkWidget *window;
10037   GtkWidget *box1;
10038   GtkWidget *box2;
10039   GtkWidget *hbox;
10040   GtkWidget *button;
10041   GtkWidget *check;
10042   GtkWidget *separator;
10043   GtkWidget *table;
10044   GtkWidget *vscrollbar;
10045   GtkWidget *text;
10046   GdkColormap *cmap;
10047   GdkColor color;
10048   GdkFont *fixed_font;
10049
10050   FILE *infile;
10051
10052   gtk_init (&amp;argc, &amp;argv);
10053  
10054   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10055   gtk_widget_set_usize (window, 600, 500);
10056   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);  
10057   gtk_signal_connect (GTK_OBJECT (window), "destroy",
10058                       GTK_SIGNAL_FUNC(close_application),
10059                       NULL);
10060   gtk_window_set_title (GTK_WINDOW (window), "Text Widget Example");
10061   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10062   
10063   
10064   box1 = gtk_vbox_new (FALSE, 0);
10065   gtk_container_add (GTK_CONTAINER (window), box1);
10066   gtk_widget_show (box1);
10067   
10068   
10069   box2 = gtk_vbox_new (FALSE, 10);
10070   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10071   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
10072   gtk_widget_show (box2);
10073   
10074   
10075   table = gtk_table_new (2, 2, FALSE);
10076   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
10077   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
10078   gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
10079   gtk_widget_show (table);
10080   
10081   /* Create the GtkText widget */
10082   text = gtk_text_new (NULL, NULL);
10083   gtk_text_set_editable (GTK_TEXT (text), TRUE);
10084   gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
10085                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
10086                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
10087   gtk_widget_show (text);
10088
10089   /* Add a vertical scrollbar to the GtkText widget */
10090   vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
10091   gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
10092                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
10093   gtk_widget_show (vscrollbar);
10094
10095   /* Get the system color map and allocate the color red */
10096   cmap = gdk_colormap_get_system();
10097   color.red = 0xffff;
10098   color.green = 0;
10099   color.blue = 0;
10100   if (!gdk_color_alloc(cmap, &amp;color)) {
10101     g_error("couldn't allocate color");
10102   }
10103
10104   /* Load a fixed font */
10105   fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");
10106
10107   /* Realizing a widget creates a window for it,
10108    * ready for us to insert some text */
10109   gtk_widget_realize (text);
10110
10111   /* Freeze the text widget, ready for multiple updates */
10112   gtk_text_freeze (GTK_TEXT (text));
10113   
10114   /* Insert some colored text */
10115   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
10116                    "Supports ", -1);
10117   gtk_text_insert (GTK_TEXT (text), NULL, &amp;color, NULL,
10118                    "colored ", -1);
10119   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
10120                    "text and different ", -1);
10121   gtk_text_insert (GTK_TEXT (text), fixed_font, &amp;text->style->black, NULL,
10122                    "fonts\n\n", -1);
10123   
10124   /* Load the file text.c into the text window */
10125
10126   infile = fopen("text.c", "r");
10127   
10128   if (infile) {
10129     char buffer[1024];
10130     int nchars;
10131     
10132     while (1)
10133       {
10134         nchars = fread(buffer, 1, 1024, infile);
10135         gtk_text_insert (GTK_TEXT (text), fixed_font, NULL,
10136                          NULL, buffer, nchars);
10137         
10138         if (nchars < 1024)
10139           break;
10140       }
10141     
10142     fclose (infile);
10143   }
10144
10145   /* Thaw the text widget, allowing the updates to become visible */  
10146   gtk_text_thaw (GTK_TEXT (text));
10147   
10148   hbox = gtk_hbutton_box_new ();
10149   gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
10150   gtk_widget_show (hbox);
10151
10152   check = gtk_check_button_new_with_label("Editable");
10153   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
10154   gtk_signal_connect (GTK_OBJECT(check), "toggled",
10155                       GTK_SIGNAL_FUNC(text_toggle_editable), text);
10156   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
10157   gtk_widget_show (check);
10158   check = gtk_check_button_new_with_label("Wrap Words");
10159   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
10160   gtk_signal_connect (GTK_OBJECT(check), "toggled",
10161                       GTK_SIGNAL_FUNC(text_toggle_word_wrap), text);
10162   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
10163   gtk_widget_show (check);
10164
10165   separator = gtk_hseparator_new ();
10166   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10167   gtk_widget_show (separator);
10168
10169   box2 = gtk_vbox_new (FALSE, 10);
10170   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10171   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10172   gtk_widget_show (box2);
10173   
10174   button = gtk_button_new_with_label ("close");
10175   gtk_signal_connect (GTK_OBJECT (button), "clicked",
10176                       GTK_SIGNAL_FUNC(close_application),
10177                       NULL);
10178   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10179   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
10180   gtk_widget_grab_default (button);
10181   gtk_widget_show (button);
10182
10183   gtk_widget_show (window);
10184
10185   gtk_main ();
10186   
10187   return(0);       
10188 }
10189 /* example-end */
10190 </verb></tscreen>
10191
10192
10193 <!-- ***************************************************************** -->
10194 <sect> Undocumented Widgets
10195 <!-- ***************************************************************** -->
10196 <p>
10197 These all require authors! :) Please consider contributing to our
10198 tutorial.
10199
10200 If you must use one of these widgets that are undocumented, I strongly
10201 suggest you take a look at their respective header files in the GTK
10202 distribution. GTK's function names are very descriptive. Once you
10203 have an understanding of how things work, it's not difficult to figure
10204 out how to use a widget simply by looking at its function
10205 declarations. This, along with a few examples from others' code, and
10206 it should be no problem.
10207
10208 When you do come to understand all the functions of a new undocumented
10209 widget, please consider writing a tutorial on it so others may benefit
10210 from your time.
10211
10212 <!-- ----------------------------------------------------------------- -->
10213 <sect1> Calendar
10214 <p>
10215 <!-- ----------------------------------------------------------------- -->
10216 <sect1> CTree
10217 <p>
10218 <!-- ----------------------------------------------------------------- -->
10219 <sect1> Curves
10220 <p>
10221 <!-- ----------------------------------------------------------------- -->
10222 <sect1> Drawing Area
10223 <p>
10224 <!-- ----------------------------------------------------------------- -->
10225 <sect1> Font Selection Dialog
10226 <p>
10227 <!-- ----------------------------------------------------------------- -->
10228 <sect1> Gamma Curve
10229 <p>
10230 <!-- ----------------------------------------------------------------- -->
10231 <sect1> Image
10232 <p>
10233 <!-- ----------------------------------------------------------------- -->
10234 <sect1> Packer
10235 <p>
10236 <!-- ----------------------------------------------------------------- -->
10237 <sect1> Plugs and Sockets
10238 <p>
10239 <!-- ----------------------------------------------------------------- -->
10240 <sect1> Preview
10241 <p>
10242
10243 <!--
10244
10245 (This may need to be rewritten to follow the style of the rest of the tutorial)
10246
10247 <tscreen><verb>
10248
10249 Previews serve a number of purposes in GIMP/GTK. The most important one is
10250 this. High quality images may take up to tens of megabytes of memory - easily!
10251 Any operation on an image that big is bound to take a long time. If it takes
10252 you 5-10 trial-and-errors (i.e., 10-20 steps, since you have to revert after
10253 you make an error) to choose the desired modification, it make take you
10254 literally hours to make the right one - if you don't run out of memory
10255 first. People who have spent hours in color darkrooms know the feeling.
10256 Previews to the rescue!
10257
10258 But the annoyance of the delay is not the only issue. Oftentimes it is
10259 helpful to compare the Before and After versions side-by-side or at least
10260 back-to-back. If you're working with big images and 10 second delays,
10261 obtaining the Before and After impressions is, to say the least, difficult.
10262 For 30M images (4"x6", 600dpi, 24 bit) the side-by-side comparison is right
10263 out for most people, while back-to-back is more like back-to-1001, 1002,
10264 ..., 1010-back! Previews to the rescue!
10265
10266 But there's more. Previews allow for side-by-side pre-previews. In other
10267 words, you write a plug-in (e.g., the filterpack simulation) which would have
10268 a number of here's-what-it-would-look-like-if-you-were-to-do-this previews.
10269 An approach like this acts as a sort of a preview palette and is very
10270 effective for subtle changes. Let's go previews!
10271
10272 There's more. For certain plug-ins real-time image-specific human
10273 intervention maybe necessary. In the SuperNova plug-in, for example, the
10274 user is asked to enter the coordinates of the center of the future
10275 supernova. The easiest way to do this, really, is to present the user with a
10276 preview and ask him to interactively select the spot. Let's go previews!
10277
10278 Finally, a couple of misc uses. One can use previews even when not working
10279 with big images. For example, they are useful when rendering complicated
10280 patterns. (Just check out the venerable Diffraction plug-in + many other
10281 ones!) As another example, take a look at the colormap rotation plug-in
10282 (work in progress). You can also use previews for little logos inside you
10283 plug-ins and even for an image of yourself, The Author. Let's go previews!
10284
10285 When Not to Use Previews
10286
10287 Don't use previews for graphs, drawing, etc. GDK is much faster for that. Use
10288 previews only for rendered images!
10289
10290 Let's go previews!
10291
10292 You can stick a preview into just about anything. In a vbox, an hbox, a
10293 table, a button, etc. But they look their best in tight frames around them.
10294 Previews by themselves do not have borders and look flat without them. (Of
10295 course, if the flat look is what you want...) Tight frames provide the
10296 necessary borders.
10297
10298                                [Image][Image]
10299
10300 Previews in many ways are like any other widgets in GTK (whatever that
10301 means) except they possess an additional feature: they need to be filled with
10302 some sort of an image! First, we will deal exclusively with the GTK aspect
10303 of previews and then we'll discuss how to fill them.
10304
10305 GtkWidget *preview!
10306
10307 Without any ado:
10308
10309                               /* Create a preview widget,
10310                               set its size, an show it */
10311 GtkWidget *preview;
10312 preview=gtk_preview_new(GTK_PREVIEW_COLOR)
10313                               /*Other option:
10314                               GTK_PREVIEW_GRAYSCALE);*/
10315 gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT);
10316 gtk_widget_show(preview);
10317 my_preview_rendering_function(preview);
10318
10319 Oh yeah, like I said, previews look good inside frames, so how about:
10320
10321 GtkWidget *create_a_preview(int        Width,
10322                             int        Height,
10323                             int        Colorfulness)
10324 {
10325   GtkWidget *preview;
10326   GtkWidget *frame;
10327   
10328   frame = gtk_frame_new(NULL);
10329   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
10330   gtk_container_set_border_width (GTK_CONTAINER(frame),0);
10331   gtk_widget_show(frame);
10332
10333   preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR
10334                                        :GTK_PREVIEW_GRAYSCALE);
10335   gtk_preview_size (GTK_PREVIEW (preview), Width, Height);
10336   gtk_container_add(GTK_CONTAINER(frame),preview);
10337   gtk_widget_show(preview);
10338
10339   my_preview_rendering_function(preview);
10340   return frame;
10341 }
10342
10343 That's my basic preview. This routine returns the "parent" frame so you can
10344 place it somewhere else in your interface. Of course, you can pass the
10345 parent frame to this routine as a parameter. In many situations, however,
10346 the contents of the preview are changed continually by your application. In
10347 this case you may want to pass a pointer to the preview to a
10348 "create_a_preview()" and thus have control of it later.
10349
10350 One more important note that may one day save you a lot of time. Sometimes
10351 it is desirable to label you preview. For example, you may label the preview
10352 containing the original image as "Original" and the one containing the
10353 modified image as "Less Original". It might occur to you to pack the
10354 preview along with the appropriate label into a vbox. The unexpected caveat
10355 is that if the label is wider than the preview (which may happen for a
10356 variety of reasons unforseeable to you, from the dynamic decision on the
10357 size of the preview to the size of the font) the frame expands and no longer
10358 fits tightly over the preview. The same problem can probably arise in other
10359 situations as well.
10360
10361                                    [Image]
10362
10363 The solution is to place the preview and the label into a 2x1 table and by
10364 attaching them with the following parameters (this is one possible variations
10365 of course. The key is no GTK_FILL in the second attachment):
10366
10367 gtk_table_attach(GTK_TABLE(table),label,0,1,0,1,
10368                  0,
10369                  GTK_EXPAND|GTK_FILL,
10370                  0,0);
10371 gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2,
10372                  GTK_EXPAND,
10373                  GTK_EXPAND,
10374                  0,0);
10375
10376
10377 And here's the result:
10378
10379                                    [Image]
10380
10381 Misc
10382
10383 Making a preview clickable is achieved most easily by placing it in a
10384 button. It also adds a nice border around the preview and you may not even
10385 need to place it in a frame. See the Filter Pack Simulation plug-in for an
10386 example.
10387
10388 This is pretty much it as far as GTK is concerned.
10389
10390 Filling In a Preview
10391
10392 In order to familiarize ourselves with the basics of filling in previews,
10393 let's create the following pattern (contrived by trial and error):
10394
10395                                    [Image]
10396
10397 void
10398 my_preview_rendering_function(GtkWidget     *preview)
10399 {
10400 #define SIZE 100
10401 #define HALF (SIZE/2)
10402
10403   guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */
10404   gint i, j;                             /* Coordinates    */
10405   double r, alpha, x, y;
10406
10407   if (preview==NULL) return; /* I usually add this when I want */
10408                              /* to avoid silly crashes. You    */
10409                              /* should probably make sure that */
10410                              /* everything has been nicely     */
10411                              /* initialized!                   */
10412   for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape?  */
10413                                          /* glib.h contains ABS(x).   */
10414         row[i*3+0] = sqrt(1-r)*255;      /* Define Red                */
10415         row[i*3+1] = 128;                /* Define Green              */
10416         row[i*3+2] = 224;                /* Define Blue               */
10417       }                                  /* "+0" is for alignment!    */
10418       else {
10419         row[i*3+0] = r*255;
10420         row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255;
10421         row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255;
10422       }
10423     }
10424     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE);
10425     /* Insert "row" into "preview" starting at the point with  */
10426     /* coordinates (0,j) first column, j_th row extending SIZE */
10427     /* pixels to the right */
10428   }
10429
10430   free(row); /* save some space */
10431   gtk_widget_draw(preview,NULL); /* what does this do? */
10432   gdk_flush(); /* or this? */
10433 }
10434
10435 Non-GIMP users can have probably seen enough to do a lot of things already.
10436 For the GIMP users I have a few pointers to add.
10437
10438 Image Preview
10439
10440 It is probably wise to keep a reduced version of the image around with just
10441 enough pixels to fill the preview. This is done by selecting every n'th
10442 pixel where n is the ratio of the size of the image to the size of the
10443 preview. All further operations (including filling in the previews) are then
10444 performed on the reduced number of pixels only. The following is my
10445 implementation of reducing the image. (Keep in mind that I've had only basic
10446 C!)
10447
10448 (UNTESTED CODE ALERT!!!)
10449
10450 typedef struct {
10451   gint      width;
10452   gint      height;
10453   gint      bbp;
10454   guchar    *rgb;
10455   guchar    *mask;
10456 } ReducedImage;
10457
10458 enum {
10459   SELECTION_ONLY,
10460   SELECTION_IN_CONTEXT,
10461   ENTIRE_IMAGE
10462 };
10463
10464 ReducedImage *Reduce_The_Image(GDrawable *drawable,
10465                                GDrawable *mask,
10466                                gint LongerSize,
10467                                gint Selection)
10468 {
10469   /* This function reduced the image down to the the selected preview size */
10470   /* The preview size is determine by LongerSize, i.e., the greater of the  */
10471   /* two dimensions. Works for RGB images only!                            */
10472   gint RH, RW;          /* Reduced height and reduced width                */
10473   gint width, height;   /* Width and Height of the area being reduced      */
10474   gint bytes=drawable->bpp;
10475   ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage));
10476
10477   guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B;
10478   gint i, j, whichcol, whichrow, x1, x2, y1, y2;
10479   GPixelRgn srcPR, srcMask;
10480   gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire  */
10481                              /* image.                                     */
10482
10483   gimp_drawable_mask_bounds (drawable->id, &amp;x1, &amp;y1, &amp;x2, &amp;y2);
10484   width  = x2-x1;
10485   height = y2-y1;
10486   /* If there's a SELECTION, we got its bounds!)
10487
10488   if (width != drawable->width &amp;&amp; height != drawable->height)
10489     NoSelectionMade=FALSE;
10490   /* Become aware of whether the user has made an active selection   */
10491   /* This will become important later, when creating a reduced mask. */
10492
10493   /* If we want to preview the entire image, overrule the above!  */
10494   /* Of course, if no selection has been made, this does nothing! */
10495   if (Selection==ENTIRE_IMAGE) {
10496     x1=0;
10497     x2=drawable->width;
10498     y1=0;
10499     y2=drawable->height;
10500   }
10501
10502   /* If we want to preview a selection with some surrounding area we */
10503   /* have to expand it a little bit. Consider it a bit of a riddle. */
10504   if (Selection==SELECTION_IN_CONTEXT) {
10505     x1=MAX(0,                x1-width/2.0);
10506     x2=MIN(drawable->width,  x2+width/2.0);
10507     y1=MAX(0,                y1-height/2.0);
10508     y2=MIN(drawable->height, y2+height/2.0);
10509   }
10510
10511   /* How we can determine the width and the height of the area being */
10512   /* reduced.                                                        */
10513   width  = x2-x1;
10514   height = y2-y1;
10515
10516   /* The lines below determine which dimension is to be the longer   */
10517   /* side. The idea borrowed from the supernova plug-in. I suspect I */
10518   /* could've thought of it myself, but the truth must be told.      */
10519   /* Plagiarism stinks!                                               */
10520   if (width>height) {
10521     RW=LongerSize;
10522     RH=(float) height * (float) LongerSize/ (float) width;
10523   }
10524   else {
10525     RH=LongerSize;
10526     RW=(float)width * (float) LongerSize/ (float) height;
10527   }
10528
10529   /* The entire image is stretched into a string! */
10530   tempRGB   = (guchar *) malloc(RW*RH*bytes);
10531   tempmask  = (guchar *) malloc(RW*RH);
10532
10533   gimp_pixel_rgn_init (&amp;srcPR, drawable, x1, y1, width, height,
10534                        FALSE, FALSE);
10535   gimp_pixel_rgn_init (&amp;srcMask, mask, x1, y1, width, height,
10536                        FALSE, FALSE);
10537
10538   /* Grab enough to save a row of image and a row of mask. */
10539   src_row       = (guchar *) malloc (width*bytes);
10540   src_mask_row  = (guchar *) malloc (width);
10541
10542   for (i=0; i < RH; i++) {
10543     whichrow=(float)i*(float)height/(float)RH;
10544     gimp_pixel_rgn_get_row (&amp;srcPR, src_row, x1, y1+whichrow, width);
10545     gimp_pixel_rgn_get_row (&amp;srcMask, src_mask_row, x1, y1+whichrow, width);
10546
10547     for (j=0; j < RW; j++) {
10548       whichcol=(float)j*(float)width/(float)RW;
10549
10550       /* No selection made = each point is completely selected! */
10551       if (NoSelectionMade)
10552         tempmask[i*RW+j]=255;
10553       else
10554         tempmask[i*RW+j]=src_mask_row[whichcol];
10555
10556       /* Add the row to the one long string which now contains the image! */
10557       tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0];
10558       tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1];
10559       tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2];
10560
10561       /* Hold on to the alpha as well */
10562       if (bytes==4)
10563         tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3];
10564     }
10565   }
10566   temp->bpp=bytes;
10567   temp->width=RW;
10568   temp->height=RH;
10569   temp->rgb=tempRGB;
10570   temp->mask=tempmask;
10571   return temp;
10572 }
10573
10574 The following is a preview function which used the same ReducedImage type!
10575 Note that it uses fakes transparency (if one is present by means of
10576 fake_transparency which is defined as follows:
10577
10578 gint fake_transparency(gint i, gint j)
10579 {
10580   if ( ((i%20)- 10) * ((j%20)- 10)>0   )
10581     return 64;
10582   else
10583     return 196;
10584 }
10585
10586 Now here's the preview function:
10587
10588 void
10589 my_preview_render_function(GtkWidget     *preview,
10590                            gint          changewhat,
10591                            gint          changewhich)
10592 {
10593   gint Inten, bytes=drawable->bpp;
10594   gint i, j, k;
10595   float partial;
10596   gint RW=reduced->width;
10597   gint RH=reduced->height;
10598   guchar *row=malloc(bytes*RW);;
10599
10600
10601   for (i=0; i < RH; i++) {
10602     for (j=0; j < RW; j++) {
10603
10604       row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0];
10605       row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1];
10606       row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2];
10607
10608       if (bytes==4)
10609         for (k=0; k<3; k++) {
10610           float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0;
10611           row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j);
10612         }
10613     }
10614     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW);
10615   }
10616
10617   free(a);
10618   gtk_widget_draw(preview,NULL);
10619   gdk_flush();
10620 }
10621
10622 Applicable Routines
10623
10624 guint           gtk_preview_get_type           (void);
10625 /* No idea */
10626 void            gtk_preview_uninit             (void);
10627 /* No idea */
10628 GtkWidget*      gtk_preview_new                (GtkPreviewType   type);
10629 /* Described above */
10630 void            gtk_preview_size               (GtkPreview      *preview,
10631                                                 gint             width,
10632                                                 gint             height);
10633 /* Allows you to resize an existing preview.    */
10634 /* Apparently there's a bug in GTK which makes  */
10635 /* this process messy. A way to clean up a mess */
10636 /* is to manually resize the window containing  */
10637 /* the preview after resizing the preview.      */
10638
10639 void            gtk_preview_put                (GtkPreview      *preview,
10640                                                 GdkWindow       *window,
10641                                                 GdkGC           *gc,
10642                                                 gint             srcx,
10643                                                 gint             srcy,
10644                                                 gint             destx,
10645                                                 gint             desty,
10646                                                 gint             width,
10647                                                 gint             height);
10648 /* No idea */
10649
10650 void            gtk_preview_put_row            (GtkPreview      *preview,
10651                                                 guchar          *src,
10652                                                 guchar          *dest,
10653                                                 gint             x,
10654                                                 gint             y,
10655                                                 gint             w);
10656 /* No idea */
10657
10658 void            gtk_preview_draw_row           (GtkPreview      *preview,
10659                                                 guchar          *data,
10660                                                 gint             x,
10661                                                 gint             y,
10662                                                 gint             w);
10663 /* Described in the text */
10664
10665 void            gtk_preview_set_expand         (GtkPreview      *preview,
10666                                                 gint             expand);
10667 /* No idea */
10668
10669 /* No clue for any of the below but    */
10670 /* should be standard for most widgets */
10671 void            gtk_preview_set_gamma          (double           gamma);
10672 void            gtk_preview_set_color_cube     (guint            nred_shades,
10673                                                 guint            ngreen_shades,
10674                                                 guint            nblue_shades,
10675                                                 guint            ngray_shades);
10676 void            gtk_preview_set_install_cmap   (gint             install_cmap);
10677 void            gtk_preview_set_reserved       (gint             nreserved);
10678 GdkVisual*      gtk_preview_get_visual         (void);
10679 GdkColormap*    gtk_preview_get_cmap           (void);
10680 GtkPreviewInfo* gtk_preview_get_info           (void);
10681
10682 That's all, folks!
10683
10684 </verb></tscreen>
10685
10686 -->
10687
10688 <!-- ***************************************************************** -->
10689 <sect>Setting Widget Attributes<label id="sec_setting_widget_attributes">
10690 <!-- ***************************************************************** -->
10691 <p>
10692 This describes the functions used to operate on widgets. These can be
10693 used to set style, padding, size, etc.
10694
10695 (Maybe I should make a whole section on accelerators.)
10696
10697 <tscreen><verb>
10698 void gtk_widget_install_accelerator( GtkWidget           *widget,
10699                                      GtkAcceleratorTable *table,
10700                                      gchar               *signal_name,
10701                                      gchar                key,
10702                                      guint8               modifiers );
10703
10704 void gtk_widget_remove_accelerator ( GtkWidget           *widget,
10705                                      GtkAcceleratorTable *table,
10706                                      gchar               *signal_name);
10707
10708 void gtk_widget_activate( GtkWidget *widget );
10709
10710 void gtk_widget_set_name( GtkWidget *widget,
10711                           gchar     *name );
10712
10713 gchar *gtk_widget_get_name( GtkWidget *widget );
10714
10715 void gtk_widget_set_sensitive( GtkWidget *widget,
10716                                gint       sensitive );
10717
10718 void gtk_widget_set_style( GtkWidget *widget,
10719                            GtkStyle  *style );
10720                                            
10721 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
10722
10723 GtkStyle *gtk_widget_get_default_style( void );
10724
10725 void gtk_widget_set_uposition( GtkWidget *widget,
10726                                gint       x,
10727                                gint       y );
10728
10729 void gtk_widget_set_usize( GtkWidget *widget,
10730                            gint       width,
10731                            gint       height );
10732
10733 void gtk_widget_grab_focus( GtkWidget *widget );
10734
10735 void gtk_widget_show( GtkWidget *widget );
10736
10737 void gtk_widget_hide( GtkWidget *widget );
10738 </verb></tscreen>
10739
10740 <!-- ***************************************************************** -->
10741 <sect>Timeouts, IO and Idle Functions<label id="sec_timeouts">
10742 <!-- ***************************************************************** -->
10743
10744 <!-- ----------------------------------------------------------------- -->
10745 <sect1>Timeouts
10746 <p>
10747 You may be wondering how you make GTK do useful work when in gtk_main.
10748 Well, you have several options. Using the following function you can
10749 create a timeout function that will be called every "interval"
10750 milliseconds.
10751
10752 <tscreen><verb>
10753 gint gtk_timeout_add( guint32     interval,
10754                       GtkFunction function,
10755                       gpointer    data );
10756 </verb></tscreen>
10757
10758 The first argument is the number of milliseconds between calls to your
10759 function. The second argument is the function you wish to have called,
10760 and the third, the data passed to this callback function. The return
10761 value is an integer "tag" which may be used to stop the timeout by
10762 calling:
10763
10764 <tscreen><verb>
10765 void gtk_timeout_remove( gint tag );
10766 </verb></tscreen>
10767
10768 You may also stop the timeout function by returning zero or FALSE from
10769 your callback function. Obviously this means if you want your function
10770 to continue to be called, it should return a non-zero value,
10771 i.e., TRUE.
10772
10773 The declaration of your callback should look something like this:
10774
10775 <tscreen><verb>
10776 gint timeout_callback( gpointer data );
10777 </verb></tscreen>
10778
10779 <!-- ----------------------------------------------------------------- -->
10780 <sect1>Monitoring IO
10781 <p>
10782 A nifty feature of GDK (the library that underlies GTK), is the
10783 ability to have it check for data on a file descriptor for you (as
10784 returned by open(2) or socket(2)). This is especially useful for
10785 networking applications. The function:
10786
10787 <tscreen><verb>
10788 gint gdk_input_add( gint              source,
10789                     GdkInputCondition condition,
10790                     GdkInputFunction  function,
10791                     gpointer          data );
10792 </verb></tscreen>
10793
10794 Where the first argument is the file descriptor you wish to have
10795 watched, and the second specifies what you want GDK to look for. This
10796 may be one of:
10797
10798 <itemize>
10799 <item><tt/GDK_INPUT_READ/ - Call your function when there is data
10800 ready for reading on your file descriptor.
10801
10802 <item>><tt/GDK_INPUT_WRITE/ - Call your function when the file
10803 descriptor is ready for writing.
10804 </itemize>
10805
10806 As I'm sure you've figured out already, the third argument is the
10807 function you wish to have called when the above conditions are
10808 satisfied, and the fourth is the data to pass to this function.
10809
10810 The return value is a tag that may be used to stop GDK from monitoring
10811 this file descriptor using the following function.
10812
10813 <tscreen><verb>
10814 void gdk_input_remove( gint tag );
10815 </verb></tscreen>
10816
10817 The callback function should be declared as:
10818
10819 <tscreen><verb>
10820 void input_callback( gpointer          data,
10821                      gint              source, 
10822                      GdkInputCondition condition );
10823 </verb></tscreen>
10824
10825 Where <tt/source/ and <tt/condition/ are as specified above.
10826
10827 <!-- ----------------------------------------------------------------- -->
10828 <sect1>Idle Functions
10829 <p>
10830 <!-- TODO: Need to check on idle priorities - TRG -->
10831 What if you have a function which you want to be called when nothing
10832 else is happening ?
10833
10834 <tscreen><verb>
10835 gint gtk_idle_add( GtkFunction function,
10836                    gpointer    data );
10837 </verb></tscreen>
10838
10839 This causes GTK to call the specified function whenever nothing else
10840 is happening.
10841
10842 <tscreen><verb>
10843 void gtk_idle_remove( gint tag );
10844 </verb></tscreen>
10845
10846 I won't explain the meaning of the arguments as they follow very much
10847 like the ones above. The function pointed to by the first argument to
10848 gtk_idle_add will be called whenever the opportunity arises. As with
10849 the others, returning FALSE will stop the idle function from being
10850 called.
10851
10852 <!-- ***************************************************************** -->
10853 <sect>Advanced Event and Signal Handling<label id="sec_Adv_Events_and_Signals">
10854 <!-- ***************************************************************** -->
10855
10856 <!-- ----------------------------------------------------------------- -->
10857 <sect1>Signal Functions
10858
10859 <!-- ----------------------------------------------------------------- -->
10860 <sect2>Connecting and Disconnecting Signal Handlers
10861 <p>
10862
10863 <tscreen><verb>
10864 guint gtk_signal_connect( GtkObject     *object,
10865                           const gchar   *name,
10866                           GtkSignalFunc  func,
10867                           gpointer       func_data );
10868
10869 guint gtk_signal_connect_after( GtkObject     *object,
10870                                 const gchar   *name,
10871                                 GtkSignalFunc  func,
10872                                 gpointer       func_data );
10873
10874 guint gtk_signal_connect_object( GtkObject     *object,
10875                                  const gchar   *name,
10876                                  GtkSignalFunc  func,
10877                                  GtkObject     *slot_object );
10878
10879 guint gtk_signal_connect_object_after( GtkObject     *object,
10880                                        const gchar   *name,
10881                                        GtkSignalFunc  func,
10882                                        GtkObject     *slot_object );
10883
10884 guint gtk_signal_connect_full( GtkObject          *object,
10885                                const gchar        *name,
10886                                GtkSignalFunc       func,
10887                                GtkCallbackMarshal  marshal,
10888                                gpointer            data,
10889                                GtkDestroyNotify    destroy_func,
10890                                gint                object_signal,
10891                                gint                after );
10892
10893 guint gtk_signal_connect_interp( GtkObject          *object,
10894                                  const gchar        *name,
10895                                  GtkCallbackMarshal  func,
10896                                  gpointer            data,
10897                                  GtkDestroyNotify    destroy_func,
10898                                  gint                after );
10899
10900 void gtk_signal_connect_object_while_alive( GtkObject     *object,
10901                                             const gchar   *signal,
10902                                             GtkSignalFunc  func,
10903                                             GtkObject     *alive_object );
10904
10905 void gtk_signal_connect_while_alive( GtkObject     *object,
10906                                      const gchar   *signal,
10907                                      GtkSignalFunc  func,
10908                                      gpointer       func_data,
10909                                      GtkObject     *alive_object );
10910
10911 void gtk_signal_disconnect( GtkObject *object,
10912                             guint      handler_id );
10913
10914 void gtk_signal_disconnect_by_func( GtkObject     *object,
10915                                     GtkSignalFunc  func,
10916                                     gpointer       data );
10917 </verb></tscreen>
10918
10919 <!-- ----------------------------------------------------------------- -->
10920 <sect2>Blocking and Unblocking Signal Handlers
10921 <p>
10922 <tscreen><verb>
10923 void gtk_signal_handler_block( GtkObject *object,
10924                                guint      handler_id);
10925
10926 void gtk_signal_handler_block_by_func( GtkObject     *object,
10927                                        GtkSignalFunc  func,
10928                                        gpointer       data );
10929
10930 void gtk_signal_handler_block_by_data( GtkObject *object,
10931                                        gpointer   data );
10932
10933 void gtk_signal_handler_unblock( GtkObject *object,
10934                                  guint      handler_id );
10935
10936 void gtk_signal_handler_unblock_by_func( GtkObject     *object,
10937                                          GtkSignalFunc  func,
10938                                          gpointer       data );
10939
10940 void gtk_signal_handler_unblock_by_data( GtkObject *object,
10941                                          gpointer   data );
10942 </verb></tscreen>
10943
10944 <!-- ----------------------------------------------------------------- -->
10945 <sect2>Emitting and Stopping Signals
10946 <p>
10947 <tscreen><verb>
10948 void gtk_signal_emit( GtkObject *object,
10949                       guint      signal_id,
10950                       ... );
10951
10952 void gtk_signal_emit_by_name( GtkObject   *object,
10953                               const gchar *name,
10954                               ... );
10955
10956 void gtk_signal_emitv( GtkObject *object,
10957                        guint      signal_id,
10958                        GtkArg    *params );
10959
10960 void gtk_signal_emitv_by_name( GtkObject   *object,
10961                                const gchar *name,
10962                                GtkArg      *params );
10963
10964 guint gtk_signal_n_emissions( GtkObject *object,
10965                               guint      signal_id );
10966
10967 guint gtk_signal_n_emissions_by_name( GtkObject   *object,
10968                                       const gchar *name );
10969
10970 void gtk_signal_emit_stop( GtkObject *object,
10971                            guint      signal_id );
10972
10973 void gtk_signal_emit_stop_by_name( GtkObject   *object,
10974                                    const gchar *name );
10975 </verb></tscreen>
10976
10977 <!-- ----------------------------------------------------------------- -->
10978 <sect1>Signal Emission and Propagation
10979 <p>
10980 Signal emission is the process whereby GTK runs all handlers for a
10981 specific object and signal.
10982
10983 First, note that the return value from a signal emission is the return
10984 value of the <em>last</em> handler executed. Since event signals are
10985 all of type <tt/GTK_RUN_LAST/, this will be the default (GTK supplied)
10986 handler, unless you connect with gtk_signal_connect_after().
10987
10988 The way an event (say "button_press_event") is handled, is:
10989 <itemize>
10990 <item>Start with the widget where the event occured.
10991
10992 <item>Emit the generic "event" signal. If that signal handler returns
10993 a value of TRUE, stop all processing.
10994
10995 <item>Otherwise, emit a specific, "button_press_event" signal. If that
10996 returns TRUE, stop all processing.
10997
10998 <item>Otherwise, go to the widget's parent, and repeat the above two
10999 steps.
11000
11001 <item>Continue until some signal handler returns TRUE, or until the
11002 top-level widget is reached.
11003 </itemize>
11004
11005 Some consequences of the above are:
11006 <itemize>
11007 <item>Your handler's return value will have no effect if there is a
11008 default handler, unless you connect with gtk_signal_connect_after().
11009
11010 <item>To prevent the default handler from being run, you need to
11011 connect with gtk_signal_connect() and use
11012 gtk_signal_emit_stop_by_name() - the return value only affects whether
11013 the signal is propagated, not the current emission.
11014 </itemize>
11015
11016 <!-- ***************************************************************** -->
11017 <sect>Managing Selections
11018 <!-- ***************************************************************** -->
11019
11020 <!-- ----------------------------------------------------------------- -->
11021 <sect1> Overview
11022 <p>
11023 One type of interprocess communication supported by X and GTK is
11024 <em>selections</em>. A selection identifies a chunk of data, for
11025 instance, a portion of text, selected by the user in some fashion, for
11026 instance, by dragging with the mouse. Only one application on a
11027 display (the <em>owner</em>) can own a particular selection at one
11028 time, so when a selection is claimed by one application, the previous
11029 owner must indicate to the user that selection has been
11030 relinquished. Other applications can request the contents of a
11031 selection in different forms, called <em>targets</em>. There can be
11032 any number of selections, but most X applications only handle one, the
11033 <em>primary selection</em>.
11034
11035 In most cases, it isn't necessary for a GTK application to deal with
11036 selections itself. The standard widgets, such as the Entry widget,
11037 already have the capability to claim the selection when appropriate
11038 (e.g., when the user drags over text), and to retrieve the contents of
11039 the selection owned by another widget or another application (e.g.,
11040 when the user clicks the second mouse button). However, there may be
11041 cases in which you want to give other widgets the ability to supply
11042 the selection, or you wish to retrieve targets not supported by
11043 default.
11044
11045 A fundamental concept needed to understand selection handling is that
11046 of the <em>atom</em>. An atom is an integer that uniquely identifies a
11047 string (on a certain display). Certain atoms are predefined by the X
11048 server, and in some cases there are constants in <tt>gtk.h</tt>
11049 corresponding to these atoms. For instance the constant
11050 <tt>GDK_PRIMARY_SELECTION</tt> corresponds to the string "PRIMARY".
11051 In other cases, you should use the functions
11052 <tt>gdk_atom_intern()</tt>, to get the atom corresponding to a string,
11053 and <tt>gdk_atom_name()</tt>, to get the name of an atom. Both
11054 selections and targets are identified by atoms.
11055
11056 <!-- ----------------------------------------------------------------- -->
11057 <sect1> Retrieving the selection
11058 <p>
11059 Retrieving the selection is an asynchronous process. To start the
11060 process, you call:
11061
11062 <tscreen><verb>
11063 gint gtk_selection_convert( GtkWidget *widget, 
11064                             GdkAtom    selection, 
11065                             GdkAtom    target,
11066                             guint32    time );
11067 </verb</tscreen>
11068
11069 This <em>converts</em> the selection into the form specified by
11070 <tt/target/. If at all possible, the time field should be the time
11071 from the event that triggered the selection. This helps make sure that
11072 events occur in the order that the user requested them. However, if it
11073 is not available (for instance, if the conversion was triggered by a
11074 "clicked" signal), then you can use the constant
11075 <tt>GDK_CURRENT_TIME</tt>.
11076
11077 When the selection owner responds to the request, a
11078 "selection_received" signal is sent to your application. The handler
11079 for this signal receives a pointer to a <tt>GtkSelectionData</tt>
11080 structure, which is defined as:
11081
11082 <tscreen><verb>
11083 struct _GtkSelectionData
11084 {
11085   GdkAtom selection;
11086   GdkAtom target;
11087   GdkAtom type;
11088   gint    format;
11089   guchar *data;
11090   gint    length;
11091 };
11092 </verb></tscreen>
11093
11094 <tt>selection</tt> and <tt>target</tt> are the values you gave in your
11095 <tt>gtk_selection_convert()</tt> call. <tt>type</tt> is an atom that
11096 identifies the type of data returned by the selection owner. Some
11097 possible values are "STRING", a string of latin-1 characters, "ATOM",
11098 a series of atoms, "INTEGER", an integer, etc. Most targets can only
11099 return one type. <tt/format/ gives the length of the units (for
11100 instance characters) in bits. Usually, you don't care about this when
11101 receiving data. <tt>data</tt> is a pointer to the returned data, and
11102 <tt>length</tt> gives the length of the returned data, in bytes. If
11103 <tt>length</tt> is negative, then an error occurred and the selection
11104 could not be retrieved. This might happen if no application owned the
11105 selection, or if you requested a target that the application didn't
11106 support. The buffer is actually guaranteed to be one byte longer than
11107 <tt>length</tt>; the extra byte will always be zero, so it isn't
11108 necessary to make a copy of strings just to null terminate them.
11109
11110 In the following example, we retrieve the special target "TARGETS",
11111 which is a list of all targets into which the selection can be
11112 converted.
11113
11114 <tscreen><verb>
11115 /* example-start selection gettargets.c */
11116
11117 #include <gtk/gtk.h>
11118
11119 void selection_received (GtkWidget *widget, 
11120                          GtkSelectionData *selection_data, 
11121                          gpointer data);
11122
11123 /* Signal handler invoked when user clicks on the "Get Targets" button */
11124 void
11125 get_targets (GtkWidget *widget, gpointer data)
11126 {
11127   static GdkAtom targets_atom = GDK_NONE;
11128
11129   /* Get the atom corresponding to the string "TARGETS" */
11130   if (targets_atom == GDK_NONE)
11131     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
11132
11133   /* And request the "TARGETS" target for the primary selection */
11134   gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
11135                          GDK_CURRENT_TIME);
11136 }
11137
11138 /* Signal handler called when the selections owner returns the data */
11139 void
11140 selection_received (GtkWidget *widget, GtkSelectionData *selection_data, 
11141                     gpointer data)
11142 {
11143   GdkAtom *atoms;
11144   GList *item_list;
11145   int i;
11146
11147   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
11148   if (selection_data->length < 0)
11149     {
11150       g_print ("Selection retrieval failed\n");
11151       return;
11152     }
11153   /* Make sure we got the data in the expected form */
11154   if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
11155     {
11156       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
11157       return;
11158     }
11159   
11160   /* Print out the atoms we received */
11161   atoms = (GdkAtom *)selection_data->data;
11162
11163   item_list = NULL;
11164   for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
11165     {
11166       char *name;
11167       name = gdk_atom_name (atoms[i]);
11168       if (name != NULL)
11169         g_print ("%s\n",name);
11170       else
11171         g_print ("(bad atom)\n");
11172     }
11173
11174   return;
11175 }
11176
11177 int 
11178 main (int argc, char *argv[])
11179 {
11180   GtkWidget *window;
11181   GtkWidget *button;
11182   
11183   gtk_init (&amp;argc, &amp;argv);
11184
11185   /* Create the toplevel window */
11186
11187   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11188   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
11189   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11190
11191   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11192                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11193
11194   /* Create a button the user can click to get targets */
11195
11196   button = gtk_button_new_with_label ("Get Targets");
11197   gtk_container_add (GTK_CONTAINER (window), button);
11198
11199   gtk_signal_connect (GTK_OBJECT(button), "clicked",
11200                       GTK_SIGNAL_FUNC (get_targets), NULL);
11201   gtk_signal_connect (GTK_OBJECT(button), "selection_received",
11202                       GTK_SIGNAL_FUNC (selection_received), NULL);
11203
11204   gtk_widget_show (button);
11205   gtk_widget_show (window);
11206   
11207   gtk_main ();
11208   
11209   return 0;
11210 }
11211 /* example-end */
11212 </verb></tscreen>
11213
11214 <!-- ----------------------------------------------------------------- -->
11215 <sect1> Supplying the selection 
11216 <p>
11217 Supplying the selection is a bit more complicated. You must register 
11218 handlers that will be called when your selection is requested. For
11219 each selection/target pair you will handle, you make a call to:
11220
11221 <tscreen><verb>
11222 void gtk_selection_add_handler( GtkWidget            *widget, 
11223                                 GdkAtom               selection,
11224                                 GdkAtom               target,
11225                                 GtkSelectionFunction  function,
11226                                 GtkRemoveFunction     remove_func,
11227                                 gpointer              data );
11228 </verb></tscreen>
11229
11230 <tt/widget/, <tt/selection/, and <tt/target/ identify the requests
11231 this handler will manage.  <tt/remove_func/, if not
11232 NULL, will be called when the signal handler is removed. This is
11233 useful, for instance, for interpreted languages which need to
11234 keep track of a reference count for <tt/data/.
11235
11236 The callback function has the signature:
11237
11238 <tscreen><verb>
11239 typedef void (*GtkSelectionFunction)( GtkWidget        *widget, 
11240                                       GtkSelectionData *selection_data,
11241                                       gpointer          data );
11242
11243 </verb></tscreen>
11244
11245 The GtkSelectionData is the same as above, but this time, we're
11246 responsible for filling in the fields <tt/type/, <tt/format/,
11247 <tt/data/, and <tt/length/. (The <tt/format/ field is actually
11248 important here - the X server uses it to figure out whether the data
11249 needs to be byte-swapped or not. Usually it will be 8 - <em/i.e./ a
11250 character - or 32 - <em/i.e./ a. integer.) This is done by calling the
11251 function:
11252
11253 <tscreen><verb>
11254 void gtk_selection_data_set( GtkSelectionData *selection_data,
11255                              GdkAtom           type,
11256                              gint              format,
11257                              guchar           *data,
11258                              gint              length );
11259 </verb></tscreen>
11260
11261 This function takes care of properly making a copy of the data so that
11262 you don't have to worry about keeping it around. (You should not fill
11263 in the fields of the GtkSelectionData structure by hand.)
11264
11265 When prompted by the user, you claim ownership of the selection by
11266 calling:
11267
11268 <tscreen><verb>
11269 gint gtk_selection_owner_set( GtkWidget *widget,
11270                               GdkAtom    selection,
11271                               guint32    time );
11272 </verb></tscreen>
11273
11274 If another application claims ownership of the selection, you will
11275 receive a "selection_clear_event".
11276
11277 As an example of supplying the selection, the following program adds
11278 selection functionality to a toggle button. When the toggle button is
11279 depressed, the program claims the primary selection. The only target
11280 supported (aside from certain targets like "TARGETS" supplied by GTK
11281 itself), is the "STRING" target. When this target is requested, a
11282 string representation of the time is returned.
11283
11284 <tscreen><verb>
11285 /* example-start selection setselection.c */
11286
11287 #include <gtk/gtk.h>
11288 #include <time.h>
11289
11290 /* Callback when the user toggles the selection */
11291 void
11292 selection_toggled (GtkWidget *widget, gint *have_selection)
11293 {
11294   if (GTK_TOGGLE_BUTTON(widget)->active)
11295     {
11296       *have_selection = gtk_selection_owner_set (widget,
11297                                                  GDK_SELECTION_PRIMARY,
11298                                                  GDK_CURRENT_TIME);
11299       /* if claiming the selection failed, we return the button to
11300          the out state */
11301       if (!*have_selection)
11302         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
11303     }
11304   else
11305     {
11306       if (*have_selection)
11307         {
11308           /* Before clearing the selection by setting the owner to NULL,
11309              we check if we are the actual owner */
11310           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
11311             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
11312                                      GDK_CURRENT_TIME);
11313           *have_selection = FALSE;
11314         }
11315     }
11316 }
11317
11318 /* Called when another application claims the selection */
11319 gint
11320 selection_clear (GtkWidget *widget, GdkEventSelection *event,
11321                  gint *have_selection)
11322 {
11323   *have_selection = FALSE;
11324   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
11325
11326   return TRUE;
11327 }
11328
11329 /* Supplies the current time as the selection. */
11330 void
11331 selection_handle (GtkWidget *widget, 
11332                   GtkSelectionData *selection_data,
11333                   gpointer data)
11334 {
11335   gchar *timestr;
11336   time_t current_time;
11337
11338   current_time = time (NULL);
11339   timestr = asctime (localtime(&amp;current_time)); 
11340   /* When we return a single string, it should not be null terminated.
11341      That will be done for us */
11342
11343   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
11344                           8, timestr, strlen(timestr));
11345 }
11346
11347 int
11348 main (int argc, char *argv[])
11349 {
11350   GtkWidget *window;
11351
11352   GtkWidget *selection_button;
11353
11354   static int have_selection = FALSE;
11355   
11356   gtk_init (&amp;argc, &amp;argv);
11357
11358   /* Create the toplevel window */
11359
11360   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11361   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
11362   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11363
11364   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11365                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11366
11367   /* Create a toggle button to act as the selection */
11368
11369   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
11370   gtk_container_add (GTK_CONTAINER (window), selection_button);
11371   gtk_widget_show (selection_button);
11372
11373   gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
11374                       GTK_SIGNAL_FUNC (selection_toggled), &amp;have_selection);
11375   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
11376                       GTK_SIGNAL_FUNC (selection_clear), &amp;have_selection);
11377
11378   gtk_selection_add_handler (selection_button, GDK_SELECTION_PRIMARY,
11379                              GDK_SELECTION_TYPE_STRING,
11380                              selection_handle, NULL);
11381
11382   gtk_widget_show (selection_button);
11383   gtk_widget_show (window);
11384   
11385   gtk_main ();
11386   
11387   return 0;
11388 }
11389 /* example-end */
11390 </verb></tscreen>
11391
11392
11393 <!-- ***************************************************************** -->
11394 <sect>GLib<label id="sec_glib">
11395 <!-- ***************************************************************** -->
11396 <p>
11397 GLib is a lower-level library that provides many useful definitions
11398 and functions available for use when creating GDK and GTK
11399 applications. These include definitions for basic types and their
11400 limits, standard macros, type conversions, byte order, memory
11401 allocation, warnings and assertions, message logging, timers, string
11402 utilities, hook functions, a lexical scanner, dynamic loading of
11403 modules, and automatic string completion. A number of data structures
11404 (and their related operations) are also defined, including memory
11405 chunks, doubly-linked lists, singly-linked lists, hash tables, strings
11406 (which can grow dynamically), string chunks (groups of strings),
11407 arrays (which can grow in size as elements are added), balanced binary
11408 trees, N-ary trees, quarks (a two-way association of a string and a
11409 unique integer identifier), keyed data lists (lists of data elements
11410 accessible by a string or integer id), relations and tuples (tables of
11411 data which can be indexed on any number of fields), and caches.
11412
11413 A summary of some of GLib's capabilities follows; not every function,
11414 data structure, or operation is covered here.  For more complete
11415 information about the GLib routines, see the GLib documentation. One
11416 source of GLib documentation is <htmlurl url="http://www.gtk.org/"
11417 name="http://www.gtk.org/">.
11418
11419 If you are using a language other than C, you should consult your
11420 language's binding documentation. In some cases your language may
11421 have equivalent functionality built-in, while in other cases it may
11422 not.
11423
11424 <!-- ----------------------------------------------------------------- -->
11425 <sect1>Definitions
11426 <p>
11427 Definitions for the extremes of many of the standard types are:
11428
11429 <tscreen><verb>
11430 G_MINFLOAT
11431 G_MAXFLOAT
11432 G_MINDOUBLE
11433 G_MAXDOUBLE
11434 G_MINSHORT
11435 G_MAXSHORT
11436 G_MININT
11437 G_MAXINT
11438 G_MINLONG
11439 G_MAXLONG
11440 </verb></tscreen>
11441
11442 Also, the following typedefs. The ones left unspecified are dynamically set
11443 depending on the architecture. Remember to avoid counting on the size of a
11444 pointer if you want to be portable! E.g., a pointer on an Alpha is 8
11445 bytes, but 4 on Intel 80x86 family CPUs.
11446
11447 <tscreen><verb>
11448 char   gchar;
11449 short  gshort;
11450 long   glong;
11451 int    gint;
11452 char   gboolean;
11453
11454 unsigned char   guchar;
11455 unsigned short  gushort;
11456 unsigned long   gulong;
11457 unsigned int    guint;
11458
11459 float   gfloat;
11460 double  gdouble;
11461 long double gldouble;
11462
11463 void* gpointer;
11464
11465 gint8
11466 guint8
11467 gint16
11468 guint16
11469 gint32
11470 guint32
11471 </verb></tscreen>
11472
11473 <!-- ----------------------------------------------------------------- -->
11474 <sect1>Doubly Linked Lists
11475 <p>
11476 The following functions are used to create, manage, and destroy
11477 standard doubly linked lists. Each element in the list contains a
11478 piece of data, together with pointers which link to the previous and
11479 next elements in the list. This enables easy movement in either
11480 direction through the list. The data item is of type "gpointer",
11481 which means the data can be a pointer to your real data or (through
11482 casting) a numeric value (but do not assume that int and gpointer have
11483 the same size!). These routines internally allocate list elements in
11484 blocks, which is more efficient than allocating elements individually.
11485
11486 There is no function to specifically create a list. Instead, simply
11487 create a variable of type GList* and set its value to NULL; NULL is
11488 considered to be the empty list.
11489
11490 To add elements to a list, use the g_list_append(), g_list_prepend(),
11491 g_list_insert(), or g_list_insert_sorted() routines. In all cases
11492 they accept a pointer to the beginning of the list, and return the
11493 (possibly changed) pointer to the beginning of the list. Thus, for
11494 all of the operations that add or remove elements, be sure to save the
11495 returned value!
11496
11497 <tscreen><verb>
11498 GList *g_list_append( GList    *list,
11499                       gpointer  data );
11500 </verb></tscreen>
11501
11502 This adds a new element (with value <tt/data/) onto the end of the
11503 list.
11504   
11505 <tscreen><verb>    
11506 GList *g_list_prepend( GList    *list,
11507                        gpointer  data );
11508 </verb></tscreen>
11509
11510 This adds a new element (with value <tt/data/) to the beginning of the
11511 list.
11512
11513 <tscreen><verb>         
11514 GList *g_list_insert( GList    *list,
11515                       gpointer  data,
11516                       gint      position );
11517
11518 </verb></tscreen>
11519
11520 This inserts a new element (with value data) into the list at the
11521 given position. If position is 0, this is just like g_list_prepend();
11522 if position is less than 0, this is just like g_list_append().
11523
11524 <tscreen><verb>
11525 GList *g_list_remove( GList    *list,
11526                       gpointer  data );
11527 </verb></tscreen>
11528
11529 This removes the element in the list with the value <tt/data/;
11530 if the element isn't there, the list is unchanged.
11531
11532 <tscreen><verb>
11533 void g_list_free( GList *list );
11534 </verb></tscreen>
11535
11536 This frees all of the memory used by a GList. If the list elements
11537 refer to dynamically-allocated memory, then they should be freed
11538 first.
11539
11540 There are many other GLib functions that support doubly linked lists;
11541 see the glib documentation for more information.  Here are a few of
11542 the more useful functions' signatures:
11543
11544 <tscreen><verb>            
11545 GList *g_list_remove_link( GList *list,
11546                            GList *link );
11547
11548 GList *g_list_reverse( GList *list );
11549
11550 GList *g_list_nth( GList *list,
11551                    gint   n );
11552                            
11553 GList *g_list_find( GList    *list,
11554                     gpointer  data );
11555
11556 GList *g_list_last( GList *list );
11557
11558 GList *g_list_first( GList *list );
11559
11560 gint g_list_length( GList *list );
11561
11562 void g_list_foreach( GList    *list,
11563                      GFunc     func,
11564                      gpointer  user_data );
11565 </verb></tscreen>                                             
11566
11567 <!-- ----------------------------------------------------------------- -->
11568 <sect1>Singly Linked Lists
11569 <p>
11570 Many of the above functions for singly linked lists are identical to the
11571 above. Here is a list of some of their operations:
11572
11573 <tscreen><verb>
11574 GSList *g_slist_append( GSList   *list,
11575                         gpointer  data );
11576                 
11577 GSList *g_slist_prepend( GSList   *list,
11578                          gpointer  data );
11579                              
11580 GSList *g_slist_insert( GSList   *list,
11581                         gpointer  data,
11582                         gint      position );
11583                              
11584 GSList *g_slist_remove( GSList   *list,
11585                         gpointer  data );
11586                              
11587 GSList *g_slist_remove_link( GSList *list,
11588                              GSList *link );
11589                              
11590 GSList *g_slist_reverse( GSList *list );
11591
11592 GSList *g_slist_nth( GSList *list,
11593                      gint    n );
11594                              
11595 GSList *g_slist_find( GSList   *list,
11596                       gpointer  data );
11597                              
11598 GSList *g_slist_last( GSList *list );
11599
11600 gint g_slist_length( GSList *list );
11601
11602 void g_slist_foreach( GSList   *list,
11603                       GFunc     func,
11604                       gpointer  user_data );
11605         
11606 </verb></tscreen>
11607
11608 <!-- ----------------------------------------------------------------- -->
11609 <sect1>Memory Management
11610 <p>
11611 <tscreen><verb>
11612 gpointer g_malloc( gulong size );
11613 </verb></tscreen>
11614
11615 This is a replacement for malloc(). You do not need to check the return
11616 value as it is done for you in this function. If the memory allocation
11617 fails for whatever reasons, your applications will be terminated.
11618
11619 <tscreen><verb>
11620 gpointer g_malloc0( gulong size );
11621 </verb></tscreen>
11622
11623 Same as above, but zeroes the memory before returning a pointer to it.
11624
11625 <tscreen><verb>
11626 gpointer g_realloc( gpointer mem,
11627                     gulong   size );
11628 </verb></tscreen>
11629
11630 Relocates "size" bytes of memory starting at "mem".  Obviously, the
11631 memory should have been previously allocated.
11632
11633 <tscreen><verb>
11634 void g_free( gpointer mem );
11635 </verb></tscreen>
11636
11637 Frees memory. Easy one. If <tt/mem/ is NULL it simply returns.
11638
11639 <tscreen><verb>
11640 void g_mem_profile( void );
11641 </verb></tscreen>
11642
11643 Dumps a profile of used memory, but requires that you add <tt>#define
11644 MEM_PROFILE</tt> to the top of glib/gmem.c and re-make and make install.
11645
11646 <tscreen><verb>
11647 void g_mem_check( gpointer mem );
11648 </verb></tscreen>
11649
11650 Checks that a memory location is valid. Requires you add <tt>#define
11651 MEM_CHECK</tt> to the top of gmem.c and re-make and make install.
11652
11653 <!-- ----------------------------------------------------------------- -->
11654 <sect1>Timers
11655 <p>
11656 Timer functions can be used to time operations (e.g., to see how much
11657 time has elapsed). First, you create a new timer with g_timer_new().
11658 You can then use g_timer_start() to start timing an operation,
11659 g_timer_stop() to stop timing an operation, and g_timer_elapsed() to
11660 determine the elapsed time.
11661
11662 <tscreen><verb>
11663 GTimer *g_timer_new( void );
11664
11665 void g_timer_destroy( GTimer *timer );
11666
11667 void g_timer_start( GTimer  *timer );
11668
11669 void g_timer_stop( GTimer  *timer );
11670
11671 void g_timer_reset( GTimer  *timer );
11672
11673 gdouble g_timer_elapsed( GTimer *timer,
11674                          gulong *microseconds );
11675 </verb></tscreen>                        
11676
11677 <!-- ----------------------------------------------------------------- -->
11678 <sect1>String Handling
11679 <p>
11680 GLib defines a new type called a GString, which is similar to a
11681 standard C string but one that grows automatically. Its string data
11682 is null-terminated. What this gives you is protection from buffer
11683 overflow programming errors within your program. This is a very
11684 important feature, and hence I recommend that you make use of
11685 GStrings. GString itself has a simple public definition:
11686
11687 <tscreen><verb>
11688 struct GString 
11689 {
11690   gchar *str; /* Points to the string's current \0-terminated value. */
11691   gint len; /* Current length */
11692 };
11693 </verb></tscreen>
11694
11695 As you might expect, there are a number of operations you can do with
11696 a GString.
11697
11698 <tscreen><verb>
11699 GString *g_string_new( gchar *init );
11700 </verb></tscreen>
11701
11702 This constructs a GString, copying the string value of <tt/init/
11703 into the GString and returning a pointer to it. NULL may be given as
11704 the argument for an initially empty GString.
11705  
11706 <tscreen><verb>
11707
11708 void g_string_free( GString *string,
11709                     gint     free_segment );
11710 </verb></tscreen>
11711
11712 This frees the memory for the given GString. If <tt/free_segment/ is
11713 TRUE, then this also frees its character data.
11714
11715 <tscreen><verb>
11716                              
11717 GString *g_string_assign( GString     *lval,
11718                           const gchar *rval );
11719 </verb></tscreen>
11720
11721 This copies the characters from rval into lval, destroying the
11722 previous contents of lval. Note that lval will be lengthened as
11723 necessary to hold the string's contents, unlike the standard strcpy()
11724 function.
11725
11726 The rest of these functions should be relatively obvious (the _c
11727 versions accept a character instead of a string):
11728
11729 <tscreen><verb>              
11730 GString *g_string_truncate( GString *string,
11731                             gint     len );
11732                              
11733 GString *g_string_append( GString *string,
11734                           gchar   *val );
11735                             
11736 GString *g_string_append_c( GString *string,
11737                             gchar    c );
11738         
11739 GString *g_string_prepend( GString *string,
11740                            gchar   *val );
11741                              
11742 GString *g_string_prepend_c( GString *string,
11743                              gchar    c );
11744         
11745 void g_string_sprintf( GString *string,
11746                        gchar   *fmt,
11747                        ...);
11748         
11749 void g_string_sprintfa ( GString *string,
11750                          gchar   *fmt,
11751                          ... );
11752 </verb></tscreen>                                                         
11753
11754 <!-- ----------------------------------------------------------------- -->
11755 <sect1>Utility and Error Functions
11756 <p>
11757 <tscreen><verb>
11758 gchar *g_strdup( const gchar *str );
11759 </verb></tscreen>
11760
11761 Replacement strdup function.  Copies the original strings contents to
11762 newly allocated memory, and returns a pointer to it.
11763
11764 <tscreen><verb>
11765 gchar *g_strerror( gint errnum );
11766 </verb></tscreen>
11767
11768 I recommend using this for all error messages.  It's much nicer, and more
11769 portable than perror() or others.  The output is usually of the form:
11770
11771 <tscreen><verb>
11772 program name:function that failed:file or further description:strerror
11773 </verb></tscreen>
11774
11775 Here's an example of one such call used in our hello_world program:
11776
11777 <tscreen><verb>
11778 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
11779 </verb></tscreen>
11780
11781 <tscreen><verb>
11782 void g_error( gchar *format, ... );
11783 </verb></tscreen>
11784
11785 Prints an error message. The format is just like printf, but it
11786 prepends "** ERROR **: " to your message, and exits the program.  
11787 Use only for fatal errors.
11788
11789 <tscreen><verb>
11790 void g_warning( gchar *format, ... );
11791 </verb></tscreen>
11792
11793 Same as above, but prepends "** WARNING **: ", and does not exit the
11794 program.
11795
11796 <tscreen><verb>
11797 void g_message( gchar *format, ... );
11798 </verb></tscreen>
11799
11800 Prints "message: " prepended to the string you pass in.
11801
11802 <tscreen><verb>
11803 void g_print( gchar *format, ... );
11804 </verb></tscreen>
11805
11806 Replacement for printf().
11807
11808 And our last function:
11809
11810 <tscreen><verb>
11811 gchar *g_strsignal( gint signum );
11812 </verb></tscreen>
11813
11814 Prints out the name of the Unix system signal given the signal number.
11815 Useful in generic signal handling functions.
11816
11817 All of the above are more or less just stolen from glib.h.  If anyone cares
11818 to document any function, just send me an email!
11819
11820 <!-- ***************************************************************** -->
11821 <sect>GTK's rc Files <label id="sec_gtkrc_files">
11822 <!-- ***************************************************************** -->
11823 <p>
11824 GTK has its own way of dealing with application defaults, by using rc
11825 files. These can be used to set the colors of just about any widget, and
11826 can also be used to tile pixmaps onto the background of some widgets.  
11827
11828 <!-- ----------------------------------------------------------------- -->
11829 <sect1>Functions For rc Files 
11830 <p>
11831 When your application starts, you should include a call to:
11832
11833 <tscreen><verb>
11834 void gtk_rc_parse( char *filename );
11835 </verb></tscreen>
11836
11837 Passing in the filename of your rc file. This will cause GTK to parse
11838 this file, and use the style settings for the widget types defined
11839 there.
11840
11841 If you wish to have a special set of widgets that can take on a
11842 different style from others, or any other logical division of widgets,
11843 use a call to:
11844
11845 <tscreen><verb>
11846 void gtk_widget_set_name( GtkWidget *widget,
11847                           gchar     *name );
11848 </verb></tscreen>
11849
11850 Passing your newly created widget as the first argument, and the name
11851 you wish to give it as the second. This will allow you to change the
11852 attributes of this widget by name through the rc file.
11853
11854 If we use a call something like this:
11855
11856 <tscreen><verb>
11857 button = gtk_button_new_with_label ("Special Button");
11858 gtk_widget_set_name (button, "special button");
11859 </verb></tscreen>
11860
11861 Then this button is given the name "special button" and may be addressed by
11862 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]
11863
11864 The example rc file below, sets the properties of the main window, and lets
11865 all children of that main window inherit the style described by the "main
11866 button" style.  The code used in the application is:
11867
11868 <tscreen><verb>
11869 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11870 gtk_widget_set_name (window, "main window");
11871 </verb></tscreen>
11872
11873 And then the style is defined in the rc file using:
11874
11875 <tscreen><verb>
11876 widget "main window.*GtkButton*" style "main_button"
11877 </verb></tscreen>
11878
11879 Which sets all the Button widgets in the "main window" to the
11880 "main_buttons" style as defined in the rc file.
11881
11882 As you can see, this is a fairly powerful and flexible system.  Use your
11883 imagination as to how best to take advantage of this.
11884
11885 <!-- ----------------------------------------------------------------- -->
11886 <sect1>GTK's rc File Format
11887 <p>
11888 The format of the GTK file is illustrated in the example below. This is
11889 the testgtkrc file from the GTK distribution, but I've added a
11890 few comments and things. You may wish to include this explanation in
11891 your application to allow the user to fine tune his application.
11892
11893 There are several directives to change the attributes of a widget.
11894
11895 <itemize>
11896 <item>fg - Sets the foreground color of a widget.
11897 <item>bg - Sets the background color of a widget.
11898 <item>bg_pixmap - Sets the background of a widget to a tiled pixmap.
11899 <item>font - Sets the font to be used with the given widget.
11900 </itemize>
11901
11902 In addition to this, there are several states a widget can be in, and you
11903 can set different colors, pixmaps and fonts for each state. These states are:
11904
11905 <itemize>
11906 <item>NORMAL - The normal state of a widget, without the mouse over top of
11907 it, and not being pressed, etc.
11908 <item>PRELIGHT - When the mouse is over top of the widget, colors defined
11909 using this state will be in effect.
11910 <item>ACTIVE - When the widget is pressed or clicked it will be active, and
11911 the attributes assigned by this tag will be in effect.
11912 <item>INSENSITIVE - When a widget is set insensitive, and cannot be
11913 activated, it will take these attributes.
11914 <item>SELECTED - When an object is selected, it takes these attributes.
11915 </itemize>
11916
11917 When using the "fg" and "bg" keywords to set the colors of widgets, the
11918 format is:
11919
11920 <tscreen><verb>
11921 fg[<STATE>] = { Red, Green, Blue }
11922 </verb></tscreen>
11923
11924 Where STATE is one of the above states (PRELIGHT, ACTIVE, etc), and the Red,
11925 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
11926 white. They must be in float form, or they will register as 0, so a straight 
11927 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
11928 doesn't matter if it's not recognized.  Unrecognized values are set to 0.
11929
11930 bg_pixmap is very similar to the above, except the colors are replaced by a
11931 filename.
11932
11933 pixmap_path is a list of paths separated by ":"'s.  These paths will be
11934 searched for any pixmap you specify.
11935
11936 The font directive is simply:
11937 <tscreen><verb>
11938 font = "<font name>"
11939 </verb></tscreen>
11940
11941 The only hard part is figuring out the font string. Using xfontsel or
11942 a similar utility should help.
11943
11944 The "widget_class" sets the style of a class of widgets. These classes are
11945 listed in the widget overview on the class hierarchy.
11946
11947 The "widget" directive sets a specifically named set of widgets to a
11948 given style, overriding any style set for the given widget class.
11949 These widgets are registered inside the application using the
11950 gtk_widget_set_name() call. This allows you to specify the attributes of a
11951 widget on a per widget basis, rather than setting the attributes of an
11952 entire widget class. I urge you to document any of these special widgets so
11953 users may customize them.
11954
11955 When the keyword <tt>parent</> is used as an attribute, the widget will take on
11956 the attributes of its parent in the application.
11957
11958 When defining a style, you may assign the attributes of a previously defined
11959 style to this new one.
11960
11961 <tscreen><verb>
11962 style "main_button" = "button"
11963 {
11964   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
11965   bg[PRELIGHT] = { 0.75, 0, 0 }
11966 }
11967 </verb></tscreen>
11968
11969 This example takes the "button" style, and creates a new "main_button" style
11970 simply by changing the font and prelight background color of the "button"
11971 style.
11972
11973 Of course, many of these attributes don't apply to all widgets. It's a
11974 simple matter of common sense really. Anything that could apply, should.
11975
11976 <!-- ----------------------------------------------------------------- -->
11977 <sect1>Example rc file
11978 <p>
11979
11980 <tscreen><verb>
11981 # pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
11982 #
11983 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
11984 #
11985 # style <name> [= <name>]
11986 # {
11987 #   <option>
11988 # }
11989 #
11990 # widget <widget_set> style <style_name>
11991 # widget_class <widget_class_set> style <style_name>
11992
11993
11994 # Here is a list of all the possible states.  Note that some do not apply to
11995 # certain widgets.
11996 #
11997 # NORMAL - The normal state of a widget, without the mouse over top of
11998 # it, and not being pressed, etc.
11999 #
12000 # PRELIGHT - When the mouse is over top of the widget, colors defined
12001 # using this state will be in effect.
12002 #
12003 # ACTIVE - When the widget is pressed or clicked it will be active, and
12004 # the attributes assigned by this tag will be in effect.
12005 #
12006 # INSENSITIVE - When a widget is set insensitive, and cannot be
12007 # activated, it will take these attributes.
12008 #
12009 # SELECTED - When an object is selected, it takes these attributes.
12010 #
12011 # Given these states, we can set the attributes of the widgets in each of
12012 # these states using the following directives.
12013 #
12014 # fg - Sets the foreground color of a widget.
12015 # fg - Sets the background color of a widget.
12016 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
12017 # font - Sets the font to be used with the given widget.
12018 #
12019
12020 # This sets a style called "button".  The name is not really important, as
12021 # it is assigned to the actual widgets at the bottom of the file.
12022
12023 style "window"
12024 {
12025   #This sets the padding around the window to the pixmap specified.
12026   #bg_pixmap[<STATE>] = "<pixmap filename>"
12027   bg_pixmap[NORMAL] = "warning.xpm"
12028 }
12029
12030 style "scale"
12031 {
12032   #Sets the foreground color (font color) to red when in the "NORMAL"
12033   #state.
12034   
12035   fg[NORMAL] = { 1.0, 0, 0 }
12036   
12037   #Sets the background pixmap of this widget to that of its parent.
12038   bg_pixmap[NORMAL] = "<parent>"
12039 }
12040
12041 style "button"
12042 {
12043   # This shows all the possible states for a button.  The only one that
12044   # doesn't apply is the SELECTED state.
12045   
12046   fg[PRELIGHT] = { 0, 1.0, 1.0 }
12047   bg[PRELIGHT] = { 0, 0, 1.0 }
12048   bg[ACTIVE] = { 1.0, 0, 0 }
12049   fg[ACTIVE] = { 0, 1.0, 0 }
12050   bg[NORMAL] = { 1.0, 1.0, 0 }
12051   fg[NORMAL] = { .99, 0, .99 }
12052   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
12053   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
12054 }
12055
12056 # In this example, we inherit the attributes of the "button" style and then
12057 # override the font and background color when prelit to create a new
12058 # "main_button" style.
12059
12060 style "main_button" = "button"
12061 {
12062   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
12063   bg[PRELIGHT] = { 0.75, 0, 0 }
12064 }
12065
12066 style "toggle_button" = "button"
12067 {
12068   fg[NORMAL] = { 1.0, 0, 0 }
12069   fg[ACTIVE] = { 1.0, 0, 0 }
12070   
12071   # This sets the background pixmap of the toggle_button to that of its
12072   # parent widget (as defined in the application).
12073   bg_pixmap[NORMAL] = "<parent>"
12074 }
12075
12076 style "text"
12077 {
12078   bg_pixmap[NORMAL] = "marble.xpm"
12079   fg[NORMAL] = { 1.0, 1.0, 1.0 }
12080 }
12081
12082 style "ruler"
12083 {
12084   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
12085 }
12086
12087 # pixmap_path "~/.pixmaps"
12088
12089 # These set the widget types to use the styles defined above.
12090 # The widget types are listed in the class hierarchy, but could probably be
12091 # just listed in this document for the users reference.
12092
12093 widget_class "GtkWindow" style "window"
12094 widget_class "GtkDialog" style "window"
12095 widget_class "GtkFileSelection" style "window"
12096 widget_class "*Gtk*Scale" style "scale"
12097 widget_class "*GtkCheckButton*" style "toggle_button"
12098 widget_class "*GtkRadioButton*" style "toggle_button"
12099 widget_class "*GtkButton*" style "button"
12100 widget_class "*Ruler" style "ruler"
12101 widget_class "*GtkText" style "text"
12102
12103 # This sets all the buttons that are children of the "main window" to
12104 # the main_button style.  These must be documented to be taken advantage of.
12105 widget "main window.*GtkButton*" style "main_button"
12106 </verb></tscreen>
12107
12108 <!-- ***************************************************************** -->
12109 <sect>Writing Your Own Widgets 
12110 <!-- ***************************************************************** -->
12111
12112 <!-- ----------------------------------------------------------------- -->
12113 <sect1> Overview
12114 <p>
12115 Although the GTK distribution comes with many types of widgets that
12116 should cover most basic needs, there may come a time when you need to
12117 create your own new widget type. Since GTK uses widget inheritance
12118 extensively, and there is already a widget that is close to what you want,
12119 it is often possible to make a useful new widget type in
12120 just a few lines of code. But before starting work on a new widget, check
12121 around first to make sure that someone has not already written
12122 it. This will prevent duplication of effort and keep the number of
12123 GTK widgets out there to a minimum, which will help keep both the code
12124 and the interface of different applications consistent. As a flip side
12125 to this, once you finish your widget, announce it to the world so
12126 other people can benefit. The best place to do this is probably the
12127 <tt>gtk-list</tt>.
12128
12129 Complete sources for the example widgets are available at the place you 
12130 got this tutorial, or from:
12131
12132 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
12133 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
12134
12135
12136 <!-- ----------------------------------------------------------------- -->
12137 <sect1> The Anatomy Of A Widget
12138 <p>
12139 In order to create a new widget, it is important to have an
12140 understanding of how GTK objects work. This section is just meant as a
12141 brief overview. See the reference documentation for the details. 
12142
12143 GTK widgets are implemented in an object oriented fashion. However,
12144 they are implemented in standard C. This greatly improves portability
12145 and stability over using current generation C++ compilers; however,
12146 it does mean that the widget writer has to pay attention to some of
12147 the implementation details. The information common to all instances of
12148 one class of widgets (e.g., to all Button widgets) is stored in the 
12149 <em>class structure</em>. There is only one copy of this in
12150 which is stored information about the class's signals
12151 (which act like virtual functions in C). To support inheritance, the
12152 first field in the class structure must be a copy of the parent's
12153 class structure. The declaration of the class structure of GtkButtton
12154 looks like:
12155
12156 <tscreen><verb>
12157 struct _GtkButtonClass
12158 {
12159   GtkContainerClass parent_class;
12160
12161   void (* pressed)  (GtkButton *button);
12162   void (* released) (GtkButton *button);
12163   void (* clicked)  (GtkButton *button);
12164   void (* enter)    (GtkButton *button);
12165   void (* leave)    (GtkButton *button);
12166 };
12167 </verb></tscreen>
12168
12169 When a button is treated as a container (for instance, when it is
12170 resized), its class structure can be cast to GtkContainerClass, and
12171 the relevant fields used to handle the signals.
12172
12173 There is also a structure for each widget that is created on a
12174 per-instance basis. This structure has fields to store information that
12175 is different for each instance of the widget. We'll call this
12176 structure the <em>object structure</em>. For the Button class, it looks
12177 like:
12178
12179 <tscreen><verb>
12180 struct _GtkButton
12181 {
12182   GtkContainer container;
12183
12184   GtkWidget *child;
12185
12186   guint in_button : 1;
12187   guint button_down : 1;
12188 };
12189 </verb></tscreen>
12190
12191 Note that, similar to the class structure, the first field is the
12192 object structure of the parent class, so that this structure can be
12193 cast to the parent class' object structure as needed.
12194
12195 <!-- ----------------------------------------------------------------- -->
12196 <sect1> Creating a Composite widget
12197
12198 <!-- ----------------------------------------------------------------- -->
12199 <sect2> Introduction
12200 <p>
12201 One type of widget that you may be interested in creating is a
12202 widget that is merely an aggregate of other GTK widgets. This type of
12203 widget does nothing that couldn't be done without creating new
12204 widgets, but provides a convenient way of packaging user interface
12205 elements for reuse. The FileSelection and ColorSelection widgets in
12206 the standard distribution are examples of this type of widget.
12207
12208 The example widget that we'll create in this section is the Tictactoe
12209 widget, a 3x3 array of toggle buttons which triggers a signal when all
12210 three buttons in a row, column, or on one of the diagonals are
12211 depressed. 
12212
12213 <!-- ----------------------------------------------------------------- -->
12214 <sect2> Choosing a parent class
12215 <p>
12216 The parent class for a composite widget is typically the container
12217 class that holds all of the elements of the composite widget. For
12218 example, the parent class of the FileSelection widget is the
12219 Dialog class. Since our buttons will be arranged in a table, it
12220 might seem natural to make our parent class the Table
12221 class. Unfortunately, this turns out not to work. The creation of a
12222 widget is divided among two functions - a <tt/WIDGETNAME_new()/
12223 function that the user calls, and a <tt/WIDGETNAME_init()/ function
12224 which does the basic work of initializing the widget which is
12225 independent of the arguments passed to the <tt/_new()/
12226 function. Descendant widgets only call the <tt/_init/ function of
12227 their parent widget. But this division of labor doesn't work well for
12228 tables, which when created need to know the number of rows and
12229 columns in the table. Unless we want to duplicate most of the
12230 functionality of <tt/gtk_table_new()/ in our Tictactoe widget, we had
12231 best avoid deriving it from Table. For that reason, we derive it
12232 from VBox instead, and stick our table inside the VBox.
12233
12234 <!-- ----------------------------------------------------------------- -->
12235 <sect2> The header file
12236 <p>
12237 Each widget class has a header file which declares the object and
12238 class structures for that widget, along with public functions. 
12239 A couple of features are worth pointing out. To prevent duplicate
12240 definitions, we wrap the entire header file in:
12241
12242 <tscreen><verb>
12243 #ifndef __TICTACTOE_H__
12244 #define __TICTACTOE_H__
12245 .
12246 .
12247 .
12248 #endif /* __TICTACTOE_H__ */
12249 </verb></tscreen>
12250
12251 And to keep C++ programs that include the header file happy, in:
12252
12253 <tscreen><verb>
12254 #ifdef __cplusplus
12255 extern "C" {
12256 #endif /* __cplusplus */
12257 .
12258 .
12259 .
12260 #ifdef __cplusplus
12261 }
12262 #endif /* __cplusplus */
12263 </verb></tscreen>
12264
12265 Along with the functions and structures, we declare three standard
12266 macros in our header file, <tt/TICTACTOE(obj)/,
12267 <tt/TICTACTOE_CLASS(klass)/, and <tt/IS_TICTACTOE(obj)/, which cast a
12268 pointer into a pointer to the object or class structure, and check
12269 if an object is a Tictactoe widget respectively.
12270
12271 Here is the complete header file:
12272
12273 <tscreen><verb>
12274 /* tictactoe.h */
12275
12276 #ifndef __TICTACTOE_H__
12277 #define __TICTACTOE_H__
12278
12279 #include <gdk/gdk.h>
12280 #include <gtk/gtkvbox.h>
12281
12282 #ifdef __cplusplus
12283 extern "C" {
12284 #endif /* __cplusplus */
12285
12286 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
12287 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
12288 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
12289
12290
12291 typedef struct _Tictactoe       Tictactoe;
12292 typedef struct _TictactoeClass  TictactoeClass;
12293
12294 struct _Tictactoe
12295 {
12296   GtkVBox vbox;
12297   
12298   GtkWidget *buttons[3][3];
12299 };
12300
12301 struct _TictactoeClass
12302 {
12303   GtkVBoxClass parent_class;
12304
12305   void (* tictactoe) (Tictactoe *ttt);
12306 };
12307
12308 guint          tictactoe_get_type        (void);
12309 GtkWidget*     tictactoe_new             (void);
12310 void           tictactoe_clear           (Tictactoe *ttt);
12311
12312 #ifdef __cplusplus
12313 }
12314 #endif /* __cplusplus */
12315
12316 #endif /* __TICTACTOE_H__ */
12317
12318 </verb></tscreen>
12319
12320 <!-- ----------------------------------------------------------------- -->
12321 <sect2> The <tt/_get_type()/ function.
12322 <p>
12323 We now continue on to the implementation of our widget. A core
12324 function for every widget is the function
12325 <tt/WIDGETNAME_get_type()/. This function, when first called, tells
12326 GTK about the widget class, and gets an ID that uniquely identifies
12327 the widget class. Upon subsequent calls, it just returns the ID.
12328
12329 <tscreen><verb>
12330 guint
12331 tictactoe_get_type ()
12332 {
12333   static guint ttt_type = 0;
12334
12335   if (!ttt_type)
12336     {
12337       GtkTypeInfo ttt_info =
12338       {
12339         "Tictactoe",
12340         sizeof (Tictactoe),
12341         sizeof (TictactoeClass),
12342         (GtkClassInitFunc) tictactoe_class_init,
12343         (GtkObjectInitFunc) tictactoe_init,
12344         (GtkArgSetFunc) NULL,
12345         (GtkArgGetFunc) NULL
12346       };
12347
12348       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
12349     }
12350
12351   return ttt_type;
12352 }
12353 </verb></tscreen>
12354
12355 The GtkTypeInfo structure has the following definition:
12356
12357 <tscreen><verb>
12358 struct _GtkTypeInfo
12359 {
12360   gchar *type_name;
12361   guint object_size;
12362   guint class_size;
12363   GtkClassInitFunc class_init_func;
12364   GtkObjectInitFunc object_init_func;
12365   GtkArgSetFunc arg_set_func;
12366   GtkArgGetFunc arg_get_func;
12367 };
12368 </verb></tscreen>
12369
12370 The fields of this structure are pretty self-explanatory. We'll ignore
12371 the <tt/arg_set_func/ and <tt/arg_get_func/ fields here: they have an important, 
12372 but as yet largely
12373 unimplemented, role in allowing widget options to be conveniently set
12374 from interpreted languages. Once GTK has a correctly filled in copy of
12375 this structure, it knows how to create objects of a particular widget
12376 type. 
12377
12378 <!-- ----------------------------------------------------------------- -->
12379 <sect2> The <tt/_class_init()/ function
12380 <p>
12381 The <tt/WIDGETNAME_class_init()/ function initializes the fields of
12382 the widget's class structure, and sets up any signals for the
12383 class. For our Tictactoe widget it looks like:
12384
12385 <tscreen><verb>
12386
12387 enum {
12388   TICTACTOE_SIGNAL,
12389   LAST_SIGNAL
12390 };
12391
12392 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
12393
12394 static void
12395 tictactoe_class_init (TictactoeClass *class)
12396 {
12397   GtkObjectClass *object_class;
12398
12399   object_class = (GtkObjectClass*) class;
12400   
12401   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
12402                                          GTK_RUN_FIRST,
12403                                          object_class->type,
12404                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
12405                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
12406
12407
12408   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
12409
12410   class->tictactoe = NULL;
12411 }
12412 </verb></tscreen>
12413
12414 Our widget has just one signal, the <tt/tictactoe/ signal that is
12415 invoked when a row, column, or diagonal is completely filled in. Not
12416 every composite widget needs signals, so if you are reading this for
12417 the first time, you may want to skip to the next section now, as
12418 things are going to get a bit complicated.
12419
12420 The function:
12421
12422 <tscreen><verb>
12423 gint gtk_signal_new( const gchar         *name,
12424                      GtkSignalRunType     run_type,
12425                      GtkType              object_type,
12426                      gint                 function_offset,
12427                      GtkSignalMarshaller  marshaller,
12428                      GtkType              return_val,
12429                      guint                nparams,
12430                      ...);
12431 </verb></tscreen>
12432
12433 Creates a new signal. The parameters are:
12434
12435 <itemize>
12436 <item> <tt/name/: The name of the signal.
12437 <item> <tt/run_type/: Whether the default handler runs before or after
12438 user handlers. Usually this will be <tt/GTK_RUN_FIRST/, or <tt/GTK_RUN_LAST/,
12439 although there are other possibilities.
12440 <item> <tt/object_type/: The ID of the object that this signal applies
12441 to. (It will also apply to that objects descendants.)
12442 <item> <tt/function_offset/: The offset within the class structure of
12443 a pointer to the default handler.
12444 <item> <tt/marshaller/: A function that is used to invoke the signal
12445 handler. For signal handlers that have no arguments other than the
12446 object that emitted the signal and user data, we can use the
12447 pre-supplied marshaller function <tt/gtk_signal_default_marshaller/.
12448 <item> <tt/return_val/: The type of the return val.
12449 <item> <tt/nparams/: The number of parameters of the signal handler
12450 (other than the two default ones mentioned above)
12451 <item> <tt/.../: The types of the parameters.
12452 </itemize>
12453
12454 When specifying types, the <tt/GtkType/ enumeration is used:
12455
12456 <tscreen><verb>
12457 typedef enum
12458 {
12459   GTK_TYPE_INVALID,
12460   GTK_TYPE_NONE,
12461   GTK_TYPE_CHAR,
12462   GTK_TYPE_BOOL,
12463   GTK_TYPE_INT,
12464   GTK_TYPE_UINT,
12465   GTK_TYPE_LONG,
12466   GTK_TYPE_ULONG,
12467   GTK_TYPE_FLOAT,
12468   GTK_TYPE_DOUBLE,
12469   GTK_TYPE_STRING,
12470   GTK_TYPE_ENUM,
12471   GTK_TYPE_FLAGS,
12472   GTK_TYPE_BOXED,
12473   GTK_TYPE_FOREIGN,
12474   GTK_TYPE_CALLBACK,
12475   GTK_TYPE_ARGS,
12476
12477   GTK_TYPE_POINTER,
12478
12479   /* it'd be great if the next two could be removed eventually */
12480   GTK_TYPE_SIGNAL,
12481   GTK_TYPE_C_CALLBACK,
12482
12483   GTK_TYPE_OBJECT
12484
12485 } GtkFundamentalType;
12486 </verb></tscreen>
12487
12488 <tt/gtk_signal_new()/ returns a unique integer identifier for the
12489 signal, that we store in the <tt/tictactoe_signals/ array, which we
12490 index using an enumeration. (Conventionally, the enumeration elements
12491 are the signal name, uppercased, but here there would be a conflict
12492 with the <tt/TICTACTOE()/ macro, so we called it <tt/TICTACTOE_SIGNAL/
12493 instead.
12494
12495 After creating our signals, we need to tell GTK to associate our
12496 signals with the Tictactoe class. We do that by calling
12497 <tt/gtk_object_class_add_signals()/. We then set the pointer which
12498 points to the default handler for the "tictactoe" signal to NULL,
12499 indicating that there is no default action.
12500
12501 <!-- ----------------------------------------------------------------- -->
12502 <sect2> The <tt/_init()/ function.
12503 <p>
12504 Each widget class also needs a function to initialize the object
12505 structure. Usually, this function has the fairly limited role of
12506 setting the fields of the structure to default values. For composite
12507 widgets, however, this function also creates the component widgets.
12508
12509 <tscreen><verb>
12510 static void
12511 tictactoe_init (Tictactoe *ttt)
12512 {
12513   GtkWidget *table;
12514   gint i,j;
12515   
12516   table = gtk_table_new (3, 3, TRUE);
12517   gtk_container_add (GTK_CONTAINER(ttt), table);
12518   gtk_widget_show (table);
12519
12520   for (i=0;i<3; i++)
12521     for (j=0;j<3; j++)
12522       {
12523         ttt->buttons[i][j] = gtk_toggle_button_new ();
12524         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
12525                                    i, i+1, j, j+1);
12526         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
12527                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
12528         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
12529         gtk_widget_show (ttt->buttons[i][j]);
12530       }
12531 }
12532 </verb></tscreen>
12533
12534 <!-- ----------------------------------------------------------------- -->
12535 <sect2> And the rest...
12536 <p>
12537 There is one more function that every widget (except for base widget
12538 types like Bin that cannot be instantiated) needs to have - the
12539 function that the user calls to create an object of that type. This is
12540 conventionally called <tt/WIDGETNAME_new()/. In some
12541 widgets, though not for the Tictactoe widgets, this function takes
12542 arguments, and does some setup based on the arguments. The other two
12543 functions are specific to the Tictactoe widget. 
12544
12545 <tt/tictactoe_clear()/ is a public function that resets all the
12546 buttons in the widget to the up position. Note the use of
12547 <tt/gtk_signal_handler_block_by_data()/ to keep our signal handler for
12548 button toggles from being triggered unnecessarily.
12549
12550 <tt/tictactoe_toggle()/ is the signal handler that is invoked when the
12551 user clicks on a button. It checks to see if there are any winning
12552 combinations that involve the toggled button, and if so, emits
12553 the "tictactoe" signal.
12554
12555 <tscreen><verb>  
12556 GtkWidget*
12557 tictactoe_new ()
12558 {
12559   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
12560 }
12561
12562 void           
12563 tictactoe_clear (Tictactoe *ttt)
12564 {
12565   int i,j;
12566
12567   for (i=0;i<3;i++)
12568     for (j=0;j<3;j++)
12569       {
12570         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
12571         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
12572                                      FALSE);
12573         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
12574       }
12575 }
12576
12577 static void
12578 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
12579 {
12580   int i,k;
12581
12582   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
12583                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
12584                              { 0, 1, 2 }, { 0, 1, 2 } };
12585   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
12586                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
12587                              { 0, 1, 2 }, { 2, 1, 0 } };
12588
12589   int success, found;
12590
12591   for (k=0; k<8; k++)
12592     {
12593       success = TRUE;
12594       found = FALSE;
12595
12596       for (i=0;i<3;i++)
12597         {
12598           success = success &amp;&amp; 
12599             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
12600           found = found ||
12601             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
12602         }
12603       
12604       if (success &amp;&amp; found)
12605         {
12606           gtk_signal_emit (GTK_OBJECT (ttt), 
12607                            tictactoe_signals[TICTACTOE_SIGNAL]);
12608           break;
12609         }
12610     }
12611 }
12612 </verb></tscreen>
12613
12614 And finally, an example program using our Tictactoe widget:
12615
12616 <tscreen><verb>
12617 #include <gtk/gtk.h>
12618 #include "tictactoe.h"
12619
12620 /* Invoked when a row, column or diagonal is completed */
12621 void
12622 win (GtkWidget *widget, gpointer data)
12623 {
12624   g_print ("Yay!\n");
12625   tictactoe_clear (TICTACTOE (widget));
12626 }
12627
12628 int 
12629 main (int argc, char *argv[])
12630 {
12631   GtkWidget *window;
12632   GtkWidget *ttt;
12633   
12634   gtk_init (&amp;argc, &amp;argv);
12635
12636   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12637   
12638   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
12639   
12640   gtk_signal_connect (GTK_OBJECT (window), "destroy",
12641                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
12642   
12643   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12644
12645   /* Create a new Tictactoe widget */
12646   ttt = tictactoe_new ();
12647   gtk_container_add (GTK_CONTAINER (window), ttt);
12648   gtk_widget_show (ttt);
12649
12650   /* And attach to its "tictactoe" signal */
12651   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
12652                       GTK_SIGNAL_FUNC (win), NULL);
12653
12654   gtk_widget_show (window);
12655   
12656   gtk_main ();
12657   
12658   return 0;
12659 }
12660
12661 </verb></tscreen>
12662
12663 <!-- ----------------------------------------------------------------- -->
12664 <sect1> Creating a widget from scratch.
12665
12666 <!-- ----------------------------------------------------------------- -->
12667 <sect2> Introduction
12668 <p>
12669 In this section, we'll learn more about how widgets display themselves
12670 on the screen and interact with events. As an example of this, we'll
12671 create an analog dial widget with a pointer that the user can drag to
12672 set the value.
12673
12674 <!-- ----------------------------------------------------------------- -->
12675 <sect2> Displaying a widget on the screen
12676 <p>
12677 There are several steps that are involved in displaying on the screen.
12678 After the widget is created with a call to <tt/WIDGETNAME_new()/,
12679 several more functions are needed:
12680
12681 <itemize>
12682 <item> <tt/WIDGETNAME_realize()/ is responsible for creating an X
12683 window for the widget if it has one.
12684 <item> <tt/WIDGETNAME_map()/ is invoked after the user calls
12685 <tt/gtk_widget_show()/. It is responsible for making sure the widget
12686 is actually drawn on the screen (<em/mapped/). For a container class,
12687 it must also make calls to <tt/map()/> functions of any child widgets.
12688 <item> <tt/WIDGETNAME_draw()/ is invoked when <tt/gtk_widget_draw()/
12689 is called for the widget or one of its ancestors. It makes the actual
12690 calls to the drawing functions to draw the widget on the screen. For
12691 container widgets, this function must make calls to
12692 <tt/gtk_widget_draw()/ for its child widgets.
12693 <item> <tt/WIDGETNAME_expose()/ is a handler for expose events for the
12694 widget. It makes the necessary calls to the drawing functions to draw
12695 the exposed portion on the screen. For container widgets, this
12696 function must generate expose events for its child widgets which don't
12697 have their own windows. (If they have their own windows, then X will
12698 generate the necessary expose events.)
12699 </itemize>
12700
12701 You might notice that the last two functions are quite similar - each
12702 is responsible for drawing the widget on the screen. In fact many
12703 types of widgets don't really care about the difference between the
12704 two. The default <tt/draw()/ function in the widget class simply
12705 generates a synthetic expose event for the redrawn area. However, some
12706 types of widgets can save work by distinguishing between the two
12707 functions. For instance, if a widget has multiple X windows, then
12708 since expose events identify the exposed window, it can redraw only
12709 the affected window, which is not possible for calls to <tt/draw()/.
12710
12711 Container widgets, even if they don't care about the difference for
12712 themselves, can't simply use the default <tt/draw()/ function because
12713 their child widgets might care about the difference. However,
12714 it would be wasteful to duplicate the drawing code between the two
12715 functions. The convention is that such widgets have a function called
12716 <tt/WIDGETNAME_paint()/ that does the actual work of drawing the
12717 widget, that is then called by the <tt/draw()/ and <tt/expose()/
12718 functions.
12719
12720 In our example approach, since the dial widget is not a container
12721 widget, and only has a single window, we can take the simplest
12722 approach and use the default <tt/draw()/ function and only implement
12723 an <tt/expose()/ function.
12724
12725 <!-- ----------------------------------------------------------------- -->
12726 <sect2> The origins of the Dial Widget
12727 <p>
12728 Just as all land animals are just variants on the first amphibian that
12729 crawled up out of the mud, GTK widgets tend to start off as variants
12730 of some other, previously written widget. Thus, although this section
12731 is entitled "Creating a Widget from Scratch", the Dial widget really
12732 began with the source code for the Range widget. This was picked as a
12733 starting point because it would be nice if our Dial had the same
12734 interface as the Scale widgets which are just specialized descendants
12735 of the Range widget. So, though the source code is presented below in
12736 finished form, it should not be implied that it was written, <em>ab
12737 initio</em> in this fashion. Also, if you aren't yet familiar with
12738 how scale widgets work from the application writer's point of view, it
12739 would be a good idea to look them over before continuing.
12740
12741 <!-- ----------------------------------------------------------------- -->
12742 <sect2> The Basics
12743 <p>
12744 Quite a bit of our widget should look pretty familiar from the
12745 Tictactoe widget. First, we have a header file:
12746
12747 <tscreen><verb>
12748 /* GTK - The GIMP Toolkit
12749  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
12750  *
12751  * This library is free software; you can redistribute it and/or
12752  * modify it under the terms of the GNU Library General Public
12753  * License as published by the Free Software Foundation; either
12754  * version 2 of the License, or (at your option) any later version.
12755  *
12756  * This library is distributed in the hope that it will be useful,
12757  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12758  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12759  * Library General Public License for more details.
12760  *
12761  * You should have received a copy of the GNU Library General Public
12762  * License along with this library; if not, write to the Free
12763  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
12764  */
12765
12766 #ifndef __GTK_DIAL_H__
12767 #define __GTK_DIAL_H__
12768
12769 #include <gdk/gdk.h>
12770 #include <gtk/gtkadjustment.h>
12771 #include <gtk/gtkwidget.h>
12772
12773
12774 #ifdef __cplusplus
12775 extern "C" {
12776 #endif /* __cplusplus */
12777
12778
12779 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
12780 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
12781 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
12782
12783
12784 typedef struct _GtkDial        GtkDial;
12785 typedef struct _GtkDialClass   GtkDialClass;
12786
12787 struct _GtkDial
12788 {
12789   GtkWidget widget;
12790
12791   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
12792   guint policy : 2;
12793
12794   /* Button currently pressed or 0 if none */
12795   guint8 button;
12796
12797   /* Dimensions of dial components */
12798   gint radius;
12799   gint pointer_width;
12800
12801   /* ID of update timer, or 0 if none */
12802   guint32 timer;
12803
12804   /* Current angle */
12805   gfloat angle;
12806
12807   /* Old values from adjustment stored so we know when something changes */
12808   gfloat old_value;
12809   gfloat old_lower;
12810   gfloat old_upper;
12811
12812   /* The adjustment object that stores the data for this dial */
12813   GtkAdjustment *adjustment;
12814 };
12815
12816 struct _GtkDialClass
12817 {
12818   GtkWidgetClass parent_class;
12819 };
12820
12821
12822 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
12823 guint          gtk_dial_get_type               (void);
12824 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
12825 void           gtk_dial_set_update_policy      (GtkDial      *dial,
12826                                                 GtkUpdateType  policy);
12827
12828 void           gtk_dial_set_adjustment         (GtkDial      *dial,
12829                                                 GtkAdjustment *adjustment);
12830 #ifdef __cplusplus
12831 }
12832 #endif /* __cplusplus */
12833
12834
12835 #endif /* __GTK_DIAL_H__ */
12836 </verb></tscreen>
12837
12838 Since there is quite a bit more going on in this widget than the last
12839 one, we have more fields in the data structure, but otherwise things
12840 are pretty similar.
12841
12842 Next, after including header files and declaring a few constants,
12843 we have some functions to provide information about the widget
12844 and initialize it:
12845
12846 <tscreen><verb>
12847 #include <math.h>
12848 #include <stdio.h>
12849 #include <gtk/gtkmain.h>
12850 #include <gtk/gtksignal.h>
12851
12852 #include "gtkdial.h"
12853
12854 #define SCROLL_DELAY_LENGTH  300
12855 #define DIAL_DEFAULT_SIZE 100
12856
12857 /* Forward declarations */
12858
12859 [ omitted to save space ]
12860
12861 /* Local data */
12862
12863 static GtkWidgetClass *parent_class = NULL;
12864
12865 guint
12866 gtk_dial_get_type ()
12867 {
12868   static guint dial_type = 0;
12869
12870   if (!dial_type)
12871     {
12872       GtkTypeInfo dial_info =
12873       {
12874         "GtkDial",
12875         sizeof (GtkDial),
12876         sizeof (GtkDialClass),
12877         (GtkClassInitFunc) gtk_dial_class_init,
12878         (GtkObjectInitFunc) gtk_dial_init,
12879         (GtkArgSetFunc) NULL,
12880         (GtkArgGetFunc) NULL,
12881       };
12882
12883       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
12884     }
12885
12886   return dial_type;
12887 }
12888
12889 static void
12890 gtk_dial_class_init (GtkDialClass *class)
12891 {
12892   GtkObjectClass *object_class;
12893   GtkWidgetClass *widget_class;
12894
12895   object_class = (GtkObjectClass*) class;
12896   widget_class = (GtkWidgetClass*) class;
12897
12898   parent_class = gtk_type_class (gtk_widget_get_type ());
12899
12900   object_class->destroy = gtk_dial_destroy;
12901
12902   widget_class->realize = gtk_dial_realize;
12903   widget_class->expose_event = gtk_dial_expose;
12904   widget_class->size_request = gtk_dial_size_request;
12905   widget_class->size_allocate = gtk_dial_size_allocate;
12906   widget_class->button_press_event = gtk_dial_button_press;
12907   widget_class->button_release_event = gtk_dial_button_release;
12908   widget_class->motion_notify_event = gtk_dial_motion_notify;
12909 }
12910
12911 static void
12912 gtk_dial_init (GtkDial *dial)
12913 {
12914   dial->button = 0;
12915   dial->policy = GTK_UPDATE_CONTINUOUS;
12916   dial->timer = 0;
12917   dial->radius = 0;
12918   dial->pointer_width = 0;
12919   dial->angle = 0.0;
12920   dial->old_value = 0.0;
12921   dial->old_lower = 0.0;
12922   dial->old_upper = 0.0;
12923   dial->adjustment = NULL;
12924 }
12925
12926 GtkWidget*
12927 gtk_dial_new (GtkAdjustment *adjustment)
12928 {
12929   GtkDial *dial;
12930
12931   dial = gtk_type_new (gtk_dial_get_type ());
12932
12933   if (!adjustment)
12934     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
12935
12936   gtk_dial_set_adjustment (dial, adjustment);
12937
12938   return GTK_WIDGET (dial);
12939 }
12940
12941 static void
12942 gtk_dial_destroy (GtkObject *object)
12943 {
12944   GtkDial *dial;
12945
12946   g_return_if_fail (object != NULL);
12947   g_return_if_fail (GTK_IS_DIAL (object));
12948
12949   dial = GTK_DIAL (object);
12950
12951   if (dial->adjustment)
12952     gtk_object_unref (GTK_OBJECT (dial->adjustment));
12953
12954   if (GTK_OBJECT_CLASS (parent_class)->destroy)
12955     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
12956 }
12957 </verb></tscreen>
12958
12959 Note that this <tt/init()/ function does less than for the Tictactoe
12960 widget, since this is not a composite widget, and the <tt/new()/
12961 function does more, since it now has an argument. Also, note that when
12962 we store a pointer to the Adjustment object, we increment its
12963 reference count, (and correspondingly decrement it when we no longer
12964 use it) so that GTK can keep track of when it can be safely destroyed.
12965
12966 <p>
12967 Also, there are a few function to manipulate the widget's options:
12968
12969 <tscreen><verb>
12970 GtkAdjustment*
12971 gtk_dial_get_adjustment (GtkDial *dial)
12972 {
12973   g_return_val_if_fail (dial != NULL, NULL);
12974   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
12975
12976   return dial->adjustment;
12977 }
12978
12979 void
12980 gtk_dial_set_update_policy (GtkDial      *dial,
12981                              GtkUpdateType  policy)
12982 {
12983   g_return_if_fail (dial != NULL);
12984   g_return_if_fail (GTK_IS_DIAL (dial));
12985
12986   dial->policy = policy;
12987 }
12988
12989 void
12990 gtk_dial_set_adjustment (GtkDial      *dial,
12991                           GtkAdjustment *adjustment)
12992 {
12993   g_return_if_fail (dial != NULL);
12994   g_return_if_fail (GTK_IS_DIAL (dial));
12995
12996   if (dial->adjustment)
12997     {
12998       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
12999       gtk_object_unref (GTK_OBJECT (dial->adjustment));
13000     }
13001
13002   dial->adjustment = adjustment;
13003   gtk_object_ref (GTK_OBJECT (dial->adjustment));
13004
13005   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
13006                       (GtkSignalFunc) gtk_dial_adjustment_changed,
13007                       (gpointer) dial);
13008   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
13009                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
13010                       (gpointer) dial);
13011
13012   dial->old_value = adjustment->value;
13013   dial->old_lower = adjustment->lower;
13014   dial->old_upper = adjustment->upper;
13015
13016   gtk_dial_update (dial);
13017 }
13018 </verb></tscreen>
13019
13020 <sect2> <tt/gtk_dial_realize()/
13021
13022 <p>
13023 Now we come to some new types of functions. First, we have a function
13024 that does the work of creating the X window. Notice that a mask is
13025 passed to the function <tt/gdk_window_new()/ which specifies which fields of
13026 the GdkWindowAttr structure actually have data in them (the remaining
13027 fields will be given default values). Also worth noting is the way the
13028 event mask of the widget is created. We call
13029 <tt/gtk_widget_get_events()/ to retrieve the event mask that the user
13030 has specified for this widget (with <tt/gtk_widget_set_events()/), and
13031 add the events that we are interested in ourselves.
13032
13033 <p>
13034 After creating the window, we set its style and background, and put a
13035 pointer to the widget in the user data field of the GdkWindow. This
13036 last step allows GTK to dispatch events for this window to the correct
13037 widget.
13038
13039 <tscreen><verb>
13040 static void
13041 gtk_dial_realize (GtkWidget *widget)
13042 {
13043   GtkDial *dial;
13044   GdkWindowAttr attributes;
13045   gint attributes_mask;
13046
13047   g_return_if_fail (widget != NULL);
13048   g_return_if_fail (GTK_IS_DIAL (widget));
13049
13050   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
13051   dial = GTK_DIAL (widget);
13052
13053   attributes.x = widget->allocation.x;
13054   attributes.y = widget->allocation.y;
13055   attributes.width = widget->allocation.width;
13056   attributes.height = widget->allocation.height;
13057   attributes.wclass = GDK_INPUT_OUTPUT;
13058   attributes.window_type = GDK_WINDOW_CHILD;
13059   attributes.event_mask = gtk_widget_get_events (widget) | 
13060     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
13061     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
13062     GDK_POINTER_MOTION_HINT_MASK;
13063   attributes.visual = gtk_widget_get_visual (widget);
13064   attributes.colormap = gtk_widget_get_colormap (widget);
13065
13066   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
13067   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
13068
13069   widget->style = gtk_style_attach (widget->style, widget->window);
13070
13071   gdk_window_set_user_data (widget->window, widget);
13072
13073   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
13074 }
13075 </verb></tscreen>
13076
13077 <sect2> Size negotiation
13078
13079 <p>
13080 Before the first time that the window containing a widget is
13081 displayed, and whenever the layout of the window changes, GTK asks
13082 each child widget for its desired size. This request is handled by the
13083 function <tt/gtk_dial_size_request()/. Since our widget isn't a
13084 container widget, and has no real constraints on its size, we just
13085 return a reasonable default value.
13086
13087 <tscreen><verb>
13088 static void 
13089 gtk_dial_size_request (GtkWidget      *widget,
13090                        GtkRequisition *requisition)
13091 {
13092   requisition->width = DIAL_DEFAULT_SIZE;
13093   requisition->height = DIAL_DEFAULT_SIZE;
13094 }
13095 </verb></tscreen>
13096
13097 <p>
13098 After all the widgets have requested an ideal size, the layout of the
13099 window is computed and each child widget is notified of its actual
13100 size. Usually, this will be at least as large as the requested size,
13101 but if for instance the user has resized the window, it may
13102 occasionally be smaller than the requested size. The size notification
13103 is handled by the function <tt/gtk_dial_size_allocate()/. Notice that
13104 as well as computing the sizes of some component pieces for future
13105 use, this routine also does the grunt work of moving the widget's X
13106 window into the new position and size.
13107
13108 <tscreen><verb>
13109 static void
13110 gtk_dial_size_allocate (GtkWidget     *widget,
13111                         GtkAllocation *allocation)
13112 {
13113   GtkDial *dial;
13114
13115   g_return_if_fail (widget != NULL);
13116   g_return_if_fail (GTK_IS_DIAL (widget));
13117   g_return_if_fail (allocation != NULL);
13118
13119   widget->allocation = *allocation;
13120   if (GTK_WIDGET_REALIZED (widget))
13121     {
13122       dial = GTK_DIAL (widget);
13123
13124       gdk_window_move_resize (widget->window,
13125                               allocation->x, allocation->y,
13126                               allocation->width, allocation->height);
13127
13128       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
13129       dial->pointer_width = dial->radius / 5;
13130     }
13131 }
13132 </verb></tscreen>.
13133
13134 <!-- ----------------------------------------------------------------- -->
13135 <sect2> <tt/gtk_dial_expose()/
13136
13137 <p>
13138 As mentioned above, all the drawing of this widget is done in the
13139 handler for expose events. There's not much to remark on here except
13140 the use of the function <tt/gtk_draw_polygon/ to draw the pointer with
13141 three dimensional shading according to the colors stored in the
13142 widget's style.
13143
13144 <tscreen><verb>
13145 static gint
13146 gtk_dial_expose (GtkWidget      *widget,
13147                  GdkEventExpose *event)
13148 {
13149   GtkDial *dial;
13150   GdkPoint points[3];
13151   gdouble s,c;
13152   gdouble theta;
13153   gint xc, yc;
13154   gint tick_length;
13155   gint i;
13156
13157   g_return_val_if_fail (widget != NULL, FALSE);
13158   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13159   g_return_val_if_fail (event != NULL, FALSE);
13160
13161   if (event->count > 0)
13162     return FALSE;
13163   
13164   dial = GTK_DIAL (widget);
13165
13166   gdk_window_clear_area (widget->window,
13167                          0, 0,
13168                          widget->allocation.width,
13169                          widget->allocation.height);
13170
13171   xc = widget->allocation.width/2;
13172   yc = widget->allocation.height/2;
13173
13174   /* Draw ticks */
13175
13176   for (i=0; i<25; i++)
13177     {
13178       theta = (i*M_PI/18. - M_PI/6.);
13179       s = sin(theta);
13180       c = cos(theta);
13181
13182       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
13183       
13184       gdk_draw_line (widget->window,
13185                      widget->style->fg_gc[widget->state],
13186                      xc + c*(dial->radius - tick_length),
13187                      yc - s*(dial->radius - tick_length),
13188                      xc + c*dial->radius,
13189                      yc - s*dial->radius);
13190     }
13191
13192   /* Draw pointer */
13193
13194   s = sin(dial->angle);
13195   c = cos(dial->angle);
13196
13197
13198   points[0].x = xc + s*dial->pointer_width/2;
13199   points[0].y = yc + c*dial->pointer_width/2;
13200   points[1].x = xc + c*dial->radius;
13201   points[1].y = yc - s*dial->radius;
13202   points[2].x = xc - s*dial->pointer_width/2;
13203   points[2].y = yc - c*dial->pointer_width/2;
13204
13205   gtk_draw_polygon (widget->style,
13206                     widget->window,
13207                     GTK_STATE_NORMAL,
13208                     GTK_SHADOW_OUT,
13209                     points, 3,
13210                     TRUE);
13211   
13212   return FALSE;
13213 }
13214 </verb></tscreen>
13215
13216 <!-- ----------------------------------------------------------------- -->
13217 <sect2> Event handling
13218 <p>
13219 The rest of the widget's code handles various types of events, and
13220 isn't too different from what would be found in many GTK
13221 applications. Two types of events can occur - either the user can
13222 click on the widget with the mouse and drag to move the pointer, or
13223 the value of the Adjustment object can change due to some external
13224 circumstance. 
13225
13226 When the user clicks on the widget, we check to see if the click was
13227 appropriately near the pointer, and if so, store the button that the
13228 user clicked with in the <tt/button/ field of the widget
13229 structure, and grab all mouse events with a call to
13230 <tt/gtk_grab_add()/. Subsequent motion of the mouse causes the
13231 value of the control to be recomputed (by the function
13232 <tt/gtk_dial_update_mouse/). Depending on the policy that has been
13233 set, "value_changed" events are either generated instantly
13234 (<tt/GTK_UPDATE_CONTINUOUS/), after a delay in a timer added with
13235 <tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), or only when the
13236 button is released (<tt/GTK_UPDATE_DISCONTINUOUS/).
13237
13238 <tscreen><verb>
13239 static gint
13240 gtk_dial_button_press (GtkWidget      *widget,
13241                        GdkEventButton *event)
13242 {
13243   GtkDial *dial;
13244   gint dx, dy;
13245   double s, c;
13246   double d_parallel;
13247   double d_perpendicular;
13248
13249   g_return_val_if_fail (widget != NULL, FALSE);
13250   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13251   g_return_val_if_fail (event != NULL, FALSE);
13252
13253   dial = GTK_DIAL (widget);
13254
13255   /* Determine if button press was within pointer region - we 
13256      do this by computing the parallel and perpendicular distance of
13257      the point where the mouse was pressed from the line passing through
13258      the pointer */
13259   
13260   dx = event->x - widget->allocation.width / 2;
13261   dy = widget->allocation.height / 2 - event->y;
13262   
13263   s = sin(dial->angle);
13264   c = cos(dial->angle);
13265   
13266   d_parallel = s*dy + c*dx;
13267   d_perpendicular = fabs(s*dx - c*dy);
13268   
13269   if (!dial->button &&
13270       (d_perpendicular < dial->pointer_width/2) &&
13271       (d_parallel > - dial->pointer_width))
13272     {
13273       gtk_grab_add (widget);
13274
13275       dial->button = event->button;
13276
13277       gtk_dial_update_mouse (dial, event->x, event->y);
13278     }
13279
13280   return FALSE;
13281 }
13282
13283 static gint
13284 gtk_dial_button_release (GtkWidget      *widget,
13285                           GdkEventButton *event)
13286 {
13287   GtkDial *dial;
13288
13289   g_return_val_if_fail (widget != NULL, FALSE);
13290   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13291   g_return_val_if_fail (event != NULL, FALSE);
13292
13293   dial = GTK_DIAL (widget);
13294
13295   if (dial->button == event->button)
13296     {
13297       gtk_grab_remove (widget);
13298
13299       dial->button = 0;
13300
13301       if (dial->policy == GTK_UPDATE_DELAYED)
13302         gtk_timeout_remove (dial->timer);
13303       
13304       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
13305           (dial->old_value != dial->adjustment->value))
13306         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13307     }
13308
13309   return FALSE;
13310 }
13311
13312 static gint
13313 gtk_dial_motion_notify (GtkWidget      *widget,
13314                          GdkEventMotion *event)
13315 {
13316   GtkDial *dial;
13317   GdkModifierType mods;
13318   gint x, y, mask;
13319
13320   g_return_val_if_fail (widget != NULL, FALSE);
13321   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13322   g_return_val_if_fail (event != NULL, FALSE);
13323
13324   dial = GTK_DIAL (widget);
13325
13326   if (dial->button != 0)
13327     {
13328       x = event->x;
13329       y = event->y;
13330
13331       if (event->is_hint || (event->window != widget->window))
13332         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
13333
13334       switch (dial->button)
13335         {
13336         case 1:
13337           mask = GDK_BUTTON1_MASK;
13338           break;
13339         case 2:
13340           mask = GDK_BUTTON2_MASK;
13341           break;
13342         case 3:
13343           mask = GDK_BUTTON3_MASK;
13344           break;
13345         default:
13346           mask = 0;
13347           break;
13348         }
13349
13350       if (mods & mask)
13351         gtk_dial_update_mouse (dial, x,y);
13352     }
13353
13354   return FALSE;
13355 }
13356
13357 static gint
13358 gtk_dial_timer (GtkDial *dial)
13359 {
13360   g_return_val_if_fail (dial != NULL, FALSE);
13361   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
13362
13363   if (dial->policy == GTK_UPDATE_DELAYED)
13364     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13365
13366   return FALSE;
13367 }
13368
13369 static void
13370 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
13371 {
13372   gint xc, yc;
13373   gfloat old_value;
13374
13375   g_return_if_fail (dial != NULL);
13376   g_return_if_fail (GTK_IS_DIAL (dial));
13377
13378   xc = GTK_WIDGET(dial)->allocation.width / 2;
13379   yc = GTK_WIDGET(dial)->allocation.height / 2;
13380
13381   old_value = dial->adjustment->value;
13382   dial->angle = atan2(yc-y, x-xc);
13383
13384   if (dial->angle < -M_PI/2.)
13385     dial->angle += 2*M_PI;
13386
13387   if (dial->angle < -M_PI/6)
13388     dial->angle = -M_PI/6;
13389
13390   if (dial->angle > 7.*M_PI/6.)
13391     dial->angle = 7.*M_PI/6.;
13392
13393   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
13394     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
13395
13396   if (dial->adjustment->value != old_value)
13397     {
13398       if (dial->policy == GTK_UPDATE_CONTINUOUS)
13399         {
13400           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13401         }
13402       else
13403         {
13404           gtk_widget_draw (GTK_WIDGET(dial), NULL);
13405
13406           if (dial->policy == GTK_UPDATE_DELAYED)
13407             {
13408               if (dial->timer)
13409                 gtk_timeout_remove (dial->timer);
13410
13411               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
13412                                              (GtkFunction) gtk_dial_timer,
13413                                              (gpointer) dial);
13414             }
13415         }
13416     }
13417 }
13418 </verb></tscreen>
13419
13420 Changes to the Adjustment by external means are communicated to our
13421 widget by the "changed" and "value_changed" signals. The handlers
13422 for these functions call <tt/gtk_dial_update()/ to validate the
13423 arguments, compute the new pointer angle, and redraw the widget (by
13424 calling <tt/gtk_widget_draw()/).
13425
13426 <tscreen><verb>
13427 static void
13428 gtk_dial_update (GtkDial *dial)
13429 {
13430   gfloat new_value;
13431   
13432   g_return_if_fail (dial != NULL);
13433   g_return_if_fail (GTK_IS_DIAL (dial));
13434
13435   new_value = dial->adjustment->value;
13436   
13437   if (new_value < dial->adjustment->lower)
13438     new_value = dial->adjustment->lower;
13439
13440   if (new_value > dial->adjustment->upper)
13441     new_value = dial->adjustment->upper;
13442
13443   if (new_value != dial->adjustment->value)
13444     {
13445       dial->adjustment->value = new_value;
13446       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13447     }
13448
13449   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
13450     (dial->adjustment->upper - dial->adjustment->lower);
13451
13452   gtk_widget_draw (GTK_WIDGET(dial), NULL);
13453 }
13454
13455 static void
13456 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
13457                               gpointer       data)
13458 {
13459   GtkDial *dial;
13460
13461   g_return_if_fail (adjustment != NULL);
13462   g_return_if_fail (data != NULL);
13463
13464   dial = GTK_DIAL (data);
13465
13466   if ((dial->old_value != adjustment->value) ||
13467       (dial->old_lower != adjustment->lower) ||
13468       (dial->old_upper != adjustment->upper))
13469     {
13470       gtk_dial_update (dial);
13471
13472       dial->old_value = adjustment->value;
13473       dial->old_lower = adjustment->lower;
13474       dial->old_upper = adjustment->upper;
13475     }
13476 }
13477
13478 static void
13479 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
13480                                     gpointer       data)
13481 {
13482   GtkDial *dial;
13483
13484   g_return_if_fail (adjustment != NULL);
13485   g_return_if_fail (data != NULL);
13486
13487   dial = GTK_DIAL (data);
13488
13489   if (dial->old_value != adjustment->value)
13490     {
13491       gtk_dial_update (dial);
13492
13493       dial->old_value = adjustment->value;
13494     }
13495 }
13496 </verb></tscreen>
13497
13498 <!-- ----------------------------------------------------------------- -->
13499 <sect2> Possible Enhancements
13500 <p>
13501 The Dial widget as we've described it so far runs about 670 lines of
13502 code. Although that might sound like a fair bit, we've really
13503 accomplished quite a bit with that much code, especially since much of
13504 that length is headers and boilerplate. However, there are quite a few
13505 more enhancements that could be made to this widget:
13506
13507 <itemize>
13508 <item> If you try this widget out, you'll find that there is some
13509 flashing as the pointer is dragged around. This is because the entire
13510 widget is erased every time the pointer is moved before being
13511 redrawn. Often, the best way to handle this problem is to draw to an
13512 offscreen pixmap, then copy the final results onto the screen in one
13513 step. (The ProgressBar widget draws itself in this fashion.)
13514
13515 <item> The user should be able to use the up and down arrow keys to
13516 increase and decrease the value.
13517
13518 <item> It would be nice if the widget had buttons to increase and
13519 decrease the value in small or large steps. Although it would be
13520 possible to use embedded Button widgets for this, we would also like
13521 the buttons to auto-repeat when held down, as the arrows on a
13522 scrollbar do. Most of the code to implement this type of behavior can
13523 be found in the Range widget.
13524
13525 <item> The Dial widget could be made into a container widget with a
13526 single child widget positioned at the bottom between the buttons
13527 mentioned above. The user could then add their choice of a label or
13528 entry widget to display the current value of the dial.
13529
13530 </itemize>
13531
13532 <!-- ----------------------------------------------------------------- -->
13533 <sect1> Learning More
13534
13535 <p>
13536 Only a small part of the many details involved in creating widgets
13537 could be described above. If you want to write your own widgets, the
13538 best source of examples is the GTK source itself. Ask yourself some
13539 questions about the widget you want to write: IS it a Container
13540 widget? Does it have its own window? Is it a modification of an
13541 existing widget? Then find a similar widget, and start making changes.
13542 Good luck!
13543
13544 <!-- ***************************************************************** -->
13545 <sect>Scribble, A Simple Example Drawing Program
13546 <!-- ***************************************************************** -->
13547
13548 <!-- ----------------------------------------------------------------- -->
13549 <sect1> Overview
13550 <p>
13551 In this section, we will build a simple drawing program. In the
13552 process, we will examine how to handle mouse events, how to draw in a
13553 window, and how to do drawing better by using a backing pixmap. After
13554 creating the simple drawing program, we will extend it by adding
13555 support for XInput devices, such as drawing tablets. GTK provides
13556 support routines which makes getting extended information, such as
13557 pressure and tilt, from such devices quite easy.
13558
13559 <!-- ----------------------------------------------------------------- -->
13560 <sect1> Event Handling
13561 <p>
13562 The GTK signals we have already discussed are for high-level actions,
13563 such as a menu item being selected. However, sometimes it is useful to
13564 learn about lower-level occurrences, such as the mouse being moved, or
13565 a key being pressed. There are also GTK signals corresponding to these
13566 low-level <em>events</em>. The handlers for these signals have an
13567 extra parameter which is a pointer to a structure containing
13568 information about the event. For instance, motion event handlers are
13569 passed a pointer to a GdkEventMotion structure which looks (in part)
13570 like:
13571
13572 <tscreen><verb>
13573 struct _GdkEventMotion
13574 {
13575   GdkEventType type;
13576   GdkWindow *window;
13577   guint32 time;
13578   gdouble x;
13579   gdouble y;
13580   ...
13581   guint state;
13582   ...
13583 };
13584 </verb></tscreen>
13585
13586 <tt/type/ will be set to the event type, in this case
13587 <tt/GDK_MOTION_NOTIFY/, window is the window in which the event
13588 occurred. <tt/x/ and <tt/y/ give the coordinates of the event.
13589 <tt/state/ specifies the modifier state when the event
13590 occurred (that is, it specifies which modifier keys and mouse buttons
13591 were pressed). It is the bitwise OR of some of the following:
13592
13593 <tscreen><verb>
13594 GDK_SHIFT_MASK  
13595 GDK_LOCK_MASK   
13596 GDK_CONTROL_MASK
13597 GDK_MOD1_MASK   
13598 GDK_MOD2_MASK   
13599 GDK_MOD3_MASK   
13600 GDK_MOD4_MASK   
13601 GDK_MOD5_MASK   
13602 GDK_BUTTON1_MASK
13603 GDK_BUTTON2_MASK
13604 GDK_BUTTON3_MASK
13605 GDK_BUTTON4_MASK
13606 GDK_BUTTON5_MASK
13607 </verb></tscreen>
13608
13609 As for other signals, to determine what happens when an event occurs
13610 we call <tt>gtk_signal_connect()</tt>. But we also need let GTK
13611 know which events we want to be notified about. To do this, we call
13612 the function:
13613
13614 <tscreen><verb>
13615 void gtk_widget_set_events (GtkWidget *widget,
13616                             gint      events);
13617 </verb></tscreen>
13618
13619 The second field specifies the events we are interested in. It
13620 is the bitwise OR of constants that specify different types
13621 of events. For future reference the event types are:
13622
13623 <tscreen><verb>
13624 GDK_EXPOSURE_MASK
13625 GDK_POINTER_MOTION_MASK
13626 GDK_POINTER_MOTION_HINT_MASK
13627 GDK_BUTTON_MOTION_MASK     
13628 GDK_BUTTON1_MOTION_MASK    
13629 GDK_BUTTON2_MOTION_MASK    
13630 GDK_BUTTON3_MOTION_MASK    
13631 GDK_BUTTON_PRESS_MASK      
13632 GDK_BUTTON_RELEASE_MASK    
13633 GDK_KEY_PRESS_MASK         
13634 GDK_KEY_RELEASE_MASK       
13635 GDK_ENTER_NOTIFY_MASK      
13636 GDK_LEAVE_NOTIFY_MASK      
13637 GDK_FOCUS_CHANGE_MASK      
13638 GDK_STRUCTURE_MASK         
13639 GDK_PROPERTY_CHANGE_MASK   
13640 GDK_PROXIMITY_IN_MASK      
13641 GDK_PROXIMITY_OUT_MASK     
13642 </verb></tscreen>
13643
13644 There are a few subtle points that have to be observed when calling
13645 <tt/gtk_widget_set_events()/. First, it must be called before the X window
13646 for a GTK widget is created. In practical terms, this means you
13647 should call it immediately after creating the widget. Second, the
13648 widget must have an associated X window. For efficiency, many widget
13649 types do not have their own window, but draw in their parent's window.
13650 These widgets are:
13651
13652 <tscreen><verb>
13653 GtkAlignment
13654 GtkArrow
13655 GtkBin
13656 GtkBox
13657 GtkImage
13658 GtkItem
13659 GtkLabel
13660 GtkPixmap
13661 GtkScrolledWindow
13662 GtkSeparator
13663 GtkTable
13664 GtkAspectFrame
13665 GtkFrame
13666 GtkVBox
13667 GtkHBox
13668 GtkVSeparator
13669 GtkHSeparator
13670 </verb></tscreen>
13671
13672 To capture events for these widgets, you need to use an EventBox
13673 widget. See the section on the <ref id="sec_EventBox"
13674 name="EventBox"> widget for details.
13675
13676 For our drawing program, we want to know when the mouse button is
13677 pressed and when the mouse is moved, so we specify
13678 <tt/GDK_POINTER_MOTION_MASK/ and <tt/GDK_BUTTON_PRESS_MASK/. We also
13679 want to know when we need to redraw our window, so we specify
13680 <tt/GDK_EXPOSURE_MASK/. Although we want to be notified via a
13681 Configure event when our window size changes, we don't have to specify
13682 the corresponding <tt/GDK_STRUCTURE_MASK/ flag, because it is
13683 automatically specified for all windows.
13684
13685 It turns out, however, that there is a problem with just specifying
13686 <tt/GDK_POINTER_MOTION_MASK/. This will cause the server to add a new
13687 motion event to the event queue every time the user moves the mouse.
13688 Imagine that it takes us 0.1 seconds to handle a motion event, but the
13689 X server queues a new motion event every 0.05 seconds. We will soon
13690 get way behind the users drawing. If the user draws for 5 seconds,
13691 it will take us another 5 seconds to catch up after they release 
13692 the mouse button! What we would like is to only get one motion
13693 event for each event we process. The way to do this is to 
13694 specify <tt/GDK_POINTER_MOTION_HINT_MASK/. 
13695
13696 When we specify <tt/GDK_POINTER_MOTION_HINT_MASK/, the server sends
13697 us a motion event the first time the pointer moves after entering
13698 our window, or after a button press or release event. Subsequent 
13699 motion events will be suppressed until we explicitly ask for
13700 the position of the pointer using the function:
13701
13702 <tscreen><verb>
13703 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
13704                                           gint            *x,
13705                                           gint            *y,
13706                                           GdkModifierType *mask);
13707 </verb></tscreen>
13708
13709 (There is another function, <tt>gtk_widget_get_pointer()</tt> which
13710 has a simpler interface, but turns out not to be very useful, since
13711 it only retrieves the position of the mouse, not whether the buttons
13712 are pressed.)
13713
13714 The code to set the events for our window then looks like:
13715
13716 <tscreen><verb>
13717   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
13718                       (GtkSignalFunc) expose_event, NULL);
13719   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
13720                       (GtkSignalFunc) configure_event, NULL);
13721   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
13722                       (GtkSignalFunc) motion_notify_event, NULL);
13723   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
13724                       (GtkSignalFunc) button_press_event, NULL);
13725
13726   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
13727                          | GDK_LEAVE_NOTIFY_MASK
13728                          | GDK_BUTTON_PRESS_MASK
13729                          | GDK_POINTER_MOTION_MASK
13730                          | GDK_POINTER_MOTION_HINT_MASK);
13731 </verb></tscreen>
13732
13733 We'll save the "expose_event" and "configure_event" handlers for
13734 later. The "motion_notify_event" and "button_press_event" handlers
13735 are pretty simple:
13736
13737 <tscreen><verb>
13738 static gint
13739 button_press_event (GtkWidget *widget, GdkEventButton *event)
13740 {
13741   if (event->button == 1 &amp;&amp; pixmap != NULL)
13742       draw_brush (widget, event->x, event->y);
13743
13744   return TRUE;
13745 }
13746
13747 static gint
13748 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
13749 {
13750   int x, y;
13751   GdkModifierType state;
13752
13753   if (event->is_hint)
13754     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
13755   else
13756     {
13757       x = event->x;
13758       y = event->y;
13759       state = event->state;
13760     }
13761     
13762   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
13763     draw_brush (widget, x, y);
13764   
13765   return TRUE;
13766 }
13767 </verb></tscreen>
13768
13769 <!-- ----------------------------------------------------------------- -->
13770 <sect1> The DrawingArea Widget, And Drawing
13771 <p>
13772 We now turn to the process of drawing on the screen. The 
13773 widget we use for this is the DrawingArea widget. A drawing area
13774 widget is essentially an X window and nothing more. It is a blank
13775 canvas in which we can draw whatever we like. A drawing area
13776 is created using the call:
13777
13778 <tscreen><verb>
13779 GtkWidget* gtk_drawing_area_new        (void);
13780 </verb></tscreen>
13781
13782 A default size for the widget can be specified by calling:
13783
13784 <tscreen><verb>
13785 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
13786                                         gint                 width,
13787                                         gint                 height);
13788 </verb></tscreen>
13789
13790 This default size can be overridden, as is true for all widgets,
13791 by calling <tt>gtk_widget_set_usize()</tt>, and that, in turn, can
13792 be overridden if the user manually resizes the the window containing
13793 the drawing area.
13794
13795 It should be noted that when we create a DrawingArea widget, we are
13796 <em>completely</em> responsible for drawing the contents. If our
13797 window is obscured then uncovered, we get an exposure event and must
13798 redraw what was previously hidden.
13799
13800 Having to remember everything that was drawn on the screen so we
13801 can properly redraw it can, to say the least, be a nuisance. In
13802 addition, it can be visually distracting if portions of the
13803 window are cleared, then redrawn step by step. The solution to
13804 this problem is to use an offscreen <em>backing pixmap</em>.
13805 Instead of drawing directly to the screen, we draw to an image
13806 stored in server memory but not displayed, then when the image
13807 changes or new portions of the image are displayed, we copy the
13808 relevant portions onto the screen.
13809
13810 To create an offscreen pixmap, we call the function:
13811
13812 <tscreen><verb>
13813 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
13814                                          gint        width,
13815                                          gint        height,
13816                                          gint        depth);
13817 </verb></tscreen>
13818
13819 The <tt>window</tt> parameter specifies a GDK window that this pixmap
13820 takes some of its properties from. <tt>width</tt> and <tt>height</tt>
13821 specify the size of the pixmap. <tt>depth</tt> specifies the <em>color
13822 depth</em>, that is the number of bits per pixel, for the new window.
13823 If the depth is specified as <tt>-1</tt>, it will match the depth
13824 of <tt>window</tt>.
13825
13826 We create the pixmap in our "configure_event" handler. This event
13827 is generated whenever the window changes size, including when it
13828 is originally created.
13829
13830 <tscreen><verb>
13831 /* Backing pixmap for drawing area */
13832 static GdkPixmap *pixmap = NULL;
13833
13834 /* Create a new backing pixmap of the appropriate size */
13835 static gint
13836 configure_event (GtkWidget *widget, GdkEventConfigure *event)
13837 {
13838   if (pixmap)
13839     gdk_pixmap_unref(pixmap);
13840
13841   pixmap = gdk_pixmap_new(widget->window,
13842                           widget->allocation.width,
13843                           widget->allocation.height,
13844                           -1);
13845   gdk_draw_rectangle (pixmap,
13846                       widget->style->white_gc,
13847                       TRUE,
13848                       0, 0,
13849                       widget->allocation.width,
13850                       widget->allocation.height);
13851
13852   return TRUE;
13853 }
13854 </verb></tscreen>
13855
13856 The call to <tt>gdk_draw_rectangle()</tt> clears the pixmap
13857 initially to white. We'll say more about that in a moment.
13858
13859 Our exposure event handler then simply copies the relevant portion
13860 of the pixmap onto the screen (we determine the area we need
13861 to redraw by using the event->area field of the exposure event):
13862
13863 <tscreen><verb>
13864 /* Redraw the screen from the backing pixmap */
13865 static gint
13866 expose_event (GtkWidget *widget, GdkEventExpose *event)
13867 {
13868   gdk_draw_pixmap(widget->window,
13869                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
13870                   pixmap,
13871                   event->area.x, event->area.y,
13872                   event->area.x, event->area.y,
13873                   event->area.width, event->area.height);
13874
13875   return FALSE;
13876 }
13877 </verb></tscreen>
13878
13879 We've now seen how to keep the screen up to date with our pixmap, but
13880 how do we actually draw interesting stuff on our pixmap?  There are a
13881 large number of calls in GTK's GDK library for drawing on
13882 <em>drawables</em>. A drawable is simply something that can be drawn
13883 upon. It can be a window, a pixmap, or a bitmap (a black and white
13884 image).  We've already seen two such calls above,
13885 <tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. The
13886 complete list is:
13887
13888 <tscreen><verb>
13889 gdk_draw_line ()
13890 gdk_draw_rectangle ()
13891 gdk_draw_arc ()
13892 gdk_draw_polygon ()
13893 gdk_draw_string ()
13894 gdk_draw_text ()
13895 gdk_draw_pixmap ()
13896 gdk_draw_bitmap ()
13897 gdk_draw_image ()
13898 gdk_draw_points ()
13899 gdk_draw_segments ()
13900 </verb></tscreen>
13901
13902 See the reference documentation or the header file
13903 <tt>&lt;gdk/gdk.h&gt;</tt> for further details on these functions.
13904 These functions all share the same first two arguments. The first
13905 argument is the drawable to draw upon, the second argument is a
13906 <em>graphics context</em> (GC). 
13907
13908 A graphics context encapsulates information about things such as
13909 foreground and background color and line width. GDK has a full set of
13910 functions for creating and modifying graphics contexts, but to keep
13911 things simple we'll just use predefined graphics contexts. Each widget
13912 has an associated style. (Which can be modified in a gtkrc file, see
13913 the section GTK's rc file.) This, among other things, stores a number
13914 of graphics contexts. Some examples of accessing these graphics
13915 contexts are:
13916
13917 <tscreen><verb>
13918 widget->style->white_gc
13919 widget->style->black_gc
13920 widget->style->fg_gc[GTK_STATE_NORMAL]
13921 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
13922 </verb></tscreen>
13923
13924 The fields <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, and
13925 <tt>light_gc</tt> are indexed by a parameter of type
13926 <tt>GtkStateType</tt> which can take on the values:
13927
13928 <tscreen><verb>
13929 GTK_STATE_NORMAL,
13930 GTK_STATE_ACTIVE,
13931 GTK_STATE_PRELIGHT,
13932 GTK_STATE_SELECTED,
13933 GTK_STATE_INSENSITIVE
13934 </verb></tscreen>
13935
13936 For instance, for <tt/GTK_STATE_SELECTED/ the default foreground
13937 color is white and the default background color, dark blue.
13938
13939 Our function <tt>draw_brush()</tt>, which does the actual drawing
13940 on the screen, is then:
13941
13942 <tscreen><verb>
13943 /* Draw a rectangle on the screen */
13944 static void
13945 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
13946 {
13947   GdkRectangle update_rect;
13948
13949   update_rect.x = x - 5;
13950   update_rect.y = y - 5;
13951   update_rect.width = 10;
13952   update_rect.height = 10;
13953   gdk_draw_rectangle (pixmap,
13954                       widget->style->black_gc,
13955                       TRUE,
13956                       update_rect.x, update_rect.y,
13957                       update_rect.width, update_rect.height);
13958   gtk_widget_draw (widget, &amp;update_rect);
13959 }
13960 </verb></tscreen>
13961
13962 After we draw the rectangle representing the brush onto the pixmap,
13963 we call the function:
13964
13965 <tscreen><verb>
13966 void       gtk_widget_draw                (GtkWidget           *widget,
13967                                            GdkRectangle        *area);
13968 </verb></tscreen>
13969
13970 which notifies X that the area given by the <tt>area</tt> parameter
13971 needs to be updated. X will eventually generate an expose event
13972 (possibly combining the areas passed in several calls to
13973 <tt>gtk_widget_draw()</tt>) which will cause our expose event handler
13974 to copy the relevant portions to the screen.
13975
13976 We have now covered the entire drawing program except for a few
13977 mundane details like creating the main window. The complete
13978 source code is available from the location from which you got
13979 this tutorial, or from:
13980
13981 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
13982 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
13983
13984
13985 <!-- ----------------------------------------------------------------- -->
13986 <sect1> Adding XInput support
13987 <p>
13988 It is now possible to buy quite inexpensive input devices such 
13989 as drawing tablets, which allow drawing with a much greater
13990 ease of artistic expression than does a mouse. The simplest way
13991 to use such devices is simply as a replacement for the mouse,
13992 but that misses out many of the advantages of these devices,
13993 such as:
13994
13995 <itemize>
13996 <item> Pressure sensitivity
13997 <item> Tilt reporting
13998 <item> Sub-pixel positioning
13999 <item> Multiple inputs (for example, a stylus with a point and eraser)
14000 </itemize>
14001
14002 For information about the XInput extension, see the <htmlurl
14003 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
14004 name="XInput-HOWTO">.
14005
14006 If we examine the full definition of, for example, the GdkEventMotion
14007 structure, we see that it has fields to support extended device
14008 information.
14009
14010 <tscreen><verb>
14011 struct _GdkEventMotion
14012 {
14013   GdkEventType type;
14014   GdkWindow *window;
14015   guint32 time;
14016   gdouble x;
14017   gdouble y;
14018   gdouble pressure;
14019   gdouble xtilt;
14020   gdouble ytilt;
14021   guint state;
14022   gint16 is_hint;
14023   GdkInputSource source;
14024   guint32 deviceid;
14025 };
14026 </verb></tscreen>
14027
14028 <tt/pressure/ gives the pressure as a floating point number between
14029 0 and 1. <tt/xtilt/ and <tt/ytilt/ can take on values between 
14030 -1 and 1, corresponding to the degree of tilt in each direction.
14031 <tt/source/ and <tt/deviceid/ specify the device for which the
14032 event occurred in two different ways. <tt/source/ gives some simple
14033 information about the type of device. It can take the enumeration
14034 values:
14035
14036 <tscreen><verb>
14037 GDK_SOURCE_MOUSE
14038 GDK_SOURCE_PEN
14039 GDK_SOURCE_ERASER
14040 GDK_SOURCE_CURSOR
14041 </verb></tscreen>
14042
14043 <tt/deviceid/ specifies a unique numeric ID for the device. This can
14044 be used to find out further information about the device using the
14045 <tt/gdk_input_list_devices()/ call (see below). The special value
14046 <tt/GDK_CORE_POINTER/ is used for the core pointer device. (Usually
14047 the mouse.)
14048
14049 <sect2> Enabling extended device information
14050 <p>
14051 To let GTK know about our interest in the extended device information,
14052 we merely have to add a single line to our program:
14053
14054 <tscreen><verb>
14055 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
14056 </verb></tscreen>
14057
14058 By giving the value <tt/GDK_EXTENSION_EVENTS_CURSOR/ we say that
14059 we are interested in extension events, but only if we don't have
14060 to draw our own cursor. See the section <ref
14061 id="sec_Further_Sophistications" name="Further Sophistications"> below
14062 for more information about drawing the cursor. We could also 
14063 give the values <tt/GDK_EXTENSION_EVENTS_ALL/ if we were willing 
14064 to draw our own cursor, or <tt/GDK_EXTENSION_EVENTS_NONE/ to revert
14065 back to the default condition.
14066
14067 This is not completely the end of the story however. By default,
14068 no extension devices are enabled. We need a mechanism to allow
14069 users to enable and configure their extension devices. GTK provides
14070 the InputDialog widget to automate this process. The following
14071 procedure manages an InputDialog widget. It creates the dialog if
14072 it isn't present, and raises it to the top otherwise.
14073
14074 <tscreen><verb>
14075 void
14076 input_dialog_destroy (GtkWidget *w, gpointer data)
14077 {
14078   *((GtkWidget **)data) = NULL;
14079 }
14080
14081 void
14082 create_input_dialog ()
14083 {
14084   static GtkWidget *inputd = NULL;
14085
14086   if (!inputd)
14087     {
14088       inputd = gtk_input_dialog_new();
14089
14090       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
14091                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
14092       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
14093                                  "clicked",
14094                                  (GtkSignalFunc)gtk_widget_hide,
14095                                  GTK_OBJECT(inputd));
14096       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
14097
14098       gtk_widget_show (inputd);
14099     }
14100   else
14101     {
14102       if (!GTK_WIDGET_MAPPED(inputd))
14103         gtk_widget_show(inputd);
14104       else
14105         gdk_window_raise(inputd->window);
14106     }
14107 }
14108 </verb></tscreen>
14109
14110 (You might want to take note of the way we handle this dialog.  By
14111 connecting to the "destroy" signal, we make sure that we don't keep a
14112 pointer to dialog around after it is destroyed - that could lead to a
14113 segfault.)
14114
14115 The InputDialog has two buttons "Close" and "Save", which by default
14116 have no actions assigned to them. In the above function we make
14117 "Close" hide the dialog, hide the "Save" button, since we don't
14118 implement saving of XInput options in this program.
14119
14120 <sect2> Using extended device information
14121 <p>
14122 Once we've enabled the device, we can just use the extended 
14123 device information in the extra fields of the event structures.
14124 In fact, it is always safe to use this information since these
14125 fields will have reasonable default values even when extended
14126 events are not enabled.
14127
14128 Once change we do have to make is to call
14129 <tt/gdk_input_window_get_pointer()/ instead of
14130 <tt/gdk_window_get_pointer/. This is necessary because
14131 <tt/gdk_window_get_pointer/ doesn't return the extended device
14132 information.
14133
14134 <tscreen><verb>
14135 void gdk_input_window_get_pointer( GdkWindow       *window,
14136                                    guint32         deviceid,
14137                                    gdouble         *x,
14138                                    gdouble         *y,
14139                                    gdouble         *pressure,
14140                                    gdouble         *xtilt,
14141                                    gdouble         *ytilt,
14142                                    GdkModifierType *mask);
14143 </verb></tscreen>
14144
14145 When calling this function, we need to specify the device ID as
14146 well as the window. Usually, we'll get the device ID from the
14147 <tt/deviceid/ field of an event structure. Again, this function
14148 will return reasonable values when extension events are not
14149 enabled. (In this case, <tt/event->deviceid/ will have the value
14150 <tt/GDK_CORE_POINTER/).
14151
14152 So the basic structure of our button-press and motion event handlers
14153 doesn't change much - we just need to add code to deal with the
14154 extended information.
14155
14156 <tscreen><verb>
14157 static gint
14158 button_press_event (GtkWidget *widget, GdkEventButton *event)
14159 {
14160   print_button_press (event->deviceid);
14161   
14162   if (event->button == 1 &amp;&amp; pixmap != NULL)
14163     draw_brush (widget, event->source, event->x, event->y, event->pressure);
14164
14165   return TRUE;
14166 }
14167
14168 static gint
14169 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
14170 {
14171   gdouble x, y;
14172   gdouble pressure;
14173   GdkModifierType state;
14174
14175   if (event->is_hint)
14176     gdk_input_window_get_pointer (event->window, event->deviceid,
14177                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
14178   else
14179     {
14180       x = event->x;
14181       y = event->y;
14182       pressure = event->pressure;
14183       state = event->state;
14184     }
14185     
14186   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
14187     draw_brush (widget, event->source, x, y, pressure);
14188   
14189   return TRUE;
14190 }
14191 </verb></tscreen>
14192
14193 We also need to do something with the new information. Our new
14194 <tt/draw_brush()/ function draws with a different color for
14195 each <tt/event->source/ and changes the brush size depending
14196 on the pressure.
14197
14198 <tscreen><verb>
14199 /* Draw a rectangle on the screen, size depending on pressure,
14200    and color on the type of device */
14201 static void
14202 draw_brush (GtkWidget *widget, GdkInputSource source,
14203             gdouble x, gdouble y, gdouble pressure)
14204 {
14205   GdkGC *gc;
14206   GdkRectangle update_rect;
14207
14208   switch (source)
14209     {
14210     case GDK_SOURCE_MOUSE:
14211       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
14212       break;
14213     case GDK_SOURCE_PEN:
14214       gc = widget->style->black_gc;
14215       break;
14216     case GDK_SOURCE_ERASER:
14217       gc = widget->style->white_gc;
14218       break;
14219     default:
14220       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
14221     }
14222
14223   update_rect.x = x - 10 * pressure;
14224   update_rect.y = y - 10 * pressure;
14225   update_rect.width = 20 * pressure;
14226   update_rect.height = 20 * pressure;
14227   gdk_draw_rectangle (pixmap, gc, TRUE,
14228                       update_rect.x, update_rect.y,
14229                       update_rect.width, update_rect.height);
14230   gtk_widget_draw (widget, &amp;update_rect);
14231 }
14232 </verb></tscreen>
14233
14234 <sect2> Finding out more about a device
14235 <p>
14236 As an example of how to find out more about a device, our program
14237 will print the name of the device that generates each button
14238 press. To find out the name of a device, we call the function:
14239
14240 <tscreen><verb>
14241 GList *gdk_input_list_devices               (void);
14242 </verb></tscreen>
14243
14244 which returns a GList (a linked list type from the GLib library)
14245 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
14246 as:
14247
14248 <tscreen><verb>
14249 struct _GdkDeviceInfo
14250 {
14251   guint32 deviceid;
14252   gchar *name;
14253   GdkInputSource source;
14254   GdkInputMode mode;
14255   gint has_cursor;
14256   gint num_axes;
14257   GdkAxisUse *axes;
14258   gint num_keys;
14259   GdkDeviceKey *keys;
14260 };
14261 </verb></tscreen>
14262
14263 Most of these fields are configuration information that you can ignore
14264 unless you are implementing XInput configuration saving. The fieldwe
14265 are interested in here is <tt/name/ which is simply the name that X
14266 assigns to the device. The other field that isn't configuration
14267 information is <tt/has_cursor/. If <tt/has_cursor/ is false, then we
14268 we need to draw our own cursor. But since we've specified
14269 <tt/GDK_EXTENSION_EVENTS_CURSOR/, we don't have to worry about this.
14270
14271 Our <tt/print_button_press()/ function simply iterates through
14272 the returned list until it finds a match, then prints out
14273 the name of the device.
14274
14275 <tscreen><verb>
14276 static void
14277 print_button_press (guint32 deviceid)
14278 {
14279   GList *tmp_list;
14280
14281   /* gdk_input_list_devices returns an internal list, so we shouldn't
14282      free it afterwards */
14283   tmp_list = gdk_input_list_devices();
14284
14285   while (tmp_list)
14286     {
14287       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
14288
14289       if (info->deviceid == deviceid)
14290         {
14291           printf("Button press on device '%s'\n", info->name);
14292           return;
14293         }
14294
14295       tmp_list = tmp_list->next;
14296     }
14297 }
14298 </verb></tscreen>
14299
14300 That completes the changes to "XInputize" our program. As with
14301 the first version, the complete source is available at the location
14302 from which you got this tutorial, or from:
14303
14304 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
14305 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
14306
14307
14308 <sect2> Further sophistications <label id="sec_Further_Sophistications">
14309 <p>
14310 Although our program now supports XInput quite well, it lacks some
14311 features we would want in a full-featured application. First, the user
14312 probably doesn't want to have to configure their device each time they
14313 run the program, so we should allow them to save the device
14314 configuration. This is done by iterating through the return of
14315 <tt/gdk_input_list_devices()/ and writing out the configuration to a
14316 file.
14317
14318 To restore the state next time the program is run, GDK provides
14319 functions to change device configuration:
14320
14321 <tscreen><verb>
14322 gdk_input_set_extension_events()
14323 gdk_input_set_source()
14324 gdk_input_set_mode()
14325 gdk_input_set_axes()
14326 gdk_input_set_key()
14327 </verb></tscreen>
14328
14329 (The list returned from <tt/gdk_input_list_devices()/ should not be
14330 modified directly.) An example of doing this can be found in the
14331 drawing program gsumi. (Available from <htmlurl
14332 url="http://www.msc.cornell.edu/~otaylor/gsumi/"
14333 name="http://www.msc.cornell.edu/~otaylor/gsumi/">) Eventually, it
14334 would be nice to have a standard way of doing this for all
14335 applications. This probably belongs at a slightly higher level than
14336 GTK, perhaps in the GNOME library.
14337
14338 Another major omission that we have mentioned above is the lack of
14339 cursor drawing. Platforms other than XFree86 currently do not allow
14340 simultaneously using a device as both the core pointer and directly by
14341 an application. See the <url
14342 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
14343 name="XInput-HOWTO"> for more information about this. This means that
14344 applications that want to support the widest audience need to draw
14345 their own cursor.
14346
14347 An application that draws its own cursor needs to do two things:
14348 determine if the current device needs a cursor drawn or not, and
14349 determine if the current device is in proximity. (If the current
14350 device is a drawing tablet, it's a nice touch to make the cursor 
14351 disappear when the stylus is lifted from the tablet. When the
14352 device is touching the stylus, that is called "in proximity.")
14353 The first is done by searching the device list, as we did
14354 to find out the device name. The second is achieved by selecting
14355 "proximity_out" events. An example of drawing one's own cursor is
14356 found in the "testinput" program found in the GTK distribution.
14357
14358 <!-- ***************************************************************** -->
14359 <sect>Tips For Writing GTK Applications
14360 <!-- ***************************************************************** -->
14361 <p>
14362 This section is simply a gathering of wisdom, general style guidelines
14363 and hints to creating good GTK applications. Currently this section
14364 is very short, but I hope it will get longer in future editions of
14365 this tutorial.
14366
14367 Use GNU autoconf and automake! They are your friends :) Automake
14368 examines C files, determines how they depend on each other, and
14369 generates a Makefile so the files can be compiled in the correct
14370 order. Autoconf permits automatic configuration of software
14371 installation, handling a large number of system quirks to increase
14372 portability. I am planning to make a quick intro on them here.
14373
14374 When writing C code, use only C comments (beginning with "/*" and
14375 ending with "*/"), and don't use C++-style comments ("//").  Although
14376 many C compilers understand C++ comments, others don't, and the ANSI C
14377 standard does not require that C++-style comments be processed as
14378 comments.
14379
14380 <!-- ***************************************************************** -->
14381 <sect>Contributing <label id="sec_Contributing">
14382 <!-- ***************************************************************** -->
14383 <p>
14384 This document, like so much other great software out there, was
14385 created for free by volunteers.  If you are at all knowledgeable about
14386 any aspect of GTK that does not already have documentation, please
14387 consider contributing to this document.
14388
14389 If you do decide to contribute, please mail your text to Tony Gale,
14390 <tt><htmlurl url="mailto:gale@gtk.org"
14391 name="gale@gtk.org"></tt>. Also, be aware that the entirety of this
14392 document is free, and any addition by you provide must also be
14393 free. That is, people may use any portion of your examples in their
14394 programs, and copies of this document may be distributed at will, etc.
14395
14396 Thank you.
14397
14398 <!-- ***************************************************************** -->
14399 <sect>Credits
14400 <!-- ***************************************************************** -->
14401 <p>
14402 We would like to thank the following for their contributions to this text.
14403
14404 <itemize>
14405 <item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com"
14406 name="chamele0n@geocities.com"></tt> for the menus tutorial.                          
14407
14408 <item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org"
14409 name="raph@acm.org"></tt>
14410 for hello world ala GTK, widget packing, and general all around wisdom.
14411 He's also generously donated a home for this tutorial.
14412
14413 <item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
14414 name="petm@xcf.berkeley.edu"></tt> for the simplest GTK program.. 
14415 and the ability to make it :)
14416
14417 <item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de"
14418 name="werner.koch@guug.de"></tt> for converting the original plain text to
14419 SGML, and the widget class hierarchy.
14420
14421 <item>Mark Crichton <tt><htmlurl
14422 url="mailto:crichton@expert.cc.purdue.edu"
14423 name="crichton@expert.cc.purdue.edu"></tt> for the menu factory code,
14424 and the table packing tutorial.
14425
14426 <item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu"
14427 name="owt1@cornell.edu"></tt> for the EventBox widget section (and the
14428 patch to the distro).  He's also responsible for the selections code
14429 and tutorial, as well as the sections on writing your own GTK widgets,
14430 and the example application. Thanks a lot Owen for all you help!
14431
14432 <item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu"
14433 name="mvboom42@calvin.edu"></tt> for his wonderful work on the
14434 Notebook, Progress Bar, Dialogs, and File selection widgets.  Thanks a
14435 lot Mark!  You've been a great help.
14436
14437 <item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org"
14438 name="timj@psynet.net"></tt> for his great job on the Lists
14439 Widget. His excellent work on automatically extracting the widget tree
14440 and signal information from GTK. Thanks Tim :)
14441
14442 <item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com"
14443 name="rajat@ix.netcom.com"</tt> for the excellent job on the Pixmap
14444 tutorial.
14445
14446 <item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com"
14447 name="johnsonm@redhat.com"></tt> for info and code for popup menus.
14448
14449 <item>David Huggins-Daines <tt><htmlurl
14450 url="mailto:bn711@freenet.carleton.ca"
14451 name="bn711@freenet.carleton.ca"></tt> for the Range Widgets and Tree
14452 Widget sections.
14453
14454 <item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se"
14455 name="mars@lysator.liu.se"></tt> for the CList section.
14456
14457 <item>David A. Wheeler <tt><htmlurl url="mailto:dwheeler@ida.org"
14458 name="dwheeler@ida.org"></tt> for portions of the text on GLib
14459 and various tutorial fixups and improvements.
14460 The GLib text was in turn based on material developed by Damon Chaplin
14461 <tt><htmlurl url="mailto:DAChaplin@msn.com" name="DAChaplin@msn.com"></tt>
14462
14463 <item>David King for style checking the entire document.
14464 </itemize>
14465
14466 And to all of you who commented on and helped refine this document.
14467
14468 Thanks.
14469
14470 <!-- ***************************************************************** -->
14471 <sect> Tutorial Copyright and Permissions Notice
14472 <!-- ***************************************************************** -->
14473
14474 <p>
14475 The GTK Tutorial is Copyright (C) 1997 Ian Main. 
14476
14477 Copyright (C) 1998-1999 Tony Gale.
14478
14479 Permission is granted to make and distribute verbatim copies of this 
14480 manual provided the copyright notice and this permission notice are 
14481 preserved on all copies.
14482
14483 Permission is granted to copy and distribute modified versions of 
14484 this document under the conditions for verbatim copying, provided that 
14485 this copyright notice is included exactly as in the original,
14486 and that the entire resulting derived work is distributed under 
14487 the terms of a permission notice identical to this one.
14488 <P>Permission is granted to copy and distribute translations of this 
14489 document into another language, under the above conditions for modified 
14490 versions.
14491
14492 If you are intending to incorporate this document into a published 
14493 work, please contact the maintainer, and we will make an effort 
14494 to ensure that you have the most up to date information available.
14495
14496 There is no guarantee that this document lives up to its intended
14497 purpose.  This is simply provided as a free resource.  As such,
14498 the authors and maintainers of the information provided within can
14499 not make any guarantee that the information is even accurate.
14500
14501 <!-- ***************************************************************** -->
14502 <appendix>
14503 <!-- ***************************************************************** -->
14504
14505 <!-- ***************************************************************** -->
14506 <sect> GTK Signals <label id="sec_GTK_Signals">
14507 <!-- ***************************************************************** -->
14508 <p>
14509 As GTK is an object oriented widget set, it has a hierarchy of
14510 inheritance. This inheritance mechanism applies for
14511 signals. Therefore, you should refer to the widget hierarchy tree when
14512 using the signals listed in this section.
14513
14514 <!-- ----------------------------------------------------------------- -->
14515 <sect1>GtkObject
14516 <!-- ----------------------------------------------------------------- -->
14517 <p>
14518 <tscreen><verb>
14519 void GtkObject::destroy (GtkObject *,
14520                          gpointer);
14521 </verb></tscreen>
14522
14523 <!-- ----------------------------------------------------------------- -->
14524 <sect1>GtkWidget
14525 <!-- ----------------------------------------------------------------- -->
14526 <p>
14527 <tscreen><verb>
14528
14529 void GtkWidget::show    (GtkWidget *,
14530                          gpointer);
14531 void GtkWidget::hide    (GtkWidget *,
14532                          gpointer);
14533 void GtkWidget::map     (GtkWidget *,
14534                          gpointer);
14535 void GtkWidget::unmap   (GtkWidget *,
14536                          gpointer);
14537 void GtkWidget::realize (GtkWidget *,
14538                          gpointer);
14539 void GtkWidget::unrealize       (GtkWidget *,
14540                                  gpointer);
14541 void GtkWidget::draw    (GtkWidget *,
14542                          ggpointer,
14543                          gpointer);
14544 void GtkWidget::draw-focus      (GtkWidget *,
14545                                  gpointer);
14546 void GtkWidget::draw-default    (GtkWidget *,
14547                                  gpointer);
14548 void GtkWidget::size-request    (GtkWidget *,
14549                                  ggpointer,
14550                                  gpointer);
14551 void GtkWidget::size-allocate   (GtkWidget *,
14552                                  ggpointer,
14553                                  gpointer);
14554 void GtkWidget::state-changed   (GtkWidget *,
14555                                  GtkStateType,
14556                                  gpointer);
14557 void GtkWidget::parent-set      (GtkWidget *,
14558                                  GtkObject *,
14559                                  gpointer);
14560 void GtkWidget::style-set       (GtkWidget *,
14561                                  GtkStyle *,
14562                                  gpointer);
14563 void GtkWidget::add-accelerator (GtkWidget *,
14564                                  gguint,
14565                                  GtkAccelGroup *,
14566                                  gguint,
14567                                  GdkModifierType,
14568                                  GtkAccelFlags,
14569                                  gpointer);
14570 void GtkWidget::remove-accelerator      (GtkWidget *,
14571                                          GtkAccelGroup *,
14572                                          gguint,
14573                                          GdkModifierType,
14574                                          gpointer);
14575 gboolean GtkWidget::event       (GtkWidget *,
14576                                  GdkEvent *,
14577                                  gpointer);
14578 gboolean GtkWidget::button-press-event  (GtkWidget *,
14579                                          GdkEvent *,
14580                                          gpointer);
14581 gboolean GtkWidget::button-release-event        (GtkWidget *,
14582                                                  GdkEvent *,
14583                                                  gpointer);
14584 gboolean GtkWidget::motion-notify-event (GtkWidget *,
14585                                          GdkEvent *,
14586                                          gpointer);
14587 gboolean GtkWidget::delete-event        (GtkWidget *,
14588                                          GdkEvent *,
14589                                          gpointer);
14590 gboolean GtkWidget::destroy-event       (GtkWidget *,
14591                                          GdkEvent *,
14592                                          gpointer);
14593 gboolean GtkWidget::expose-event        (GtkWidget *,
14594                                          GdkEvent *,
14595                                          gpointer);
14596 gboolean GtkWidget::key-press-event     (GtkWidget *,
14597                                          GdkEvent *,
14598                                          gpointer);
14599 gboolean GtkWidget::key-release-event   (GtkWidget *,
14600                                          GdkEvent *,
14601                                          gpointer);
14602 gboolean GtkWidget::enter-notify-event  (GtkWidget *,
14603                                          GdkEvent *,
14604                                          gpointer);
14605 gboolean GtkWidget::leave-notify-event  (GtkWidget *,
14606                                          GdkEvent *,
14607                                          gpointer);
14608 gboolean GtkWidget::configure-event     (GtkWidget *,
14609                                          GdkEvent *,
14610                                          gpointer);
14611 gboolean GtkWidget::focus-in-event      (GtkWidget *,
14612                                          GdkEvent *,
14613                                          gpointer);
14614 gboolean GtkWidget::focus-out-event     (GtkWidget *,
14615                                          GdkEvent *,
14616                                          gpointer);
14617 gboolean GtkWidget::map-event   (GtkWidget *,
14618                                  GdkEvent *,
14619                                  gpointer);
14620 gboolean GtkWidget::unmap-event (GtkWidget *,
14621                                  GdkEvent *,
14622                                  gpointer);
14623 gboolean GtkWidget::property-notify-event       (GtkWidget *,
14624                                                  GdkEvent *,
14625                                                  gpointer);
14626 gboolean GtkWidget::selection-clear-event       (GtkWidget *,
14627                                                  GdkEvent *,
14628                                                  gpointer);
14629 gboolean GtkWidget::selection-request-event     (GtkWidget *,
14630                                                  GdkEvent *,
14631                                                  gpointer);
14632 gboolean GtkWidget::selection-notify-event      (GtkWidget *,
14633                                                  GdkEvent *,
14634                                                  gpointer);
14635 void GtkWidget::selection-get   (GtkWidget *,
14636                                  GtkSelectionData *,
14637                                  gguint,
14638                                  gpointer);
14639 void GtkWidget::selection-received      (GtkWidget *,
14640                                          GtkSelectionData *,
14641                                          gguint,
14642                                          gpointer);
14643 gboolean GtkWidget::proximity-in-event  (GtkWidget *,
14644                                          GdkEvent *,
14645                                          gpointer);
14646 gboolean GtkWidget::proximity-out-event (GtkWidget *,
14647                                          GdkEvent *,
14648                                          gpointer);
14649 void GtkWidget::drag-begin      (GtkWidget *,
14650                                  GdkDragContext *,
14651                                  gpointer);
14652 void GtkWidget::drag-end        (GtkWidget *,
14653                                  GdkDragContext *,
14654                                  gpointer);
14655 void GtkWidget::drag-data-delete        (GtkWidget *,
14656                                          GdkDragContext *,
14657                                          gpointer);
14658 void GtkWidget::drag-leave      (GtkWidget *,
14659                                  GdkDragContext *,
14660                                  gguint,
14661                                  gpointer);
14662 gboolean GtkWidget::drag-motion (GtkWidget *,
14663                                  GdkDragContext *,
14664                                  ggint,
14665                                  ggint,
14666                                  gguint,
14667                                  gpointer);
14668 gboolean GtkWidget::drag-drop   (GtkWidget *,
14669                                  GdkDragContext *,
14670                                  ggint,
14671                                  ggint,
14672                                  gguint,
14673                                  gpointer);
14674 void GtkWidget::drag-data-get   (GtkWidget *,
14675                                  GdkDragContext *,
14676                                  GtkSelectionData *,
14677                                  gguint,
14678                                  gguint,
14679                                  gpointer);
14680 void GtkWidget::drag-data-received      (GtkWidget *,
14681                                          GdkDragContext *,
14682                                          ggint,
14683                                          ggint,
14684                                          GtkSelectionData *,
14685                                          gguint,
14686                                          gguint,
14687                                          gpointer);
14688 gboolean GtkWidget::client-event        (GtkWidget *,
14689                                          GdkEvent *,
14690                                          gpointer);
14691 gboolean GtkWidget::no-expose-event     (GtkWidget *,
14692                                          GdkEvent *,
14693                                          gpointer);
14694 gboolean GtkWidget::visibility-notify-event     (GtkWidget *,
14695                                                  GdkEvent *,
14696                                                  gpointer);
14697 void GtkWidget::debug-msg       (GtkWidget *,
14698                                  GtkString *,
14699                                  gpointer);
14700 </verb></tscreen>
14701
14702 <!-- ----------------------------------------------------------------- -->
14703 <sect1>GtkData
14704 <!-- ----------------------------------------------------------------- -->
14705 <p>
14706 <tscreen><verb>
14707 void GtkData::disconnect        (GtkData *,
14708                                  gpointer);
14709 </verb></tscreen>
14710
14711 <!-- ----------------------------------------------------------------- -->
14712 <sect1>GtkContainer
14713 <!-- ----------------------------------------------------------------- -->
14714 <p>
14715 <tscreen><verb>
14716 void GtkContainer::add  (GtkContainer *,
14717                          GtkWidget *,
14718                          gpointer);
14719 void GtkContainer::remove       (GtkContainer *,
14720                                  GtkWidget *,
14721                                  gpointer);
14722 void GtkContainer::check-resize (GtkContainer *,
14723                                  gpointer);
14724 GtkDirectionType GtkContainer::focus    (GtkContainer *,
14725                                          GtkDirectionType,
14726                                          gpointer);
14727 void GtkContainer::set-focus-child      (GtkContainer *,
14728                                          GtkWidget *,
14729                                          gpointer);
14730 </verb></tscreen>
14731
14732 <!-- ----------------------------------------------------------------- -->
14733 <sect1>GtkCalendar
14734 <!-- ----------------------------------------------------------------- -->
14735 <p>
14736 <tscreen><verb>
14737 void GtkCalendar::month-changed (GtkCalendar *,
14738                                  gpointer);
14739 void GtkCalendar::day-selected  (GtkCalendar *,
14740                                  gpointer);
14741 void GtkCalendar::day-selected-double-click     (GtkCalendar *,
14742                                                  gpointer);
14743 void GtkCalendar::prev-month    (GtkCalendar *,
14744                                  gpointer);
14745 void GtkCalendar::next-month    (GtkCalendar *,
14746                                  gpointer);
14747 void GtkCalendar::prev-year     (GtkCalendar *,
14748                                  gpointer);
14749 void GtkCalendar::next-year     (GtkCalendar *,
14750                                  gpointer);
14751 </verb></tscreen>
14752
14753 <!-- ----------------------------------------------------------------- -->
14754 <sect1>GtkEditable
14755 <!-- ----------------------------------------------------------------- -->
14756 <p>
14757 <tscreen><verb>
14758 void GtkEditable::changed       (GtkEditable *,
14759                                  gpointer);
14760 void GtkEditable::insert-text   (GtkEditable *,
14761                                  GtkString *,
14762                                  ggint,
14763                                  ggpointer,
14764                                  gpointer);
14765 void GtkEditable::delete-text   (GtkEditable *,
14766                                  ggint,
14767                                  ggint,
14768                                  gpointer);
14769 void GtkEditable::activate      (GtkEditable *,
14770                                  gpointer);
14771 void GtkEditable::set-editable  (GtkEditable *,
14772                                  gboolean,
14773                                  gpointer);
14774 void GtkEditable::move-cursor   (GtkEditable *,
14775                                  ggint,
14776                                  ggint,
14777                                  gpointer);
14778 void GtkEditable::move-word     (GtkEditable *,
14779                                  ggint,
14780                                  gpointer);
14781 void GtkEditable::move-page     (GtkEditable *,
14782                                  ggint,
14783                                  ggint,
14784                                  gpointer);
14785 void GtkEditable::move-to-row   (GtkEditable *,
14786                                  ggint,
14787                                  gpointer);
14788 void GtkEditable::move-to-column        (GtkEditable *,
14789                                          ggint,
14790                                          gpointer);
14791 void GtkEditable::kill-char     (GtkEditable *,
14792                                  ggint,
14793                                  gpointer);
14794 void GtkEditable::kill-word     (GtkEditable *,
14795                                  ggint,
14796                                  gpointer);
14797 void GtkEditable::kill-line     (GtkEditable *,
14798                                  ggint,
14799                                  gpointer);
14800 void GtkEditable::cut-clipboard (GtkEditable *,
14801                                  gpointer);
14802 void GtkEditable::copy-clipboard        (GtkEditable *,
14803                                          gpointer);
14804 void GtkEditable::paste-clipboard       (GtkEditable *,
14805                                          gpointer);
14806 </verb></tscreen>
14807
14808 <!-- ----------------------------------------------------------------- -->
14809 <sect1>GtkTipsQuery
14810 <!-- ----------------------------------------------------------------- -->
14811 <p>
14812 <tscreen><verb>
14813 void GtkTipsQuery::start-query  (GtkTipsQuery *,
14814                                  gpointer);
14815 void GtkTipsQuery::stop-query   (GtkTipsQuery *,
14816                                  gpointer);
14817 void GtkTipsQuery::widget-entered       (GtkTipsQuery *,
14818                                          GtkWidget *,
14819                                          GtkString *,
14820                                          GtkString *,
14821                                          gpointer);
14822 gboolean GtkTipsQuery::widget-selected  (GtkTipsQuery *,
14823                                          GtkWidget *,
14824                                          GtkString *,
14825                                          GtkString *,
14826                                          GdkEvent *,
14827                                          gpointer);
14828 </verb></tscreen>
14829
14830 <!-- ----------------------------------------------------------------- -->
14831 <sect1>GtkCList
14832 <!-- ----------------------------------------------------------------- -->
14833 <p>
14834 <tscreen><verb>
14835 void GtkCList::select-row       (GtkCList *,
14836                                  ggint,
14837                                  ggint,
14838                                  GdkEvent *,
14839                                  gpointer);
14840 void GtkCList::unselect-row     (GtkCList *,
14841                                  ggint,
14842                                  ggint,
14843                                  GdkEvent *,
14844                                  gpointer);
14845 void GtkCList::row-move (GtkCList *,
14846                          ggint,
14847                          ggint,
14848                          gpointer);
14849 void GtkCList::click-column     (GtkCList *,
14850                                  ggint,
14851                                  gpointer);
14852 void GtkCList::resize-column    (GtkCList *,
14853                                  ggint,
14854                                  ggint,
14855                                  gpointer);
14856 void GtkCList::toggle-focus-row (GtkCList *,
14857                                  gpointer);
14858 void GtkCList::select-all       (GtkCList *,
14859                                  gpointer);
14860 void GtkCList::unselect-all     (GtkCList *,
14861                                  gpointer);
14862 void GtkCList::undo-selection   (GtkCList *,
14863                                  gpointer);
14864 void GtkCList::start-selection  (GtkCList *,
14865                                  gpointer);
14866 void GtkCList::end-selection    (GtkCList *,
14867                                  gpointer);
14868 void GtkCList::toggle-add-mode  (GtkCList *,
14869                                  gpointer);
14870 void GtkCList::extend-selection (GtkCList *,
14871                                  GtkScrollType,
14872                                  ggfloat,
14873                                  gboolean,
14874                                  gpointer);
14875 void GtkCList::scroll-vertical  (GtkCList *,
14876                                  GtkScrollType,
14877                                  ggfloat,
14878                                  gpointer);
14879 void GtkCList::scroll-horizontal        (GtkCList *,
14880                                          GtkScrollType,
14881                                          ggfloat,
14882                                          gpointer);
14883 void GtkCList::abort-column-resize      (GtkCList *,
14884                                          gpointer);
14885 </verb></tscreen>
14886
14887 <!-- ----------------------------------------------------------------- -->
14888 <sect1>GtkNotebook
14889 <!-- ----------------------------------------------------------------- -->
14890 <p>
14891 <tscreen><verb>
14892 void GtkNotebook::switch-page   (GtkNotebook *,
14893                                  ggpointer,
14894                                  gguint,
14895                                  gpointer);
14896
14897 </verb></tscreen>
14898
14899 <!-- ----------------------------------------------------------------- -->
14900 <sect1>GtkList
14901 <!-- ----------------------------------------------------------------- -->
14902 <p>
14903 <tscreen><verb>
14904 void GtkList::selection-changed (GtkList *,
14905                                  gpointer);
14906 void GtkList::select-child      (GtkList *,
14907                                  GtkWidget *,
14908                                  gpointer);
14909 void GtkList::unselect-child    (GtkList *,
14910                                  GtkWidget *,
14911                                  gpointer);
14912 </verb></tscreen>
14913
14914 <!-- ----------------------------------------------------------------- -->
14915 <sect1>GtkMenuShell
14916 <!-- ----------------------------------------------------------------- -->
14917 <p>
14918 <tscreen><verb>
14919 void GtkMenuShell::deactivate   (GtkMenuShell *,
14920                                  gpointer);
14921 void GtkMenuShell::selection-done       (GtkMenuShell *,
14922                                          gpointer);
14923 void GtkMenuShell::move-current (GtkMenuShell *,
14924                                  GtkMenuDirectionType,
14925                                  gpointer);
14926 void GtkMenuShell::activate-current     (GtkMenuShell *,
14927                                          gboolean,
14928                                          gpointer);
14929 void GtkMenuShell::cancel       (GtkMenuShell *,
14930                                  gpointer);
14931 </verb></tscreen>
14932
14933 <!-- ----------------------------------------------------------------- -->
14934 <sect1>GtkToolbar
14935 <!-- ----------------------------------------------------------------- -->
14936 <p>
14937 <tscreen><verb>
14938 void GtkToolbar::orientation-changed    (GtkToolbar *,
14939                                          ggint,
14940                                          gpointer);
14941 void GtkToolbar::style-changed  (GtkToolbar *,
14942                                  ggint,
14943                                  gpointer);
14944 </verb></tscreen>
14945
14946 <!-- ----------------------------------------------------------------- -->
14947 <sect1>GtkTree
14948 <!-- ----------------------------------------------------------------- -->
14949 <p>
14950 <tscreen><verb>
14951 void GtkTree::selection-changed (GtkTree *,
14952                                  gpointer);
14953 void GtkTree::select-child      (GtkTree *,
14954                                  GtkWidget *,
14955                                  gpointer);
14956 void GtkTree::unselect-child    (GtkTree *,
14957                                  GtkWidget *,
14958                                  gpointer);
14959 </verb></tscreen>
14960
14961 <!-- ----------------------------------------------------------------- -->
14962 <sect1>GtkButton
14963 <!-- ----------------------------------------------------------------- -->
14964 <p>
14965 <tscreen><verb>
14966 void GtkButton::pressed (GtkButton *,
14967                          gpointer);
14968 void GtkButton::released        (GtkButton *,
14969                                  gpointer);
14970 void GtkButton::clicked (GtkButton *,
14971                          gpointer);
14972 void GtkButton::enter   (GtkButton *,
14973                          gpointer);
14974 void GtkButton::leave   (GtkButton *,
14975                          gpointer);
14976 </verb></tscreen>
14977
14978 <!-- ----------------------------------------------------------------- -->
14979 <sect1>GtkItem
14980 <!-- ----------------------------------------------------------------- -->
14981 <p>
14982 <tscreen><verb>
14983 void GtkItem::select    (GtkItem *,
14984                          gpointer);
14985 void GtkItem::deselect  (GtkItem *,
14986                          gpointer);
14987 void GtkItem::toggle    (GtkItem *,
14988                          gpointer);
14989 </verb></tscreen>
14990
14991 <!-- ----------------------------------------------------------------- -->
14992 <sect1>GtkWindow
14993 <!-- ----------------------------------------------------------------- -->
14994 <p>
14995 <tscreen><verb>
14996 void GtkWindow::set-focus       (GtkWindow *,
14997                                  ggpointer,
14998                                  gpointer);
14999 </verb></tscreen>
15000
15001 <!-- ----------------------------------------------------------------- -->
15002 <sect1>GtkHandleBox
15003 <!-- ----------------------------------------------------------------- -->
15004 <p>
15005 <tscreen><verb>
15006 void GtkHandleBox::child-attached       (GtkHandleBox *,
15007                                          GtkWidget *,
15008                                          gpointer);
15009 void GtkHandleBox::child-detached       (GtkHandleBox *,
15010                                          GtkWidget *,
15011                                          gpointer);
15012 </verb></tscreen>
15013
15014 <!-- ----------------------------------------------------------------- -->
15015 <sect1>GtkToggleButton
15016 <!-- ----------------------------------------------------------------- -->
15017 <p>
15018 <tscreen><verb>
15019 void GtkToggleButton::toggled   (GtkToggleButton *,
15020                                  gpointer);
15021
15022 </verb></tscreen>
15023
15024 <!-- ----------------------------------------------------------------- -->
15025 <sect1>GtkMenuItem
15026 <!-- ----------------------------------------------------------------- -->
15027 <p>
15028 <tscreen><verb>
15029 void GtkMenuItem::activate      (GtkMenuItem *,
15030                                  gpointer);
15031 void GtkMenuItem::activate-item (GtkMenuItem *,
15032                                  gpointer);
15033 </verb></tscreen>
15034
15035 <!-- ----------------------------------------------------------------- -->
15036 <sect1>GtkListItem
15037 <!-- ----------------------------------------------------------------- -->
15038 <p>
15039 <tscreen><verb>
15040 void GtkListItem::toggle-focus-row      (GtkListItem *,
15041                                          gpointer);
15042 void GtkListItem::select-all    (GtkListItem *,
15043                                  gpointer);
15044 void GtkListItem::unselect-all  (GtkListItem *,
15045                                  gpointer);
15046 void GtkListItem::undo-selection        (GtkListItem *,
15047                                          gpointer);
15048 void GtkListItem::start-selection       (GtkListItem *,
15049                                          gpointer);
15050 void GtkListItem::end-selection (GtkListItem *,
15051                                  gpointer);
15052 void GtkListItem::toggle-add-mode       (GtkListItem *,
15053                                          gpointer);
15054 void GtkListItem::extend-selection      (GtkListItem *,
15055                                          GtkEnum,
15056                                          ggfloat,
15057                                          gboolean,
15058                                          gpointer);
15059 void GtkListItem::scroll-vertical       (GtkListItem *,
15060                                          GtkEnum,
15061                                          ggfloat,
15062                                          gpointer);
15063 void GtkListItem::scroll-horizontal     (GtkListItem *,
15064                                          GtkEnum,
15065                                          ggfloat,
15066                                          gpointer);
15067 </verb></tscreen>
15068
15069 <!-- ----------------------------------------------------------------- -->
15070 <sect1>GtkTreeItem
15071 <!-- ----------------------------------------------------------------- -->
15072 <p>
15073 <tscreen><verb>
15074 void GtkTreeItem::collapse      (GtkTreeItem *,
15075                                  gpointer);
15076 void GtkTreeItem::expand        (GtkTreeItem *,
15077                                  gpointer);
15078 </verb></tscreen>
15079
15080 <!-- ----------------------------------------------------------------- -->
15081 <sect1>GtkCheckMenuItem
15082 <!-- ----------------------------------------------------------------- -->
15083 <p>
15084 <tscreen><verb>
15085 void GtkCheckMenuItem::toggled  (GtkCheckMenuItem *,
15086                                  gpointer);
15087 </verb></tscreen>
15088
15089 <!-- ----------------------------------------------------------------- -->
15090 <sect1>GtkInputDialog
15091 <!-- ----------------------------------------------------------------- -->
15092 <p>
15093 <tscreen><verb>
15094 void GtkInputDialog::enable-device      (GtkInputDialog *,
15095                                          ggint,
15096                                          gpointer);
15097 void GtkInputDialog::disable-device     (GtkInputDialog *,
15098                                          ggint,
15099                                          gpointer);
15100 </verb></tscreen>
15101
15102 <!-- ----------------------------------------------------------------- -->
15103 <sect1>GtkColorSelection
15104 <!-- ----------------------------------------------------------------- -->
15105 <p>
15106 <tscreen><verb>
15107 void GtkColorSelection::color-changed   (GtkColorSelection *,
15108                                          gpointer);
15109 </verb></tscreen>
15110
15111 <!-- ----------------------------------------------------------------- -->
15112 <sect1>GtkStatusBar
15113 <!-- ----------------------------------------------------------------- -->
15114 <p>
15115 <tscreen><verb>
15116 void GtkStatusbar::text-pushed  (GtkStatusbar *,
15117                                  gguint,
15118                                  GtkString *,
15119                                  gpointer);
15120 void GtkStatusbar::text-popped  (GtkStatusbar *,
15121                                  gguint,
15122                                  GtkString *,
15123                                  gpointer);
15124 </verb></tscreen>
15125
15126 <!-- ----------------------------------------------------------------- -->
15127 <sect1>GtkCTree
15128 <!-- ----------------------------------------------------------------- -->
15129 <p>
15130 <tscreen><verb>
15131 void GtkCTree::tree-select-row  (GtkCTree *,
15132                                  GtkCTreeNode *,
15133                                  ggint,
15134                                  gpointer);
15135 void GtkCTree::tree-unselect-row        (GtkCTree *,
15136                                          GtkCTreeNode *,
15137                                          ggint,
15138                                          gpointer);
15139 void GtkCTree::tree-expand      (GtkCTree *,
15140                                  GtkCTreeNode *,
15141                                  gpointer);
15142 void GtkCTree::tree-collapse    (GtkCTree *,
15143                                  ggpointer,
15144                                  gpointer);
15145 void GtkCTree::tree-move        (GtkCTree *,
15146                                  GtkCTreeNode *,
15147                                  GtkCTreeNode *,
15148                                  GtkCTreeNode *,
15149                                  gpointer);
15150 void GtkCTree::change-focus-row-expansion       (GtkCTree *,
15151                                                  GtkCTreeExpansionType,
15152                                                  gpointer);
15153 </verb></tscreen>
15154
15155 <!-- ----------------------------------------------------------------- -->
15156 <sect1>GtkCurve
15157 <!-- ----------------------------------------------------------------- -->
15158 <p>
15159 <tscreen><verb>
15160 void GtkCurve::curve-type-changed       (GtkCurve *,
15161                                          gpointer);
15162 </verb></tscreen>
15163
15164 <!-- ----------------------------------------------------------------- -->
15165 <sect1>GtkAdjustment
15166 <!-- ----------------------------------------------------------------- -->
15167 <p>
15168 <tscreen><verb>
15169 void GtkAdjustment::changed     (GtkAdjustment *,
15170                                  gpointer);
15171 void GtkAdjustment::value-changed       (GtkAdjustment *,
15172                                          gpointer);
15173 </verb></tscreen>
15174
15175 <!-- ***************************************************************** -->
15176 <sect> GDK Event Types<label id="sec_GDK_Event_Types">
15177 <!-- ***************************************************************** -->
15178 <p>
15179 The following data types are passed into event handlers by GTK+. For
15180 each data type listed, the signals that use this data type are listed.
15181
15182 <itemize>
15183 <item>  GdkEvent
15184           <itemize>
15185           <item>drag_end_event
15186           </itemize>
15187
15188 <item>  GdkEventType
15189
15190 <item>  GdkEventAny
15191           <itemize>
15192           <item>delete_event
15193           <item>destroy_event
15194           <item>map_event
15195           <item>unmap_event
15196           <item>no_expose_event
15197           </itemize>
15198
15199 <item>  GdkEventExpose
15200           <itemize>
15201           <item>expose_event
15202           </itemize>
15203
15204 <item>  GdkEventNoExpose
15205
15206 <item>  GdkEventVisibility
15207
15208 <item>  GdkEventMotion
15209           <itemize>
15210           <item>motion_notify_event
15211           </itemize>
15212
15213 <item>  GdkEventButton
15214           <itemize>
15215           <item>button_press_event
15216           <item>button_release_event
15217           </itemize>
15218
15219 <item>  GdkEventKey
15220           <itemize>
15221           <item>key_press_event
15222           <item>key_release_event
15223           </itemize>
15224
15225 <item>  GdkEventCrossing
15226           <itemize>
15227           <item>enter_notify_event
15228           <item>leave_notify_event
15229           </itemize>
15230
15231 <item>  GdkEventFocus
15232           <itemize>
15233           <item>focus_in_event
15234           <item>focus_out_event
15235           </itemize>
15236
15237 <item>  GdkEventConfigure
15238           <itemize>
15239           <item>configure_event
15240           </itemize>
15241
15242 <item>  GdkEventProperty
15243           <itemize>
15244           <item>property_notify_event
15245           </itemize>
15246
15247 <item>  GdkEventSelection
15248           <itemize>
15249           <item>selection_clear_event
15250           <item>selection_request_event
15251           <item>selection_notify_event
15252           </itemize>
15253
15254 <item>  GdkEventProximity
15255           <itemize>
15256           <item>proximity_in_event
15257           <item>proximity_out_event
15258           </itemize>
15259
15260 <item>  GdkEventDragBegin
15261           <itemize>
15262           <item>drag_begin_event
15263           </itemize>
15264
15265 <item>  GdkEventDragRequest
15266           <itemize>
15267           <item>drag_request_event
15268           </itemize>
15269
15270 <item>  GdkEventDropEnter
15271           <itemize>
15272           <item>drop_enter_event
15273           </itemize>
15274
15275 <item>  GdkEventDropLeave
15276           <itemize>
15277           <item>drop_leave_event
15278           </itemize>
15279
15280 <item>  GdkEventDropDataAvailable
15281           <itemize>
15282           <item>drop_data_available_event
15283           </itemize>
15284
15285 <item>  GdkEventClient
15286           <itemize>
15287           <item>client_event
15288           </itemize>
15289
15290 <item>  GdkEventOther
15291           <itemize>
15292           <item>other_event
15293           </itemize>
15294 </itemize>
15295
15296 The data type <tt/GdkEventType/ is a special data type that is used by
15297 all the other data types as an indicator of the data type being passed
15298 to the signal handler. As you will see below, each of the event data
15299 structures has a member of this type. It is defined as an enumeration
15300 type as follows:
15301
15302 <tscreen><verb>
15303 typedef enum
15304 {
15305   GDK_NOTHING           = -1,
15306   GDK_DELETE            = 0,
15307   GDK_DESTROY           = 1,
15308   GDK_EXPOSE            = 2,
15309   GDK_MOTION_NOTIFY     = 3,
15310   GDK_BUTTON_PRESS      = 4,
15311   GDK_2BUTTON_PRESS     = 5,
15312   GDK_3BUTTON_PRESS     = 6,
15313   GDK_BUTTON_RELEASE    = 7,
15314   GDK_KEY_PRESS         = 8,
15315   GDK_KEY_RELEASE       = 9,
15316   GDK_ENTER_NOTIFY      = 10,
15317   GDK_LEAVE_NOTIFY      = 11,
15318   GDK_FOCUS_CHANGE      = 12,
15319   GDK_CONFIGURE         = 13,
15320   GDK_MAP               = 14,
15321   GDK_UNMAP             = 15,
15322   GDK_PROPERTY_NOTIFY   = 16,
15323   GDK_SELECTION_CLEAR   = 17,
15324   GDK_SELECTION_REQUEST = 18,
15325   GDK_SELECTION_NOTIFY  = 19,
15326   GDK_PROXIMITY_IN      = 20,
15327   GDK_PROXIMITY_OUT     = 21,
15328   GDK_DRAG_BEGIN        = 22,
15329   GDK_DRAG_REQUEST      = 23,
15330   GDK_DROP_ENTER        = 24,
15331   GDK_DROP_LEAVE        = 25,
15332   GDK_DROP_DATA_AVAIL   = 26,
15333   GDK_CLIENT_EVENT      = 27,
15334   GDK_VISIBILITY_NOTIFY = 28,
15335   GDK_NO_EXPOSE         = 29,
15336   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
15337 } GdkEventType;
15338 </verb></tscreen>
15339
15340 The other event type that is different from the others is
15341 <tt/GdkEvent/ itself. This is a union of all the other
15342 data types, which allows it to be cast to a specific
15343 event data type within a signal handler.
15344
15345 <!-- Just a big list for now, needs expanding upon - TRG -->
15346 So, the event data types are defined as follows:
15347
15348 <tscreen><verb>
15349 struct _GdkEventAny
15350 {
15351   GdkEventType type;
15352   GdkWindow *window;
15353   gint8 send_event;
15354 };
15355
15356 struct _GdkEventExpose
15357 {
15358   GdkEventType type;
15359   GdkWindow *window;
15360   gint8 send_event;
15361   GdkRectangle area;
15362   gint count; /* If non-zero, how many more events follow. */
15363 };
15364
15365 struct _GdkEventNoExpose
15366 {
15367   GdkEventType type;
15368   GdkWindow *window;
15369   gint8 send_event;
15370   /* XXX: does anyone need the X major_code or minor_code fields? */
15371 };
15372
15373 struct _GdkEventVisibility
15374 {
15375   GdkEventType type;
15376   GdkWindow *window;
15377   gint8 send_event;
15378   GdkVisibilityState state;
15379 };
15380
15381 struct _GdkEventMotion
15382 {
15383   GdkEventType type;
15384   GdkWindow *window;
15385   gint8 send_event;
15386   guint32 time;
15387   gdouble x;
15388   gdouble y;
15389   gdouble pressure;
15390   gdouble xtilt;
15391   gdouble ytilt;
15392   guint state;
15393   gint16 is_hint;
15394   GdkInputSource source;
15395   guint32 deviceid;
15396   gdouble x_root, y_root;
15397 };
15398
15399 struct _GdkEventButton
15400 {
15401   GdkEventType type;
15402   GdkWindow *window;
15403   gint8 send_event;
15404   guint32 time;
15405   gdouble x;
15406   gdouble y;
15407   gdouble pressure;
15408   gdouble xtilt;
15409   gdouble ytilt;
15410   guint state;
15411   guint button;
15412   GdkInputSource source;
15413   guint32 deviceid;
15414   gdouble x_root, y_root;
15415 };
15416
15417 struct _GdkEventKey
15418 {
15419   GdkEventType type;
15420   GdkWindow *window;
15421   gint8 send_event;
15422   guint32 time;
15423   guint state;
15424   guint keyval;
15425   gint length;
15426   gchar *string;
15427 };
15428
15429 struct _GdkEventCrossing
15430 {
15431   GdkEventType type;
15432   GdkWindow *window;
15433   gint8 send_event;
15434   GdkWindow *subwindow;
15435   GdkNotifyType detail;
15436 };
15437
15438 struct _GdkEventFocus
15439 {
15440   GdkEventType type;
15441   GdkWindow *window;
15442   gint8 send_event;
15443   gint16 in;
15444 };
15445
15446 struct _GdkEventConfigure
15447 {
15448   GdkEventType type;
15449   GdkWindow *window;
15450   gint8 send_event;
15451   gint16 x, y;
15452   gint16 width;
15453   gint16 height;
15454 };
15455
15456 struct _GdkEventProperty
15457 {
15458   GdkEventType type;
15459   GdkWindow *window;
15460   gint8 send_event;
15461   GdkAtom atom;
15462   guint32 time;
15463   guint state;
15464 };
15465
15466 struct _GdkEventSelection
15467 {
15468   GdkEventType type;
15469   GdkWindow *window;
15470   gint8 send_event;
15471   GdkAtom selection;
15472   GdkAtom target;
15473   GdkAtom property;
15474   guint32 requestor;
15475   guint32 time;
15476 };
15477
15478 /* This event type will be used pretty rarely. It only is important
15479    for XInput aware programs that are drawing their own cursor */
15480
15481 struct _GdkEventProximity
15482 {
15483   GdkEventType type;
15484   GdkWindow *window;
15485   gint8 send_event;
15486   guint32 time;
15487   GdkInputSource source;
15488   guint32 deviceid;
15489 };
15490
15491 struct _GdkEventDragRequest
15492 {
15493   GdkEventType type;
15494   GdkWindow *window;
15495   gint8 send_event;
15496   guint32 requestor;
15497   union {
15498     struct {
15499       guint protocol_version:4;
15500       guint sendreply:1;
15501       guint willaccept:1;
15502       guint delete_data:1; /* Do *not* delete if link is sent, only
15503                               if data is sent */
15504       guint senddata:1;
15505       guint reserved:22;
15506     } flags;
15507     glong allflags;
15508   } u;
15509   guint8 isdrop; /* This gdk event can be generated by a couple of
15510                     X events - this lets the app know whether the
15511                     drop really occurred or we just set the data */
15512
15513   GdkPoint drop_coords;
15514   gchar *data_type;
15515   guint32 timestamp;
15516 };
15517
15518 struct _GdkEventDragBegin
15519 {
15520   GdkEventType type;
15521   GdkWindow *window;
15522   gint8 send_event;
15523   union {
15524     struct {
15525       guint protocol_version:4;
15526       guint reserved:28;
15527     } flags;
15528     glong allflags;
15529   } u;
15530 };
15531
15532 struct _GdkEventDropEnter
15533 {
15534   GdkEventType type;
15535   GdkWindow *window;
15536   gint8 send_event;
15537   guint32 requestor;
15538   union {
15539     struct {
15540       guint protocol_version:4;
15541       guint sendreply:1;
15542       guint extended_typelist:1;
15543       guint reserved:26;
15544     } flags;
15545     glong allflags;
15546   } u;
15547 };
15548
15549 struct _GdkEventDropLeave
15550 {
15551   GdkEventType type;
15552   GdkWindow *window;
15553   gint8 send_event;
15554   guint32 requestor;
15555   union {
15556     struct {
15557       guint protocol_version:4;
15558       guint reserved:28;
15559     } flags;
15560     glong allflags;
15561   } u;
15562 };
15563
15564 struct _GdkEventDropDataAvailable
15565 {
15566   GdkEventType type;
15567   GdkWindow *window;
15568   gint8 send_event;
15569   guint32 requestor;
15570   union {
15571     struct {
15572       guint protocol_version:4;
15573       guint isdrop:1;
15574       guint reserved:25;
15575     } flags;
15576     glong allflags;
15577   } u;
15578   gchar *data_type; /* MIME type */
15579   gulong data_numbytes;
15580   gpointer data;
15581   guint32 timestamp;
15582   GdkPoint coords;
15583 };
15584
15585 struct _GdkEventClient
15586 {
15587   GdkEventType type;
15588   GdkWindow *window;
15589   gint8 send_event;
15590   GdkAtom message_type;
15591   gushort data_format;
15592   union {
15593     char b[20];
15594     short s[10];
15595     long l[5];
15596   } data;
15597 };
15598
15599 struct _GdkEventOther
15600 {
15601   GdkEventType type;
15602   GdkWindow *window;
15603   gint8 send_event;
15604   GdkXEvent *xevent;
15605 };
15606 </verb></tscreen>
15607
15608 <!-- ***************************************************************** -->
15609 <sect> Code Examples
15610 <!-- ***************************************************************** -->
15611 <p>
15612 Below are the code examples that are used in the above text
15613 which are not included in complete form elsewhere.
15614
15615 <!-- ----------------------------------------------------------------- -->
15616 <sect1>Tictactoe
15617 <!-- ----------------------------------------------------------------- -->
15618 <sect2>tictactoe.h
15619 <p>
15620 <tscreen><verb>
15621 /* example-start tictactoe tictactoe.h */
15622
15623 /* GTK - The GIMP Toolkit
15624  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15625  *
15626  * This library is free software; you can redistribute it and/or
15627  * modify it under the terms of the GNU Library General Public
15628  * License as published by the Free Software Foundation; either
15629  * version 2 of the License, or (at your option) any later version.
15630  *
15631  * This library is distributed in the hope that it will be useful,
15632  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15633  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15634  * Library General Public License for more details.
15635  *
15636  * You should have received a copy of the GNU Library General Public
15637  * License along with this library; if not, write to the
15638  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15639  * Boston, MA 02111-1307, USA.
15640  */
15641 #ifndef __TICTACTOE_H__
15642 #define __TICTACTOE_H__
15643
15644
15645 #include <gdk/gdk.h>
15646 #include <gtk/gtkvbox.h>
15647
15648
15649 #ifdef __cplusplus
15650 extern "C" {
15651 #endif /* __cplusplus */
15652
15653 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
15654 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
15655 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
15656
15657
15658 typedef struct _Tictactoe       Tictactoe;
15659 typedef struct _TictactoeClass  TictactoeClass;
15660
15661 struct _Tictactoe
15662 {
15663   GtkVBox vbox;
15664   
15665   GtkWidget *buttons[3][3];
15666 };
15667
15668 struct _TictactoeClass
15669 {
15670   GtkVBoxClass parent_class;
15671
15672   void (* tictactoe) (Tictactoe *ttt);
15673 };
15674
15675 guint          tictactoe_get_type        (void);
15676 GtkWidget*     tictactoe_new             (void);
15677 void           tictactoe_clear           (Tictactoe *ttt);
15678
15679 #ifdef __cplusplus
15680 }
15681 #endif /* __cplusplus */
15682
15683 #endif /* __TICTACTOE_H__ */
15684
15685 /* example-end */
15686 </verb></tscreen>
15687
15688 <!-- ----------------------------------------------------------------- -->
15689 <sect2>tictactoe.c
15690 <p>
15691 <tscreen><verb>
15692 /* example-start tictactoe tictactoe.c */
15693
15694 /* GTK - The GIMP Toolkit
15695  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15696  *
15697  * This library is free software; you can redistribute it and/or
15698  * modify it under the terms of the GNU Library General Public
15699  * License as published by the Free Software Foundation; either
15700  * version 2 of the License, or (at your option) any later version.
15701  *
15702  * This library is distributed in the hope that it will be useful,
15703  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15704  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15705  * Library General Public License for more details.
15706  *
15707  * You should have received a copy of the GNU Library General Public
15708  * License along with this library; if not, write to the
15709  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15710  * Boston, MA 02111-1307, USA.
15711  */
15712 #include "gtk/gtksignal.h"
15713 #include "gtk/gtktable.h"
15714 #include "gtk/gtktogglebutton.h"
15715 #include "tictactoe.h"
15716
15717 enum {
15718   TICTACTOE_SIGNAL,
15719   LAST_SIGNAL
15720 };
15721
15722 static void tictactoe_class_init          (TictactoeClass *klass);
15723 static void tictactoe_init                (Tictactoe      *ttt);
15724 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
15725
15726 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
15727
15728 guint
15729 tictactoe_get_type ()
15730 {
15731   static guint ttt_type = 0;
15732
15733   if (!ttt_type)
15734     {
15735       GtkTypeInfo ttt_info =
15736       {
15737         "Tictactoe",
15738         sizeof (Tictactoe),
15739         sizeof (TictactoeClass),
15740         (GtkClassInitFunc) tictactoe_class_init,
15741         (GtkObjectInitFunc) tictactoe_init,
15742         (GtkArgSetFunc) NULL,
15743         (GtkArgGetFunc) NULL
15744       };
15745
15746       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
15747     }
15748
15749   return ttt_type;
15750 }
15751
15752 static void
15753 tictactoe_class_init (TictactoeClass *class)
15754 {
15755   GtkObjectClass *object_class;
15756
15757   object_class = (GtkObjectClass*) class;
15758   
15759   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
15760                                          GTK_RUN_FIRST,
15761                                          object_class->type,
15762                                          GTK_SIGNAL_OFFSET (TictactoeClass,
15763                                                             tictactoe),
15764                                          gtk_signal_default_marshaller,
15765                                          GTK_TYPE_NONE, 0);
15766
15767
15768   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
15769
15770   class->tictactoe = NULL;
15771 }
15772
15773 static void
15774 tictactoe_init (Tictactoe *ttt)
15775 {
15776   GtkWidget *table;
15777   gint i,j;
15778   
15779   table = gtk_table_new (3, 3, TRUE);
15780   gtk_container_add (GTK_CONTAINER(ttt), table);
15781   gtk_widget_show (table);
15782
15783   for (i=0;i<3; i++)
15784     for (j=0;j<3; j++)
15785       {
15786         ttt->buttons[i][j] = gtk_toggle_button_new ();
15787         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
15788                                    i, i+1, j, j+1);
15789         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
15790                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
15791         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
15792         gtk_widget_show (ttt->buttons[i][j]);
15793       }
15794 }
15795
15796 GtkWidget*
15797 tictactoe_new ()
15798 {
15799   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
15800 }
15801
15802 void           
15803 tictactoe_clear (Tictactoe *ttt)
15804 {
15805   int i,j;
15806
15807   for (i=0;i<3;i++)
15808     for (j=0;j<3;j++)
15809       {
15810         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
15811         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
15812                                      FALSE);
15813         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
15814       }
15815 }
15816
15817 static void
15818 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
15819 {
15820   int i,k;
15821
15822   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
15823                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
15824                              { 0, 1, 2 }, { 0, 1, 2 } };
15825   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
15826                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
15827                              { 0, 1, 2 }, { 2, 1, 0 } };
15828
15829   int success, found;
15830
15831   for (k=0; k<8; k++)
15832     {
15833       success = TRUE;
15834       found = FALSE;
15835
15836       for (i=0;i<3;i++)
15837         {
15838           success = success &amp;&amp; 
15839             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
15840           found = found ||
15841             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
15842         }
15843       
15844       if (success &amp;&amp; found)
15845         {
15846           gtk_signal_emit (GTK_OBJECT (ttt), 
15847                            tictactoe_signals[TICTACTOE_SIGNAL]);
15848           break;
15849         }
15850     }
15851 }
15852
15853 /* example-end */
15854 </verb></tscreen>
15855
15856 <!-- ----------------------------------------------------------------- -->
15857 <sect2>ttt_test.c
15858 <p>
15859 <tscreen><verb>
15860 /* example-start tictactoe ttt_test.c */
15861
15862 #include <gtk/gtk.h>
15863 #include "tictactoe.h"
15864
15865 void
15866 win (GtkWidget *widget, gpointer data)
15867 {
15868   g_print ("Yay!\n");
15869   tictactoe_clear (TICTACTOE (widget));
15870 }
15871
15872 int 
15873 main (int argc, char *argv[])
15874 {
15875   GtkWidget *window;
15876   GtkWidget *ttt;
15877   
15878   gtk_init (&amp;argc, &amp;argv);
15879
15880   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15881   
15882   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
15883   
15884   gtk_signal_connect (GTK_OBJECT (window), "destroy",
15885                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
15886   
15887   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
15888
15889   ttt = tictactoe_new ();
15890   
15891   gtk_container_add (GTK_CONTAINER (window), ttt);
15892   gtk_widget_show (ttt);
15893
15894   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
15895                       GTK_SIGNAL_FUNC (win), NULL);
15896
15897   gtk_widget_show (window);
15898   
15899   gtk_main ();
15900   
15901   return 0;
15902 }
15903
15904 /* example-end */
15905 </verb></tscreen>
15906
15907 <!-- ----------------------------------------------------------------- -->
15908 <sect1> GtkDial
15909
15910 <!-- ----------------------------------------------------------------- -->
15911 <sect2> gtkdial.h
15912 <p>
15913 <tscreen><verb>
15914 /* example-start gtkdial gtkdial.h */
15915
15916 /* GTK - The GIMP Toolkit
15917  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15918  *
15919  * This library is free software; you can redistribute it and/or
15920  * modify it under the terms of the GNU Library General Public
15921  * License as published by the Free Software Foundation; either
15922  * version 2 of the License, or (at your option) any later version.
15923  *
15924  * This library is distributed in the hope that it will be useful,
15925  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15926  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15927  * Library General Public License for more details.
15928  *
15929  * You should have received a copy of the GNU Library General Public
15930  * License along with this library; if not, write to the
15931  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15932  * Boston, MA 02111-1307, USA.
15933  */
15934 #ifndef __GTK_DIAL_H__
15935 #define __GTK_DIAL_H__
15936
15937
15938 #include <gdk/gdk.h>
15939 #include <gtk/gtkadjustment.h>
15940 #include <gtk/gtkwidget.h>
15941
15942
15943 #ifdef __cplusplus
15944 extern "C" {
15945 #endif /* __cplusplus */
15946
15947
15948 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
15949 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
15950 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
15951
15952
15953 typedef struct _GtkDial        GtkDial;
15954 typedef struct _GtkDialClass   GtkDialClass;
15955
15956 struct _GtkDial
15957 {
15958   GtkWidget widget;
15959
15960   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
15961   guint policy : 2;
15962
15963   /* Button currently pressed or 0 if none */
15964   guint8 button;
15965
15966   /* Dimensions of dial components */
15967   gint radius;
15968   gint pointer_width;
15969
15970   /* ID of update timer, or 0 if none */
15971   guint32 timer;
15972
15973   /* Current angle */
15974   gfloat angle;
15975
15976   /* Old values from adjustment stored so we know when something changes */
15977   gfloat old_value;
15978   gfloat old_lower;
15979   gfloat old_upper;
15980
15981   /* The adjustment object that stores the data for this dial */
15982   GtkAdjustment *adjustment;
15983 };
15984
15985 struct _GtkDialClass
15986 {
15987   GtkWidgetClass parent_class;
15988 };
15989
15990
15991 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
15992 guint          gtk_dial_get_type               (void);
15993 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
15994 void           gtk_dial_set_update_policy      (GtkDial      *dial,
15995                                                 GtkUpdateType  policy);
15996
15997 void           gtk_dial_set_adjustment         (GtkDial      *dial,
15998                                                 GtkAdjustment *adjustment);
15999 #ifdef __cplusplus
16000 }
16001 #endif /* __cplusplus */
16002
16003
16004 #endif /* __GTK_DIAL_H__ */
16005 /* example-end */
16006 </verb></tscreen>
16007
16008 <!-- ----------------------------------------------------------------- -->
16009 <sect2> gtkdial.c
16010 <p>
16011 <tscreen><verb>
16012 /* example-start gtkdial gtkdial.c */
16013
16014 /* GTK - The GIMP Toolkit
16015  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16016  *
16017  * This library is free software; you can redistribute it and/or
16018  * modify it under the terms of the GNU Library General Public
16019  * License as published by the Free Software Foundation; either
16020  * version 2 of the License, or (at your option) any later version.
16021  *
16022  * This library is distributed in the hope that it will be useful,
16023  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16025  * Library General Public License for more details.
16026  *
16027  * You should have received a copy of the GNU Library General Public
16028  * License along with this library; if not, write to the
16029  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16030  * Boston, MA 02111-1307, USA.
16031  */
16032 #include <math.h>
16033 #include <stdio.h>
16034 #include <gtk/gtkmain.h>
16035 #include <gtk/gtksignal.h>
16036
16037 #include "gtkdial.h"
16038
16039 #define SCROLL_DELAY_LENGTH  300
16040 #define DIAL_DEFAULT_SIZE 100
16041
16042 /* Forward declarations */
16043
16044 static void gtk_dial_class_init               (GtkDialClass    *klass);
16045 static void gtk_dial_init                     (GtkDial         *dial);
16046 static void gtk_dial_destroy                  (GtkObject        *object);
16047 static void gtk_dial_realize                  (GtkWidget        *widget);
16048 static void gtk_dial_size_request             (GtkWidget      *widget,
16049                                                GtkRequisition *requisition);
16050 static void gtk_dial_size_allocate            (GtkWidget     *widget,
16051                                                GtkAllocation *allocation);
16052 static gint gtk_dial_expose                   (GtkWidget        *widget,
16053                                                 GdkEventExpose   *event);
16054 static gint gtk_dial_button_press             (GtkWidget        *widget,
16055                                                 GdkEventButton   *event);
16056 static gint gtk_dial_button_release           (GtkWidget        *widget,
16057                                                 GdkEventButton   *event);
16058 static gint gtk_dial_motion_notify            (GtkWidget        *widget,
16059                                                 GdkEventMotion   *event);
16060 static gint gtk_dial_timer                    (GtkDial         *dial);
16061
16062 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
16063 static void gtk_dial_update                   (GtkDial *dial);
16064 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
16065                                                 gpointer          data);
16066 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
16067                                                 gpointer          data);
16068
16069 /* Local data */
16070
16071 static GtkWidgetClass *parent_class = NULL;
16072
16073 guint
16074 gtk_dial_get_type ()
16075 {
16076   static guint dial_type = 0;
16077
16078   if (!dial_type)
16079     {
16080       GtkTypeInfo dial_info =
16081       {
16082         "GtkDial",
16083         sizeof (GtkDial),
16084         sizeof (GtkDialClass),
16085         (GtkClassInitFunc) gtk_dial_class_init,
16086         (GtkObjectInitFunc) gtk_dial_init,
16087         (GtkArgSetFunc) NULL,
16088         (GtkArgGetFunc) NULL,
16089       };
16090
16091       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
16092     }
16093
16094   return dial_type;
16095 }
16096
16097 static void
16098 gtk_dial_class_init (GtkDialClass *class)
16099 {
16100   GtkObjectClass *object_class;
16101   GtkWidgetClass *widget_class;
16102
16103   object_class = (GtkObjectClass*) class;
16104   widget_class = (GtkWidgetClass*) class;
16105
16106   parent_class = gtk_type_class (gtk_widget_get_type ());
16107
16108   object_class->destroy = gtk_dial_destroy;
16109
16110   widget_class->realize = gtk_dial_realize;
16111   widget_class->expose_event = gtk_dial_expose;
16112   widget_class->size_request = gtk_dial_size_request;
16113   widget_class->size_allocate = gtk_dial_size_allocate;
16114   widget_class->button_press_event = gtk_dial_button_press;
16115   widget_class->button_release_event = gtk_dial_button_release;
16116   widget_class->motion_notify_event = gtk_dial_motion_notify;
16117 }
16118
16119 static void
16120 gtk_dial_init (GtkDial *dial)
16121 {
16122   dial->button = 0;
16123   dial->policy = GTK_UPDATE_CONTINUOUS;
16124   dial->timer = 0;
16125   dial->radius = 0;
16126   dial->pointer_width = 0;
16127   dial->angle = 0.0;
16128   dial->old_value = 0.0;
16129   dial->old_lower = 0.0;
16130   dial->old_upper = 0.0;
16131   dial->adjustment = NULL;
16132 }
16133
16134 GtkWidget*
16135 gtk_dial_new (GtkAdjustment *adjustment)
16136 {
16137   GtkDial *dial;
16138
16139   dial = gtk_type_new (gtk_dial_get_type ());
16140
16141   if (!adjustment)
16142     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0,
16143                                                       0.0, 0.0, 0.0);
16144
16145   gtk_dial_set_adjustment (dial, adjustment);
16146
16147   return GTK_WIDGET (dial);
16148 }
16149
16150 static void
16151 gtk_dial_destroy (GtkObject *object)
16152 {
16153   GtkDial *dial;
16154
16155   g_return_if_fail (object != NULL);
16156   g_return_if_fail (GTK_IS_DIAL (object));
16157
16158   dial = GTK_DIAL (object);
16159
16160   if (dial->adjustment)
16161     gtk_object_unref (GTK_OBJECT (dial->adjustment));
16162
16163   if (GTK_OBJECT_CLASS (parent_class)->destroy)
16164     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
16165 }
16166
16167 GtkAdjustment*
16168 gtk_dial_get_adjustment (GtkDial *dial)
16169 {
16170   g_return_val_if_fail (dial != NULL, NULL);
16171   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
16172
16173   return dial->adjustment;
16174 }
16175
16176 void
16177 gtk_dial_set_update_policy (GtkDial      *dial,
16178                              GtkUpdateType  policy)
16179 {
16180   g_return_if_fail (dial != NULL);
16181   g_return_if_fail (GTK_IS_DIAL (dial));
16182
16183   dial->policy = policy;
16184 }
16185
16186 void
16187 gtk_dial_set_adjustment (GtkDial      *dial,
16188                           GtkAdjustment *adjustment)
16189 {
16190   g_return_if_fail (dial != NULL);
16191   g_return_if_fail (GTK_IS_DIAL (dial));
16192
16193   if (dial->adjustment)
16194     {
16195       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment),
16196                                      (gpointer) dial);
16197       gtk_object_unref (GTK_OBJECT (dial->adjustment));
16198     }
16199
16200   dial->adjustment = adjustment;
16201   gtk_object_ref (GTK_OBJECT (dial->adjustment));
16202
16203   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
16204                       (GtkSignalFunc) gtk_dial_adjustment_changed,
16205                       (gpointer) dial);
16206   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
16207                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
16208                       (gpointer) dial);
16209
16210   dial->old_value = adjustment->value;
16211   dial->old_lower = adjustment->lower;
16212   dial->old_upper = adjustment->upper;
16213
16214   gtk_dial_update (dial);
16215 }
16216
16217 static void
16218 gtk_dial_realize (GtkWidget *widget)
16219 {
16220   GtkDial *dial;
16221   GdkWindowAttr attributes;
16222   gint attributes_mask;
16223
16224   g_return_if_fail (widget != NULL);
16225   g_return_if_fail (GTK_IS_DIAL (widget));
16226
16227   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
16228   dial = GTK_DIAL (widget);
16229
16230   attributes.x = widget->allocation.x;
16231   attributes.y = widget->allocation.y;
16232   attributes.width = widget->allocation.width;
16233   attributes.height = widget->allocation.height;
16234   attributes.wclass = GDK_INPUT_OUTPUT;
16235   attributes.window_type = GDK_WINDOW_CHILD;
16236   attributes.event_mask = gtk_widget_get_events (widget) | 
16237     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
16238     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
16239     GDK_POINTER_MOTION_HINT_MASK;
16240   attributes.visual = gtk_widget_get_visual (widget);
16241   attributes.colormap = gtk_widget_get_colormap (widget);
16242
16243   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
16244   widget->window = gdk_window_new (widget->parent->window,
16245                                    &amp;attributes,
16246                                    attributes_mask);
16247
16248   widget->style = gtk_style_attach (widget->style, widget->window);
16249
16250   gdk_window_set_user_data (widget->window, widget);
16251
16252   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
16253 }
16254
16255 static void 
16256 gtk_dial_size_request (GtkWidget      *widget,
16257                        GtkRequisition *requisition)
16258 {
16259   requisition->width = DIAL_DEFAULT_SIZE;
16260   requisition->height = DIAL_DEFAULT_SIZE;
16261 }
16262
16263 static void
16264 gtk_dial_size_allocate (GtkWidget     *widget,
16265                         GtkAllocation *allocation)
16266 {
16267   GtkDial *dial;
16268
16269   g_return_if_fail (widget != NULL);
16270   g_return_if_fail (GTK_IS_DIAL (widget));
16271   g_return_if_fail (allocation != NULL);
16272
16273   widget->allocation = *allocation;
16274   dial = GTK_DIAL (widget);
16275
16276   if (GTK_WIDGET_REALIZED (widget))
16277     {
16278
16279       gdk_window_move_resize (widget->window,
16280                               allocation->x, allocation->y,
16281                               allocation->width, allocation->height);
16282
16283     }
16284   dial->radius = MIN(allocation->width,allocation->height) * 0.45;
16285   dial->pointer_width = dial->radius / 5;
16286 }
16287
16288 static gint
16289 gtk_dial_expose (GtkWidget      *widget,
16290                  GdkEventExpose *event)
16291 {
16292   GtkDial *dial;
16293   GdkPoint points[3];
16294   gdouble s,c;
16295   gdouble theta;
16296   gint xc, yc;
16297   gint tick_length;
16298   gint i;
16299
16300   g_return_val_if_fail (widget != NULL, FALSE);
16301   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16302   g_return_val_if_fail (event != NULL, FALSE);
16303
16304   if (event->count > 0)
16305     return FALSE;
16306   
16307   dial = GTK_DIAL (widget);
16308
16309   gdk_window_clear_area (widget->window,
16310                          0, 0,
16311                          widget->allocation.width,
16312                          widget->allocation.height);
16313
16314   xc = widget->allocation.width/2;
16315   yc = widget->allocation.height/2;
16316
16317   /* Draw ticks */
16318
16319   for (i=0; i<25; i++)
16320     {
16321       theta = (i*M_PI/18. - M_PI/6.);
16322       s = sin(theta);
16323       c = cos(theta);
16324
16325       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
16326       
16327       gdk_draw_line (widget->window,
16328                      widget->style->fg_gc[widget->state],
16329                      xc + c*(dial->radius - tick_length),
16330                      yc - s*(dial->radius - tick_length),
16331                      xc + c*dial->radius,
16332                      yc - s*dial->radius);
16333     }
16334
16335   /* Draw pointer */
16336
16337   s = sin(dial->angle);
16338   c = cos(dial->angle);
16339
16340
16341   points[0].x = xc + s*dial->pointer_width/2;
16342   points[0].y = yc + c*dial->pointer_width/2;
16343   points[1].x = xc + c*dial->radius;
16344   points[1].y = yc - s*dial->radius;
16345   points[2].x = xc - s*dial->pointer_width/2;
16346   points[2].y = yc - c*dial->pointer_width/2;
16347
16348   gtk_draw_polygon (widget->style,
16349                     widget->window,
16350                     GTK_STATE_NORMAL,
16351                     GTK_SHADOW_OUT,
16352                     points, 3,
16353                     TRUE);
16354   
16355   return FALSE;
16356 }
16357
16358 static gint
16359 gtk_dial_button_press (GtkWidget      *widget,
16360                        GdkEventButton *event)
16361 {
16362   GtkDial *dial;
16363   gint dx, dy;
16364   double s, c;
16365   double d_parallel;
16366   double d_perpendicular;
16367
16368   g_return_val_if_fail (widget != NULL, FALSE);
16369   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16370   g_return_val_if_fail (event != NULL, FALSE);
16371
16372   dial = GTK_DIAL (widget);
16373
16374   /* Determine if button press was within pointer region - we 
16375      do this by computing the parallel and perpendicular distance of
16376      the point where the mouse was pressed from the line passing through
16377      the pointer */
16378   
16379   dx = event->x - widget->allocation.width / 2;
16380   dy = widget->allocation.height / 2 - event->y;
16381   
16382   s = sin(dial->angle);
16383   c = cos(dial->angle);
16384   
16385   d_parallel = s*dy + c*dx;
16386   d_perpendicular = fabs(s*dx - c*dy);
16387   
16388   if (!dial->button &amp;&amp;
16389       (d_perpendicular < dial->pointer_width/2) &amp;&amp;
16390       (d_parallel > - dial->pointer_width))
16391     {
16392       gtk_grab_add (widget);
16393
16394       dial->button = event->button;
16395
16396       gtk_dial_update_mouse (dial, event->x, event->y);
16397     }
16398
16399   return FALSE;
16400 }
16401
16402 static gint
16403 gtk_dial_button_release (GtkWidget      *widget,
16404                           GdkEventButton *event)
16405 {
16406   GtkDial *dial;
16407
16408   g_return_val_if_fail (widget != NULL, FALSE);
16409   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16410   g_return_val_if_fail (event != NULL, FALSE);
16411
16412   dial = GTK_DIAL (widget);
16413
16414   if (dial->button == event->button)
16415     {
16416       gtk_grab_remove (widget);
16417
16418       dial->button = 0;
16419
16420       if (dial->policy == GTK_UPDATE_DELAYED)
16421         gtk_timeout_remove (dial->timer);
16422       
16423       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
16424           (dial->old_value != dial->adjustment->value))
16425         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
16426                                  "value_changed");
16427     }
16428
16429   return FALSE;
16430 }
16431
16432 static gint
16433 gtk_dial_motion_notify (GtkWidget      *widget,
16434                          GdkEventMotion *event)
16435 {
16436   GtkDial *dial;
16437   GdkModifierType mods;
16438   gint x, y, mask;
16439
16440   g_return_val_if_fail (widget != NULL, FALSE);
16441   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16442   g_return_val_if_fail (event != NULL, FALSE);
16443
16444   dial = GTK_DIAL (widget);
16445
16446   if (dial->button != 0)
16447     {
16448       x = event->x;
16449       y = event->y;
16450
16451       if (event->is_hint || (event->window != widget->window))
16452         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
16453
16454       switch (dial->button)
16455         {
16456         case 1:
16457           mask = GDK_BUTTON1_MASK;
16458           break;
16459         case 2:
16460           mask = GDK_BUTTON2_MASK;
16461           break;
16462         case 3:
16463           mask = GDK_BUTTON3_MASK;
16464           break;
16465         default:
16466           mask = 0;
16467           break;
16468         }
16469
16470       if (mods &amp; mask)
16471         gtk_dial_update_mouse (dial, x,y);
16472     }
16473
16474   return FALSE;
16475 }
16476
16477 static gint
16478 gtk_dial_timer (GtkDial *dial)
16479 {
16480   g_return_val_if_fail (dial != NULL, FALSE);
16481   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
16482
16483   if (dial->policy == GTK_UPDATE_DELAYED)
16484     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
16485                              "value_changed");
16486
16487   return FALSE;
16488 }
16489
16490 static void
16491 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
16492 {
16493   gint xc, yc;
16494   gfloat old_value;
16495
16496   g_return_if_fail (dial != NULL);
16497   g_return_if_fail (GTK_IS_DIAL (dial));
16498
16499   xc = GTK_WIDGET(dial)->allocation.width / 2;
16500   yc = GTK_WIDGET(dial)->allocation.height / 2;
16501
16502   old_value = dial->adjustment->value;
16503   dial->angle = atan2(yc-y, x-xc);
16504
16505   if (dial->angle < -M_PI/2.)
16506     dial->angle += 2*M_PI;
16507
16508   if (dial->angle < -M_PI/6)
16509     dial->angle = -M_PI/6;
16510
16511   if (dial->angle > 7.*M_PI/6.)
16512     dial->angle = 7.*M_PI/6.;
16513
16514   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
16515     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
16516
16517   if (dial->adjustment->value != old_value)
16518     {
16519       if (dial->policy == GTK_UPDATE_CONTINUOUS)
16520         {
16521           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment),
16522                                    "value_changed");
16523         }
16524       else
16525         {
16526           gtk_widget_draw (GTK_WIDGET(dial), NULL);
16527
16528           if (dial->policy == GTK_UPDATE_DELAYED)
16529             {
16530               if (dial->timer)
16531                 gtk_timeout_remove (dial->timer);
16532
16533               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
16534                                              (GtkFunction) gtk_dial_timer,
16535                                              (gpointer) dial);
16536             }
16537         }
16538     }
16539 }
16540
16541 static void
16542 gtk_dial_update (GtkDial *dial)
16543 {
16544   gfloat new_value;
16545   
16546   g_return_if_fail (dial != NULL);
16547   g_return_if_fail (GTK_IS_DIAL (dial));
16548
16549   new_value = dial->adjustment->value;
16550   
16551   if (new_value < dial->adjustment->lower)
16552     new_value = dial->adjustment->lower;
16553
16554   if (new_value > dial->adjustment->upper)
16555     new_value = dial->adjustment->upper;
16556
16557   if (new_value != dial->adjustment->value)
16558     {
16559       dial->adjustment->value = new_value;
16560       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
16561     }
16562
16563   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 
16564                               4.*M_PI/3. /
16565     (dial->adjustment->upper - dial->adjustment->lower);
16566
16567   gtk_widget_draw (GTK_WIDGET(dial), NULL);
16568 }
16569
16570 static void
16571 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
16572                               gpointer       data)
16573 {
16574   GtkDial *dial;
16575
16576   g_return_if_fail (adjustment != NULL);
16577   g_return_if_fail (data != NULL);
16578
16579   dial = GTK_DIAL (data);
16580
16581   if ((dial->old_value != adjustment->value) ||
16582       (dial->old_lower != adjustment->lower) ||
16583       (dial->old_upper != adjustment->upper))
16584     {
16585       gtk_dial_update (dial);
16586
16587       dial->old_value = adjustment->value;
16588       dial->old_lower = adjustment->lower;
16589       dial->old_upper = adjustment->upper;
16590     }
16591 }
16592
16593 static void
16594 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
16595                                     gpointer       data)
16596 {
16597   GtkDial *dial;
16598
16599   g_return_if_fail (adjustment != NULL);
16600   g_return_if_fail (data != NULL);
16601
16602   dial = GTK_DIAL (data);
16603
16604   if (dial->old_value != adjustment->value)
16605     {
16606       gtk_dial_update (dial);
16607
16608       dial->old_value = adjustment->value;
16609     }
16610 }
16611 /* example-end */
16612 </verb></tscreen>
16613
16614 <!-- ----------------------------------------------------------------- -->
16615 <sect1> Scribble
16616 <p>
16617 <tscreen><verb>
16618 /* example-start scribble-simple scribble-simple.c */
16619
16620 /* GTK - The GIMP Toolkit
16621  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16622  *
16623  * This library is free software; you can redistribute it and/or
16624  * modify it under the terms of the GNU Library General Public
16625  * License as published by the Free Software Foundation; either
16626  * version 2 of the License, or (at your option) any later version.
16627  *
16628  * This library is distributed in the hope that it will be useful,
16629  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16630  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16631  * Library General Public License for more details.
16632  *
16633  * You should have received a copy of the GNU Library General Public
16634  * License along with this library; if not, write to the
16635  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16636  * Boston, MA 02111-1307, USA.
16637  */
16638
16639 #include <gtk/gtk.h>
16640
16641 /* Backing pixmap for drawing area */
16642 static GdkPixmap *pixmap = NULL;
16643
16644 /* Create a new backing pixmap of the appropriate size */
16645 static gint
16646 configure_event (GtkWidget *widget, GdkEventConfigure *event)
16647 {
16648   if (pixmap)
16649     gdk_pixmap_unref(pixmap);
16650
16651   pixmap = gdk_pixmap_new(widget->window,
16652                           widget->allocation.width,
16653                           widget->allocation.height,
16654                           -1);
16655   gdk_draw_rectangle (pixmap,
16656                       widget->style->white_gc,
16657                       TRUE,
16658                       0, 0,
16659                       widget->allocation.width,
16660                       widget->allocation.height);
16661
16662   return TRUE;
16663 }
16664
16665 /* Redraw the screen from the backing pixmap */
16666 static gint
16667 expose_event (GtkWidget *widget, GdkEventExpose *event)
16668 {
16669   gdk_draw_pixmap(widget->window,
16670                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
16671                   pixmap,
16672                   event->area.x, event->area.y,
16673                   event->area.x, event->area.y,
16674                   event->area.width, event->area.height);
16675
16676   return FALSE;
16677 }
16678
16679 /* Draw a rectangle on the screen */
16680 static void
16681 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
16682 {
16683   GdkRectangle update_rect;
16684
16685   update_rect.x = x - 5;
16686   update_rect.y = y - 5;
16687   update_rect.width = 10;
16688   update_rect.height = 10;
16689   gdk_draw_rectangle (pixmap,
16690                       widget->style->black_gc,
16691                       TRUE,
16692                       update_rect.x, update_rect.y,
16693                       update_rect.width, update_rect.height);
16694   gtk_widget_draw (widget, &amp;update_rect);
16695 }
16696
16697 static gint
16698 button_press_event (GtkWidget *widget, GdkEventButton *event)
16699 {
16700   if (event->button == 1 &amp;&amp; pixmap != NULL)
16701     draw_brush (widget, event->x, event->y);
16702
16703   return TRUE;
16704 }
16705
16706 static gint
16707 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
16708 {
16709   int x, y;
16710   GdkModifierType state;
16711
16712   if (event->is_hint)
16713     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
16714   else
16715     {
16716       x = event->x;
16717       y = event->y;
16718       state = event->state;
16719     }
16720     
16721   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
16722     draw_brush (widget, x, y);
16723   
16724   return TRUE;
16725 }
16726
16727 void
16728 quit ()
16729 {
16730   gtk_exit (0);
16731 }
16732
16733 int
16734 main (int argc, char *argv[])
16735 {
16736   GtkWidget *window;
16737   GtkWidget *drawing_area;
16738   GtkWidget *vbox;
16739
16740   GtkWidget *button;
16741
16742   gtk_init (&amp;argc, &amp;argv);
16743
16744   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
16745   gtk_widget_set_name (window, "Test Input");
16746
16747   vbox = gtk_vbox_new (FALSE, 0);
16748   gtk_container_add (GTK_CONTAINER (window), vbox);
16749   gtk_widget_show (vbox);
16750
16751   gtk_signal_connect (GTK_OBJECT (window), "destroy",
16752                       GTK_SIGNAL_FUNC (quit), NULL);
16753
16754   /* Create the drawing area */
16755
16756   drawing_area = gtk_drawing_area_new ();
16757   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
16758   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
16759
16760   gtk_widget_show (drawing_area);
16761
16762   /* Signals used to handle backing pixmap */
16763
16764   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
16765                       (GtkSignalFunc) expose_event, NULL);
16766   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
16767                       (GtkSignalFunc) configure_event, NULL);
16768
16769   /* Event signals */
16770
16771   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
16772                       (GtkSignalFunc) motion_notify_event, NULL);
16773   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
16774                       (GtkSignalFunc) button_press_event, NULL);
16775
16776   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
16777                          | GDK_LEAVE_NOTIFY_MASK
16778                          | GDK_BUTTON_PRESS_MASK
16779                          | GDK_POINTER_MOTION_MASK
16780                          | GDK_POINTER_MOTION_HINT_MASK);
16781
16782   /* .. And a quit button */
16783   button = gtk_button_new_with_label ("Quit");
16784   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
16785
16786   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
16787                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
16788                              GTK_OBJECT (window));
16789   gtk_widget_show (button);
16790
16791   gtk_widget_show (window);
16792
16793   gtk_main ();
16794
16795   return 0;
16796 }
16797 /* example-end */
16798 </verb></tscreen>
16799
16800 <!-- ***************************************************************** -->
16801 <sect> List Widget
16802 <!-- ***************************************************************** -->
16803 <p>
16804 NOTE: The List widget has been superseded by the CList widget. It is
16805 detailed here just for completeness.
16806
16807 The List widget is designed to act as a vertical container for
16808 widgets that should be of the type ListItem.
16809
16810 A List widget has its own window to receive events and its own
16811 background color which is usually white. As it is directly derived
16812 from a Container it can be treated as such by using the
16813 GTK_CONTAINER(List) macro, see the Container widget for more on
16814 this. One should already be familiar with the usage of a GList and
16815 its related functions g_list_*() to be able to use the List widget
16816 to it full extent.
16817
16818 There is one field inside the structure definition of the List
16819 widget that will be of greater interest to us, this is:
16820
16821 <tscreen><verb>
16822 struct _GtkList
16823 {
16824   ...
16825   GList *selection;
16826   guint selection_mode;
16827   ...
16828 }; 
16829 </verb></tscreen>
16830
16831 The selection field of a List points to a linked list of all items
16832 that are currently selected, or NULL if the selection is empty.  So to
16833 learn about the current selection we read the GTK_LIST()->selection
16834 field, but do not modify it since the internal fields are maintained
16835 by the gtk_list_*() functions.
16836
16837 The selection_mode of the List determines the selection facilities
16838 of a List and therefore the contents of the GTK_LIST()->selection
16839 field. The selection_mode may be one of the following:
16840
16841 <itemize>
16842 <item> <tt/GTK_SELECTION_SINGLE/ - The selection is either NULL
16843                         or contains a GList pointer
16844                         for a single selected item.
16845
16846 <item> <tt/GTK_SELECTION_BROWSE/ -  The selection is NULL if the list
16847                         contains no widgets or insensitive
16848                         ones only, otherwise it contains
16849                         a GList pointer for one GList
16850                         structure, and therefore exactly
16851                         one list item.
16852
16853 <item> <tt/GTK_SELECTION_MULTIPLE/ -  The selection is NULL if no list
16854                         items are selected or a GList pointer
16855                         for the first selected item. That
16856                         in turn points to a GList structure
16857                         for the second selected item and so
16858                         on.
16859
16860 <item> <tt/GTK_SELECTION_EXTENDED/ - The selection is always NULL.
16861 </itemize>
16862
16863 The default is <tt/GTK_SELECTION_MULTIPLE/.
16864
16865 <!-- ----------------------------------------------------------------- -->
16866 <sect1> Signals
16867 <p>
16868 <tscreen><verb>
16869 void selection_changed( GtkList *list );
16870 </verb></tscreen>
16871
16872 This signal will be invoked whenever the selection field of a List
16873 has changed. This happens when a child of thekList got selected or
16874 deselected.
16875
16876 <tscreen><verb>
16877 void select_child( GtkList   *list,
16878                    GtkWidget *child);
16879 </verb></tscreen>
16880
16881 This signal is invoked when a child of the List is about to get
16882 selected. This happens mainly on calls to gtk_list_select_item(),
16883 gtk_list_select_child(), button presses and sometimes indirectly
16884 triggered on some else occasions where children get added to or
16885 removed from the List.
16886
16887 <tscreen><verb>
16888 void unselect_child( GtkList   *list,
16889                      GtkWidget *child );
16890 </verb></tscreen>
16891
16892 This signal is invoked when a child of the List is about to get
16893 deselected. This happens mainly on calls to gtk_list_unselect_item(),
16894 gtk_list_unselect_child(), button presses and sometimes indirectly
16895 triggered on some else occasions where children get added to or
16896 removed from the List.
16897
16898 <!-- ----------------------------------------------------------------- -->
16899 <sect1> Functions
16900 <p>
16901 <tscreen><verb>
16902 guint gtk_list_get_type( void );
16903 </verb></tscreen>
16904
16905 Returns the "GtkList" type identifier.
16906
16907 <tscreen><verb>
16908 GtkWidget *gtk_list_new( void );
16909 </verb></tscreen>
16910
16911 Create a new List object. The new widget is returned as a pointer
16912 to a GtkWidget object. NULL is returned on failure.
16913
16914 <tscreen><verb>
16915 void gtk_list_insert_items( GtkList *list,
16916                             GList   *items,
16917                             gint     position );
16918 </verb></tscreen>
16919
16920 Insert list items into the list, starting at <tt/position/.
16921 <tt/items/ is a doubly linked list where each nodes data pointer is
16922 expected to point to a newly created ListItem. The GList nodes of
16923 <tt/items/ are taken over by the list.
16924
16925 <tscreen><verb>
16926 void gtk_list_append_items( GtkList *list,
16927                             GList   *items);
16928 </verb></tscreen>
16929
16930 Insert list items just like gtk_list_insert_items() at the end of the
16931 list. The GList nodes of <tt/items/ are taken over by the list.
16932
16933 <tscreen><verb>
16934 void gtk_list_prepend_items( GtkList *list,
16935                              GList   *items);
16936 </verb></tscreen>
16937
16938 Insert list items just like gtk_list_insert_items() at the very
16939 beginning of the list. The GList nodes of <tt/items/ are taken over by
16940 the list.
16941
16942 <tscreen><verb>
16943 void gtk_list_remove_items( GtkList *list,
16944                             GList   *items);
16945 </verb></tscreen>
16946
16947 Remove list items from the list. <tt/items/ is a doubly linked list
16948 where each nodes data pointer is expected to point to a direct child
16949 of list. It is the callers responsibility to make a call to
16950 g_list_free(items) afterwards. Also the caller has to destroy the list
16951 items himself.
16952
16953 <tscreen><verb>
16954 void gtk_list_clear_items( GtkList *list,
16955                            gint start,
16956                            gint end );
16957 </verb></tscreen>
16958
16959 Remove and destroy list items from the list. A widget is affected if
16960 its current position within the list is in the range specified by
16961 <tt/start/ and <tt/end/.
16962
16963 <tscreen><verb>
16964 void gtk_list_select_item( GtkList *list,
16965                            gint     item );
16966 </verb></tscreen>
16967
16968 Invoke the select_child signal for a list item specified through its
16969 current position within the list.
16970
16971 <tscreen><verb>
16972 void gtk_list_unselect_item( GtkList *list,
16973                              gint     item);
16974 </verb></tscreen>
16975
16976 Invoke the unselect_child signal for a list item specified through its
16977 current position within the list.
16978
16979 <tscreen><verb>
16980 void gtk_list_select_child( GtkList *list,
16981                             GtkWidget *child);
16982 </verb></tscreen>
16983
16984 Invoke the select_child signal for the specified child.
16985
16986 <tscreen><verb>
16987 void gtk_list_unselect_child( GtkList   *list,
16988                               GtkWidget *child);
16989 </verb></tscreen>
16990
16991 Invoke the unselect_child signal for the specified child.
16992
16993 <tscreen><verb>
16994 gint gtk_list_child_position( GtkList *list,
16995                               GtkWidget *child);
16996 </verb></tscreen>
16997
16998 Return the position of <tt/child/ within the list. "-1" is returned on
16999 failure.
17000
17001 <tscreen><verb>
17002 void gtk_list_set_selection_mode( GtkList         *list,
17003                                   GtkSelectionMode mode );
17004 </verb></tscreen>
17005
17006 Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
17007 GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
17008 GTK_SELECTION_EXTENDED.
17009
17010 <tscreen><verb>
17011 GtkList *GTK_LIST( gpointer obj );
17012 </verb></tscreen>
17013
17014 Cast a generic pointer to "GtkList *".
17015
17016 <tscreen><verb>
17017 GtkListClass *GTK_LIST_CLASS( gpointer class);
17018 </verb></tscreen>
17019
17020 Cast a generic pointer to "GtkListClass *". 
17021
17022 <tscreen><verb>
17023 gint GTK_IS_LIST( gpointer obj);
17024 </verb></tscreen>
17025
17026 Determine if a generic pointer refers to a "GtkList" object.
17027
17028 <!-- ----------------------------------------------------------------- -->
17029 <sect1> Example
17030 <p>
17031 Following is an example program that will print out the changes of the
17032 selection of a List, and lets you "arrest" list items into a prison
17033 by selecting them with the rightmost mouse button.
17034
17035 <tscreen><verb>
17036 /* example-start list list.c */
17037
17038 /* Include the GTK header files
17039  * Include stdio.h, we need that for the printf() function
17040  */
17041 #include        <gtk/gtk.h>
17042 #include        <stdio.h>
17043
17044 /* This is our data identification string to store
17045  * data in list items
17046  */
17047 const gchar *list_item_data_key="list_item_data";
17048
17049
17050 /* prototypes for signal handler that we are going to connect
17051  * to the List widget
17052  */
17053 static void  sigh_print_selection( GtkWidget *gtklist,
17054                                    gpointer   func_data);
17055
17056 static void  sigh_button_event( GtkWidget      *gtklist,
17057                                 GdkEventButton *event,
17058                                 GtkWidget      *frame );
17059
17060
17061 /* Main function to set up the user interface */
17062
17063 gint main (int    argc,
17064            gchar *argv[])
17065 {                                  
17066     GtkWidget *separator;
17067     GtkWidget *window;
17068     GtkWidget *vbox;
17069     GtkWidget *scrolled_window;
17070     GtkWidget *frame;
17071     GtkWidget *gtklist;
17072     GtkWidget *button;
17073     GtkWidget *list_item;
17074     GList *dlist;
17075     guint i;
17076     gchar buffer[64];
17077     
17078     
17079     /* Initialize GTK (and subsequently GDK) */
17080
17081     gtk_init(&amp;argc, &amp;argv);
17082     
17083     
17084     /* Create a window to put all the widgets in
17085      * connect gtk_main_quit() to the "destroy" event of
17086      * the window to handle window manager close-window-events
17087      */
17088     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
17089     gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
17090     gtk_signal_connect(GTK_OBJECT(window),
17091                        "destroy",
17092                        GTK_SIGNAL_FUNC(gtk_main_quit),
17093                        NULL);
17094     
17095     
17096     /* Inside the window we need a box to arrange the widgets
17097      * vertically */
17098     vbox=gtk_vbox_new(FALSE, 5);
17099     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
17100     gtk_container_add(GTK_CONTAINER(window), vbox);
17101     gtk_widget_show(vbox);
17102     
17103     /* This is the scrolled window to put the List widget inside */
17104     scrolled_window=gtk_scrolled_window_new(NULL, NULL);
17105     gtk_widget_set_usize(scrolled_window, 250, 150);
17106     gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
17107     gtk_widget_show(scrolled_window);
17108     
17109     /* Create thekList widget.
17110      * Connect the sigh_print_selection() signal handler
17111      * function to the "selection_changed" signal of the List
17112      * to print out the selected items each time the selection
17113      * has changed */
17114     gtklist=gtk_list_new();
17115     gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
17116                                            gtklist);
17117     gtk_widget_show(gtklist);
17118     gtk_signal_connect(GTK_OBJECT(gtklist),
17119                        "selection_changed",
17120                        GTK_SIGNAL_FUNC(sigh_print_selection),
17121                        NULL);
17122     
17123     /* We create a "Prison" to put a list item in ;) */
17124     frame=gtk_frame_new("Prison");
17125     gtk_widget_set_usize(frame, 200, 50);
17126     gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
17127     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
17128     gtk_container_add(GTK_CONTAINER(vbox), frame);
17129     gtk_widget_show(frame);
17130     
17131     /* Connect the sigh_button_event() signal handler to the List
17132      * which will handle the "arresting" of list items
17133      */
17134     gtk_signal_connect(GTK_OBJECT(gtklist),
17135                        "button_release_event",
17136                        GTK_SIGNAL_FUNC(sigh_button_event),
17137                        frame);
17138     
17139     /* Create a separator */
17140     separator=gtk_hseparator_new();
17141     gtk_container_add(GTK_CONTAINER(vbox), separator);
17142     gtk_widget_show(separator);
17143     
17144     /* Finally create a button and connect its "clicked" signal
17145      * to the destruction of the window */
17146     button=gtk_button_new_with_label("Close");
17147     gtk_container_add(GTK_CONTAINER(vbox), button);
17148     gtk_widget_show(button);
17149     gtk_signal_connect_object(GTK_OBJECT(button),
17150                               "clicked",
17151                               GTK_SIGNAL_FUNC(gtk_widget_destroy),
17152                               GTK_OBJECT(window));
17153     
17154     
17155     /* Now we create 5 list items, each having its own
17156      * label and add them to the List using gtk_container_add()
17157      * Also we query the text string from the label and
17158      * associate it with the list_item_data_key for each list item
17159      */
17160     for (i=0; i<5; i++) {
17161         GtkWidget       *label;
17162         gchar           *string;
17163         
17164         sprintf(buffer, "ListItemContainer with Label #%d", i);
17165         label=gtk_label_new(buffer);
17166         list_item=gtk_list_item_new();
17167         gtk_container_add(GTK_CONTAINER(list_item), label);
17168         gtk_widget_show(label);
17169         gtk_container_add(GTK_CONTAINER(gtklist), list_item);
17170         gtk_widget_show(list_item);
17171         gtk_label_get(GTK_LABEL(label), &amp;string);
17172         gtk_object_set_data(GTK_OBJECT(list_item),
17173                             list_item_data_key,
17174                             string);
17175     }
17176     /* Here, we are creating another 5 labels, this time
17177      * we use gtk_list_item_new_with_label() for the creation
17178      * we can't query the text string from the label because
17179      * we don't have the labels pointer and therefore
17180      * we just associate the list_item_data_key of each
17181      * list item with the same text string.
17182      * For adding of the list items we put them all into a doubly
17183      * linked list (GList), and then add them by a single call to
17184      * gtk_list_append_items().
17185      * Because we use g_list_prepend() to put the items into the
17186      * doubly linked list, their order will be descending (instead
17187      * of ascending when using g_list_append())
17188      */
17189     dlist=NULL;
17190     for (; i<10; i++) {
17191         sprintf(buffer, "List Item with Label %d", i);
17192         list_item=gtk_list_item_new_with_label(buffer);
17193         dlist=g_list_prepend(dlist, list_item);
17194         gtk_widget_show(list_item);
17195         gtk_object_set_data(GTK_OBJECT(list_item),
17196                             list_item_data_key,
17197                             "ListItem with integrated Label");
17198     }
17199     gtk_list_append_items(GTK_LIST(gtklist), dlist);
17200     
17201     /* Finally we want to see the window, don't we? ;) */
17202     gtk_widget_show(window);
17203     
17204     /* Fire up the main event loop of gtk */
17205     gtk_main();
17206     
17207     /* We get here after gtk_main_quit() has been called which
17208      * happens if the main window gets destroyed
17209      */
17210     return(0);
17211 }
17212
17213 /* This is the signal handler that got connected to button
17214  * press/release events of the List
17215  */
17216 void sigh_button_event( GtkWidget      *gtklist,
17217                         GdkEventButton *event,
17218                         GtkWidget      *frame )
17219 {
17220     /* We only do something if the third (rightmost mouse button
17221      * was released
17222      */
17223     if (event->type==GDK_BUTTON_RELEASE &amp;&amp;
17224         event->button==3) {
17225         GList           *dlist, *free_list;
17226         GtkWidget       *new_prisoner;
17227         
17228         /* Fetch the currently selected list item which
17229          * will be our next prisoner ;)
17230          */
17231         dlist=GTK_LIST(gtklist)->selection;
17232         if (dlist)
17233                 new_prisoner=GTK_WIDGET(dlist->data);
17234         else
17235                 new_prisoner=NULL;
17236         
17237         /* Look for already imprisoned list items, we
17238          * will put them back into the list.
17239          * Remember to free the doubly linked list that
17240          * gtk_container_children() returns
17241          */
17242         dlist=gtk_container_children(GTK_CONTAINER(frame));
17243         free_list=dlist;
17244         while (dlist) {
17245             GtkWidget       *list_item;
17246             
17247             list_item=dlist->data;
17248             
17249             gtk_widget_reparent(list_item, gtklist);
17250             
17251             dlist=dlist->next;
17252         }
17253         g_list_free(free_list);
17254         
17255         /* If we have a new prisoner, remove him from the
17256          * List and put him into the frame "Prison".
17257          * We need to unselect the item first.
17258          */
17259         if (new_prisoner) {
17260             GList   static_dlist;
17261             
17262             static_dlist.data=new_prisoner;
17263             static_dlist.next=NULL;
17264             static_dlist.prev=NULL;
17265             
17266             gtk_list_unselect_child(GTK_LIST(gtklist),
17267                                     new_prisoner);
17268             gtk_widget_reparent(new_prisoner, frame);
17269         }
17270     }
17271 }
17272
17273 /* This is the signal handler that gets called if List
17274  * emits the "selection_changed" signal
17275  */
17276 void sigh_print_selection( GtkWidget *gtklist,
17277                            gpointer   func_data)
17278 {
17279     GList   *dlist;
17280     
17281     /* Fetch the doubly linked list of selected items
17282      * of the List, remember to treat this as read-only!
17283      */
17284     dlist=GTK_LIST(gtklist)->selection;
17285     
17286     /* If there are no selected items there is nothing more
17287      * to do than just telling the user so
17288      */
17289     if (!dlist) {
17290         g_print("Selection cleared\n");
17291         return;
17292     }
17293     /* Ok, we got a selection and so we print it
17294      */
17295     g_print("The selection is a ");
17296     
17297     /* Get the list item from the doubly linked list
17298      * and then query the data associated with list_item_data_key.
17299      * We then just print it */
17300     while (dlist) {
17301         GtkObject       *list_item;
17302         gchar           *item_data_string;
17303         
17304         list_item=GTK_OBJECT(dlist->data);
17305         item_data_string=gtk_object_get_data(list_item,
17306                                              list_item_data_key);
17307         g_print("%s ", item_data_string);
17308         
17309         dlist=dlist->next;
17310     }
17311     g_print("\n");
17312 }
17313 /* example-end */
17314 </verb></tscreen>
17315
17316 <!-- ----------------------------------------------------------------- -->
17317 <sect1> List Item Widget
17318 <p>
17319 The ListItem widget is designed to act as a container holding up to
17320 one child, providing functions for selection/deselection just like the
17321 List widget requires them for its children.
17322
17323 A ListItem has its own window to receive events and has its own
17324 background color which is usually white.
17325
17326 As it is directly derived from an Item it can be treated as such by
17327 using the GTK_ITEM(ListItem) macro, see the Item widget for more on
17328 this. Usually a ListItem just holds a label to identify, e.g., a
17329 filename within a List -- therefore the convenience function
17330 gtk_list_item_new_with_label() is provided. The same effect can be
17331 achieved by creating a Label on its own, setting its alignment to
17332 xalign=0 and yalign=0.5 with a subsequent container addition to the
17333 ListItem.
17334
17335 As one is not forced to add a GtkLabel to a GtkListItem, you could
17336 also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
17337
17338 <!-- ----------------------------------------------------------------- -->
17339 <sect1> Signals
17340 <p>
17341 AkListItem does not create new signals on its own, but inherits
17342 the signals of a Item.
17343
17344 <!-- ----------------------------------------------------------------- -->
17345 <sect1> Functions
17346 <p>
17347 <tscreen><verb>
17348 guint gtk_list_item_get_type( void );
17349 </verb></tscreen>
17350
17351 Returns the "GtkListItem" type identifier.
17352
17353 <tscreen><verb>
17354 GtkWidget *gtk_list_item_new( void );
17355 </verb></tscreen>
17356
17357 Create a new ListItem object. The new widget is returned as a
17358 pointer to a GtkWidget object. NULL is returned on failure.
17359
17360 <tscreen><verb>
17361 GtkWidget *gtk_list_item_new_with_label( gchar *label );
17362 </verb></tscreen>
17363
17364 Create a new ListItem object, having a single GtkLabel as the sole
17365 child. The new widget is returned as a pointer to a GtkWidget
17366 object. NULL is returned on failure.
17367
17368 <tscreen><verb>
17369 void gtk_list_item_select( GtkListItem *list_item );
17370 </verb></tscreen>
17371
17372 This function is basically a wrapper around a call to gtk_item_select
17373 (GTK_ITEM (list_item)) which will emit the select signal.  *Note
17374 GtkItem::, for more info.
17375
17376 <tscreen><verb>
17377 void gtk_list_item_deselect( GtkListItem *list_item );
17378 </verb></tscreen>
17379
17380 This function is basically a wrapper around a call to
17381 gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
17382 signal.  *Note GtkItem::, for more info.
17383
17384 <tscreen><verb>
17385 GtkListItem *GTK_LIST_ITEM( gpointer obj );
17386 </verb></tscreen>
17387
17388 Cast a generic pointer to "GtkListItem *".
17389
17390 <tscreen><verb>
17391 GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
17392 </verb></tscreen>
17393
17394 Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
17395 for more info.
17396
17397 <tscreen><verb>
17398 gint GTK_IS_LIST_ITEM( gpointer obj );
17399 </verb></tscreen>
17400
17401 Determine if a generic pointer refers to a `GtkListItem' object.
17402 *Note Standard Macros::, for more info.
17403  
17404 <!-- ----------------------------------------------------------------- -->
17405 <sect1> Example
17406 <p>
17407 Please see the List example on this, which covers the usage of a
17408 ListItem as well.
17409
17410
17411 </article>