]> Pileus Git - ~andy/gtk/blob - docs/tutorial/gtk_tut.sgml
threads example from Erik Mouw. New question on GtkLabel background
[~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>November 13th, 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 above 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 gint delete_event( GtkWidget *widget,
874                    GdkEvent  *event,
875                    gpointer   data )
876 {
877     gtk_main_quit();
878     return(FALSE);
879 }
880
881 int main( int   argc,
882           char *argv[] )
883 {
884     /* GtkWidget is the storage type for widgets */
885     GtkWidget *window;
886     GtkWidget *button;
887     GtkWidget *box1;
888
889     /* This is called in all GTK applications. Arguments are parsed
890      * from the command line and are returned to the application. */
891     gtk_init (&amp;argc, &amp;argv);
892
893     /* Create a new window */
894     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
895
896     /* This is a new call, which just sets the title of our
897      * new window to "Hello Buttons!" */
898     gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
899
900     /* Here we just set a handler for delete_event that immediately
901      * exits GTK. */
902     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
903                         GTK_SIGNAL_FUNC (delete_event), NULL);
904
905     /* Sets the border width of the window. */
906     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
907
908     /* We create a box to pack widgets into.  This is described in detail
909      * in the "packing" section. The box is not really visible, it
910      * is just used as a tool to arrange widgets. */
911     box1 = gtk_hbox_new(FALSE, 0);
912
913     /* Put the box into the main window. */
914     gtk_container_add (GTK_CONTAINER (window), box1);
915
916     /* Creates a new button with the label "Button 1". */
917     button = gtk_button_new_with_label ("Button 1");
918
919     /* Now when the button is clicked, we call the "callback" function
920      * with a pointer to "button 1" as its argument */
921     gtk_signal_connect (GTK_OBJECT (button), "clicked",
922                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
923
924     /* Instead of gtk_container_add, we pack this button into the invisible
925      * box, which has been packed into the window. */
926     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
927
928     /* Always remember this step, this tells GTK that our preparation for
929      * this button is complete, and it can now be displayed. */
930     gtk_widget_show(button);
931
932     /* Do these same steps again to create a second button */
933     button = gtk_button_new_with_label ("Button 2");
934
935     /* Call the same callback function with a different argument,
936      * passing a pointer to "button 2" instead. */
937     gtk_signal_connect (GTK_OBJECT (button), "clicked",
938                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
939
940     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
941
942     /* The order in which we show the buttons is not really important, but I
943      * recommend showing the window last, so it all pops up at once. */
944     gtk_widget_show(button);
945
946     gtk_widget_show(box1);
947
948     gtk_widget_show (window);
949
950     /* Rest in gtk_main and wait for the fun to begin! */
951     gtk_main ();
952
953     return(0);
954 }
955 /* example-end */
956 </verb></tscreen>
957
958 Compile this program using the same linking arguments as our first
959 example.  You'll notice this time there is no easy way to exit the
960 program, you have to use your window manager or command line to kill
961 it. A good exercise for the reader would be to insert a third "Quit"
962 button that will exit the program. You may also wish to play with the
963 options to gtk_box_pack_start() while reading the next section.  Try
964 resizing the window, and observe the behavior.
965
966 Just as a side note, there is another useful define for
967 gtk_window_new() - <tt/GTK_WINDOW_DIALOG/. This interacts with the
968 window manager a little differently and should be used for transient
969 windows.
970
971 <!-- ***************************************************************** -->
972 <sect>Packing Widgets <label id="sec_packing_widgets">
973 <!-- ***************************************************************** -->
974 <p>
975 When creating an application, you'll want to put more than one widget
976 inside a window. Our first <em>helloworld</em> example only used one
977 widget so we could simply use a gtk_container_add call to "pack" the
978 widget into the window. But when you want to put more than one widget
979 into a window, how do you control where that widget is positioned?
980 This is where packing comes in.
981
982 <!-- ----------------------------------------------------------------- -->
983 <sect1>Theory of Packing Boxes
984 <p>
985 Most packing is done by creating boxes as in the example above. These
986 are invisible widget containers that we can pack our widgets into
987 which come in two forms, a horizontal box, and a vertical box. When
988 packing widgets into a horizontal box, the objects are inserted
989 horizontally from left to right or right to left depending on the call
990 used. In a vertical box, widgets are packed from top to bottom or vice
991 versa. You may use any combination of boxes inside or beside other
992 boxes to create the desired effect.
993
994 To create a new horizontal box, we use a call to gtk_hbox_new(), and
995 for vertical boxes, gtk_vbox_new(). The gtk_box_pack_start() and
996 gtk_box_pack_end() functions are used to place objects inside of these
997 containers. The gtk_box_pack_start() function will start at the top
998 and work its way down in a vbox, and pack left to right in an hbox.
999 gtk_box_pack_end() will do the opposite, packing from bottom to top in
1000 a vbox, and right to left in an hbox. Using these functions allows us
1001 to right justify or left justify our widgets and may be mixed in any
1002 way to achieve the desired effect. We will use gtk_box_pack_start() in
1003 most of our examples. An object may be another container or a
1004 widget. In fact, many widgets are actually containers themselves,
1005 including the button, but we usually only use a label inside a button.
1006
1007 By using these calls, GTK knows where you want to place your widgets
1008 so it can do automatic resizing and other nifty things. There are also
1009 a number of options as to how your widgets should be packed. As you
1010 can imagine, this method gives us a quite a bit of flexibility when
1011 placing and creating widgets.
1012
1013 <!-- ----------------------------------------------------------------- -->
1014 <sect1>Details of Boxes
1015 <p>
1016 Because of this flexibility, packing boxes in GTK can be confusing at
1017 first. There are a lot of options, and it's not immediately obvious how
1018 they all fit together. In the end, however, there are basically five
1019 different styles.
1020
1021 <? <CENTER> >
1022 <?
1023 <IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528"
1024 HEIGHT="235" ALT="Box Packing Example Image">
1025 >
1026 <? </CENTER> >
1027
1028 Each line contains one horizontal box (hbox) with several buttons. The
1029 call to gtk_box_pack is shorthand for the call to pack each of the
1030 buttons into the hbox. Each of the buttons is packed into the hbox the
1031 same way (i.e., same arguments to the gtk_box_pack_start() function).
1032
1033 This is the declaration of the gtk_box_pack_start function.
1034
1035 <tscreen><verb>
1036 void gtk_box_pack_start( GtkBox    *box,
1037                          GtkWidget *child,
1038                          gint       expand,
1039                          gint       fill,
1040                          gint       padding );
1041 </verb></tscreen>
1042
1043 The first argument is the box you are packing the object into, the
1044 second is the object. The objects will all be buttons for now, so
1045 we'll be packing buttons into boxes.
1046
1047 The expand argument to gtk_box_pack_start() and gtk_box_pack_end()
1048 controls whether the widgets are laid out in the box to fill in all
1049 the extra space in the box so the box is expanded to fill the area
1050 allotted to it (TRUE); or the box is shrunk to just fit the widgets
1051 (FALSE). Setting expand to FALSE will allow you to do right and left
1052 justification of your widgets.  Otherwise, they will all expand to fit
1053 into the box, and the same effect could be achieved by using only one
1054 of gtk_box_pack_start or gtk_box_pack_end.
1055
1056 The fill argument to the gtk_box_pack functions control whether the
1057 extra space is allocated to the objects themselves (TRUE), or as extra
1058 padding in the box around these objects (FALSE). It only has an effect
1059 if the expand argument is also TRUE.
1060
1061 When creating a new box, the function looks like this:
1062
1063 <tscreen><verb>
1064 GtkWidget *gtk_hbox_new (gint homogeneous,
1065                          gint spacing);
1066 </verb></tscreen>
1067
1068 The homogeneous argument to gtk_hbox_new (and the same for
1069 gtk_vbox_new) controls whether each object in the box has the same
1070 size (i.e., the same width in an hbox, or the same height in a
1071 vbox). If it is set, the gtk_box_pack routines function essentially
1072 as if the <tt/expand/ argument was always turned on.
1073
1074 What's the difference between spacing (set when the box is created)
1075 and padding (set when elements are packed)? Spacing is added between
1076 objects, and padding is added on either side of an object. The
1077 following figure should make it clearer:
1078
1079 <? <CENTER> >
1080 <?
1081 <IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509"
1082 HEIGHT="213" VSPACE="15" HSPACE="10"
1083 ALT="Box Packing Example Image">
1084 >
1085 <? </CENTER> >
1086
1087 Here is the code used to create the above images. I've commented it
1088 fairly heavily so I hope you won't have any problems following
1089 it. Compile it yourself and play with it.
1090
1091 <!-- ----------------------------------------------------------------- -->
1092 <sect1>Packing Demonstration Program
1093 <p>
1094 <tscreen><verb>
1095 /* example-start packbox packbox.c */
1096
1097 #include <stdio.h>
1098 #include <stdlib.h>
1099 #include "gtk/gtk.h"
1100
1101 gint delete_event( GtkWidget *widget,
1102                    GdkEvent  *event,
1103                    gpointer   data )
1104 {
1105     gtk_main_quit();
1106     return(FALSE);
1107 }
1108
1109 /* Make a new hbox filled with button-labels. Arguments for the 
1110  * variables we're interested are passed in to this function. 
1111  * We do not show the box, but do show everything inside. */
1112 GtkWidget *make_box( gint homogeneous,
1113                      gint spacing,
1114                      gint expand,
1115                      gint fill,
1116                      gint padding ) 
1117 {
1118     GtkWidget *box;
1119     GtkWidget *button;
1120     char padstr[80];
1121     
1122     /* Create a new hbox with the appropriate homogeneous
1123      * and spacing settings */
1124     box = gtk_hbox_new (homogeneous, spacing);
1125     
1126     /* Create a series of buttons with the appropriate settings */
1127     button = gtk_button_new_with_label ("gtk_box_pack");
1128     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1129     gtk_widget_show (button);
1130     
1131     button = gtk_button_new_with_label ("(box,");
1132     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1133     gtk_widget_show (button);
1134     
1135     button = gtk_button_new_with_label ("button,");
1136     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1137     gtk_widget_show (button);
1138     
1139     /* Create a button with the label depending on the value of
1140      * expand. */
1141     if (expand == TRUE)
1142             button = gtk_button_new_with_label ("TRUE,");
1143     else
1144             button = gtk_button_new_with_label ("FALSE,");
1145     
1146     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1147     gtk_widget_show (button);
1148     
1149     /* This is the same as the button creation for "expand"
1150      * above, but uses the shorthand form. */
1151     button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
1152     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1153     gtk_widget_show (button);
1154     
1155     sprintf (padstr, "%d);", padding);
1156     
1157     button = gtk_button_new_with_label (padstr);
1158     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1159     gtk_widget_show (button);
1160     
1161     return box;
1162 }
1163
1164 int main( int   argc,
1165           char *argv[]) 
1166 {
1167     GtkWidget *window;
1168     GtkWidget *button;
1169     GtkWidget *box1;
1170     GtkWidget *box2;
1171     GtkWidget *separator;
1172     GtkWidget *label;
1173     GtkWidget *quitbox;
1174     int which;
1175     
1176     /* Our init, don't forget this! :) */
1177     gtk_init (&amp;argc, &amp;argv);
1178     
1179     if (argc != 2) {
1180         fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n");
1181         /* This just does cleanup in GTK and exits with an exit status of 1. */
1182         gtk_exit (1);
1183     }
1184     
1185     which = atoi (argv[1]);
1186
1187     /* Create our window */
1188     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1189
1190     /* You should always remember to connect the delete_event signal
1191      * to the main window. This is very important for proper intuitive
1192      * behavior */
1193     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1194                         GTK_SIGNAL_FUNC (delete_event), NULL);
1195     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1196     
1197     /* We create a vertical box (vbox) to pack the horizontal boxes into.
1198      * This allows us to stack the horizontal boxes filled with buttons one
1199      * on top of the other in this vbox. */
1200     box1 = gtk_vbox_new (FALSE, 0);
1201     
1202     /* which example to show. These correspond to the pictures above. */
1203     switch (which) {
1204     case 1:
1205         /* create a new label. */
1206         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1207         
1208         /* Align the label to the left side.  We'll discuss this function and 
1209          * others in the section on Widget Attributes. */
1210         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1211
1212         /* Pack the label into the vertical box (vbox box1).  Remember that 
1213          * widgets added to a vbox will be packed one on top of the other in
1214          * order. */
1215         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1216         
1217         /* Show the label */
1218         gtk_widget_show (label);
1219         
1220         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1221          * expand = FALSE, fill = FALSE, padding = 0 */
1222         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1223         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1224         gtk_widget_show (box2);
1225
1226         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1227          * expand = TRUE, fill = FALSE, padding = 0 */
1228         box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
1229         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1230         gtk_widget_show (box2);
1231         
1232         /* Args are: homogeneous, spacing, expand, fill, padding */
1233         box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
1234         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1235         gtk_widget_show (box2);
1236         
1237         /* Creates a separator, we'll learn more about these later, 
1238          * but they are quite simple. */
1239         separator = gtk_hseparator_new ();
1240         
1241         /* Pack the separator into the vbox. Remember each of these
1242          * widgets is being packed into a vbox, so they'll be stacked
1243          * vertically. */
1244         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1245         gtk_widget_show (separator);
1246         
1247         /* Create another new label, and show it. */
1248         label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
1249         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1250         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1251         gtk_widget_show (label);
1252         
1253         /* Args are: homogeneous, spacing, expand, fill, padding */
1254         box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
1255         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1256         gtk_widget_show (box2);
1257         
1258         /* Args are: homogeneous, spacing, expand, fill, padding */
1259         box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
1260         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1261         gtk_widget_show (box2);
1262         
1263         /* Another new separator. */
1264         separator = gtk_hseparator_new ();
1265         /* The last 3 arguments to gtk_box_pack_start are:
1266          * expand, fill, padding. */
1267         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1268         gtk_widget_show (separator);
1269         
1270         break;
1271
1272     case 2:
1273
1274         /* Create a new label, remember box1 is a vbox as created 
1275          * near the beginning of main() */
1276         label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
1277         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1278         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1279         gtk_widget_show (label);
1280         
1281         /* Args are: homogeneous, spacing, expand, fill, padding */
1282         box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
1283         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1284         gtk_widget_show (box2);
1285         
1286         /* Args are: homogeneous, spacing, expand, fill, padding */
1287         box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
1288         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1289         gtk_widget_show (box2);
1290         
1291         separator = gtk_hseparator_new ();
1292         /* The last 3 arguments to gtk_box_pack_start are:
1293          * expand, fill, padding. */
1294         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1295         gtk_widget_show (separator);
1296         
1297         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1298         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1299         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1300         gtk_widget_show (label);
1301         
1302         /* Args are: homogeneous, spacing, expand, fill, padding */
1303         box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
1304         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1305         gtk_widget_show (box2);
1306         
1307         /* Args are: homogeneous, spacing, expand, fill, padding */
1308         box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
1309         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1310         gtk_widget_show (box2);
1311         
1312         separator = gtk_hseparator_new ();
1313         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1314         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1315         gtk_widget_show (separator);
1316         break;
1317     
1318     case 3:
1319
1320         /* This demonstrates the ability to use gtk_box_pack_end() to
1321          * right justify widgets. First, we create a new box as before. */
1322         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1323
1324         /* Create the label that will be put at the end. */
1325         label = gtk_label_new ("end");
1326         /* Pack it using gtk_box_pack_end(), so it is put on the right
1327          * side of the hbox created in the make_box() call. */
1328         gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
1329         /* Show the label. */
1330         gtk_widget_show (label);
1331         
1332         /* Pack box2 into box1 (the vbox remember ? :) */
1333         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1334         gtk_widget_show (box2);
1335         
1336         /* A separator for the bottom. */
1337         separator = gtk_hseparator_new ();
1338         /* This explicitly sets the separator to 400 pixels wide by 5 pixels
1339          * high. This is so the hbox we created will also be 400 pixels wide,
1340          * and the "end" label will be separated from the other labels in the
1341          * hbox. Otherwise, all the widgets in the hbox would be packed as
1342          * close together as possible. */
1343         gtk_widget_set_usize (separator, 400, 5);
1344         /* pack the separator into the vbox (box1) created near the start 
1345          * of main() */
1346         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1347         gtk_widget_show (separator);    
1348     }
1349     
1350     /* Create another new hbox.. remember we can use as many as we need! */
1351     quitbox = gtk_hbox_new (FALSE, 0);
1352     
1353     /* Our quit button. */
1354     button = gtk_button_new_with_label ("Quit");
1355     
1356     /* Setup the signal to terminate the program when the button is clicked */
1357     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1358                                GTK_SIGNAL_FUNC (gtk_main_quit),
1359                                GTK_OBJECT (window));
1360     /* Pack the button into the quitbox.
1361      * The last 3 arguments to gtk_box_pack_start are:
1362      * expand, fill, padding. */
1363     gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
1364     /* pack the quitbox into the vbox (box1) */
1365     gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
1366     
1367     /* Pack the vbox (box1) which now contains all our widgets, into the
1368      * main window. */
1369     gtk_container_add (GTK_CONTAINER (window), box1);
1370     
1371     /* And show everything left */
1372     gtk_widget_show (button);
1373     gtk_widget_show (quitbox);
1374     
1375     gtk_widget_show (box1);
1376     /* Showing the window last so everything pops up at once. */
1377     gtk_widget_show (window);
1378     
1379     /* And of course, our main function. */
1380     gtk_main ();
1381
1382     /* Control returns here when gtk_main_quit() is called, but not when 
1383      * gtk_exit is used. */
1384     
1385     return(0);
1386 }
1387 /* example-end */
1388 </verb></tscreen>
1389
1390 <!-- ----------------------------------------------------------------- -->
1391 <sect1>Packing Using Tables
1392 <p>
1393 Let's take a look at another way of packing - Tables. These can be
1394 extremely useful in certain situations.
1395
1396 Using tables, we create a grid that we can place widgets in. The
1397 widgets may take up as many spaces as we specify.
1398
1399 The first thing to look at, of course, is the gtk_table_new function:
1400
1401 <tscreen><verb>
1402 GtkWidget *gtk_table_new( gint rows,
1403                           gint columns,
1404                           gint homogeneous );
1405 </verb></tscreen>
1406
1407 The first argument is the number of rows to make in the table, while
1408 the second, obviously, is the number of columns.
1409
1410 The homogeneous argument has to do with how the table's boxes are
1411 sized. If homogeneous is TRUE, the table boxes are resized to the size
1412 of the largest widget in the table. If homogeneous is FALSE, the size
1413 of a table boxes is dictated by the tallest widget in its same row,
1414 and the widest widget in its column.
1415
1416 The rows and columns are laid out from 0 to n, where n was the number
1417 specified in the call to gtk_table_new. So, if you specify rows = 2
1418 and columns = 2, the layout would look something like this:
1419
1420 <tscreen><verb>
1421  0          1          2
1422 0+----------+----------+
1423  |          |          |
1424 1+----------+----------+
1425  |          |          |
1426 2+----------+----------+
1427 </verb></tscreen>
1428
1429 Note that the coordinate system starts in the upper left hand corner.
1430 To place a widget into a box, use the following function:
1431
1432 <tscreen><verb>
1433 void gtk_table_attach( GtkTable  *table,
1434                        GtkWidget *child,
1435                        gint       left_attach,
1436                        gint       right_attach,
1437                        gint       top_attach,
1438                        gint       bottom_attach,
1439                        gint       xoptions,
1440                        gint       yoptions,
1441                        gint       xpadding,
1442                        gint       ypadding );
1443 </verb></tscreen>                                      
1444
1445 The first argument ("table") is the table you've created and the
1446 second ("child") the widget you wish to place in the table.
1447
1448 The left and right attach arguments specify where to place the widget,
1449 and how many boxes to use. If you want a button in the lower right
1450 table entry of our 2x2 table, and want it to fill that entry ONLY,
1451 left_attach would be = 1, right_attach = 2, top_attach = 1,
1452 bottom_attach = 2.
1453
1454 Now, if you wanted a widget to take up the whole top row of our 2x2
1455 table, you'd use left_attach = 0, right_attach = 2, top_attach = 0,
1456 bottom_attach = 1.
1457
1458 The xoptions and yoptions are used to specify packing options and may
1459 be bitwise OR'ed together to allow multiple options.
1460
1461 These options are:
1462 <itemize>
1463 <item><tt/GTK_FILL/ - If the table box is larger than the widget, and
1464 <tt/GTK_FILL/ is specified, the widget will expand to use all the room
1465 available.
1466
1467 <item><tt/GTK_SHRINK/ - If the table widget was allocated less space
1468 then was requested (usually by the user resizing the window), then the
1469 widgets would normally just be pushed off the bottom of the window and
1470 disappear. If <tt/GTK_SHRINK/ is specified, the widgets will shrink
1471 with the table.
1472
1473 <item><tt/GTK_EXPAND/ - This will cause the table to expand to use up
1474 any remaining space in the window.
1475 </itemize>
1476
1477 Padding is just like in boxes, creating a clear area around the widget
1478 specified in pixels.
1479
1480 gtk_table_attach() has a LOT of options.  So, there's a shortcut:
1481
1482 <tscreen><verb>
1483 void gtk_table_attach_defaults( GtkTable  *table,
1484                                 GtkWidget *widget,
1485                                 gint       left_attach,
1486                                 gint       right_attach,
1487                                 gint       top_attach,
1488                                 gint       bottom_attach );
1489 </verb></tscreen>
1490
1491 The X and Y options default to <tt/GTK_FILL | GTK_EXPAND/, and X and Y
1492 padding are set to 0. The rest of the arguments are identical to the
1493 previous function.
1494
1495 We also have gtk_table_set_row_spacing() and
1496 gtk_table_set_col_spacing(). These places spacing between the rows at
1497 the specified row or column.
1498
1499 <tscreen><verb>
1500 void gtk_table_set_row_spacing( GtkTable *table,
1501                                 gint      row,
1502                                 gint      spacing );
1503 </verb></tscreen>
1504
1505 and
1506
1507 <tscreen><verb>
1508 void gtk_table_set_col_spacing ( GtkTable *table,
1509                                  gint      column,
1510                                  gint      spacing );
1511 </verb></tscreen>
1512
1513 Note that for columns, the space goes to the right of the column, and
1514 for rows, the space goes below the row.
1515
1516 You can also set a consistent spacing of all rows and/or columns with:
1517
1518 <tscreen><verb>
1519 void gtk_table_set_row_spacings( GtkTable *table,
1520                                  gint      spacing );
1521 </verb></tscreen>
1522
1523 And,
1524
1525 <tscreen><verb>
1526 void gtk_table_set_col_spacings( GtkTable *table,
1527                                  gint      spacing );
1528 </verb></tscreen>
1529
1530 Note that with these calls, the last row and last column do not get
1531 any spacing.
1532
1533 <!-- ----------------------------------------------------------------- -->
1534 <sect1>Table Packing Example
1535 <p>
1536 Here we make a window with three buttons in a 2x2 table.
1537 The first two buttons will be placed in the upper row.
1538 A third, quit button, is placed in the lower row, spanning both columns.
1539 Which means it should look something like this:
1540
1541 <? <CENTER> >
1542 <?
1543 <IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" 
1544 ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120">
1545 >
1546 <? </CENTER> >
1547
1548 Here's the source code:
1549
1550 <tscreen><verb>
1551 /* example-start table table.c */
1552
1553 #include <gtk/gtk.h>
1554
1555 /* Our callback.
1556  * The data passed to this function is printed to stdout */
1557 void callback( GtkWidget *widget,
1558                gpointer   data )
1559 {
1560     g_print ("Hello again - %s was pressed\n", (char *) data);
1561 }
1562
1563 /* This callback quits the program */
1564 gint delete_event( GtkWidget *widget,
1565                    GdkEvent  *event,
1566                    gpointer   data )
1567 {
1568     gtk_main_quit ();
1569     return(FALSE);
1570 }
1571
1572 int main( int   argc,
1573           char *argv[] )
1574 {
1575     GtkWidget *window;
1576     GtkWidget *button;
1577     GtkWidget *table;
1578
1579     gtk_init (&amp;argc, &amp;argv);
1580
1581     /* Create a new window */
1582     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1583
1584     /* Set the window title */
1585     gtk_window_set_title (GTK_WINDOW (window), "Table");
1586
1587     /* Set a handler for delete_event that immediately
1588      * exits GTK. */
1589     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1590                         GTK_SIGNAL_FUNC (delete_event), NULL);
1591
1592     /* Sets the border width of the window. */
1593     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
1594
1595     /* Create a 2x2 table */
1596     table = gtk_table_new (2, 2, TRUE);
1597
1598     /* Put the table in the main window */
1599     gtk_container_add (GTK_CONTAINER (window), table);
1600
1601     /* Create first button */
1602     button = gtk_button_new_with_label ("button 1");
1603
1604     /* When the button is clicked, we call the "callback" function
1605      * with a pointer to "button 1" as its argument */
1606     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1607               GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
1608
1609
1610     /* Insert button 1 into the upper left quadrant of the table */
1611     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);
1612
1613     gtk_widget_show (button);
1614
1615     /* Create second button */
1616
1617     button = gtk_button_new_with_label ("button 2");
1618
1619     /* When the button is clicked, we call the "callback" function
1620      * with a pointer to "button 2" as its argument */
1621     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1622               GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
1623     /* Insert button 2 into the upper right quadrant of the table */
1624     gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);
1625
1626     gtk_widget_show (button);
1627
1628     /* Create "Quit" button */
1629     button = gtk_button_new_with_label ("Quit");
1630
1631     /* When the button is clicked, we call the "delete_event" function
1632      * and the program exits */
1633     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1634                         GTK_SIGNAL_FUNC (delete_event), NULL);
1635
1636     /* Insert the quit button into the both 
1637      * lower quadrants of the table */
1638     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);
1639
1640     gtk_widget_show (button);
1641
1642     gtk_widget_show (table);
1643     gtk_widget_show (window);
1644
1645     gtk_main ();
1646
1647     return 0;
1648 }
1649 /* example-end */
1650 </verb></tscreen>
1651
1652 <!-- ***************************************************************** -->
1653 <sect>Widget Overview
1654 <!-- ***************************************************************** -->
1655 <p>
1656 The general steps to creating a widget in GTK are:
1657 <enum>
1658 <item> gtk_*_new - one of various functions to create a new widget.
1659 These are all detailed in this section.
1660
1661 <item> Connect all signals and events we wish to use to the
1662 appropriate handlers.
1663
1664 <item> Set the attributes of the widget.
1665
1666 <item> Pack the widget into a container using the appropriate call
1667 such as gtk_container_add() or gtk_box_pack_start().
1668
1669 <item> gtk_widget_show() the widget.
1670 </enum>
1671
1672 gtk_widget_show() lets GTK know that we are done setting the
1673 attributes of the widget, and it is ready to be displayed. You may
1674 also use gtk_widget_hide to make it disappear again. The order in
1675 which you show the widgets is not important, but I suggest showing the
1676 window last so the whole window pops up at once rather than seeing the
1677 individual widgets come up on the screen as they're formed. The
1678 children of a widget (a window is a widget too) will not be displayed
1679 until the window itself is shown using the gtk_widget_show() function.
1680
1681 <!-- ----------------------------------------------------------------- -->
1682 <sect1> Casting
1683 <p>
1684 You'll notice as you go on that GTK uses a type casting system. This
1685 is always done using macros that both test the ability to cast the
1686 given item, and perform the cast. Some common ones you will see are:
1687
1688 <tscreen><verb>
1689   GTK_WIDGET(widget)
1690   GTK_OBJECT(object)
1691   GTK_SIGNAL_FUNC(function)
1692   GTK_CONTAINER(container)
1693   GTK_WINDOW(window)
1694   GTK_BOX(box)
1695 </verb></tscreen>
1696
1697 These are all used to cast arguments in functions. You'll see them in the
1698 examples, and can usually tell when to use them simply by looking at the
1699 function's declaration.
1700
1701 As you can see below in the class hierarchy, all GtkWidgets are
1702 derived from the Object base class. This means you can use a widget
1703 in any place the function asks for an object - simply use the
1704 <tt/GTK_OBJECT()/ macro.
1705
1706 For example:
1707
1708 <tscreen><verb>
1709 gtk_signal_connect( GTK_OBJECT(button), "clicked",
1710                     GTK_SIGNAL_FUNC(callback_function), callback_data);
1711 </verb></tscreen> 
1712
1713 This casts the button into an object, and provides a cast for the
1714 function pointer to the callback.
1715
1716 Many widgets are also containers. If you look in the class hierarchy
1717 below, you'll notice that many widgets derive from the Container
1718 class. Any one of these widgets may be used with the
1719 <tt/GTK_CONTAINER/ macro to pass them to functions that ask for
1720 containers.
1721
1722 Unfortunately, these macros are not extensively covered in the
1723 tutorial, but I recommend taking a look through the GTK header
1724 files. It can be very educational. In fact, it's not difficult to
1725 learn how a widget works just by looking at the function declarations.
1726
1727 <!-- ----------------------------------------------------------------- -->
1728 <sect1>Widget Hierarchy
1729 <p>
1730 For your reference, here is the class hierarchy tree used to implement widgets.
1731
1732 <tscreen><verb>
1733  GtkObject
1734   +GtkWidget
1735   | +GtkMisc
1736   | | +GtkLabel
1737   | | | +GtkAccelLabel
1738   | | | `GtkTipsQuery
1739   | | +GtkArrow
1740   | | +GtkImage
1741   | | `GtkPixmap
1742   | +GtkContainer
1743   | | +GtkBin
1744   | | | +GtkAlignment
1745   | | | +GtkFrame
1746   | | | | `GtkAspectFrame
1747   | | | +GtkButton
1748   | | | | +GtkToggleButton
1749   | | | | | `GtkCheckButton
1750   | | | | |   `GtkRadioButton
1751   | | | | `GtkOptionMenu
1752   | | | +GtkItem
1753   | | | | +GtkMenuItem
1754   | | | | | +GtkCheckMenuItem
1755   | | | | | | `GtkRadioMenuItem
1756   | | | | | `GtkTearoffMenuItem
1757   | | | | +GtkListItem
1758   | | | | `GtkTreeItem
1759   | | | +GtkWindow
1760   | | | | +GtkColorSelectionDialog
1761   | | | | +GtkDialog
1762   | | | | | `GtkInputDialog
1763   | | | | +GtkDrawWindow
1764   | | | | +GtkFileSelection
1765   | | | | +GtkFontSelectionDialog
1766   | | | | `GtkPlug
1767   | | | +GtkEventBox
1768   | | | +GtkHandleBox
1769   | | | +GtkScrolledWindow
1770   | | | `GtkViewport
1771   | | +GtkBox
1772   | | | +GtkButtonBox
1773   | | | | +GtkHButtonBox
1774   | | | | `GtkVButtonBox
1775   | | | +GtkVBox
1776   | | | | +GtkColorSelection
1777   | | | | `GtkGammaCurve
1778   | | | `GtkHBox
1779   | | |   +GtkCombo
1780   | | |   `GtkStatusbar
1781   | | +GtkCList
1782   | | | `GtkCTree
1783   | | +GtkFixed
1784   | | +GtkNotebook
1785   | | | `GtkFontSelection
1786   | | +GtkPaned
1787   | | | +GtkHPaned
1788   | | | `GtkVPaned
1789   | | +GtkLayout
1790   | | +GtkList
1791   | | +GtkMenuShell
1792   | | | +GtkMenuBar
1793   | | | `GtkMenu
1794   | | +GtkPacker
1795   | | +GtkSocket
1796   | | +GtkTable
1797   | | +GtkToolbar
1798   | | `GtkTree
1799   | +GtkCalendar
1800   | +GtkDrawingArea
1801   | | `GtkCurve
1802   | +GtkEditable
1803   | | +GtkEntry
1804   | | | `GtkSpinButton
1805   | | `GtkText
1806   | +GtkRuler
1807   | | +GtkHRuler
1808   | | `GtkVRuler
1809   | +GtkRange
1810   | | +GtkScale
1811   | | | +GtkHScale
1812   | | | `GtkVScale
1813   | | `GtkScrollbar
1814   | |   +GtkHScrollbar
1815   | |   `GtkVScrollbar
1816   | +GtkSeparator
1817   | | +GtkHSeparator
1818   | | `GtkVSeparator
1819   | +GtkPreview
1820   | `GtkProgress
1821   |   `GtkProgressBar
1822   +GtkData
1823   | +GtkAdjustment
1824   | `GtkTooltips
1825   `GtkItemFactory
1826 </verb></tscreen>
1827
1828 <!-- ----------------------------------------------------------------- -->
1829 <sect1>Widgets Without Windows
1830 <p>
1831 The following widgets do not have an associated window. If you want to
1832 capture events, you'll have to use the EventBox. See the section on
1833 the <ref id="sec_EventBox" name="EventBox"> widget.
1834
1835 <tscreen><verb>
1836 GtkAlignment
1837 GtkArrow
1838 GtkBin
1839 GtkBox
1840 GtkImage
1841 GtkItem
1842 GtkLabel
1843 GtkPixmap
1844 GtkScrolledWindow
1845 GtkSeparator
1846 GtkTable
1847 GtkAspectFrame
1848 GtkFrame
1849 GtkVBox
1850 GtkHBox
1851 GtkVSeparator
1852 GtkHSeparator
1853 </verb></tscreen>
1854
1855 We'll further our exploration of GTK by examining each widget in turn,
1856 creating a few simple functions to display them. Another good source
1857 is the testgtk.c program that comes with GTK. It can be found in
1858 gtk/testgtk.c.
1859
1860 <!-- ***************************************************************** -->
1861 <sect>The Button Widget
1862 <!-- ***************************************************************** -->
1863
1864 <!-- ----------------------------------------------------------------- -->
1865 <sect1>Normal Buttons
1866 <p>
1867 We've almost seen all there is to see of the button widget. It's
1868 pretty simple. There are however two ways to create a button. You can
1869 use the gtk_button_new_with_label() to create a button with a label,
1870 or use gtk_button_new() to create a blank button. It's then up to you
1871 to pack a label or pixmap into this new button. To do this, create a
1872 new box, and then pack your objects into this box using the usual
1873 gtk_box_pack_start, and then use gtk_container_add to pack the box
1874 into the button.
1875
1876 Here's an example of using gtk_button_new to create a button with a
1877 picture and a label in it. I've broken up the code to create a box
1878 from the rest so you can use it in your programs. There are further
1879 examples of using pixmaps later in the tutorial.
1880
1881 <tscreen><verb>
1882 /* example-start buttons buttons.c */
1883
1884 #include <gtk/gtk.h>
1885
1886 /* Create a new hbox with an image and a label packed into it
1887  * and return the box. */
1888
1889 GtkWidget *xpm_label_box( GtkWidget *parent,
1890                           gchar     *xpm_filename,
1891                           gchar     *label_text )
1892 {
1893     GtkWidget *box1;
1894     GtkWidget *label;
1895     GtkWidget *pixmapwid;
1896     GdkPixmap *pixmap;
1897     GdkBitmap *mask;
1898     GtkStyle *style;
1899
1900     /* Create box for xpm and label */
1901     box1 = gtk_hbox_new (FALSE, 0);
1902     gtk_container_set_border_width (GTK_CONTAINER (box1), 2);
1903
1904     /* Get the style of the button to get the
1905      * background color. */
1906     style = gtk_widget_get_style(parent);
1907
1908     /* Now on to the xpm stuff */
1909     pixmap = gdk_pixmap_create_from_xpm (parent->window, &amp;mask,
1910                                          &amp;style->bg[GTK_STATE_NORMAL],
1911                                          xpm_filename);
1912     pixmapwid = gtk_pixmap_new (pixmap, mask);
1913
1914     /* Create a label for the button */
1915     label = gtk_label_new (label_text);
1916
1917     /* Pack the pixmap and label into the box */
1918     gtk_box_pack_start (GTK_BOX (box1),
1919                         pixmapwid, FALSE, FALSE, 3);
1920
1921     gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);
1922
1923     gtk_widget_show(pixmapwid);
1924     gtk_widget_show(label);
1925
1926     return(box1);
1927 }
1928
1929 /* Our usual callback function */
1930 void callback( GtkWidget *widget,
1931                gpointer   data )
1932 {
1933     g_print ("Hello again - %s was pressed\n", (char *) data);
1934 }
1935
1936
1937 int main( int   argc,
1938           char *argv[] )
1939 {
1940     /* GtkWidget is the storage type for widgets */
1941     GtkWidget *window;
1942     GtkWidget *button;
1943     GtkWidget *box1;
1944
1945     gtk_init (&amp;argc, &amp;argv);
1946
1947     /* Create a new window */
1948     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1949
1950     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
1951
1952     /* It's a good idea to do this for all windows. */
1953     gtk_signal_connect (GTK_OBJECT (window), "destroy",
1954                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1955
1956     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1957                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1958
1959     /* Sets the border width of the window. */
1960     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1961     gtk_widget_realize(window);
1962
1963     /* Create a new button */
1964     button = gtk_button_new ();
1965
1966     /* Connect the "clicked" signal of the button to our callback */
1967     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1968                         GTK_SIGNAL_FUNC (callback), (gpointer) "cool button");
1969
1970     /* This calls our box creating function */
1971     box1 = xpm_label_box(window, "info.xpm", "cool button");
1972
1973     /* Pack and show all our widgets */
1974     gtk_widget_show(box1);
1975
1976     gtk_container_add (GTK_CONTAINER (button), box1);
1977
1978     gtk_widget_show(button);
1979
1980     gtk_container_add (GTK_CONTAINER (window), button);
1981
1982     gtk_widget_show (window);
1983
1984     /* Rest in gtk_main and wait for the fun to begin! */
1985     gtk_main ();
1986
1987     return(0);
1988 }
1989 /* example-end */
1990 </verb></tscreen>
1991
1992 The xpm_label_box function could be used to pack xpm's and labels into
1993 any widget that can be a container.
1994
1995 Notice in <tt/xpm_label_box/ how there is a call to
1996 <tt/gtk_widget_get_style/. Every widget has a "style", consisting of
1997 foreground and background colors for a variety of situations, font
1998 selection, and other graphics data relevant to a widget. These style
1999 values are defaulted in each widget, and are required by many GDK
2000 function calls, such as <tt/gdk_pixmap_create_from_xpm/, which here is
2001 given the "normal" background color. The style data of widgets may
2002 be customized, using <ref id="sec_gtkrc_files" name="GTK's rc files">.
2003
2004 Also notice the call to <tt/gtk_widget_realize/ after setting the
2005 window's border width. This function uses GDK to create the X
2006 windows related to the widget. The function is automatically called
2007 when you invoke <tt/gtk_widget_show/ for a widget, and so has not been
2008 shown in earlier examples. But the call to
2009 <tt/gdk_pixmap_create_from_xpm/ requires that its <tt/window/ argument
2010 refer to a real X window, so it is necessary to realize the widget
2011 before this GDK call.
2012
2013 The Button widget has the following signals:
2014
2015 <itemize>
2016 <item><tt/pressed/ - emitted when pointer button is pressed within
2017 Button widget
2018 <item><tt/released/ - emitted when pointer button is released within
2019 Button widget
2020 <item><tt/clicked/ - emitted when pointer button is pressed and then
2021 released within Button widget
2022 <item><tt/enter/ - emitted when pointer enters Button widget
2023 <item><tt/leave/ - emitted when pointer leaves Button widget
2024 </itemize>
2025
2026 <!-- ----------------------------------------------------------------- -->
2027 <sect1> Toggle Buttons
2028 <p>
2029 Toggle buttons are derived from normal buttons and are very similar,
2030 except they will always be in one of two states, alternated by a
2031 click. They may be depressed, and when you click again, they will pop
2032 back up. Click again, and they will pop back down.
2033
2034 Toggle buttons are the basis for check buttons and radio buttons, as
2035 such, many of the calls used for toggle buttons are inherited by radio
2036 and check buttons. I will point these out when we come to them.
2037
2038 Creating a new toggle button:
2039
2040 <tscreen><verb>
2041 GtkWidget *gtk_toggle_button_new( void );
2042
2043 GtkWidget *gtk_toggle_button_new_with_label( gchar *label );
2044 </verb></tscreen>
2045
2046 As you can imagine, these work identically to the normal button widget
2047 calls. The first creates a blank toggle button, and the second, a
2048 button with a label widget already packed into it.
2049
2050 To retrieve the state of the toggle widget, including radio and check
2051 buttons, we use a construct as shown in our example below. This tests
2052 the state of the toggle, by accessing the <tt/active/ field of the
2053 toggle widget's structure, after first using the
2054 <tt/GTK_TOGGLE_BUTTON/ macro to cast the widget pointer into a toggle
2055 widget pointer. The signal of interest to us emitted by toggle
2056 buttons (the toggle button, check button, and radio button widgets) is
2057 the "toggled" signal. To check the state of these buttons, set up a
2058 signal handler to catch the toggled signal, and access the structure
2059 to determine its state. The callback will look something like:
2060
2061 <tscreen><verb>
2062 void toggle_button_callback (GtkWidget *widget, gpointer data)
2063 {
2064     if (GTK_TOGGLE_BUTTON (widget)->active) 
2065     {
2066         /* If control reaches here, the toggle button is down */
2067     
2068     } else {
2069     
2070         /* If control reaches here, the toggle button is up */
2071     }
2072 }
2073 </verb></tscreen>
2074
2075 To force the state of a toggle button, and its children, the radio and
2076 check buttons, use this function:
2077
2078 <tscreen><verb>
2079 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2080                                   gint             state );
2081 </verb></tscreen>
2082
2083 The above call can be used to set the state of the toggle button, and
2084 its children the radio and check buttons. Passing in your created
2085 button as the first argument, and a TRUE or FALSE for the second state
2086 argument to specify whether it should be down (depressed) or up
2087 (released). Default is up, or FALSE.
2088
2089 Note that when you use the gtk_toggle_button_set_active() function, and
2090 the state is actually changed, it causes the "clicked" signal to be
2091 emitted from the button.
2092
2093 <tscreen><verb>
2094 void gtk_toggle_button_toggled (GtkToggleButton *toggle_button);
2095 </verb></tscreen>
2096
2097 This simply toggles the button, and emits the "toggled" signal.
2098
2099 <!-- ----------------------------------------------------------------- -->
2100 <sect1> Check Buttons
2101 <p>
2102 Check buttons inherit many properties and functions from the the
2103 toggle buttons above, but look a little different. Rather than being
2104 buttons with text inside them, they are small squares with the text to
2105 the right of them. These are often used for toggling options on and
2106 off in applications.
2107
2108 The two creation functions are similar to those of the normal button.
2109
2110 <tscreen><verb>
2111 GtkWidget *gtk_check_button_new( void );
2112
2113 GtkWidget *gtk_check_button_new_with_label ( gchar *label );
2114 </verb></tscreen>
2115
2116 The new_with_label function creates a check button with a label beside
2117 it.
2118
2119 Checking the state of the check button is identical to that of the
2120 toggle button.
2121
2122 <!-- ----------------------------------------------------------------- -->
2123 <sect1> Radio Buttons <label id="sec_Radio_Buttons">
2124 <p>
2125 Radio buttons are similar to check buttons except they are grouped so
2126 that only one may be selected/depressed at a time. This is good for
2127 places in your application where you need to select from a short list
2128 of options.
2129
2130 Creating a new radio button is done with one of these calls:
2131
2132 <tscreen><verb>
2133 GtkWidget *gtk_radio_button_new( GSList *group );
2134
2135 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
2136                                             gchar  *label );
2137 </verb></tscreen>
2138
2139 You'll notice the extra argument to these calls. They require a group
2140 to perform their duty properly. The first call to
2141 gtk_radio_button_new_with_label or gtk_radio_button_new_with_label
2142 should pass NULL as the first argument. Then create a group using:
2143
2144 <tscreen><verb>
2145 GSList *gtk_radio_button_group( GtkRadioButton *radio_button );
2146 </verb></tscreen>
2147
2148 The important thing to remember is that gtk_radio_button_group must be
2149 called for each new button added to the group, with the previous
2150 button passed in as an argument. The result is then passed into the
2151 next call to gtk_radio_button_new or
2152 gtk_radio_button_new_with_label. This allows a chain of buttons to be
2153 established. The example below should make this clear.
2154
2155 You can shorten this slightly by using the following syntax, which
2156 removes the need for a variable to hold the list of buttons. This form
2157 is used in the example to create the third button:
2158
2159 <tscreen><verb>
2160      button2 = gtk_radio_button_new_with_label(
2161                  gtk_radio_button_group (GTK_RADIO_BUTTON (button1)),
2162                  "button2");
2163 </verb></tscreen>
2164
2165 It is also a good idea to explicitly set which button should be the
2166 default depressed button with:
2167
2168 <tscreen><verb>
2169 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2170                                   gint             state );
2171 </verb></tscreen>
2172
2173 This is described in the section on toggle buttons, and works in
2174 exactly the same way.  Once the radio buttons are grouped together,
2175 only one of the group may be active at a time. If the user clicks on
2176 one radio button, and then on another, the first radio button will
2177 first emit a "toggled" signal (to report becoming inactive), and then
2178 the second will emit its "toggled" signal (to report becoming active).
2179
2180 The following example creates a radio button group with three buttons.
2181
2182 <tscreen><verb>
2183 /* example-start radiobuttons radiobuttons.c */
2184
2185 #include <gtk/gtk.h>
2186 #include <glib.h>
2187
2188 gint close_application( GtkWidget *widget,
2189                         GdkEvent  *event,
2190                         gpointer   data )
2191 {
2192   gtk_main_quit();
2193   return(FALSE);
2194 }
2195
2196 int main( int   argc,
2197           char *argv[] )
2198 {
2199     GtkWidget *window = NULL;
2200     GtkWidget *box1;
2201     GtkWidget *box2;
2202     GtkWidget *button;
2203     GtkWidget *separator;
2204     GSList *group;
2205   
2206     gtk_init(&amp;argc,&amp;argv);    
2207       
2208     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2209   
2210     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
2211                         GTK_SIGNAL_FUNC(close_application),
2212                         NULL);
2213
2214     gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
2215     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2216
2217     box1 = gtk_vbox_new (FALSE, 0);
2218     gtk_container_add (GTK_CONTAINER (window), box1);
2219     gtk_widget_show (box1);
2220
2221     box2 = gtk_vbox_new (FALSE, 10);
2222     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2223     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2224     gtk_widget_show (box2);
2225
2226     button = gtk_radio_button_new_with_label (NULL, "button1");
2227     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2228     gtk_widget_show (button);
2229
2230     group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
2231     button = gtk_radio_button_new_with_label(group, "button2");
2232     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2233     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2234     gtk_widget_show (button);
2235
2236     button = gtk_radio_button_new_with_label(
2237                  gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
2238                  "button3");
2239     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2240     gtk_widget_show (button);
2241
2242     separator = gtk_hseparator_new ();
2243     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2244     gtk_widget_show (separator);
2245
2246     box2 = gtk_vbox_new (FALSE, 10);
2247     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2248     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2249     gtk_widget_show (box2);
2250
2251     button = gtk_button_new_with_label ("close");
2252     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2253                                GTK_SIGNAL_FUNC(close_application),
2254                                GTK_OBJECT (window));
2255     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2256     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2257     gtk_widget_grab_default (button);
2258     gtk_widget_show (button);
2259     gtk_widget_show (window);
2260      
2261     gtk_main();
2262
2263     return(0);
2264 }
2265 /* example-end */
2266 </verb></tscreen>
2267
2268 <!-- TODO: check out gtk_radio_button_new_from_widget function - TRG -->
2269
2270 <!-- ***************************************************************** -->
2271 <sect> Adjustments <label id="sec_Adjustment">
2272 <!-- ***************************************************************** -->
2273 <p>
2274 GTK has various widgets that can be visually adjusted by the user
2275 using the mouse or the keyboard, such as the range widgets, described
2276 in the <ref id="sec_Range_Widgets" name="Range Widgets">
2277 section. There are also a few widgets that display some adjustable
2278 portion of a larger area of data, such as the text widget and the
2279 viewport widget.
2280
2281 Obviously, an application needs to be able to react to changes the
2282 user makes in range widgets. One way to do this would be to have each
2283 widget emit its own type of signal when its adjustment changes, and
2284 either pass the new value to the signal handler, or require it to look
2285 inside the widget's data structure in order to ascertain the value.
2286 But you may also want to connect the adjustments of several widgets
2287 together, so that adjusting one adjusts the others. The most obvious
2288 example of this is connecting a scrollbar to a panning viewport or a
2289 scrolling text area. If each widget has its own way of setting or
2290 getting the adjustment value, then the programmer may have to write
2291 their own signal handlers to translate between the output of one
2292 widget's signal and the "input" of another's adjustment setting
2293 function.
2294
2295 GTK solves this problem using the Adjustment object, which is not a
2296 widget but a way for widgets to store and pass adjustment information
2297 in an abstract and flexible form. The most obvious use of Adjustment
2298 is to store the configuration parameters and values of range widgets,
2299 such as scrollbars and scale controls. However, since Adjustments are
2300 derived from Object, they have some special powers beyond those of
2301 normal data structures. Most importantly, they can emit signals, just
2302 like widgets, and these signals can be used not only to allow your
2303 program to react to user input on adjustable widgets, but also to
2304 propagate adjustment values transparently between adjustable widgets.
2305
2306 You will see how adjustments fit in when you see the other widgets
2307 that incorporate them:
2308 <ref id="sec_ProgressBar" name="Progress Bars">,
2309 <ref id="sec_Viewports" name="Viewports">,
2310 <ref id="sec_ScrolledWindow" name="Scrolled Windows">, and others.
2311
2312 <sect1> Creating an Adjustment
2313 <p>
2314 Many of the widgets which use adjustment objects do so automatically,
2315 but some cases will be shown in later examples where you may need to
2316 create one yourself. You create an adjustment using:
2317
2318 <tscreen><verb>
2319 GtkObject *gtk_adjustment_new( gfloat value,
2320                                gfloat lower,
2321                                gfloat upper,
2322                                gfloat step_increment,
2323                                gfloat page_increment,
2324                                gfloat page_size );
2325 </verb></tscreen>
2326
2327 The <tt/value/ argument is the initial value you want to give to the
2328 adjustment, usually corresponding to the topmost or leftmost position
2329 of an adjustable widget. The <tt/lower/ argument specifies the lowest
2330 value which the adjustment can hold. The <tt/step_increment/ argument
2331 specifies the "smaller" of the two increments by which the user can
2332 change the value, while the <tt/page_increment/ is the "larger" one.
2333 The <tt/page_size/ argument usually corresponds somehow to the visible
2334 area of a panning widget. The <tt/upper/ argument is used to represent
2335 the bottom most or right most coordinate in a panning widget's
2336 child. Therefore it is <em/not/ always the largest number that
2337 <tt/value/ can take, since the <tt/page_size/ of such widgets is
2338 usually non-zero.
2339
2340 <!-- ----------------------------------------------------------------- -->
2341 <sect1> Using Adjustments the Easy Way
2342 <p>
2343 The adjustable widgets can be roughly divided into those which use and
2344 require specific units for these values and those which treat them as
2345 arbitrary numbers. The group which treats the values as arbitrary
2346 numbers includes the range widgets (scrollbars and scales, the
2347 progress bar widget, and the spin button widget). These widgets are
2348 all the widgets which are typically "adjusted" directly by the user
2349 with the mouse or keyboard. They will treat the <tt/lower/ and
2350 <tt/upper/ values of an adjustment as a range within which the user
2351 can manipulate the adjustment's <tt/value/. By default, they will only
2352 modify the <tt/value/ of an adjustment.
2353
2354 The other group includes the text widget, the viewport widget, the
2355 compound list widget, and the scrolled window widget. All of these
2356 widgets use pixel values for their adjustments. These are also all
2357 widgets which are typically "adjusted" indirectly using scrollbars.
2358 While all widgets which use adjustments can either create their own
2359 adjustments or use ones you supply, you'll generally want to let this
2360 particular category of widgets create its own adjustments. Usually,
2361 they will eventually override all the values except the <tt/value/
2362 itself in whatever adjustments you give them, but the results are, in
2363 general, undefined (meaning, you'll have to read the source code to
2364 find out, and it may be different from widget to widget).
2365
2366 Now, you're probably thinking, since text widgets and viewports insist
2367 on setting everything except the <tt/value/ of their adjustments,
2368 while scrollbars will <em/only/ touch the adjustment's <tt/value/, if
2369 you <em/share/ an adjustment object between a scrollbar and a text
2370 widget, manipulating the scrollbar will automagically adjust the text
2371 widget?  Of course it will! Just like this:
2372
2373 <tscreen><verb>
2374   /* creates its own adjustments */
2375   text = gtk_text_new (NULL, NULL);
2376   /* uses the newly-created adjustment for the scrollbar as well */
2377   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
2378 </verb></tscreen>
2379
2380 </sect1>
2381 <!-- ----------------------------------------------------------------- -->
2382 <sect1> Adjustment Internals
2383 <p>
2384 Ok, you say, that's nice, but what if I want to create my own handlers
2385 to respond when the user adjusts a range widget or a spin button, and
2386 how do I get at the value of the adjustment in these handlers?  To
2387 answer these questions and more, let's start by taking a look at
2388 <tt>struct _GtkAdjustment</tt> itself:
2389
2390 <tscreen><verb>
2391 struct _GtkAdjustment
2392 {
2393   GtkData data;
2394   
2395   gfloat lower;
2396   gfloat upper;
2397   gfloat value;
2398   gfloat step_increment;
2399   gfloat page_increment;
2400   gfloat page_size;
2401 };     
2402 </verb></tscreen>
2403
2404 The first thing you should know is that there aren't any handy-dandy
2405 macros or accessor functions for getting the <tt/value/ out of an
2406 Adjustment, so you'll have to (horror of horrors) do it like a
2407 <em/real/ C programmer.  Don't worry - the <tt>GTK_ADJUSTMENT
2408 (Object)</tt> macro does run-time type checking (as do all the GTK
2409 type-casting macros, actually).
2410
2411 Since, when you set the <tt/value/ of an adjustment, you generally
2412 want the change to be reflected by every widget that uses this
2413 adjustment, GTK provides this convenience function to do this:
2414
2415 <tscreen><verb>
2416 void gtk_adjustment_set_value( GtkAdjustment *adjustment,
2417                                gfloat         value );
2418 </verb></tscreen>
2419
2420 As mentioned earlier, Adjustment is a subclass of Object just
2421 like all the various widgets, and thus it is able to emit signals.
2422 This is, of course, why updates happen automagically when you share an
2423 adjustment object between a scrollbar and another adjustable widget;
2424 all adjustable widgets connect signal handlers to their adjustment's
2425 <tt/value_changed/ signal, as can your program. Here's the definition
2426 of this signal in <tt/struct _GtkAdjustmentClass/:
2427
2428 <tscreen><verb>
2429   void (* value_changed) (GtkAdjustment *adjustment);
2430 </verb></tscreen>
2431
2432 The various widgets that use the Adjustment object will emit this
2433 signal on an adjustment whenever they change its value. This happens
2434 both when user input causes the slider to move on a range widget, as
2435 well as when the program explicitly changes the value with
2436 <tt/gtk_adjustment_set_value()/. So, for example, if you have a scale
2437 widget, and you want to change the rotation of a picture whenever its
2438 value changes, you would create a callback like this:
2439
2440 <tscreen><verb>
2441 void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
2442 {
2443   set_picture_rotation (picture, adj->value);
2444 ...
2445 </verb></tscreen>
2446
2447 and connect it to the scale widget's adjustment like this:
2448
2449 <tscreen><verb>
2450 gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
2451                     GTK_SIGNAL_FUNC (cb_rotate_picture), picture);
2452 </verb></tscreen>
2453
2454 What about when a widget reconfigures the <tt/upper/ or <tt/lower/
2455 fields of its adjustment, such as when a user adds more text to a text
2456 widget?  In this case, it emits the <tt/changed/ signal, which looks
2457 like this:
2458
2459 <tscreen><verb>
2460   void (* changed)       (GtkAdjustment *adjustment);
2461 </verb></tscreen>
2462
2463 Range widgets typically connect a handler to this signal, which
2464 changes their appearance to reflect the change - for example, the size
2465 of the slider in a scrollbar will grow or shrink in inverse proportion
2466 to the difference between the <tt/lower/ and <tt/upper/ values of its
2467 adjustment.
2468
2469 You probably won't ever need to attach a handler to this signal,
2470 unless you're writing a new type of range widget.  However, if you
2471 change any of the values in a Adjustment directly, you should emit
2472 this signal on it to reconfigure whatever widgets are using it, like
2473 this:
2474
2475 <tscreen><verb>
2476 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2477 </verb></tscreen>
2478
2479 Now go forth and adjust!
2480 </sect1>
2481 </sect>
2482
2483 <!-- ***************************************************************** -->
2484 <sect> Range Widgets<label id="sec_Range_Widgets">
2485 <!-- ***************************************************************** -->
2486
2487 <p>
2488 The category of range widgets includes the ubiquitous scrollbar widget
2489 and the less common "scale" widget. Though these two types of widgets
2490 are generally used for different purposes, they are quite similar in
2491 function and implementation. All range widgets share a set of common
2492 graphic elements, each of which has its own X window and receives
2493 events. They all contain a "trough" and a "slider" (what is sometimes
2494 called a "thumbwheel" in other GUI environments). Dragging the slider
2495 with the pointer moves it back and forth within the trough, while
2496 clicking in the trough advances the slider towards the location of the
2497 click, either completely, or by a designated amount, depending on
2498 which mouse button is used.
2499
2500 As mentioned in <ref id="sec_Adjustment" name="Adjustments"> above,
2501 all range widgets are associated with an adjustment object, from which
2502 they calculate the length of the slider and its position within the
2503 trough. When the user manipulates the slider, the range widget will
2504 change the value of the adjustment.
2505
2506 <!-- ----------------------------------------------------------------- -->
2507 <sect1> Scrollbar Widgets
2508 <p>
2509 These are your standard, run-of-the-mill scrollbars. These should be
2510 used only for scrolling some other widget, such as a list, a text box,
2511 or a viewport (and it's generally easier to use the scrolled window
2512 widget in most cases).  For other purposes, you should use scale
2513 widgets, as they are friendlier and more featureful.
2514
2515 There are separate types for horizontal and vertical scrollbars.
2516 There really isn't much to say about these. You create them with the
2517 following functions, defined in <tt>&lt;gtk/gtkhscrollbar.h&gt;</tt>
2518 and <tt>&lt;gtk/gtkvscrollbar.h&gt;</tt>:
2519
2520 <tscreen><verb>
2521 GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );
2522
2523 GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );
2524 </verb></tscreen>
2525
2526 and that's about it (if you don't believe me, look in the header
2527 files!).  The <tt/adjustment/ argument can either be a pointer to an
2528 existing Adjustment, or NULL, in which case one will be created for
2529 you. Specifying NULL might actually be useful in this case, if you
2530 wish to pass the newly-created adjustment to the constructor function
2531 of some other widget which will configure it for you, such as a text
2532 widget.
2533 </sect1>
2534
2535 <!-- ----------------------------------------------------------------- -->
2536 <sect1> Scale Widgets
2537 <p>
2538 Scale widgets are used to allow the user to visually select and
2539 manipulate a value within a specific range. You might want to use a
2540 scale widget, for example, to adjust the magnification level on a
2541 zoomed preview of a picture, or to control the brightness of a color,
2542 or to specify the number of minutes of inactivity before a screensaver
2543 takes over the screen.
2544
2545 <!-- ----------------------------------------------------------------- -->
2546 <sect2>Creating a Scale Widget
2547 <p>
2548 As with scrollbars, there are separate widget types for horizontal and
2549 vertical scale widgets. (Most programmers seem to favour horizontal
2550 scale widgets.) Since they work essentially the same way, there's no
2551 need to treat them separately here. The following functions, defined
2552 in <tt>&lt;gtk/gtkvscale.h&gt;</tt> and
2553 <tt>&lt;gtk/gtkhscale.h&gt;</tt>, create vertical and horizontal scale
2554 widgets, respectively:
2555
2556 <tscreen>
2557 <verb>
2558 GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );
2559
2560 GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );
2561 </verb>
2562 </tscreen>
2563
2564 The <tt/adjustment/ argument can either be an adjustment which has
2565 already been created with <tt/gtk_adjustment_new()/, or <tt/NULL/, in
2566 which case, an anonymous Adjustment is created with all of its
2567 values set to <tt/0.0/ (which isn't very useful in this case). In
2568 order to avoid confusing yourself, you probably want to create your
2569 adjustment with a <tt/page_size/ of <tt/0.0/ so that its <tt/upper/
2570 value actually corresponds to the highest value the user can select.
2571 (If you're <em/already/ thoroughly confused, read the section on <ref
2572 id="sec_Adjustment" name="Adjustments"> again for an explanation of
2573 what exactly adjustments do and how to create and manipulate them.)
2574
2575 <!-- ----------------------------------------------------------------- -->
2576 <sect2> Functions and Signals (well, functions, at least)
2577 <p>
2578 Scale widgets can display their current value as a number beside the
2579 trough. The default behaviour is to show the value, but you can change
2580 this with this function:
2581
2582 <tscreen><verb>
2583 void gtk_scale_set_draw_value( GtkScale *scale,
2584                                gint      draw_value );
2585 </verb></tscreen>
2586
2587 As you might have guessed, <tt/draw_value/ is either <tt/TRUE/ or
2588 <tt/FALSE/, with predictable consequences for either one.
2589
2590 The value displayed by a scale widget is rounded to one decimal point
2591 by default, as is the <tt/value/ field in its GtkAdjustment. You can
2592 change this with:
2593
2594 <tscreen>
2595 <verb>
2596 void gtk_scale_set_digits( GtkScale *scale,
2597                             gint     digits );
2598 </verb>
2599 </tscreen>
2600
2601 where <tt/digits/ is the number of decimal places you want. You can
2602 set <tt/digits/ to anything you like, but no more than 13 decimal
2603 places will actually be drawn on screen.
2604
2605 Finally, the value can be drawn in different positions
2606 relative to the trough:
2607
2608 <tscreen>
2609 <verb>
2610 void gtk_scale_set_value_pos( GtkScale        *scale,
2611                               GtkPositionType  pos );
2612 </verb>
2613 </tscreen>
2614
2615 The argument <tt/pos/ is of type <tt>GtkPositionType</tt>, which is
2616 defined in <tt>&lt;gtk/gtkenums.h&gt;</tt>, and can take one of the
2617 following values:
2618
2619 <tscreen><verb>
2620   GTK_POS_LEFT
2621   GTK_POS_RIGHT
2622   GTK_POS_TOP
2623   GTK_POS_BOTTOM
2624 </verb></tscreen>
2625
2626 If you position the value on the "side" of the trough (e.g., on the
2627 top or bottom of a horizontal scale widget), then it will follow the
2628 slider up and down the trough.
2629
2630 All the preceding functions are defined in
2631 <tt>&lt;gtk/gtkscale.h&gt;</tt>. The header files for all GTK widgets
2632 are automatically included when you include
2633 <tt>&lt;gtk/gtk.h&gt;</tt>. But you should look over the header files
2634 of all widgets that interest you,
2635
2636 </sect2>
2637 </sect1>
2638
2639 <!-- ----------------------------------------------------------------- -->
2640 <sect1> Common Range Functions <label id="sec_Range_Functions">
2641 <p>
2642 The Range widget class is fairly complicated internally, but, like
2643 all the "base class" widgets, most of its complexity is only
2644 interesting if you want to hack on it. Also, almost all of the
2645 functions and signals it defines are only really used in writing
2646 derived widgets. There are, however, a few useful functions that are
2647 defined in <tt>&lt;gtk/gtkrange.h&gt;</tt> and will work on all range
2648 widgets.
2649
2650 <!-- ----------------------------------------------------------------- -->
2651 <sect2> Setting the Update Policy
2652 <p>
2653 The "update policy" of a range widget defines at what points during
2654 user interaction it will change the <tt/value/ field of its
2655 Adjustment and emit the "value_changed" signal on this
2656 Adjustment. The update policies, defined in
2657 <tt>&lt;gtk/gtkenums.h&gt;</tt> as type <tt>enum GtkUpdateType</tt>,
2658 are:
2659
2660 <itemize>
2661 <item>GTK_UPDATE_POLICY_CONTINUOUS - This is the default. The
2662 "value_changed" signal is emitted continuously, i.e., whenever the
2663 slider is moved by even the tiniest amount.
2664 </item>
2665 <item>GTK_UPDATE_POLICY_DISCONTINUOUS - The "value_changed" signal is
2666 only emitted once the slider has stopped moving and the user has
2667 released the mouse button.
2668 </item>
2669 <item>GTK_UPDATE_POLICY_DELAYED - The "value_changed" signal is emitted
2670 when the user releases the mouse button, or if the slider stops moving
2671 for a short period of time.
2672 </item>
2673 </itemize>
2674
2675 The update policy of a range widget can be set by casting it using the
2676 <tt>GTK_RANGE (Widget)</tt> macro and passing it to this function:
2677
2678 <tscreen><verb>
2679 void gtk_range_set_update_policy( GtkRange      *range,
2680                                   GtkUpdateType  policy) ;
2681 </verb></tscreen>
2682
2683 <!-- ----------------------------------------------------------------- -->
2684 <sect2>Getting and Setting Adjustments
2685 <p>
2686 Getting and setting the adjustment for a range widget "on the fly" is
2687 done, predictably, with:
2688
2689 <tscreen><verb>
2690 GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );
2691
2692 void gtk_range_set_adjustment( GtkRange      *range,
2693                                GtkAdjustment *adjustment );
2694 </verb></tscreen>
2695
2696 <tt/gtk_range_get_adjustment()/ returns a pointer to the adjustment to
2697 which <tt/range/ is connected.
2698
2699 <tt/gtk_range_set_adjustment()/ does absolutely nothing if you pass it
2700 the adjustment that <tt/range/ is already using, regardless of whether
2701 you changed any of its fields or not. If you pass it a new
2702 Adjustment, it will unreference the old one if it exists (possibly
2703 destroying it), connect the appropriate signals to the new one, and
2704 call the private function <tt/gtk_range_adjustment_changed()/, which
2705 will (or at least, is supposed to...) recalculate the size and/or
2706 position of the slider and redraw if necessary. As mentioned in the
2707 section on adjustments, if you wish to reuse the same Adjustment,
2708 when you modify its values directly, you should emit the "changed"
2709 signal on it, like this:
2710
2711 <tscreen><verb>
2712 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2713 </verb></tscreen>
2714 </sect2>
2715 </sect1>
2716
2717 <!-- ----------------------------------------------------------------- -->
2718 <sect1> Key and Mouse bindings
2719 <p>
2720 All of the GTK range widgets react to mouse clicks in more or less
2721 the same way. Clicking button-1 in the trough will cause its
2722 adjustment's <tt/page_increment/ to be added or subtracted from its
2723 <tt/value/, and the slider to be moved accordingly. Clicking mouse
2724 button-2 in the trough will jump the slider to the point at which the
2725 button was clicked. Clicking any button on a scrollbar's arrows will
2726 cause its adjustment's value to change <tt/step_increment/ at a time.
2727
2728 It may take a little while to get used to, but by default, scrollbars
2729 as well as scale widgets can take the keyboard focus in GTK. If you
2730 think your users will find this too confusing, you can always disable
2731 this by unsetting the <tt/GTK_CAN_FOCUS/ flag on the scrollbar, like
2732 this:
2733
2734 <tscreen><verb>
2735 GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS);
2736 </verb></tscreen>
2737
2738 The key bindings (which are, of course, only active when the widget
2739 has focus) are slightly different between horizontal and vertical
2740 range widgets, for obvious reasons. They are also not quite the same
2741 for scale widgets as they are for scrollbars, for somewhat less
2742 obvious reasons (possibly to avoid confusion between the keys for
2743 horizontal and vertical scrollbars in scrolled windows, where both
2744 operate on the same area).
2745
2746 <sect2> Vertical Range Widgets
2747 <p>
2748 All vertical range widgets can be operated with the up and down arrow
2749 keys, as well as with the <tt/Page Up/ and <tt/Page Down/ keys. The
2750 arrows move the slider up and down by <tt/step_increment/, while
2751 <tt/Page Up/ and <tt/Page Down/ move it by <tt/page_increment/.
2752
2753 The user can also move the slider all the way to one end or the other
2754 of the trough using the keyboard. With the VScale widget, this is
2755 done with the <tt/Home/ and <tt/End/ keys, whereas with the
2756 VScrollbar widget, this is done by typing <tt>Control-Page Up</tt>
2757 and <tt>Control-Page Down</tt>.
2758
2759 <!-- ----------------------------------------------------------------- -->
2760 <sect2> Horizontal Range Widgets
2761 <p>
2762 The left and right arrow keys work as you might expect in these
2763 widgets, moving the slider back and forth by <tt/step_increment/. The
2764 <tt/Home/ and <tt/End/ keys move the slider to the ends of the trough.
2765 For the HScale widget, moving the slider by <tt/page_increment/ is
2766 accomplished with <tt>Control-Left</tt> and <tt>Control-Right</tt>,
2767 while for HScrollbar, it's done with <tt>Control-Home</tt> and
2768 <tt>Control-End</tt>.
2769 </sect2>
2770 </sect1>
2771
2772 <!-- ----------------------------------------------------------------- -->
2773 <sect1> Example<label id="sec_Range_Example">
2774 <p>
2775 This example is a somewhat modified version of the "range controls"
2776 test from <tt/testgtk.c/. It basically puts up a window with three
2777 range widgets all connected to the same adjustment, and a couple of
2778 controls for adjusting some of the parameters mentioned above and in
2779 the section on adjustments, so you can see how they affect the way
2780 these widgets work for the user.
2781
2782 <tscreen><verb>
2783 /* example-start rangewidgets rangewidgets.c */
2784
2785 #include <gtk/gtk.h>
2786
2787 GtkWidget *hscale, *vscale;
2788
2789 void cb_pos_menu_select( GtkWidget       *item,
2790                          GtkPositionType  pos )
2791 {
2792     /* Set the value position on both scale widgets */
2793     gtk_scale_set_value_pos (GTK_SCALE (hscale), pos);
2794     gtk_scale_set_value_pos (GTK_SCALE (vscale), pos);
2795 }
2796
2797 void cb_update_menu_select( GtkWidget     *item,
2798                             GtkUpdateType  policy )
2799 {
2800     /* Set the update policy for both scale widgets */
2801     gtk_range_set_update_policy (GTK_RANGE (hscale), policy);
2802     gtk_range_set_update_policy (GTK_RANGE (vscale), policy);
2803 }
2804
2805 void cb_digits_scale( GtkAdjustment *adj )
2806 {
2807     /* Set the number of decimal places to which adj->value is rounded */
2808     gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
2809     gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
2810 }
2811
2812 void cb_page_size( GtkAdjustment *get,
2813                    GtkAdjustment *set )
2814 {
2815     /* Set the page size and page increment size of the sample
2816      * adjustment to the value specified by the "Page Size" scale */
2817     set->page_size = get->value;
2818     set->page_increment = get->value;
2819     /* Now emit the "changed" signal to reconfigure all the widgets that
2820      * are attached to this adjustment */
2821     gtk_signal_emit_by_name (GTK_OBJECT (set), "changed");
2822 }
2823
2824 void cb_draw_value( GtkToggleButton *button )
2825 {
2826     /* Turn the value display on the scale widgets off or on depending
2827      *  on the state of the checkbutton */
2828     gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active);
2829     gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active);  
2830 }
2831
2832 /* Convenience functions */
2833
2834 GtkWidget *make_menu_item( gchar         *name,
2835                            GtkSignalFunc  callback,
2836                            gpointer       data )
2837 {
2838     GtkWidget *item;
2839   
2840     item = gtk_menu_item_new_with_label (name);
2841     gtk_signal_connect (GTK_OBJECT (item), "activate",
2842                         callback, data);
2843     gtk_widget_show (item);
2844
2845     return(item);
2846 }
2847
2848 void scale_set_default_values( GtkScale *scale )
2849 {
2850     gtk_range_set_update_policy (GTK_RANGE (scale),
2851                                  GTK_UPDATE_CONTINUOUS);
2852     gtk_scale_set_digits (scale, 1);
2853     gtk_scale_set_value_pos (scale, GTK_POS_TOP);
2854     gtk_scale_set_draw_value (scale, TRUE);
2855 }
2856
2857 /* makes the sample window */
2858
2859 void create_range_controls( void )
2860 {
2861     GtkWidget *window;
2862     GtkWidget *box1, *box2, *box3;
2863     GtkWidget *button;
2864     GtkWidget *scrollbar;
2865     GtkWidget *separator;
2866     GtkWidget *opt, *menu, *item;
2867     GtkWidget *label;
2868     GtkWidget *scale;
2869     GtkObject *adj1, *adj2;
2870
2871     /* Standard window-creating stuff */
2872     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2873     gtk_signal_connect (GTK_OBJECT (window), "destroy",
2874                         GTK_SIGNAL_FUNC(gtk_main_quit),
2875                         NULL);
2876     gtk_window_set_title (GTK_WINDOW (window), "range controls");
2877
2878     box1 = gtk_vbox_new (FALSE, 0);
2879     gtk_container_add (GTK_CONTAINER (window), box1);
2880     gtk_widget_show (box1);
2881
2882     box2 = gtk_hbox_new (FALSE, 10);
2883     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2884     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2885     gtk_widget_show (box2);
2886
2887     /* value, lower, upper, step_increment, page_increment, page_size */
2888     /* Note that the page_size value only makes a difference for
2889      * scrollbar widgets, and the highest value you'll get is actually
2890      * (upper - page_size). */
2891     adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
2892   
2893     vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1));
2894     scale_set_default_values (GTK_SCALE (vscale));
2895     gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0);
2896     gtk_widget_show (vscale);
2897
2898     box3 = gtk_vbox_new (FALSE, 10);
2899     gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0);
2900     gtk_widget_show (box3);
2901
2902     /* Reuse the same adjustment */
2903     hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1));
2904     gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 30);
2905     scale_set_default_values (GTK_SCALE (hscale));
2906     gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0);
2907     gtk_widget_show (hscale);
2908
2909     /* Reuse the same adjustment again */
2910     scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1));
2911     /* Notice how this causes the scales to always be updated
2912      * continuously when the scrollbar is moved */
2913     gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
2914                                  GTK_UPDATE_CONTINUOUS);
2915     gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0);
2916     gtk_widget_show (scrollbar);
2917
2918     box2 = gtk_hbox_new (FALSE, 10);
2919     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2920     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2921     gtk_widget_show (box2);
2922
2923     /* A checkbutton to control whether the value is displayed or not */
2924     button = gtk_check_button_new_with_label("Display value on scale widgets");
2925     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2926     gtk_signal_connect (GTK_OBJECT (button), "toggled",
2927                         GTK_SIGNAL_FUNC(cb_draw_value), NULL);
2928     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2929     gtk_widget_show (button);
2930   
2931     box2 = gtk_hbox_new (FALSE, 10);
2932     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2933
2934     /* An option menu to change the position of the value */
2935     label = gtk_label_new ("Scale Value Position:");
2936     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2937     gtk_widget_show (label);
2938   
2939     opt = gtk_option_menu_new();
2940     menu = gtk_menu_new();
2941
2942     item = make_menu_item ("Top",
2943                            GTK_SIGNAL_FUNC(cb_pos_menu_select),
2944                            GINT_TO_POINTER (GTK_POS_TOP));
2945     gtk_menu_append (GTK_MENU (menu), item);
2946   
2947     item = make_menu_item ("Bottom", GTK_SIGNAL_FUNC (cb_pos_menu_select), 
2948                            GINT_TO_POINTER (GTK_POS_BOTTOM));
2949     gtk_menu_append (GTK_MENU (menu), item);
2950   
2951     item = make_menu_item ("Left", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2952                            GINT_TO_POINTER (GTK_POS_LEFT));
2953     gtk_menu_append (GTK_MENU (menu), item);
2954   
2955     item = make_menu_item ("Right", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2956                             GINT_TO_POINTER (GTK_POS_RIGHT));
2957     gtk_menu_append (GTK_MENU (menu), item);
2958   
2959     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2960     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2961     gtk_widget_show (opt);
2962
2963     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2964     gtk_widget_show (box2);
2965
2966     box2 = gtk_hbox_new (FALSE, 10);
2967     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2968
2969     /* Yet another option menu, this time for the update policy of the
2970      * scale widgets */
2971     label = gtk_label_new ("Scale Update Policy:");
2972     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2973     gtk_widget_show (label);
2974   
2975     opt = gtk_option_menu_new();
2976     menu = gtk_menu_new();
2977   
2978     item = make_menu_item ("Continuous",
2979                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2980                            GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS));
2981     gtk_menu_append (GTK_MENU (menu), item);
2982   
2983     item = make_menu_item ("Discontinuous",
2984                             GTK_SIGNAL_FUNC (cb_update_menu_select),
2985                             GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS));
2986     gtk_menu_append (GTK_MENU (menu), item);
2987   
2988     item = make_menu_item ("Delayed",
2989                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2990                            GINT_TO_POINTER (GTK_UPDATE_DELAYED));
2991     gtk_menu_append (GTK_MENU (menu), item);
2992   
2993     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2994     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2995     gtk_widget_show (opt);
2996   
2997     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2998     gtk_widget_show (box2);
2999
3000     box2 = gtk_hbox_new (FALSE, 10);
3001     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3002   
3003     /* An HScale widget for adjusting the number of digits on the
3004      * sample scales. */
3005     label = gtk_label_new ("Scale Digits:");
3006     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3007     gtk_widget_show (label);
3008
3009     adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0);
3010     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
3011                         GTK_SIGNAL_FUNC (cb_digits_scale), NULL);
3012     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
3013     gtk_scale_set_digits (GTK_SCALE (scale), 0);
3014     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
3015     gtk_widget_show (scale);
3016
3017     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3018     gtk_widget_show (box2);
3019   
3020     box2 = gtk_hbox_new (FALSE, 10);
3021     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3022   
3023     /* And, one last HScale widget for adjusting the page size of the
3024      * scrollbar. */
3025     label = gtk_label_new ("Scrollbar Page Size:");
3026     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3027     gtk_widget_show (label);
3028
3029     adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0);
3030     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
3031                         GTK_SIGNAL_FUNC (cb_page_size), adj1);
3032     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
3033     gtk_scale_set_digits (GTK_SCALE (scale), 0);
3034     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
3035     gtk_widget_show (scale);
3036
3037     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3038     gtk_widget_show (box2);
3039
3040     separator = gtk_hseparator_new ();
3041     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3042     gtk_widget_show (separator);
3043
3044     box2 = gtk_vbox_new (FALSE, 10);
3045     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3046     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3047     gtk_widget_show (box2);
3048
3049     button = gtk_button_new_with_label ("Quit");
3050     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3051                                GTK_SIGNAL_FUNC(gtk_main_quit),
3052                                NULL);
3053     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3054     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3055     gtk_widget_grab_default (button);
3056     gtk_widget_show (button);
3057
3058     gtk_widget_show (window);
3059 }
3060
3061 int main( int   argc,
3062           char *argv[] )
3063 {
3064     gtk_init(&amp;argc, &amp;argv);
3065
3066     create_range_controls();
3067
3068     gtk_main();
3069
3070     return(0);
3071 }
3072
3073 /* example-end */
3074 </verb></tscreen>
3075
3076 You will notice that the program does not call <tt/gtk_signal_connect/
3077 for the "delete_event", but only for the "destroy" signal. This will
3078 still perform the desired function, because an unhandled
3079 "delete_event" will result in a "destroy" signal being given to the
3080 window.
3081
3082 </sect1>
3083 </sect>
3084
3085 <!-- ***************************************************************** -->
3086 <sect> Miscellaneous Widgets
3087 <!-- ***************************************************************** -->
3088
3089 <!-- ----------------------------------------------------------------- -->
3090 <sect1> Labels
3091 <p>
3092 Labels are used a lot in GTK, and are relatively simple. Labels emit
3093 no signals as they do not have an associated X window. If you need to
3094 catch signals, or do clipping, place it inside a <ref id="sec_EventBox"
3095 name="EventBox"> widget or a Button widget.
3096
3097 To create a new label, use:
3098
3099 <tscreen><verb>
3100 GtkWidget *gtk_label_new( char *str );
3101 </verb></tscreen>
3102
3103 The sole argument is the string you wish the label to display.
3104
3105 To change the label's text after creation, use the function:
3106
3107 <tscreen><verb>
3108 void gtk_label_set_text( GtkLabel *label,
3109                          char     *str );
3110 </verb></tscreen>
3111
3112 The first argument is the label you created previously (cast
3113 using the <tt/GTK_LABEL()/ macro), and the second is the new string.
3114
3115 The space needed for the new string will be automatically adjusted if
3116 needed. You can produce multi-line labels by putting line breaks in
3117 the label string.
3118
3119 To retrieve the current string, use:
3120
3121 <tscreen><verb>
3122 void gtk_label_get( GtkLabel  *label,
3123                     char     **str );
3124 </verb></tscreen>
3125
3126 The first argument is the label you've created, and the second,
3127 the return for the string. Do not free the return string, as it is
3128 used internally by GTK.
3129
3130 The label text can be justified using:
3131
3132 <tscreen><verb>
3133 void gtk_label_set_justify( GtkLabel         *label,
3134                             GtkJustification  jtype );
3135 </verb></tscreen>
3136
3137 Values for <tt/jtype/ are:
3138 <tscreen><verb>
3139   GTK_JUSTIFY_LEFT
3140   GTK_JUSTIFY_RIGHT
3141   GTK_JUSTIFY_CENTER (the default)
3142   GTK_JUSTIFY_FILL
3143 </verb></tscreen>
3144
3145 The label widget is also capable of line wrapping the text
3146 automatically. This can be activated using:
3147
3148 <tscreen><verb>
3149 void gtk_label_set_line_wrap (GtkLabel *label,
3150                               gboolean  wrap);
3151 </verb></tscreen>
3152
3153 The <tt/wrap/ argument takes a TRUE or FALSE value.
3154
3155 If you want your label underlined, then you can set a pattern on the
3156 label:
3157
3158 <tscreen><verb>
3159 void       gtk_label_set_pattern   (GtkLabel          *label,
3160                                     const gchar       *pattern);
3161 </verb></tscreen>
3162
3163 The pattern argument indicates how the underlining should look. It
3164 consists of a string of underscore and space characters. An underscore
3165 indicates that the corresponding character in the label should be
3166 underlined. For example, the string <verb/"__     __"/ would underline the
3167 first two characters and eight and ninth characters.
3168
3169 Below is a short example to illustrate these functions. This example
3170 makes use of the Frame widget to better demonstrate the label
3171 styles. You can ignore this for now as the <ref id="sec_Frames"
3172 name="Frame"> widget is explained later on.
3173
3174 <tscreen><verb>
3175 /* example-start label label.c */
3176
3177 #include <gtk/gtk.h>
3178
3179 int main( int   argc,
3180           char *argv[] )
3181 {
3182   static GtkWidget *window = NULL;
3183   GtkWidget *hbox;
3184   GtkWidget *vbox;
3185   GtkWidget *frame;
3186   GtkWidget *label;
3187
3188   /* Initialise GTK */
3189   gtk_init(&amp;argc, &amp;argv);
3190
3191   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3192   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3193                       GTK_SIGNAL_FUNC(gtk_main_quit),
3194                       NULL);
3195
3196   gtk_window_set_title (GTK_WINDOW (window), "Label");
3197   vbox = gtk_vbox_new (FALSE, 5);
3198   hbox = gtk_hbox_new (FALSE, 5);
3199   gtk_container_add (GTK_CONTAINER (window), hbox);
3200   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3201   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3202   
3203   frame = gtk_frame_new ("Normal Label");
3204   label = gtk_label_new ("This is a Normal label");
3205   gtk_container_add (GTK_CONTAINER (frame), label);
3206   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3207   
3208   frame = gtk_frame_new ("Multi-line Label");
3209   label = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \
3210                          "Third line");
3211   gtk_container_add (GTK_CONTAINER (frame), label);
3212   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3213   
3214   frame = gtk_frame_new ("Left Justified Label");
3215   label = gtk_label_new ("This is a Left-Justified\n" \
3216                          "Multi-line label.\nThird      line");
3217   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3218   gtk_container_add (GTK_CONTAINER (frame), label);
3219   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3220   
3221   frame = gtk_frame_new ("Right Justified Label");
3222   label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \
3223                          "Fourth line, (j/k)");
3224   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3225   gtk_container_add (GTK_CONTAINER (frame), label);
3226   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3227
3228   vbox = gtk_vbox_new (FALSE, 5);
3229   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3230   frame = gtk_frame_new ("Line wrapped label");
3231   label = gtk_label_new ("This is an example of a line-wrapped label.  It " \
3232                          "should not be taking up the entire             " /* big space to test spacing */\
3233                          "width allocated to it, but automatically " \
3234                          "wraps the words to fit.  " \
3235                          "The time has come, for all good men, to come to " \
3236                          "the aid of their party.  " \
3237                          "The sixth sheik's six sheep's sick.\n" \
3238                          "     It supports multiple paragraphs correctly, " \
3239                          "and  correctly   adds "\
3240                          "many          extra  spaces. ");
3241   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3242   gtk_container_add (GTK_CONTAINER (frame), label);
3243   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3244   
3245   frame = gtk_frame_new ("Filled, wrapped label");
3246   label = gtk_label_new ("This is an example of a line-wrapped, filled label.  " \
3247                          "It should be taking "\
3248                          "up the entire              width allocated to it.  " \
3249                          "Here is a sentence to prove "\
3250                          "my point.  Here is another sentence. "\
3251                          "Here comes the sun, do de do de do.\n"\
3252                          "    This is a new paragraph.\n"\
3253                          "    This is another newer, longer, better " \
3254                          "paragraph.  It is coming to an end, "\
3255                          "unfortunately.");
3256   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3257   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3258   gtk_container_add (GTK_CONTAINER (frame), label);
3259   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3260   
3261   frame = gtk_frame_new ("Underlined label");
3262   label = gtk_label_new ("This label is underlined!\n"
3263                          "This one is underlined in quite a funky fashion");
3264   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3265   gtk_label_set_pattern (GTK_LABEL (label),
3266                          "_________________________ _ _________ _ ______     __ _______ ___");
3267   gtk_container_add (GTK_CONTAINER (frame), label);
3268   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3269   
3270   gtk_widget_show_all (window);
3271
3272   gtk_main ();
3273   
3274   return(0);
3275 }
3276 /* example-end */
3277 </verb></tscreen>
3278
3279 <!-- ----------------------------------------------------------------- -->
3280 <sect1> Arrows
3281 <p>
3282 The Arrow widget draws an arrowhead, facing in a number of possible
3283 directions and having a number of possible styles. It can be very
3284 useful when placed on a button in many applications. Like the Label
3285 widget, it emits no signals.
3286
3287 There are only two functions for manipulating an Arrow widget:
3288
3289 <tscreen><verb>
3290 GtkWidget *gtk_arrow_new( GtkArrowType   arrow_type,
3291                           GtkShadowType  shadow_type );
3292
3293 void gtk_arrow_set( GtkArrow      *arrow,
3294                     GtkArrowType   arrow_type,
3295                     GtkShadowType  shadow_type );
3296 </verb></tscreen>
3297
3298 The first creates a new arrow widget with the indicated type and
3299 appearance. The second allows these values to be altered
3300 retrospectively. The <tt/arrow_type/ argument may take one of the
3301 following values:
3302
3303 <tscreen><verb>
3304   GTK_ARROW_UP
3305   GTK_ARROW_DOWN
3306   GTK_ARROW_LEFT
3307   GTK_ARROW_RIGHT
3308 </verb></tscreen>
3309
3310 These values obviously indicate the direction in which the arrow will
3311 point. The <tt/shadow_type/ argument may take one of these values:
3312
3313 <tscreen><verb>
3314   GTK_SHADOW_IN
3315   GTK_SHADOW_OUT (the default)
3316   GTK_SHADOW_ETCHED_IN
3317   GTK_SHADOW_ETCHED_OUT
3318 </verb></tscreen>
3319
3320 Here's a brief example to illustrate their use.
3321
3322 <tscreen><verb>
3323 /* example-start arrow arrow.c */
3324
3325 #include <gtk/gtk.h>
3326
3327 /* Create an Arrow widget with the specified parameters
3328  * and pack it into a button */
3329 GtkWidget *create_arrow_button( GtkArrowType  arrow_type,
3330                                 GtkShadowType shadow_type )
3331 {
3332   GtkWidget *button;
3333   GtkWidget *arrow;
3334
3335   button = gtk_button_new();
3336   arrow = gtk_arrow_new (arrow_type, shadow_type);
3337
3338   gtk_container_add (GTK_CONTAINER (button), arrow);
3339   
3340   gtk_widget_show(button);
3341   gtk_widget_show(arrow);
3342
3343   return(button);
3344 }
3345
3346 int main( int   argc,
3347           char *argv[] )
3348 {
3349   /* GtkWidget is the storage type for widgets */
3350   GtkWidget *window;
3351   GtkWidget *button;
3352   GtkWidget *box;
3353
3354   /* Initialize the toolkit */
3355   gtk_init (&amp;argc, &amp;argv);
3356
3357   /* Create a new window */
3358   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3359
3360   gtk_window_set_title (GTK_WINDOW (window), "Arrow Buttons");
3361
3362   /* It's a good idea to do this for all windows. */
3363   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3364                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
3365
3366   /* Sets the border width of the window. */
3367   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
3368
3369   /* Create a box to hold the arrows/buttons */
3370   box = gtk_hbox_new (FALSE, 0);
3371   gtk_container_set_border_width (GTK_CONTAINER (box), 2);
3372   gtk_container_add (GTK_CONTAINER (window), box);
3373
3374   /* Pack and show all our widgets */
3375   gtk_widget_show(box);
3376
3377   button = create_arrow_button(GTK_ARROW_UP, GTK_SHADOW_IN);
3378   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3379
3380   button = create_arrow_button(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
3381   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3382   
3383   button = create_arrow_button(GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN);
3384   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3385   
3386   button = create_arrow_button(GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT);
3387   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3388   
3389   gtk_widget_show (window);
3390   
3391   /* Rest in gtk_main and wait for the fun to begin! */
3392   gtk_main ();
3393   
3394   return(0);
3395 }
3396 /* example-end */
3397 </verb></tscreen>
3398
3399 <!-- ----------------------------------------------------------------- -->
3400 <sect1>The Tooltips Object
3401 <p>
3402 These are the little text strings that pop up when you leave your
3403 pointer over a button or other widget for a few seconds. They are easy
3404 to use, so I will just explain them without giving an example. If you
3405 want to see some code, take a look at the testgtk.c program
3406 distributed with GTK.
3407
3408 Widgets that do not receive events (widgets that do not have their
3409 own window) will not work with tooltips.
3410
3411 The first call you will use creates a new tooltip. You only need to do
3412 this once for a set of tooltips as the <tt/GtkTooltips/ object this
3413 function returns can be used to create multiple tooltips.
3414
3415 <tscreen><verb>
3416 GtkTooltips *gtk_tooltips_new( void );
3417 </verb></tscreen>
3418
3419 Once you have created a new tooltip, and the widget you wish to use it
3420 on, simply use this call to set it:
3421
3422 <tscreen><verb>
3423 void gtk_tooltips_set_tip( GtkTooltips *tooltips,
3424                            GtkWidget   *widget,
3425                            const gchar *tip_text,
3426                            const gchar *tip_private );
3427 </verb></tscreen>
3428
3429 The first argument is the tooltip you've already created, followed by
3430 the widget you wish to have this tooltip pop up for, and the text you
3431 wish it to say. The last argument is a text string that can be used as
3432 an identifier when using GtkTipsQuery to implement context sensitive
3433 help. For now, you can set it to NULL.
3434
3435 <!-- TODO: sort out what how to do the context sensitive help -->
3436
3437 Here's a short example:
3438
3439 <tscreen><verb>
3440 GtkTooltips *tooltips;
3441 GtkWidget *button;
3442 .
3443 .
3444 .
3445 tooltips = gtk_tooltips_new ();
3446 button = gtk_button_new_with_label ("button 1");
3447 .
3448 .
3449 .
3450 gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);
3451 </verb></tscreen>
3452
3453 There are other calls that can be used with tooltips. I will just list
3454 them with a brief description of what they do.
3455
3456 <tscreen><verb>
3457 void gtk_tooltips_enable( GtkTooltips *tooltips );
3458 </verb></tscreen>
3459
3460 Enable a disabled set of tooltips.
3461
3462 <tscreen><verb>
3463 void gtk_tooltips_disable( GtkTooltips *tooltips );
3464 </verb></tscreen>
3465
3466 Disable an enabled set of tooltips.
3467
3468 <tscreen><verb>
3469 void gtk_tooltips_set_delay( GtkTooltips *tooltips,
3470                              gint         delay );
3471
3472 </verb></tscreen>
3473
3474 Sets how many milliseconds you have to hold your pointer over the
3475 widget before the tooltip will pop up. The default is 500
3476 milliseconds (half a second).
3477
3478 <tscreen><verb>
3479 void gtk_tooltips_set_colors( GtkTooltips *tooltips,
3480                               GdkColor    *background,
3481                               GdkColor    *foreground );
3482 </verb></tscreen>
3483
3484 Set the foreground and background color of the tooltips.
3485
3486 And that's all the functions associated with tooltips. More than
3487 you'll ever want to know :-)
3488
3489 <!-- ----------------------------------------------------------------- -->
3490 <sect1> Progress Bars <label id="sec_ProgressBar">
3491 <p>
3492 Progress bars are used to show the status of an operation. They are
3493 pretty easy to use, as you will see with the code below. But first
3494 lets start out with the calls to create a new progress bar.
3495
3496 There are two ways to create a progress bar, one simple that takes
3497 no arguments, and one that takes an Adjustment object as an
3498 argument. If the former is used, the progress bar creates its own
3499 adjustment object.
3500
3501 <tscreen><verb>
3502 GtkWidget *gtk_progress_bar_new( void );
3503
3504 GtkWidget *gtk_progress_bar_new_with_adjustment( GtkAdjustment *adjustment );
3505 </verb></tscreen>
3506
3507 The second method has the advantage that we can use the adjustment
3508 object to specify our own range parameters for the progress bar.
3509
3510 The adjustment of a progress object can be changed dynamically using:
3511
3512 <tscreen><verb>
3513 void gtk_progress_set_adjustment( GtkProgress   *progress,
3514                                   GtkAdjustment *adjustment );
3515 </verb></tscreen>
3516
3517 Now that the progress bar has been created we can use it.
3518
3519 <tscreen><verb>
3520 void gtk_progress_bar_update( GtkProgressBar *pbar,
3521                               gfloat          percentage );
3522 </verb></tscreen>
3523
3524 The first argument is the progress bar you wish to operate on, and the
3525 second argument is the amount "completed", meaning the amount the
3526 progress bar has been filled from 0-100%. This is passed to the
3527 function as a real number ranging from 0 to 1.
3528
3529 GTK v1.2 has added new functionality to the progress bar that enables
3530 it to display its value in different ways, and to inform the user of
3531 its current value and its range.
3532
3533 A progress bar may be set to one of a number of orientations using the
3534 function
3535
3536 <tscreen><verb>
3537 void gtk_progress_bar_set_orientation( GtkProgressBar *pbar,
3538                                        GtkProgressBarOrientation orientation );
3539 </verb></tscreen>
3540
3541 The <tt/orientation/ argument may take one of the following
3542 values to indicate the direction in which the progress bar moves:
3543
3544 <tscreen><verb>
3545   GTK_PROGRESS_LEFT_TO_RIGHT
3546   GTK_PROGRESS_RIGHT_TO_LEFT
3547   GTK_PROGRESS_BOTTOM_TO_TOP
3548   GTK_PROGRESS_TOP_TO_BOTTOM
3549 </verb></tscreen>
3550
3551 When used as a measure of how far a process has progressed, the
3552 ProgressBar can be set to display its value in either a continuous
3553 or discrete mode. In continuous mode, the progress bar is updated for
3554 each value. In discrete mode, the progress bar is updated in a number
3555 of discrete blocks. The number of blocks is also configurable.
3556
3557 The style of a progress bar can be set using the following function.
3558
3559 <tscreen><verb>
3560 void gtk_progress_bar_set_bar_style( GtkProgressBar      *pbar,
3561                                      GtkProgressBarStyle  style );
3562 </verb></tscreen>
3563
3564 The <tt/style/ parameter can take one of two values:
3565
3566 <tscreen><verb>
3567   GTK_PROGRESS_CONTINUOUS
3568   GTK_PROGRESS_DISCRETE
3569 </verb></tscreen>
3570
3571 The number of discrete blocks can be set by calling
3572
3573 <tscreen><verb>
3574 void gtk_progress_bar_set_discrete_blocks( GtkProgressBar *pbar,
3575                                            guint           blocks );
3576 </verb></tscreen>
3577
3578 As well as indicating the amount of progress that has occured, the
3579 progress bar may be set to just indicate that there is some
3580 activity. This can be useful in situations where progress cannot be
3581 measured against a value range. Activity mode is not effected by the
3582 bar style that is described above, and overrides it. This mode is
3583 either TRUE or FALSE, and is selected by the following function.
3584
3585 <tscreen><verb>
3586 void gtk_progress_set_activity_mode( GtkProgress *progress,
3587                                      guint        activity_mode );
3588 </verb></tscreen>
3589
3590 The step size of the activity indicator, and the number of blocks are
3591 set using the following functions.
3592
3593 <tscreen><verb>
3594 void gtk_progress_bar_set_activity_step( GtkProgressBar *pbar,
3595                                          guint           step );
3596
3597 void gtk_progress_bar_set_activity_blocks( GtkProgressBar *pbar,
3598                                            guint           blocks );
3599 </verb></tscreen>
3600
3601 When in continuous mode, the progress bar can also display a
3602 configurable text string within its trough, using the following
3603 function.
3604
3605 <tscreen><verb>
3606 void gtk_progress_set_format_string( GtkProgress *progress,
3607                                      gchar       *format);
3608 </verb></tscreen>
3609
3610 The <tt/format/ argument is similiar to one that would be used in a C
3611 <tt/printf/ statement. The following directives may be used within the
3612 format string:
3613
3614 <itemize>
3615 <item> %p - percentage
3616 <item> %v - value
3617 <item> %l - lower range value
3618 <item> %u - upper range value
3619 </itemize>
3620
3621 The displaying of this text string can be toggled using:
3622
3623 <tscreen><verb>
3624 void gtk_progress_set_show_text( GtkProgress *progress,
3625                                  gint         show_text );
3626 </verb></tscreen>
3627
3628 The <tt/show_text/ argument is a boolean TRUE/FALSE value. The
3629 appearance of the text can be modified further using:
3630
3631 <tscreen><verb>
3632 void gtk_progress_set_text_alignment( GtkProgress   *progress,
3633                                       gfloat         x_align,
3634                                       gfloat         y_align );
3635 </verb></tscreen>
3636
3637 The <tt/x_align/ and <tt/y_align/ arguments take values between 0.0
3638 and 1.0. Their values indicate the position of the text string within
3639 the trough. Values of 0.0 for both would place the string in the top
3640 left hand corner; values of 0.5 (the default) centres the text, and
3641 values of 1.0 places the text in the lower right hand corner.
3642
3643 The current text setting of a progress object can be retrieved using
3644 the current or a specified adjustment value using the following two
3645 functions. The character string returned by these functions should be
3646 freed by the application (using the g_free() function). These
3647 functions return the formatted string that would be displayed within
3648 the trough.
3649
3650 <tscreen><verb>
3651 gchar *gtk_progress_get_current_text( GtkProgress   *progress );
3652
3653 gchar *gtk_progress_get_text_from_value( GtkProgress *progress,
3654                                          gfloat       value );
3655 </verb></tscreen>
3656
3657 There is yet another way to change the range and value of a progress
3658 object using the following function:
3659
3660 <tscreen><verb>
3661 void gtk_progress_configure( GtkProgress  *progress,
3662                              gfloat        value,
3663                              gfloat        min,
3664                              gfloat        max );
3665 </verb></tscreen>
3666
3667 This function provides quite a simple interface to the range and value
3668 of a progress object.
3669
3670 The remaining functions can be used to get and set the current value
3671 of a progess object in various types and formats:
3672
3673 <tscreen><verb>
3674 void gtk_progress_set_percentage( GtkProgress *progress,
3675                                   gfloat       percentage );
3676
3677 void gtk_progress_set_value( GtkProgress *progress,
3678                              gfloat       value );
3679
3680 gfloat gtk_progress_get_value( GtkProgress *progress );
3681
3682 gfloat gtk_progress_get_current_percentage( GtkProgress *progress );
3683
3684 gfloat gtk_progress_get_percentage_from_value( GtkProgress *progress,
3685                                                gfloat       value );
3686 </verb></tscreen>
3687
3688 These functions are pretty self explanatory. The last function uses
3689 the the adjustment of the specified progess object to compute the
3690 percentage value of the given range value.
3691
3692 Progress Bars are usually used with timeouts or other such functions
3693 (see section on <ref id="sec_timeouts" name="Timeouts, I/O and Idle
3694 Functions">) to give the illusion of multitasking. All will employ the
3695 gtk_progress_bar_update function in the same manner.
3696
3697 Here is an example of the progress bar, updated using timeouts. This
3698 code also shows you how to reset the Progress Bar.
3699
3700 <tscreen><verb>
3701 /* example-start progressbar progressbar.c */
3702
3703 #include <gtk/gtk.h>
3704
3705 typedef struct _ProgressData {
3706     GtkWidget *window;
3707     GtkWidget *pbar;
3708     int timer;
3709 } ProgressData;
3710
3711 /* Update the value of the progress bar so that we get
3712  * some movement */
3713 gint progress_timeout( gpointer data )
3714 {
3715     gfloat new_val;
3716     GtkAdjustment *adj;
3717
3718     /* Calculate the value of the progress bar using the
3719      * value range set in the adjustment object */
3720
3721     new_val = gtk_progress_get_value( GTK_PROGRESS(data) ) + 1;
3722
3723     adj = GTK_PROGRESS (data)->adjustment;
3724     if (new_val > adj->upper)
3725       new_val = adj->lower;
3726
3727     /* Set the new value */
3728     gtk_progress_set_value (GTK_PROGRESS (data), new_val);
3729
3730     /* As this is a timeout function, return TRUE so that it
3731      * continues to get called */
3732     return(TRUE);
3733
3734
3735 /* Callback that toggles the text display within the progress
3736  * bar trough */
3737 void toggle_show_text( GtkWidget    *widget,
3738                        ProgressData *pdata )
3739 {
3740     gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
3741                                 GTK_TOGGLE_BUTTON (widget)->active);
3742 }
3743
3744 /* Callback that toggles the activity mode of the progress
3745  * bar */
3746 void toggle_activity_mode( GtkWidget    *widget,
3747                            ProgressData *pdata )
3748 {
3749     gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
3750                                     GTK_TOGGLE_BUTTON (widget)->active);
3751 }
3752
3753 /* Callback that toggles the continuous mode of the progress
3754  * bar */
3755 void set_continuous_mode( GtkWidget    *widget,
3756                           ProgressData *pdata )
3757 {
3758     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3759                                     GTK_PROGRESS_CONTINUOUS);
3760 }
3761
3762 /* Callback that toggles the discrete mode of the progress
3763  * bar */
3764 void set_discrete_mode( GtkWidget    *widget,
3765                         ProgressData *pdata )
3766 {
3767     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3768                                     GTK_PROGRESS_DISCRETE);
3769 }
3770  
3771 /* Clean up allocated memory and remove the timer */
3772 void destroy_progress( GtkWidget     *widget,
3773                        ProgressData *pdata)
3774 {
3775     gtk_timeout_remove (pdata->timer);
3776     pdata->timer = 0;
3777     pdata->window = NULL;
3778     g_free(pdata);
3779     gtk_main_quit();
3780 }
3781
3782 int main( int   argc,
3783           char *argv[])
3784 {
3785     ProgressData *pdata;
3786     GtkWidget *align;
3787     GtkWidget *separator;
3788     GtkWidget *table;
3789     GtkAdjustment *adj;
3790     GtkWidget *button;
3791     GtkWidget *check;
3792     GtkWidget *vbox;
3793
3794     gtk_init (&amp;argc, &amp;argv);
3795
3796     /* Allocate memory for the data that is passwd to the callbacks */
3797     pdata = g_malloc( sizeof(ProgressData) );
3798   
3799     pdata->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3800     gtk_window_set_policy (GTK_WINDOW (pdata->window), FALSE, FALSE, TRUE);
3801
3802     gtk_signal_connect (GTK_OBJECT (pdata->window), "destroy",
3803                         GTK_SIGNAL_FUNC (destroy_progress),
3804                         pdata);
3805     gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
3806     gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
3807
3808     vbox = gtk_vbox_new (FALSE, 5);
3809     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
3810     gtk_container_add (GTK_CONTAINER (pdata->window), vbox);
3811     gtk_widget_show(vbox);
3812   
3813     /* Create a centering alignment object */
3814     align = gtk_alignment_new (0.5, 0.5, 0, 0);
3815     gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
3816     gtk_widget_show(align);
3817
3818     /* Create a Adjusment object to hold the range of the
3819      * progress bar */
3820     adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 150, 0, 0, 0);
3821
3822     /* Create the GtkProgressBar using the adjustment */
3823     pdata->pbar = gtk_progress_bar_new_with_adjustment (adj);
3824
3825     /* Set the format of the string that can be displayed in the
3826      * trough of the progress bar:
3827      * %p - percentage
3828      * %v - value
3829      * %l - lower range value
3830      * %u - upper range value */
3831     gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
3832                                     "%v from [%l-%u] (=%p%%)");
3833     gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
3834     gtk_widget_show(pdata->pbar);
3835
3836     /* Add a timer callback to update the value of the progress bar */
3837     pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
3838
3839     separator = gtk_hseparator_new ();
3840     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3841     gtk_widget_show(separator);
3842
3843     /* rows, columns, homogeneous */
3844     table = gtk_table_new (2, 3, FALSE);
3845     gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
3846     gtk_widget_show(table);
3847
3848     /* Add a check button to select displaying of the trough text */
3849     check = gtk_check_button_new_with_label ("Show text");
3850     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
3851                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3852                       5, 5);
3853     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3854                         GTK_SIGNAL_FUNC (toggle_show_text),
3855                         pdata);
3856     gtk_widget_show(check);
3857
3858     /* Add a check button to toggle activity mode */
3859     check = gtk_check_button_new_with_label ("Activity mode");
3860     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
3861                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3862                       5, 5);
3863     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3864                         GTK_SIGNAL_FUNC (toggle_activity_mode),
3865                         pdata);
3866     gtk_widget_show(check);
3867
3868     separator = gtk_vseparator_new ();
3869     gtk_table_attach (GTK_TABLE (table), separator, 1, 2, 0, 2,
3870                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3871                       5, 5);
3872     gtk_widget_show(separator);
3873
3874     /* Add a radio button to select continuous display mode */
3875     button = gtk_radio_button_new_with_label (NULL, "Continuous");
3876     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
3877                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3878                       5, 5);
3879     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3880                         GTK_SIGNAL_FUNC (set_continuous_mode),
3881                         pdata);
3882     gtk_widget_show (button);
3883
3884     /* Add a radio button to select discrete display mode */
3885     button = gtk_radio_button_new_with_label(
3886                gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
3887                "Discrete");
3888     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
3889                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3890                       5, 5);
3891     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3892                         GTK_SIGNAL_FUNC (set_discrete_mode),
3893                         pdata);
3894     gtk_widget_show (button);
3895
3896     separator = gtk_hseparator_new ();
3897     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3898     gtk_widget_show(separator);
3899
3900     /* Add a button to exit the program */
3901     button = gtk_button_new_with_label ("close");
3902     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3903                                (GtkSignalFunc) gtk_widget_destroy,
3904                                GTK_OBJECT (pdata->window));
3905     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3906
3907     /* This makes it so the button is the default. */
3908     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3909
3910     /* This grabs this button to be the default button. Simply hitting
3911      * the "Enter" key will cause this button to activate. */
3912     gtk_widget_grab_default (button);
3913     gtk_widget_show(button);
3914
3915     gtk_widget_show (pdata->window);
3916
3917     gtk_main ();
3918     
3919     return(0);
3920 }
3921 /* example-end */
3922 </verb></tscreen>
3923
3924 <!-- ----------------------------------------------------------------- -->
3925 <sect1> Dialogs
3926 <p>
3927 The Dialog widget is very simple, and is actually just a window with a
3928 few things pre-packed into it for you. The structure for a Dialog is:
3929
3930 <tscreen><verb>
3931 struct GtkDialog
3932 {
3933       GtkWindow window;
3934     
3935       GtkWidget *vbox;
3936       GtkWidget *action_area;
3937 };
3938 </verb></tscreen>
3939
3940 So you see, it simply creates a window, and then packs a vbox into the
3941 top, which contains a separator and then an hbox called the
3942 "action_area".
3943
3944 The Dialog widget can be used for pop-up messages to the user, and
3945 other similar tasks. It is really basic, and there is only one
3946 function for the dialog box, which is:
3947
3948 <tscreen><verb>
3949 GtkWidget *gtk_dialog_new( void );
3950 </verb></tscreen>
3951
3952 So to create a new dialog box, use,
3953
3954 <tscreen><verb>
3955     GtkWidget *window;
3956     window = gtk_dialog_new ();
3957 </verb></tscreen>
3958
3959 This will create the dialog box, and it is now up to you to use it.
3960 You could pack a button in the action_area by doing something like this:
3961
3962 <tscreen><verb>
3963     button = ...
3964     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
3965                         button, TRUE, TRUE, 0);
3966     gtk_widget_show (button);
3967 </verb></tscreen>
3968
3969 And you could add to the vbox area by packing, for instance, a label 
3970 in it, try something like this:
3971
3972 <tscreen><verb>
3973     label = gtk_label_new ("Dialogs are groovy");
3974     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
3975                         label, TRUE, TRUE, 0);
3976     gtk_widget_show (label);
3977 </verb></tscreen>
3978
3979 As an example in using the dialog box, you could put two buttons in
3980 the action_area, a Cancel button and an Ok button, and a label in the
3981 vbox area, asking the user a question or giving an error etc. Then
3982 you could attach a different signal to each of the buttons and perform
3983 the operation the user selects.
3984
3985 If the simple functionality provided by the default vertical and
3986 horizontal boxes in the two areas doesn't give you enough control for
3987 your application, then you can simply pack another layout widget into
3988 the boxes provided. For example, you could pack a table into the
3989 vertical box.
3990
3991 <!-- ----------------------------------------------------------------- -->
3992 <sect1> Pixmaps <label id="sec_Pixmaps">
3993 <p>
3994 Pixmaps are data structures that contain pictures. These pictures can
3995 be used in various places, but most commonly as icons on the X
3996 desktop, or as cursors.
3997
3998 A pixmap which only has 2 colors is called a bitmap, and there are a
3999 few additional routines for handling this common special case.
4000
4001 To understand pixmaps, it would help to understand how X window
4002 system works. Under X, applications do not need to be running on the
4003 same computer that is interacting with the user. Instead, the various
4004 applications, called "clients", all communicate with a program which
4005 displays the graphics and handles the keyboard and mouse. This
4006 program which interacts directly with the user is called a "display
4007 server" or "X server." Since the communication might take place over
4008 a network, it's important to keep some information with the X server.
4009 Pixmaps, for example, are stored in the memory of the X server. This
4010 means that once pixmap values are set, they don't need to keep getting
4011 transmitted over the network; instead a command is sent to "display
4012 pixmap number XYZ here." Even if you aren't using X with GTK
4013 currently, using constructs such as Pixmaps will make your programs
4014 work acceptably under X.
4015
4016 To use pixmaps in GTK, we must first build a GdkPixmap structure using
4017 routines from the GDK layer. Pixmaps can either be created from
4018 in-memory data, or from data read from a file. We'll go through each
4019 of the calls to create a pixmap.
4020
4021 <tscreen><verb>
4022 GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window,
4023                                         gchar     *data,
4024                                         gint       width,
4025                                         gint       height );
4026 </verb></tscreen>
4027
4028 This routine is used to create a single-plane pixmap (2 colors) from
4029 data in memory. Each bit of the data represents whether that pixel is
4030 off or on. Width and height are in pixels. The GdkWindow pointer is to
4031 the current window, since a pixmap's resources are meaningful only in
4032 the context of the screen where it is to be displayed.
4033
4034 <tscreen><verb>
4035 GdkPixmap *gdk_pixmap_create_from_data( GdkWindow *window,
4036                                         gchar     *data,
4037                                         gint       width,
4038                                         gint       height,
4039                                         gint       depth,
4040                                         GdkColor  *fg,
4041                                         GdkColor  *bg );
4042 </verb></tscreen>
4043
4044 This is used to create a pixmap of the given depth (number of colors) from
4045 the bitmap data specified. <tt/fg/ and <tt/bg/ are the foreground and
4046 background color to use.
4047
4048 <tscreen><verb>
4049 GdkPixmap *gdk_pixmap_create_from_xpm( GdkWindow   *window,
4050                                        GdkBitmap  **mask,
4051                                        GdkColor    *transparent_color,
4052                                        const gchar *filename );
4053 </verb></tscreen>
4054
4055 XPM format is a readable pixmap representation for the X Window
4056 System. It is widely used and many different utilities are available
4057 for creating image files in this format. The file specified by
4058 filename must contain an image in that format and it is loaded into
4059 the pixmap structure. The mask specifies which bits of the pixmap are
4060 opaque. All other bits are colored using the color specified by
4061 transparent_color. An example using this follows below.
4062
4063 <tscreen><verb>
4064 GdkPixmap *gdk_pixmap_create_from_xpm_d( GdkWindow  *window,
4065                                          GdkBitmap **mask,
4066                                          GdkColor   *transparent_color,
4067                                          gchar     **data );
4068 </verb></tscreen>
4069
4070 Small images can be incorporated into a program as data in the XPM
4071 format. A pixmap is created using this data, instead of reading it
4072 from a file. An example of such data is
4073
4074 <tscreen><verb>
4075 /* XPM */
4076 static const char * xpm_data[] = {
4077 "16 16 3 1",
4078 "       c None",
4079 ".      c #000000000000",
4080 "X      c #FFFFFFFFFFFF",
4081 "                ",
4082 "   ......       ",
4083 "   .XXX.X.      ",
4084 "   .XXX.XX.     ",
4085 "   .XXX.XXX.    ",
4086 "   .XXX.....    ",
4087 "   .XXXXXXX.    ",
4088 "   .XXXXXXX.    ",
4089 "   .XXXXXXX.    ",
4090 "   .XXXXXXX.    ",
4091 "   .XXXXXXX.    ",
4092 "   .XXXXXXX.    ",
4093 "   .XXXXXXX.    ",
4094 "   .........    ",
4095 "                ",
4096 "                "};
4097 </verb></tscreen>
4098
4099 When we're done using a pixmap and not likely to reuse it again soon,
4100 it is a good idea to release the resource using
4101 gdk_pixmap_unref(). Pixmaps should be considered a precious resource,
4102 because they take up memory in the end-user's X server process. Even
4103 though the X client you write may run on a powerful "server" computer,
4104 the user may be running the X server on a small personal computer.
4105
4106 Once we've created a pixmap, we can display it as a GTK widget. We
4107 must create a GTK pixmap widget to contain the GDK pixmap. This is
4108 done using
4109
4110 <tscreen><verb>
4111 GtkWidget *gtk_pixmap_new( GdkPixmap *pixmap,
4112                            GdkBitmap *mask );
4113 </verb></tscreen>
4114
4115 The other pixmap widget calls are
4116
4117 <tscreen><verb>
4118 guint gtk_pixmap_get_type( void );
4119
4120 void  gtk_pixmap_set( GtkPixmap  *pixmap,
4121                       GdkPixmap  *val,
4122                       GdkBitmap  *mask );
4123
4124 void  gtk_pixmap_get( GtkPixmap  *pixmap,
4125                       GdkPixmap **val,
4126                       GdkBitmap **mask);
4127 </verb></tscreen>
4128
4129 gtk_pixmap_set is used to change the pixmap that the widget is currently
4130 managing. Val is the pixmap created using GDK.
4131
4132 The following is an example of using a pixmap in a button.
4133
4134 <tscreen><verb>
4135 /* example-start pixmap pixmap.c */
4136
4137 #include <gtk/gtk.h>
4138
4139
4140 /* XPM data of Open-File icon */
4141 static const char * xpm_data[] = {
4142 "16 16 3 1",
4143 "       c None",
4144 ".      c #000000000000",
4145 "X      c #FFFFFFFFFFFF",
4146 "                ",
4147 "   ......       ",
4148 "   .XXX.X.      ",
4149 "   .XXX.XX.     ",
4150 "   .XXX.XXX.    ",
4151 "   .XXX.....    ",
4152 "   .XXXXXXX.    ",
4153 "   .XXXXXXX.    ",
4154 "   .XXXXXXX.    ",
4155 "   .XXXXXXX.    ",
4156 "   .XXXXXXX.    ",
4157 "   .XXXXXXX.    ",
4158 "   .XXXXXXX.    ",
4159 "   .........    ",
4160 "                ",
4161 "                "};
4162
4163
4164 /* when invoked (via signal delete_event), terminates the application.
4165  */
4166 gint close_application( GtkWidget *widget,
4167                         GdkEvent  *event,
4168                         gpointer   data )
4169 {
4170     gtk_main_quit();
4171     return(FALSE);
4172 }
4173
4174
4175 /* is invoked when the button is clicked.  It just prints a message.
4176  */
4177 void button_clicked( GtkWidget *widget,
4178                      gpointer   data ) {
4179     g_print( "button clicked\n" );
4180 }
4181
4182 int main( int   argc,
4183           char *argv[] )
4184 {
4185     /* GtkWidget is the storage type for widgets */
4186     GtkWidget *window, *pixmapwid, *button;
4187     GdkPixmap *pixmap;
4188     GdkBitmap *mask;
4189     GtkStyle *style;
4190     
4191     /* create the main window, and attach delete_event signal to terminating
4192        the application */
4193     gtk_init( &amp;argc, &amp;argv );
4194     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4195     gtk_signal_connect( GTK_OBJECT (window), "delete_event",
4196                         GTK_SIGNAL_FUNC (close_application), NULL );
4197     gtk_container_set_border_width( GTK_CONTAINER (window), 10 );
4198     gtk_widget_show( window );
4199
4200     /* now for the pixmap from gdk */
4201     style = gtk_widget_get_style( window );
4202     pixmap = gdk_pixmap_create_from_xpm_d( window->window,  &amp;mask,
4203                                            &amp;style->bg[GTK_STATE_NORMAL],
4204                                            (gchar **)xpm_data );
4205
4206     /* a pixmap widget to contain the pixmap */
4207     pixmapwid = gtk_pixmap_new( pixmap, mask );
4208     gtk_widget_show( pixmapwid );
4209
4210     /* a button to contain the pixmap widget */
4211     button = gtk_button_new();
4212     gtk_container_add( GTK_CONTAINER(button), pixmapwid );
4213     gtk_container_add( GTK_CONTAINER(window), button );
4214     gtk_widget_show( button );
4215
4216     gtk_signal_connect( GTK_OBJECT(button), "clicked",
4217                         GTK_SIGNAL_FUNC(button_clicked), NULL );
4218
4219     /* show the window */
4220     gtk_main ();
4221           
4222     return 0;
4223 }
4224 /* example-end */
4225 </verb></tscreen>
4226
4227 To load a file from an XPM data file called icon0.xpm in the current
4228 directory, we would have created the pixmap thus
4229
4230 <tscreen><verb>
4231     /* load a pixmap from a file */
4232     pixmap = gdk_pixmap_create_from_xpm( window->window, &amp;mask,
4233                                          &amp;style->bg[GTK_STATE_NORMAL],
4234                                          "./icon0.xpm" );
4235     pixmapwid = gtk_pixmap_new( pixmap, mask );
4236     gtk_widget_show( pixmapwid );
4237     gtk_container_add( GTK_CONTAINER(window), pixmapwid );
4238 </verb></tscreen>
4239
4240 A disadvantage of using pixmaps is that the displayed object is always
4241 rectangular, regardless of the image. We would like to create desktops
4242 and applications with icons that have more natural shapes. For
4243 example, for a game interface, we would like to have round buttons to
4244 push. The way to do this is using shaped windows.
4245
4246 A shaped window is simply a pixmap where the background pixels are
4247 transparent. This way, when the background image is multi-colored, we
4248 don't overwrite it with a rectangular, non-matching border around our
4249 icon. The following example displays a full wheelbarrow image on the
4250 desktop.
4251
4252 <tscreen><verb>
4253 /* example-start wheelbarrow wheelbarrow.c */
4254
4255 #include <gtk/gtk.h>
4256
4257 /* XPM */
4258 static char * WheelbarrowFull_xpm[] = {
4259 "48 48 64 1",
4260 "       c None",
4261 ".      c #DF7DCF3CC71B",
4262 "X      c #965875D669A6",
4263 "o      c #71C671C671C6",
4264 "O      c #A699A289A699",
4265 "+      c #965892489658",
4266 "@      c #8E38410330C2",
4267 "#      c #D75C7DF769A6",
4268 "$      c #F7DECF3CC71B",
4269 "%      c #96588A288E38",
4270 "&amp;      c #A69992489E79",
4271 "*      c #8E3886178E38",
4272 "=      c #104008200820",
4273 "-      c #596510401040",
4274 ";      c #C71B30C230C2",
4275 ":      c #C71B9A699658",
4276 ">      c #618561856185",
4277 ",      c #20811C712081",
4278 "<      c #104000000000",
4279 "1      c #861720812081",
4280 "2      c #DF7D4D344103",
4281 "3      c #79E769A671C6",
4282 "4      c #861782078617",
4283 "5      c #41033CF34103",
4284 "6      c #000000000000",
4285 "7      c #49241C711040",
4286 "8      c #492445144924",
4287 "9      c #082008200820",
4288 "0      c #69A618611861",
4289 "q      c #B6DA71C65144",
4290 "w      c #410330C238E3",
4291 "e      c #CF3CBAEAB6DA",
4292 "r      c #71C6451430C2",
4293 "t      c #EFBEDB6CD75C",
4294 "y      c #28A208200820",
4295 "u      c #186110401040",
4296 "i      c #596528A21861",
4297 "p      c #71C661855965",
4298 "a      c #A69996589658",
4299 "s      c #30C228A230C2",
4300 "d      c #BEFBA289AEBA",
4301 "f      c #596545145144",
4302 "g      c #30C230C230C2",
4303 "h      c #8E3882078617",
4304 "j      c #208118612081",
4305 "k      c #38E30C300820",
4306 "l      c #30C2208128A2",
4307 "z      c #38E328A238E3",
4308 "x      c #514438E34924",
4309 "c      c #618555555965",
4310 "v      c #30C2208130C2",
4311 "b      c #38E328A230C2",
4312 "n      c #28A228A228A2",
4313 "m      c #41032CB228A2",
4314 "M      c #104010401040",
4315 "N      c #492438E34103",
4316 "B      c #28A2208128A2",
4317 "V      c #A699596538E3",
4318 "C      c #30C21C711040",
4319 "Z      c #30C218611040",
4320 "A      c #965865955965",
4321 "S      c #618534D32081",
4322 "D      c #38E31C711040",
4323 "F      c #082000000820",
4324 "                                                ",
4325 "          .XoO                                  ",
4326 "         +@#$%o&amp;                                ",
4327 "         *=-;#::o+                              ",
4328 "           >,<12#:34                            ",
4329 "             45671#:X3                          ",
4330 "               +89<02qwo                        ",
4331 "e*                >,67;ro                       ",
4332 "ty>                 459@>+&amp;&amp;                    ",
4333 "$2u+                  ><ipas8*                  ",
4334 "%$;=*                *3:.Xa.dfg>                ",
4335 "Oh$;ya             *3d.a8j,Xe.d3g8+             ",
4336 " Oh$;ka          *3d$a8lz,,xxc:.e3g54           ",
4337 "  Oh$;kO       *pd$%svbzz,sxxxxfX..&amp;wn>         ",
4338 "   Oh$@mO    *3dthwlsslszjzxxxxxxx3:td8M4       ",
4339 "    Oh$@g&amp; *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B*     ",
4340 "     Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5&amp;   ",
4341 "      Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM*  ",
4342 "       OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
4343 "        2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
4344 "        :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
4345 "         +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
4346 "          *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&amp;en",
4347 "           p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
4348 "           OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
4349 "            3206Bwxxszx%et.eaAp77m77mmmf3&amp;eeeg* ",
4350 "             @26MvzxNzvlbwfpdettttttttttt.c,n&amp;  ",
4351 "             *;16=lsNwwNwgsvslbwwvccc3pcfu<o    ",
4352 "              p;<69BvwwsszslllbBlllllllu<5+     ",
4353 "              OS0y6FBlvvvzvzss,u=Blllj=54       ",
4354 "               c1-699Blvlllllu7k96MMMg4         ",
4355 "               *10y8n6FjvllllB<166668           ",
4356 "                S-kg+>666<M<996-y6n<8*          ",
4357 "                p71=4 m69996kD8Z-66698&amp;&amp;        ",
4358 "                &amp;i0ycm6n4 ogk17,0<6666g         ",
4359 "                 N-k-<>     >=01-kuu666>        ",
4360 "                 ,6ky&amp;      &amp;46-10ul,66,        ",
4361 "                 Ou0<>       o66y<ulw<66&amp;       ",
4362 "                  *kk5       >66By7=xu664       ",
4363 "                   <<M4      466lj<Mxu66o       ",
4364 "                   *>>       +66uv,zN666*       ",
4365 "                              566,xxj669        ",
4366 "                              4666FF666>        ",
4367 "                               >966666M         ",
4368 "                                oM6668+         ",
4369 "                                  *4            ",
4370 "                                                ",
4371 "                                                "};
4372
4373
4374 /* When invoked (via signal delete_event), terminates the application */
4375 gint close_application( GtkWidget *widget,
4376                         GdkEvent  *event,
4377                         gpointer   data )
4378 {
4379     gtk_main_quit();
4380     return(FALSE);
4381 }
4382
4383 int main (int argc,
4384           char *argv[] )
4385 {
4386     /* GtkWidget is the storage type for widgets */
4387     GtkWidget *window, *pixmap, *fixed;
4388     GdkPixmap *gdk_pixmap;
4389     GdkBitmap *mask;
4390     GtkStyle *style;
4391     GdkGC *gc;
4392     
4393     /* Create the main window, and attach delete_event signal to terminate
4394      * the application.  Note that the main window will not have a titlebar
4395      * since we're making it a popup. */
4396     gtk_init (&amp;argc, &amp;argv);
4397     window = gtk_window_new( GTK_WINDOW_POPUP );
4398     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4399                         GTK_SIGNAL_FUNC (close_application), NULL);
4400     gtk_widget_show (window);
4401
4402     /* Now for the pixmap and the pixmap widget */
4403     style = gtk_widget_get_default_style();
4404     gc = style->black_gc;
4405     gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &amp;mask,
4406                                              &amp;style->bg[GTK_STATE_NORMAL],
4407                                              WheelbarrowFull_xpm );
4408     pixmap = gtk_pixmap_new( gdk_pixmap, mask );
4409     gtk_widget_show( pixmap );
4410
4411     /* To display the pixmap, we use a fixed widget to place the pixmap */
4412     fixed = gtk_fixed_new();
4413     gtk_widget_set_usize( fixed, 200, 200 );
4414     gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
4415     gtk_container_add( GTK_CONTAINER(window), fixed );
4416     gtk_widget_show( fixed );
4417
4418     /* This masks out everything except for the image itself */
4419     gtk_widget_shape_combine_mask( window, mask, 0, 0 );
4420     
4421     /* show the window */
4422     gtk_widget_set_uposition( window, 20, 400 );
4423     gtk_widget_show( window );
4424     gtk_main ();
4425           
4426     return(0);
4427 }
4428 /* example-end */
4429 </verb></tscreen>
4430
4431 To make the wheelbarrow image sensitive, we could attach the button
4432 press event signal to make it do something. The following few lines
4433 would make the picture sensitive to a mouse button being pressed which
4434 makes the application terminate.
4435
4436 <tscreen><verb>
4437     gtk_widget_set_events( window,
4438                           gtk_widget_get_events( window ) |
4439                           GDK_BUTTON_PRESS_MASK );
4440
4441    gtk_signal_connect( GTK_OBJECT(window), "button_press_event",
4442                        GTK_SIGNAL_FUNC(close_application), NULL );
4443 </verb></tscreen>
4444
4445 <!-- ----------------------------------------------------------------- -->
4446 <sect1>Rulers
4447 <p>
4448 Ruler widgets are used to indicate the location of the mouse pointer
4449 in a given window. A window can have a vertical ruler spanning across
4450 the width and a horizontal ruler spanning down the height. A small
4451 triangular indicator on the ruler shows the exact location of the
4452 pointer relative to the ruler.
4453
4454 A ruler must first be created. Horizontal and vertical rulers are
4455 created using
4456
4457 <tscreen><verb>
4458 GtkWidget *gtk_hruler_new( void );    /* horizontal ruler */
4459
4460 GtkWidget *gtk_vruler_new( void );    /* vertical ruler   */
4461 </verb></tscreen>
4462
4463 Once a ruler is created, we can define the unit of measurement. Units
4464 of measure for rulers can be<tt/GTK_PIXELS/, <tt/GTK_INCHES/ or
4465 <tt/GTK_CENTIMETERS/. This is set using
4466
4467 <tscreen><verb>
4468 void gtk_ruler_set_metric( GtkRuler      *ruler,
4469                            GtkMetricType  metric );
4470 </verb></tscreen>
4471
4472 The default measure is <tt/GTK_PIXELS/.
4473
4474 <tscreen><verb>
4475     gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
4476 </verb></tscreen>
4477
4478 Other important characteristics of a ruler are how to mark the units
4479 of scale and where the position indicator is initially placed. These
4480 are set for a ruler using
4481
4482 <tscreen><verb>
4483 void gtk_ruler_set_range( GtkRuler *ruler,
4484                           gfloat    lower,
4485                           gfloat    upper,
4486                           gfloat    position,
4487                           gfloat    max_size );
4488 </verb></tscreen>
4489
4490 The lower and upper arguments define the extent of the ruler, and
4491 max_size is the largest possible number that will be displayed.
4492 Position defines the initial position of the pointer indicator within
4493 the ruler.
4494
4495 A vertical ruler can span an 800 pixel wide window thus
4496
4497 <tscreen><verb>
4498     gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
4499 </verb></tscreen>
4500
4501 The markings displayed on the ruler will be from 0 to 800, with a
4502 number for every 100 pixels. If instead we wanted the ruler to range
4503 from 7 to 16, we would code
4504
4505 <tscreen><verb>
4506     gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
4507 </verb></tscreen>
4508
4509 The indicator on the ruler is a small triangular mark that indicates
4510 the position of the pointer relative to the ruler. If the ruler is
4511 used to follow the mouse pointer, the motion_notify_event signal
4512 should be connected to the motion_notify_event method of the ruler.
4513 To follow all mouse movements within a window area, we would use
4514
4515 <tscreen><verb>
4516 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4517
4518     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4519            (GtkSignalFunc)EVENT_METHOD(ruler, motion_notify_event),
4520            GTK_OBJECT(ruler) );
4521 </verb></tscreen>
4522
4523 The following example creates a drawing area with a horizontal ruler
4524 above it and a vertical ruler to the left of it. The size of the
4525 drawing area is 600 pixels wide by 400 pixels high. The horizontal
4526 ruler spans from 7 to 13 with a mark every 100 pixels, while the
4527 vertical ruler spans from 0 to 400 with a mark every 100 pixels.
4528 Placement of the drawing area and the rulers is done using a table.
4529
4530 <tscreen><verb>
4531 /* example-start rulers rulers.c */
4532
4533 #include <gtk/gtk.h>
4534
4535 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4536
4537 #define XSIZE  600
4538 #define YSIZE  400
4539
4540 /* This routine gets control when the close button is clicked */
4541 gint close_application( GtkWidget *widget,
4542                         GdkEvent  *event,
4543                         gpointer   data )
4544 {
4545     gtk_main_quit();
4546     return(FALSE);
4547 }
4548
4549 /* The main routine */
4550 int main( int   argc,
4551           char *argv[] ) {
4552     GtkWidget *window, *table, *area, *hrule, *vrule;
4553
4554     /* Initialize GTK and create the main window */
4555     gtk_init( &amp;argc, &amp;argv );
4556
4557     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4558     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4559             GTK_SIGNAL_FUNC( close_application ), NULL);
4560     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
4561
4562     /* Create a table for placing the ruler and the drawing area */
4563     table = gtk_table_new( 3, 2, FALSE );
4564     gtk_container_add( GTK_CONTAINER(window), table );
4565
4566     area = gtk_drawing_area_new();
4567     gtk_drawing_area_size( (GtkDrawingArea *)area, XSIZE, YSIZE );
4568     gtk_table_attach( GTK_TABLE(table), area, 1, 2, 1, 2,
4569                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0 );
4570     gtk_widget_set_events( area, GDK_POINTER_MOTION_MASK |
4571                                  GDK_POINTER_MOTION_HINT_MASK );
4572
4573     /* The horizontal ruler goes on top. As the mouse moves across the
4574      * drawing area, a motion_notify_event is passed to the
4575      * appropriate event handler for the ruler. */
4576     hrule = gtk_hruler_new();
4577     gtk_ruler_set_metric( GTK_RULER(hrule), GTK_PIXELS );
4578     gtk_ruler_set_range( GTK_RULER(hrule), 7, 13, 0, 20 );
4579     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4580                                (GtkSignalFunc)EVENT_METHOD(hrule,
4581                                                         motion_notify_event),
4582                                GTK_OBJECT(hrule) );
4583     /*  GTK_WIDGET_CLASS(GTK_OBJECT(hrule)->klass)->motion_notify_event, */
4584     gtk_table_attach( GTK_TABLE(table), hrule, 1, 2, 0, 1,
4585                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0 );
4586     
4587     /* The vertical ruler goes on the left. As the mouse moves across
4588      * the drawing area, a motion_notify_event is passed to the
4589      * appropriate event handler for the ruler. */
4590     vrule = gtk_vruler_new();
4591     gtk_ruler_set_metric( GTK_RULER(vrule), GTK_PIXELS );
4592     gtk_ruler_set_range( GTK_RULER(vrule), 0, YSIZE, 10, YSIZE );
4593     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4594                                (GtkSignalFunc)
4595                                   GTK_WIDGET_CLASS(GTK_OBJECT(vrule)->klass)->
4596                                                          motion_notify_event,
4597                                GTK_OBJECT(vrule) );
4598     gtk_table_attach( GTK_TABLE(table), vrule, 0, 1, 1, 2,
4599                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );
4600
4601     /* Now show everything */
4602     gtk_widget_show( area );
4603     gtk_widget_show( hrule );
4604     gtk_widget_show( vrule );
4605     gtk_widget_show( table );
4606     gtk_widget_show( window );
4607     gtk_main();
4608
4609     return(0);
4610 }
4611 /* example-end */
4612 </verb></tscreen>
4613
4614 <!-- ----------------------------------------------------------------- -->
4615 <sect1>Statusbars
4616 <p>
4617 Statusbars are simple widgets used to display a text message. They
4618 keep a stack of the messages pushed onto them, so that popping the
4619 current message will re-display the previous text message.
4620
4621 In order to allow different parts of an application to use the same
4622 statusbar to display messages, the statusbar widget issues Context
4623 Identifiers which are used to identify different "users". The message
4624 on top of the stack is the one displayed, no matter what context it is
4625 in. Messages are stacked in last-in-first-out order, not context
4626 identifier order.
4627
4628 A statusbar is created with a call to:
4629
4630 <tscreen><verb>
4631 GtkWidget *gtk_statusbar_new( void );
4632 </verb></tscreen>
4633
4634 A new Context Identifier is requested using a call to the following 
4635 function with a short textual description of the context:
4636
4637 <tscreen><verb>
4638 guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
4639                                     const gchar  *context_description );
4640 </verb></tscreen>
4641
4642 There are three functions that can operate on statusbars:
4643
4644 <tscreen><verb>
4645 guint gtk_statusbar_push( GtkStatusbar *statusbar,
4646                           guint         context_id,
4647                           gchar        *text );
4648
4649 void gtk_statusbar_pop( GtkStatusbar *statusbar)
4650                         guint         context_id );
4651
4652 void gtk_statusbar_remove( GtkStatusbar *statusbar,
4653                            guint         context_id,
4654                            guint         message_id ); 
4655 </verb></tscreen>
4656
4657 The first, gtk_statusbar_push, is used to add a new message to the
4658 statusbar.  It returns a Message Identifier, which can be passed later
4659 to the function gtk_statusbar_remove to remove the message with the
4660 given Message and Context Identifiers from the statusbar's stack.
4661
4662 The function gtk_statusbar_pop removes the message highest in the
4663 stack with the given Context Identifier.
4664
4665 The following example creates a statusbar and two buttons, one for
4666 pushing items onto the statusbar, and one for popping the last item
4667 back off.
4668
4669 <tscreen><verb>
4670 /* example-start statusbar statusbar.c */
4671
4672 #include <gtk/gtk.h>
4673 #include <glib.h>
4674
4675 GtkWidget *status_bar;
4676
4677 void push_item( GtkWidget *widget,
4678                 gpointer   data )
4679 {
4680   static int count = 1;
4681   char buff[20];
4682
4683   g_snprintf(buff, 20, "Item %d", count++);
4684   gtk_statusbar_push( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data), buff);
4685
4686   return;
4687 }
4688
4689 void pop_item( GtkWidget *widget,
4690                gpointer   data )
4691 {
4692   gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) );
4693   return;
4694 }
4695
4696 int main( int   argc,
4697           char *argv[] )
4698 {
4699
4700     GtkWidget *window;
4701     GtkWidget *vbox;
4702     GtkWidget *button;
4703
4704     gint context_id;
4705
4706     gtk_init (&amp;argc, &amp;argv);
4707
4708     /* create a new window */
4709     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4710     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4711     gtk_window_set_title(GTK_WINDOW (window), "GTK Statusbar Example");
4712     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4713                        (GtkSignalFunc) gtk_exit, NULL);
4714  
4715     vbox = gtk_vbox_new(FALSE, 1);
4716     gtk_container_add(GTK_CONTAINER(window), vbox);
4717     gtk_widget_show(vbox);
4718           
4719     status_bar = gtk_statusbar_new();      
4720     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
4721     gtk_widget_show (status_bar);
4722
4723     context_id = gtk_statusbar_get_context_id(
4724                           GTK_STATUSBAR(status_bar), "Statusbar example");
4725
4726     button = gtk_button_new_with_label("push item");
4727     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4728         GTK_SIGNAL_FUNC (push_item), GINT_TO_POINTER(context_id) );
4729     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4730     gtk_widget_show(button);              
4731
4732     button = gtk_button_new_with_label("pop last item");
4733     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4734         GTK_SIGNAL_FUNC (pop_item), GINT_TO_POINTER(context_id) );
4735     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4736     gtk_widget_show(button);              
4737
4738     /* always display the window as the last step so it all splashes on
4739      * the screen at once. */
4740     gtk_widget_show(window);
4741
4742     gtk_main ();
4743
4744     return 0;
4745 }
4746 /* example-end */
4747 </verb></tscreen>
4748
4749 <!-- ----------------------------------------------------------------- -->
4750 <sect1>Text Entries
4751 <p>
4752 The Entry widget allows text to be typed and displayed in a single line
4753 text box. The text may be set with function calls that allow new text
4754 to replace, prepend or append the current contents of the Entry widget.
4755
4756 There are two functions for creating Entry widgets:
4757
4758 <tscreen><verb>
4759 GtkWidget *gtk_entry_new( void );
4760
4761 GtkWidget *gtk_entry_new_with_max_length( guint16 max );
4762 </verb></tscreen>
4763
4764 The first just creates a new Entry widget, whilst the second creates a
4765 new Entry and sets a limit on the length of the text within the Entry.
4766
4767 There are several functions for altering the text which is currently
4768 within the Entry widget.
4769
4770 <tscreen><verb>
4771 void gtk_entry_set_text( GtkEntry    *entry,
4772                          const gchar *text );
4773
4774 void gtk_entry_append_text( GtkEntry    *entry,
4775                             const gchar *text );
4776
4777 void gtk_entry_prepend_text( GtkEntry    *entry,
4778                              const gchar *text );
4779 </verb></tscreen>
4780
4781 The function gtk_entry_set_text sets the contents of the Entry widget,
4782 replacing the current contents. The functions gtk_entry_append_text
4783 and gtk_entry_prepend_text allow the current contents to be appended
4784 and prepended to.
4785
4786 The next function allows the current insertion point to be set.
4787
4788 <tscreen><verb>
4789 void gtk_entry_set_position( GtkEntry *entry,
4790                              gint      position );
4791 </verb></tscreen>
4792
4793 The contents of the Entry can be retrieved by using a call to the
4794 following function. This is useful in the callback functions described below.
4795
4796 <tscreen><verb>
4797 gchar *gtk_entry_get_text( GtkEntry *entry );
4798 </verb></tscreen>
4799
4800 The value returned by this function is used internally, and must not
4801 be freed using either free() or g_free()
4802
4803 If we don't want the contents of the Entry to be changed by someone typing
4804 into it, we can change its editable state.
4805
4806 <tscreen><verb>
4807 void gtk_entry_set_editable( GtkEntry *entry,
4808                              gboolean  editable );
4809 </verb></tscreen>
4810
4811 The function above allows us to toggle the editable state of the
4812 Entry widget by passing in a TRUE or FALSE value for the <tt/editable/
4813 argument.
4814
4815 If we are using the Entry where we don't want the text entered to be
4816 visible, for example when a password is being entered, we can use the
4817 following function, which also takes a boolean flag.
4818
4819 <tscreen><verb>
4820 void gtk_entry_set_visibility( GtkEntry *entry,
4821                                gboolean  visible );
4822 </verb></tscreen>
4823
4824 A region of the text may be set as selected by using the following
4825 function. This would most often be used after setting some default
4826 text in an Entry, making it easy for the user to remove it.
4827
4828 <tscreen><verb>
4829 void gtk_entry_select_region( GtkEntry *entry,
4830                               gint      start,
4831                               gint      end );
4832 </verb></tscreen>
4833
4834 If we want to catch when the user has entered text, we can connect to
4835 the <tt/activate/ or <tt/changed/ signal. Activate is raised when the
4836 user hits the enter key within the Entry widget. Changed is raised
4837 when the text changes at all, e.g., for every character entered or
4838 removed.
4839
4840 The following code is an example of using an Entry widget.
4841
4842 <tscreen><verb>
4843 /* example-start entry entry.c */
4844
4845 #include <gtk/gtk.h>
4846
4847 void enter_callback( GtkWidget *widget,
4848                      GtkWidget *entry )
4849 {
4850   gchar *entry_text;
4851   entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
4852   printf("Entry contents: %s\n", entry_text);
4853 }
4854
4855 void entry_toggle_editable( GtkWidget *checkbutton,
4856                             GtkWidget *entry )
4857 {
4858   gtk_entry_set_editable(GTK_ENTRY(entry),
4859                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4860 }
4861
4862 void entry_toggle_visibility( GtkWidget *checkbutton,
4863                               GtkWidget *entry )
4864 {
4865   gtk_entry_set_visibility(GTK_ENTRY(entry),
4866                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4867 }
4868
4869 int main( int   argc,
4870           char *argv[] )
4871 {
4872
4873     GtkWidget *window;
4874     GtkWidget *vbox, *hbox;
4875     GtkWidget *entry;
4876     GtkWidget *button;
4877     GtkWidget *check;
4878
4879     gtk_init (&amp;argc, &amp;argv);
4880
4881     /* create a new window */
4882     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4883     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4884     gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
4885     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4886                        (GtkSignalFunc) gtk_exit, NULL);
4887
4888     vbox = gtk_vbox_new (FALSE, 0);
4889     gtk_container_add (GTK_CONTAINER (window), vbox);
4890     gtk_widget_show (vbox);
4891
4892     entry = gtk_entry_new_with_max_length (50);
4893     gtk_signal_connect(GTK_OBJECT(entry), "activate",
4894                        GTK_SIGNAL_FUNC(enter_callback),
4895                        entry);
4896     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
4897     gtk_entry_append_text (GTK_ENTRY (entry), " world");
4898     gtk_entry_select_region (GTK_ENTRY (entry),
4899                              0, GTK_ENTRY(entry)->text_length);
4900     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4901     gtk_widget_show (entry);
4902
4903     hbox = gtk_hbox_new (FALSE, 0);
4904     gtk_container_add (GTK_CONTAINER (vbox), hbox);
4905     gtk_widget_show (hbox);
4906                                   
4907     check = gtk_check_button_new_with_label("Editable");
4908     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4909     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4910                         GTK_SIGNAL_FUNC(entry_toggle_editable), entry);
4911     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4912     gtk_widget_show (check);
4913     
4914     check = gtk_check_button_new_with_label("Visible");
4915     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4916     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4917                         GTK_SIGNAL_FUNC(entry_toggle_visibility), entry);
4918     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4919     gtk_widget_show (check);
4920                                    
4921     button = gtk_button_new_with_label ("Close");
4922     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4923                                GTK_SIGNAL_FUNC(gtk_exit),
4924                                GTK_OBJECT (window));
4925     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4926     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4927     gtk_widget_grab_default (button);
4928     gtk_widget_show (button);
4929     
4930     gtk_widget_show(window);
4931
4932     gtk_main();
4933     return(0);
4934 }
4935 /* example-end */
4936 </verb></tscreen>
4937
4938 <!-- ----------------------------------------------------------------- -->
4939 <sect1>Spin Buttons
4940 <p>
4941 The Spin Button widget is generally used to allow the user to select a
4942 value from a range of numeric values. It consists of a text
4943 entry box with up and down arrow buttons attached to the
4944 side. Selecting one of the buttons causes the value to "spin" up and
4945 down the range of possible values. The entry box may also be edited
4946 directly to enter a specific value.
4947
4948 The Spin Button allows the value to have zero or a number of decimal
4949 places and to be incremented/decremented in configurable steps. The
4950 action of holding down one of the buttons optionally results in an
4951 acceleration of change in the value according to how long it is
4952 depressed.
4953
4954 The Spin Button uses an <ref id="sec_Adjustment" name="Adjustment">
4955 object to hold information about the range of values that the spin
4956 button can take. This makes for a powerful Spin Button widget.
4957
4958 Recall that an adjustment widget is created with the following
4959 function, which illustrates the information that it holds:
4960
4961 <tscreen><verb>
4962 GtkObject *gtk_adjustment_new( gfloat value,
4963                                gfloat lower,
4964                                gfloat upper,
4965                                gfloat step_increment,
4966                                gfloat page_increment,
4967                                gfloat page_size );
4968 </verb></tscreen>
4969
4970 These attributes of an Adjustment are used by the Spin Button in the
4971 following way:
4972
4973 <itemize>
4974 <item> <tt/value/: initial value for the Spin Button
4975 <item> <tt/lower/: lower range value
4976 <item> <tt/upper/: upper range value
4977 <item> <tt/step_increment/: value to increment/decrement when pressing
4978 mouse button 1 on a button
4979 <item> <tt/page_increment/: value to increment/decrement when pressing
4980 mouse button 2 on a button
4981 <item> <tt/page_size/: unused
4982 </itemize>
4983
4984 Additionally, mouse button 3 can be used to jump directly to the
4985 <tt/upper/ or <tt/lower/ values when used to select one of the
4986 buttons. Lets look at how to create a Spin Button:
4987
4988 <tscreen><verb>
4989 GtkWidget *gtk_spin_button_new( GtkAdjustment *adjustment,
4990                                 gfloat         climb_rate,
4991                                 guint          digits );
4992 </verb></tscreen>
4993
4994 The <tt/climb_rate/ argument take a value between 0.0 and 1.0 and
4995 indicates the amount of acceleration that the Spin Button has. The
4996 <tt/digits/ argument specifies the number of decimal places to which
4997 the value will be displayed.
4998
4999 A Spin Button can be reconfigured after creation using the following
5000 function:
5001
5002 <tscreen><verb>
5003 void gtk_spin_button_configure( GtkSpinButton *spin_button,
5004                                 GtkAdjustment *adjustment,
5005                                 gfloat         climb_rate,
5006                                 guint          digits );
5007 </verb></tscreen>
5008
5009 The <tt/spin_button/ argument specifies the Spin Button widget that is
5010 to be reconfigured. The other arguments are as specified above.
5011
5012 The adjustment can be set and retrieved independantly using the
5013 following two functions:
5014
5015 <tscreen><verb>
5016 void gtk_spin_button_set_adjustment( GtkSpinButton  *spin_button,
5017                                      GtkAdjustment  *adjustment );
5018
5019 GtkAdjustment *gtk_spin_button_get_adjustment( GtkSpinButton *spin_button );
5020 </verb></tscreen>
5021
5022 The number of decimal places can also be altered using:
5023
5024 <tscreen><verb>
5025 void gtk_spin_button_set_digits( GtkSpinButton *spin_button,
5026                                  guint          digits) ;
5027 </verb></tscreen>
5028
5029 The value that a Spin Button is currently displaying can be changed
5030 using the following function:
5031
5032 <tscreen><verb>
5033 void gtk_spin_button_set_value( GtkSpinButton *spin_button,
5034                                 gfloat         value );
5035 </verb></tscreen>
5036
5037 The current value of a Spin Button can be retrieved as either a
5038 floating point or integer value with the following functions:
5039
5040 <tscreen><verb>
5041 gfloat gtk_spin_button_get_value_as_float( GtkSpinButton *spin_button );
5042
5043 gint gtk_spin_button_get_value_as_int( GtkSpinButton *spin_button );
5044 </verb></tscreen>
5045
5046 If you want to alter the value of a Spin Value relative to its current
5047 value, then the following function can be used:
5048
5049 <tscreen><verb>
5050 void gtk_spin_button_spin( GtkSpinButton *spin_button,
5051                            GtkSpinType    direction,
5052                            gfloat         increment );
5053 </verb></tscreen>
5054
5055 The <tt/direction/ parameter can take one of the following values:
5056
5057 <tscreen><verb>
5058   GTK_SPIN_STEP_FORWARD
5059   GTK_SPIN_STEP_BACKWARD
5060   GTK_SPIN_PAGE_FORWARD
5061   GTK_SPIN_PAGE_BACKWARD
5062   GTK_SPIN_HOME
5063   GTK_SPIN_END
5064   GTK_SPIN_USER_DEFINED
5065 </verb></tscreen>
5066
5067 This function packs in quite a bit of functionality, which I will
5068 attempt to clearly explain. Many of these settings use values from the
5069 Adjustment object that is associated with a Spin Button.
5070
5071 <tt/GTK_SPIN_STEP_FORWARD/ and <tt/GTK_SPIN_STEP_BACKWARD/ change the
5072 value of the Spin Button by the amount specified by <tt/increment/,
5073 unless <tt/increment/ is equal to 0, in which case the value is
5074 changed by the value of <tt/step_increment/ in theAdjustment.
5075
5076 <tt/GTK_SPIN_PAGE_FORWARD/ and <tt/GTK_SPIN_PAGE_BACKWARD/ simply
5077 alter the value of the Spin Button by <tt/increment/.
5078
5079 <tt/GTK_SPIN_HOME/ sets the value of the Spin Button to the bottom of
5080 the Adjustments range.
5081
5082 <tt/GTK_SPIN_END/ sets the value of the Spin Button to the top of the
5083 Adjustments range.
5084
5085 <tt/GTK_SPIN_USER_DEFINED/ simply alters the value of the Spin Button
5086 by the specified amount.
5087
5088 We move away from functions for setting and retreving the range attributes
5089 of the Spin Button now, and move onto functions that effect the
5090 appearance and behaviour of the Spin Button widget itself.
5091
5092 The first of these functions is used to constrain the text box of the
5093 Spin Button such that it may only contain a numeric value. This
5094 prevents a user from typing anything other than numeric values into
5095 the text box of a Spin Button:
5096
5097 <tscreen><verb>
5098 void gtk_spin_button_set_numeric( GtkSpinButton *spin_button,
5099                                   gboolean       numeric );
5100 </verb></tscreen>
5101
5102 You can set whether a Spin Button will wrap around between the upper
5103 and lower range values with the following function:
5104
5105 <tscreen><verb>
5106 void gtk_spin_button_set_wrap( GtkSpinButton *spin_button,
5107                                gboolean       wrap );
5108 </verb></tscreen>
5109
5110 You can set a Spin Button to round the value to the nearest
5111 <tt/step_increment/, which is set within the Adjustment object used
5112 with the Spin Button. This is accomplished with the following
5113 function:
5114
5115 <tscreen><verb>
5116 void gtk_spin_button_set_snap_to_ticks( GtkSpinButton  *spin_button,
5117                                         gboolean        snap_to_ticks );
5118 </verb></tscreen>
5119
5120 The update policy of a Spin Button can be changed with the following
5121 function:
5122
5123 <tscreen><verb>
5124 void gtk_spin_button_set_update_policy( GtkSpinButton  *spin_button,
5125                                     GtkSpinButtonUpdatePolicy policy );
5126 </verb></tscreen>
5127
5128 <!-- TODO: find out what this does - TRG -->
5129
5130 The possible values of <tt/policy/ are either <tt/GTK_UPDATE_ALWAYS/ or
5131 <tt/GTK_UPDATE_IF_VALID/.
5132
5133 These policies affect the behavior of a Spin Button when parsing
5134 inserted text and syncing its value with the values of the
5135 Adjustment.
5136
5137 In the case of <tt/GTK_UPDATE_IF_VALID/ the Spin Button only value
5138 gets changed if the text input is a numeric value that is within the
5139 range specified by the Adjustment. Otherwise the text is reset to the
5140 current value.
5141
5142 In case of <tt/GTK_UPDATE_ALWAYS/ we ignore errors while converting
5143 text into a numeric value.
5144
5145 The appearance of the buttons used in a Spin Button can be changed
5146 using the following function:
5147
5148 <tscreen><verb>
5149 void gtk_spin_button_set_shadow_type( GtkSpinButton *spin_button,
5150                                       GtkShadowType  shadow_type );
5151 </verb></tscreen>
5152
5153 As usual, the <tt/shadow_type/ can be one of:
5154
5155 <tscreen><verb>
5156   GTK_SHADOW_IN
5157   GTK_SHADOW_OUT
5158   GTK_SHADOW_ETCHED_IN
5159   GTK_SHADOW_ETCHED_OUT
5160 </verb></tscreen>
5161
5162 Finally, you can explicitly request that a Spin Button update itself:
5163
5164 <tscreen><verb>
5165 void gtk_spin_button_update( GtkSpinButton  *spin_button );
5166 </verb></tscreen>
5167
5168 It's example time again.
5169
5170 <tscreen><verb>
5171 /* example-start spinbutton spinbutton.c */
5172
5173 #include <gtk/gtk.h>
5174
5175 static GtkWidget *spinner1;
5176
5177 void toggle_snap( GtkWidget     *widget,
5178                   GtkSpinButton *spin )
5179 {
5180   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active);
5181 }
5182
5183 void toggle_numeric( GtkWidget *widget,
5184                      GtkSpinButton *spin )
5185 {
5186   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active);
5187 }
5188
5189 void change_digits( GtkWidget *widget,
5190                     GtkSpinButton *spin )
5191 {
5192   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
5193                               gtk_spin_button_get_value_as_int (spin));
5194 }
5195
5196 void get_value( GtkWidget *widget,
5197                 gpointer data )
5198 {
5199   gchar buf[32];
5200   GtkLabel *label;
5201   GtkSpinButton *spin;
5202
5203   spin = GTK_SPIN_BUTTON (spinner1);
5204   label = GTK_LABEL (gtk_object_get_user_data (GTK_OBJECT (widget)));
5205   if (GPOINTER_TO_INT (data) == 1)
5206     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
5207   else
5208     sprintf (buf, "%0.*f", spin->digits,
5209              gtk_spin_button_get_value_as_float (spin));
5210   gtk_label_set_text (label, buf);
5211 }
5212
5213
5214 int main( int   argc,
5215           char *argv[] )
5216 {
5217   GtkWidget *window;
5218   GtkWidget *frame;
5219   GtkWidget *hbox;
5220   GtkWidget *main_vbox;
5221   GtkWidget *vbox;
5222   GtkWidget *vbox2;
5223   GtkWidget *spinner2;
5224   GtkWidget *spinner;
5225   GtkWidget *button;
5226   GtkWidget *label;
5227   GtkWidget *val_label;
5228   GtkAdjustment *adj;
5229
5230   /* Initialise GTK */
5231   gtk_init(&amp;argc, &amp;argv);
5232
5233   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5234
5235   gtk_signal_connect (GTK_OBJECT (window), "destroy",
5236                       GTK_SIGNAL_FUNC (gtk_main_quit),
5237                       NULL);
5238
5239   gtk_window_set_title (GTK_WINDOW (window), "Spin Button");
5240
5241   main_vbox = gtk_vbox_new (FALSE, 5);
5242   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5243   gtk_container_add (GTK_CONTAINER (window), main_vbox);
5244   
5245   frame = gtk_frame_new ("Not accelerated");
5246   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5247   
5248   vbox = gtk_vbox_new (FALSE, 0);
5249   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5250   gtk_container_add (GTK_CONTAINER (frame), vbox);
5251   
5252   /* Day, month, year spinners */
5253   
5254   hbox = gtk_hbox_new (FALSE, 0);
5255   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5256   
5257   vbox2 = gtk_vbox_new (FALSE, 0);
5258   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5259   
5260   label = gtk_label_new ("Day :");
5261   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5262   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5263   
5264   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 31.0, 1.0,
5265                                               5.0, 0.0);
5266   spinner = gtk_spin_button_new (adj, 0, 0);
5267   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5268   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5269                                    GTK_SHADOW_OUT);
5270   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5271   
5272   vbox2 = gtk_vbox_new (FALSE, 0);
5273   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5274   
5275   label = gtk_label_new ("Month :");
5276   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5277   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5278   
5279   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5280                                               5.0, 0.0);
5281   spinner = gtk_spin_button_new (adj, 0, 0);
5282   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5283   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5284                                    GTK_SHADOW_ETCHED_IN);
5285   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5286   
5287   vbox2 = gtk_vbox_new (FALSE, 0);
5288   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5289   
5290   label = gtk_label_new ("Year :");
5291   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5292   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5293   
5294   adj = (GtkAdjustment *) gtk_adjustment_new (1998.0, 0.0, 2100.0,
5295                                               1.0, 100.0, 0.0);
5296   spinner = gtk_spin_button_new (adj, 0, 0);
5297   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), FALSE);
5298   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5299                                    GTK_SHADOW_IN);
5300   gtk_widget_set_usize (spinner, 55, 0);
5301   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5302   
5303   frame = gtk_frame_new ("Accelerated");
5304   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5305   
5306   vbox = gtk_vbox_new (FALSE, 0);
5307   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5308   gtk_container_add (GTK_CONTAINER (frame), vbox);
5309   
5310   hbox = gtk_hbox_new (FALSE, 0);
5311   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5312   
5313   vbox2 = gtk_vbox_new (FALSE, 0);
5314   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5315   
5316   label = gtk_label_new ("Value :");
5317   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5318   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5319   
5320   adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
5321                                               0.5, 100.0, 0.0);
5322   spinner1 = gtk_spin_button_new (adj, 1.0, 2);
5323   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
5324   gtk_widget_set_usize (spinner1, 100, 0);
5325   gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
5326   
5327   vbox2 = gtk_vbox_new (FALSE, 0);
5328   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5329   
5330   label = gtk_label_new ("Digits :");
5331   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5332   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5333   
5334   adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 5, 1, 1, 0);
5335   spinner2 = gtk_spin_button_new (adj, 0.0, 0);
5336   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner2), TRUE);
5337   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
5338                       GTK_SIGNAL_FUNC (change_digits),
5339                       (gpointer) spinner2);
5340   gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
5341   
5342   hbox = gtk_hbox_new (FALSE, 0);
5343   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5344   
5345   button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
5346   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5347                       GTK_SIGNAL_FUNC (toggle_snap),
5348                       spinner1);
5349   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5350   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5351   
5352   button = gtk_check_button_new_with_label ("Numeric only input mode");
5353   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5354                       GTK_SIGNAL_FUNC (toggle_numeric),
5355                       spinner1);
5356   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5357   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5358   
5359   val_label = gtk_label_new ("");
5360   
5361   hbox = gtk_hbox_new (FALSE, 0);
5362   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5363   button = gtk_button_new_with_label ("Value as Int");
5364   gtk_object_set_user_data (GTK_OBJECT (button), val_label);
5365   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5366                       GTK_SIGNAL_FUNC (get_value),
5367                       GINT_TO_POINTER (1));
5368   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5369   
5370   button = gtk_button_new_with_label ("Value as Float");
5371   gtk_object_set_user_data (GTK_OBJECT (button), val_label);
5372   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5373                       GTK_SIGNAL_FUNC (get_value),
5374                       GINT_TO_POINTER (2));
5375   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5376   
5377   gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
5378   gtk_label_set_text (GTK_LABEL (val_label), "0");
5379   
5380   hbox = gtk_hbox_new (FALSE, 0);
5381   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5382   
5383   button = gtk_button_new_with_label ("Close");
5384   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
5385                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
5386                              GTK_OBJECT (window));
5387   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5388
5389   gtk_widget_show_all (window);
5390
5391   /* Enter the event loop */
5392   gtk_main ();
5393     
5394   return(0);
5395 }
5396 /* example-end */
5397 </verb></tscreen>
5398
5399 <!-- ----------------------------------------------------------------- -->
5400 <sect1>Combo Box
5401 <p>
5402 The combo box is another fairly simple widget that is really just a
5403 collection of other widgets. From the user's point of view, the widget
5404 consists of a text entry box and a pull down menu from which the user
5405 can select one of a set of predefined entries. Alternatively, the user
5406 can type a different option directly into the text box.
5407
5408 The following extract from the structure that defines a Combo Box
5409 identifies several of the components:
5410
5411 <tscreen><verb>
5412 struct _GtkCombo { 
5413         GtkHBox hbox; 
5414         GtkWidget *entry; 
5415         GtkWidget *button;
5416         GtkWidget *popup; 
5417         GtkWidget *popwin; 
5418         GtkWidget *list;
5419         ...  };
5420 </verb></tscreen>
5421
5422 As you can see, the Combo Box has two principal parts that you really
5423 care about: an entry and a list.
5424
5425 First off, to create a combo box, use:
5426
5427 <tscreen><verb>
5428 GtkWidget *gtk_combo_new( void );
5429 </verb></tscreen>
5430
5431 Now, if you want to set the string in the entry section of the combo
5432 box, this is done by manipulating the <tt/entry/ widget directly:
5433
5434 <tscreen><verb>
5435     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), "My String.");
5436 </verb></tscreen>
5437
5438 To set the values in the popdown list, one uses the function:
5439
5440 <tscreen><verb>
5441 void gtk_combo_set_popdown_strings( GtkCombo *combo,
5442                                     GList    *strings );
5443 </verb></tscreen>
5444
5445 Before you can do this, you have to assemble a GList of the strings
5446 that you want. GList is a linked list implementation that is part of
5447 <ref id="sec_glib" name="GLib">, a library supporing GTK. For the
5448 moment, the quick and dirty explanation is that you need to set up a
5449 GList pointer, set it equal to NULL, then append strings to it with
5450
5451 <tscreen><verb>
5452 GList *g_list_append( GList *glist, 
5453                       gpointer data );
5454 </verb></tscreen>
5455
5456 It is important that you set the initial GList pointer to NULL. The
5457 value returned from the g_list_append function must be used as the new
5458 pointer to the GList.
5459
5460 Here's a typical code segment for creating a set of options:
5461
5462 <tscreen><verb>
5463     GList *glist=NULL;
5464
5465     glist = g_list_append(glist, "String 1");
5466     glist = g_list_append(glist, "String 2");
5467     glist = g_list_append(glist, "String 3"); 
5468     glist = g_list_append(glist, "String 4");
5469
5470     gtk_combo_set_popdown_strings( GTK_COMBO(combo), glist) ;
5471 </verb></tscreen>
5472
5473 The combo widget makes a copy of the strings passed to it in the glist
5474 structure. As a result, you need to make sure you free the memory used
5475 by the list if that is appropriate for your application.
5476
5477 At this point you have a working combo box that has been set up.
5478 There are a few aspects of its behavior that you can change. These
5479 are accomplished with the functions: 
5480
5481 <tscreen><verb>
5482 void gtk_combo_set_use_arrows( GtkCombo *combo,
5483                                gint      val );
5484
5485 void gtk_combo_set_use_arrows_always( GtkCombo *combo,
5486                                       gint      val );
5487
5488 void gtk_combo_set_case_sensitive( GtkCombo *combo,
5489                                    gint      val );
5490 </verb></tscreen>
5491
5492 <tt/gtk_combo_set_use_arrows()/ lets the user change the value in the
5493 entry using the up/down arrow keys. This doesn't bring up the list, but
5494 rather replaces the current text in the entry with the next list entry
5495 (up or down, as your key choice indicates). It does this by searching
5496 in the list for the item corresponding to the current value in the
5497 entry and selecting the previous/next item accordingly. Usually in an
5498 entry the arrow keys are used to change focus (you can do that anyway
5499 using TAB). Note that when the current item is the last of the list
5500 and you press arrow-down it changes the focus (the same applies with
5501 the first item and arrow-up).
5502
5503 If the current value in the entry is not in the list, then the
5504 function of <tt/gtk_combo_set_use_arrows()/ is disabled.
5505
5506 <tt/gtk_combo_set_use_arrows_always()/ similarly allows the use the
5507 the up/down arrow keys to cycle through the choices in the dropdown
5508 list, except that it wraps around the values in the list, completely
5509 disabling the use of the up and down arrow keys for changing focus.
5510
5511 <tt/gtk_combo_set_case_sensitive()/ toggles whether or not GTK
5512 searches for entries in a case sensitive manner. This is used when the
5513 Combo widget is asked to find a value from the list using the current
5514 entry in the text box. This completion can be performed in either a
5515 case sensitive or insensitive manner, depending upon the use of this
5516 function. The Combo widget can also simply complete the current entry
5517 if the user presses the key combination MOD-1 and "Tab". MOD-1 is
5518 often mapped to the "Alt" key, by the <tt/xmodmap/ utility. Note,
5519 however that some window managers also use this key combination, which
5520 will override its use within GTK.
5521
5522 Now that we have a combo box, tailored to look and act how we want it,
5523 all that remains is being able to get data from the combo box. This is
5524 relatively straightforward. The majority of the time, all you are
5525 going to care about getting data from is the entry. The entry is
5526 accessed simply by <tt>GTK_ENTRY(GTK_COMBO(combo)->entry)</tt>. The
5527 two principal things that you are going to want to do with it are
5528 attach to the activate signal, which indicates that the user has
5529 pressed the Return or Enter key, and read the text. The first is
5530 accomplished using something like:
5531
5532 <tscreen><verb>
5533     gtk_signal_connect(GTK_OBJECT(GTK_COMB(combo)->entry), "activate",
5534                        GTK_SIGNAL_FUNC (my_callback_function), my_data);
5535 </verb></tscreen>
5536
5537 Getting the text at any arbitrary time is accomplished by simply using
5538 the entry function:
5539
5540 <tscreen><verb>
5541 gchar *gtk_entry_get_text(GtkEntry *entry);
5542 </verb></tscreen>
5543
5544 Such as:
5545
5546 <tscreen><verb>
5547     char *string;
5548
5549     string = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry));
5550 </verb></tscreen>
5551
5552 That's about all there is to it. There is a function
5553
5554 <tscreen><verb>
5555 void gtk_combo_disable_activate(GtkCombo *combo);
5556 </verb></tscreen>
5557
5558 that will disable the activate signal on the entry widget in the combo
5559 box. Personally, I can't think of why you'd want to use it, but it
5560 does exist.
5561
5562 <!-- There is also a function to set the string on a particular item, void
5563 gtk_combo_set_item_string(GtkCombo *combo, GtkItem *item, const gchar
5564 *item_value), but this requires that you have a pointer to the
5565 appropriate Item. Frankly, I have no idea how to do that.
5566 -->
5567
5568 <!-- ----------------------------------------------------------------- -->
5569 <sect1> Color Selection
5570 <p>
5571 The color selection widget is, not surprisingly, a widget for
5572 interactive selection of colors. This composite widget lets the user
5573 select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
5574 Saturation, Value) triples.  This is done either by adjusting single
5575 values with sliders or entries, or by picking the desired color from a
5576 hue-saturation wheel/value bar.  Optionally, the opacity of the color
5577 can also be set.
5578
5579 The color selection widget currently emits only one signal,
5580 "color_changed", which is emitted whenever the current color in the
5581 widget changes, either when the user changes it or if it's set
5582 explicitly through gtk_color_selection_set_color().
5583
5584 Lets have a look at what the color selection widget has to offer
5585 us. The widget comes in two flavours: gtk_color_selection and
5586 gtk_color_selection_dialog.
5587
5588 <tscreen><verb>
5589 GtkWidget *gtk_color_selection_new( void );
5590 </verb></tscreen>
5591         
5592 You'll probably not be using this constructor directly. It creates an
5593 orphan ColorSelection widget which you'll have to parent
5594 yourself. The ColorSelection widget inherits from the VBox
5595 widget.
5596
5597 <tscreen><verb> 
5598 GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
5599 </verb></tscreen>
5600
5601 This is the most common color selection constructor. It creates a
5602 ColorSelectionDialog. It consists of a Frame containing a
5603 ColorSelection widget, an HSeparator and an HBox with three buttons,
5604 "Ok", "Cancel" and "Help". You can reach these buttons by accessing
5605 the "ok_button", "cancel_button" and "help_button" widgets in the
5606 ColorSelectionDialog structure,
5607 (i.e., <tt>GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button</tt>)).
5608
5609 <tscreen><verb>
5610 void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel, 
5611                                             GtkUpdateType      policy );
5612 </verb></tscreen>
5613
5614 This function sets the update policy. The default policy is
5615 <tt/GTK_UPDATE_CONTINUOUS/ which means that the current color is
5616 updated continuously when the user drags the sliders or presses the
5617 mouse and drags in the hue-saturation wheel or value bar. If you
5618 experience performance problems, you may want to set the policy to
5619 <tt/GTK_UPDATE_DISCONTINUOUS/ or <tt/GTK_UPDATE_DELAYED/.
5620
5621 <tscreen><verb>
5622 void gtk_color_selection_set_opacity( GtkColorSelection *colorsel,
5623                                       gint               use_opacity );
5624 </verb></tscreen>
5625
5626 The color selection widget supports adjusting the opacity of a color
5627 (also known as the alpha channel). This is disabled by
5628 default. Calling this function with use_opacity set to TRUE enables
5629 opacity. Likewise, use_opacity set to FALSE will disable opacity.
5630
5631 <tscreen><verb>
5632 void gtk_color_selection_set_color( GtkColorSelection *colorsel,
5633                                     gdouble           *color );
5634 </verb></tscreen>
5635
5636 You can set the current color explicitly by calling this function with
5637 a pointer to an array of colors (gdouble). The length of the array
5638 depends on whether opacity is enabled or not. Position 0 contains the
5639 red component, 1 is green, 2 is blue and opacity is at position 3
5640 (only if opacity is enabled, see
5641 gtk_color_selection_set_opacity()). All values are between 0.0 and
5642 1.0.
5643
5644 <tscreen><verb>
5645 void gtk_color_selection_get_color( GtkColorSelection *colorsel,
5646                                     gdouble           *color );
5647 </verb></tscreen>
5648
5649 When you need to query the current color, typically when you've
5650 received a "color_changed" signal, you use this function. Color is a
5651 pointer to the array of colors to fill in. See the
5652 gtk_color_selection_set_color() function for the description of this
5653 array.
5654
5655 <!-- Need to do a whole section on DnD - TRG
5656 Drag and drop
5657 -------------
5658
5659 The color sample areas (right under the hue-saturation wheel) supports
5660 drag and drop. The type of drag and drop is "application/x-color". The
5661 message data consists of an array of 4 (or 5 if opacity is enabled)
5662 gdouble values, where the value at position 0 is 0.0 (opacity on) or
5663 1.0 (opacity off) followed by the red, green and blue values at
5664 positions 1,2 and 3 respectively.  If opacity is enabled, the opacity
5665 is passed in the value at position 4.
5666 -->
5667
5668 Here's a simple example demonstrating the use of the
5669 ColorSelectionDialog. The program displays a window containing a
5670 drawing area. Clicking on it opens a color selection dialog, and
5671 changing the color in the color selection dialog changes the
5672 background color.
5673
5674 <tscreen><verb>
5675 /* example-start colorsel colorsel.c */
5676
5677 #include <glib.h>
5678 #include <gdk/gdk.h>
5679 #include <gtk/gtk.h>
5680
5681 GtkWidget *colorseldlg = NULL;
5682 GtkWidget *drawingarea = NULL;
5683
5684 /* Color changed handler */
5685
5686 void color_changed_cb( GtkWidget         *widget,
5687                        GtkColorSelection *colorsel )
5688 {
5689   gdouble color[3];
5690   GdkColor gdk_color;
5691   GdkColormap *colormap;
5692
5693   /* Get drawingarea colormap */
5694
5695   colormap = gdk_window_get_colormap (drawingarea->window);
5696
5697   /* Get current color */
5698
5699   gtk_color_selection_get_color (colorsel,color);
5700
5701   /* Fit to a unsigned 16 bit integer (0..65535) and
5702    * insert into the GdkColor structure */
5703
5704   gdk_color.red = (guint16)(color[0]*65535.0);
5705   gdk_color.green = (guint16)(color[1]*65535.0);
5706   gdk_color.blue = (guint16)(color[2]*65535.0);
5707
5708   /* Allocate color */
5709
5710   gdk_color_alloc (colormap, &amp;gdk_color);
5711
5712   /* Set window background color */
5713
5714   gdk_window_set_background (drawingarea->window, &amp;gdk_color);
5715
5716   /* Clear window */
5717
5718   gdk_window_clear (drawingarea->window);
5719 }
5720
5721 /* Drawingarea event handler */
5722
5723 gint area_event( GtkWidget *widget,
5724                  GdkEvent  *event,
5725                  gpointer   client_data )
5726 {
5727   gint handled = FALSE;
5728   GtkWidget *colorsel;
5729
5730   /* Check if we've received a button pressed event */
5731
5732   if (event->type == GDK_BUTTON_PRESS &amp;&amp; colorseldlg == NULL)
5733     {
5734       /* Yes, we have an event and there's no colorseldlg yet! */
5735
5736       handled = TRUE;
5737
5738       /* Create color selection dialog */
5739
5740       colorseldlg = gtk_color_selection_dialog_new("Select background color");
5741
5742       /* Get the ColorSelection widget */
5743
5744       colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;
5745
5746       /* Connect to the "color_changed" signal, set the client-data
5747        * to the colorsel widget */
5748
5749       gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed",
5750         (GtkSignalFunc)color_changed_cb, (gpointer)colorsel);
5751
5752       /* Show the dialog */
5753
5754       gtk_widget_show(colorseldlg);
5755     }
5756
5757   return handled;
5758 }
5759
5760 /* Close down and exit handler */
5761
5762 gint destroy_window( GtkWidget *widget,
5763                      GdkEvent  *event,
5764                      gpointer   client_data )
5765 {
5766   gtk_main_quit ();
5767   return(TRUE);
5768 }
5769
5770 /* Main */
5771
5772 gint main( gint   argc,
5773            gchar *argv[] )
5774 {
5775   GtkWidget *window;
5776
5777   /* Initialize the toolkit, remove gtk-related commandline stuff */
5778
5779   gtk_init (&amp;argc,&amp;argv);
5780
5781   /* Create toplevel window, set title and policies */
5782
5783   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5784   gtk_window_set_title (GTK_WINDOW(window), "Color selection test");
5785   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, TRUE);
5786
5787   /* Attach to the "delete" and "destroy" events so we can exit */
5788
5789   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
5790     (GtkSignalFunc)destroy_window, (gpointer)window);
5791   
5792   /* Create drawingarea, set size and catch button events */
5793
5794   drawingarea = gtk_drawing_area_new ();
5795
5796   gtk_drawing_area_size (GTK_DRAWING_AREA(drawingarea), 200, 200);
5797
5798   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
5799
5800   gtk_signal_connect (GTK_OBJECT(drawingarea), "event", 
5801     (GtkSignalFunc)area_event, (gpointer)drawingarea);
5802   
5803   /* Add drawingarea to window, then show them both */
5804
5805   gtk_container_add (GTK_CONTAINER(window), drawingarea);
5806
5807   gtk_widget_show (drawingarea);
5808   gtk_widget_show (window);
5809   
5810   /* Enter the gtk main loop (this never returns) */
5811
5812   gtk_main ();
5813
5814   /* Satisfy grumpy compilers */
5815
5816   return(0);
5817 }
5818 /* example-end */
5819 </verb></tscreen>
5820
5821 <!-- ----------------------------------------------------------------- -->
5822 <sect1> File Selections
5823 <p>
5824 The file selection widget is a quick and simple way to display a File
5825 dialog box. It comes complete with Ok, Cancel, and Help buttons, a
5826 great way to cut down on programming time.
5827
5828 To create a new file selection box use:
5829
5830 <tscreen><verb>
5831 GtkWidget *gtk_file_selection_new( gchar *title );
5832 </verb></tscreen>
5833
5834 To set the filename, for example to bring up a specific directory, or
5835 give a default filename, use this function:
5836
5837 <tscreen><verb>
5838 void gtk_file_selection_set_filename( GtkFileSelection *filesel,
5839                                       gchar            *filename );
5840 </verb></tscreen>
5841
5842 To grab the text that the user has entered or clicked on, use this 
5843 function:
5844
5845 <tscreen><verb>
5846 gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel );
5847 </verb></tscreen>
5848
5849 There are also pointers to the widgets contained within the file 
5850 selection widget. These are:
5851
5852 <tscreen><verb>
5853   dir_list
5854   file_list
5855   selection_entry
5856   selection_text
5857   main_vbox
5858   ok_button
5859   cancel_button
5860   help_button
5861 </verb></tscreen>
5862  
5863 Most likely you will want to use the ok_button, cancel_button, and
5864 help_button pointers in signaling their use.
5865
5866 Included here is an example stolen from testgtk.c, modified to run on
5867 its own. As you will see, there is nothing much to creating a file
5868 selection widget. While in this example the Help button appears on the
5869 screen, it does nothing as there is not a signal attached to it.
5870
5871 <tscreen><verb>
5872 /* example-start filesel filesel.c */
5873
5874 #include <gtk/gtk.h>
5875
5876 /* Get the selected filename and print it to the console */
5877 void file_ok_sel( GtkWidget        *w,
5878                   GtkFileSelection *fs )
5879 {
5880     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
5881 }
5882
5883 void destroy( GtkWidget *widget,
5884               gpointer   data )
5885 {
5886     gtk_main_quit ();
5887 }
5888
5889 int main( int   argc,
5890           char *argv[] )
5891 {
5892     GtkWidget *filew;
5893     
5894     gtk_init (&amp;argc, &amp;argv);
5895     
5896     /* Create a new file selection widget */
5897     filew = gtk_file_selection_new ("File selection");
5898     
5899     gtk_signal_connect (GTK_OBJECT (filew), "destroy",
5900                         (GtkSignalFunc) destroy, &amp;filew);
5901     /* Connect the ok_button to file_ok_sel function */
5902     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
5903                         "clicked", (GtkSignalFunc) file_ok_sel, filew );
5904     
5905     /* Connect the cancel_button to destroy the widget */
5906     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
5907                                             (filew)->cancel_button),
5908                                "clicked", (GtkSignalFunc) gtk_widget_destroy,
5909                                GTK_OBJECT (filew));
5910     
5911     /* Lets set the filename, as if this were a save dialog, and we are giving
5912      a default filename */
5913     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
5914                                      "penguin.png");
5915     
5916     gtk_widget_show(filew);
5917     gtk_main ();
5918     return 0;
5919 }
5920 /* example-end */
5921 </verb></tscreen>
5922
5923 <!-- ***************************************************************** -->
5924 <sect> Container Widgets
5925 <!-- ***************************************************************** -->
5926
5927 <!-- ----------------------------------------------------------------- -->   
5928 <sect1>The EventBox <label id="sec_EventBox">
5929 <p> 
5930 Some GTK widgets don't have associated X windows, so they just draw on
5931 their parents. Because of this, they cannot receive events and if they
5932 are incorrectly sized, they don't clip so you can get messy
5933 overwriting, etc. If you require more from these widgets, the EventBox
5934 is for you.
5935
5936 At first glance, the EventBox widget might appear to be totally
5937 useless. It draws nothing on the screen and responds to no
5938 events. However, it does serve a function - it provides an X window
5939 for its child widget. This is important as many GTK widgets do not
5940 have an associated X window. Not having an X window saves memory and
5941 improves performance, but also has some drawbacks. A widget without an
5942 X window cannot receive events, and does not perform any clipping on
5943 its contents. Although the name <em/EventBox/ emphasizes the
5944 event-handling function, the widget can also be used for clipping.
5945 (and more, see the example below).
5946
5947 To create a new EventBox widget, use:
5948
5949 <tscreen><verb>
5950 GtkWidget *gtk_event_box_new( void );
5951 </verb></tscreen>
5952
5953 A child widget can then be added to this EventBox:
5954
5955 <tscreen><verb>
5956     gtk_container_add( GTK_CONTAINER(event_box), child_widget );
5957 </verb></tscreen>
5958
5959 The following example demonstrates both uses of an EventBox - a label
5960 is created that is clipped to a small box, and set up so that a
5961 mouse-click on the label causes the program to exit. Resizing the
5962 window reveals varying amounts of the label.
5963
5964 <tscreen><verb>
5965 /* example-start eventbox eventbox.c */
5966
5967 #include <gtk/gtk.h>
5968
5969 int main( int argc,
5970           char *argv[] )
5971 {
5972     GtkWidget *window;
5973     GtkWidget *event_box;
5974     GtkWidget *label;
5975     
5976     gtk_init (&amp;argc, &amp;argv);
5977     
5978     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5979     
5980     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
5981     
5982     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5983                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
5984     
5985     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
5986     
5987     /* Create an EventBox and add it to our toplevel window */
5988     
5989     event_box = gtk_event_box_new ();
5990     gtk_container_add (GTK_CONTAINER(window), event_box);
5991     gtk_widget_show (event_box);
5992     
5993     /* Create a long label */
5994     
5995     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
5996     gtk_container_add (GTK_CONTAINER (event_box), label);
5997     gtk_widget_show (label);
5998     
5999     /* Clip it short. */
6000     gtk_widget_set_usize (label, 110, 20);
6001     
6002     /* And bind an action to it */
6003     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
6004     gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
6005                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
6006     
6007     /* Yet one more thing you need an X window for ... */
6008     
6009     gtk_widget_realize (event_box);
6010     gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
6011     
6012     gtk_widget_show (window);
6013     
6014     gtk_main ();
6015     
6016     return(0);
6017 }
6018 /* example-end */
6019 </verb></tscreen>
6020
6021 <!-- ----------------------------------------------------------------- -->   
6022 <sect1>The Alignment widget <label id="sec_Alignment">
6023 <p>
6024 The alignment widget allows you to place a widget within its window at
6025 a position and size relative to the size of the Alignment widget
6026 itself. For example, it can be very useful for centering a widget
6027 within the window.
6028
6029 There are only two functions associated with the Alignment widget:
6030
6031 <tscreen><verb>
6032 GtkWidget* gtk_alignment_new( gfloat xalign,
6033                               gfloat yalign,
6034                               gfloat xscale,
6035                               gfloat yscale );
6036
6037 void gtk_alignment_set( GtkAlignment *alignment,
6038                         gfloat        xalign,
6039                         gfloat        yalign,
6040                         gfloat        xscale,
6041                         gfloat        yscale );
6042 </verb></tscreen>
6043
6044 The first function creates a new Alignment widget with the specified
6045 parameters. The second function allows the alignment paramters of an
6046 exisiting Alignment widget to be altered.
6047
6048 All four alignment parameters are floating point numbers which can
6049 range from 0.0 to 1.0. The <tt/xalign/ and <tt/yalign/ arguments
6050 affect the position of the widget placed within the Alignment
6051 widget. The <tt/xscale/ and <tt/yscale/ arguments effect the amount of
6052 space allocated to the widget.
6053
6054 A child widget can be added to this Alignment widget using:
6055
6056 <tscreen><verb>
6057     gtk_container_add( GTK_CONTAINER(alignment), child_widget );
6058 </verb></tscreen>
6059
6060 For an example of using an Alignment widget, refer to the example for
6061 the <ref id="sec_ProgressBar" name="Progress Bar"> widget.
6062
6063 <!-- ----------------------------------------------------------------- -->
6064 <sect1> Fixed Container
6065 <p>
6066 The Fixed container allows you to place widgets at a fixed position
6067 within it's window, relative to it's upper left hand corner. The
6068 position of the widgets can be changed dynamically.
6069
6070 There are only three functions associated with the fixed widget:
6071
6072 <tscreen><verb>
6073 GtkWidget* gtk_fixed_new( void );
6074
6075 void gtk_fixed_put( GtkFixed  *fixed,
6076                     GtkWidget *widget,
6077                     gint16     x,
6078                     gint16     y );
6079
6080 void gtk_fixed_move( GtkFixed  *fixed,
6081                      GtkWidget *widget,
6082                      gint16     x,
6083                      gint16     y );
6084 </verb></tscreen>
6085
6086 The function <tt/gtk_fixed_new/ allows you to create a new Fixed
6087 container.
6088
6089 <tt/gtk_fixed_put/ places <tt/widget/ in the container <tt/fixed/ at
6090 the position specified by <tt/x/ and <tt/y/.
6091
6092 <tt/gtk_fixed_move/ allows the specified widget to be moved to a new
6093 position.
6094
6095 The following example illustrates how to use the Fixed Container.
6096
6097 <tscreen><verb>
6098 /* example-start fixed fixed.c */
6099
6100 #include <gtk/gtk.h>
6101
6102 /* I'm going to be lazy and use some global variables to
6103  * store the position of the widget within the fixed
6104  * container */
6105 gint x=50;
6106 gint y=50;
6107
6108 /* This callback function moves the button to a new position
6109  * in the Fixed container. */
6110 void move_button( GtkWidget *widget,
6111                   GtkWidget *fixed )
6112 {
6113   x = (x+30)%300;
6114   y = (y+50)%300;
6115   gtk_fixed_move( GTK_FIXED(fixed), widget, x, y); 
6116 }
6117
6118 int main( int   argc,
6119           char *argv[] )
6120 {
6121   /* GtkWidget is the storage type for widgets */
6122   GtkWidget *window;
6123   GtkWidget *fixed;
6124   GtkWidget *button;
6125   gint i;
6126
6127   /* Initialise GTK */
6128   gtk_init(&amp;argc, &amp;argv);
6129     
6130   /* Create a new window */
6131   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6132   gtk_window_set_title(GTK_WINDOW(window), "Fixed Container");
6133
6134   /* Here we connect the "destroy" event to a signal handler */ 
6135   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6136                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6137  
6138   /* Sets the border width of the window. */
6139   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6140
6141   /* Create a Fixed Container */
6142   fixed = gtk_fixed_new();
6143   gtk_container_add(GTK_CONTAINER(window), fixed);
6144   gtk_widget_show(fixed);
6145   
6146   for (i = 1 ; i <= 3 ; i++) {
6147     /* Creates a new button with the label "Press me" */
6148     button = gtk_button_new_with_label ("Press me");
6149   
6150     /* When the button receives the "clicked" signal, it will call the
6151      * function move_button() passing it the Fixed Container as its
6152      * argument. */
6153     gtk_signal_connect (GTK_OBJECT (button), "clicked",
6154                         GTK_SIGNAL_FUNC (move_button), fixed);
6155   
6156     /* This packs the button into the fixed containers window. */
6157     gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
6158   
6159     /* The final step is to display this newly created widget. */
6160     gtk_widget_show (button);
6161   }
6162
6163   /* Display the window */
6164   gtk_widget_show (window);
6165     
6166   /* Enter the event loop */
6167   gtk_main ();
6168     
6169   return(0);
6170 }
6171 /* example-end */
6172 </verb></tscreen>
6173
6174 <!-- ----------------------------------------------------------------- -->
6175 <sect1> Layout Container
6176 <p>
6177 The Layout container is similar to the Fixed container except that it
6178 implements an infinite (where infinity is less than 2^32) scrolling
6179 area. The X window system has a limitation where windows can be at
6180 most 32767 pixels wide or tall. The Layout container gets around this
6181 limitation by doing some exotic stuff using window and bit gravities,
6182 so that you can have smooth scrolling even when you have many child
6183 widgets in your scrolling area.
6184
6185 A Layout container is created using:
6186
6187 <tscreen><verb>
6188 GtkWidget *gtk_layout_new( GtkAdjustment *hadjustment,
6189                            GtkAdjustment *vadjustment );
6190 </verb></tscreen>
6191
6192 As you can see, you can optionally specify the Adjustment objects that
6193 the Layout widget will use for its scrolling.
6194
6195 You can add and move widgets in the Layout container using the
6196 following two functions:
6197
6198 <tscreen><verb>
6199 void gtk_layout_put( GtkLayout *layout,
6200                      GtkWidget *widget,
6201                      gint       x,
6202                      gint       y );
6203
6204 void gtk_layout_move( GtkLayout *layout,
6205                       GtkWidget *widget,
6206                       gint       x,
6207                       gint       y );
6208 </verb></tscreen>
6209
6210 The size of the Layout container can be set using the next function:
6211
6212 <tscreen><verb>
6213 void gtk_layout_set_size( GtkLayout *layout,
6214                           guint      width,
6215                           guint      height );
6216 </verb></tscreen>
6217
6218 Layout containers are one of the very few widgets in the GTK widget
6219 set that actively repaint themselves on screen as they are changed
6220 using the above functions (the vast majority of widgets queue
6221 requests which are then processed when control returns to the
6222 <tt/gtk_main()/ function).
6223
6224 When you want to make a large number of changes to a Layout container,
6225 you can use the following two functions to disable and re-enable this
6226 repainting functionality:
6227
6228 <tscreen><verb>
6229 void gtk_layout_freeze( GtkLayout *layout );
6230
6231 void gtk_layout_thaw( GtkLayout *layout );
6232 </verb></tscreen>
6233
6234 The final four functions for use with Layout widgets are for
6235 manipulating the horizontal and vertical adjustment widgets:
6236
6237 <tscreen><verb>
6238 GtkAdjustment* gtk_layout_get_hadjustment( GtkLayout *layout );
6239
6240 GtkAdjustment* gtk_layout_get_vadjustment( GtkLayout *layout );
6241
6242 void gtk_layout_set_hadjustment( GtkLayout     *layout,
6243                                  GtkAdjustment *adjustment );
6244
6245 void gtk_layout_set_vadjustment( GtkLayout     *layout,
6246                                  GtkAdjustment *adjustment);
6247 </verb></tscreen>
6248
6249 <!-- ----------------------------------------------------------------- -->
6250 <sect1> Frames <label id="sec_Frames">
6251 <p>
6252 Frames can be used to enclose one or a group of widgets with a box
6253 which can optionally be labelled. The position of the label and the
6254 style of the box can be altered to suit.
6255
6256 A Frame can be created with the following function:
6257
6258 <tscreen><verb>
6259 GtkWidget *gtk_frame_new( const gchar *label );
6260 </verb></tscreen>
6261
6262 The label is by default placed in the upper left hand corner of the
6263 frame. A value of NULL for the <tt/label/ argument will result in no
6264 label being displayed. The text of the label can be changed using the
6265 next function.
6266
6267 <tscreen><verb>
6268 void gtk_frame_set_label( GtkFrame    *frame,
6269                           const gchar *label );
6270 </verb></tscreen>
6271
6272 The position of the label can be changed using this function:
6273
6274 <tscreen><verb>
6275 void gtk_frame_set_label_align( GtkFrame *frame,
6276                                 gfloat    xalign,
6277                                 gfloat    yalign );
6278 </verb></tscreen>
6279
6280 <tt/xalign/ and <tt/yalign/ take values between 0.0 and 1.0. <tt/xalign/
6281 indicates the position of the label along the top horizontal of the
6282 frame. <tt/yalign/ is not currently used. The default value of xalign
6283 is 0.0 which places the label at the left hand end of the frame.
6284
6285 The next function alters the style of the box that is used to outline
6286 the frame.
6287
6288 <tscreen><verb>
6289 void gtk_frame_set_shadow_type( GtkFrame      *frame,
6290                                 GtkShadowType  type);
6291 </verb></tscreen>
6292
6293 The <tt/type/ argument can take one of the following values:
6294 <tscreen><verb>
6295   GTK_SHADOW_NONE
6296   GTK_SHADOW_IN
6297   GTK_SHADOW_OUT
6298   GTK_SHADOW_ETCHED_IN (the default)
6299   GTK_SHADOW_ETCHED_OUT
6300 </verb></tscreen>
6301
6302 The following code example illustrates the use of the Frame widget.
6303
6304 <tscreen><verb>
6305 /* example-start frame frame.c */
6306
6307 #include <gtk/gtk.h>
6308
6309 int main( int   argc,
6310           char *argv[] )
6311 {
6312   /* GtkWidget is the storage type for widgets */
6313   GtkWidget *window;
6314   GtkWidget *frame;
6315   GtkWidget *button;
6316   gint i;
6317
6318   /* Initialise GTK */
6319   gtk_init(&amp;argc, &amp;argv);
6320     
6321   /* Create a new window */
6322   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6323   gtk_window_set_title(GTK_WINDOW(window), "Frame Example");
6324
6325   /* Here we connect the "destroy" event to a signal handler */ 
6326   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6327                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6328
6329   gtk_widget_set_usize(window, 300, 300);
6330   /* Sets the border width of the window. */
6331   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6332
6333   /* Create a Frame */
6334   frame = gtk_frame_new(NULL);
6335   gtk_container_add(GTK_CONTAINER(window), frame);
6336
6337   /* Set the frame's label */
6338   gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" );
6339
6340   /* Align the label at the right of the frame */
6341   gtk_frame_set_label_align( GTK_FRAME(frame), 1.0, 0.0);
6342
6343   /* Set the style of the frame */
6344   gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
6345
6346   gtk_widget_show(frame);
6347   
6348   /* Display the window */
6349   gtk_widget_show (window);
6350     
6351   /* Enter the event loop */
6352   gtk_main ();
6353     
6354   return(0);
6355 }
6356 /* example-end */
6357
6358 </verb></tscreen>
6359
6360 <!-- ----------------------------------------------------------------- -->   
6361 <sect1> Aspect Frames
6362 <p>
6363 The aspect frame widget is like a frame widget, except that it also
6364 enforces the aspect ratio (that is, the ratio of the width to the
6365 height) of the child widget to have a certain value, adding extra
6366 space if necessary. This is useful, for instance, if you want to
6367 preview a larger image. The size of the preview should vary when the
6368 user resizes the window, but the aspect ratio needs to always match
6369 the original image.
6370   
6371 To create a new aspect frame use:
6372    
6373 <tscreen><verb>
6374 GtkWidget *gtk_aspect_frame_new( const gchar *label,
6375                                  gfloat       xalign,
6376                                  gfloat       yalign,
6377                                  gfloat       ratio,
6378                                  gint         obey_child);
6379 </verb></tscreen>
6380    
6381 <tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
6382 widgets. If <tt/obey_child/ is true, the aspect ratio of a child
6383 widget will match the aspect ratio of the ideal size it requests.
6384 Otherwise, it is given by <tt/ratio/.
6385    
6386 To change the options of an existing aspect frame, you can use:
6387    
6388 <tscreen><verb>
6389 void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
6390                            gfloat          xalign,
6391                            gfloat          yalign,
6392                            gfloat          ratio,
6393                            gint            obey_child);
6394 </verb></tscreen>
6395    
6396 As an example, the following program uses an AspectFrame to present a
6397 drawing area whose aspect ratio will always be 2:1, no matter how the
6398 user resizes the top-level window.
6399    
6400 <tscreen><verb>
6401 /* example-start aspectframe aspectframe.c */
6402
6403 #include <gtk/gtk.h>
6404    
6405 int main( int argc,
6406           char *argv[] )
6407 {
6408     GtkWidget *window;
6409     GtkWidget *aspect_frame;
6410     GtkWidget *drawing_area;
6411     gtk_init (&amp;argc, &amp;argv);
6412    
6413     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6414     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
6415     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6416                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6417     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6418    
6419     /* Create an aspect_frame and add it to our toplevel window */
6420    
6421     aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
6422                                          0.5, /* center x */
6423                                          0.5, /* center y */
6424                                          2, /* xsize/ysize = 2 */
6425                                          FALSE /* ignore child's aspect */);
6426    
6427     gtk_container_add (GTK_CONTAINER(window), aspect_frame);
6428     gtk_widget_show (aspect_frame);
6429    
6430     /* Now add a child widget to the aspect frame */
6431    
6432     drawing_area = gtk_drawing_area_new ();
6433    
6434     /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
6435      * window since we are forcing a 2x1 aspect ratio */
6436     gtk_widget_set_usize (drawing_area, 200, 200);
6437     gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
6438     gtk_widget_show (drawing_area);
6439    
6440     gtk_widget_show (window);
6441     gtk_main ();
6442     return 0;
6443 }
6444 /* example-end */
6445 </verb></tscreen>
6446
6447 <!-- ----------------------------------------------------------------- -->   
6448 <sect1> Paned Window Widgets
6449 <p>
6450 The paned window widgets are useful when you want to divide an area
6451 into two parts, with the relative size of the two parts controlled by
6452 the user. A groove is drawn between the two portions with a handle
6453 that the user can drag to change the ratio. The division can either be
6454 horizontal (HPaned) or vertical (VPaned).
6455    
6456 To create a new paned window, call one of:
6457    
6458 <tscreen><verb>
6459 GtkWidget *gtk_hpaned_new (void);
6460
6461 GtkWidget *gtk_vpaned_new (void);
6462 </verb></tscreen>
6463
6464 After creating the paned window widget, you need to add child widgets
6465 to its two halves. To do this, use the functions:
6466    
6467 <tscreen><verb>
6468 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
6469
6470 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
6471 </verb></tscreen>
6472    
6473 <tt/gtk_paned_add1()/ adds the child widget to the left or top half of
6474 the paned window. <tt/gtk_paned_add2()/ adds the child widget to the
6475 right or bottom half of the paned window.
6476
6477 A paned widget can be changed visually using the following two
6478 functions.
6479
6480 <tscreen><verb>
6481 void gtk_paned_set_handle_size( GtkPaned *paned,
6482                                 guint16   size);
6483
6484 void gtk_paned_set_gutter_size( GtkPaned *paned,
6485                                 guint16   size);
6486 </verb></tscreen>
6487
6488 The first of these sets the size of the handle and the second sets the
6489 size of the gutter that is between the two parts of the paned window.
6490
6491 As an example, we will create part of the user interface of an
6492 imaginary email program. A window is divided into two portions
6493 vertically, with the top portion being a list of email messages and
6494 the bottom portion the text of the email message. Most of the program
6495 is pretty straightforward. A couple of points to note: text can't be
6496 added to a Text widget until it is realized. This could be done by
6497 calling <tt/gtk_widget_realize()/, but as a demonstration of an
6498 alternate technique, we connect a handler to the "realize" signal to
6499 add the text. Also, we need to add the <tt/GTK_SHRINK/ option to some
6500 of the items in the table containing the text window and its
6501 scrollbars, so that when the bottom portion is made smaller, the
6502 correct portions shrink instead of being pushed off the bottom of the
6503 window.
6504
6505 <tscreen><verb>
6506 /* example-start paned paned.c */
6507
6508 #include <gtk/gtk.h>
6509    
6510 /* Create the list of "messages" */
6511 GtkWidget *create_list( void )
6512 {
6513
6514     GtkWidget *scrolled_window;
6515     GtkWidget *list;
6516     GtkWidget *list_item;
6517    
6518     int i;
6519     char buffer[16];
6520    
6521     /* Create a new scrolled window, with scrollbars only if needed */
6522     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6523     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6524                                     GTK_POLICY_AUTOMATIC, 
6525                                     GTK_POLICY_AUTOMATIC);
6526    
6527     /* Create a new list and put it in the scrolled window */
6528     list = gtk_list_new ();
6529     gtk_scrolled_window_add_with_viewport (
6530                GTK_SCROLLED_WINDOW (scrolled_window), list);
6531     gtk_widget_show (list);
6532    
6533     /* Add some messages to the window */
6534     for (i=0; i<10; i++) {
6535
6536         sprintf(buffer,"Message #%d",i);
6537         list_item = gtk_list_item_new_with_label (buffer);
6538         gtk_container_add (GTK_CONTAINER(list), list_item);
6539         gtk_widget_show (list_item);
6540
6541     }
6542    
6543     return scrolled_window;
6544 }
6545    
6546 /* Add some text to our text widget - this is a callback that is invoked
6547 when our window is realized. We could also force our window to be
6548 realized with gtk_widget_realize, but it would have to be part of
6549 a hierarchy first */
6550
6551 void realize_text( GtkWidget *text,
6552                    gpointer data )
6553 {
6554     gtk_text_freeze (GTK_TEXT (text));
6555     gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
6556     "From: pathfinder@nasa.gov\n"
6557     "To: mom@nasa.gov\n"
6558     "Subject: Made it!\n"
6559     "\n"
6560     "We just got in this morning. The weather has been\n"
6561     "great - clear but cold, and there are lots of fun sights.\n"
6562     "Sojourner says hi. See you soon.\n"
6563     " -Path\n", -1);
6564    
6565     gtk_text_thaw (GTK_TEXT (text));
6566 }
6567    
6568 /* Create a scrolled text area that displays a "message" */
6569 GtkWidget *create_text( void )
6570 {
6571     GtkWidget *table;
6572     GtkWidget *text;
6573     GtkWidget *hscrollbar;
6574     GtkWidget *vscrollbar;
6575    
6576     /* Create a table to hold the text widget and scrollbars */
6577     table = gtk_table_new (2, 2, FALSE);
6578    
6579     /* Put a text widget in the upper left hand corner. Note the use of
6580      * GTK_SHRINK in the y direction */
6581     text = gtk_text_new (NULL, NULL);
6582     gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
6583                       GTK_FILL | GTK_EXPAND,
6584                       GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
6585     gtk_widget_show (text);
6586    
6587     /* Put a HScrollbar in the lower left hand corner */
6588     hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
6589     gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
6590                       GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
6591     gtk_widget_show (hscrollbar);
6592    
6593     /* And a VScrollbar in the upper right */
6594     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
6595     gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
6596                       GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
6597     gtk_widget_show (vscrollbar);
6598    
6599     /* Add a handler to put a message in the text widget when it is realized */
6600     gtk_signal_connect (GTK_OBJECT (text), "realize",
6601                         GTK_SIGNAL_FUNC (realize_text), NULL);
6602    
6603     return table;
6604 }
6605    
6606 int main( int   argc,
6607           char *argv[] )
6608 {
6609     GtkWidget *window;
6610     GtkWidget *vpaned;
6611     GtkWidget *list;
6612     GtkWidget *text;
6613
6614     gtk_init (&amp;argc, &amp;argv);
6615    
6616     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6617     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
6618     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6619                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6620     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6621     gtk_widget_set_usize (GTK_WIDGET(window), 450, 400);
6622
6623     /* create a vpaned widget and add it to our toplevel window */
6624    
6625     vpaned = gtk_vpaned_new ();
6626     gtk_container_add (GTK_CONTAINER(window), vpaned);
6627     gtk_paned_set_handle_size (GTK_PANED(vpaned),
6628                                10);
6629     gtk_paned_set_gutter_size (GTK_PANED(vpaned),
6630                                15);                       
6631     gtk_widget_show (vpaned);
6632    
6633     /* Now create the contents of the two halves of the window */
6634    
6635     list = create_list ();
6636     gtk_paned_add1 (GTK_PANED(vpaned), list);
6637     gtk_widget_show (list);
6638    
6639     text = create_text ();
6640     gtk_paned_add2 (GTK_PANED(vpaned), text);
6641     gtk_widget_show (text);
6642     gtk_widget_show (window);
6643     gtk_main ();
6644     return 0;
6645 }
6646 /* example-end */
6647 </verb></tscreen>
6648
6649 <!-- ----------------------------------------------------------------- -->
6650 <sect1>Viewports <label id="sec_Viewports">
6651 <p>
6652 It is unlikely that you will ever need to use the Viewport widget
6653 directly. You are much more likely to use the
6654 <ref id="sec_ScrolledWindow" name="Scrolled Window"> widget which
6655 itself uses the Viewport.
6656
6657 A viewport widget allows you to place a larger widget within it such
6658 that you can view a part of it at a time. It uses
6659 <ref id="sec_Adjustment" name="Adjustments"> to define the area that
6660 is currently in view.
6661
6662 A Viewport is created with the function
6663
6664 <tscreen><verb>
6665 GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment,
6666                              GtkAdjustment *vadjustment );
6667 </verb></tscreen>
6668
6669 As you can see you can specify the horizontal and vertical Adjustments
6670 that the widget is to use when you create the widget. It will create
6671 its own if you pass NULL as the value of the arguments.
6672
6673 You can get and set the adjustments after the widget has been created
6674 using the following four functions:
6675
6676 <tscreen><verb>
6677 GtkAdjustment *gtk_viewport_get_hadjustment (GtkViewport *viewport );
6678
6679 GtkAdjustment *gtk_viewport_get_vadjustment (GtkViewport *viewport );
6680
6681 void gtk_viewport_set_hadjustment( GtkViewport   *viewport,
6682                                    GtkAdjustment *adjustment );
6683
6684 void gtk_viewport_set_vadjustment( GtkViewport   *viewport,
6685                                    GtkAdjustment *adjustment );
6686 </verb></tscreen>
6687
6688 The only other viewport function is used to alter its appearance:
6689
6690 <tscreen><verb>
6691 void gtk_viewport_set_shadow_type( GtkViewport   *viewport,
6692                                    GtkShadowType  type );
6693 </verb></tscreen>
6694
6695 Possible values for the <tt/type/ parameter are:
6696 <tscreen><verb>
6697   GTK_SHADOW_NONE,
6698   GTK_SHADOW_IN,
6699   GTK_SHADOW_OUT,
6700   GTK_SHADOW_ETCHED_IN,
6701   GTK_SHADOW_ETCHED_OUT
6702 </verb></tscreen>
6703  
6704 <!-- ----------------------------------------------------------------- -->
6705 <sect1>Scrolled Windows <label id="sec_ScrolledWindow">
6706 <p>
6707 Scrolled windows are used to create a scrollable area with another
6708 widget inside it. You may insert any type of widget into a scrolled
6709 window, and it will be accessible regardless of the size by using the
6710 scrollbars.
6711
6712 The following function is used to create a new scrolled window.
6713
6714 <tscreen><verb>
6715 GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
6716                                     GtkAdjustment *vadjustment );
6717 </verb></tscreen>
6718
6719 Where the first argument is the adjustment for the horizontal
6720 direction, and the second, the adjustment for the vertical direction.
6721 These are almost always set to NULL.
6722
6723 <tscreen><verb>
6724 void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
6725                                      GtkPolicyType      hscrollbar_policy,
6726                                      GtkPolicyType      vscrollbar_policy );
6727 </verb></tscreen>
6728
6729 This sets the policy to be used with respect to the scrollbars.
6730 The first argument is the scrolled window you wish to change. The second
6731 sets the policy for the horizontal scrollbar, and the third the policy for 
6732 the vertical scrollbar.
6733
6734 The policy may be one of <tt/GTK_POLICY_AUTOMATIC/ or
6735 <tt/GTK_POLICY_ALWAYS/. <tt/GTK_POLICY_AUTOMATIC/ will automatically
6736 decide whether you need scrollbars, whereas <tt/GTK_POLICY_ALWAYS/
6737 will always leave the scrollbars there.
6738
6739 You can then place your object into the scrolled window using the
6740 following function.
6741
6742 <tscreen><verb>
6743 void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
6744                                             GtkWidget         *child);
6745 </verb></tscreen>
6746
6747 Here is a simple example that packs a table eith 100 toggle buttons
6748 into a scrolled window. I've only commented on the parts that may be
6749 new to you.
6750
6751 <tscreen><verb>
6752 /* example-start scrolledwin scrolledwin.c */
6753
6754 #include <gtk/gtk.h>
6755
6756 void destroy( GtkWidget *widget,
6757               gpointer   data )
6758 {
6759     gtk_main_quit();
6760 }
6761
6762 int main( int   argc,
6763           char *argv[] )
6764 {
6765     static GtkWidget *window;
6766     GtkWidget *scrolled_window;
6767     GtkWidget *table;
6768     GtkWidget *button;
6769     char buffer[32];
6770     int i, j;
6771     
6772     gtk_init (&amp;argc, &amp;argv);
6773     
6774     /* Create a new dialog window for the scrolled window to be
6775      * packed into.  */
6776     window = gtk_dialog_new ();
6777     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6778                         (GtkSignalFunc) destroy, NULL);
6779     gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
6780     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6781     gtk_widget_set_usize(window, 300, 300);
6782     
6783     /* create a new scrolled window. */
6784     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
6785     
6786     gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
6787     
6788     /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
6789      * GTK_POLICY_AUTOMATIC will automatically decide whether you need
6790      * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
6791      * there.  The first one is the horizontal scrollbar, the second, 
6792      * the vertical. */
6793     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
6794                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
6795     /* The dialog window is created with a vbox packed into it. */                                                              
6796     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, 
6797                         TRUE, TRUE, 0);
6798     gtk_widget_show (scrolled_window);
6799     
6800     /* create a table of 10 by 10 squares. */
6801     table = gtk_table_new (10, 10, FALSE);
6802     
6803     /* set the spacing to 10 on x and 10 on y */
6804     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
6805     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
6806     
6807     /* pack the table into the scrolled window */
6808     gtk_scrolled_window_add_with_viewport (
6809                    GTK_SCROLLED_WINDOW (scrolled_window), table);
6810     gtk_widget_show (table);
6811     
6812     /* this simply creates a grid of toggle buttons on the table
6813      * to demonstrate the scrolled window. */
6814     for (i = 0; i < 10; i++)
6815        for (j = 0; j < 10; j++) {
6816           sprintf (buffer, "button (%d,%d)\n", i, j);
6817           button = gtk_toggle_button_new_with_label (buffer);
6818           gtk_table_attach_defaults (GTK_TABLE (table), button,
6819                                      i, i+1, j, j+1);
6820           gtk_widget_show (button);
6821        }
6822     
6823     /* Add a "close" button to the bottom of the dialog */
6824     button = gtk_button_new_with_label ("close");
6825     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
6826                                (GtkSignalFunc) gtk_widget_destroy,
6827                                GTK_OBJECT (window));
6828     
6829     /* this makes it so the button is the default. */
6830     
6831     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
6832     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
6833     
6834     /* This grabs this button to be the default button. Simply hitting
6835      * the "Enter" key will cause this button to activate. */
6836     gtk_widget_grab_default (button);
6837     gtk_widget_show (button);
6838     
6839     gtk_widget_show (window);
6840     
6841     gtk_main();
6842     
6843     return(0);
6844 }
6845 /* example-end */
6846 </verb></tscreen>
6847
6848 Try playing with resizing the window. You'll notice how the scrollbars
6849 react. You may also wish to use the gtk_widget_set_usize() call to set
6850 the default size of the window or other widgets.
6851
6852 <!-- ----------------------------------------------------------------- -->   
6853 <sect1>Button Boxes
6854 <p>
6855 Button Boxes are a convenient way to quickly layout a group of
6856 buttons. They come in both horizontal and vertical flavours. You
6857 create a new Button Box with one of the following calls, which create
6858 a horizontal or vertical box, respectively:
6859
6860 <tscreen><verb>
6861 GtkWidget *gtk_hbutton_box_new( void );
6862
6863 GtkWidget *gtk_vbutton_box_new( void );
6864 </verb></tscreen>
6865
6866 The only attributes pertaining to button boxes effect how the buttons
6867 are laid out. You can change the spacing between the buttons with:
6868
6869 <tscreen><verb>
6870 void gtk_hbutton_box_set_spacing_default( gint spacing );
6871
6872 void gtk_vbutton_box_set_spacing_default( gint spacing );
6873 </verb></tscreen>
6874
6875 Similarly, the current spacing values can be queried using:
6876
6877 <tscreen><verb>
6878 gint gtk_hbutton_box_get_spacing_default( void );
6879
6880 gint gtk_vbutton_box_get_spacing_default( void );
6881 </verb></tscreen>
6882
6883 The second attribute that we can access effects the layout of the
6884 buttons within the box. It is set using one of:
6885
6886 <tscreen><verb>
6887 void gtk_hbutton_box_set_layout_default( GtkButtonBoxStyle layout );
6888
6889 void gtk_vbutton_box_set_layout_default( GtkButtonBoxStyle layout );
6890 </verb></tscreen>
6891
6892 The <tt/layout/ argument can take one of the following values:
6893
6894 <tscreen><verb>
6895   GTK_BUTTONBOX_DEFAULT_STYLE
6896   GTK_BUTTONBOX_SPREAD
6897   GTK_BUTTONBOX_EDGE
6898   GTK_BUTTONBOX_START
6899   GTK_BUTTONBOX_END
6900 </verb></tscreen>
6901
6902 The current layout setting can be retrieved using:
6903
6904 <tscreen><verb>
6905 GtkButtonBoxStyle gtk_hbutton_box_get_layout_default( void );
6906
6907 GtkButtonBoxStyle gtk_vbutton_box_get_layout_default( void );
6908 </verb></tscreen>
6909
6910 Buttons are added to a Button Box using the usual function:
6911
6912 <tscreen><verb>
6913     gtk_container_add( GTK_CONTAINER(button_box), child_widget );
6914 </verb></tscreen>
6915
6916 Here's an example that illustrates all the different layout settings
6917 for Button Boxes.
6918
6919 <tscreen><verb>
6920 /* example-start buttonbox buttonbox.c */
6921
6922 #include <gtk/gtk.h>
6923
6924 /* Create a Button Box with the specified parameters */
6925 GtkWidget *create_bbox( gint  horizontal,
6926                         char *title,
6927                         gint  spacing,
6928                         gint  child_w,
6929                         gint  child_h,
6930                         gint  layout )
6931 {
6932   GtkWidget *frame;
6933   GtkWidget *bbox;
6934   GtkWidget *button;
6935
6936   frame = gtk_frame_new (title);
6937
6938   if (horizontal)
6939     bbox = gtk_hbutton_box_new ();
6940   else
6941     bbox = gtk_vbutton_box_new ();
6942
6943   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
6944   gtk_container_add (GTK_CONTAINER (frame), bbox);
6945
6946   /* Set the appearance of the Button Box */
6947   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
6948   gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), spacing);
6949   gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
6950
6951   button = gtk_button_new_with_label ("OK");
6952   gtk_container_add (GTK_CONTAINER (bbox), button);
6953
6954   button = gtk_button_new_with_label ("Cancel");
6955   gtk_container_add (GTK_CONTAINER (bbox), button);
6956
6957   button = gtk_button_new_with_label ("Help");
6958   gtk_container_add (GTK_CONTAINER (bbox), button);
6959
6960   return(frame);
6961 }
6962
6963 int main( int   argc,
6964           char *argv[] )
6965 {
6966   static GtkWidget* window = NULL;
6967   GtkWidget *main_vbox;
6968   GtkWidget *vbox;
6969   GtkWidget *hbox;
6970   GtkWidget *frame_horz;
6971   GtkWidget *frame_vert;
6972
6973   /* Initialize GTK */
6974   gtk_init( &amp;argc, &amp;argv );
6975
6976   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6977   gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
6978
6979   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6980                       GTK_SIGNAL_FUNC(gtk_main_quit),
6981                       NULL);
6982
6983   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6984
6985   main_vbox = gtk_vbox_new (FALSE, 0);
6986   gtk_container_add (GTK_CONTAINER (window), main_vbox);
6987
6988   frame_horz = gtk_frame_new ("Horizontal Button Boxes");
6989   gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
6990
6991   vbox = gtk_vbox_new (FALSE, 0);
6992   gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6993   gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
6994
6995   gtk_box_pack_start (GTK_BOX (vbox),
6996            create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
6997                       TRUE, TRUE, 0);
6998
6999   gtk_box_pack_start (GTK_BOX (vbox),
7000            create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
7001                       TRUE, TRUE, 5);
7002
7003   gtk_box_pack_start (GTK_BOX (vbox),
7004            create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
7005                       TRUE, TRUE, 5);
7006
7007   gtk_box_pack_start (GTK_BOX (vbox),
7008            create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END),
7009                       TRUE, TRUE, 5);
7010
7011   frame_vert = gtk_frame_new ("Vertical Button Boxes");
7012   gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
7013
7014   hbox = gtk_hbox_new (FALSE, 0);
7015   gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
7016   gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
7017
7018   gtk_box_pack_start (GTK_BOX (hbox),
7019            create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD),
7020                       TRUE, TRUE, 0);
7021
7022   gtk_box_pack_start (GTK_BOX (hbox),
7023            create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
7024                       TRUE, TRUE, 5);
7025
7026   gtk_box_pack_start (GTK_BOX (hbox),
7027            create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
7028                       TRUE, TRUE, 5);
7029
7030   gtk_box_pack_start (GTK_BOX (hbox),
7031            create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END),
7032                       TRUE, TRUE, 5);
7033
7034   gtk_widget_show_all (window);
7035
7036   /* Enter the event loop */
7037   gtk_main ();
7038     
7039   return(0);
7040 }
7041 /* example-end */
7042 </verb></tscreen>
7043
7044 <!-- ----------------------------------------------------------------- -->   
7045 <sect1>Toolbar
7046 <p>
7047 Toolbars are usually used to group some number of widgets in order to
7048 simplify customization of their look and layout. Typically a toolbar
7049 consists of buttons with icons, labels and tooltips, but any other
7050 widget can also be put inside a toolbar. Finally, items can be
7051 arranged horizontally or vertically and buttons can be displayed with
7052 icons, labels, or both.
7053
7054 Creating a toolbar is (as one may already suspect) done with the
7055 following function:
7056
7057 <tscreen><verb>
7058 GtkWidget *gtk_toolbar_new( GtkOrientation orientation,
7059                             GtkToolbarStyle  style );
7060 </verb></tscreen>
7061
7062 where orientation may be one of:
7063
7064 <tscreen><verb>
7065   GTK_ORIENTATION_HORIZONTAL    
7066   GTK_ORIENTATION_VERTICAL
7067 </verb></tscreen>
7068
7069 and style one of:
7070
7071 <tscreen><verb>
7072   GTK_TOOLBAR_TEXT
7073   GTK_TOOLBAR_ICONS
7074   GTK_TOOLBAR_BOTH
7075 </verb></tscreen>
7076
7077 The style applies to all the buttons created with the `item' functions
7078 (not to buttons inserted into toolbar as separate widgets).
7079
7080 After creating a toolbar one can append, prepend and insert items
7081 (that means simple text strings) or elements (that means any widget
7082 types) into the toolbar. To describe an item we need a label text, a
7083 tooltip text, a private tooltip text, an icon for the button and a
7084 callback function for it. For example, to append or prepend an item
7085 you may use the following functions:
7086
7087 <tscreen><verb>
7088 GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
7089                                     const char    *text,
7090                                     const char    *tooltip_text,
7091                                     const char    *tooltip_private_text,
7092                                     GtkWidget     *icon,
7093                                     GtkSignalFunc  callback,
7094                                     gpointer       user_data );
7095
7096 GtkWidget *gtk_toolbar_prepend_item( GtkToolbar    *toolbar,
7097                                      const char    *text,
7098                                      const char    *tooltip_text,
7099                                      const char    *tooltip_private_text,
7100                                      GtkWidget     *icon,
7101                                      GtkSignalFunc  callback,
7102                                      gpointer       user_data );
7103 </verb></tscreen>
7104
7105 If you want to use gtk_toolbar_insert_item, the only additional
7106 parameter which must be specified is the position in which the item
7107 should be inserted, thus:
7108
7109 <tscreen><verb>
7110 GtkWidget *gtk_toolbar_insert_item( GtkToolbar    *toolbar,
7111                                     const char    *text,
7112                                     const char    *tooltip_text,
7113                                     const char    *tooltip_private_text,
7114                                     GtkWidget     *icon,
7115                                     GtkSignalFunc  callback,
7116                                     gpointer       user_data,
7117                                     gint           position );
7118 </verb></tscreen>
7119
7120 To simplify adding spaces between toolbar items, you may use the
7121 following functions:
7122
7123 <tscreen><verb>
7124 void gtk_toolbar_append_space( GtkToolbar *toolbar );
7125
7126 void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
7127
7128 void gtk_toolbar_insert_space( GtkToolbar *toolbar,
7129                                gint        position );
7130  
7131 </verb></tscreen>
7132
7133 While the size of the added space can be set globally for a
7134 whole toolbar with the function:
7135
7136 <tscreen><verb>
7137 void gtk_toolbar_set_space_size( GtkToolbar *toolbar,
7138                                  gint        space_size) ;
7139 </verb></tscreen>
7140
7141 If it's required, the orientation of a toolbar and its style can be
7142 changed "on the fly" using the following functions:
7143
7144 <tscreen><verb>
7145 void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
7146                                   GtkOrientation  orientation );
7147
7148 void gtk_toolbar_set_style( GtkToolbar      *toolbar,
7149                             GtkToolbarStyle  style );
7150
7151 void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
7152                                gint        enable );
7153 </verb></tscreen>
7154
7155 Where <tt/orientation/ is one of <tt/GTK_ORIENTATION_HORIZONTAL/ or
7156 <tt/GTK_ORIENTATION_VERTICAL/. The <tt/style/ is used to set
7157 appearance of the toolbar items by using one of
7158 <tt/GTK_TOOLBAR_ICONS/, <tt/GTK_TOOLBAR_TEXT/, or
7159 <tt/GTK_TOOLBAR_BOTH/.
7160
7161 To show some other things that can be done with a toolbar, let's take
7162 the following program (we'll interrupt the listing with some
7163 additional explanations):
7164
7165 <tscreen><verb>
7166 #include <gtk/gtk.h>
7167
7168 #include "gtk.xpm"
7169
7170 /* This function is connected to the Close button or
7171  * closing the window from the WM */
7172 gint delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
7173 {
7174   gtk_main_quit ();
7175   return(FALSE);
7176 }
7177 </verb></tscreen>
7178
7179 The above beginning seems for sure familiar to you if it's not your first
7180 GTK program. There is one additional thing though, we include a nice XPM
7181 picture to serve as an icon for all of the buttons.
7182
7183 <tscreen><verb>
7184 GtkWidget* close_button; /* This button will emit signal to close
7185                           * application */
7186 GtkWidget* tooltips_button; /* to enable/disable tooltips */
7187 GtkWidget* text_button,
7188          * icon_button,
7189          * both_button; /* radio buttons for toolbar style */
7190 GtkWidget* entry; /* a text entry to show packing any widget into
7191                    * toolbar */
7192 </verb></tscreen>
7193
7194 In fact not all of the above widgets are needed here, but to make things
7195 clearer I put them all together.
7196
7197 <tscreen><verb>
7198 /* that's easy... when one of the buttons is toggled, we just
7199  * check which one is active and set the style of the toolbar
7200  * accordingly
7201  * ATTENTION: our toolbar is passed as data to callback ! */
7202 void radio_event (GtkWidget *widget, gpointer data)
7203 {
7204   if (GTK_TOGGLE_BUTTON (text_button)->active) 
7205     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_TEXT);
7206   else if (GTK_TOGGLE_BUTTON (icon_button)->active)
7207     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_ICONS);
7208   else if (GTK_TOGGLE_BUTTON (both_button)->active)
7209     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_BOTH);
7210 }
7211
7212 /* even easier, just check given toggle button and enable/disable 
7213  * tooltips */
7214 void toggle_event (GtkWidget *widget, gpointer data)
7215 {
7216   gtk_toolbar_set_tooltips (GTK_TOOLBAR ( data ),
7217                             GTK_TOGGLE_BUTTON (widget)->active );
7218 }
7219 </verb></tscreen>
7220
7221 The above are just two callback functions that will be called when
7222 one of the buttons on a toolbar is pressed. You should already be
7223 familiar with things like this if you've already used toggle buttons (and
7224 radio buttons).
7225
7226 <tscreen><verb>
7227 int main (int argc, char *argv[])
7228 {
7229   /* Here is our main window (a dialog) and a handle for the handlebox */
7230   GtkWidget* dialog;
7231   GtkWidget* handlebox;
7232
7233   /* Ok, we need a toolbar, an icon with a mask (one for all of 
7234      the buttons) and an icon widget to put this icon in (but 
7235      we'll create a separate widget for each button) */
7236   GtkWidget * toolbar;
7237   GdkPixmap * icon;
7238   GdkBitmap * mask;
7239   GtkWidget * iconw;
7240
7241   /* this is called in all GTK application. */
7242   gtk_init (&amp;argc, &amp;argv);
7243   
7244   /* create a new window with a given title, and nice size */
7245   dialog = gtk_dialog_new ();
7246   gtk_window_set_title ( GTK_WINDOW ( dialog ) , "GTKToolbar Tutorial");
7247   gtk_widget_set_usize( GTK_WIDGET ( dialog ) , 600 , 300 );
7248   GTK_WINDOW ( dialog ) ->allow_shrink = TRUE;
7249
7250   /* typically we quit if someone tries to close us */
7251   gtk_signal_connect ( GTK_OBJECT ( dialog ), "delete_event",
7252                        GTK_SIGNAL_FUNC ( delete_event ), NULL);
7253
7254   /* we need to realize the window because we use pixmaps for 
7255    * items on the toolbar in the context of it */
7256   gtk_widget_realize ( dialog );
7257
7258   /* to make it nice we'll put the toolbar into the handle box, 
7259    * so that it can be detached from the main window */
7260   handlebox = gtk_handle_box_new ();
7261   gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(dialog)->vbox ),
7262                        handlebox, FALSE, FALSE, 5 );
7263 </verb></tscreen>
7264
7265 The above should be similar to any other GTK application. Just
7266 initialization of GTK, creating the window, etc. There is only one
7267 thing that probably needs some explanation: a handle box. A handle box
7268 is just another box that can be used to pack widgets in to. The
7269 difference between it and typical boxes is that it can be detached
7270 from a parent window (or, in fact, the handle box remains in the
7271 parent, but it is reduced to a very small rectangle, while all of its
7272 contents are reparented to a new freely floating window). It is
7273 usually nice to have a detachable toolbar, so these two widgets occur
7274 together quite often.
7275
7276 <tscreen><verb>
7277   /* toolbar will be horizontal, with both icons and text, and
7278    * with 5pxl spaces between items and finally, 
7279    * we'll also put it into our handlebox */
7280   toolbar = gtk_toolbar_new ( GTK_ORIENTATION_HORIZONTAL,
7281                               GTK_TOOLBAR_BOTH );
7282   gtk_container_set_border_width ( GTK_CONTAINER ( toolbar ) , 5 );
7283   gtk_toolbar_set_space_size ( GTK_TOOLBAR ( toolbar ), 5 );
7284   gtk_container_add ( GTK_CONTAINER ( handlebox ) , toolbar );
7285
7286   /* now we create icon with mask: we'll reuse it to create
7287    * icon widgets for toolbar items */
7288   icon = gdk_pixmap_create_from_xpm_d ( dialog->window, &amp;mask,
7289       &amp;dialog->style->white, gtk_xpm );
7290 </verb></tscreen>
7291
7292 Well, what we do above is just a straightforward initialization of
7293 the toolbar widget and creation of a GDK pixmap with its mask. If you
7294 want to know something more about using pixmaps, refer to GDK
7295 documentation or to the <ref id="sec_Pixmaps" name="Pixmaps"> section
7296 earlier in this tutorial.
7297
7298 <tscreen><verb>
7299   /* our first item is <close> button */
7300   iconw = gtk_pixmap_new ( icon, mask ); /* icon widget */
7301   close_button = 
7302     gtk_toolbar_append_item ( GTK_TOOLBAR (toolbar), /* our toolbar */
7303                               "Close",               /* button label */
7304                               "Closes this app",     /* this button's tooltip */
7305                               "Private",             /* tooltip private info */
7306                               iconw,                 /* icon widget */
7307                               GTK_SIGNAL_FUNC (delete_event), /* a signal */
7308                                NULL );
7309   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); /* space after item */
7310 </verb></tscreen>
7311
7312 In the above code you see the simplest case: adding a button to
7313 toolbar.  Just before appending a new item, we have to construct a
7314 pixmap widget to serve as an icon for this item; this step will have
7315 to be repeated for each new item. Just after the item we also add a
7316 space, so the following items will not touch each other. As you see
7317 gtk_toolbar_append_item returns a pointer to our newly created button
7318 widget, so that we can work with it in the normal way.
7319
7320 <tscreen><verb>
7321   /* now, let's make our radio buttons group... */
7322   iconw = gtk_pixmap_new ( icon, mask );
7323   icon_button = gtk_toolbar_append_element(
7324                     GTK_TOOLBAR(toolbar),
7325                     GTK_TOOLBAR_CHILD_RADIOBUTTON, /* a type of element */
7326                     NULL,                          /* pointer to widget */
7327                     "Icon",                        /* label */
7328                     "Only icons in toolbar",       /* tooltip */
7329                     "Private",                     /* tooltip private string */
7330                     iconw,                         /* icon */
7331                     GTK_SIGNAL_FUNC (radio_event), /* signal */
7332                     toolbar);                      /* data for signal */
7333   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7334 </verb></tscreen>
7335
7336 Here we begin creating a radio buttons group. To do this we use
7337 gtk_toolbar_append_element.  In fact, using this function one can also
7338 +add simple items or even spaces (type = <tt/GTK_TOOLBAR_CHILD_SPACE/
7339 or +<tt/GTK_TOOLBAR_CHILD_BUTTON/). In the above case we start
7340 creating a radio group. In creating other radio buttons for this group
7341 a pointer to the previous button in the group is required, so that a
7342 list of buttons can be easily constructed (see the section on <ref
7343 id="sec_Radio_Buttons" name="Radio Buttons"> earlier in this
7344 tutorial).
7345
7346 <tscreen><verb>
7347   /* following radio buttons refer to previous ones */
7348   iconw = gtk_pixmap_new ( icon, mask );
7349   text_button = 
7350     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7351                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
7352                                icon_button,
7353                                "Text",
7354                                "Only texts in toolbar",
7355                                "Private",
7356                                iconw,
7357                                GTK_SIGNAL_FUNC (radio_event),
7358                                toolbar);
7359   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7360                                           
7361   iconw = gtk_pixmap_new ( icon, mask );
7362   both_button = 
7363     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7364                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
7365                                text_button,
7366                                "Both",
7367                                "Icons and text in toolbar",
7368                                "Private",
7369                                iconw,
7370                                GTK_SIGNAL_FUNC (radio_event),
7371                                toolbar);
7372   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7373   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_button),TRUE);
7374 </verb></tscreen>
7375
7376 In the end we have to set the state of one of the buttons manually
7377 (otherwise they all stay in active state, preventing us from switching
7378 between them).
7379
7380 <tscreen><verb>
7381   /* here we have just a simple toggle button */
7382   iconw = gtk_pixmap_new ( icon, mask );
7383   tooltips_button = 
7384     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7385                                GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
7386                                NULL,
7387                                "Tooltips",
7388                                "Toolbar with or without tips",
7389                                "Private",
7390                                iconw,
7391                                GTK_SIGNAL_FUNC (toggle_event),
7392                                toolbar);
7393   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7394   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltips_button),TRUE);
7395 </verb></tscreen>
7396
7397 A toggle button can be created in the obvious way (if one knows how to create
7398 radio buttons already).
7399
7400 <tscreen><verb>
7401   /* to pack a widget into toolbar, we only have to 
7402    * create it and append it with an appropriate tooltip */
7403   entry = gtk_entry_new ();
7404   gtk_toolbar_append_widget( GTK_TOOLBAR (toolbar), 
7405                              entry, 
7406                              "This is just an entry", 
7407                              "Private" );
7408
7409   /* well, it isn't created within thetoolbar, so we must still show it */
7410   gtk_widget_show ( entry );
7411 </verb></tscreen>
7412
7413 As you see, adding any kind of widget to a toolbar is simple. The
7414 one thing you have to remember is that this widget must be shown manually
7415 (contrary to other items which will be shown together with the toolbar).
7416
7417 <tscreen><verb>
7418   /* that's it ! let's show everything. */
7419   gtk_widget_show ( toolbar );
7420   gtk_widget_show (handlebox);
7421   gtk_widget_show ( dialog );
7422
7423   /* rest in gtk_main and wait for the fun to begin! */
7424   gtk_main ();
7425   
7426   return 0;
7427 }
7428 </verb></tscreen>
7429
7430 So, here we are at the end of toolbar tutorial. Of course, to appreciate
7431 it in full you need also this nice XPM icon, so here it is:
7432
7433 <tscreen><verb>
7434 /* XPM */
7435 static char * gtk_xpm[] = {
7436 "32 39 5 1",
7437 ".      c none",
7438 "+      c black",
7439 "@      c #3070E0",
7440 "#      c #F05050",
7441 "$      c #35E035",
7442 "................+...............",
7443 "..............+++++.............",
7444 "............+++++@@++...........",
7445 "..........+++++@@@@@@++.........",
7446 "........++++@@@@@@@@@@++........",
7447 "......++++@@++++++++@@@++.......",
7448 ".....+++@@@+++++++++++@@@++.....",
7449 "...+++@@@@+++@@@@@@++++@@@@+....",
7450 "..+++@@@@+++@@@@@@@@+++@@@@@++..",
7451 ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
7452 ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
7453 ".+##++@@@@+++@@@+++++@@@@@@@@$@.",
7454 ".+###++@@@@+++@@@+++@@@@@++$$$@.",
7455 ".+####+++@@@+++++++@@@@@+@$$$$@.",
7456 ".+#####+++@@@@+++@@@@++@$$$$$$+.",
7457 ".+######++++@@@@@@@++@$$$$$$$$+.",
7458 ".+#######+##+@@@@+++$$$$$$@@$$+.",
7459 ".+###+++##+##+@@++@$$$$$$++$$$+.",
7460 ".+###++++##+##+@@$$$$$$$@+@$$@+.",
7461 ".+###++++++#+++@$$@+@$$@++$$$@+.",
7462 ".+####+++++++#++$$@+@$$++$$$$+..",
7463 ".++####++++++#++$$@+@$++@$$$$+..",
7464 ".+#####+++++##++$$++@+++$$$$$+..",
7465 ".++####+++##+#++$$+++++@$$$$$+..",
7466 ".++####+++####++$$++++++@$$$@+..",
7467 ".+#####++#####++$$+++@++++@$@+..",
7468 ".+#####++#####++$$++@$$@+++$@@..",
7469 ".++####++#####++$$++$$$$$+@$@++.",
7470 ".++####++#####++$$++$$$$$$$$+++.",
7471 ".+++####+#####++$$++$$$$$$$@+++.",
7472 "..+++#########+@$$+@$$$$$$+++...",
7473 "...+++########+@$$$$$$$$@+++....",
7474 ".....+++######+@$$$$$$$+++......",
7475 "......+++#####+@$$$$$@++........",
7476 ".......+++####+@$$$$+++.........",
7477 ".........++###+$$$@++...........",
7478 "..........++##+$@+++............",
7479 "...........+++++++..............",
7480 ".............++++..............."};
7481 </verb></tscreen>
7482
7483 <!-- ----------------------------------------------------------------- -->
7484 <sect1> Notebooks
7485 <p>
7486 The NoteBook Widget is a collection of "pages" that overlap each
7487 other, each page contains different information with only one page
7488 visible at a time. This widget has become more common lately in GUI
7489 programming, and it is a good way to show blocks of similar
7490 information that warrant separation in their display.
7491
7492 The first function call you will need to know, as you can probably
7493 guess by now, is used to create a new notebook widget.
7494
7495 <tscreen><verb>
7496 GtkWidget *gtk_notebook_new( void );
7497 </verb></tscreen>
7498
7499 Once the notebook has been created, there are a number of functions
7500 that operate on the notebook widget. Let's look at them individually.
7501
7502 The first one we will look at is how to position the page indicators.
7503 These page indicators or "tabs" as they are referred to, can be
7504 positioned in four ways: top, bottom, left, or right.
7505
7506 <tscreen><verb>
7507 void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
7508                                GtkPositionType  pos );
7509 </verb></tscreen>
7510
7511 GtkPositionType will be one of the following, which are pretty self
7512 explanatory:
7513 <tscreen><verb>
7514   GTK_POS_LEFT
7515   GTK_POS_RIGHT
7516   GTK_POS_TOP
7517   GTK_POS_BOTTOM
7518 </verb></tscreen>
7519
7520 <tt/GTK_POS_TOP/ is the default.
7521
7522 Next we will look at how to add pages to the notebook. There are three
7523 ways to add pages to the NoteBook. Let's look at the first two
7524 together as they are quite similar.
7525
7526 <tscreen><verb>
7527 void gtk_notebook_append_page( GtkNotebook *notebook,
7528                                GtkWidget   *child,
7529                                GtkWidget   *tab_label );
7530
7531 void gtk_notebook_prepend_page( GtkNotebook *notebook,
7532                                 GtkWidget   *child,
7533                                 GtkWidget   *tab_label );
7534 </verb></tscreen>
7535
7536 These functions add pages to the notebook by inserting them from the
7537 back of the notebook (append), or the front of the notebook (prepend).
7538 <tt/child/ is the widget that is placed within the notebook page, and
7539 <tt/tab_label/ is the label for the page being added. The <tt/child/
7540 widget must be created separately, and is typically a set of options
7541 setup witin one of the other container widgets, such as a table.
7542
7543 The final function for adding a page to the notebook contains all of
7544 the properties of the previous two, but it allows you to specify what
7545 position you want the page to be in the notebook.
7546
7547 <tscreen><verb>
7548 void gtk_notebook_insert_page( GtkNotebook *notebook,
7549                                GtkWidget   *child,
7550                                GtkWidget   *tab_label,
7551                                gint         position );
7552 </verb></tscreen>
7553
7554 The parameters are the same as _append_ and _prepend_ except it
7555 contains an extra parameter, <tt/position/.  This parameter is used to
7556 specify what place this page will be inserted into the first page
7557 having position zero.
7558
7559 Now that we know how to add a page, lets see how we can remove a page
7560 from the notebook.
7561
7562 <tscreen><verb>
7563 void gtk_notebook_remove_page( GtkNotebook *notebook,
7564                                gint         page_num );
7565 </verb></tscreen>
7566
7567 This function takes the page specified by <tt/page_num/ and removes it
7568 from the widget pointed to by <tt/notebook/.
7569
7570 To find out what the current page is in a notebook use the function:
7571
7572 <tscreen><verb>
7573 gint gtk_notebook_get_current_page( GtkNotebook *notebook );
7574 </verb></tscreen>
7575
7576 These next two functions are simple calls to move the notebook page
7577 forward or backward. Simply provide the respective function call with
7578 the notebook widget you wish to operate on. Note: When the NoteBook is
7579 currently on the last page, and gtk_notebook_next_page is called, the
7580 notebook will wrap back to the first page. Likewise, if the NoteBook
7581 is on the first page, and gtk_notebook_prev_page is called, the
7582 notebook will wrap to the last page.
7583
7584 <tscreen><verb>
7585 void gtk_notebook_next_page( GtkNoteBook *notebook );
7586
7587 void gtk_notebook_prev_page( GtkNoteBook *notebook );
7588 </verb></tscreen>
7589
7590 This next function sets the "active" page. If you wish the notebook to
7591 be opened to page 5 for example, you would use this function.  Without
7592 using this function, the notebook defaults to the first page.
7593
7594 <tscreen><verb>
7595 void gtk_notebook_set_page( GtkNotebook *notebook,
7596                             gint         page_num );
7597 </verb></tscreen>
7598
7599 The next two functions add or remove the notebook page tabs and the
7600 notebook border respectively.
7601
7602 <tscreen><verb>
7603 void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
7604                                  gboolean     show_tabs);
7605
7606 void gtk_notebook_set_show_border( GtkNotebook *notebook,
7607                                    gboolean     show_border );
7608 </verb></tscreen>
7609
7610 The next function is useful when the you have a large number of pages,
7611 and the tabs don't fit on the page. It allows the tabs to be scrolled
7612 through using two arrow buttons.
7613
7614 <tscreen><verb>
7615 void gtk_notebook_set_scrollable( GtkNotebook *notebook,
7616                                   gboolean     scrollable );
7617 </verb></tscreen>
7618
7619 <tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
7620 TRUE or FALSE.
7621
7622 Now let's look at an example, it is expanded from the testgtk.c code
7623 that comes with the GTK distribution. This small program creates a
7624 window with a notebook and six buttons. The notebook contains 11
7625 pages, added in three different ways, appended, inserted, and
7626 prepended. The buttons allow you rotate the tab positions, add/remove
7627 the tabs and border, remove a page, change pages in both a forward and
7628 backward manner, and exit the program.
7629
7630 <tscreen><verb>
7631 /* example-start notebook notebook.c */
7632
7633 #include <gtk/gtk.h>
7634
7635 /* This function rotates the position of the tabs */
7636 void rotate_book( GtkButton   *button,
7637                   GtkNotebook *notebook )
7638 {
7639     gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
7640 }
7641
7642 /* Add/Remove the page tabs and the borders */
7643 void tabsborder_book( GtkButton   *button,
7644                       GtkNotebook *notebook )
7645 {
7646     gint tval = FALSE;
7647     gint bval = FALSE;
7648     if (notebook->show_tabs == 0)
7649             tval = TRUE; 
7650     if (notebook->show_border == 0)
7651             bval = TRUE;
7652     
7653     gtk_notebook_set_show_tabs (notebook, tval);
7654     gtk_notebook_set_show_border (notebook, bval);
7655 }
7656
7657 /* Remove a page from the notebook */
7658 void remove_book( GtkButton   *button,
7659                   GtkNotebook *notebook )
7660 {
7661     gint page;
7662     
7663     page = gtk_notebook_get_current_page(notebook);
7664     gtk_notebook_remove_page (notebook, page);
7665     /* Need to refresh the widget -- 
7666      This forces the widget to redraw itself. */
7667     gtk_widget_draw(GTK_WIDGET(notebook), NULL);
7668 }
7669
7670 gint delete( GtkWidget *widget,
7671              GtkWidget *event,
7672              gpointer   data )
7673 {
7674     gtk_main_quit();
7675     return(FALSE);
7676 }
7677
7678 int main( int argc,
7679           char *argv[] )
7680 {
7681     GtkWidget *window;
7682     GtkWidget *button;
7683     GtkWidget *table;
7684     GtkWidget *notebook;
7685     GtkWidget *frame;
7686     GtkWidget *label;
7687     GtkWidget *checkbutton;
7688     int i;
7689     char bufferf[32];
7690     char bufferl[32];
7691     
7692     gtk_init (&amp;argc, &amp;argv);
7693     
7694     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7695     
7696     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
7697                         GTK_SIGNAL_FUNC (delete), NULL);
7698     
7699     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7700
7701     table = gtk_table_new(3,6,FALSE);
7702     gtk_container_add (GTK_CONTAINER (window), table);
7703     
7704     /* Create a new notebook, place the position of the tabs */
7705     notebook = gtk_notebook_new ();
7706     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
7707     gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
7708     gtk_widget_show(notebook);
7709     
7710     /* Let's append a bunch of pages to the notebook */
7711     for (i=0; i < 5; i++) {
7712         sprintf(bufferf, "Append Frame %d", i+1);
7713         sprintf(bufferl, "Page %d", i+1);
7714         
7715         frame = gtk_frame_new (bufferf);
7716         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
7717         gtk_widget_set_usize (frame, 100, 75);
7718         gtk_widget_show (frame);
7719         
7720         label = gtk_label_new (bufferf);
7721         gtk_container_add (GTK_CONTAINER (frame), label);
7722         gtk_widget_show (label);
7723         
7724         label = gtk_label_new (bufferl);
7725         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
7726     }
7727       
7728     /* Now let's add a page to a specific spot */
7729     checkbutton = gtk_check_button_new_with_label ("Check me please!");
7730     gtk_widget_set_usize(checkbutton, 100, 75);
7731     gtk_widget_show (checkbutton);
7732    
7733     label = gtk_label_new ("Add page");
7734     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
7735     
7736     /* Now finally let's prepend pages to the notebook */
7737     for (i=0; i < 5; i++) {
7738         sprintf(bufferf, "Prepend Frame %d", i+1);
7739         sprintf(bufferl, "PPage %d", i+1);
7740         
7741         frame = gtk_frame_new (bufferf);
7742         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
7743         gtk_widget_set_usize (frame, 100, 75);
7744         gtk_widget_show (frame);
7745         
7746         label = gtk_label_new (bufferf);
7747         gtk_container_add (GTK_CONTAINER (frame), label);
7748         gtk_widget_show (label);
7749         
7750         label = gtk_label_new (bufferl);
7751         gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
7752     }
7753     
7754     /* Set what page to start at (page 4) */
7755     gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
7756
7757     /* Create a bunch of buttons */
7758     button = gtk_button_new_with_label ("close");
7759     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7760                                GTK_SIGNAL_FUNC (delete), NULL);
7761     gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
7762     gtk_widget_show(button);
7763     
7764     button = gtk_button_new_with_label ("next page");
7765     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7766                                (GtkSignalFunc) gtk_notebook_next_page,
7767                                GTK_OBJECT (notebook));
7768     gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
7769     gtk_widget_show(button);
7770     
7771     button = gtk_button_new_with_label ("prev page");
7772     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7773                                (GtkSignalFunc) gtk_notebook_prev_page,
7774                                GTK_OBJECT (notebook));
7775     gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
7776     gtk_widget_show(button);
7777     
7778     button = gtk_button_new_with_label ("tab position");
7779     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7780                         (GtkSignalFunc) rotate_book,
7781                         GTK_OBJECT(notebook));
7782     gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
7783     gtk_widget_show(button);
7784     
7785     button = gtk_button_new_with_label ("tabs/border on/off");
7786     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7787                         (GtkSignalFunc) tabsborder_book,
7788                         GTK_OBJECT (notebook));
7789     gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
7790     gtk_widget_show(button);
7791     
7792     button = gtk_button_new_with_label ("remove page");
7793     gtk_signal_connect (GTK_OBJECT (button), "clicked",
7794                         (GtkSignalFunc) remove_book,
7795                         GTK_OBJECT(notebook));
7796     gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
7797     gtk_widget_show(button);
7798     
7799     gtk_widget_show(table);
7800     gtk_widget_show(window);
7801     
7802     gtk_main ();
7803     
7804     return(0);
7805 }
7806 /* example-end */
7807 </verb></tscreen>
7808
7809 I hope this helps you on your way with creating notebooks for your
7810 GTK applications.
7811
7812 <!-- ***************************************************************** -->
7813 <sect>CList Widget
7814 <!-- ***************************************************************** -->
7815
7816 <!-- ----------------------------------------------------------------- -->
7817 <p>
7818 The CList widget has replaced the List widget (which is still
7819 available).
7820
7821 The CList widget is a multi-column list widget that is capable of
7822 handling literally thousands of rows of information. Each column can
7823 optionally have a title, which itself is optionally active, allowing
7824 us to bind a function to its selection.
7825
7826 <!-- ----------------------------------------------------------------- -->
7827 <sect1>Creating a CList widget
7828 <p>
7829 Creating a CList is quite straightforward, once you have learned
7830 about widgets in general. It provides the almost standard two ways,
7831 that is the hard way, and the easy way. But before we create it, there
7832 is one thing we should figure out beforehand: how many columns should
7833 it have?
7834
7835 Not all columns have to be visible and can be used to store data that
7836 is related to a certain cell in the list.
7837
7838 <tscreen><verb>
7839 GtkWidget *gtk_clist_new ( gint columns );
7840
7841 GtkWidget *gtk_clist_new_with_titles( gint   columns,
7842                                       gchar *titles[] );
7843 </verb></tscreen>
7844
7845 The first form is very straightforward, the second might require some
7846 explanation. Each column can have a title associated with it, and this
7847 title can be a label or a button that reacts when we click on it. If
7848 we use the second form, we must provide pointers to the title texts,
7849 and the number of pointers should equal the number of columns
7850 specified. Of course we can always use the first form, and manually
7851 add titles later.
7852
7853 Note: The CList widget does not have its own scrollbars and should
7854 be placed within a ScrolledWindow widget if your require this
7855 functionality. This is a change from the GTK 1.0 implementation.
7856
7857 <!-- ----------------------------------------------------------------- -->
7858 <sect1>Modes of operation
7859 <p>
7860 There are several attributes that can be used to alter the behaviour of
7861 a CList. First there is
7862
7863 <tscreen><verb>
7864 void gtk_clist_set_selection_mode( GtkCList         *clist,
7865                                    GtkSelectionMode  mode );
7866 </verb></tscreen>
7867
7868 which, as the name implies, sets the selection mode of the
7869 CList. The first argument is the CList widget, and the second
7870 specifies the cell selection mode (they are defined in gtkenums.h). At
7871 the time of this writing, the following modes are available to us:
7872
7873 <itemize>
7874 <item> <tt/GTK_SELECTION_SINGLE/ - The selection is either NULL or contains
7875 a GList pointer for a single selected item.
7876
7877 <item> <tt/GTK_SELECTION_BROWSE/ - The selection is NULL if the list
7878 contains no widgets or insensitive ones only, otherwise it contains a
7879 GList pointer for one GList structure, and therefore exactly one list
7880 item.
7881
7882 <item> <tt/GTK_SELECTION_MULTIPLE/ - The selection is NULL if no list items
7883 are selected or a GList pointer for the first selected item. That in
7884 turn points to a GList structure for the second selected item and so
7885 on. This is currently the <bf>default</bf> for the CList widget.
7886
7887 <item> <tt/GTK_SELECTION_EXTENDED/ - The selection is always NULL.
7888 </itemize>
7889
7890 Others might be added in later revisions of GTK.
7891
7892 We can also define what the border of the CList widget should look
7893 like. It is done through
7894
7895 <tscreen><verb>
7896 void gtk_clist_set_shadow_type( GtkCList      *clist,
7897                                 GtkShadowType  border );
7898 </verb></tscreen>
7899
7900 The possible values for the second argument are
7901
7902 <tscreen><verb>
7903   GTK_SHADOW_NONE
7904   GTK_SHADOW_IN
7905   GTK_SHADOW_OUT
7906   GTK_SHADOW_ETCHED_IN
7907   GTK_SHADOW_ETCHED_OUT
7908 </verb></tscreen>
7909
7910 <!-- ----------------------------------------------------------------- -->
7911 <sect1>Working with titles
7912 <p>
7913 When you create a CList widget, you will also get a set of title
7914 buttons automatically. They live in the top of the CList window, and
7915 can act either as normal buttons that respond to being pressed, or
7916 they can be passive, in which case they are nothing more than a
7917 title. There are four different calls that aid us in setting the
7918 status of the title buttons.
7919
7920 <tscreen><verb>
7921 void gtk_clist_column_title_active( GtkCList *clist,
7922                                      gint     column );
7923
7924 void gtk_clist_column_title_passive( GtkCList *clist,
7925                                      gint      column );
7926
7927 void gtk_clist_column_titles_active( GtkCList *clist );
7928
7929 void gtk_clist_column_titles_passive( GtkCList *clist );
7930 </verb></tscreen>
7931
7932 An active title is one which acts as a normal button, a passive one is
7933 just a label. The first two calls above will activate/deactivate the
7934 title button above the specific column, while the last two calls
7935 activate/deactivate all title buttons in the supplied clist widget.
7936
7937 But of course there are those cases when we don't want them at all,
7938 and so they can be hidden and shown at will using the following two
7939 calls.
7940
7941 <tscreen><verb>
7942 void gtk_clist_column_titles_show( GtkCList *clist );
7943
7944 void gtk_clist_column_titles_hide( GtkCList *clist );
7945 </verb></tscreen>
7946
7947 For titles to be really useful we need a mechanism to set and change
7948 them, and this is done using
7949
7950 <tscreen><verb>
7951 void gtk_clist_set_column_title( GtkCList *clist,
7952                                  gint      column,
7953                                  gchar    *title );
7954 </verb></tscreen>
7955
7956 Note that only the title of one column can be set at a time, so if all
7957 the titles are known from the beginning, then I really suggest using
7958 gtk_clist_new_with_titles (as described above) to set them. It saves
7959 you coding time, and makes your program smaller. There are some cases
7960 where getting the job done the manual way is better, and that's when
7961 not all titles will be text. CList provides us with title buttons
7962 that can in fact incorporate whole widgets, for example a pixmap. It's
7963 all done through
7964
7965 <tscreen><verb>
7966 void gtk_clist_set_column_widget( GtkCList  *clist,
7967                                   gint       column,
7968                                   GtkWidget *widget );
7969 </verb></tscreen>
7970
7971 which should require no special explanation.
7972
7973 <!-- ----------------------------------------------------------------- -->
7974 <sect1>Manipulating the list itself
7975 <p>
7976 It is possible to change the justification for a column, and it is
7977 done through
7978
7979 <tscreen><verb>
7980 void gtk_clist_set_column_justification( GtkCList         *clist,
7981                                          gint              column,
7982                                          GtkJustification  justification );
7983 </verb></tscreen>
7984
7985 The GtkJustification type can take the following values:
7986
7987 <itemize>
7988 <item><tt/GTK_JUSTIFY_LEFT/ - The text in the column will begin from the
7989 left edge.
7990
7991 <item><tt/GTK_JUSTIFY_RIGHT/ - The text in the column will begin from the
7992 right edge.
7993
7994 <item><tt/GTK_JUSTIFY_CENTER/ - The text is placed in the center of the
7995 column.
7996
7997 <item><tt/GTK_JUSTIFY_FILL/ - The text will use up all available space in
7998 the column. It is normally done by inserting extra blank spaces
7999 between words (or between individual letters if it's a single
8000 word). Much in the same way as any ordinary WYSIWYG text editor.
8001 </itemize>
8002
8003 The next function is a very important one, and should be standard in
8004 the setup of all CList widgets. When the list is created, the width
8005 of the various columns are chosen to match their titles, and since
8006 this is seldom the right width we have to set it using
8007
8008 <tscreen><verb>
8009 void gtk_clist_set_column_width( GtkCList *clist,
8010                                  gint      column,
8011                                  gint      width );
8012 </verb></tscreen>
8013
8014 Note that the width is given in pixels and not letters. The same goes
8015 for the height of the cells in the columns, but as the default value
8016 is the height of the current font this isn't as critical to the
8017 application. Still, it is done through
8018
8019 <tscreen><verb>
8020 void gtk_clist_set_row_height( GtkCList *clist,
8021                                gint      height );
8022 </verb></tscreen>
8023
8024 Again, note that the height is given in pixels.
8025
8026 We can also move the list around without user interaction, however, it
8027 does require that we know what we are looking for. Or in other words,
8028 we need the row and column of the item we want to scroll to.
8029
8030 <tscreen><verb>
8031 void gtk_clist_moveto( GtkCList *clist,
8032                        gint      row,
8033                        gint      column,
8034                        gfloat    row_align,
8035                        gfloat    col_align );
8036 </verb></tscreen>
8037
8038 The gfloat row_align is pretty important to understand. It's a value
8039 between 0.0 and 1.0, where 0.0 means that we should scroll the list so
8040 the row appears at the top, while if the value of row_align is 1.0,
8041 the row will appear at the bottom instead. All other values between
8042 0.0 and 1.0 are also valid and will place the row between the top and
8043 the bottom. The last argument, gfloat col_align works in the same way,
8044 though 0.0 marks left and 1.0 marks right instead.
8045
8046 Depending on the application's needs, we don't have to scroll to an
8047 item that is already visible to us. So how do we know if it is
8048 visible? As usual, there is a function to find that out as well.
8049
8050 <tscreen><verb>
8051 GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
8052                                         gint      row );
8053 </verb></tscreen>
8054
8055 The return value is is one of the following:
8056
8057 <tscreen><verb>
8058   GTK_VISIBILITY_NONE
8059   GTK_VISIBILITY_PARTIAL
8060   GTK_VISIBILITY_FULL
8061 </verb></tscreen>
8062
8063 Note that it will only tell us if a row is visible. Currently there is
8064 no way to determine this for a column. We can get partial information
8065 though, because if the return is <tt/GTK_VISIBILITY_PARTIAL/, then
8066 some of it is hidden, but we don't know if it is the row that is being
8067 cut by the lower edge of the listbox, or if the row has columns that
8068 are outside.
8069
8070 We can also change both the foreground and background colors of a
8071 particular row. This is useful for marking the row selected by the
8072 user, and the two functions that is used to do it are
8073
8074 <tscreen><verb>
8075 void gtk_clist_set_foreground( GtkCList *clist,
8076                                gint      row,
8077                                GdkColor *color );
8078
8079 void gtk_clist_set_background( GtkCList *clist,
8080                                gint      row,
8081                                GdkColor *color );
8082 </verb></tscreen>
8083
8084 Please note that the colors must have been previously allocated.
8085
8086 <!-- ----------------------------------------------------------------- -->
8087 <sect1>Adding rows to the list
8088 <p>
8089 We can add rows in three ways. They can be prepended or appended to
8090 the list using
8091
8092 <tscreen><verb>
8093 gint gtk_clist_prepend( GtkCList *clist,
8094                         gchar    *text[] );
8095
8096 gint gtk_clist_append( GtkCList *clist,
8097                        gchar    *text[] );
8098 </verb></tscreen>
8099
8100 The return value of these two functions indicate the index of the row
8101 that was just added. We can insert a row at a given place using
8102
8103 <tscreen><verb>
8104 void gtk_clist_insert( GtkCList *clist,
8105                        gint      row,
8106                        gchar    *text[] );
8107 </verb></tscreen>
8108
8109 In these calls we have to provide a collection of pointers that are
8110 the texts we want to put in the columns. The number of pointers should
8111 equal the number of columns in the list. If the text[] argument is
8112 NULL, then there will be no text in the columns of the row. This is
8113 useful, for example, if we want to add pixmaps instead (something that
8114 has to be done manually).
8115
8116 Also, please note that the numbering of both rows and columns start at 0.
8117
8118 To remove an individual row we use
8119
8120 <tscreen><verb>
8121 void gtk_clist_remove( GtkCList *clist,
8122                        gint      row );
8123 </verb></tscreen>
8124
8125 There is also a call that removes all rows in the list. This is a lot
8126 faster than calling gtk_clist_remove once for each row, which is the
8127 only alternative.
8128
8129 <tscreen><verb>
8130 void gtk_clist_clear( GtkCList *clist );
8131 </verb></tscreen>
8132
8133 There are also two convenience functions that should be used when a
8134 lot of changes have to be made to the list. This is to prevent the
8135 list flickering while being repeatedly updated, which may be highly
8136 annoying to the user. So instead it is a good idea to freeze the list,
8137 do the updates to it, and finally thaw it which causes the list to be
8138 updated on the screen.
8139
8140 <tscreen><verb>
8141 void gtk_clist_freeze( GtkCList * clist );
8142
8143 void gtk_clist_thaw( GtkCList * clist );
8144 </verb></tscreen>
8145
8146 <!-- ----------------------------------------------------------------- -->
8147 <sect1>Setting text and pixmaps in the cells
8148 <p>
8149 A cell can contain a pixmap, text or both. To set them the following
8150 functions are used.
8151
8152 <tscreen><verb>
8153 void gtk_clist_set_text( GtkCList    *clist,
8154                          gint         row,
8155                          gint         column,
8156                          const gchar *text );
8157
8158 void gtk_clist_set_pixmap( GtkCList  *clist,
8159                            gint       row,
8160                            gint       column,
8161                            GdkPixmap *pixmap,
8162                            GdkBitmap *mask );
8163
8164 void gtk_clist_set_pixtext( GtkCList  *clist,
8165                             gint       row,
8166                             gint       column,
8167                             gchar     *text,
8168                             guint8     spacing,
8169                             GdkPixmap *pixmap,
8170                             GdkBitmap *mask );
8171 </verb></tscreen>
8172
8173 It's quite straightforward. All the calls have the CList as the first
8174 argument, followed by the row and column of the cell, followed by the
8175 data to be set. The <tt/spacing/ argument in gtk_clist_set_pixtext is
8176 the number of pixels between the pixmap and the beginning of the
8177 text. In all cases the data is copied into the widget.
8178
8179 To read back the data, we instead use
8180
8181 <tscreen><verb>
8182 gint gtk_clist_get_text( GtkCList  *clist,
8183                          gint       row,
8184                          gint       column,
8185                          gchar    **text );
8186
8187 gint gtk_clist_get_pixmap( GtkCList   *clist,
8188                            gint        row,
8189                            gint        column,
8190                            GdkPixmap **pixmap,
8191                            GdkBitmap **mask );
8192
8193 gint gtk_clist_get_pixtext( GtkCList   *clist,
8194                             gint        row,
8195                             gint        column,
8196                             gchar     **text,
8197                             guint8     *spacing,
8198                             GdkPixmap **pixmap,
8199                             GdkBitmap **mask );
8200 </verb></tscreen>
8201
8202 The returned pointers are all pointers to the data stored within the
8203 widget, so the referenced data should not be modified or released. It
8204 isn't necessary to read it all back in case you aren't interested. Any
8205 of the pointers that are meant for return values (all except the
8206 clist) can be NULL. So if we want to read back only the text from a
8207 cell that is of type pixtext, then we would do the following, assuming
8208 that clist, row and column already exist:
8209
8210 <tscreen><verb>
8211 gchar *mytext;
8212
8213 gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
8214 </verb></tscreen>
8215
8216 There is one more call that is related to what's inside a cell in the
8217 clist, and that's
8218
8219 <tscreen><verb>
8220 GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
8221                                      gint      row,
8222                                      gint      column );
8223 </verb></tscreen>
8224
8225 which returns the type of data in a cell. The return value is one of
8226
8227 <tscreen><verb>
8228   GTK_CELL_EMPTY
8229   GTK_CELL_TEXT
8230   GTK_CELL_PIXMAP
8231   GTK_CELL_PIXTEXT
8232   GTK_CELL_WIDGET
8233 </verb></tscreen>
8234
8235 There is also a function that will let us set the indentation, both
8236 vertical and horizontal, of a cell. The indentation value is of type
8237 gint, given in pixels, and can be both positive and negative.
8238
8239 <tscreen><verb>
8240 void gtk_clist_set_shift( GtkCList *clist,
8241                           gint      row,
8242                           gint      column,
8243                           gint      vertical,
8244                           gint      horizontal );
8245 </verb></tscreen>
8246
8247 <!-- ----------------------------------------------------------------- -->
8248 <sect1>Storing data pointers
8249 <p>
8250 With a CList it is possible to set a data pointer for a row. This
8251 pointer will not be visible for the user, but is merely a convenience
8252 for the programmer to associate a row with a pointer to some
8253 additional data.
8254
8255 The functions should be fairly self-explanatory by now.
8256
8257 <tscreen><verb>
8258 void gtk_clist_set_row_data( GtkCList *clist,
8259                              gint      row,
8260                              gpointer  data );
8261
8262 void gtk_clist_set_row_data_full( GtkCList         *clist,
8263                                   gint              row,
8264                                   gpointer          data,
8265                                   GtkDestroyNotify  destroy );
8266
8267 gpointer gtk_clist_get_row_data( GtkCList *clist,
8268                                  gint      row );
8269
8270 gint gtk_clist_find_row_from_data( GtkCList *clist,
8271                                    gpointer  data );
8272 </verb></tscreen>
8273
8274 <!-- ----------------------------------------------------------------- -->
8275 <sect1>Working with selections
8276 <p>
8277 There are also functions available that let us force the (un)selection
8278 of a row. These are
8279
8280 <tscreen><verb>
8281 void gtk_clist_select_row( GtkCList *clist,
8282                            gint      row,
8283                            gint      column );
8284
8285 void gtk_clist_unselect_row( GtkCList *clist,
8286                              gint      row,
8287                              gint      column );
8288 </verb></tscreen>
8289
8290 And also a function that will take x and y coordinates (for example,
8291 read from the mousepointer), and map that onto the list, returning the
8292 corresponding row and column.
8293
8294 <tscreen><verb>
8295 gint gtk_clist_get_selection_info( GtkCList *clist,
8296                                    gint      x,
8297                                    gint      y,
8298                                    gint     *row,
8299                                    gint     *column );
8300 </verb></tscreen>
8301
8302 When we detect something of interest (it might be movement of the
8303 pointer, a click somewhere in the list) we can read the pointer
8304 coordinates and find out where in the list the pointer is. Cumbersome?
8305 Luckily, there is a simpler way...
8306
8307 <!-- ----------------------------------------------------------------- -->
8308 <sect1>The signals that bring it together
8309 <p>
8310 As with all other widgets, there are a few signals that can be used. The
8311 CList widget is derived from the Container widget, and so has all the
8312 same signals, but also adds the following:
8313
8314 <itemize>
8315 <item>select_row - This signal will send the following information, in
8316 order: GtkCList *clist, gint row, gint column, GtkEventButton *event
8317
8318 <item>unselect_row - When the user unselects a row, this signal is
8319 activated. It sends the same information as select_row
8320
8321 <item>click_column - Send GtkCList *clist, gint column
8322 </itemize>
8323
8324 So if we want to connect a callback to select_row, the callback
8325 function would be declared like this
8326
8327 <tscreen><verb>
8328 void select_row_callback(GtkWidget *widget,
8329                          gint row,
8330                          gint column,
8331                          GdkEventButton *event,
8332                          gpointer data);
8333 </verb></tscreen>
8334
8335 The callback is connected as usual with
8336
8337 <tscreen><verb>
8338 gtk_signal_connect(GTK_OBJECT( clist),
8339                    "select_row"
8340                    GTK_SIGNAL_FUNC(select_row_callback),
8341                    NULL);
8342 </verb></tscreen>
8343
8344 <!-- ----------------------------------------------------------------- -->
8345 <sect1>A CList example
8346 <p>
8347
8348 <tscreen><verb>
8349 /* example-start clist clist.c */
8350
8351 #include <gtk/gtk.h>
8352
8353 /* User clicked the "Add List" button. */
8354 void button_add_clicked( gpointer data )
8355 {
8356     int indx;
8357  
8358     /* Something silly to add to the list. 4 rows of 2 columns each */
8359     gchar *drink[4][2] = { { "Milk",    "3 Oz" },
8360                            { "Water",   "6 l" },
8361                            { "Carrots", "2" },
8362                            { "Snakes",  "55" } };
8363
8364     /* Here we do the actual adding of the text. It's done once for
8365      * each row.
8366      */
8367     for ( indx=0 ; indx < 4 ; indx++ )
8368         gtk_clist_append( (GtkCList *) data, drink[indx]);
8369
8370     return;
8371 }
8372
8373 /* User clicked the "Clear List" button. */
8374 void button_clear_clicked( gpointer data )
8375 {
8376     /* Clear the list using gtk_clist_clear. This is much faster than
8377      * calling gtk_clist_remove once for each row.
8378      */
8379     gtk_clist_clear( (GtkCList *) data);
8380
8381     return;
8382 }
8383
8384 /* The user clicked the "Hide/Show titles" button. */
8385 void button_hide_show_clicked( gpointer data )
8386 {
8387     /* Just a flag to remember the status. 0 = currently visible */
8388     static short int flag = 0;
8389
8390     if (flag == 0)
8391     {
8392         /* Hide the titles and set the flag to 1 */
8393         gtk_clist_column_titles_hide((GtkCList *) data);
8394         flag++;
8395     }
8396     else
8397     {
8398         /* Show the titles and reset flag to 0 */
8399         gtk_clist_column_titles_show((GtkCList *) data);
8400         flag--;
8401     }
8402
8403     return;
8404 }
8405
8406 /* If we come here, then the user has selected a row in the list. */
8407 void selection_made( GtkWidget      *clist,
8408                      gint            row,
8409                      gint            column,
8410                      GdkEventButton *event,
8411                      gpointer        data )
8412 {
8413     gchar *text;
8414
8415     /* Get the text that is stored in the selected row and column
8416      * which was clicked in. We will receive it as a pointer in the
8417      * argument text.
8418      */
8419     gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
8420
8421     /* Just prints some information about the selected row */
8422     g_print("You selected row %d. More specifically you clicked in "
8423             "column %d, and the text in this cell is %s\n\n",
8424             row, column, text);
8425
8426     return;
8427 }
8428
8429 int main( int    argc,
8430           gchar *argv[] )
8431 {                                  
8432     GtkWidget *window;
8433     GtkWidget *vbox, *hbox;
8434     GtkWidget *scrolled_window, *clist;
8435     GtkWidget *button_add, *button_clear, *button_hide_show;    
8436     gchar *titles[2] = { "Ingredients", "Amount" };
8437
8438     gtk_init(&amp;argc, &amp;argv);
8439     
8440     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
8441     gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
8442
8443     gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
8444     gtk_signal_connect(GTK_OBJECT(window),
8445                        "destroy",
8446                        GTK_SIGNAL_FUNC(gtk_main_quit),
8447                        NULL);
8448     
8449     vbox=gtk_vbox_new(FALSE, 5);
8450     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
8451     gtk_container_add(GTK_CONTAINER(window), vbox);
8452     gtk_widget_show(vbox);
8453     
8454     /* Create a scrolled window to pack the CList widget into */
8455     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
8456     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
8457                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
8458
8459     gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);
8460     gtk_widget_show (scrolled_window);
8461
8462     /* Create the CList. For this example we use 2 columns */
8463     clist = gtk_clist_new_with_titles( 2, titles);
8464
8465     /* When a selection is made, we want to know about it. The callback
8466      * used is selection_made, and its code can be found further down */
8467     gtk_signal_connect(GTK_OBJECT(clist), "select_row",
8468                        GTK_SIGNAL_FUNC(selection_made),
8469                        NULL);
8470
8471     /* It isn't necessary to shadow the border, but it looks nice :) */
8472     gtk_clist_set_shadow_type (GTK_CLIST(clist), GTK_SHADOW_OUT);
8473
8474     /* What however is important, is that we set the column widths as
8475      * they will never be right otherwise. Note that the columns are
8476      * numbered from 0 and up (to 1 in this case).
8477      */
8478     gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
8479
8480     /* Add the CList widget to the vertical box and show it. */
8481     gtk_container_add(GTK_CONTAINER(scrolled_window), clist);
8482     gtk_widget_show(clist);
8483
8484     /* Create the buttons and add them to the window. See the button
8485      * tutorial for more examples and comments on this.
8486      */
8487     hbox = gtk_hbox_new(FALSE, 0);
8488     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
8489     gtk_widget_show(hbox);
8490
8491     button_add = gtk_button_new_with_label("Add List");
8492     button_clear = gtk_button_new_with_label("Clear List");
8493     button_hide_show = gtk_button_new_with_label("Hide/Show titles");
8494
8495     gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
8496     gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
8497     gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
8498
8499     /* Connect our callbacks to the three buttons */
8500     gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
8501                               GTK_SIGNAL_FUNC(button_add_clicked),
8502                               (gpointer) clist);
8503     gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
8504                               GTK_SIGNAL_FUNC(button_clear_clicked),
8505                               (gpointer) clist);
8506     gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
8507                               GTK_SIGNAL_FUNC(button_hide_show_clicked),
8508                               (gpointer) clist);
8509
8510     gtk_widget_show(button_add);
8511     gtk_widget_show(button_clear);
8512     gtk_widget_show(button_hide_show);
8513
8514     /* The interface is completely set up so we show the window and
8515      * enter the gtk_main loop.
8516      */
8517     gtk_widget_show(window);
8518     gtk_main();
8519     
8520     return(0);
8521 }
8522 /* example-end */
8523 </verb></tscreen>
8524                     
8525 <!-- ***************************************************************** -->
8526 <sect> Tree Widget <label id="sec_Tree_Widgets">
8527 <!-- ***************************************************************** -->
8528 <p>
8529 The purpose of tree widgets is to display hierarchically-organized
8530 data. The Tree widget itself is a vertical container for widgets of
8531 type TreeItem. Tree itself is not terribly different from
8532 CList - both are derived directly from Container, and the
8533 Container methods work in the same way on Tree widgets as on
8534 CList widgets. The difference is that Tree widgets can be nested
8535 within other Tree widgets. We'll see how to do this shortly.
8536
8537 The Tree widget has its own window, and defaults to a white
8538 background, as does CList. Also, most of the Tree methods work in
8539 the same way as the corresponding CList ones. However, Tree is
8540 not derived from CList, so you cannot use them interchangeably.
8541
8542
8543 <sect1> Creating a Tree
8544 <p>
8545 A Tree is created in the usual way, using:
8546
8547 <tscreen><verb>
8548 GtkWidget *gtk_tree_new( void );
8549 </verb></tscreen>
8550
8551 Like the CList widget, a Tree will simply keep growing as more
8552 items are added to it, as well as when subtrees are expanded.  For
8553 this reason, they are almost always packed into a
8554 ScrolledWindow. You might want to use gtk_widget_set_usize() on the
8555 scrolled window to ensure that it is big enough to see the tree's
8556 items, as the default size for ScrolledWindow is quite small.
8557
8558 Now that you have a tree, you'll probably want to add some items to
8559 it.  <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
8560 explains the gory details of TreeItem. For now, it'll suffice to
8561 create one, using:
8562
8563 <tscreen><verb>
8564 GtkWidget *gtk_tree_item_new_with_label( gchar *label );
8565 </verb></tscreen>
8566
8567 You can then add it to the tree using one of the following (see
8568 <ref id="sec_Tree_Functions" name="Functions and Macros">
8569 below for more options):
8570
8571 <tscreen><verb>
8572 void gtk_tree_append( GtkTree    *tree,
8573                        GtkWidget *tree_item );
8574
8575 void gtk_tree_prepend( GtkTree   *tree,
8576                        GtkWidget *tree_item );
8577 </verb></tscreen>
8578
8579 Note that you must add items to a Tree one at a time - there is no
8580 equivalent to gtk_list_*_items().
8581
8582 <!-- ----------------------------------------------------------------- -->
8583 <sect1> Adding a Subtree
8584 <p>
8585 A subtree is created like any other Tree widget. A subtree is added
8586 to another tree beneath a tree item, using:
8587
8588 <tscreen><verb>
8589 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
8590                                 GtkWidget   *subtree );
8591 </verb></tscreen>
8592
8593 You do not need to call gtk_widget_show() on a subtree before or after
8594 adding it to a TreeItem. However, you <em>must</em> have added the
8595 TreeItem in question to a parent tree before calling
8596 gtk_tree_item_set_subtree(). This is because, technically, the parent
8597 of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
8598 rather the GtkTree which holds that GtkTreeItem.
8599
8600 When you add a subtree to a TreeItem, a plus or minus sign appears
8601 beside it, which the user can click on to "expand" or "collapse" it,
8602 meaning, to show or hide its subtree. TreeItems are collapsed by
8603 default. Note that when you collapse a TreeItem, any selected
8604 items in its subtree remain selected, which may not be what the user
8605 expects.
8606
8607 <!-- ----------------------------------------------------------------- -->
8608 <sect1> Handling the Selection List
8609 <p>
8610 As with CList, the Tree type has a <tt>selection</tt> field, and
8611 it is possible to control the behaviour of the tree (somewhat) by
8612 setting the selection type using:
8613
8614 <tscreen><verb>
8615 void gtk_tree_set_selection_mode( GtkTree          *tree,
8616                                   GtkSelectionMode  mode );
8617 </verb></tscreen>
8618
8619 The semantics associated with the various selection modes are
8620 described in the section on the CList widget. As with the CList
8621 widget, the "select_child", "unselect_child" (not really - see <ref
8622 id="sec_Tree_Signals" name="Signals"> below for an explanation),
8623 and "selection_changed" signals are emitted when list items are
8624 selected or unselected. However, in order to take advantage of these
8625 signals, you need to know <em>which</em> Tree widget they will be
8626 emitted by, and where to find the list of selected items.
8627
8628 This is a source of potential confusion. The best way to explain this
8629 is that though all Tree widgets are created equal, some are more equal
8630 than others. All Tree widgets have their own X window, and can
8631 therefore receive events such as mouse clicks (if their TreeItems or
8632 their children don't catch them first!). However, to make
8633 <tt/GTK_SELECTION_SINGLE/ and <tt/GTK_SELECTION_BROWSE/ selection
8634 types behave in a sane manner, the list of selected items is specific
8635 to the topmost Tree widget in a hierarchy, known as the "root tree".
8636
8637 Thus, accessing the <tt>selection</tt> field directly in an arbitrary
8638 Tree widget is not a good idea unless you <em>know</em> it's the root
8639 tree. Instead, use the <tt/GTK_TREE_SELECTION (Tree)/ macro, which
8640 gives the root tree's selection list as a GList pointer. Of course,
8641 this list can include items that are not in the subtree in question if
8642 the selection type is <tt/GTK_SELECTION_MULTIPLE/.
8643
8644 Finally, the "select_child" (and "unselect_child", in theory) signals
8645 are emitted by all trees, but the "selection_changed" signal is only
8646 emitted by the root tree. Consequently, if you want to handle the
8647 "select_child" signal for a tree and all its subtrees, you will have
8648 to call gtk_signal_connect() for every subtree.
8649
8650 <sect1> Tree Widget Internals
8651 <p>
8652 The Tree's struct definition looks like this:
8653
8654 <tscreen><verb>
8655 struct _GtkTree
8656 {
8657   GtkContainer container;
8658
8659   GList *children;
8660   
8661   GtkTree* root_tree; /* owner of selection list */
8662   GtkWidget* tree_owner;
8663   GList *selection;
8664   guint level;
8665   guint indent_value;
8666   guint current_indent;
8667   guint selection_mode : 2;
8668   guint view_mode : 1;
8669   guint view_line : 1;
8670 };
8671 </verb></tscreen>
8672
8673 The perils associated with accessing the <tt>selection</tt> field
8674 directly have already been mentioned. The other important fields of
8675 the struct can also be accessed with handy macros or class functions.
8676 <tt/GTK_IS_ROOT_TREE (Tree)/ returns a boolean value which
8677 indicates whether a tree is the root tree in a Tree hierarchy, while
8678 <tt/GTK_TREE_ROOT_TREE (Tree)/ returns the root tree, an object of
8679 type GtkTree (so, remember to cast it using <tt/GTK_WIDGET (Tree)/ if
8680 you want to use one of the gtk_widget_*() functions on it).
8681
8682 Instead of directly accessing the children field of a Tree widget,
8683 it's probably best to cast it using >tt/GTK_CONTAINER (Tree)/, and
8684 pass it to the gtk_container_children() function. This creates a
8685 duplicate of the original list, so it's advisable to free it up using
8686 g_list_free() after you're done with it, or to iterate on it
8687 destructively, like this:
8688
8689 <tscreen><verb>
8690     children = gtk_container_children (GTK_CONTAINER (tree));
8691     while (children) {
8692       do_something_nice (GTK_TREE_ITEM (children->data));
8693       children = g_list_remove_link (children, children);
8694 }
8695 </verb></tscreen>
8696
8697 The <tt>tree_owner</tt> field is defined only in subtrees, where it
8698 points to the TreeItem widget which holds the tree in question.
8699 The <tt>level</tt> field indicates how deeply nested a particular tree
8700 is; root trees have level 0, and each successive level of subtrees has
8701 a level one greater than the parent level. This field is set only
8702 after a Tree widget is actually mapped (i.e. drawn on the screen).
8703
8704 <sect2> Signals<label id="sec_Tree_Signals">
8705 <p>
8706 <tscreen><verb>
8707 void selection_changed( GtkTree *tree );
8708 </verb></tscreen>
8709
8710 This signal will be emitted whenever the <tt>selection</tt> field of a
8711 Tree has changed. This happens when a child of the Tree is
8712 selected or deselected.
8713
8714 <tscreen><verb>
8715 void select_child( GtkTree   *tree,
8716                    GtkWidget *child );
8717 </verb></tscreen>
8718
8719 This signal is emitted when a child of the Tree is about to get
8720 selected. This happens on calls to gtk_tree_select_item(),
8721 gtk_tree_select_child(), on <em>all</em> button presses and calls to
8722 gtk_tree_item_toggle() and gtk_item_toggle().  It may sometimes be
8723 indirectly triggered on other occasions where children get added to or
8724 removed from the Tree.
8725
8726 <tscreen><verb>
8727 void unselect_child (GtkTree   *tree,
8728                      GtkWidget *child);
8729 </verb></tscreen>
8730
8731 This signal is emitted when a child of the Tree is about to get
8732 deselected. As of GTK 1.0.4, this seems to only occur on calls to
8733 gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
8734 other occasions, but <em>not</em> when a button press deselects a
8735 child, nor on emission of the "toggle" signal by gtk_item_toggle().
8736
8737 <sect2> Functions and Macros<label id="sec_Tree_Functions">
8738 <p>
8739 <tscreen><verb>
8740 guint gtk_tree_get_type( void );
8741 </verb></tscreen>
8742
8743 Returns the "GtkTree" type identifier.
8744
8745 <tscreen><verb>
8746 GtkWidget* gtk_tree_new( void );
8747 </verb></tscreen>
8748
8749 Create a new Tree object. The new widget is returned as a pointer to a
8750 GtkWidget object. NULL is returned on failure.
8751
8752 <tscreen><verb>
8753 void gtk_tree_append( GtkTree   *tree,
8754                       GtkWidget *tree_item );
8755 </verb></tscreen>
8756
8757 Append a tree item to a Tree.
8758
8759 <tscreen><verb>
8760 void gtk_tree_prepend( GtkTree   *tree,
8761                        GtkWidget *tree_item );
8762 </verb></tscreen>
8763
8764 Prepend a tree item to a Tree.
8765
8766 <tscreen><verb>
8767 void gtk_tree_insert( GtkTree   *tree,
8768                       GtkWidget *tree_item,
8769                       gint       position );
8770 </verb></tscreen>
8771
8772 Insert a tree item into a Tree at the position in the list
8773 specified by <tt>position.</tt>
8774
8775 <tscreen><verb>
8776 void gtk_tree_remove_items( GtkTree *tree,
8777                             GList   *items );
8778 </verb></tscreen>
8779
8780 Remove a list of items (in the form of a GList *) from a Tree.
8781 Note that removing an item from a tree dereferences (and thus usually)
8782 destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
8783 subtrees in that subtree. If you want to remove only one item, you
8784 can use gtk_container_remove().
8785
8786 <tscreen><verb>
8787 void gtk_tree_clear_items( GtkTree *tree,
8788                            gint     start,
8789                            gint     end );
8790 </verb></tscreen>
8791
8792 Remove the items from position <tt>start</tt> to position <tt>end</tt>
8793 from a Tree. The same warning about dereferencing applies here, as
8794 gtk_tree_clear_items() simply constructs a list and passes it to
8795 gtk_tree_remove_items().
8796
8797 <tscreen><verb>
8798 void gtk_tree_select_item( GtkTree *tree,
8799                            gint     item );
8800 </verb></tscreen>
8801
8802 Emits the "select_item" signal for the child at position
8803 <tt>item</tt>, thus selecting the child (unless you unselect it in a
8804 signal handler).
8805
8806 <tscreen><verb>
8807 void gtk_tree_unselect_item( GtkTree *tree,
8808                              gint     item );
8809 </verb></tscreen>
8810
8811 Emits the "unselect_item" signal for the child at position
8812 <tt>item</tt>, thus unselecting the child.
8813
8814 <tscreen><verb>
8815 void gtk_tree_select_child( GtkTree   *tree,
8816                             GtkWidget *tree_item );
8817 </verb></tscreen>
8818
8819 Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
8820 selecting it.
8821
8822 <tscreen><verb>
8823 void gtk_tree_unselect_child( GtkTree   *tree,
8824                               GtkWidget *tree_item );
8825 </verb></tscreen>
8826
8827 Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
8828 thus unselecting it.
8829
8830 <tscreen><verb>
8831 gint gtk_tree_child_position( GtkTree   *tree,
8832                               GtkWidget *child );
8833 </verb></tscreen>
8834
8835 Returns the position in the tree of <tt>child</tt>, unless
8836 <tt>child</tt> is not in the tree, in which case it returns -1.
8837
8838 <tscreen><verb>
8839 void gtk_tree_set_selection_mode( GtkTree          *tree,
8840                                   GtkSelectionMode  mode );
8841 </verb></tscreen>
8842
8843 Sets the selection mode, which can be one of <tt/GTK_SELECTION_SINGLE/ (the
8844 default), <tt/GTK_SELECTION_BROWSE/, <tt/GTK_SELECTION_MULTIPLE/, or
8845 <tt/GTK_SELECTION_EXTENDED/. This is only defined for root trees, which
8846 makes sense, since the root tree "owns" the selection. Setting it for
8847 subtrees has no effect at all; the value is simply ignored.
8848
8849 <tscreen><verb>
8850 void gtk_tree_set_view_mode( GtkTree         *tree,
8851                              GtkTreeViewMode  mode ); 
8852 </verb></tscreen>
8853
8854 Sets the "view mode", which can be either <tt/GTK_TREE_VIEW_LINE/ (the
8855 default) or <tt/GTK_TREE_VIEW_ITEM/.  The view mode propagates from a
8856 tree to its subtrees, and can't be set exclusively to a subtree (this
8857 is not exactly true - see the example code comments).
8858
8859 The term "view mode" is rather ambiguous - basically, it controls the
8860 way the highlight is drawn when one of a tree's children is selected.
8861 If it's <tt/GTK_TREE_VIEW_LINE/, the entire TreeItem widget is
8862 highlighted, while for <tt/GTK_TREE_VIEW_ITEM/, only the child widget
8863 (i.e., usually the label) is highlighted.
8864
8865 <tscreen><verb>
8866 void gtk_tree_set_view_lines( GtkTree *tree,
8867                               guint    flag );
8868 </verb></tscreen>
8869
8870 Controls whether connecting lines between tree items are drawn.
8871 <tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
8872 which case they aren't.
8873
8874 <tscreen><verb>
8875 GtkTree *GTK_TREE (gpointer obj);
8876 </verb></tscreen>
8877
8878 Cast a generic pointer to "GtkTree *".
8879
8880 <tscreen><verb>
8881 GtkTreeClass *GTK_TREE_CLASS (gpointer class);
8882 </verb></tscreen>
8883
8884 Cast a generic pointer to "GtkTreeClass *".
8885
8886 <tscreen><verb>
8887 gint GTK_IS_TREE (gpointer obj);
8888 </verb></tscreen>
8889
8890 Determine if a generic pointer refers to a "GtkTree" object.
8891
8892 <tscreen><verb>
8893 gint GTK_IS_ROOT_TREE (gpointer obj)
8894 </verb></tscreen>
8895
8896 Determine if a generic pointer refers to a "GtkTree" object
8897 <em>and</em> is a root tree. Though this will accept any pointer, the
8898 results of passing it a pointer that does not refer to a Tree are
8899 undefined and possibly harmful.
8900
8901 <tscreen><verb>
8902 GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
8903 </verb></tscreen>
8904
8905 Return the root tree of a pointer to a "GtkTree" object. The above
8906 warning applies.
8907
8908 <tscreen><verb>
8909 GList *GTK_TREE_SELECTION( gpointer obj)
8910 </verb></tscreen>
8911
8912 Return the selection list of the root tree of a "GtkTree" object. The
8913 above warning applies here, too.
8914
8915 <sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
8916 <p>
8917 The TreeItem widget, like CListItem, is derived from Item,
8918 which in turn is derived from Bin.  Therefore, the item itself is a
8919 generic container holding exactly one child widget, which can be of
8920 any type. The TreeItem widget has a number of extra fields, but
8921 the only one we need be concerned with is the <tt>subtree</tt> field.
8922
8923 The definition for the TreeItem struct looks like this:
8924
8925 <tscreen><verb>
8926 struct _GtkTreeItem
8927 {
8928   GtkItem item;
8929
8930   GtkWidget *subtree;
8931   GtkWidget *pixmaps_box;
8932   GtkWidget *plus_pix_widget, *minus_pix_widget;
8933
8934   GList *pixmaps;               /* pixmap node for this items color depth */
8935
8936   guint expanded : 1;
8937 };
8938 </verb></tscreen>
8939
8940 The <tt>pixmaps_box</tt> field is an EventBox which catches clicks on
8941 the plus/minus symbol which controls expansion and collapsing. The
8942 <tt>pixmaps</tt> field points to an internal data structure. Since
8943 you can always obtain the subtree of a TreeItem in a (relatively)
8944 type-safe manner with the <tt/GTK_TREE_ITEM_SUBTREE (Item)/ macro,
8945 it's probably advisable never to touch the insides of a TreeItem
8946 unless you <em>really</em> know what you're doing.
8947
8948 Since it is directly derived from an Item it can be treated as such by
8949 using the <tt/GTK_ITEM (TreeItem)/ macro. A TreeItem usually holds a
8950 label, so the convenience function gtk_list_item_new_with_label() is
8951 provided. The same effect can be achieved using code like the
8952 following, which is actually copied verbatim from
8953 gtk_tree_item_new_with_label():
8954
8955 <tscreen><verb>
8956 tree_item = gtk_tree_item_new ();
8957 label_widget = gtk_label_new (label);
8958 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
8959
8960 gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
8961 gtk_widget_show (label_widget);
8962 </verb></tscreen>
8963
8964 As one is not forced to add a Label to a TreeItem, you could
8965 also add an HBox or an Arrow, or even a Notebook (though your
8966 app will likely be quite unpopular in this case) to the TreeItem.
8967
8968 If you remove all the items from a subtree, it will be destroyed and
8969 unparented, unless you reference it beforehand, and the TreeItem
8970 which owns it will be collapsed. So, if you want it to stick around,
8971 do something like the following:
8972
8973 <tscreen><verb>
8974 gtk_widget_ref (tree);
8975 owner = GTK_TREE(tree)->tree_owner;
8976 gtk_container_remove (GTK_CONTAINER(tree), item);
8977 if (tree->parent == NULL){
8978   gtk_tree_item_expand (GTK_TREE_ITEM(owner));
8979   gtk_tree_item_set_subtree (GTK_TREE_ITEM(owner), tree);
8980 }
8981 else
8982   gtk_widget_unref (tree);
8983 </verb></tscreen>
8984
8985 Finally, drag-n-drop <em>does</em> work with TreeItems. You just
8986 have to make sure that the TreeItem you want to make into a drag
8987 item or a drop site has not only been added to a Tree, but that
8988 each successive parent widget has a parent itself, all the way back to
8989 a toplevel or dialog window, when you call gtk_widget_dnd_drag_set()
8990 or gtk_widget_dnd_drop_set().  Otherwise, strange things will happen.
8991
8992 <sect2> Signals
8993 <p>
8994 TreeItem inherits the "select", "deselect", and "toggle" signals
8995 from Item. In addition, it adds two signals of its own, "expand"
8996 and "collapse".
8997
8998 <tscreen><verb>
8999 void select( GtkItem *tree_item );
9000 </verb></tscreen>
9001
9002 This signal is emitted when an item is about to be selected, either
9003 after it has been clicked on by the user, or when the program calls
9004 gtk_tree_item_select(), gtk_item_select(), or gtk_tree_select_child().
9005
9006 <tscreen><verb>
9007 void deselect( GtkItem *tree_item );
9008 </verb></tscreen>
9009
9010 This signal is emitted when an item is about to be unselected, either
9011 after it has been clicked on by the user, or when the program calls
9012 gtk_tree_item_deselect() or gtk_item_deselect(). In the case of
9013 TreeItems, it is also emitted by gtk_tree_unselect_child(), and
9014 sometimes gtk_tree_select_child().
9015
9016 <tscreen><verb>
9017 void toggle( GtkItem *tree_item );
9018 </verb></tscreen>
9019
9020 This signal is emitted when the program calls gtk_item_toggle().  The
9021 effect it has when emitted on a TreeItem is to call
9022 gtk_tree_select_child() (and never gtk_tree_unselect_child()) on the
9023 item's parent tree, if the item has a parent tree.  If it doesn't,
9024 then the highlight is reversed on the item.
9025
9026 <tscreen><verb>
9027 void expand( GtkTreeItem *tree_item );
9028 </verb></tscreen>
9029
9030 This signal is emitted when the tree item's subtree is about to be
9031 expanded, that is, when the user clicks on the plus sign next to the
9032 item, or when the program calls gtk_tree_item_expand().
9033
9034 <tscreen><verb>
9035 void collapse( GtkTreeItem *tree_item );
9036 </verb></tscreen>
9037
9038 This signal is emitted when the tree item's subtree is about to be
9039 collapsed, that is, when the user clicks on the minus sign next to the
9040 item, or when the program calls gtk_tree_item_collapse().
9041
9042 <sect2> Functions and Macros
9043 <p>
9044 <tscreen><verb>
9045 guint gtk_tree_item_get_type( void );
9046 </verb></tscreen>
9047
9048 Returns the "GtkTreeItem" type identifier.
9049
9050 <tscreen><verb>
9051 GtkWidget* gtk_tree_item_new( void );
9052 </verb></tscreen>
9053
9054 Create a new TreeItem object. The new widget is returned as a
9055 pointer to a GtkWidget object. NULL is returned on failure.
9056
9057 <tscreen><verb>
9058 GtkWidget* gtk_tree_item_new_with_label (gchar       *label);
9059 </verb></tscreen>
9060
9061 Create a new TreeItem object, having a single GtkLabel as the sole
9062 child. The new widget is returned as a pointer to a GtkWidget
9063 object. NULL is returned on failure.
9064
9065 <tscreen><verb>
9066 void gtk_tree_item_select( GtkTreeItem *tree_item );
9067 </verb></tscreen>
9068
9069 This function is basically a wrapper around a call to
9070 <tt>gtk_item_select (GTK_ITEM (tree_item))</tt> which will emit the
9071 select signal.
9072
9073 <tscreen><verb>
9074 void gtk_tree_item_deselect( GtkTreeItem *tree_item );
9075 </verb></tscreen>
9076
9077 This function is basically a wrapper around a call to
9078 gtk_item_deselect (GTK_ITEM (tree_item)) which will emit the deselect
9079 signal.
9080
9081 <tscreen><verb>
9082 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
9083                                 GtkWidget   *subtree );
9084 </verb></tscreen>
9085
9086 This function adds a subtree to tree_item, showing it if tree_item is
9087 expanded, or hiding it if tree_item is collapsed. Again, remember that
9088 the tree_item must have already been added to a tree for this to work.
9089
9090 <tscreen><verb>
9091 void gtk_tree_item_remove_subtree( GtkTreeItem *tree_item );
9092 </verb></tscreen>
9093
9094 This removes all of tree_item's subtree's children (thus unreferencing
9095 and destroying it, any of its children's subtrees, and so on...), then
9096 removes the subtree itself, and hides the plus/minus sign.
9097
9098 <tscreen><verb>
9099 void gtk_tree_item_expand( GtkTreeItem *tree_item );
9100 </verb></tscreen>
9101
9102 This emits the "expand" signal on tree_item, which expands it.
9103
9104 <tscreen><verb>
9105 void gtk_tree_item_collapse( GtkTreeItem *tree_item );
9106 </verb></tscreen>
9107
9108 This emits the "collapse" signal on tree_item, which collapses it.
9109
9110 <tscreen><verb>
9111 GtkTreeItem *GTK_TREE_ITEM (gpointer obj)
9112 </verb></tscreen>
9113
9114 Cast a generic pointer to "GtkTreeItem *".
9115
9116 <tscreen><verb>
9117 GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj)
9118 </verb></tscreen>
9119
9120 Cast a generic pointer to "GtkTreeItemClass".
9121
9122 <tscreen><verb>
9123 gint GTK_IS_TREE_ITEM (gpointer obj)
9124 </verb></tscreen>
9125
9126 Determine if a generic pointer refers to a "GtkTreeItem" object.
9127  
9128 <tscreen><verb>
9129 GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj)
9130 </verb></tscreen>
9131
9132 Returns a tree item's subtree (<tt/obj/ should point to a
9133 "GtkTreeItem" object).
9134
9135 <sect1> Tree Example
9136 <p>
9137 This is somewhat like the tree example in testgtk.c, but a lot less
9138 complete (although much better commented).  It puts up a window with a
9139 tree, and connects all the signals for the relevant objects, so you
9140 can see when they are emitted.
9141
9142 <tscreen><verb>
9143 /* example-start tree tree.c */
9144
9145 #include <gtk/gtk.h>
9146
9147 /* for all the GtkItem:: and GtkTreeItem:: signals */
9148 static void cb_itemsignal( GtkWidget *item,
9149                            gchar     *signame )
9150 {
9151   gchar *name;
9152   GtkLabel *label;
9153
9154   /* It's a Bin, so it has one child, which we know to be a
9155      label, so get that */
9156   label = GTK_LABEL (GTK_BIN (item)->child);
9157   /* Get the text of the label */
9158   gtk_label_get (label, &amp;name);
9159   /* Get the level of the tree which the item is in */
9160   g_print ("%s called for item %s->%p, level %d\n", signame, name,
9161            item, GTK_TREE (item->parent)->level);
9162 }
9163
9164 /* Note that this is never called */
9165 static void cb_unselect_child( GtkWidget *root_tree,
9166                                GtkWidget *child,
9167                                GtkWidget *subtree )
9168 {
9169   g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
9170            root_tree, subtree, child);
9171 }
9172
9173 /* Note that this is called every time the user clicks on an item,
9174    whether it is already selected or not. */
9175 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
9176                              GtkWidget *subtree)
9177 {
9178   g_print ("select_child called for root tree %p, subtree %p, child %p\n",
9179            root_tree, subtree, child);
9180 }
9181
9182 static void cb_selection_changed( GtkWidget *tree )
9183 {
9184   GList *i;
9185   
9186   g_print ("selection_change called for tree %p\n", tree);
9187   g_print ("selected objects are:\n");
9188
9189   i = GTK_TREE_SELECTION(tree);
9190   while (i){
9191     gchar *name;
9192     GtkLabel *label;
9193     GtkWidget *item;
9194
9195     /* Get a GtkWidget pointer from the list node */
9196     item = GTK_WIDGET (i->data);
9197     label = GTK_LABEL (GTK_BIN (item)->child);
9198     gtk_label_get (label, &amp;name);
9199     g_print ("\t%s on level %d\n", name, GTK_TREE
9200              (item->parent)->level);
9201     i = i->next;
9202   }
9203 }
9204
9205 int main( int   argc,
9206           char *argv[] )
9207 {
9208   GtkWidget *window, *scrolled_win, *tree;
9209   static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux",
9210                                "Maurice"};
9211   gint i;
9212
9213   gtk_init (&amp;argc, &amp;argv);
9214
9215   /* a generic toplevel window */
9216   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9217   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
9218                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
9219   gtk_container_set_border_width (GTK_CONTAINER(window), 5);
9220
9221   /* A generic scrolled window */
9222   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
9223   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
9224                                   GTK_POLICY_AUTOMATIC,
9225                                   GTK_POLICY_AUTOMATIC);
9226   gtk_widget_set_usize (scrolled_win, 150, 200);
9227   gtk_container_add (GTK_CONTAINER(window), scrolled_win);
9228   gtk_widget_show (scrolled_win);
9229   
9230   /* Create the root tree */
9231   tree = gtk_tree_new();
9232   g_print ("root tree is %p\n", tree);
9233   /* connect all GtkTree:: signals */
9234   gtk_signal_connect (GTK_OBJECT(tree), "select_child",
9235                       GTK_SIGNAL_FUNC(cb_select_child), tree);
9236   gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
9237                       GTK_SIGNAL_FUNC(cb_unselect_child), tree);
9238   gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
9239                       GTK_SIGNAL_FUNC(cb_selection_changed), tree);
9240   /* Add it to the scrolled window */
9241   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
9242                                          tree);
9243   /* Set the selection mode */
9244   gtk_tree_set_selection_mode (GTK_TREE(tree),
9245                                GTK_SELECTION_MULTIPLE);
9246   /* Show it */
9247   gtk_widget_show (tree);
9248
9249   for (i = 0; i < 5; i++){
9250     GtkWidget *subtree, *item;
9251     gint j;
9252
9253     /* Create a tree item */
9254     item = gtk_tree_item_new_with_label (itemnames[i]);
9255     /* Connect all GtkItem:: and GtkTreeItem:: signals */
9256     gtk_signal_connect (GTK_OBJECT(item), "select",
9257                         GTK_SIGNAL_FUNC(cb_itemsignal), "select");
9258     gtk_signal_connect (GTK_OBJECT(item), "deselect",
9259                         GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
9260     gtk_signal_connect (GTK_OBJECT(item), "toggle",
9261                         GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
9262     gtk_signal_connect (GTK_OBJECT(item), "expand",
9263                         GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
9264     gtk_signal_connect (GTK_OBJECT(item), "collapse",
9265                         GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
9266     /* Add it to the parent tree */
9267     gtk_tree_append (GTK_TREE(tree), item);
9268     /* Show it - this can be done at any time */
9269     gtk_widget_show (item);
9270     /* Create this item's subtree */
9271     subtree = gtk_tree_new();
9272     g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item,
9273              subtree);
9274
9275     /* This is still necessary if you want these signals to be called
9276        for the subtree's children.  Note that selection_change will be 
9277        signalled for the root tree regardless. */
9278     gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
9279                         GTK_SIGNAL_FUNC(cb_select_child), subtree);
9280     gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
9281                         GTK_SIGNAL_FUNC(cb_unselect_child), subtree);
9282     /* This has absolutely no effect, because it is completely ignored 
9283        in subtrees */
9284     gtk_tree_set_selection_mode (GTK_TREE(subtree),
9285                                  GTK_SELECTION_SINGLE);
9286     /* Neither does this, but for a rather different reason - the
9287        view_mode and view_line values of a tree are propagated to
9288        subtrees when they are mapped.  So, setting it later on would
9289        actually have a (somewhat unpredictable) effect */
9290     gtk_tree_set_view_mode (GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
9291     /* Set this item's subtree - note that you cannot do this until
9292        AFTER the item has been added to its parent tree! */
9293     gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subtree);
9294
9295     for (j = 0; j < 5; j++){
9296       GtkWidget *subitem;
9297
9298       /* Create a subtree item, in much the same way */
9299       subitem = gtk_tree_item_new_with_label (itemnames[j]);
9300       /* Connect all GtkItem:: and GtkTreeItem:: signals */
9301       gtk_signal_connect (GTK_OBJECT(subitem), "select",
9302                           GTK_SIGNAL_FUNC(cb_itemsignal), "select");
9303       gtk_signal_connect (GTK_OBJECT(subitem), "deselect",
9304                           GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
9305       gtk_signal_connect (GTK_OBJECT(subitem), "toggle",
9306                           GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
9307       gtk_signal_connect (GTK_OBJECT(subitem), "expand",
9308                           GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
9309       gtk_signal_connect (GTK_OBJECT(subitem), "collapse",
9310                           GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
9311       g_print ("-> -> item %s->%p\n", itemnames[j], subitem);
9312       /* Add it to its parent tree */
9313       gtk_tree_append (GTK_TREE(subtree), subitem);
9314       /* Show it */
9315       gtk_widget_show (subitem);
9316     }
9317   }
9318
9319   /* Show the window and loop endlessly */
9320   gtk_widget_show (window);
9321   gtk_main();
9322   return 0;
9323 }
9324 /* example-end */
9325 </verb></tscreen>
9326
9327 <!-- ***************************************************************** -->
9328 <sect>Menu Widget
9329 <!-- ***************************************************************** -->
9330 <p>
9331 There are two ways to create menus: there's the easy way, and there's
9332 the hard way. Both have their uses, but you can usually use the
9333 Itemfactory (the easy way). The "hard" way is to create all the menus
9334 using the calls directly. The easy way is to use the gtk_item_factory
9335 calls. This is much simpler, but there are advantages and
9336 disadvantages to each approach.
9337
9338 The Itemfactory is much easier to use, and to add new menus to,
9339 although writing a few wrapper functions to create menus using the
9340 manual method could go a long way towards usability. With the
9341 Itemfactory, it is not possible to add images or the character '/' to
9342 the menus.
9343
9344 <!-- ----------------------------------------------------------------- -->
9345 <sect1>Manual Menu Creation
9346 <p>
9347 In the true tradition of teaching, we'll show you the hard way
9348 first. <tt>:)</>
9349
9350 There are three widgets that go into making a menubar and submenus:
9351 <itemize>
9352 <item>a menu item, which is what the user wants to select, e.g.,
9353 "Save"
9354 <item>a menu, which acts as a container for the menu items, and
9355 <item>a menubar, which is a container for each of the individual
9356 menus.
9357 </itemize>
9358
9359 This is slightly complicated by the fact that menu item widgets are
9360 used for two different things. They are both the widgets that are
9361 packed into the menu, and the widget that is packed into the menubar,
9362 which, when selected, activates the menu.
9363
9364 Let's look at the functions that are used to create menus and
9365 menubars.  This first function is used to create a new menubar.
9366
9367 <tscreen>
9368 <verb>
9369 GtkWidget *gtk_menu_bar_new( void );
9370 </verb>
9371 </tscreen>
9372
9373 This rather self explanatory function creates a new menubar. You use
9374 gtk_container_add to pack this into a window, or the box_pack
9375 functions to pack it into a box - the same as buttons.
9376
9377 <tscreen><verb>
9378 GtkWidget *gtk_menu_new( void );
9379 </verb></tscreen>
9380
9381 This function returns a pointer to a new menu; it is never actually
9382 shown (with gtk_widget_show), it is just a container for the menu
9383 items. I hope this will become more clear when you look at the
9384 example below.
9385
9386 The next two calls are used to create menu items that are packed into
9387 the menu (and menubar).
9388
9389 <tscreen><verb>
9390 GtkWidget *gtk_menu_item_new( void );
9391 </verb></tscreen>
9392
9393 and
9394
9395 <tscreen><verb>
9396 GtkWidget *gtk_menu_item_new_with_label( const char *label );
9397 </verb></tscreen>
9398
9399 These calls are used to create the menu items that are to be
9400 displayed.  Remember to differentiate between a "menu" as created with
9401 gtk_menu_new and a "menu item" as created by the gtk_menu_item_new
9402 functions. The menu item will be an actual button with an associated
9403 action, whereas a menu will be a container holding menu items.
9404
9405 The gtk_menu_new_with_label and gtk_menu_new functions are just as
9406 you'd expect after reading about the buttons. One creates a new menu
9407 item with a label already packed into it, and the other just creates a
9408 blank menu item.
9409
9410 Once you've created a menu item you have to put it into a menu. This
9411 is done using the function gtk_menu_append. In order to capture when
9412 the item is selected by the user, we need to connect to the
9413 <tt/activate/ signal in the usual way. So, if we wanted to create a
9414 standard <tt/File/ menu, with the options <tt/Open/, <tt/Save/, and
9415 <tt/Quit/, the code would look something like:
9416
9417 <tscreen><verb>
9418     file_menu = gtk_menu_new ();    /* Don't need to show menus */
9419
9420     /* Create the menu items */
9421     open_item = gtk_menu_item_new_with_label ("Open");
9422     save_item = gtk_menu_item_new_with_label ("Save");
9423     quit_item = gtk_menu_item_new_with_label ("Quit");
9424
9425     /* Add them to the menu */
9426     gtk_menu_append (GTK_MENU (file_menu), open_item);
9427     gtk_menu_append (GTK_MENU (file_menu), save_item);
9428     gtk_menu_append (GTK_MENU (file_menu), quit_item);
9429
9430     /* Attach the callback functions to the activate signal */
9431     gtk_signal_connect_object (GTK_OBJECT (open_items), "activate",
9432                                GTK_SIGNAL_FUNC (menuitem_response),
9433                                (gpointer) "file.open");
9434     gtk_signal_connect_object (GTK_OBJECT (save_items), "activate",
9435                                GTK_SIGNAL_FUNC (menuitem_response),
9436                                (gpointer) "file.save");
9437
9438     /* We can attach the Quit menu item to our exit function */
9439     gtk_signal_connect_object (GTK_OBJECT (quit_items), "activate",
9440                                GTK_SIGNAL_FUNC (destroy),
9441                                (gpointer) "file.quit");
9442
9443     /* We do need to show menu items */
9444     gtk_widget_show (open_item);
9445     gtk_widget_show (save_item);
9446     gtk_widget_show (quit_item);
9447 </verb></tscreen>
9448
9449 At this point we have our menu. Now we need to create a menubar and a
9450 menu item for the <tt/File/ entry, to which we add our menu. The code
9451 looks like this:
9452
9453 <tscreen><verb>
9454     menu_bar = gtk_menu_bar_new ();
9455     gtk_container_add (GTK_CONTAINER (window), menu_bar);
9456     gtk_widget_show (menu_bar);
9457
9458     file_item = gtk_menu_item_new_with_label ("File");
9459     gtk_widget_show (file_item);
9460 </verb></tscreen>
9461
9462 Now we need to associate the menu with <tt/file_item/. This is done
9463 with the function
9464
9465 <tscreen>
9466 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
9467                                 GtkWidget   *submenu );
9468 </tscreen>
9469
9470 So, our example would continue with
9471
9472 <tscreen><verb>
9473     gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_item), file_menu);
9474 </verb></tscreen>
9475
9476 All that is left to do is to add the menu to the menubar, which is
9477 accomplished using the function
9478
9479 <tscreen>
9480 void gtk_menu_bar_append( GtkMenuBar *menu_bar,
9481                           GtkWidget  *menu_item );
9482 </tscreen>
9483
9484 which in our case looks like this:
9485
9486 <tscreen><verb>
9487     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), file_item);
9488 </verb></tscreen>
9489
9490 If we wanted the menu right justified on the menubar, such as help
9491 menus often are, we can use the following function (again on
9492 <tt/file_item/ in the current example) before attaching it to the
9493 menubar.
9494
9495 <tscreen><verb>
9496 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
9497 </verb></tscreen>
9498
9499 Here is a summary of the steps needed to create a menu bar with menus
9500 attached:
9501
9502 <itemize>
9503 <item> Create a new menu using gtk_menu_new()
9504 <item> Use multiple calls to gtk_menu_item_new() for each item you
9505 wish to have on your menu. And use gtk_menu_append() to put each of
9506 these new items on to the menu.
9507 <item> Create a menu item using gtk_menu_item_new(). This will be the
9508 root of the menu, the text appearing here will be on the menubar
9509 itself.
9510 <item>Use gtk_menu_item_set_submenu() to attach the menu to the root
9511 menu item (the one created in the above step).
9512 <item> Create a new menubar using gtk_menu_bar_new. This step only
9513 needs to be done once when creating a series of menus on one menu bar.
9514 <item> Use gtk_menu_bar_append() to put the root menu onto the menubar.
9515 </itemize>
9516
9517 Creating a popup menu is nearly the same. The difference is that the
9518 menu is not posted "automatically" by a menubar, but explicitly by
9519 calling the function gtk_menu_popup() from a button-press event, for
9520 example.  Take these steps:
9521
9522 <itemize>
9523 <item>Create an event handling function. It needs to have the
9524 prototype
9525 <tscreen>
9526 static gint handler (GtkWidget *widget,
9527                      GdkEvent  *event);
9528 </tscreen>
9529 and it will use the event to find out where to pop up the menu.
9530 <item>In the event handler, if the event is a mouse button press,
9531 treat <tt>event</tt> as a button event (which it is) and use it as
9532 shown in the sample code to pass information to gtk_menu_popup().
9533 <item>Bind that event handler to a widget with
9534 <tscreen>
9535     gtk_signal_connect_object (GTK_OBJECT (widget), "event",
9536                                GTK_SIGNAL_FUNC (handler),
9537                                GTK_OBJECT (menu));
9538 </tscreen>
9539 where <tt>widget</tt> is the widget you are binding to,
9540 <tt>handler</tt> is the handling function, and <tt>menu</tt> is a menu
9541 created with gtk_menu_new(). This can be a menu which is also posted
9542 by a menu bar, as shown in the sample code.
9543 </itemize>
9544
9545 <!-- ----------------------------------------------------------------- -->
9546 <sect1>Manual Menu Example
9547 <p>
9548 That should about do it. Let's take a look at an example to help clarify.
9549
9550 <tscreen><verb>
9551 /* example-start menu menu.c */
9552
9553 #include <gtk/gtk.h>
9554
9555 static gint button_press (GtkWidget *, GdkEvent *);
9556 static void menuitem_response (gchar *);
9557
9558 int main( int   argc,
9559           char *argv[] )
9560 {
9561
9562     GtkWidget *window;
9563     GtkWidget *menu;
9564     GtkWidget *menu_bar;
9565     GtkWidget *root_menu;
9566     GtkWidget *menu_items;
9567     GtkWidget *vbox;
9568     GtkWidget *button;
9569     char buf[128];
9570     int i;
9571
9572     gtk_init (&amp;argc, &amp;argv);
9573
9574     /* create a new window */
9575     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9576     gtk_widget_set_usize (GTK_WIDGET (window), 200, 100);
9577     gtk_window_set_title (GTK_WINDOW (window), "GTK Menu Test");
9578     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
9579                         (GtkSignalFunc) gtk_main_quit, NULL);
9580
9581     /* Init the menu-widget, and remember -- never
9582      * gtk_show_widget() the menu widget!! 
9583      * This is the menu that holds the menu items, the one that
9584      * will pop up when you click on the "Root Menu" in the app */
9585     menu = gtk_menu_new ();
9586
9587     /* Next we make a little loop that makes three menu-entries for "test-menu".
9588      * Notice the call to gtk_menu_append.  Here we are adding a list of
9589      * menu items to our menu.  Normally, we'd also catch the "clicked"
9590      * signal on each of the menu items and setup a callback for it,
9591      * but it's omitted here to save space. */
9592
9593     for (i = 0; i < 3; i++)
9594         {
9595             /* Copy the names to the buf. */
9596             sprintf (buf, "Test-undermenu - %d", i);
9597
9598             /* Create a new menu-item with a name... */
9599             menu_items = gtk_menu_item_new_with_label (buf);
9600
9601             /* ...and add it to the menu. */
9602             gtk_menu_append (GTK_MENU (menu), menu_items);
9603
9604             /* Do something interesting when the menuitem is selected */
9605             gtk_signal_connect_object (GTK_OBJECT (menu_items), "activate",
9606                 GTK_SIGNAL_FUNC (menuitem_response), (gpointer) g_strdup (buf));
9607
9608             /* Show the widget */
9609             gtk_widget_show (menu_items);
9610         }
9611
9612     /* This is the root menu, and will be the label
9613      * displayed on the menu bar.  There won't be a signal handler attached,
9614      * as it only pops up the rest of the menu when pressed. */
9615     root_menu = gtk_menu_item_new_with_label ("Root Menu");
9616
9617     gtk_widget_show (root_menu);
9618
9619     /* Now we specify that we want our newly created "menu" to be the menu
9620      * for the "root menu" */
9621     gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu);
9622
9623     /* A vbox to put a menu and a button in: */
9624     vbox = gtk_vbox_new (FALSE, 0);
9625     gtk_container_add (GTK_CONTAINER (window), vbox);
9626     gtk_widget_show (vbox);
9627
9628     /* Create a menu-bar to hold the menus and add it to our main window */
9629     menu_bar = gtk_menu_bar_new ();
9630     gtk_box_pack_start (GTK_BOX (vbox), menu_bar, FALSE, FALSE, 2);
9631     gtk_widget_show (menu_bar);
9632
9633     /* Create a button to which to attach menu as a popup */
9634     button = gtk_button_new_with_label ("press me");
9635     gtk_signal_connect_object (GTK_OBJECT (button), "event",
9636         GTK_SIGNAL_FUNC (button_press), GTK_OBJECT (menu));
9637     gtk_box_pack_end (GTK_BOX (vbox), button, TRUE, TRUE, 2);
9638     gtk_widget_show (button);
9639
9640     /* And finally we append the menu-item to the menu-bar -- this is the
9641      * "root" menu-item I have been raving about =) */
9642     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), root_menu);
9643
9644     /* always display the window as the last step so it all splashes on
9645      * the screen at once. */
9646     gtk_widget_show (window);
9647
9648     gtk_main ();
9649
9650     return(0);
9651 }
9652
9653 /* Respond to a button-press by posting a menu passed in as widget.
9654  *
9655  * Note that the "widget" argument is the menu being posted, NOT
9656  * the button that was pressed.
9657  */
9658
9659 static gint button_press( GtkWidget *widget,
9660                           GdkEvent *event )
9661 {
9662
9663     if (event->type == GDK_BUTTON_PRESS) {
9664         GdkEventButton *bevent = (GdkEventButton *) event; 
9665         gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
9666                         bevent->button, bevent->time);
9667         /* Tell calling code that we have handled this event; the buck
9668          * stops here. */
9669         return TRUE;
9670     }
9671
9672     /* Tell calling code that we have not handled this event; pass it on. */
9673     return FALSE;
9674 }
9675
9676
9677 /* Print a string when a menu item is selected */
9678
9679 static void menuitem_response( gchar *string )
9680 {
9681     printf ("%s\n", string);
9682 }
9683 /* example-end */
9684 </verb></tscreen>
9685
9686 You may also set a menu item to be insensitive and, using an accelerator
9687 table, bind keys to menu functions.
9688
9689 <!-- ----------------------------------------------------------------- -->
9690 <sect1>Using ItemFactory
9691 <p>
9692 Now that we've shown you the hard way, here's how you do it using the
9693 gtk_item_factory calls.
9694
9695 <!-- ----------------------------------------------------------------- -->
9696 <sect1>Item Factory Example
9697 <p>
9698 Here is an example using the GTK item factory.
9699
9700 <tscreen><verb>
9701 /* example-start menu itemfactory.c */
9702
9703 #include <gtk/gtk.h>
9704 #include <strings.h>
9705
9706 /* Obligatory basic callback */
9707 static void print_hello( GtkWidget *w,
9708                          gpointer   data )
9709 {
9710   g_message ("Hello, World!\n");
9711 }
9712
9713 /* This is the GtkItemFactoryEntry structure used to generate new menus.
9714    Item 1: The menu path. The letter after the underscore indicates an
9715            accelerator key once the menu is open.
9716    Item 2: The accelerator key for the entry
9717    Item 3: The callback function.
9718    Item 4: The callback action.  This changes the parameters with
9719            which the function is called.  The default is 0.
9720    Item 5: The item type, used to define what kind of an item it is.
9721            Here are the possible values:
9722
9723            NULL               -> "<Item>"
9724            ""                 -> "<Item>"
9725            "<Title>"          -> create a title item
9726            "<Item>"           -> create a simple item
9727            "<CheckItem>"      -> create a check item
9728            "<ToggleItem>"     -> create a toggle item
9729            "<RadioItem>"      -> create a radio item
9730            <path>             -> path of a radio item to link against
9731            "<Separator>"      -> create a separator
9732            "<Branch>"         -> create an item to hold sub items (optional)
9733            "<LastBranch>"     -> create a right justified branch 
9734 */
9735
9736 static GtkItemFactoryEntry menu_items[] = {
9737   { "/_File",         NULL,         NULL, 0, "<Branch>" },
9738   { "/File/_New",     "<control>N", print_hello, 0, NULL },
9739   { "/File/_Open",    "<control>O", print_hello, 0, NULL },
9740   { "/File/_Save",    "<control>S", print_hello, 0, NULL },
9741   { "/File/Save _As", NULL,         NULL, 0, NULL },
9742   { "/File/sep1",     NULL,         NULL, 0, "<Separator>" },
9743   { "/File/Quit",     "<control>Q", gtk_main_quit, 0, NULL },
9744   { "/_Options",      NULL,         NULL, 0, "<Branch>" },
9745   { "/Options/Test",  NULL,         NULL, 0, NULL },
9746   { "/_Help",         NULL,         NULL, 0, "<LastBranch>" },
9747   { "/_Help/About",   NULL,         NULL, 0, NULL },
9748 };
9749
9750
9751 void get_main_menu( GtkWidget  *window,
9752                     GtkWidget **menubar )
9753 {
9754   GtkItemFactory *item_factory;
9755   GtkAccelGroup *accel_group;
9756   gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
9757
9758   accel_group = gtk_accel_group_new ();
9759
9760   /* This function initializes the item factory.
9761      Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
9762               or GTK_TYPE_OPTION_MENU.
9763      Param 2: The path of the menu.
9764      Param 3: A pointer to a gtk_accel_group.  The item factory sets up
9765               the accelerator table while generating menus.
9766   */
9767
9768   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", 
9769                                        accel_group);
9770
9771   /* This function generates the menu items. Pass the item factory,
9772      the number of items in the array, the array itself, and any
9773      callback data for the the menu items. */
9774   gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
9775
9776   /* Attach the new accelerator group to the window. */
9777   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
9778
9779   if (menubar)
9780     /* Finally, return the actual menu bar created by the item factory. */ 
9781     *menubar = gtk_item_factory_get_widget (item_factory, "<main>");
9782 }
9783
9784 int main( int argc,
9785           char *argv[] )
9786 {
9787   GtkWidget *window;
9788   GtkWidget *main_vbox;
9789   GtkWidget *menubar;
9790   
9791   gtk_init (&amp;argc, &amp;argv);
9792   
9793   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9794   gtk_signal_connect (GTK_OBJECT (window), "destroy", 
9795                       GTK_SIGNAL_FUNC (gtk_main_quit), 
9796                       "WM destroy");
9797   gtk_window_set_title (GTK_WINDOW(window), "Item Factory");
9798   gtk_widget_set_usize (GTK_WIDGET(window), 300, 200);
9799   
9800   main_vbox = gtk_vbox_new (FALSE, 1);
9801   gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
9802   gtk_container_add (GTK_CONTAINER (window), main_vbox);
9803   gtk_widget_show (main_vbox);
9804   
9805   get_main_menu (window, &amp;menubar);
9806   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
9807   gtk_widget_show (menubar);
9808   
9809   gtk_widget_show (window);
9810   gtk_main ();
9811   
9812   return(0);
9813 }
9814 /* example-end */
9815 </verb></tscreen>
9816
9817
9818 For now, there's only this example. An explanation and lots 'o' comments
9819 will follow later.
9820
9821 <!-- ***************************************************************** -->
9822 <sect> Text Widget
9823 <!-- ***************************************************************** -->
9824 <p>
9825 The Text widget allows multiple lines of text to be displayed and
9826 edited. It supports both multi-colored and multi-font text, allowing
9827 them to be mixed in any way we wish. It also has a wide set of key
9828 based text editing commands, which are compatible with Emacs.
9829
9830 The text widget supports full cut-and-paste facilities, including the
9831 use of double- and triple-click to select a word and a whole line,
9832 respectively.
9833
9834 <!-- ----------------------------------------------------------------- -->
9835 <sect1>Creating and Configuring a Text box
9836 <p>
9837 There is only one function for creating a new Text widget.
9838
9839 <tscreen><verb>
9840 GtkWidget *gtk_text_new( GtkAdjustment *hadj,
9841                          GtkAdjustment *vadj );
9842 </verb></tscreen>
9843
9844 The arguments allow us to give the Text widget pointers to Adjustments
9845 that can be used to track the viewing position of the widget. Passing
9846 NULL values to either or both of these arguments will cause the
9847 gtk_text_new function to create its own.
9848
9849 <tscreen><verb>
9850 void gtk_text_set_adjustments( GtkText       *text,
9851                                GtkAdjustment *hadj,
9852                                GtkAdjustment *vadj );
9853 </verb></tscreen>
9854
9855 The above function allows the horizontal and vertical adjustments of a
9856 text widget to be changed at any time.
9857
9858 The text widget will not automatically create its own scrollbars when
9859 the amount of text to be displayed is too long for the display
9860 window. We therefore have to create and add them to the display layout
9861 ourselves.
9862
9863 <tscreen><verb>
9864   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
9865   gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
9866   gtk_widget_show (vscrollbar);
9867 </verb></tscreen>
9868
9869 The above code snippet creates a new vertical scrollbar, and attaches
9870 it to the vertical adjustment of the text widget, <tt/text/. It then
9871 packs it into a box in the normal way.
9872
9873 Note, currently the Text widget does not support horizontal
9874 scrollbars.
9875
9876 There are two main ways in which a Text widget can be used: to allow
9877 the user to edit a body of text, or to allow us to display multiple
9878 lines of text to the user. In order for us to switch between these
9879 modes of operation, the text widget has the following function:
9880
9881 <tscreen><verb>
9882 void gtk_text_set_editable( GtkText *text,
9883                             gint     editable );
9884 </verb></tscreen>
9885
9886 The <tt/editable/ argument is a TRUE or FALSE value that specifies
9887 whether the user is permitted to edit the contents of the Text
9888 widget. When the text widget is editable, it will display a cursor at
9889 the current insertion point.
9890
9891 You are not, however, restricted to just using the text widget in
9892 these two modes. You can toggle the editable state of the text widget
9893 at any time, and can insert text at any time.
9894
9895 The text widget wraps lines of text that are too long to fit onto a
9896 single line of the display window. Its default behaviour is to break
9897 words across line breaks. This can be changed using the next function:
9898
9899 <tscreen><verb>
9900 void gtk_text_set_word_wrap( GtkText *text,
9901                              gint     word_wrap );
9902 </verb></tscreen>
9903
9904 Using this function allows us to specify that the text widget should
9905 wrap long lines on word boundaries. The <tt/word_wrap/ argument is a
9906 TRUE or FALSE value.
9907
9908 <!-- ----------------------------------------------------------------- -->
9909 <sect1>Text Manipulation
9910 <P>
9911 The current insertion point of a Text widget can be set using
9912 <tscreen><verb>
9913 void gtk_text_set_point( GtkText *text,
9914                          guint    index );
9915 </verb></tscreen>
9916
9917 where <tt/index/ is the position to set the insertion point.
9918
9919 Analogous to this is the function for getting the current insertion
9920 point:
9921
9922 <tscreen><verb>
9923 guint gtk_text_get_point( GtkText *text );
9924 </verb></tscreen>
9925
9926 A function that is useful in combination with the above two functions
9927 is
9928
9929 <tscreen><verb>
9930 guint gtk_text_get_length( GtkText *text );
9931 </verb></tscreen>
9932
9933 which returns the current length of the Text widget. The length is the
9934 number of characters that are within the text block of the widget,
9935 including characters such as newline, which marks the end of
9936 lines.
9937
9938 In order to insert text at the current insertion point of a Text
9939 widget, the function gtk_text_insert is used, which also allows us to
9940 specify background and foreground colors and a font for the text.
9941
9942 <tscreen><verb>
9943 void gtk_text_insert( GtkText    *text,
9944                       GdkFont    *font,
9945                       GdkColor   *fore,
9946                       GdkColor   *back,
9947                       const char *chars,
9948                       gint        length );
9949 </verb></tscreen>
9950
9951 Passing a value of <tt/NULL/ in as the value for the foreground color,
9952 background color or font will result in the values set within the
9953 widget style to be used. Using a value of <tt/-1/ for the length
9954 parameter will result in the whole of the text string given being
9955 inserted.
9956
9957 The text widget is one of the few within GTK that redraws itself
9958 dynamically, outside of the gtk_main function. This means that all
9959 changes to the contents of the text widget take effect
9960 immediately. This may be undesirable when performing multiple changes
9961 to the text widget. In order to allow us to perform multiple updates
9962 to the text widget without it continuously redrawing, we can freeze
9963 the widget, which temporarily stops it from automatically redrawing
9964 itself every time it is changed. We can then thaw the widget after our
9965 updates are complete.
9966
9967 The following two functions perform this freeze and thaw action:
9968
9969 <tscreen><verb>
9970 void gtk_text_freeze( GtkText *text );
9971
9972 void gtk_text_thaw( GtkText *text );         
9973 </verb></tscreen>
9974
9975 Text is deleted from the text widget relative to the current insertion
9976 point by the following two functions. The return value is a TRUE or
9977 FALSE indicator of whether the operation was successful.
9978
9979 <tscreen><verb>
9980 gint gtk_text_backward_delete( GtkText *text,
9981                                guint    nchars );
9982
9983 gint gtk_text_forward_delete ( GtkText *text,
9984                                guint    nchars );
9985 </verb></tscreen>
9986
9987 If you want to retrieve the contents of the text widget, then the
9988 macro <tt/GTK_TEXT_INDEX(t, index)/ allows you to retrieve the
9989 character at position <tt/index/ within the text widget <tt/t/.
9990
9991 To retrieve larger blocks of text, we can use the function
9992
9993 <tscreen><verb>
9994 gchar *gtk_editable_get_chars( GtkEditable *editable,
9995                                gint         start_pos,
9996                                gint         end_pos );   
9997 </verb></tscreen>
9998
9999 This is a function of the parent class of the text widget. A value of
10000 -1 as <tt/end_pos/ signifies the end of the text. The index of the
10001 text starts at 0.
10002
10003 The function allocates a new chunk of memory for the text block, so
10004 don't forget to free it with a call to g_free when you have finished
10005 with it.
10006  
10007 <!-- ----------------------------------------------------------------- -->
10008 <sect1>Keyboard Shortcuts
10009 <p>
10010 The text widget has a number of pre-installed keyboard shortcuts for
10011 common editing, motion and selection functions. These are accessed
10012 using Control and Alt key combinations.
10013
10014 In addition to these, holding down the Control key whilst using cursor
10015 key movement will move the cursor by words rather than
10016 characters. Holding down Shift whilst using cursor movement will
10017 extend the selection.
10018
10019 <sect2>Motion Shortcuts
10020 <p>
10021 <itemize>
10022 <item> Ctrl-A   Beginning of line
10023 <item> Ctrl-E   End of line
10024 <item> Ctrl-N   Next Line
10025 <item> Ctrl-P   Previous Line
10026 <item> Ctrl-B   Backward one character
10027 <item> Ctrl-F   Forward one character
10028 <item> Alt-B    Backward one word
10029 <item> Alt-F    Forward one word
10030 </itemize>
10031
10032 <sect2>Editing Shortcuts
10033 <p>
10034 <itemize>
10035 <item> Ctrl-H   Delete Backward Character (Backspace)
10036 <item> Ctrl-D   Delete Forward Character (Delete)
10037 <item> Ctrl-W   Delete Backward Word
10038 <item> Alt-D    Delete Forward Word
10039 <item> Ctrl-K   Delete to end of line
10040 <item> Ctrl-U   Delete line
10041 </itemize>
10042
10043 <sect2>Selection Shortcuts
10044 <p>
10045 <itemize>
10046 <item> Ctrl-X   Cut to clipboard
10047 <item> Ctrl-C   Copy to clipboard
10048 <item> Ctrl-V   Paste from clipboard
10049 </itemize>
10050
10051 <!-- ----------------------------------------------------------------- -->
10052 <sect1>A GtkText Example
10053 <p>
10054 <tscreen><verb>
10055 /* example-start text text.c */
10056
10057 /* text.c */
10058
10059 #include <stdio.h>
10060 #include <gtk/gtk.h>
10061
10062 void text_toggle_editable (GtkWidget *checkbutton,
10063                            GtkWidget *text)
10064 {
10065   gtk_text_set_editable(GTK_TEXT(text),
10066                         GTK_TOGGLE_BUTTON(checkbutton)->active);
10067 }
10068
10069 void text_toggle_word_wrap (GtkWidget *checkbutton,
10070                             GtkWidget *text)
10071 {
10072   gtk_text_set_word_wrap(GTK_TEXT(text),
10073                          GTK_TOGGLE_BUTTON(checkbutton)->active);
10074 }
10075
10076 void close_application( GtkWidget *widget,
10077                         gpointer   data )
10078 {
10079        gtk_main_quit();
10080 }
10081
10082 int main( int argc,
10083           char *argv[] )
10084 {
10085   GtkWidget *window;
10086   GtkWidget *box1;
10087   GtkWidget *box2;
10088   GtkWidget *hbox;
10089   GtkWidget *button;
10090   GtkWidget *check;
10091   GtkWidget *separator;
10092   GtkWidget *table;
10093   GtkWidget *vscrollbar;
10094   GtkWidget *text;
10095   GdkColormap *cmap;
10096   GdkColor color;
10097   GdkFont *fixed_font;
10098
10099   FILE *infile;
10100
10101   gtk_init (&amp;argc, &amp;argv);
10102  
10103   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10104   gtk_widget_set_usize (window, 600, 500);
10105   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);  
10106   gtk_signal_connect (GTK_OBJECT (window), "destroy",
10107                       GTK_SIGNAL_FUNC(close_application),
10108                       NULL);
10109   gtk_window_set_title (GTK_WINDOW (window), "Text Widget Example");
10110   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10111   
10112   
10113   box1 = gtk_vbox_new (FALSE, 0);
10114   gtk_container_add (GTK_CONTAINER (window), box1);
10115   gtk_widget_show (box1);
10116   
10117   
10118   box2 = gtk_vbox_new (FALSE, 10);
10119   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10120   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
10121   gtk_widget_show (box2);
10122   
10123   
10124   table = gtk_table_new (2, 2, FALSE);
10125   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
10126   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
10127   gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
10128   gtk_widget_show (table);
10129   
10130   /* Create the GtkText widget */
10131   text = gtk_text_new (NULL, NULL);
10132   gtk_text_set_editable (GTK_TEXT (text), TRUE);
10133   gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
10134                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
10135                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
10136   gtk_widget_show (text);
10137
10138   /* Add a vertical scrollbar to the GtkText widget */
10139   vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
10140   gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
10141                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
10142   gtk_widget_show (vscrollbar);
10143
10144   /* Get the system color map and allocate the color red */
10145   cmap = gdk_colormap_get_system();
10146   color.red = 0xffff;
10147   color.green = 0;
10148   color.blue = 0;
10149   if (!gdk_color_alloc(cmap, &amp;color)) {
10150     g_error("couldn't allocate color");
10151   }
10152
10153   /* Load a fixed font */
10154   fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");
10155
10156   /* Realizing a widget creates a window for it,
10157    * ready for us to insert some text */
10158   gtk_widget_realize (text);
10159
10160   /* Freeze the text widget, ready for multiple updates */
10161   gtk_text_freeze (GTK_TEXT (text));
10162   
10163   /* Insert some colored text */
10164   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
10165                    "Supports ", -1);
10166   gtk_text_insert (GTK_TEXT (text), NULL, &amp;color, NULL,
10167                    "colored ", -1);
10168   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
10169                    "text and different ", -1);
10170   gtk_text_insert (GTK_TEXT (text), fixed_font, &amp;text->style->black, NULL,
10171                    "fonts\n\n", -1);
10172   
10173   /* Load the file text.c into the text window */
10174
10175   infile = fopen("text.c", "r");
10176   
10177   if (infile) {
10178     char buffer[1024];
10179     int nchars;
10180     
10181     while (1)
10182       {
10183         nchars = fread(buffer, 1, 1024, infile);
10184         gtk_text_insert (GTK_TEXT (text), fixed_font, NULL,
10185                          NULL, buffer, nchars);
10186         
10187         if (nchars < 1024)
10188           break;
10189       }
10190     
10191     fclose (infile);
10192   }
10193
10194   /* Thaw the text widget, allowing the updates to become visible */  
10195   gtk_text_thaw (GTK_TEXT (text));
10196   
10197   hbox = gtk_hbutton_box_new ();
10198   gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
10199   gtk_widget_show (hbox);
10200
10201   check = gtk_check_button_new_with_label("Editable");
10202   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
10203   gtk_signal_connect (GTK_OBJECT(check), "toggled",
10204                       GTK_SIGNAL_FUNC(text_toggle_editable), text);
10205   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
10206   gtk_widget_show (check);
10207   check = gtk_check_button_new_with_label("Wrap Words");
10208   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
10209   gtk_signal_connect (GTK_OBJECT(check), "toggled",
10210                       GTK_SIGNAL_FUNC(text_toggle_word_wrap), text);
10211   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
10212   gtk_widget_show (check);
10213
10214   separator = gtk_hseparator_new ();
10215   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10216   gtk_widget_show (separator);
10217
10218   box2 = gtk_vbox_new (FALSE, 10);
10219   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10220   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10221   gtk_widget_show (box2);
10222   
10223   button = gtk_button_new_with_label ("close");
10224   gtk_signal_connect (GTK_OBJECT (button), "clicked",
10225                       GTK_SIGNAL_FUNC(close_application),
10226                       NULL);
10227   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10228   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
10229   gtk_widget_grab_default (button);
10230   gtk_widget_show (button);
10231
10232   gtk_widget_show (window);
10233
10234   gtk_main ();
10235   
10236   return(0);       
10237 }
10238 /* example-end */
10239 </verb></tscreen>
10240
10241
10242 <!-- ***************************************************************** -->
10243 <sect> Undocumented Widgets
10244 <!-- ***************************************************************** -->
10245 <p>
10246 These all require authors! :) Please consider contributing to our
10247 tutorial.
10248
10249 If you must use one of these widgets that are undocumented, I strongly
10250 suggest you take a look at their respective header files in the GTK
10251 distribution. GTK's function names are very descriptive. Once you
10252 have an understanding of how things work, it's not difficult to figure
10253 out how to use a widget simply by looking at its function
10254 declarations. This, along with a few examples from others' code, and
10255 it should be no problem.
10256
10257 When you do come to understand all the functions of a new undocumented
10258 widget, please consider writing a tutorial on it so others may benefit
10259 from your time.
10260
10261 <!-- ----------------------------------------------------------------- -->
10262 <sect1> Calendar
10263 <p>
10264 <!-- ----------------------------------------------------------------- -->
10265 <sect1> CTree
10266 <p>
10267 <!-- ----------------------------------------------------------------- -->
10268 <sect1> Curves
10269 <p>
10270 <!-- ----------------------------------------------------------------- -->
10271 <sect1> Drawing Area
10272 <p>
10273 <!-- ----------------------------------------------------------------- -->
10274 <sect1> Font Selection Dialog
10275 <p>
10276 <!-- ----------------------------------------------------------------- -->
10277 <sect1> Gamma Curve
10278 <p>
10279 <!-- ----------------------------------------------------------------- -->
10280 <sect1> Image
10281 <p>
10282 <!-- ----------------------------------------------------------------- -->
10283 <sect1> Packer
10284 <p>
10285 <!-- ----------------------------------------------------------------- -->
10286 <sect1> Plugs and Sockets
10287 <p>
10288 <!-- ----------------------------------------------------------------- -->
10289 <sect1> Preview
10290 <p>
10291
10292 <!--
10293
10294 (This may need to be rewritten to follow the style of the rest of the tutorial)
10295
10296 <tscreen><verb>
10297
10298 Previews serve a number of purposes in GIMP/GTK. The most important one is
10299 this. High quality images may take up to tens of megabytes of memory - easily!
10300 Any operation on an image that big is bound to take a long time. If it takes
10301 you 5-10 trial-and-errors (i.e., 10-20 steps, since you have to revert after
10302 you make an error) to choose the desired modification, it make take you
10303 literally hours to make the right one - if you don't run out of memory
10304 first. People who have spent hours in color darkrooms know the feeling.
10305 Previews to the rescue!
10306
10307 But the annoyance of the delay is not the only issue. Oftentimes it is
10308 helpful to compare the Before and After versions side-by-side or at least
10309 back-to-back. If you're working with big images and 10 second delays,
10310 obtaining the Before and After impressions is, to say the least, difficult.
10311 For 30M images (4"x6", 600dpi, 24 bit) the side-by-side comparison is right
10312 out for most people, while back-to-back is more like back-to-1001, 1002,
10313 ..., 1010-back! Previews to the rescue!
10314
10315 But there's more. Previews allow for side-by-side pre-previews. In other
10316 words, you write a plug-in (e.g., the filterpack simulation) which would have
10317 a number of here's-what-it-would-look-like-if-you-were-to-do-this previews.
10318 An approach like this acts as a sort of a preview palette and is very
10319 effective for subtle changes. Let's go previews!
10320
10321 There's more. For certain plug-ins real-time image-specific human
10322 intervention maybe necessary. In the SuperNova plug-in, for example, the
10323 user is asked to enter the coordinates of the center of the future
10324 supernova. The easiest way to do this, really, is to present the user with a
10325 preview and ask him to interactively select the spot. Let's go previews!
10326
10327 Finally, a couple of misc uses. One can use previews even when not working
10328 with big images. For example, they are useful when rendering complicated
10329 patterns. (Just check out the venerable Diffraction plug-in + many other
10330 ones!) As another example, take a look at the colormap rotation plug-in
10331 (work in progress). You can also use previews for little logos inside you
10332 plug-ins and even for an image of yourself, The Author. Let's go previews!
10333
10334 When Not to Use Previews
10335
10336 Don't use previews for graphs, drawing, etc. GDK is much faster for that. Use
10337 previews only for rendered images!
10338
10339 Let's go previews!
10340
10341 You can stick a preview into just about anything. In a vbox, an hbox, a
10342 table, a button, etc. But they look their best in tight frames around them.
10343 Previews by themselves do not have borders and look flat without them. (Of
10344 course, if the flat look is what you want...) Tight frames provide the
10345 necessary borders.
10346
10347                                [Image][Image]
10348
10349 Previews in many ways are like any other widgets in GTK (whatever that
10350 means) except they possess an additional feature: they need to be filled with
10351 some sort of an image! First, we will deal exclusively with the GTK aspect
10352 of previews and then we'll discuss how to fill them.
10353
10354 GtkWidget *preview!
10355
10356 Without any ado:
10357
10358                               /* Create a preview widget,
10359                               set its size, an show it */
10360 GtkWidget *preview;
10361 preview=gtk_preview_new(GTK_PREVIEW_COLOR)
10362                               /*Other option:
10363                               GTK_PREVIEW_GRAYSCALE);*/
10364 gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT);
10365 gtk_widget_show(preview);
10366 my_preview_rendering_function(preview);
10367
10368 Oh yeah, like I said, previews look good inside frames, so how about:
10369
10370 GtkWidget *create_a_preview(int        Width,
10371                             int        Height,
10372                             int        Colorfulness)
10373 {
10374   GtkWidget *preview;
10375   GtkWidget *frame;
10376   
10377   frame = gtk_frame_new(NULL);
10378   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
10379   gtk_container_set_border_width (GTK_CONTAINER(frame),0);
10380   gtk_widget_show(frame);
10381
10382   preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR
10383                                        :GTK_PREVIEW_GRAYSCALE);
10384   gtk_preview_size (GTK_PREVIEW (preview), Width, Height);
10385   gtk_container_add(GTK_CONTAINER(frame),preview);
10386   gtk_widget_show(preview);
10387
10388   my_preview_rendering_function(preview);
10389   return frame;
10390 }
10391
10392 That's my basic preview. This routine returns the "parent" frame so you can
10393 place it somewhere else in your interface. Of course, you can pass the
10394 parent frame to this routine as a parameter. In many situations, however,
10395 the contents of the preview are changed continually by your application. In
10396 this case you may want to pass a pointer to the preview to a
10397 "create_a_preview()" and thus have control of it later.
10398
10399 One more important note that may one day save you a lot of time. Sometimes
10400 it is desirable to label you preview. For example, you may label the preview
10401 containing the original image as "Original" and the one containing the
10402 modified image as "Less Original". It might occur to you to pack the
10403 preview along with the appropriate label into a vbox. The unexpected caveat
10404 is that if the label is wider than the preview (which may happen for a
10405 variety of reasons unforseeable to you, from the dynamic decision on the
10406 size of the preview to the size of the font) the frame expands and no longer
10407 fits tightly over the preview. The same problem can probably arise in other
10408 situations as well.
10409
10410                                    [Image]
10411
10412 The solution is to place the preview and the label into a 2x1 table and by
10413 attaching them with the following parameters (this is one possible variations
10414 of course. The key is no GTK_FILL in the second attachment):
10415
10416 gtk_table_attach(GTK_TABLE(table),label,0,1,0,1,
10417                  0,
10418                  GTK_EXPAND|GTK_FILL,
10419                  0,0);
10420 gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2,
10421                  GTK_EXPAND,
10422                  GTK_EXPAND,
10423                  0,0);
10424
10425
10426 And here's the result:
10427
10428                                    [Image]
10429
10430 Misc
10431
10432 Making a preview clickable is achieved most easily by placing it in a
10433 button. It also adds a nice border around the preview and you may not even
10434 need to place it in a frame. See the Filter Pack Simulation plug-in for an
10435 example.
10436
10437 This is pretty much it as far as GTK is concerned.
10438
10439 Filling In a Preview
10440
10441 In order to familiarize ourselves with the basics of filling in previews,
10442 let's create the following pattern (contrived by trial and error):
10443
10444                                    [Image]
10445
10446 void
10447 my_preview_rendering_function(GtkWidget     *preview)
10448 {
10449 #define SIZE 100
10450 #define HALF (SIZE/2)
10451
10452   guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */
10453   gint i, j;                             /* Coordinates    */
10454   double r, alpha, x, y;
10455
10456   if (preview==NULL) return; /* I usually add this when I want */
10457                              /* to avoid silly crashes. You    */
10458                              /* should probably make sure that */
10459                              /* everything has been nicely     */
10460                              /* initialized!                   */
10461   for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape?  */
10462                                          /* glib.h contains ABS(x).   */
10463         row[i*3+0] = sqrt(1-r)*255;      /* Define Red                */
10464         row[i*3+1] = 128;                /* Define Green              */
10465         row[i*3+2] = 224;                /* Define Blue               */
10466       }                                  /* "+0" is for alignment!    */
10467       else {
10468         row[i*3+0] = r*255;
10469         row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255;
10470         row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255;
10471       }
10472     }
10473     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE);
10474     /* Insert "row" into "preview" starting at the point with  */
10475     /* coordinates (0,j) first column, j_th row extending SIZE */
10476     /* pixels to the right */
10477   }
10478
10479   free(row); /* save some space */
10480   gtk_widget_draw(preview,NULL); /* what does this do? */
10481   gdk_flush(); /* or this? */
10482 }
10483
10484 Non-GIMP users can have probably seen enough to do a lot of things already.
10485 For the GIMP users I have a few pointers to add.
10486
10487 Image Preview
10488
10489 It is probably wise to keep a reduced version of the image around with just
10490 enough pixels to fill the preview. This is done by selecting every n'th
10491 pixel where n is the ratio of the size of the image to the size of the
10492 preview. All further operations (including filling in the previews) are then
10493 performed on the reduced number of pixels only. The following is my
10494 implementation of reducing the image. (Keep in mind that I've had only basic
10495 C!)
10496
10497 (UNTESTED CODE ALERT!!!)
10498
10499 typedef struct {
10500   gint      width;
10501   gint      height;
10502   gint      bbp;
10503   guchar    *rgb;
10504   guchar    *mask;
10505 } ReducedImage;
10506
10507 enum {
10508   SELECTION_ONLY,
10509   SELECTION_IN_CONTEXT,
10510   ENTIRE_IMAGE
10511 };
10512
10513 ReducedImage *Reduce_The_Image(GDrawable *drawable,
10514                                GDrawable *mask,
10515                                gint LongerSize,
10516                                gint Selection)
10517 {
10518   /* This function reduced the image down to the the selected preview size */
10519   /* The preview size is determine by LongerSize, i.e., the greater of the  */
10520   /* two dimensions. Works for RGB images only!                            */
10521   gint RH, RW;          /* Reduced height and reduced width                */
10522   gint width, height;   /* Width and Height of the area being reduced      */
10523   gint bytes=drawable->bpp;
10524   ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage));
10525
10526   guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B;
10527   gint i, j, whichcol, whichrow, x1, x2, y1, y2;
10528   GPixelRgn srcPR, srcMask;
10529   gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire  */
10530                              /* image.                                     */
10531
10532   gimp_drawable_mask_bounds (drawable->id, &amp;x1, &amp;y1, &amp;x2, &amp;y2);
10533   width  = x2-x1;
10534   height = y2-y1;
10535   /* If there's a SELECTION, we got its bounds!)
10536
10537   if (width != drawable->width &amp;&amp; height != drawable->height)
10538     NoSelectionMade=FALSE;
10539   /* Become aware of whether the user has made an active selection   */
10540   /* This will become important later, when creating a reduced mask. */
10541
10542   /* If we want to preview the entire image, overrule the above!  */
10543   /* Of course, if no selection has been made, this does nothing! */
10544   if (Selection==ENTIRE_IMAGE) {
10545     x1=0;
10546     x2=drawable->width;
10547     y1=0;
10548     y2=drawable->height;
10549   }
10550
10551   /* If we want to preview a selection with some surrounding area we */
10552   /* have to expand it a little bit. Consider it a bit of a riddle. */
10553   if (Selection==SELECTION_IN_CONTEXT) {
10554     x1=MAX(0,                x1-width/2.0);
10555     x2=MIN(drawable->width,  x2+width/2.0);
10556     y1=MAX(0,                y1-height/2.0);
10557     y2=MIN(drawable->height, y2+height/2.0);
10558   }
10559
10560   /* How we can determine the width and the height of the area being */
10561   /* reduced.                                                        */
10562   width  = x2-x1;
10563   height = y2-y1;
10564
10565   /* The lines below determine which dimension is to be the longer   */
10566   /* side. The idea borrowed from the supernova plug-in. I suspect I */
10567   /* could've thought of it myself, but the truth must be told.      */
10568   /* Plagiarism stinks!                                               */
10569   if (width>height) {
10570     RW=LongerSize;
10571     RH=(float) height * (float) LongerSize/ (float) width;
10572   }
10573   else {
10574     RH=LongerSize;
10575     RW=(float)width * (float) LongerSize/ (float) height;
10576   }
10577
10578   /* The entire image is stretched into a string! */
10579   tempRGB   = (guchar *) malloc(RW*RH*bytes);
10580   tempmask  = (guchar *) malloc(RW*RH);
10581
10582   gimp_pixel_rgn_init (&amp;srcPR, drawable, x1, y1, width, height,
10583                        FALSE, FALSE);
10584   gimp_pixel_rgn_init (&amp;srcMask, mask, x1, y1, width, height,
10585                        FALSE, FALSE);
10586
10587   /* Grab enough to save a row of image and a row of mask. */
10588   src_row       = (guchar *) malloc (width*bytes);
10589   src_mask_row  = (guchar *) malloc (width);
10590
10591   for (i=0; i < RH; i++) {
10592     whichrow=(float)i*(float)height/(float)RH;
10593     gimp_pixel_rgn_get_row (&amp;srcPR, src_row, x1, y1+whichrow, width);
10594     gimp_pixel_rgn_get_row (&amp;srcMask, src_mask_row, x1, y1+whichrow, width);
10595
10596     for (j=0; j < RW; j++) {
10597       whichcol=(float)j*(float)width/(float)RW;
10598
10599       /* No selection made = each point is completely selected! */
10600       if (NoSelectionMade)
10601         tempmask[i*RW+j]=255;
10602       else
10603         tempmask[i*RW+j]=src_mask_row[whichcol];
10604
10605       /* Add the row to the one long string which now contains the image! */
10606       tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0];
10607       tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1];
10608       tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2];
10609
10610       /* Hold on to the alpha as well */
10611       if (bytes==4)
10612         tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3];
10613     }
10614   }
10615   temp->bpp=bytes;
10616   temp->width=RW;
10617   temp->height=RH;
10618   temp->rgb=tempRGB;
10619   temp->mask=tempmask;
10620   return temp;
10621 }
10622
10623 The following is a preview function which used the same ReducedImage type!
10624 Note that it uses fakes transparency (if one is present by means of
10625 fake_transparency which is defined as follows:
10626
10627 gint fake_transparency(gint i, gint j)
10628 {
10629   if ( ((i%20)- 10) * ((j%20)- 10)>0   )
10630     return 64;
10631   else
10632     return 196;
10633 }
10634
10635 Now here's the preview function:
10636
10637 void
10638 my_preview_render_function(GtkWidget     *preview,
10639                            gint          changewhat,
10640                            gint          changewhich)
10641 {
10642   gint Inten, bytes=drawable->bpp;
10643   gint i, j, k;
10644   float partial;
10645   gint RW=reduced->width;
10646   gint RH=reduced->height;
10647   guchar *row=malloc(bytes*RW);;
10648
10649
10650   for (i=0; i < RH; i++) {
10651     for (j=0; j < RW; j++) {
10652
10653       row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0];
10654       row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1];
10655       row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2];
10656
10657       if (bytes==4)
10658         for (k=0; k<3; k++) {
10659           float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0;
10660           row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j);
10661         }
10662     }
10663     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW);
10664   }
10665
10666   free(a);
10667   gtk_widget_draw(preview,NULL);
10668   gdk_flush();
10669 }
10670
10671 Applicable Routines
10672
10673 guint           gtk_preview_get_type           (void);
10674 /* No idea */
10675 void            gtk_preview_uninit             (void);
10676 /* No idea */
10677 GtkWidget*      gtk_preview_new                (GtkPreviewType   type);
10678 /* Described above */
10679 void            gtk_preview_size               (GtkPreview      *preview,
10680                                                 gint             width,
10681                                                 gint             height);
10682 /* Allows you to resize an existing preview.    */
10683 /* Apparently there's a bug in GTK which makes  */
10684 /* this process messy. A way to clean up a mess */
10685 /* is to manually resize the window containing  */
10686 /* the preview after resizing the preview.      */
10687
10688 void            gtk_preview_put                (GtkPreview      *preview,
10689                                                 GdkWindow       *window,
10690                                                 GdkGC           *gc,
10691                                                 gint             srcx,
10692                                                 gint             srcy,
10693                                                 gint             destx,
10694                                                 gint             desty,
10695                                                 gint             width,
10696                                                 gint             height);
10697 /* No idea */
10698
10699 void            gtk_preview_put_row            (GtkPreview      *preview,
10700                                                 guchar          *src,
10701                                                 guchar          *dest,
10702                                                 gint             x,
10703                                                 gint             y,
10704                                                 gint             w);
10705 /* No idea */
10706
10707 void            gtk_preview_draw_row           (GtkPreview      *preview,
10708                                                 guchar          *data,
10709                                                 gint             x,
10710                                                 gint             y,
10711                                                 gint             w);
10712 /* Described in the text */
10713
10714 void            gtk_preview_set_expand         (GtkPreview      *preview,
10715                                                 gint             expand);
10716 /* No idea */
10717
10718 /* No clue for any of the below but    */
10719 /* should be standard for most widgets */
10720 void            gtk_preview_set_gamma          (double           gamma);
10721 void            gtk_preview_set_color_cube     (guint            nred_shades,
10722                                                 guint            ngreen_shades,
10723                                                 guint            nblue_shades,
10724                                                 guint            ngray_shades);
10725 void            gtk_preview_set_install_cmap   (gint             install_cmap);
10726 void            gtk_preview_set_reserved       (gint             nreserved);
10727 GdkVisual*      gtk_preview_get_visual         (void);
10728 GdkColormap*    gtk_preview_get_cmap           (void);
10729 GtkPreviewInfo* gtk_preview_get_info           (void);
10730
10731 That's all, folks!
10732
10733 </verb></tscreen>
10734
10735 -->
10736
10737 <!-- ***************************************************************** -->
10738 <sect>Setting Widget Attributes<label id="sec_setting_widget_attributes">
10739 <!-- ***************************************************************** -->
10740 <p>
10741 This describes the functions used to operate on widgets. These can be
10742 used to set style, padding, size, etc.
10743
10744 (Maybe I should make a whole section on accelerators.)
10745
10746 <tscreen><verb>
10747 void gtk_widget_install_accelerator( GtkWidget           *widget,
10748                                      GtkAcceleratorTable *table,
10749                                      gchar               *signal_name,
10750                                      gchar                key,
10751                                      guint8               modifiers );
10752
10753 void gtk_widget_remove_accelerator ( GtkWidget           *widget,
10754                                      GtkAcceleratorTable *table,
10755                                      gchar               *signal_name);
10756
10757 void gtk_widget_activate( GtkWidget *widget );
10758
10759 void gtk_widget_set_name( GtkWidget *widget,
10760                           gchar     *name );
10761
10762 gchar *gtk_widget_get_name( GtkWidget *widget );
10763
10764 void gtk_widget_set_sensitive( GtkWidget *widget,
10765                                gint       sensitive );
10766
10767 void gtk_widget_set_style( GtkWidget *widget,
10768                            GtkStyle  *style );
10769                                            
10770 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
10771
10772 GtkStyle *gtk_widget_get_default_style( void );
10773
10774 void gtk_widget_set_uposition( GtkWidget *widget,
10775                                gint       x,
10776                                gint       y );
10777
10778 void gtk_widget_set_usize( GtkWidget *widget,
10779                            gint       width,
10780                            gint       height );
10781
10782 void gtk_widget_grab_focus( GtkWidget *widget );
10783
10784 void gtk_widget_show( GtkWidget *widget );
10785
10786 void gtk_widget_hide( GtkWidget *widget );
10787 </verb></tscreen>
10788
10789 <!-- ***************************************************************** -->
10790 <sect>Timeouts, IO and Idle Functions<label id="sec_timeouts">
10791 <!-- ***************************************************************** -->
10792
10793 <!-- ----------------------------------------------------------------- -->
10794 <sect1>Timeouts
10795 <p>
10796 You may be wondering how you make GTK do useful work when in gtk_main.
10797 Well, you have several options. Using the following function you can
10798 create a timeout function that will be called every "interval"
10799 milliseconds.
10800
10801 <tscreen><verb>
10802 gint gtk_timeout_add( guint32     interval,
10803                       GtkFunction function,
10804                       gpointer    data );
10805 </verb></tscreen>
10806
10807 The first argument is the number of milliseconds between calls to your
10808 function. The second argument is the function you wish to have called,
10809 and the third, the data passed to this callback function. The return
10810 value is an integer "tag" which may be used to stop the timeout by
10811 calling:
10812
10813 <tscreen><verb>
10814 void gtk_timeout_remove( gint tag );
10815 </verb></tscreen>
10816
10817 You may also stop the timeout function by returning zero or FALSE from
10818 your callback function. Obviously this means if you want your function
10819 to continue to be called, it should return a non-zero value,
10820 i.e., TRUE.
10821
10822 The declaration of your callback should look something like this:
10823
10824 <tscreen><verb>
10825 gint timeout_callback( gpointer data );
10826 </verb></tscreen>
10827
10828 <!-- ----------------------------------------------------------------- -->
10829 <sect1>Monitoring IO
10830 <p>
10831 A nifty feature of GDK (the library that underlies GTK), is the
10832 ability to have it check for data on a file descriptor for you (as
10833 returned by open(2) or socket(2)). This is especially useful for
10834 networking applications. The function:
10835
10836 <tscreen><verb>
10837 gint gdk_input_add( gint              source,
10838                     GdkInputCondition condition,
10839                     GdkInputFunction  function,
10840                     gpointer          data );
10841 </verb></tscreen>
10842
10843 Where the first argument is the file descriptor you wish to have
10844 watched, and the second specifies what you want GDK to look for. This
10845 may be one of:
10846
10847 <itemize>
10848 <item><tt/GDK_INPUT_READ/ - Call your function when there is data
10849 ready for reading on your file descriptor.
10850
10851 <item>><tt/GDK_INPUT_WRITE/ - Call your function when the file
10852 descriptor is ready for writing.
10853 </itemize>
10854
10855 As I'm sure you've figured out already, the third argument is the
10856 function you wish to have called when the above conditions are
10857 satisfied, and the fourth is the data to pass to this function.
10858
10859 The return value is a tag that may be used to stop GDK from monitoring
10860 this file descriptor using the following function.
10861
10862 <tscreen><verb>
10863 void gdk_input_remove( gint tag );
10864 </verb></tscreen>
10865
10866 The callback function should be declared as:
10867
10868 <tscreen><verb>
10869 void input_callback( gpointer          data,
10870                      gint              source, 
10871                      GdkInputCondition condition );
10872 </verb></tscreen>
10873
10874 Where <tt/source/ and <tt/condition/ are as specified above.
10875
10876 <!-- ----------------------------------------------------------------- -->
10877 <sect1>Idle Functions
10878 <p>
10879 <!-- TODO: Need to check on idle priorities - TRG -->
10880 What if you have a function which you want to be called when nothing
10881 else is happening ?
10882
10883 <tscreen><verb>
10884 gint gtk_idle_add( GtkFunction function,
10885                    gpointer    data );
10886 </verb></tscreen>
10887
10888 This causes GTK to call the specified function whenever nothing else
10889 is happening.
10890
10891 <tscreen><verb>
10892 void gtk_idle_remove( gint tag );
10893 </verb></tscreen>
10894
10895 I won't explain the meaning of the arguments as they follow very much
10896 like the ones above. The function pointed to by the first argument to
10897 gtk_idle_add will be called whenever the opportunity arises. As with
10898 the others, returning FALSE will stop the idle function from being
10899 called.
10900
10901 <!-- ***************************************************************** -->
10902 <sect>Advanced Event and Signal Handling<label id="sec_Adv_Events_and_Signals">
10903 <!-- ***************************************************************** -->
10904
10905 <!-- ----------------------------------------------------------------- -->
10906 <sect1>Signal Functions
10907
10908 <!-- ----------------------------------------------------------------- -->
10909 <sect2>Connecting and Disconnecting Signal Handlers
10910 <p>
10911
10912 <tscreen><verb>
10913 guint gtk_signal_connect( GtkObject     *object,
10914                           const gchar   *name,
10915                           GtkSignalFunc  func,
10916                           gpointer       func_data );
10917
10918 guint gtk_signal_connect_after( GtkObject     *object,
10919                                 const gchar   *name,
10920                                 GtkSignalFunc  func,
10921                                 gpointer       func_data );
10922
10923 guint gtk_signal_connect_object( GtkObject     *object,
10924                                  const gchar   *name,
10925                                  GtkSignalFunc  func,
10926                                  GtkObject     *slot_object );
10927
10928 guint gtk_signal_connect_object_after( GtkObject     *object,
10929                                        const gchar   *name,
10930                                        GtkSignalFunc  func,
10931                                        GtkObject     *slot_object );
10932
10933 guint gtk_signal_connect_full( GtkObject          *object,
10934                                const gchar        *name,
10935                                GtkSignalFunc       func,
10936                                GtkCallbackMarshal  marshal,
10937                                gpointer            data,
10938                                GtkDestroyNotify    destroy_func,
10939                                gint                object_signal,
10940                                gint                after );
10941
10942 guint gtk_signal_connect_interp( GtkObject          *object,
10943                                  const gchar        *name,
10944                                  GtkCallbackMarshal  func,
10945                                  gpointer            data,
10946                                  GtkDestroyNotify    destroy_func,
10947                                  gint                after );
10948
10949 void gtk_signal_connect_object_while_alive( GtkObject     *object,
10950                                             const gchar   *signal,
10951                                             GtkSignalFunc  func,
10952                                             GtkObject     *alive_object );
10953
10954 void gtk_signal_connect_while_alive( GtkObject     *object,
10955                                      const gchar   *signal,
10956                                      GtkSignalFunc  func,
10957                                      gpointer       func_data,
10958                                      GtkObject     *alive_object );
10959
10960 void gtk_signal_disconnect( GtkObject *object,
10961                             guint      handler_id );
10962
10963 void gtk_signal_disconnect_by_func( GtkObject     *object,
10964                                     GtkSignalFunc  func,
10965                                     gpointer       data );
10966 </verb></tscreen>
10967
10968 <!-- ----------------------------------------------------------------- -->
10969 <sect2>Blocking and Unblocking Signal Handlers
10970 <p>
10971 <tscreen><verb>
10972 void gtk_signal_handler_block( GtkObject *object,
10973                                guint      handler_id);
10974
10975 void gtk_signal_handler_block_by_func( GtkObject     *object,
10976                                        GtkSignalFunc  func,
10977                                        gpointer       data );
10978
10979 void gtk_signal_handler_block_by_data( GtkObject *object,
10980                                        gpointer   data );
10981
10982 void gtk_signal_handler_unblock( GtkObject *object,
10983                                  guint      handler_id );
10984
10985 void gtk_signal_handler_unblock_by_func( GtkObject     *object,
10986                                          GtkSignalFunc  func,
10987                                          gpointer       data );
10988
10989 void gtk_signal_handler_unblock_by_data( GtkObject *object,
10990                                          gpointer   data );
10991 </verb></tscreen>
10992
10993 <!-- ----------------------------------------------------------------- -->
10994 <sect2>Emitting and Stopping Signals
10995 <p>
10996 <tscreen><verb>
10997 void gtk_signal_emit( GtkObject *object,
10998                       guint      signal_id,
10999                       ... );
11000
11001 void gtk_signal_emit_by_name( GtkObject   *object,
11002                               const gchar *name,
11003                               ... );
11004
11005 void gtk_signal_emitv( GtkObject *object,
11006                        guint      signal_id,
11007                        GtkArg    *params );
11008
11009 void gtk_signal_emitv_by_name( GtkObject   *object,
11010                                const gchar *name,
11011                                GtkArg      *params );
11012
11013 guint gtk_signal_n_emissions( GtkObject *object,
11014                               guint      signal_id );
11015
11016 guint gtk_signal_n_emissions_by_name( GtkObject   *object,
11017                                       const gchar *name );
11018
11019 void gtk_signal_emit_stop( GtkObject *object,
11020                            guint      signal_id );
11021
11022 void gtk_signal_emit_stop_by_name( GtkObject   *object,
11023                                    const gchar *name );
11024 </verb></tscreen>
11025
11026 <!-- ----------------------------------------------------------------- -->
11027 <sect1>Signal Emission and Propagation
11028 <p>
11029 Signal emission is the process whereby GTK runs all handlers for a
11030 specific object and signal.
11031
11032 First, note that the return value from a signal emission is the return
11033 value of the <em>last</em> handler executed. Since event signals are
11034 all of type <tt/GTK_RUN_LAST/, this will be the default (GTK supplied)
11035 handler, unless you connect with gtk_signal_connect_after().
11036
11037 The way an event (say "button_press_event") is handled, is:
11038 <itemize>
11039 <item>Start with the widget where the event occured.
11040
11041 <item>Emit the generic "event" signal. If that signal handler returns
11042 a value of TRUE, stop all processing.
11043
11044 <item>Otherwise, emit a specific, "button_press_event" signal. If that
11045 returns TRUE, stop all processing.
11046
11047 <item>Otherwise, go to the widget's parent, and repeat the above two
11048 steps.
11049
11050 <item>Continue until some signal handler returns TRUE, or until the
11051 top-level widget is reached.
11052 </itemize>
11053
11054 Some consequences of the above are:
11055 <itemize>
11056 <item>Your handler's return value will have no effect if there is a
11057 default handler, unless you connect with gtk_signal_connect_after().
11058
11059 <item>To prevent the default handler from being run, you need to
11060 connect with gtk_signal_connect() and use
11061 gtk_signal_emit_stop_by_name() - the return value only affects whether
11062 the signal is propagated, not the current emission.
11063 </itemize>
11064
11065 <!-- ***************************************************************** -->
11066 <sect>Managing Selections
11067 <!-- ***************************************************************** -->
11068
11069 <!-- ----------------------------------------------------------------- -->
11070 <sect1> Overview
11071 <p>
11072 One type of interprocess communication supported by X and GTK is
11073 <em>selections</em>. A selection identifies a chunk of data, for
11074 instance, a portion of text, selected by the user in some fashion, for
11075 instance, by dragging with the mouse. Only one application on a
11076 display (the <em>owner</em>) can own a particular selection at one
11077 time, so when a selection is claimed by one application, the previous
11078 owner must indicate to the user that selection has been
11079 relinquished. Other applications can request the contents of a
11080 selection in different forms, called <em>targets</em>. There can be
11081 any number of selections, but most X applications only handle one, the
11082 <em>primary selection</em>.
11083
11084 In most cases, it isn't necessary for a GTK application to deal with
11085 selections itself. The standard widgets, such as the Entry widget,
11086 already have the capability to claim the selection when appropriate
11087 (e.g., when the user drags over text), and to retrieve the contents of
11088 the selection owned by another widget or another application (e.g.,
11089 when the user clicks the second mouse button). However, there may be
11090 cases in which you want to give other widgets the ability to supply
11091 the selection, or you wish to retrieve targets not supported by
11092 default.
11093
11094 A fundamental concept needed to understand selection handling is that
11095 of the <em>atom</em>. An atom is an integer that uniquely identifies a
11096 string (on a certain display). Certain atoms are predefined by the X
11097 server, and in some cases there are constants in <tt>gtk.h</tt>
11098 corresponding to these atoms. For instance the constant
11099 <tt>GDK_PRIMARY_SELECTION</tt> corresponds to the string "PRIMARY".
11100 In other cases, you should use the functions
11101 <tt>gdk_atom_intern()</tt>, to get the atom corresponding to a string,
11102 and <tt>gdk_atom_name()</tt>, to get the name of an atom. Both
11103 selections and targets are identified by atoms.
11104
11105 <!-- ----------------------------------------------------------------- -->
11106 <sect1> Retrieving the selection
11107 <p>
11108 Retrieving the selection is an asynchronous process. To start the
11109 process, you call:
11110
11111 <tscreen><verb>
11112 gint gtk_selection_convert( GtkWidget *widget, 
11113                             GdkAtom    selection, 
11114                             GdkAtom    target,
11115                             guint32    time );
11116 </verb</tscreen>
11117
11118 This <em>converts</em> the selection into the form specified by
11119 <tt/target/. If at all possible, the time field should be the time
11120 from the event that triggered the selection. This helps make sure that
11121 events occur in the order that the user requested them. However, if it
11122 is not available (for instance, if the conversion was triggered by a
11123 "clicked" signal), then you can use the constant
11124 <tt>GDK_CURRENT_TIME</tt>.
11125
11126 When the selection owner responds to the request, a
11127 "selection_received" signal is sent to your application. The handler
11128 for this signal receives a pointer to a <tt>GtkSelectionData</tt>
11129 structure, which is defined as:
11130
11131 <tscreen><verb>
11132 struct _GtkSelectionData
11133 {
11134   GdkAtom selection;
11135   GdkAtom target;
11136   GdkAtom type;
11137   gint    format;
11138   guchar *data;
11139   gint    length;
11140 };
11141 </verb></tscreen>
11142
11143 <tt>selection</tt> and <tt>target</tt> are the values you gave in your
11144 <tt>gtk_selection_convert()</tt> call. <tt>type</tt> is an atom that
11145 identifies the type of data returned by the selection owner. Some
11146 possible values are "STRING", a string of latin-1 characters, "ATOM",
11147 a series of atoms, "INTEGER", an integer, etc. Most targets can only
11148 return one type. <tt/format/ gives the length of the units (for
11149 instance characters) in bits. Usually, you don't care about this when
11150 receiving data. <tt>data</tt> is a pointer to the returned data, and
11151 <tt>length</tt> gives the length of the returned data, in bytes. If
11152 <tt>length</tt> is negative, then an error occurred and the selection
11153 could not be retrieved. This might happen if no application owned the
11154 selection, or if you requested a target that the application didn't
11155 support. The buffer is actually guaranteed to be one byte longer than
11156 <tt>length</tt>; the extra byte will always be zero, so it isn't
11157 necessary to make a copy of strings just to null terminate them.
11158
11159 In the following example, we retrieve the special target "TARGETS",
11160 which is a list of all targets into which the selection can be
11161 converted.
11162
11163 <tscreen><verb>
11164 /* example-start selection gettargets.c */
11165
11166 #include <gtk/gtk.h>
11167
11168 void selection_received( GtkWidget        *widget, 
11169                          GtkSelectionData *selection_data, 
11170                          gpointer          data );
11171
11172 /* Signal handler invoked when user clicks on the "Get Targets" button */
11173 void get_targets( GtkWidget *widget,
11174                   gpointer data )
11175 {
11176   static GdkAtom targets_atom = GDK_NONE;
11177
11178   /* Get the atom corresponding to the string "TARGETS" */
11179   if (targets_atom == GDK_NONE)
11180     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
11181
11182   /* And request the "TARGETS" target for the primary selection */
11183   gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
11184                          GDK_CURRENT_TIME);
11185 }
11186
11187 /* Signal handler called when the selections owner returns the data */
11188 void selection_received( GtkWidget        *widget,
11189                          GtkSelectionData *selection_data, 
11190                          gpointer          data )
11191 {
11192   GdkAtom *atoms;
11193   GList *item_list;
11194   int i;
11195
11196   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
11197   if (selection_data->length < 0)
11198     {
11199       g_print ("Selection retrieval failed\n");
11200       return;
11201     }
11202   /* Make sure we got the data in the expected form */
11203   if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
11204     {
11205       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
11206       return;
11207     }
11208   
11209   /* Print out the atoms we received */
11210   atoms = (GdkAtom *)selection_data->data;
11211
11212   item_list = NULL;
11213   for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
11214     {
11215       char *name;
11216       name = gdk_atom_name (atoms[i]);
11217       if (name != NULL)
11218         g_print ("%s\n",name);
11219       else
11220         g_print ("(bad atom)\n");
11221     }
11222
11223   return;
11224 }
11225
11226 int main( int   argc,
11227           char *argv[] )
11228 {
11229   GtkWidget *window;
11230   GtkWidget *button;
11231   
11232   gtk_init (&amp;argc, &amp;argv);
11233
11234   /* Create the toplevel window */
11235
11236   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11237   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
11238   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11239
11240   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11241                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11242
11243   /* Create a button the user can click to get targets */
11244
11245   button = gtk_button_new_with_label ("Get Targets");
11246   gtk_container_add (GTK_CONTAINER (window), button);
11247
11248   gtk_signal_connect (GTK_OBJECT(button), "clicked",
11249                       GTK_SIGNAL_FUNC (get_targets), NULL);
11250   gtk_signal_connect (GTK_OBJECT(button), "selection_received",
11251                       GTK_SIGNAL_FUNC (selection_received), NULL);
11252
11253   gtk_widget_show (button);
11254   gtk_widget_show (window);
11255   
11256   gtk_main ();
11257   
11258   return 0;
11259 }
11260 /* example-end */
11261 </verb></tscreen>
11262
11263 <!-- ----------------------------------------------------------------- -->
11264 <sect1> Supplying the selection 
11265 <p>
11266 Supplying the selection is a bit more complicated. You must register 
11267 handlers that will be called when your selection is requested. For
11268 each selection/target pair you will handle, you make a call to:
11269
11270 <tscreen><verb>
11271 void gtk_selection_add_target (GtkWidget           *widget, 
11272                                GdkAtom              selection,
11273                                GdkAtom              target,
11274                                guint                info);
11275 </verb></tscreen>
11276
11277 <tt/widget/, <tt/selection/, and <tt/target/ identify the requests
11278 this handler will manage. When a request for a selection is received,
11279 the "selection_get" signal will be called. <tt/info/ can be used as an
11280 enumerator to identify the specific target within the callback function.
11281
11282 The callback function has the signature:
11283
11284 <tscreen><verb>
11285 void  "selection_get" (GtkWidget          *widget,
11286                        GtkSelectionData   *selection_data,
11287                        guint               info,
11288                        guint               time);
11289 </verb></tscreen>
11290
11291 The GtkSelectionData is the same as above, but this time, we're
11292 responsible for filling in the fields <tt/type/, <tt/format/,
11293 <tt/data/, and <tt/length/. (The <tt/format/ field is actually
11294 important here - the X server uses it to figure out whether the data
11295 needs to be byte-swapped or not. Usually it will be 8 - <em/i.e./ a
11296 character - or 32 - <em/i.e./ a. integer.) This is done by calling the
11297 function:
11298
11299 <tscreen><verb>
11300 void gtk_selection_data_set( GtkSelectionData *selection_data,
11301                              GdkAtom           type,
11302                              gint              format,
11303                              guchar           *data,
11304                              gint              length );
11305 </verb></tscreen>
11306
11307 This function takes care of properly making a copy of the data so that
11308 you don't have to worry about keeping it around. (You should not fill
11309 in the fields of the GtkSelectionData structure by hand.)
11310
11311 When prompted by the user, you claim ownership of the selection by
11312 calling:
11313
11314 <tscreen><verb>
11315 gint gtk_selection_owner_set( GtkWidget *widget,
11316                               GdkAtom    selection,
11317                               guint32    time );
11318 </verb></tscreen>
11319
11320 If another application claims ownership of the selection, you will
11321 receive a "selection_clear_event".
11322
11323 As an example of supplying the selection, the following program adds
11324 selection functionality to a toggle button. When the toggle button is
11325 depressed, the program claims the primary selection. The only target
11326 supported (aside from certain targets like "TARGETS" supplied by GTK
11327 itself), is the "STRING" target. When this target is requested, a
11328 string representation of the time is returned.
11329
11330 <tscreen><verb>
11331 /* example-start selection setselection.c */
11332
11333 #include <gtk/gtk.h>
11334 #include <time.h>
11335
11336 /* Callback when the user toggles the selection */
11337 void selection_toggled( GtkWidget *widget,
11338                         gint      *have_selection )
11339 {
11340   if (GTK_TOGGLE_BUTTON(widget)->active)
11341     {
11342       *have_selection = gtk_selection_owner_set (widget,
11343                                                  GDK_SELECTION_PRIMARY,
11344                                                  GDK_CURRENT_TIME);
11345       /* if claiming the selection failed, we return the button to
11346          the out state */
11347       if (!*have_selection)
11348         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
11349     }
11350   else
11351     {
11352       if (*have_selection)
11353         {
11354           /* Before clearing the selection by setting the owner to NULL,
11355              we check if we are the actual owner */
11356           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
11357             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
11358                                      GDK_CURRENT_TIME);
11359           *have_selection = FALSE;
11360         }
11361     }
11362 }
11363
11364 /* Called when another application claims the selection */
11365 gint selection_clear( GtkWidget         *widget,
11366                       GdkEventSelection *event,
11367                       gint              *have_selection )
11368 {
11369   *have_selection = FALSE;
11370   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
11371
11372   return TRUE;
11373 }
11374
11375 /* Supplies the current time as the selection. */
11376 void selection_handle( GtkWidget        *widget, 
11377                        GtkSelectionData *selection_data,
11378                        guint             info,
11379                        guint             time_stamp,
11380                        gpointer          data )
11381 {
11382   gchar *timestr;
11383   time_t current_time;
11384
11385   current_time = time(NULL);
11386   timestr = asctime (localtime(&amp;current_time)); 
11387   /* When we return a single string, it should not be null terminated.
11388      That will be done for us */
11389
11390   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
11391                           8, timestr, strlen(timestr));
11392 }
11393
11394 int main( int   argc,
11395           char *argv[] )
11396 {
11397   GtkWidget *window;
11398   GtkWidget *selection_button;
11399
11400   static int have_selection = FALSE;
11401   
11402   gtk_init (&amp;argc, &amp;argv);
11403
11404   /* Create the toplevel window */
11405
11406   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11407   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
11408   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11409
11410   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11411                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11412
11413   /* Create a toggle button to act as the selection */
11414
11415   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
11416   gtk_container_add (GTK_CONTAINER (window), selection_button);
11417   gtk_widget_show (selection_button);
11418
11419   gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
11420                       GTK_SIGNAL_FUNC (selection_toggled), &amp;have_selection);
11421   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
11422                       GTK_SIGNAL_FUNC (selection_clear), &amp;have_selection);
11423
11424   gtk_selection_add_target (selection_button,
11425                             GDK_SELECTION_PRIMARY,
11426                             GDK_SELECTION_TYPE_STRING,
11427                             1);
11428   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_get",
11429                       GTK_SIGNAL_FUNC (selection_handle), &amp;have_selection);
11430
11431   gtk_widget_show (selection_button);
11432   gtk_widget_show (window);
11433   
11434   gtk_main ();
11435   
11436   return 0;
11437 }
11438 /* example-end */
11439 </verb></tscreen>
11440
11441
11442 <!-- ***************************************************************** -->
11443 <sect>GLib<label id="sec_glib">
11444 <!-- ***************************************************************** -->
11445 <p>
11446 GLib is a lower-level library that provides many useful definitions
11447 and functions available for use when creating GDK and GTK
11448 applications. These include definitions for basic types and their
11449 limits, standard macros, type conversions, byte order, memory
11450 allocation, warnings and assertions, message logging, timers, string
11451 utilities, hook functions, a lexical scanner, dynamic loading of
11452 modules, and automatic string completion. A number of data structures
11453 (and their related operations) are also defined, including memory
11454 chunks, doubly-linked lists, singly-linked lists, hash tables, strings
11455 (which can grow dynamically), string chunks (groups of strings),
11456 arrays (which can grow in size as elements are added), balanced binary
11457 trees, N-ary trees, quarks (a two-way association of a string and a
11458 unique integer identifier), keyed data lists (lists of data elements
11459 accessible by a string or integer id), relations and tuples (tables of
11460 data which can be indexed on any number of fields), and caches.
11461
11462 A summary of some of GLib's capabilities follows; not every function,
11463 data structure, or operation is covered here.  For more complete
11464 information about the GLib routines, see the GLib documentation. One
11465 source of GLib documentation is <htmlurl url="http://www.gtk.org/"
11466 name="http://www.gtk.org/">.
11467
11468 If you are using a language other than C, you should consult your
11469 language's binding documentation. In some cases your language may
11470 have equivalent functionality built-in, while in other cases it may
11471 not.
11472
11473 <!-- ----------------------------------------------------------------- -->
11474 <sect1>Definitions
11475 <p>
11476 Definitions for the extremes of many of the standard types are:
11477
11478 <tscreen><verb>
11479 G_MINFLOAT
11480 G_MAXFLOAT
11481 G_MINDOUBLE
11482 G_MAXDOUBLE
11483 G_MINSHORT
11484 G_MAXSHORT
11485 G_MININT
11486 G_MAXINT
11487 G_MINLONG
11488 G_MAXLONG
11489 </verb></tscreen>
11490
11491 Also, the following typedefs. The ones left unspecified are dynamically set
11492 depending on the architecture. Remember to avoid counting on the size of a
11493 pointer if you want to be portable! E.g., a pointer on an Alpha is 8
11494 bytes, but 4 on Intel 80x86 family CPUs.
11495
11496 <tscreen><verb>
11497 char   gchar;
11498 short  gshort;
11499 long   glong;
11500 int    gint;
11501 char   gboolean;
11502
11503 unsigned char   guchar;
11504 unsigned short  gushort;
11505 unsigned long   gulong;
11506 unsigned int    guint;
11507
11508 float   gfloat;
11509 double  gdouble;
11510 long double gldouble;
11511
11512 void* gpointer;
11513
11514 gint8
11515 guint8
11516 gint16
11517 guint16
11518 gint32
11519 guint32
11520 </verb></tscreen>
11521
11522 <!-- ----------------------------------------------------------------- -->
11523 <sect1>Doubly Linked Lists
11524 <p>
11525 The following functions are used to create, manage, and destroy
11526 standard doubly linked lists. Each element in the list contains a
11527 piece of data, together with pointers which link to the previous and
11528 next elements in the list. This enables easy movement in either
11529 direction through the list. The data item is of type "gpointer",
11530 which means the data can be a pointer to your real data or (through
11531 casting) a numeric value (but do not assume that int and gpointer have
11532 the same size!). These routines internally allocate list elements in
11533 blocks, which is more efficient than allocating elements individually.
11534
11535 There is no function to specifically create a list. Instead, simply
11536 create a variable of type GList* and set its value to NULL; NULL is
11537 considered to be the empty list.
11538
11539 To add elements to a list, use the g_list_append(), g_list_prepend(),
11540 g_list_insert(), or g_list_insert_sorted() routines. In all cases
11541 they accept a pointer to the beginning of the list, and return the
11542 (possibly changed) pointer to the beginning of the list. Thus, for
11543 all of the operations that add or remove elements, be sure to save the
11544 returned value!
11545
11546 <tscreen><verb>
11547 GList *g_list_append( GList    *list,
11548                       gpointer  data );
11549 </verb></tscreen>
11550
11551 This adds a new element (with value <tt/data/) onto the end of the
11552 list.
11553   
11554 <tscreen><verb>    
11555 GList *g_list_prepend( GList    *list,
11556                        gpointer  data );
11557 </verb></tscreen>
11558
11559 This adds a new element (with value <tt/data/) to the beginning of the
11560 list.
11561
11562 <tscreen><verb>         
11563 GList *g_list_insert( GList    *list,
11564                       gpointer  data,
11565                       gint      position );
11566
11567 </verb></tscreen>
11568
11569 This inserts a new element (with value data) into the list at the
11570 given position. If position is 0, this is just like g_list_prepend();
11571 if position is less than 0, this is just like g_list_append().
11572
11573 <tscreen><verb>
11574 GList *g_list_remove( GList    *list,
11575                       gpointer  data );
11576 </verb></tscreen>
11577
11578 This removes the element in the list with the value <tt/data/;
11579 if the element isn't there, the list is unchanged.
11580
11581 <tscreen><verb>
11582 void g_list_free( GList *list );
11583 </verb></tscreen>
11584
11585 This frees all of the memory used by a GList. If the list elements
11586 refer to dynamically-allocated memory, then they should be freed
11587 first.
11588
11589 There are many other GLib functions that support doubly linked lists;
11590 see the glib documentation for more information.  Here are a few of
11591 the more useful functions' signatures:
11592
11593 <tscreen><verb>            
11594 GList *g_list_remove_link( GList *list,
11595                            GList *link );
11596
11597 GList *g_list_reverse( GList *list );
11598
11599 GList *g_list_nth( GList *list,
11600                    gint   n );
11601                            
11602 GList *g_list_find( GList    *list,
11603                     gpointer  data );
11604
11605 GList *g_list_last( GList *list );
11606
11607 GList *g_list_first( GList *list );
11608
11609 gint g_list_length( GList *list );
11610
11611 void g_list_foreach( GList    *list,
11612                      GFunc     func,
11613                      gpointer  user_data );
11614 </verb></tscreen>                                             
11615
11616 <!-- ----------------------------------------------------------------- -->
11617 <sect1>Singly Linked Lists
11618 <p>
11619 Many of the above functions for singly linked lists are identical to the
11620 above. Here is a list of some of their operations:
11621
11622 <tscreen><verb>
11623 GSList *g_slist_append( GSList   *list,
11624                         gpointer  data );
11625                 
11626 GSList *g_slist_prepend( GSList   *list,
11627                          gpointer  data );
11628                              
11629 GSList *g_slist_insert( GSList   *list,
11630                         gpointer  data,
11631                         gint      position );
11632                              
11633 GSList *g_slist_remove( GSList   *list,
11634                         gpointer  data );
11635                              
11636 GSList *g_slist_remove_link( GSList *list,
11637                              GSList *link );
11638                              
11639 GSList *g_slist_reverse( GSList *list );
11640
11641 GSList *g_slist_nth( GSList *list,
11642                      gint    n );
11643                              
11644 GSList *g_slist_find( GSList   *list,
11645                       gpointer  data );
11646                              
11647 GSList *g_slist_last( GSList *list );
11648
11649 gint g_slist_length( GSList *list );
11650
11651 void g_slist_foreach( GSList   *list,
11652                       GFunc     func,
11653                       gpointer  user_data );
11654         
11655 </verb></tscreen>
11656
11657 <!-- ----------------------------------------------------------------- -->
11658 <sect1>Memory Management
11659 <p>
11660 <tscreen><verb>
11661 gpointer g_malloc( gulong size );
11662 </verb></tscreen>
11663
11664 This is a replacement for malloc(). You do not need to check the return
11665 value as it is done for you in this function. If the memory allocation
11666 fails for whatever reasons, your applications will be terminated.
11667
11668 <tscreen><verb>
11669 gpointer g_malloc0( gulong size );
11670 </verb></tscreen>
11671
11672 Same as above, but zeroes the memory before returning a pointer to it.
11673
11674 <tscreen><verb>
11675 gpointer g_realloc( gpointer mem,
11676                     gulong   size );
11677 </verb></tscreen>
11678
11679 Relocates "size" bytes of memory starting at "mem".  Obviously, the
11680 memory should have been previously allocated.
11681
11682 <tscreen><verb>
11683 void g_free( gpointer mem );
11684 </verb></tscreen>
11685
11686 Frees memory. Easy one. If <tt/mem/ is NULL it simply returns.
11687
11688 <tscreen><verb>
11689 void g_mem_profile( void );
11690 </verb></tscreen>
11691
11692 Dumps a profile of used memory, but requires that you add <tt>#define
11693 MEM_PROFILE</tt> to the top of glib/gmem.c and re-make and make install.
11694
11695 <tscreen><verb>
11696 void g_mem_check( gpointer mem );
11697 </verb></tscreen>
11698
11699 Checks that a memory location is valid. Requires you add <tt>#define
11700 MEM_CHECK</tt> to the top of gmem.c and re-make and make install.
11701
11702 <!-- ----------------------------------------------------------------- -->
11703 <sect1>Timers
11704 <p>
11705 Timer functions can be used to time operations (e.g., to see how much
11706 time has elapsed). First, you create a new timer with g_timer_new().
11707 You can then use g_timer_start() to start timing an operation,
11708 g_timer_stop() to stop timing an operation, and g_timer_elapsed() to
11709 determine the elapsed time.
11710
11711 <tscreen><verb>
11712 GTimer *g_timer_new( void );
11713
11714 void g_timer_destroy( GTimer *timer );
11715
11716 void g_timer_start( GTimer  *timer );
11717
11718 void g_timer_stop( GTimer  *timer );
11719
11720 void g_timer_reset( GTimer  *timer );
11721
11722 gdouble g_timer_elapsed( GTimer *timer,
11723                          gulong *microseconds );
11724 </verb></tscreen>                        
11725
11726 <!-- ----------------------------------------------------------------- -->
11727 <sect1>String Handling
11728 <p>
11729 GLib defines a new type called a GString, which is similar to a
11730 standard C string but one that grows automatically. Its string data
11731 is null-terminated. What this gives you is protection from buffer
11732 overflow programming errors within your program. This is a very
11733 important feature, and hence I recommend that you make use of
11734 GStrings. GString itself has a simple public definition:
11735
11736 <tscreen><verb>
11737 struct GString 
11738 {
11739   gchar *str; /* Points to the string's current \0-terminated value. */
11740   gint len; /* Current length */
11741 };
11742 </verb></tscreen>
11743
11744 As you might expect, there are a number of operations you can do with
11745 a GString.
11746
11747 <tscreen><verb>
11748 GString *g_string_new( gchar *init );
11749 </verb></tscreen>
11750
11751 This constructs a GString, copying the string value of <tt/init/
11752 into the GString and returning a pointer to it. NULL may be given as
11753 the argument for an initially empty GString.
11754  
11755 <tscreen><verb>
11756
11757 void g_string_free( GString *string,
11758                     gint     free_segment );
11759 </verb></tscreen>
11760
11761 This frees the memory for the given GString. If <tt/free_segment/ is
11762 TRUE, then this also frees its character data.
11763
11764 <tscreen><verb>
11765                              
11766 GString *g_string_assign( GString     *lval,
11767                           const gchar *rval );
11768 </verb></tscreen>
11769
11770 This copies the characters from rval into lval, destroying the
11771 previous contents of lval. Note that lval will be lengthened as
11772 necessary to hold the string's contents, unlike the standard strcpy()
11773 function.
11774
11775 The rest of these functions should be relatively obvious (the _c
11776 versions accept a character instead of a string):
11777
11778 <tscreen><verb>              
11779 GString *g_string_truncate( GString *string,
11780                             gint     len );
11781                              
11782 GString *g_string_append( GString *string,
11783                           gchar   *val );
11784                             
11785 GString *g_string_append_c( GString *string,
11786                             gchar    c );
11787         
11788 GString *g_string_prepend( GString *string,
11789                            gchar   *val );
11790                              
11791 GString *g_string_prepend_c( GString *string,
11792                              gchar    c );
11793         
11794 void g_string_sprintf( GString *string,
11795                        gchar   *fmt,
11796                        ...);
11797         
11798 void g_string_sprintfa ( GString *string,
11799                          gchar   *fmt,
11800                          ... );
11801 </verb></tscreen>                                                         
11802
11803 <!-- ----------------------------------------------------------------- -->
11804 <sect1>Utility and Error Functions
11805 <p>
11806 <tscreen><verb>
11807 gchar *g_strdup( const gchar *str );
11808 </verb></tscreen>
11809
11810 Replacement strdup function.  Copies the original strings contents to
11811 newly allocated memory, and returns a pointer to it.
11812
11813 <tscreen><verb>
11814 gchar *g_strerror( gint errnum );
11815 </verb></tscreen>
11816
11817 I recommend using this for all error messages.  It's much nicer, and more
11818 portable than perror() or others.  The output is usually of the form:
11819
11820 <tscreen><verb>
11821 program name:function that failed:file or further description:strerror
11822 </verb></tscreen>
11823
11824 Here's an example of one such call used in our hello_world program:
11825
11826 <tscreen><verb>
11827 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
11828 </verb></tscreen>
11829
11830 <tscreen><verb>
11831 void g_error( gchar *format, ... );
11832 </verb></tscreen>
11833
11834 Prints an error message. The format is just like printf, but it
11835 prepends "** ERROR **: " to your message, and exits the program.  
11836 Use only for fatal errors.
11837
11838 <tscreen><verb>
11839 void g_warning( gchar *format, ... );
11840 </verb></tscreen>
11841
11842 Same as above, but prepends "** WARNING **: ", and does not exit the
11843 program.
11844
11845 <tscreen><verb>
11846 void g_message( gchar *format, ... );
11847 </verb></tscreen>
11848
11849 Prints "message: " prepended to the string you pass in.
11850
11851 <tscreen><verb>
11852 void g_print( gchar *format, ... );
11853 </verb></tscreen>
11854
11855 Replacement for printf().
11856
11857 And our last function:
11858
11859 <tscreen><verb>
11860 gchar *g_strsignal( gint signum );
11861 </verb></tscreen>
11862
11863 Prints out the name of the Unix system signal given the signal number.
11864 Useful in generic signal handling functions.
11865
11866 All of the above are more or less just stolen from glib.h.  If anyone cares
11867 to document any function, just send me an email!
11868
11869 <!-- ***************************************************************** -->
11870 <sect>GTK's rc Files <label id="sec_gtkrc_files">
11871 <!-- ***************************************************************** -->
11872 <p>
11873 GTK has its own way of dealing with application defaults, by using rc
11874 files. These can be used to set the colors of just about any widget, and
11875 can also be used to tile pixmaps onto the background of some widgets.  
11876
11877 <!-- ----------------------------------------------------------------- -->
11878 <sect1>Functions For rc Files 
11879 <p>
11880 When your application starts, you should include a call to:
11881
11882 <tscreen><verb>
11883 void gtk_rc_parse( char *filename );
11884 </verb></tscreen>
11885
11886 Passing in the filename of your rc file. This will cause GTK to parse
11887 this file, and use the style settings for the widget types defined
11888 there.
11889
11890 If you wish to have a special set of widgets that can take on a
11891 different style from others, or any other logical division of widgets,
11892 use a call to:
11893
11894 <tscreen><verb>
11895 void gtk_widget_set_name( GtkWidget *widget,
11896                           gchar     *name );
11897 </verb></tscreen>
11898
11899 Passing your newly created widget as the first argument, and the name
11900 you wish to give it as the second. This will allow you to change the
11901 attributes of this widget by name through the rc file.
11902
11903 If we use a call something like this:
11904
11905 <tscreen><verb>
11906 button = gtk_button_new_with_label ("Special Button");
11907 gtk_widget_set_name (button, "special button");
11908 </verb></tscreen>
11909
11910 Then this button is given the name "special button" and may be addressed by
11911 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]
11912
11913 The example rc file below, sets the properties of the main window, and lets
11914 all children of that main window inherit the style described by the "main
11915 button" style.  The code used in the application is:
11916
11917 <tscreen><verb>
11918 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11919 gtk_widget_set_name (window, "main window");
11920 </verb></tscreen>
11921
11922 And then the style is defined in the rc file using:
11923
11924 <tscreen><verb>
11925 widget "main window.*GtkButton*" style "main_button"
11926 </verb></tscreen>
11927
11928 Which sets all the Button widgets in the "main window" to the
11929 "main_buttons" style as defined in the rc file.
11930
11931 As you can see, this is a fairly powerful and flexible system.  Use your
11932 imagination as to how best to take advantage of this.
11933
11934 <!-- ----------------------------------------------------------------- -->
11935 <sect1>GTK's rc File Format
11936 <p>
11937 The format of the GTK file is illustrated in the example below. This is
11938 the testgtkrc file from the GTK distribution, but I've added a
11939 few comments and things. You may wish to include this explanation in
11940 your application to allow the user to fine tune his application.
11941
11942 There are several directives to change the attributes of a widget.
11943
11944 <itemize>
11945 <item>fg - Sets the foreground color of a widget.
11946 <item>bg - Sets the background color of a widget.
11947 <item>bg_pixmap - Sets the background of a widget to a tiled pixmap.
11948 <item>font - Sets the font to be used with the given widget.
11949 </itemize>
11950
11951 In addition to this, there are several states a widget can be in, and you
11952 can set different colors, pixmaps and fonts for each state. These states are:
11953
11954 <itemize>
11955 <item>NORMAL - The normal state of a widget, without the mouse over top of
11956 it, and not being pressed, etc.
11957 <item>PRELIGHT - When the mouse is over top of the widget, colors defined
11958 using this state will be in effect.
11959 <item>ACTIVE - When the widget is pressed or clicked it will be active, and
11960 the attributes assigned by this tag will be in effect.
11961 <item>INSENSITIVE - When a widget is set insensitive, and cannot be
11962 activated, it will take these attributes.
11963 <item>SELECTED - When an object is selected, it takes these attributes.
11964 </itemize>
11965
11966 When using the "fg" and "bg" keywords to set the colors of widgets, the
11967 format is:
11968
11969 <tscreen><verb>
11970 fg[<STATE>] = { Red, Green, Blue }
11971 </verb></tscreen>
11972
11973 Where STATE is one of the above states (PRELIGHT, ACTIVE, etc), and the Red,
11974 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
11975 white. They must be in float form, or they will register as 0, so a straight 
11976 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
11977 doesn't matter if it's not recognized.  Unrecognized values are set to 0.
11978
11979 bg_pixmap is very similar to the above, except the colors are replaced by a
11980 filename.
11981
11982 pixmap_path is a list of paths separated by ":"'s.  These paths will be
11983 searched for any pixmap you specify.
11984
11985 The font directive is simply:
11986 <tscreen><verb>
11987 font = "<font name>"
11988 </verb></tscreen>
11989
11990 The only hard part is figuring out the font string. Using xfontsel or
11991 a similar utility should help.
11992
11993 The "widget_class" sets the style of a class of widgets. These classes are
11994 listed in the widget overview on the class hierarchy.
11995
11996 The "widget" directive sets a specifically named set of widgets to a
11997 given style, overriding any style set for the given widget class.
11998 These widgets are registered inside the application using the
11999 gtk_widget_set_name() call. This allows you to specify the attributes of a
12000 widget on a per widget basis, rather than setting the attributes of an
12001 entire widget class. I urge you to document any of these special widgets so
12002 users may customize them.
12003
12004 When the keyword <tt>parent</> is used as an attribute, the widget will take on
12005 the attributes of its parent in the application.
12006
12007 When defining a style, you may assign the attributes of a previously defined
12008 style to this new one.
12009
12010 <tscreen><verb>
12011 style "main_button" = "button"
12012 {
12013   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
12014   bg[PRELIGHT] = { 0.75, 0, 0 }
12015 }
12016 </verb></tscreen>
12017
12018 This example takes the "button" style, and creates a new "main_button" style
12019 simply by changing the font and prelight background color of the "button"
12020 style.
12021
12022 Of course, many of these attributes don't apply to all widgets. It's a
12023 simple matter of common sense really. Anything that could apply, should.
12024
12025 <!-- ----------------------------------------------------------------- -->
12026 <sect1>Example rc file
12027 <p>
12028
12029 <tscreen><verb>
12030 # pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
12031 #
12032 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
12033 #
12034 # style <name> [= <name>]
12035 # {
12036 #   <option>
12037 # }
12038 #
12039 # widget <widget_set> style <style_name>
12040 # widget_class <widget_class_set> style <style_name>
12041
12042
12043 # Here is a list of all the possible states.  Note that some do not apply to
12044 # certain widgets.
12045 #
12046 # NORMAL - The normal state of a widget, without the mouse over top of
12047 # it, and not being pressed, etc.
12048 #
12049 # PRELIGHT - When the mouse is over top of the widget, colors defined
12050 # using this state will be in effect.
12051 #
12052 # ACTIVE - When the widget is pressed or clicked it will be active, and
12053 # the attributes assigned by this tag will be in effect.
12054 #
12055 # INSENSITIVE - When a widget is set insensitive, and cannot be
12056 # activated, it will take these attributes.
12057 #
12058 # SELECTED - When an object is selected, it takes these attributes.
12059 #
12060 # Given these states, we can set the attributes of the widgets in each of
12061 # these states using the following directives.
12062 #
12063 # fg - Sets the foreground color of a widget.
12064 # fg - Sets the background color of a widget.
12065 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
12066 # font - Sets the font to be used with the given widget.
12067 #
12068
12069 # This sets a style called "button".  The name is not really important, as
12070 # it is assigned to the actual widgets at the bottom of the file.
12071
12072 style "window"
12073 {
12074   #This sets the padding around the window to the pixmap specified.
12075   #bg_pixmap[<STATE>] = "<pixmap filename>"
12076   bg_pixmap[NORMAL] = "warning.xpm"
12077 }
12078
12079 style "scale"
12080 {
12081   #Sets the foreground color (font color) to red when in the "NORMAL"
12082   #state.
12083   
12084   fg[NORMAL] = { 1.0, 0, 0 }
12085   
12086   #Sets the background pixmap of this widget to that of its parent.
12087   bg_pixmap[NORMAL] = "<parent>"
12088 }
12089
12090 style "button"
12091 {
12092   # This shows all the possible states for a button.  The only one that
12093   # doesn't apply is the SELECTED state.
12094   
12095   fg[PRELIGHT] = { 0, 1.0, 1.0 }
12096   bg[PRELIGHT] = { 0, 0, 1.0 }
12097   bg[ACTIVE] = { 1.0, 0, 0 }
12098   fg[ACTIVE] = { 0, 1.0, 0 }
12099   bg[NORMAL] = { 1.0, 1.0, 0 }
12100   fg[NORMAL] = { .99, 0, .99 }
12101   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
12102   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
12103 }
12104
12105 # In this example, we inherit the attributes of the "button" style and then
12106 # override the font and background color when prelit to create a new
12107 # "main_button" style.
12108
12109 style "main_button" = "button"
12110 {
12111   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
12112   bg[PRELIGHT] = { 0.75, 0, 0 }
12113 }
12114
12115 style "toggle_button" = "button"
12116 {
12117   fg[NORMAL] = { 1.0, 0, 0 }
12118   fg[ACTIVE] = { 1.0, 0, 0 }
12119   
12120   # This sets the background pixmap of the toggle_button to that of its
12121   # parent widget (as defined in the application).
12122   bg_pixmap[NORMAL] = "<parent>"
12123 }
12124
12125 style "text"
12126 {
12127   bg_pixmap[NORMAL] = "marble.xpm"
12128   fg[NORMAL] = { 1.0, 1.0, 1.0 }
12129 }
12130
12131 style "ruler"
12132 {
12133   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
12134 }
12135
12136 # pixmap_path "~/.pixmaps"
12137
12138 # These set the widget types to use the styles defined above.
12139 # The widget types are listed in the class hierarchy, but could probably be
12140 # just listed in this document for the users reference.
12141
12142 widget_class "GtkWindow" style "window"
12143 widget_class "GtkDialog" style "window"
12144 widget_class "GtkFileSelection" style "window"
12145 widget_class "*Gtk*Scale" style "scale"
12146 widget_class "*GtkCheckButton*" style "toggle_button"
12147 widget_class "*GtkRadioButton*" style "toggle_button"
12148 widget_class "*GtkButton*" style "button"
12149 widget_class "*Ruler" style "ruler"
12150 widget_class "*GtkText" style "text"
12151
12152 # This sets all the buttons that are children of the "main window" to
12153 # the main_button style.  These must be documented to be taken advantage of.
12154 widget "main window.*GtkButton*" style "main_button"
12155 </verb></tscreen>
12156
12157 <!-- ***************************************************************** -->
12158 <sect>Writing Your Own Widgets 
12159 <!-- ***************************************************************** -->
12160
12161 <!-- ----------------------------------------------------------------- -->
12162 <sect1> Overview
12163 <p>
12164 Although the GTK distribution comes with many types of widgets that
12165 should cover most basic needs, there may come a time when you need to
12166 create your own new widget type. Since GTK uses widget inheritance
12167 extensively, and there is already a widget that is close to what you want,
12168 it is often possible to make a useful new widget type in
12169 just a few lines of code. But before starting work on a new widget, check
12170 around first to make sure that someone has not already written
12171 it. This will prevent duplication of effort and keep the number of
12172 GTK widgets out there to a minimum, which will help keep both the code
12173 and the interface of different applications consistent. As a flip side
12174 to this, once you finish your widget, announce it to the world so
12175 other people can benefit. The best place to do this is probably the
12176 <tt>gtk-list</tt>.
12177
12178 Complete sources for the example widgets are available at the place you 
12179 got this tutorial, or from:
12180
12181 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
12182 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
12183
12184
12185 <!-- ----------------------------------------------------------------- -->
12186 <sect1> The Anatomy Of A Widget
12187 <p>
12188 In order to create a new widget, it is important to have an
12189 understanding of how GTK objects work. This section is just meant as a
12190 brief overview. See the reference documentation for the details. 
12191
12192 GTK widgets are implemented in an object oriented fashion. However,
12193 they are implemented in standard C. This greatly improves portability
12194 and stability over using current generation C++ compilers; however,
12195 it does mean that the widget writer has to pay attention to some of
12196 the implementation details. The information common to all instances of
12197 one class of widgets (e.g., to all Button widgets) is stored in the 
12198 <em>class structure</em>. There is only one copy of this in
12199 which is stored information about the class's signals
12200 (which act like virtual functions in C). To support inheritance, the
12201 first field in the class structure must be a copy of the parent's
12202 class structure. The declaration of the class structure of GtkButtton
12203 looks like:
12204
12205 <tscreen><verb>
12206 struct _GtkButtonClass
12207 {
12208   GtkContainerClass parent_class;
12209
12210   void (* pressed)  (GtkButton *button);
12211   void (* released) (GtkButton *button);
12212   void (* clicked)  (GtkButton *button);
12213   void (* enter)    (GtkButton *button);
12214   void (* leave)    (GtkButton *button);
12215 };
12216 </verb></tscreen>
12217
12218 When a button is treated as a container (for instance, when it is
12219 resized), its class structure can be cast to GtkContainerClass, and
12220 the relevant fields used to handle the signals.
12221
12222 There is also a structure for each widget that is created on a
12223 per-instance basis. This structure has fields to store information that
12224 is different for each instance of the widget. We'll call this
12225 structure the <em>object structure</em>. For the Button class, it looks
12226 like:
12227
12228 <tscreen><verb>
12229 struct _GtkButton
12230 {
12231   GtkContainer container;
12232
12233   GtkWidget *child;
12234
12235   guint in_button : 1;
12236   guint button_down : 1;
12237 };
12238 </verb></tscreen>
12239
12240 Note that, similar to the class structure, the first field is the
12241 object structure of the parent class, so that this structure can be
12242 cast to the parent class' object structure as needed.
12243
12244 <!-- ----------------------------------------------------------------- -->
12245 <sect1> Creating a Composite widget
12246
12247 <!-- ----------------------------------------------------------------- -->
12248 <sect2> Introduction
12249 <p>
12250 One type of widget that you may be interested in creating is a
12251 widget that is merely an aggregate of other GTK widgets. This type of
12252 widget does nothing that couldn't be done without creating new
12253 widgets, but provides a convenient way of packaging user interface
12254 elements for reuse. The FileSelection and ColorSelection widgets in
12255 the standard distribution are examples of this type of widget.
12256
12257 The example widget that we'll create in this section is the Tictactoe
12258 widget, a 3x3 array of toggle buttons which triggers a signal when all
12259 three buttons in a row, column, or on one of the diagonals are
12260 depressed. 
12261
12262 <!-- ----------------------------------------------------------------- -->
12263 <sect2> Choosing a parent class
12264 <p>
12265 The parent class for a composite widget is typically the container
12266 class that holds all of the elements of the composite widget. For
12267 example, the parent class of the FileSelection widget is the
12268 Dialog class. Since our buttons will be arranged in a table, it
12269 might seem natural to make our parent class the Table
12270 class. Unfortunately, this turns out not to work. The creation of a
12271 widget is divided among two functions - a <tt/WIDGETNAME_new()/
12272 function that the user calls, and a <tt/WIDGETNAME_init()/ function
12273 which does the basic work of initializing the widget which is
12274 independent of the arguments passed to the <tt/_new()/
12275 function. Descendant widgets only call the <tt/_init/ function of
12276 their parent widget. But this division of labor doesn't work well for
12277 tables, which when created need to know the number of rows and
12278 columns in the table. Unless we want to duplicate most of the
12279 functionality of <tt/gtk_table_new()/ in our Tictactoe widget, we had
12280 best avoid deriving it from Table. For that reason, we derive it
12281 from VBox instead, and stick our table inside the VBox.
12282
12283 <!-- ----------------------------------------------------------------- -->
12284 <sect2> The header file
12285 <p>
12286 Each widget class has a header file which declares the object and
12287 class structures for that widget, along with public functions. 
12288 A couple of features are worth pointing out. To prevent duplicate
12289 definitions, we wrap the entire header file in:
12290
12291 <tscreen><verb>
12292 #ifndef __TICTACTOE_H__
12293 #define __TICTACTOE_H__
12294 .
12295 .
12296 .
12297 #endif /* __TICTACTOE_H__ */
12298 </verb></tscreen>
12299
12300 And to keep C++ programs that include the header file happy, in:
12301
12302 <tscreen><verb>
12303 #ifdef __cplusplus
12304 extern "C" {
12305 #endif /* __cplusplus */
12306 .
12307 .
12308 .
12309 #ifdef __cplusplus
12310 }
12311 #endif /* __cplusplus */
12312 </verb></tscreen>
12313
12314 Along with the functions and structures, we declare three standard
12315 macros in our header file, <tt/TICTACTOE(obj)/,
12316 <tt/TICTACTOE_CLASS(klass)/, and <tt/IS_TICTACTOE(obj)/, which cast a
12317 pointer into a pointer to the object or class structure, and check
12318 if an object is a Tictactoe widget respectively.
12319
12320 Here is the complete header file:
12321
12322 <tscreen><verb>
12323 /* tictactoe.h */
12324
12325 #ifndef __TICTACTOE_H__
12326 #define __TICTACTOE_H__
12327
12328 #include <gdk/gdk.h>
12329 #include <gtk/gtkvbox.h>
12330
12331 #ifdef __cplusplus
12332 extern "C" {
12333 #endif /* __cplusplus */
12334
12335 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
12336 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
12337 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
12338
12339
12340 typedef struct _Tictactoe       Tictactoe;
12341 typedef struct _TictactoeClass  TictactoeClass;
12342
12343 struct _Tictactoe
12344 {
12345   GtkVBox vbox;
12346   
12347   GtkWidget *buttons[3][3];
12348 };
12349
12350 struct _TictactoeClass
12351 {
12352   GtkVBoxClass parent_class;
12353
12354   void (* tictactoe) (Tictactoe *ttt);
12355 };
12356
12357 guint          tictactoe_get_type        (void);
12358 GtkWidget*     tictactoe_new             (void);
12359 void           tictactoe_clear           (Tictactoe *ttt);
12360
12361 #ifdef __cplusplus
12362 }
12363 #endif /* __cplusplus */
12364
12365 #endif /* __TICTACTOE_H__ */
12366
12367 </verb></tscreen>
12368
12369 <!-- ----------------------------------------------------------------- -->
12370 <sect2> The <tt/_get_type()/ function.
12371 <p>
12372 We now continue on to the implementation of our widget. A core
12373 function for every widget is the function
12374 <tt/WIDGETNAME_get_type()/. This function, when first called, tells
12375 GTK about the widget class, and gets an ID that uniquely identifies
12376 the widget class. Upon subsequent calls, it just returns the ID.
12377
12378 <tscreen><verb>
12379 guint
12380 tictactoe_get_type ()
12381 {
12382   static guint ttt_type = 0;
12383
12384   if (!ttt_type)
12385     {
12386       GtkTypeInfo ttt_info =
12387       {
12388         "Tictactoe",
12389         sizeof (Tictactoe),
12390         sizeof (TictactoeClass),
12391         (GtkClassInitFunc) tictactoe_class_init,
12392         (GtkObjectInitFunc) tictactoe_init,
12393         (GtkArgSetFunc) NULL,
12394         (GtkArgGetFunc) NULL
12395       };
12396
12397       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
12398     }
12399
12400   return ttt_type;
12401 }
12402 </verb></tscreen>
12403
12404 The GtkTypeInfo structure has the following definition:
12405
12406 <tscreen><verb>
12407 struct _GtkTypeInfo
12408 {
12409   gchar *type_name;
12410   guint object_size;
12411   guint class_size;
12412   GtkClassInitFunc class_init_func;
12413   GtkObjectInitFunc object_init_func;
12414   GtkArgSetFunc arg_set_func;
12415   GtkArgGetFunc arg_get_func;
12416 };
12417 </verb></tscreen>
12418
12419 The fields of this structure are pretty self-explanatory. We'll ignore
12420 the <tt/arg_set_func/ and <tt/arg_get_func/ fields here: they have an important, 
12421 but as yet largely
12422 unimplemented, role in allowing widget options to be conveniently set
12423 from interpreted languages. Once GTK has a correctly filled in copy of
12424 this structure, it knows how to create objects of a particular widget
12425 type. 
12426
12427 <!-- ----------------------------------------------------------------- -->
12428 <sect2> The <tt/_class_init()/ function
12429 <p>
12430 The <tt/WIDGETNAME_class_init()/ function initializes the fields of
12431 the widget's class structure, and sets up any signals for the
12432 class. For our Tictactoe widget it looks like:
12433
12434 <tscreen><verb>
12435
12436 enum {
12437   TICTACTOE_SIGNAL,
12438   LAST_SIGNAL
12439 };
12440
12441 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
12442
12443 static void
12444 tictactoe_class_init (TictactoeClass *class)
12445 {
12446   GtkObjectClass *object_class;
12447
12448   object_class = (GtkObjectClass*) class;
12449   
12450   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
12451                                          GTK_RUN_FIRST,
12452                                          object_class->type,
12453                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
12454                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
12455
12456
12457   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
12458
12459   class->tictactoe = NULL;
12460 }
12461 </verb></tscreen>
12462
12463 Our widget has just one signal, the <tt/tictactoe/ signal that is
12464 invoked when a row, column, or diagonal is completely filled in. Not
12465 every composite widget needs signals, so if you are reading this for
12466 the first time, you may want to skip to the next section now, as
12467 things are going to get a bit complicated.
12468
12469 The function:
12470
12471 <tscreen><verb>
12472 gint gtk_signal_new( const gchar         *name,
12473                      GtkSignalRunType     run_type,
12474                      GtkType              object_type,
12475                      gint                 function_offset,
12476                      GtkSignalMarshaller  marshaller,
12477                      GtkType              return_val,
12478                      guint                nparams,
12479                      ...);
12480 </verb></tscreen>
12481
12482 Creates a new signal. The parameters are:
12483
12484 <itemize>
12485 <item> <tt/name/: The name of the signal.
12486 <item> <tt/run_type/: Whether the default handler runs before or after
12487 user handlers. Usually this will be <tt/GTK_RUN_FIRST/, or <tt/GTK_RUN_LAST/,
12488 although there are other possibilities.
12489 <item> <tt/object_type/: The ID of the object that this signal applies
12490 to. (It will also apply to that objects descendants.)
12491 <item> <tt/function_offset/: The offset within the class structure of
12492 a pointer to the default handler.
12493 <item> <tt/marshaller/: A function that is used to invoke the signal
12494 handler. For signal handlers that have no arguments other than the
12495 object that emitted the signal and user data, we can use the
12496 pre-supplied marshaller function <tt/gtk_signal_default_marshaller/.
12497 <item> <tt/return_val/: The type of the return val.
12498 <item> <tt/nparams/: The number of parameters of the signal handler
12499 (other than the two default ones mentioned above)
12500 <item> <tt/.../: The types of the parameters.
12501 </itemize>
12502
12503 When specifying types, the <tt/GtkType/ enumeration is used:
12504
12505 <tscreen><verb>
12506 typedef enum
12507 {
12508   GTK_TYPE_INVALID,
12509   GTK_TYPE_NONE,
12510   GTK_TYPE_CHAR,
12511   GTK_TYPE_BOOL,
12512   GTK_TYPE_INT,
12513   GTK_TYPE_UINT,
12514   GTK_TYPE_LONG,
12515   GTK_TYPE_ULONG,
12516   GTK_TYPE_FLOAT,
12517   GTK_TYPE_DOUBLE,
12518   GTK_TYPE_STRING,
12519   GTK_TYPE_ENUM,
12520   GTK_TYPE_FLAGS,
12521   GTK_TYPE_BOXED,
12522   GTK_TYPE_FOREIGN,
12523   GTK_TYPE_CALLBACK,
12524   GTK_TYPE_ARGS,
12525
12526   GTK_TYPE_POINTER,
12527
12528   /* it'd be great if the next two could be removed eventually */
12529   GTK_TYPE_SIGNAL,
12530   GTK_TYPE_C_CALLBACK,
12531
12532   GTK_TYPE_OBJECT
12533
12534 } GtkFundamentalType;
12535 </verb></tscreen>
12536
12537 <tt/gtk_signal_new()/ returns a unique integer identifier for the
12538 signal, that we store in the <tt/tictactoe_signals/ array, which we
12539 index using an enumeration. (Conventionally, the enumeration elements
12540 are the signal name, uppercased, but here there would be a conflict
12541 with the <tt/TICTACTOE()/ macro, so we called it <tt/TICTACTOE_SIGNAL/
12542 instead.
12543
12544 After creating our signals, we need to tell GTK to associate our
12545 signals with the Tictactoe class. We do that by calling
12546 <tt/gtk_object_class_add_signals()/. We then set the pointer which
12547 points to the default handler for the "tictactoe" signal to NULL,
12548 indicating that there is no default action.
12549
12550 <!-- ----------------------------------------------------------------- -->
12551 <sect2> The <tt/_init()/ function.
12552 <p>
12553 Each widget class also needs a function to initialize the object
12554 structure. Usually, this function has the fairly limited role of
12555 setting the fields of the structure to default values. For composite
12556 widgets, however, this function also creates the component widgets.
12557
12558 <tscreen><verb>
12559 static void
12560 tictactoe_init (Tictactoe *ttt)
12561 {
12562   GtkWidget *table;
12563   gint i,j;
12564   
12565   table = gtk_table_new (3, 3, TRUE);
12566   gtk_container_add (GTK_CONTAINER(ttt), table);
12567   gtk_widget_show (table);
12568
12569   for (i=0;i<3; i++)
12570     for (j=0;j<3; j++)
12571       {
12572         ttt->buttons[i][j] = gtk_toggle_button_new ();
12573         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
12574                                    i, i+1, j, j+1);
12575         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
12576                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
12577         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
12578         gtk_widget_show (ttt->buttons[i][j]);
12579       }
12580 }
12581 </verb></tscreen>
12582
12583 <!-- ----------------------------------------------------------------- -->
12584 <sect2> And the rest...
12585 <p>
12586 There is one more function that every widget (except for base widget
12587 types like Bin that cannot be instantiated) needs to have - the
12588 function that the user calls to create an object of that type. This is
12589 conventionally called <tt/WIDGETNAME_new()/. In some
12590 widgets, though not for the Tictactoe widgets, this function takes
12591 arguments, and does some setup based on the arguments. The other two
12592 functions are specific to the Tictactoe widget. 
12593
12594 <tt/tictactoe_clear()/ is a public function that resets all the
12595 buttons in the widget to the up position. Note the use of
12596 <tt/gtk_signal_handler_block_by_data()/ to keep our signal handler for
12597 button toggles from being triggered unnecessarily.
12598
12599 <tt/tictactoe_toggle()/ is the signal handler that is invoked when the
12600 user clicks on a button. It checks to see if there are any winning
12601 combinations that involve the toggled button, and if so, emits
12602 the "tictactoe" signal.
12603
12604 <tscreen><verb>  
12605 GtkWidget*
12606 tictactoe_new ()
12607 {
12608   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
12609 }
12610
12611 void           
12612 tictactoe_clear (Tictactoe *ttt)
12613 {
12614   int i,j;
12615
12616   for (i=0;i<3;i++)
12617     for (j=0;j<3;j++)
12618       {
12619         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
12620         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
12621                                      FALSE);
12622         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
12623       }
12624 }
12625
12626 static void
12627 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
12628 {
12629   int i,k;
12630
12631   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
12632                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
12633                              { 0, 1, 2 }, { 0, 1, 2 } };
12634   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
12635                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
12636                              { 0, 1, 2 }, { 2, 1, 0 } };
12637
12638   int success, found;
12639
12640   for (k=0; k<8; k++)
12641     {
12642       success = TRUE;
12643       found = FALSE;
12644
12645       for (i=0;i<3;i++)
12646         {
12647           success = success &amp;&amp; 
12648             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
12649           found = found ||
12650             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
12651         }
12652       
12653       if (success &amp;&amp; found)
12654         {
12655           gtk_signal_emit (GTK_OBJECT (ttt), 
12656                            tictactoe_signals[TICTACTOE_SIGNAL]);
12657           break;
12658         }
12659     }
12660 }
12661 </verb></tscreen>
12662
12663 And finally, an example program using our Tictactoe widget:
12664
12665 <tscreen><verb>
12666 #include <gtk/gtk.h>
12667 #include "tictactoe.h"
12668
12669 /* Invoked when a row, column or diagonal is completed */
12670 void
12671 win (GtkWidget *widget, gpointer data)
12672 {
12673   g_print ("Yay!\n");
12674   tictactoe_clear (TICTACTOE (widget));
12675 }
12676
12677 int 
12678 main (int argc, char *argv[])
12679 {
12680   GtkWidget *window;
12681   GtkWidget *ttt;
12682   
12683   gtk_init (&amp;argc, &amp;argv);
12684
12685   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12686   
12687   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
12688   
12689   gtk_signal_connect (GTK_OBJECT (window), "destroy",
12690                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
12691   
12692   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12693
12694   /* Create a new Tictactoe widget */
12695   ttt = tictactoe_new ();
12696   gtk_container_add (GTK_CONTAINER (window), ttt);
12697   gtk_widget_show (ttt);
12698
12699   /* And attach to its "tictactoe" signal */
12700   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
12701                       GTK_SIGNAL_FUNC (win), NULL);
12702
12703   gtk_widget_show (window);
12704   
12705   gtk_main ();
12706   
12707   return 0;
12708 }
12709
12710 </verb></tscreen>
12711
12712 <!-- ----------------------------------------------------------------- -->
12713 <sect1> Creating a widget from scratch.
12714
12715 <!-- ----------------------------------------------------------------- -->
12716 <sect2> Introduction
12717 <p>
12718 In this section, we'll learn more about how widgets display themselves
12719 on the screen and interact with events. As an example of this, we'll
12720 create an analog dial widget with a pointer that the user can drag to
12721 set the value.
12722
12723 <!-- ----------------------------------------------------------------- -->
12724 <sect2> Displaying a widget on the screen
12725 <p>
12726 There are several steps that are involved in displaying on the screen.
12727 After the widget is created with a call to <tt/WIDGETNAME_new()/,
12728 several more functions are needed:
12729
12730 <itemize>
12731 <item> <tt/WIDGETNAME_realize()/ is responsible for creating an X
12732 window for the widget if it has one.
12733 <item> <tt/WIDGETNAME_map()/ is invoked after the user calls
12734 <tt/gtk_widget_show()/. It is responsible for making sure the widget
12735 is actually drawn on the screen (<em/mapped/). For a container class,
12736 it must also make calls to <tt/map()/> functions of any child widgets.
12737 <item> <tt/WIDGETNAME_draw()/ is invoked when <tt/gtk_widget_draw()/
12738 is called for the widget or one of its ancestors. It makes the actual
12739 calls to the drawing functions to draw the widget on the screen. For
12740 container widgets, this function must make calls to
12741 <tt/gtk_widget_draw()/ for its child widgets.
12742 <item> <tt/WIDGETNAME_expose()/ is a handler for expose events for the
12743 widget. It makes the necessary calls to the drawing functions to draw
12744 the exposed portion on the screen. For container widgets, this
12745 function must generate expose events for its child widgets which don't
12746 have their own windows. (If they have their own windows, then X will
12747 generate the necessary expose events.)
12748 </itemize>
12749
12750 You might notice that the last two functions are quite similar - each
12751 is responsible for drawing the widget on the screen. In fact many
12752 types of widgets don't really care about the difference between the
12753 two. The default <tt/draw()/ function in the widget class simply
12754 generates a synthetic expose event for the redrawn area. However, some
12755 types of widgets can save work by distinguishing between the two
12756 functions. For instance, if a widget has multiple X windows, then
12757 since expose events identify the exposed window, it can redraw only
12758 the affected window, which is not possible for calls to <tt/draw()/.
12759
12760 Container widgets, even if they don't care about the difference for
12761 themselves, can't simply use the default <tt/draw()/ function because
12762 their child widgets might care about the difference. However,
12763 it would be wasteful to duplicate the drawing code between the two
12764 functions. The convention is that such widgets have a function called
12765 <tt/WIDGETNAME_paint()/ that does the actual work of drawing the
12766 widget, that is then called by the <tt/draw()/ and <tt/expose()/
12767 functions.
12768
12769 In our example approach, since the dial widget is not a container
12770 widget, and only has a single window, we can take the simplest
12771 approach and use the default <tt/draw()/ function and only implement
12772 an <tt/expose()/ function.
12773
12774 <!-- ----------------------------------------------------------------- -->
12775 <sect2> The origins of the Dial Widget
12776 <p>
12777 Just as all land animals are just variants on the first amphibian that
12778 crawled up out of the mud, GTK widgets tend to start off as variants
12779 of some other, previously written widget. Thus, although this section
12780 is entitled "Creating a Widget from Scratch", the Dial widget really
12781 began with the source code for the Range widget. This was picked as a
12782 starting point because it would be nice if our Dial had the same
12783 interface as the Scale widgets which are just specialized descendants
12784 of the Range widget. So, though the source code is presented below in
12785 finished form, it should not be implied that it was written, <em>ab
12786 initio</em> in this fashion. Also, if you aren't yet familiar with
12787 how scale widgets work from the application writer's point of view, it
12788 would be a good idea to look them over before continuing.
12789
12790 <!-- ----------------------------------------------------------------- -->
12791 <sect2> The Basics
12792 <p>
12793 Quite a bit of our widget should look pretty familiar from the
12794 Tictactoe widget. First, we have a header file:
12795
12796 <tscreen><verb>
12797 /* GTK - The GIMP Toolkit
12798  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
12799  *
12800  * This library is free software; you can redistribute it and/or
12801  * modify it under the terms of the GNU Library General Public
12802  * License as published by the Free Software Foundation; either
12803  * version 2 of the License, or (at your option) any later version.
12804  *
12805  * This library is distributed in the hope that it will be useful,
12806  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12807  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12808  * Library General Public License for more details.
12809  *
12810  * You should have received a copy of the GNU Library General Public
12811  * License along with this library; if not, write to the Free
12812  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
12813  */
12814
12815 #ifndef __GTK_DIAL_H__
12816 #define __GTK_DIAL_H__
12817
12818 #include <gdk/gdk.h>
12819 #include <gtk/gtkadjustment.h>
12820 #include <gtk/gtkwidget.h>
12821
12822
12823 #ifdef __cplusplus
12824 extern "C" {
12825 #endif /* __cplusplus */
12826
12827
12828 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
12829 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
12830 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
12831
12832
12833 typedef struct _GtkDial        GtkDial;
12834 typedef struct _GtkDialClass   GtkDialClass;
12835
12836 struct _GtkDial
12837 {
12838   GtkWidget widget;
12839
12840   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
12841   guint policy : 2;
12842
12843   /* Button currently pressed or 0 if none */
12844   guint8 button;
12845
12846   /* Dimensions of dial components */
12847   gint radius;
12848   gint pointer_width;
12849
12850   /* ID of update timer, or 0 if none */
12851   guint32 timer;
12852
12853   /* Current angle */
12854   gfloat angle;
12855
12856   /* Old values from adjustment stored so we know when something changes */
12857   gfloat old_value;
12858   gfloat old_lower;
12859   gfloat old_upper;
12860
12861   /* The adjustment object that stores the data for this dial */
12862   GtkAdjustment *adjustment;
12863 };
12864
12865 struct _GtkDialClass
12866 {
12867   GtkWidgetClass parent_class;
12868 };
12869
12870
12871 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
12872 guint          gtk_dial_get_type               (void);
12873 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
12874 void           gtk_dial_set_update_policy      (GtkDial      *dial,
12875                                                 GtkUpdateType  policy);
12876
12877 void           gtk_dial_set_adjustment         (GtkDial      *dial,
12878                                                 GtkAdjustment *adjustment);
12879 #ifdef __cplusplus
12880 }
12881 #endif /* __cplusplus */
12882
12883
12884 #endif /* __GTK_DIAL_H__ */
12885 </verb></tscreen>
12886
12887 Since there is quite a bit more going on in this widget than the last
12888 one, we have more fields in the data structure, but otherwise things
12889 are pretty similar.
12890
12891 Next, after including header files and declaring a few constants,
12892 we have some functions to provide information about the widget
12893 and initialize it:
12894
12895 <tscreen><verb>
12896 #include <math.h>
12897 #include <stdio.h>
12898 #include <gtk/gtkmain.h>
12899 #include <gtk/gtksignal.h>
12900
12901 #include "gtkdial.h"
12902
12903 #define SCROLL_DELAY_LENGTH  300
12904 #define DIAL_DEFAULT_SIZE 100
12905
12906 /* Forward declarations */
12907
12908 [ omitted to save space ]
12909
12910 /* Local data */
12911
12912 static GtkWidgetClass *parent_class = NULL;
12913
12914 guint
12915 gtk_dial_get_type ()
12916 {
12917   static guint dial_type = 0;
12918
12919   if (!dial_type)
12920     {
12921       GtkTypeInfo dial_info =
12922       {
12923         "GtkDial",
12924         sizeof (GtkDial),
12925         sizeof (GtkDialClass),
12926         (GtkClassInitFunc) gtk_dial_class_init,
12927         (GtkObjectInitFunc) gtk_dial_init,
12928         (GtkArgSetFunc) NULL,
12929         (GtkArgGetFunc) NULL,
12930       };
12931
12932       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
12933     }
12934
12935   return dial_type;
12936 }
12937
12938 static void
12939 gtk_dial_class_init (GtkDialClass *class)
12940 {
12941   GtkObjectClass *object_class;
12942   GtkWidgetClass *widget_class;
12943
12944   object_class = (GtkObjectClass*) class;
12945   widget_class = (GtkWidgetClass*) class;
12946
12947   parent_class = gtk_type_class (gtk_widget_get_type ());
12948
12949   object_class->destroy = gtk_dial_destroy;
12950
12951   widget_class->realize = gtk_dial_realize;
12952   widget_class->expose_event = gtk_dial_expose;
12953   widget_class->size_request = gtk_dial_size_request;
12954   widget_class->size_allocate = gtk_dial_size_allocate;
12955   widget_class->button_press_event = gtk_dial_button_press;
12956   widget_class->button_release_event = gtk_dial_button_release;
12957   widget_class->motion_notify_event = gtk_dial_motion_notify;
12958 }
12959
12960 static void
12961 gtk_dial_init (GtkDial *dial)
12962 {
12963   dial->button = 0;
12964   dial->policy = GTK_UPDATE_CONTINUOUS;
12965   dial->timer = 0;
12966   dial->radius = 0;
12967   dial->pointer_width = 0;
12968   dial->angle = 0.0;
12969   dial->old_value = 0.0;
12970   dial->old_lower = 0.0;
12971   dial->old_upper = 0.0;
12972   dial->adjustment = NULL;
12973 }
12974
12975 GtkWidget*
12976 gtk_dial_new (GtkAdjustment *adjustment)
12977 {
12978   GtkDial *dial;
12979
12980   dial = gtk_type_new (gtk_dial_get_type ());
12981
12982   if (!adjustment)
12983     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
12984
12985   gtk_dial_set_adjustment (dial, adjustment);
12986
12987   return GTK_WIDGET (dial);
12988 }
12989
12990 static void
12991 gtk_dial_destroy (GtkObject *object)
12992 {
12993   GtkDial *dial;
12994
12995   g_return_if_fail (object != NULL);
12996   g_return_if_fail (GTK_IS_DIAL (object));
12997
12998   dial = GTK_DIAL (object);
12999
13000   if (dial->adjustment)
13001     gtk_object_unref (GTK_OBJECT (dial->adjustment));
13002
13003   if (GTK_OBJECT_CLASS (parent_class)->destroy)
13004     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
13005 }
13006 </verb></tscreen>
13007
13008 Note that this <tt/init()/ function does less than for the Tictactoe
13009 widget, since this is not a composite widget, and the <tt/new()/
13010 function does more, since it now has an argument. Also, note that when
13011 we store a pointer to the Adjustment object, we increment its
13012 reference count, (and correspondingly decrement it when we no longer
13013 use it) so that GTK can keep track of when it can be safely destroyed.
13014
13015 <p>
13016 Also, there are a few function to manipulate the widget's options:
13017
13018 <tscreen><verb>
13019 GtkAdjustment*
13020 gtk_dial_get_adjustment (GtkDial *dial)
13021 {
13022   g_return_val_if_fail (dial != NULL, NULL);
13023   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
13024
13025   return dial->adjustment;
13026 }
13027
13028 void
13029 gtk_dial_set_update_policy (GtkDial      *dial,
13030                              GtkUpdateType  policy)
13031 {
13032   g_return_if_fail (dial != NULL);
13033   g_return_if_fail (GTK_IS_DIAL (dial));
13034
13035   dial->policy = policy;
13036 }
13037
13038 void
13039 gtk_dial_set_adjustment (GtkDial      *dial,
13040                           GtkAdjustment *adjustment)
13041 {
13042   g_return_if_fail (dial != NULL);
13043   g_return_if_fail (GTK_IS_DIAL (dial));
13044
13045   if (dial->adjustment)
13046     {
13047       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
13048       gtk_object_unref (GTK_OBJECT (dial->adjustment));
13049     }
13050
13051   dial->adjustment = adjustment;
13052   gtk_object_ref (GTK_OBJECT (dial->adjustment));
13053
13054   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
13055                       (GtkSignalFunc) gtk_dial_adjustment_changed,
13056                       (gpointer) dial);
13057   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
13058                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
13059                       (gpointer) dial);
13060
13061   dial->old_value = adjustment->value;
13062   dial->old_lower = adjustment->lower;
13063   dial->old_upper = adjustment->upper;
13064
13065   gtk_dial_update (dial);
13066 }
13067 </verb></tscreen>
13068
13069 <sect2> <tt/gtk_dial_realize()/
13070
13071 <p>
13072 Now we come to some new types of functions. First, we have a function
13073 that does the work of creating the X window. Notice that a mask is
13074 passed to the function <tt/gdk_window_new()/ which specifies which fields of
13075 the GdkWindowAttr structure actually have data in them (the remaining
13076 fields will be given default values). Also worth noting is the way the
13077 event mask of the widget is created. We call
13078 <tt/gtk_widget_get_events()/ to retrieve the event mask that the user
13079 has specified for this widget (with <tt/gtk_widget_set_events()/), and
13080 add the events that we are interested in ourselves.
13081
13082 <p>
13083 After creating the window, we set its style and background, and put a
13084 pointer to the widget in the user data field of the GdkWindow. This
13085 last step allows GTK to dispatch events for this window to the correct
13086 widget.
13087
13088 <tscreen><verb>
13089 static void
13090 gtk_dial_realize (GtkWidget *widget)
13091 {
13092   GtkDial *dial;
13093   GdkWindowAttr attributes;
13094   gint attributes_mask;
13095
13096   g_return_if_fail (widget != NULL);
13097   g_return_if_fail (GTK_IS_DIAL (widget));
13098
13099   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
13100   dial = GTK_DIAL (widget);
13101
13102   attributes.x = widget->allocation.x;
13103   attributes.y = widget->allocation.y;
13104   attributes.width = widget->allocation.width;
13105   attributes.height = widget->allocation.height;
13106   attributes.wclass = GDK_INPUT_OUTPUT;
13107   attributes.window_type = GDK_WINDOW_CHILD;
13108   attributes.event_mask = gtk_widget_get_events (widget) | 
13109     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
13110     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
13111     GDK_POINTER_MOTION_HINT_MASK;
13112   attributes.visual = gtk_widget_get_visual (widget);
13113   attributes.colormap = gtk_widget_get_colormap (widget);
13114
13115   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
13116   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
13117
13118   widget->style = gtk_style_attach (widget->style, widget->window);
13119
13120   gdk_window_set_user_data (widget->window, widget);
13121
13122   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
13123 }
13124 </verb></tscreen>
13125
13126 <sect2> Size negotiation
13127
13128 <p>
13129 Before the first time that the window containing a widget is
13130 displayed, and whenever the layout of the window changes, GTK asks
13131 each child widget for its desired size. This request is handled by the
13132 function <tt/gtk_dial_size_request()/. Since our widget isn't a
13133 container widget, and has no real constraints on its size, we just
13134 return a reasonable default value.
13135
13136 <tscreen><verb>
13137 static void 
13138 gtk_dial_size_request (GtkWidget      *widget,
13139                        GtkRequisition *requisition)
13140 {
13141   requisition->width = DIAL_DEFAULT_SIZE;
13142   requisition->height = DIAL_DEFAULT_SIZE;
13143 }
13144 </verb></tscreen>
13145
13146 <p>
13147 After all the widgets have requested an ideal size, the layout of the
13148 window is computed and each child widget is notified of its actual
13149 size. Usually, this will be at least as large as the requested size,
13150 but if for instance the user has resized the window, it may
13151 occasionally be smaller than the requested size. The size notification
13152 is handled by the function <tt/gtk_dial_size_allocate()/. Notice that
13153 as well as computing the sizes of some component pieces for future
13154 use, this routine also does the grunt work of moving the widget's X
13155 window into the new position and size.
13156
13157 <tscreen><verb>
13158 static void
13159 gtk_dial_size_allocate (GtkWidget     *widget,
13160                         GtkAllocation *allocation)
13161 {
13162   GtkDial *dial;
13163
13164   g_return_if_fail (widget != NULL);
13165   g_return_if_fail (GTK_IS_DIAL (widget));
13166   g_return_if_fail (allocation != NULL);
13167
13168   widget->allocation = *allocation;
13169   if (GTK_WIDGET_REALIZED (widget))
13170     {
13171       dial = GTK_DIAL (widget);
13172
13173       gdk_window_move_resize (widget->window,
13174                               allocation->x, allocation->y,
13175                               allocation->width, allocation->height);
13176
13177       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
13178       dial->pointer_width = dial->radius / 5;
13179     }
13180 }
13181 </verb></tscreen>.
13182
13183 <!-- ----------------------------------------------------------------- -->
13184 <sect2> <tt/gtk_dial_expose()/
13185
13186 <p>
13187 As mentioned above, all the drawing of this widget is done in the
13188 handler for expose events. There's not much to remark on here except
13189 the use of the function <tt/gtk_draw_polygon/ to draw the pointer with
13190 three dimensional shading according to the colors stored in the
13191 widget's style.
13192
13193 <tscreen><verb>
13194 static gint
13195 gtk_dial_expose (GtkWidget      *widget,
13196                  GdkEventExpose *event)
13197 {
13198   GtkDial *dial;
13199   GdkPoint points[3];
13200   gdouble s,c;
13201   gdouble theta;
13202   gint xc, yc;
13203   gint tick_length;
13204   gint i;
13205
13206   g_return_val_if_fail (widget != NULL, FALSE);
13207   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13208   g_return_val_if_fail (event != NULL, FALSE);
13209
13210   if (event->count > 0)
13211     return FALSE;
13212   
13213   dial = GTK_DIAL (widget);
13214
13215   gdk_window_clear_area (widget->window,
13216                          0, 0,
13217                          widget->allocation.width,
13218                          widget->allocation.height);
13219
13220   xc = widget->allocation.width/2;
13221   yc = widget->allocation.height/2;
13222
13223   /* Draw ticks */
13224
13225   for (i=0; i<25; i++)
13226     {
13227       theta = (i*M_PI/18. - M_PI/6.);
13228       s = sin(theta);
13229       c = cos(theta);
13230
13231       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
13232       
13233       gdk_draw_line (widget->window,
13234                      widget->style->fg_gc[widget->state],
13235                      xc + c*(dial->radius - tick_length),
13236                      yc - s*(dial->radius - tick_length),
13237                      xc + c*dial->radius,
13238                      yc - s*dial->radius);
13239     }
13240
13241   /* Draw pointer */
13242
13243   s = sin(dial->angle);
13244   c = cos(dial->angle);
13245
13246
13247   points[0].x = xc + s*dial->pointer_width/2;
13248   points[0].y = yc + c*dial->pointer_width/2;
13249   points[1].x = xc + c*dial->radius;
13250   points[1].y = yc - s*dial->radius;
13251   points[2].x = xc - s*dial->pointer_width/2;
13252   points[2].y = yc - c*dial->pointer_width/2;
13253
13254   gtk_draw_polygon (widget->style,
13255                     widget->window,
13256                     GTK_STATE_NORMAL,
13257                     GTK_SHADOW_OUT,
13258                     points, 3,
13259                     TRUE);
13260   
13261   return FALSE;
13262 }
13263 </verb></tscreen>
13264
13265 <!-- ----------------------------------------------------------------- -->
13266 <sect2> Event handling
13267 <p>
13268 The rest of the widget's code handles various types of events, and
13269 isn't too different from what would be found in many GTK
13270 applications. Two types of events can occur - either the user can
13271 click on the widget with the mouse and drag to move the pointer, or
13272 the value of the Adjustment object can change due to some external
13273 circumstance. 
13274
13275 When the user clicks on the widget, we check to see if the click was
13276 appropriately near the pointer, and if so, store the button that the
13277 user clicked with in the <tt/button/ field of the widget
13278 structure, and grab all mouse events with a call to
13279 <tt/gtk_grab_add()/. Subsequent motion of the mouse causes the
13280 value of the control to be recomputed (by the function
13281 <tt/gtk_dial_update_mouse/). Depending on the policy that has been
13282 set, "value_changed" events are either generated instantly
13283 (<tt/GTK_UPDATE_CONTINUOUS/), after a delay in a timer added with
13284 <tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), or only when the
13285 button is released (<tt/GTK_UPDATE_DISCONTINUOUS/).
13286
13287 <tscreen><verb>
13288 static gint
13289 gtk_dial_button_press (GtkWidget      *widget,
13290                        GdkEventButton *event)
13291 {
13292   GtkDial *dial;
13293   gint dx, dy;
13294   double s, c;
13295   double d_parallel;
13296   double d_perpendicular;
13297
13298   g_return_val_if_fail (widget != NULL, FALSE);
13299   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13300   g_return_val_if_fail (event != NULL, FALSE);
13301
13302   dial = GTK_DIAL (widget);
13303
13304   /* Determine if button press was within pointer region - we 
13305      do this by computing the parallel and perpendicular distance of
13306      the point where the mouse was pressed from the line passing through
13307      the pointer */
13308   
13309   dx = event->x - widget->allocation.width / 2;
13310   dy = widget->allocation.height / 2 - event->y;
13311   
13312   s = sin(dial->angle);
13313   c = cos(dial->angle);
13314   
13315   d_parallel = s*dy + c*dx;
13316   d_perpendicular = fabs(s*dx - c*dy);
13317   
13318   if (!dial->button &&
13319       (d_perpendicular < dial->pointer_width/2) &&
13320       (d_parallel > - dial->pointer_width))
13321     {
13322       gtk_grab_add (widget);
13323
13324       dial->button = event->button;
13325
13326       gtk_dial_update_mouse (dial, event->x, event->y);
13327     }
13328
13329   return FALSE;
13330 }
13331
13332 static gint
13333 gtk_dial_button_release (GtkWidget      *widget,
13334                           GdkEventButton *event)
13335 {
13336   GtkDial *dial;
13337
13338   g_return_val_if_fail (widget != NULL, FALSE);
13339   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13340   g_return_val_if_fail (event != NULL, FALSE);
13341
13342   dial = GTK_DIAL (widget);
13343
13344   if (dial->button == event->button)
13345     {
13346       gtk_grab_remove (widget);
13347
13348       dial->button = 0;
13349
13350       if (dial->policy == GTK_UPDATE_DELAYED)
13351         gtk_timeout_remove (dial->timer);
13352       
13353       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
13354           (dial->old_value != dial->adjustment->value))
13355         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13356     }
13357
13358   return FALSE;
13359 }
13360
13361 static gint
13362 gtk_dial_motion_notify (GtkWidget      *widget,
13363                          GdkEventMotion *event)
13364 {
13365   GtkDial *dial;
13366   GdkModifierType mods;
13367   gint x, y, mask;
13368
13369   g_return_val_if_fail (widget != NULL, FALSE);
13370   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13371   g_return_val_if_fail (event != NULL, FALSE);
13372
13373   dial = GTK_DIAL (widget);
13374
13375   if (dial->button != 0)
13376     {
13377       x = event->x;
13378       y = event->y;
13379
13380       if (event->is_hint || (event->window != widget->window))
13381         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
13382
13383       switch (dial->button)
13384         {
13385         case 1:
13386           mask = GDK_BUTTON1_MASK;
13387           break;
13388         case 2:
13389           mask = GDK_BUTTON2_MASK;
13390           break;
13391         case 3:
13392           mask = GDK_BUTTON3_MASK;
13393           break;
13394         default:
13395           mask = 0;
13396           break;
13397         }
13398
13399       if (mods & mask)
13400         gtk_dial_update_mouse (dial, x,y);
13401     }
13402
13403   return FALSE;
13404 }
13405
13406 static gint
13407 gtk_dial_timer (GtkDial *dial)
13408 {
13409   g_return_val_if_fail (dial != NULL, FALSE);
13410   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
13411
13412   if (dial->policy == GTK_UPDATE_DELAYED)
13413     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13414
13415   return FALSE;
13416 }
13417
13418 static void
13419 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
13420 {
13421   gint xc, yc;
13422   gfloat old_value;
13423
13424   g_return_if_fail (dial != NULL);
13425   g_return_if_fail (GTK_IS_DIAL (dial));
13426
13427   xc = GTK_WIDGET(dial)->allocation.width / 2;
13428   yc = GTK_WIDGET(dial)->allocation.height / 2;
13429
13430   old_value = dial->adjustment->value;
13431   dial->angle = atan2(yc-y, x-xc);
13432
13433   if (dial->angle < -M_PI/2.)
13434     dial->angle += 2*M_PI;
13435
13436   if (dial->angle < -M_PI/6)
13437     dial->angle = -M_PI/6;
13438
13439   if (dial->angle > 7.*M_PI/6.)
13440     dial->angle = 7.*M_PI/6.;
13441
13442   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
13443     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
13444
13445   if (dial->adjustment->value != old_value)
13446     {
13447       if (dial->policy == GTK_UPDATE_CONTINUOUS)
13448         {
13449           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13450         }
13451       else
13452         {
13453           gtk_widget_draw (GTK_WIDGET(dial), NULL);
13454
13455           if (dial->policy == GTK_UPDATE_DELAYED)
13456             {
13457               if (dial->timer)
13458                 gtk_timeout_remove (dial->timer);
13459
13460               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
13461                                              (GtkFunction) gtk_dial_timer,
13462                                              (gpointer) dial);
13463             }
13464         }
13465     }
13466 }
13467 </verb></tscreen>
13468
13469 Changes to the Adjustment by external means are communicated to our
13470 widget by the "changed" and "value_changed" signals. The handlers
13471 for these functions call <tt/gtk_dial_update()/ to validate the
13472 arguments, compute the new pointer angle, and redraw the widget (by
13473 calling <tt/gtk_widget_draw()/).
13474
13475 <tscreen><verb>
13476 static void
13477 gtk_dial_update (GtkDial *dial)
13478 {
13479   gfloat new_value;
13480   
13481   g_return_if_fail (dial != NULL);
13482   g_return_if_fail (GTK_IS_DIAL (dial));
13483
13484   new_value = dial->adjustment->value;
13485   
13486   if (new_value < dial->adjustment->lower)
13487     new_value = dial->adjustment->lower;
13488
13489   if (new_value > dial->adjustment->upper)
13490     new_value = dial->adjustment->upper;
13491
13492   if (new_value != dial->adjustment->value)
13493     {
13494       dial->adjustment->value = new_value;
13495       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13496     }
13497
13498   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
13499     (dial->adjustment->upper - dial->adjustment->lower);
13500
13501   gtk_widget_draw (GTK_WIDGET(dial), NULL);
13502 }
13503
13504 static void
13505 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
13506                               gpointer       data)
13507 {
13508   GtkDial *dial;
13509
13510   g_return_if_fail (adjustment != NULL);
13511   g_return_if_fail (data != NULL);
13512
13513   dial = GTK_DIAL (data);
13514
13515   if ((dial->old_value != adjustment->value) ||
13516       (dial->old_lower != adjustment->lower) ||
13517       (dial->old_upper != adjustment->upper))
13518     {
13519       gtk_dial_update (dial);
13520
13521       dial->old_value = adjustment->value;
13522       dial->old_lower = adjustment->lower;
13523       dial->old_upper = adjustment->upper;
13524     }
13525 }
13526
13527 static void
13528 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
13529                                     gpointer       data)
13530 {
13531   GtkDial *dial;
13532
13533   g_return_if_fail (adjustment != NULL);
13534   g_return_if_fail (data != NULL);
13535
13536   dial = GTK_DIAL (data);
13537
13538   if (dial->old_value != adjustment->value)
13539     {
13540       gtk_dial_update (dial);
13541
13542       dial->old_value = adjustment->value;
13543     }
13544 }
13545 </verb></tscreen>
13546
13547 <!-- ----------------------------------------------------------------- -->
13548 <sect2> Possible Enhancements
13549 <p>
13550 The Dial widget as we've described it so far runs about 670 lines of
13551 code. Although that might sound like a fair bit, we've really
13552 accomplished quite a bit with that much code, especially since much of
13553 that length is headers and boilerplate. However, there are quite a few
13554 more enhancements that could be made to this widget:
13555
13556 <itemize>
13557 <item> If you try this widget out, you'll find that there is some
13558 flashing as the pointer is dragged around. This is because the entire
13559 widget is erased every time the pointer is moved before being
13560 redrawn. Often, the best way to handle this problem is to draw to an
13561 offscreen pixmap, then copy the final results onto the screen in one
13562 step. (The ProgressBar widget draws itself in this fashion.)
13563
13564 <item> The user should be able to use the up and down arrow keys to
13565 increase and decrease the value.
13566
13567 <item> It would be nice if the widget had buttons to increase and
13568 decrease the value in small or large steps. Although it would be
13569 possible to use embedded Button widgets for this, we would also like
13570 the buttons to auto-repeat when held down, as the arrows on a
13571 scrollbar do. Most of the code to implement this type of behavior can
13572 be found in the Range widget.
13573
13574 <item> The Dial widget could be made into a container widget with a
13575 single child widget positioned at the bottom between the buttons
13576 mentioned above. The user could then add their choice of a label or
13577 entry widget to display the current value of the dial.
13578
13579 </itemize>
13580
13581 <!-- ----------------------------------------------------------------- -->
13582 <sect1> Learning More
13583
13584 <p>
13585 Only a small part of the many details involved in creating widgets
13586 could be described above. If you want to write your own widgets, the
13587 best source of examples is the GTK source itself. Ask yourself some
13588 questions about the widget you want to write: IS it a Container
13589 widget? Does it have its own window? Is it a modification of an
13590 existing widget? Then find a similar widget, and start making changes.
13591 Good luck!
13592
13593 <!-- ***************************************************************** -->
13594 <sect>Scribble, A Simple Example Drawing Program
13595 <!-- ***************************************************************** -->
13596
13597 <!-- ----------------------------------------------------------------- -->
13598 <sect1> Overview
13599 <p>
13600 In this section, we will build a simple drawing program. In the
13601 process, we will examine how to handle mouse events, how to draw in a
13602 window, and how to do drawing better by using a backing pixmap. After
13603 creating the simple drawing program, we will extend it by adding
13604 support for XInput devices, such as drawing tablets. GTK provides
13605 support routines which makes getting extended information, such as
13606 pressure and tilt, from such devices quite easy.
13607
13608 <!-- ----------------------------------------------------------------- -->
13609 <sect1> Event Handling
13610 <p>
13611 The GTK signals we have already discussed are for high-level actions,
13612 such as a menu item being selected. However, sometimes it is useful to
13613 learn about lower-level occurrences, such as the mouse being moved, or
13614 a key being pressed. There are also GTK signals corresponding to these
13615 low-level <em>events</em>. The handlers for these signals have an
13616 extra parameter which is a pointer to a structure containing
13617 information about the event. For instance, motion event handlers are
13618 passed a pointer to a GdkEventMotion structure which looks (in part)
13619 like:
13620
13621 <tscreen><verb>
13622 struct _GdkEventMotion
13623 {
13624   GdkEventType type;
13625   GdkWindow *window;
13626   guint32 time;
13627   gdouble x;
13628   gdouble y;
13629   ...
13630   guint state;
13631   ...
13632 };
13633 </verb></tscreen>
13634
13635 <tt/type/ will be set to the event type, in this case
13636 <tt/GDK_MOTION_NOTIFY/, window is the window in which the event
13637 occurred. <tt/x/ and <tt/y/ give the coordinates of the event.
13638 <tt/state/ specifies the modifier state when the event
13639 occurred (that is, it specifies which modifier keys and mouse buttons
13640 were pressed). It is the bitwise OR of some of the following:
13641
13642 <tscreen><verb>
13643 GDK_SHIFT_MASK  
13644 GDK_LOCK_MASK   
13645 GDK_CONTROL_MASK
13646 GDK_MOD1_MASK   
13647 GDK_MOD2_MASK   
13648 GDK_MOD3_MASK   
13649 GDK_MOD4_MASK   
13650 GDK_MOD5_MASK   
13651 GDK_BUTTON1_MASK
13652 GDK_BUTTON2_MASK
13653 GDK_BUTTON3_MASK
13654 GDK_BUTTON4_MASK
13655 GDK_BUTTON5_MASK
13656 </verb></tscreen>
13657
13658 As for other signals, to determine what happens when an event occurs
13659 we call <tt>gtk_signal_connect()</tt>. But we also need let GTK
13660 know which events we want to be notified about. To do this, we call
13661 the function:
13662
13663 <tscreen><verb>
13664 void gtk_widget_set_events (GtkWidget *widget,
13665                             gint      events);
13666 </verb></tscreen>
13667
13668 The second field specifies the events we are interested in. It
13669 is the bitwise OR of constants that specify different types
13670 of events. For future reference the event types are:
13671
13672 <tscreen><verb>
13673 GDK_EXPOSURE_MASK
13674 GDK_POINTER_MOTION_MASK
13675 GDK_POINTER_MOTION_HINT_MASK
13676 GDK_BUTTON_MOTION_MASK     
13677 GDK_BUTTON1_MOTION_MASK    
13678 GDK_BUTTON2_MOTION_MASK    
13679 GDK_BUTTON3_MOTION_MASK    
13680 GDK_BUTTON_PRESS_MASK      
13681 GDK_BUTTON_RELEASE_MASK    
13682 GDK_KEY_PRESS_MASK         
13683 GDK_KEY_RELEASE_MASK       
13684 GDK_ENTER_NOTIFY_MASK      
13685 GDK_LEAVE_NOTIFY_MASK      
13686 GDK_FOCUS_CHANGE_MASK      
13687 GDK_STRUCTURE_MASK         
13688 GDK_PROPERTY_CHANGE_MASK   
13689 GDK_PROXIMITY_IN_MASK      
13690 GDK_PROXIMITY_OUT_MASK     
13691 </verb></tscreen>
13692
13693 There are a few subtle points that have to be observed when calling
13694 <tt/gtk_widget_set_events()/. First, it must be called before the X window
13695 for a GTK widget is created. In practical terms, this means you
13696 should call it immediately after creating the widget. Second, the
13697 widget must have an associated X window. For efficiency, many widget
13698 types do not have their own window, but draw in their parent's window.
13699 These widgets are:
13700
13701 <tscreen><verb>
13702 GtkAlignment
13703 GtkArrow
13704 GtkBin
13705 GtkBox
13706 GtkImage
13707 GtkItem
13708 GtkLabel
13709 GtkPixmap
13710 GtkScrolledWindow
13711 GtkSeparator
13712 GtkTable
13713 GtkAspectFrame
13714 GtkFrame
13715 GtkVBox
13716 GtkHBox
13717 GtkVSeparator
13718 GtkHSeparator
13719 </verb></tscreen>
13720
13721 To capture events for these widgets, you need to use an EventBox
13722 widget. See the section on the <ref id="sec_EventBox"
13723 name="EventBox"> widget for details.
13724
13725 For our drawing program, we want to know when the mouse button is
13726 pressed and when the mouse is moved, so we specify
13727 <tt/GDK_POINTER_MOTION_MASK/ and <tt/GDK_BUTTON_PRESS_MASK/. We also
13728 want to know when we need to redraw our window, so we specify
13729 <tt/GDK_EXPOSURE_MASK/. Although we want to be notified via a
13730 Configure event when our window size changes, we don't have to specify
13731 the corresponding <tt/GDK_STRUCTURE_MASK/ flag, because it is
13732 automatically specified for all windows.
13733
13734 It turns out, however, that there is a problem with just specifying
13735 <tt/GDK_POINTER_MOTION_MASK/. This will cause the server to add a new
13736 motion event to the event queue every time the user moves the mouse.
13737 Imagine that it takes us 0.1 seconds to handle a motion event, but the
13738 X server queues a new motion event every 0.05 seconds. We will soon
13739 get way behind the users drawing. If the user draws for 5 seconds,
13740 it will take us another 5 seconds to catch up after they release 
13741 the mouse button! What we would like is to only get one motion
13742 event for each event we process. The way to do this is to 
13743 specify <tt/GDK_POINTER_MOTION_HINT_MASK/. 
13744
13745 When we specify <tt/GDK_POINTER_MOTION_HINT_MASK/, the server sends
13746 us a motion event the first time the pointer moves after entering
13747 our window, or after a button press or release event. Subsequent 
13748 motion events will be suppressed until we explicitly ask for
13749 the position of the pointer using the function:
13750
13751 <tscreen><verb>
13752 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
13753                                           gint            *x,
13754                                           gint            *y,
13755                                           GdkModifierType *mask);
13756 </verb></tscreen>
13757
13758 (There is another function, <tt>gtk_widget_get_pointer()</tt> which
13759 has a simpler interface, but turns out not to be very useful, since
13760 it only retrieves the position of the mouse, not whether the buttons
13761 are pressed.)
13762
13763 The code to set the events for our window then looks like:
13764
13765 <tscreen><verb>
13766   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
13767                       (GtkSignalFunc) expose_event, NULL);
13768   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
13769                       (GtkSignalFunc) configure_event, NULL);
13770   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
13771                       (GtkSignalFunc) motion_notify_event, NULL);
13772   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
13773                       (GtkSignalFunc) button_press_event, NULL);
13774
13775   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
13776                          | GDK_LEAVE_NOTIFY_MASK
13777                          | GDK_BUTTON_PRESS_MASK
13778                          | GDK_POINTER_MOTION_MASK
13779                          | GDK_POINTER_MOTION_HINT_MASK);
13780 </verb></tscreen>
13781
13782 We'll save the "expose_event" and "configure_event" handlers for
13783 later. The "motion_notify_event" and "button_press_event" handlers
13784 are pretty simple:
13785
13786 <tscreen><verb>
13787 static gint
13788 button_press_event (GtkWidget *widget, GdkEventButton *event)
13789 {
13790   if (event->button == 1 &amp;&amp; pixmap != NULL)
13791       draw_brush (widget, event->x, event->y);
13792
13793   return TRUE;
13794 }
13795
13796 static gint
13797 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
13798 {
13799   int x, y;
13800   GdkModifierType state;
13801
13802   if (event->is_hint)
13803     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
13804   else
13805     {
13806       x = event->x;
13807       y = event->y;
13808       state = event->state;
13809     }
13810     
13811   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
13812     draw_brush (widget, x, y);
13813   
13814   return TRUE;
13815 }
13816 </verb></tscreen>
13817
13818 <!-- ----------------------------------------------------------------- -->
13819 <sect1> The DrawingArea Widget, And Drawing
13820 <p>
13821 We now turn to the process of drawing on the screen. The 
13822 widget we use for this is the DrawingArea widget. A drawing area
13823 widget is essentially an X window and nothing more. It is a blank
13824 canvas in which we can draw whatever we like. A drawing area
13825 is created using the call:
13826
13827 <tscreen><verb>
13828 GtkWidget* gtk_drawing_area_new        (void);
13829 </verb></tscreen>
13830
13831 A default size for the widget can be specified by calling:
13832
13833 <tscreen><verb>
13834 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
13835                                         gint                 width,
13836                                         gint                 height);
13837 </verb></tscreen>
13838
13839 This default size can be overridden, as is true for all widgets,
13840 by calling <tt>gtk_widget_set_usize()</tt>, and that, in turn, can
13841 be overridden if the user manually resizes the the window containing
13842 the drawing area.
13843
13844 It should be noted that when we create a DrawingArea widget, we are
13845 <em>completely</em> responsible for drawing the contents. If our
13846 window is obscured then uncovered, we get an exposure event and must
13847 redraw what was previously hidden.
13848
13849 Having to remember everything that was drawn on the screen so we
13850 can properly redraw it can, to say the least, be a nuisance. In
13851 addition, it can be visually distracting if portions of the
13852 window are cleared, then redrawn step by step. The solution to
13853 this problem is to use an offscreen <em>backing pixmap</em>.
13854 Instead of drawing directly to the screen, we draw to an image
13855 stored in server memory but not displayed, then when the image
13856 changes or new portions of the image are displayed, we copy the
13857 relevant portions onto the screen.
13858
13859 To create an offscreen pixmap, we call the function:
13860
13861 <tscreen><verb>
13862 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
13863                                          gint        width,
13864                                          gint        height,
13865                                          gint        depth);
13866 </verb></tscreen>
13867
13868 The <tt>window</tt> parameter specifies a GDK window that this pixmap
13869 takes some of its properties from. <tt>width</tt> and <tt>height</tt>
13870 specify the size of the pixmap. <tt>depth</tt> specifies the <em>color
13871 depth</em>, that is the number of bits per pixel, for the new window.
13872 If the depth is specified as <tt>-1</tt>, it will match the depth
13873 of <tt>window</tt>.
13874
13875 We create the pixmap in our "configure_event" handler. This event
13876 is generated whenever the window changes size, including when it
13877 is originally created.
13878
13879 <tscreen><verb>
13880 /* Backing pixmap for drawing area */
13881 static GdkPixmap *pixmap = NULL;
13882
13883 /* Create a new backing pixmap of the appropriate size */
13884 static gint
13885 configure_event (GtkWidget *widget, GdkEventConfigure *event)
13886 {
13887   if (pixmap)
13888     gdk_pixmap_unref(pixmap);
13889
13890   pixmap = gdk_pixmap_new(widget->window,
13891                           widget->allocation.width,
13892                           widget->allocation.height,
13893                           -1);
13894   gdk_draw_rectangle (pixmap,
13895                       widget->style->white_gc,
13896                       TRUE,
13897                       0, 0,
13898                       widget->allocation.width,
13899                       widget->allocation.height);
13900
13901   return TRUE;
13902 }
13903 </verb></tscreen>
13904
13905 The call to <tt>gdk_draw_rectangle()</tt> clears the pixmap
13906 initially to white. We'll say more about that in a moment.
13907
13908 Our exposure event handler then simply copies the relevant portion
13909 of the pixmap onto the screen (we determine the area we need
13910 to redraw by using the event->area field of the exposure event):
13911
13912 <tscreen><verb>
13913 /* Redraw the screen from the backing pixmap */
13914 static gint
13915 expose_event (GtkWidget *widget, GdkEventExpose *event)
13916 {
13917   gdk_draw_pixmap(widget->window,
13918                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
13919                   pixmap,
13920                   event->area.x, event->area.y,
13921                   event->area.x, event->area.y,
13922                   event->area.width, event->area.height);
13923
13924   return FALSE;
13925 }
13926 </verb></tscreen>
13927
13928 We've now seen how to keep the screen up to date with our pixmap, but
13929 how do we actually draw interesting stuff on our pixmap?  There are a
13930 large number of calls in GTK's GDK library for drawing on
13931 <em>drawables</em>. A drawable is simply something that can be drawn
13932 upon. It can be a window, a pixmap, or a bitmap (a black and white
13933 image).  We've already seen two such calls above,
13934 <tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. The
13935 complete list is:
13936
13937 <tscreen><verb>
13938 gdk_draw_line ()
13939 gdk_draw_rectangle ()
13940 gdk_draw_arc ()
13941 gdk_draw_polygon ()
13942 gdk_draw_string ()
13943 gdk_draw_text ()
13944 gdk_draw_pixmap ()
13945 gdk_draw_bitmap ()
13946 gdk_draw_image ()
13947 gdk_draw_points ()
13948 gdk_draw_segments ()
13949 </verb></tscreen>
13950
13951 See the reference documentation or the header file
13952 <tt>&lt;gdk/gdk.h&gt;</tt> for further details on these functions.
13953 These functions all share the same first two arguments. The first
13954 argument is the drawable to draw upon, the second argument is a
13955 <em>graphics context</em> (GC). 
13956
13957 A graphics context encapsulates information about things such as
13958 foreground and background color and line width. GDK has a full set of
13959 functions for creating and modifying graphics contexts, but to keep
13960 things simple we'll just use predefined graphics contexts. Each widget
13961 has an associated style. (Which can be modified in a gtkrc file, see
13962 the section GTK's rc file.) This, among other things, stores a number
13963 of graphics contexts. Some examples of accessing these graphics
13964 contexts are:
13965
13966 <tscreen><verb>
13967 widget->style->white_gc
13968 widget->style->black_gc
13969 widget->style->fg_gc[GTK_STATE_NORMAL]
13970 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
13971 </verb></tscreen>
13972
13973 The fields <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, and
13974 <tt>light_gc</tt> are indexed by a parameter of type
13975 <tt>GtkStateType</tt> which can take on the values:
13976
13977 <tscreen><verb>
13978 GTK_STATE_NORMAL,
13979 GTK_STATE_ACTIVE,
13980 GTK_STATE_PRELIGHT,
13981 GTK_STATE_SELECTED,
13982 GTK_STATE_INSENSITIVE
13983 </verb></tscreen>
13984
13985 For instance, for <tt/GTK_STATE_SELECTED/ the default foreground
13986 color is white and the default background color, dark blue.
13987
13988 Our function <tt>draw_brush()</tt>, which does the actual drawing
13989 on the screen, is then:
13990
13991 <tscreen><verb>
13992 /* Draw a rectangle on the screen */
13993 static void
13994 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
13995 {
13996   GdkRectangle update_rect;
13997
13998   update_rect.x = x - 5;
13999   update_rect.y = y - 5;
14000   update_rect.width = 10;
14001   update_rect.height = 10;
14002   gdk_draw_rectangle (pixmap,
14003                       widget->style->black_gc,
14004                       TRUE,
14005                       update_rect.x, update_rect.y,
14006                       update_rect.width, update_rect.height);
14007   gtk_widget_draw (widget, &amp;update_rect);
14008 }
14009 </verb></tscreen>
14010
14011 After we draw the rectangle representing the brush onto the pixmap,
14012 we call the function:
14013
14014 <tscreen><verb>
14015 void       gtk_widget_draw                (GtkWidget           *widget,
14016                                            GdkRectangle        *area);
14017 </verb></tscreen>
14018
14019 which notifies X that the area given by the <tt>area</tt> parameter
14020 needs to be updated. X will eventually generate an expose event
14021 (possibly combining the areas passed in several calls to
14022 <tt>gtk_widget_draw()</tt>) which will cause our expose event handler
14023 to copy the relevant portions to the screen.
14024
14025 We have now covered the entire drawing program except for a few
14026 mundane details like creating the main window.
14027
14028 <!-- ----------------------------------------------------------------- -->
14029 <sect1> Adding XInput support
14030 <p>
14031 It is now possible to buy quite inexpensive input devices such 
14032 as drawing tablets, which allow drawing with a much greater
14033 ease of artistic expression than does a mouse. The simplest way
14034 to use such devices is simply as a replacement for the mouse,
14035 but that misses out many of the advantages of these devices,
14036 such as:
14037
14038 <itemize>
14039 <item> Pressure sensitivity
14040 <item> Tilt reporting
14041 <item> Sub-pixel positioning
14042 <item> Multiple inputs (for example, a stylus with a point and eraser)
14043 </itemize>
14044
14045 For information about the XInput extension, see the <htmlurl
14046 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
14047 name="XInput-HOWTO">.
14048
14049 If we examine the full definition of, for example, the GdkEventMotion
14050 structure, we see that it has fields to support extended device
14051 information.
14052
14053 <tscreen><verb>
14054 struct _GdkEventMotion
14055 {
14056   GdkEventType type;
14057   GdkWindow *window;
14058   guint32 time;
14059   gdouble x;
14060   gdouble y;
14061   gdouble pressure;
14062   gdouble xtilt;
14063   gdouble ytilt;
14064   guint state;
14065   gint16 is_hint;
14066   GdkInputSource source;
14067   guint32 deviceid;
14068 };
14069 </verb></tscreen>
14070
14071 <tt/pressure/ gives the pressure as a floating point number between
14072 0 and 1. <tt/xtilt/ and <tt/ytilt/ can take on values between 
14073 -1 and 1, corresponding to the degree of tilt in each direction.
14074 <tt/source/ and <tt/deviceid/ specify the device for which the
14075 event occurred in two different ways. <tt/source/ gives some simple
14076 information about the type of device. It can take the enumeration
14077 values:
14078
14079 <tscreen><verb>
14080 GDK_SOURCE_MOUSE
14081 GDK_SOURCE_PEN
14082 GDK_SOURCE_ERASER
14083 GDK_SOURCE_CURSOR
14084 </verb></tscreen>
14085
14086 <tt/deviceid/ specifies a unique numeric ID for the device. This can
14087 be used to find out further information about the device using the
14088 <tt/gdk_input_list_devices()/ call (see below). The special value
14089 <tt/GDK_CORE_POINTER/ is used for the core pointer device. (Usually
14090 the mouse.)
14091
14092 <sect2> Enabling extended device information
14093 <p>
14094 To let GTK know about our interest in the extended device information,
14095 we merely have to add a single line to our program:
14096
14097 <tscreen><verb>
14098 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
14099 </verb></tscreen>
14100
14101 By giving the value <tt/GDK_EXTENSION_EVENTS_CURSOR/ we say that
14102 we are interested in extension events, but only if we don't have
14103 to draw our own cursor. See the section <ref
14104 id="sec_Further_Sophistications" name="Further Sophistications"> below
14105 for more information about drawing the cursor. We could also 
14106 give the values <tt/GDK_EXTENSION_EVENTS_ALL/ if we were willing 
14107 to draw our own cursor, or <tt/GDK_EXTENSION_EVENTS_NONE/ to revert
14108 back to the default condition.
14109
14110 This is not completely the end of the story however. By default,
14111 no extension devices are enabled. We need a mechanism to allow
14112 users to enable and configure their extension devices. GTK provides
14113 the InputDialog widget to automate this process. The following
14114 procedure manages an InputDialog widget. It creates the dialog if
14115 it isn't present, and raises it to the top otherwise.
14116
14117 <tscreen><verb>
14118 void
14119 input_dialog_destroy (GtkWidget *w, gpointer data)
14120 {
14121   *((GtkWidget **)data) = NULL;
14122 }
14123
14124 void
14125 create_input_dialog ()
14126 {
14127   static GtkWidget *inputd = NULL;
14128
14129   if (!inputd)
14130     {
14131       inputd = gtk_input_dialog_new();
14132
14133       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
14134                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
14135       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
14136                                  "clicked",
14137                                  (GtkSignalFunc)gtk_widget_hide,
14138                                  GTK_OBJECT(inputd));
14139       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
14140
14141       gtk_widget_show (inputd);
14142     }
14143   else
14144     {
14145       if (!GTK_WIDGET_MAPPED(inputd))
14146         gtk_widget_show(inputd);
14147       else
14148         gdk_window_raise(inputd->window);
14149     }
14150 }
14151 </verb></tscreen>
14152
14153 (You might want to take note of the way we handle this dialog.  By
14154 connecting to the "destroy" signal, we make sure that we don't keep a
14155 pointer to dialog around after it is destroyed - that could lead to a
14156 segfault.)
14157
14158 The InputDialog has two buttons "Close" and "Save", which by default
14159 have no actions assigned to them. In the above function we make
14160 "Close" hide the dialog, hide the "Save" button, since we don't
14161 implement saving of XInput options in this program.
14162
14163 <sect2> Using extended device information
14164 <p>
14165 Once we've enabled the device, we can just use the extended 
14166 device information in the extra fields of the event structures.
14167 In fact, it is always safe to use this information since these
14168 fields will have reasonable default values even when extended
14169 events are not enabled.
14170
14171 Once change we do have to make is to call
14172 <tt/gdk_input_window_get_pointer()/ instead of
14173 <tt/gdk_window_get_pointer/. This is necessary because
14174 <tt/gdk_window_get_pointer/ doesn't return the extended device
14175 information.
14176
14177 <tscreen><verb>
14178 void gdk_input_window_get_pointer( GdkWindow       *window,
14179                                    guint32         deviceid,
14180                                    gdouble         *x,
14181                                    gdouble         *y,
14182                                    gdouble         *pressure,
14183                                    gdouble         *xtilt,
14184                                    gdouble         *ytilt,
14185                                    GdkModifierType *mask);
14186 </verb></tscreen>
14187
14188 When calling this function, we need to specify the device ID as
14189 well as the window. Usually, we'll get the device ID from the
14190 <tt/deviceid/ field of an event structure. Again, this function
14191 will return reasonable values when extension events are not
14192 enabled. (In this case, <tt/event->deviceid/ will have the value
14193 <tt/GDK_CORE_POINTER/).
14194
14195 So the basic structure of our button-press and motion event handlers
14196 doesn't change much - we just need to add code to deal with the
14197 extended information.
14198
14199 <tscreen><verb>
14200 static gint
14201 button_press_event (GtkWidget *widget, GdkEventButton *event)
14202 {
14203   print_button_press (event->deviceid);
14204   
14205   if (event->button == 1 &amp;&amp; pixmap != NULL)
14206     draw_brush (widget, event->source, event->x, event->y, event->pressure);
14207
14208   return TRUE;
14209 }
14210
14211 static gint
14212 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
14213 {
14214   gdouble x, y;
14215   gdouble pressure;
14216   GdkModifierType state;
14217
14218   if (event->is_hint)
14219     gdk_input_window_get_pointer (event->window, event->deviceid,
14220                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
14221   else
14222     {
14223       x = event->x;
14224       y = event->y;
14225       pressure = event->pressure;
14226       state = event->state;
14227     }
14228     
14229   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
14230     draw_brush (widget, event->source, x, y, pressure);
14231   
14232   return TRUE;
14233 }
14234 </verb></tscreen>
14235
14236 We also need to do something with the new information. Our new
14237 <tt/draw_brush()/ function draws with a different color for
14238 each <tt/event->source/ and changes the brush size depending
14239 on the pressure.
14240
14241 <tscreen><verb>
14242 /* Draw a rectangle on the screen, size depending on pressure,
14243    and color on the type of device */
14244 static void
14245 draw_brush (GtkWidget *widget, GdkInputSource source,
14246             gdouble x, gdouble y, gdouble pressure)
14247 {
14248   GdkGC *gc;
14249   GdkRectangle update_rect;
14250
14251   switch (source)
14252     {
14253     case GDK_SOURCE_MOUSE:
14254       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
14255       break;
14256     case GDK_SOURCE_PEN:
14257       gc = widget->style->black_gc;
14258       break;
14259     case GDK_SOURCE_ERASER:
14260       gc = widget->style->white_gc;
14261       break;
14262     default:
14263       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
14264     }
14265
14266   update_rect.x = x - 10 * pressure;
14267   update_rect.y = y - 10 * pressure;
14268   update_rect.width = 20 * pressure;
14269   update_rect.height = 20 * pressure;
14270   gdk_draw_rectangle (pixmap, gc, TRUE,
14271                       update_rect.x, update_rect.y,
14272                       update_rect.width, update_rect.height);
14273   gtk_widget_draw (widget, &amp;update_rect);
14274 }
14275 </verb></tscreen>
14276
14277 <sect2> Finding out more about a device
14278 <p>
14279 As an example of how to find out more about a device, our program
14280 will print the name of the device that generates each button
14281 press. To find out the name of a device, we call the function:
14282
14283 <tscreen><verb>
14284 GList *gdk_input_list_devices               (void);
14285 </verb></tscreen>
14286
14287 which returns a GList (a linked list type from the GLib library)
14288 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
14289 as:
14290
14291 <tscreen><verb>
14292 struct _GdkDeviceInfo
14293 {
14294   guint32 deviceid;
14295   gchar *name;
14296   GdkInputSource source;
14297   GdkInputMode mode;
14298   gint has_cursor;
14299   gint num_axes;
14300   GdkAxisUse *axes;
14301   gint num_keys;
14302   GdkDeviceKey *keys;
14303 };
14304 </verb></tscreen>
14305
14306 Most of these fields are configuration information that you can ignore
14307 unless you are implementing XInput configuration saving. The fieldwe
14308 are interested in here is <tt/name/ which is simply the name that X
14309 assigns to the device. The other field that isn't configuration
14310 information is <tt/has_cursor/. If <tt/has_cursor/ is false, then we
14311 we need to draw our own cursor. But since we've specified
14312 <tt/GDK_EXTENSION_EVENTS_CURSOR/, we don't have to worry about this.
14313
14314 Our <tt/print_button_press()/ function simply iterates through
14315 the returned list until it finds a match, then prints out
14316 the name of the device.
14317
14318 <tscreen><verb>
14319 static void
14320 print_button_press (guint32 deviceid)
14321 {
14322   GList *tmp_list;
14323
14324   /* gdk_input_list_devices returns an internal list, so we shouldn't
14325      free it afterwards */
14326   tmp_list = gdk_input_list_devices();
14327
14328   while (tmp_list)
14329     {
14330       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
14331
14332       if (info->deviceid == deviceid)
14333         {
14334           printf("Button press on device '%s'\n", info->name);
14335           return;
14336         }
14337
14338       tmp_list = tmp_list->next;
14339     }
14340 }
14341 </verb></tscreen>
14342
14343 That completes the changes to "XInputize" our program.
14344
14345 <sect2> Further sophistications <label id="sec_Further_Sophistications">
14346 <p>
14347 Although our program now supports XInput quite well, it lacks some
14348 features we would want in a full-featured application. First, the user
14349 probably doesn't want to have to configure their device each time they
14350 run the program, so we should allow them to save the device
14351 configuration. This is done by iterating through the return of
14352 <tt/gdk_input_list_devices()/ and writing out the configuration to a
14353 file.
14354
14355 To restore the state next time the program is run, GDK provides
14356 functions to change device configuration:
14357
14358 <tscreen><verb>
14359 gdk_input_set_extension_events()
14360 gdk_input_set_source()
14361 gdk_input_set_mode()
14362 gdk_input_set_axes()
14363 gdk_input_set_key()
14364 </verb></tscreen>
14365
14366 (The list returned from <tt/gdk_input_list_devices()/ should not be
14367 modified directly.) An example of doing this can be found in the
14368 drawing program gsumi. (Available from <htmlurl
14369 url="http://www.msc.cornell.edu/~otaylor/gsumi/"
14370 name="http://www.msc.cornell.edu/~otaylor/gsumi/">) Eventually, it
14371 would be nice to have a standard way of doing this for all
14372 applications. This probably belongs at a slightly higher level than
14373 GTK, perhaps in the GNOME library.
14374
14375 Another major omission that we have mentioned above is the lack of
14376 cursor drawing. Platforms other than XFree86 currently do not allow
14377 simultaneously using a device as both the core pointer and directly by
14378 an application. See the <url
14379 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
14380 name="XInput-HOWTO"> for more information about this. This means that
14381 applications that want to support the widest audience need to draw
14382 their own cursor.
14383
14384 An application that draws its own cursor needs to do two things:
14385 determine if the current device needs a cursor drawn or not, and
14386 determine if the current device is in proximity. (If the current
14387 device is a drawing tablet, it's a nice touch to make the cursor 
14388 disappear when the stylus is lifted from the tablet. When the
14389 device is touching the stylus, that is called "in proximity.")
14390 The first is done by searching the device list, as we did
14391 to find out the device name. The second is achieved by selecting
14392 "proximity_out" events. An example of drawing one's own cursor is
14393 found in the "testinput" program found in the GTK distribution.
14394
14395 <!-- ***************************************************************** -->
14396 <sect>Tips For Writing GTK Applications
14397 <!-- ***************************************************************** -->
14398 <p>
14399 This section is simply a gathering of wisdom, general style guidelines
14400 and hints to creating good GTK applications. Currently this section
14401 is very short, but I hope it will get longer in future editions of
14402 this tutorial.
14403
14404 Use GNU autoconf and automake! They are your friends :) Automake
14405 examines C files, determines how they depend on each other, and
14406 generates a Makefile so the files can be compiled in the correct
14407 order. Autoconf permits automatic configuration of software
14408 installation, handling a large number of system quirks to increase
14409 portability. I am planning to make a quick intro on them here.
14410
14411 When writing C code, use only C comments (beginning with "/*" and
14412 ending with "*/"), and don't use C++-style comments ("//").  Although
14413 many C compilers understand C++ comments, others don't, and the ANSI C
14414 standard does not require that C++-style comments be processed as
14415 comments.
14416
14417 <!-- ***************************************************************** -->
14418 <sect>Contributing <label id="sec_Contributing">
14419 <!-- ***************************************************************** -->
14420 <p>
14421 This document, like so much other great software out there, was
14422 created for free by volunteers.  If you are at all knowledgeable about
14423 any aspect of GTK that does not already have documentation, please
14424 consider contributing to this document.
14425
14426 If you do decide to contribute, please mail your text to Tony Gale,
14427 <tt><htmlurl url="mailto:gale@gtk.org"
14428 name="gale@gtk.org"></tt>. Also, be aware that the entirety of this
14429 document is free, and any addition by you provide must also be
14430 free. That is, people may use any portion of your examples in their
14431 programs, and copies of this document may be distributed at will, etc.
14432
14433 Thank you.
14434
14435 <!-- ***************************************************************** -->
14436 <sect>Credits
14437 <!-- ***************************************************************** -->
14438 <p>
14439 We would like to thank the following for their contributions to this text.
14440
14441 <itemize>
14442 <item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com"
14443 name="chamele0n@geocities.com"></tt> for the menus tutorial.                          
14444
14445 <item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org"
14446 name="raph@acm.org"></tt>
14447 for hello world ala GTK, widget packing, and general all around wisdom.
14448 He's also generously donated a home for this tutorial.
14449
14450 <item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
14451 name="petm@xcf.berkeley.edu"></tt> for the simplest GTK program.. 
14452 and the ability to make it :)
14453
14454 <item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de"
14455 name="werner.koch@guug.de"></tt> for converting the original plain text to
14456 SGML, and the widget class hierarchy.
14457
14458 <item>Mark Crichton <tt><htmlurl
14459 url="mailto:crichton@expert.cc.purdue.edu"
14460 name="crichton@expert.cc.purdue.edu"></tt> for the menu factory code,
14461 and the table packing tutorial.
14462
14463 <item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu"
14464 name="owt1@cornell.edu"></tt> for the EventBox widget section (and the
14465 patch to the distro).  He's also responsible for the selections code
14466 and tutorial, as well as the sections on writing your own GTK widgets,
14467 and the example application. Thanks a lot Owen for all you help!
14468
14469 <item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu"
14470 name="mvboom42@calvin.edu"></tt> for his wonderful work on the
14471 Notebook, Progress Bar, Dialogs, and File selection widgets.  Thanks a
14472 lot Mark!  You've been a great help.
14473
14474 <item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org"
14475 name="timj@psynet.net"></tt> for his great job on the Lists
14476 Widget. His excellent work on automatically extracting the widget tree
14477 and signal information from GTK. Thanks Tim :)
14478
14479 <item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com"
14480 name="rajat@ix.netcom.com"</tt> for the excellent job on the Pixmap
14481 tutorial.
14482
14483 <item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com"
14484 name="johnsonm@redhat.com"></tt> for info and code for popup menus.
14485
14486 <item>David Huggins-Daines <tt><htmlurl
14487 url="mailto:bn711@freenet.carleton.ca"
14488 name="bn711@freenet.carleton.ca"></tt> for the Range Widgets and Tree
14489 Widget sections.
14490
14491 <item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se"
14492 name="mars@lysator.liu.se"></tt> for the CList section.
14493
14494 <item>David A. Wheeler <tt><htmlurl url="mailto:dwheeler@ida.org"
14495 name="dwheeler@ida.org"></tt> for portions of the text on GLib
14496 and various tutorial fixups and improvements.
14497 The GLib text was in turn based on material developed by Damon Chaplin
14498 <tt><htmlurl url="mailto:DAChaplin@msn.com" name="DAChaplin@msn.com"></tt>
14499
14500 <item>David King for style checking the entire document.
14501 </itemize>
14502
14503 And to all of you who commented on and helped refine this document.
14504
14505 Thanks.
14506
14507 <!-- ***************************************************************** -->
14508 <sect> Tutorial Copyright and Permissions Notice
14509 <!-- ***************************************************************** -->
14510
14511 <p>
14512 The GTK Tutorial is Copyright (C) 1997 Ian Main. 
14513
14514 Copyright (C) 1998-1999 Tony Gale.
14515
14516 Permission is granted to make and distribute verbatim copies of this 
14517 manual provided the copyright notice and this permission notice are 
14518 preserved on all copies.
14519
14520 Permission is granted to copy and distribute modified versions of 
14521 this document under the conditions for verbatim copying, provided that 
14522 this copyright notice is included exactly as in the original,
14523 and that the entire resulting derived work is distributed under 
14524 the terms of a permission notice identical to this one.
14525 <P>Permission is granted to copy and distribute translations of this 
14526 document into another language, under the above conditions for modified 
14527 versions.
14528
14529 If you are intending to incorporate this document into a published 
14530 work, please contact the maintainer, and we will make an effort 
14531 to ensure that you have the most up to date information available.
14532
14533 There is no guarantee that this document lives up to its intended
14534 purpose.  This is simply provided as a free resource.  As such,
14535 the authors and maintainers of the information provided within can
14536 not make any guarantee that the information is even accurate.
14537
14538 <!-- ***************************************************************** -->
14539 <appendix>
14540 <!-- ***************************************************************** -->
14541
14542 <!-- ***************************************************************** -->
14543 <sect> GTK Signals <label id="sec_GTK_Signals">
14544 <!-- ***************************************************************** -->
14545 <p>
14546 As GTK is an object oriented widget set, it has a hierarchy of
14547 inheritance. This inheritance mechanism applies for
14548 signals. Therefore, you should refer to the widget hierarchy tree when
14549 using the signals listed in this section.
14550
14551 <!-- ----------------------------------------------------------------- -->
14552 <sect1>GtkObject
14553 <!-- ----------------------------------------------------------------- -->
14554 <p>
14555 <tscreen><verb>
14556 void GtkObject::destroy (GtkObject *,
14557                          gpointer);
14558 </verb></tscreen>
14559
14560 <!-- ----------------------------------------------------------------- -->
14561 <sect1>GtkWidget
14562 <!-- ----------------------------------------------------------------- -->
14563 <p>
14564 <tscreen><verb>
14565
14566 void GtkWidget::show    (GtkWidget *,
14567                          gpointer);
14568 void GtkWidget::hide    (GtkWidget *,
14569                          gpointer);
14570 void GtkWidget::map     (GtkWidget *,
14571                          gpointer);
14572 void GtkWidget::unmap   (GtkWidget *,
14573                          gpointer);
14574 void GtkWidget::realize (GtkWidget *,
14575                          gpointer);
14576 void GtkWidget::unrealize       (GtkWidget *,
14577                                  gpointer);
14578 void GtkWidget::draw    (GtkWidget *,
14579                          ggpointer,
14580                          gpointer);
14581 void GtkWidget::draw-focus      (GtkWidget *,
14582                                  gpointer);
14583 void GtkWidget::draw-default    (GtkWidget *,
14584                                  gpointer);
14585 void GtkWidget::size-request    (GtkWidget *,
14586                                  ggpointer,
14587                                  gpointer);
14588 void GtkWidget::size-allocate   (GtkWidget *,
14589                                  ggpointer,
14590                                  gpointer);
14591 void GtkWidget::state-changed   (GtkWidget *,
14592                                  GtkStateType,
14593                                  gpointer);
14594 void GtkWidget::parent-set      (GtkWidget *,
14595                                  GtkObject *,
14596                                  gpointer);
14597 void GtkWidget::style-set       (GtkWidget *,
14598                                  GtkStyle *,
14599                                  gpointer);
14600 void GtkWidget::add-accelerator (GtkWidget *,
14601                                  gguint,
14602                                  GtkAccelGroup *,
14603                                  gguint,
14604                                  GdkModifierType,
14605                                  GtkAccelFlags,
14606                                  gpointer);
14607 void GtkWidget::remove-accelerator      (GtkWidget *,
14608                                          GtkAccelGroup *,
14609                                          gguint,
14610                                          GdkModifierType,
14611                                          gpointer);
14612 gboolean GtkWidget::event       (GtkWidget *,
14613                                  GdkEvent *,
14614                                  gpointer);
14615 gboolean GtkWidget::button-press-event  (GtkWidget *,
14616                                          GdkEvent *,
14617                                          gpointer);
14618 gboolean GtkWidget::button-release-event        (GtkWidget *,
14619                                                  GdkEvent *,
14620                                                  gpointer);
14621 gboolean GtkWidget::motion-notify-event (GtkWidget *,
14622                                          GdkEvent *,
14623                                          gpointer);
14624 gboolean GtkWidget::delete-event        (GtkWidget *,
14625                                          GdkEvent *,
14626                                          gpointer);
14627 gboolean GtkWidget::destroy-event       (GtkWidget *,
14628                                          GdkEvent *,
14629                                          gpointer);
14630 gboolean GtkWidget::expose-event        (GtkWidget *,
14631                                          GdkEvent *,
14632                                          gpointer);
14633 gboolean GtkWidget::key-press-event     (GtkWidget *,
14634                                          GdkEvent *,
14635                                          gpointer);
14636 gboolean GtkWidget::key-release-event   (GtkWidget *,
14637                                          GdkEvent *,
14638                                          gpointer);
14639 gboolean GtkWidget::enter-notify-event  (GtkWidget *,
14640                                          GdkEvent *,
14641                                          gpointer);
14642 gboolean GtkWidget::leave-notify-event  (GtkWidget *,
14643                                          GdkEvent *,
14644                                          gpointer);
14645 gboolean GtkWidget::configure-event     (GtkWidget *,
14646                                          GdkEvent *,
14647                                          gpointer);
14648 gboolean GtkWidget::focus-in-event      (GtkWidget *,
14649                                          GdkEvent *,
14650                                          gpointer);
14651 gboolean GtkWidget::focus-out-event     (GtkWidget *,
14652                                          GdkEvent *,
14653                                          gpointer);
14654 gboolean GtkWidget::map-event   (GtkWidget *,
14655                                  GdkEvent *,
14656                                  gpointer);
14657 gboolean GtkWidget::unmap-event (GtkWidget *,
14658                                  GdkEvent *,
14659                                  gpointer);
14660 gboolean GtkWidget::property-notify-event       (GtkWidget *,
14661                                                  GdkEvent *,
14662                                                  gpointer);
14663 gboolean GtkWidget::selection-clear-event       (GtkWidget *,
14664                                                  GdkEvent *,
14665                                                  gpointer);
14666 gboolean GtkWidget::selection-request-event     (GtkWidget *,
14667                                                  GdkEvent *,
14668                                                  gpointer);
14669 gboolean GtkWidget::selection-notify-event      (GtkWidget *,
14670                                                  GdkEvent *,
14671                                                  gpointer);
14672 void GtkWidget::selection-get   (GtkWidget *,
14673                                  GtkSelectionData *,
14674                                  gguint,
14675                                  gpointer);
14676 void GtkWidget::selection-received      (GtkWidget *,
14677                                          GtkSelectionData *,
14678                                          gguint,
14679                                          gpointer);
14680 gboolean GtkWidget::proximity-in-event  (GtkWidget *,
14681                                          GdkEvent *,
14682                                          gpointer);
14683 gboolean GtkWidget::proximity-out-event (GtkWidget *,
14684                                          GdkEvent *,
14685                                          gpointer);
14686 void GtkWidget::drag-begin      (GtkWidget *,
14687                                  GdkDragContext *,
14688                                  gpointer);
14689 void GtkWidget::drag-end        (GtkWidget *,
14690                                  GdkDragContext *,
14691                                  gpointer);
14692 void GtkWidget::drag-data-delete        (GtkWidget *,
14693                                          GdkDragContext *,
14694                                          gpointer);
14695 void GtkWidget::drag-leave      (GtkWidget *,
14696                                  GdkDragContext *,
14697                                  gguint,
14698                                  gpointer);
14699 gboolean GtkWidget::drag-motion (GtkWidget *,
14700                                  GdkDragContext *,
14701                                  ggint,
14702                                  ggint,
14703                                  gguint,
14704                                  gpointer);
14705 gboolean GtkWidget::drag-drop   (GtkWidget *,
14706                                  GdkDragContext *,
14707                                  ggint,
14708                                  ggint,
14709                                  gguint,
14710                                  gpointer);
14711 void GtkWidget::drag-data-get   (GtkWidget *,
14712                                  GdkDragContext *,
14713                                  GtkSelectionData *,
14714                                  gguint,
14715                                  gguint,
14716                                  gpointer);
14717 void GtkWidget::drag-data-received      (GtkWidget *,
14718                                          GdkDragContext *,
14719                                          ggint,
14720                                          ggint,
14721                                          GtkSelectionData *,
14722                                          gguint,
14723                                          gguint,
14724                                          gpointer);
14725 gboolean GtkWidget::client-event        (GtkWidget *,
14726                                          GdkEvent *,
14727                                          gpointer);
14728 gboolean GtkWidget::no-expose-event     (GtkWidget *,
14729                                          GdkEvent *,
14730                                          gpointer);
14731 gboolean GtkWidget::visibility-notify-event     (GtkWidget *,
14732                                                  GdkEvent *,
14733                                                  gpointer);
14734 void GtkWidget::debug-msg       (GtkWidget *,
14735                                  GtkString *,
14736                                  gpointer);
14737 </verb></tscreen>
14738
14739 <!-- ----------------------------------------------------------------- -->
14740 <sect1>GtkData
14741 <!-- ----------------------------------------------------------------- -->
14742 <p>
14743 <tscreen><verb>
14744 void GtkData::disconnect        (GtkData *,
14745                                  gpointer);
14746 </verb></tscreen>
14747
14748 <!-- ----------------------------------------------------------------- -->
14749 <sect1>GtkContainer
14750 <!-- ----------------------------------------------------------------- -->
14751 <p>
14752 <tscreen><verb>
14753 void GtkContainer::add  (GtkContainer *,
14754                          GtkWidget *,
14755                          gpointer);
14756 void GtkContainer::remove       (GtkContainer *,
14757                                  GtkWidget *,
14758                                  gpointer);
14759 void GtkContainer::check-resize (GtkContainer *,
14760                                  gpointer);
14761 GtkDirectionType GtkContainer::focus    (GtkContainer *,
14762                                          GtkDirectionType,
14763                                          gpointer);
14764 void GtkContainer::set-focus-child      (GtkContainer *,
14765                                          GtkWidget *,
14766                                          gpointer);
14767 </verb></tscreen>
14768
14769 <!-- ----------------------------------------------------------------- -->
14770 <sect1>GtkCalendar
14771 <!-- ----------------------------------------------------------------- -->
14772 <p>
14773 <tscreen><verb>
14774 void GtkCalendar::month-changed (GtkCalendar *,
14775                                  gpointer);
14776 void GtkCalendar::day-selected  (GtkCalendar *,
14777                                  gpointer);
14778 void GtkCalendar::day-selected-double-click     (GtkCalendar *,
14779                                                  gpointer);
14780 void GtkCalendar::prev-month    (GtkCalendar *,
14781                                  gpointer);
14782 void GtkCalendar::next-month    (GtkCalendar *,
14783                                  gpointer);
14784 void GtkCalendar::prev-year     (GtkCalendar *,
14785                                  gpointer);
14786 void GtkCalendar::next-year     (GtkCalendar *,
14787                                  gpointer);
14788 </verb></tscreen>
14789
14790 <!-- ----------------------------------------------------------------- -->
14791 <sect1>GtkEditable
14792 <!-- ----------------------------------------------------------------- -->
14793 <p>
14794 <tscreen><verb>
14795 void GtkEditable::changed       (GtkEditable *,
14796                                  gpointer);
14797 void GtkEditable::insert-text   (GtkEditable *,
14798                                  GtkString *,
14799                                  ggint,
14800                                  ggpointer,
14801                                  gpointer);
14802 void GtkEditable::delete-text   (GtkEditable *,
14803                                  ggint,
14804                                  ggint,
14805                                  gpointer);
14806 void GtkEditable::activate      (GtkEditable *,
14807                                  gpointer);
14808 void GtkEditable::set-editable  (GtkEditable *,
14809                                  gboolean,
14810                                  gpointer);
14811 void GtkEditable::move-cursor   (GtkEditable *,
14812                                  ggint,
14813                                  ggint,
14814                                  gpointer);
14815 void GtkEditable::move-word     (GtkEditable *,
14816                                  ggint,
14817                                  gpointer);
14818 void GtkEditable::move-page     (GtkEditable *,
14819                                  ggint,
14820                                  ggint,
14821                                  gpointer);
14822 void GtkEditable::move-to-row   (GtkEditable *,
14823                                  ggint,
14824                                  gpointer);
14825 void GtkEditable::move-to-column        (GtkEditable *,
14826                                          ggint,
14827                                          gpointer);
14828 void GtkEditable::kill-char     (GtkEditable *,
14829                                  ggint,
14830                                  gpointer);
14831 void GtkEditable::kill-word     (GtkEditable *,
14832                                  ggint,
14833                                  gpointer);
14834 void GtkEditable::kill-line     (GtkEditable *,
14835                                  ggint,
14836                                  gpointer);
14837 void GtkEditable::cut-clipboard (GtkEditable *,
14838                                  gpointer);
14839 void GtkEditable::copy-clipboard        (GtkEditable *,
14840                                          gpointer);
14841 void GtkEditable::paste-clipboard       (GtkEditable *,
14842                                          gpointer);
14843 </verb></tscreen>
14844
14845 <!-- ----------------------------------------------------------------- -->
14846 <sect1>GtkTipsQuery
14847 <!-- ----------------------------------------------------------------- -->
14848 <p>
14849 <tscreen><verb>
14850 void GtkTipsQuery::start-query  (GtkTipsQuery *,
14851                                  gpointer);
14852 void GtkTipsQuery::stop-query   (GtkTipsQuery *,
14853                                  gpointer);
14854 void GtkTipsQuery::widget-entered       (GtkTipsQuery *,
14855                                          GtkWidget *,
14856                                          GtkString *,
14857                                          GtkString *,
14858                                          gpointer);
14859 gboolean GtkTipsQuery::widget-selected  (GtkTipsQuery *,
14860                                          GtkWidget *,
14861                                          GtkString *,
14862                                          GtkString *,
14863                                          GdkEvent *,
14864                                          gpointer);
14865 </verb></tscreen>
14866
14867 <!-- ----------------------------------------------------------------- -->
14868 <sect1>GtkCList
14869 <!-- ----------------------------------------------------------------- -->
14870 <p>
14871 <tscreen><verb>
14872 void GtkCList::select-row       (GtkCList *,
14873                                  ggint,
14874                                  ggint,
14875                                  GdkEvent *,
14876                                  gpointer);
14877 void GtkCList::unselect-row     (GtkCList *,
14878                                  ggint,
14879                                  ggint,
14880                                  GdkEvent *,
14881                                  gpointer);
14882 void GtkCList::row-move (GtkCList *,
14883                          ggint,
14884                          ggint,
14885                          gpointer);
14886 void GtkCList::click-column     (GtkCList *,
14887                                  ggint,
14888                                  gpointer);
14889 void GtkCList::resize-column    (GtkCList *,
14890                                  ggint,
14891                                  ggint,
14892                                  gpointer);
14893 void GtkCList::toggle-focus-row (GtkCList *,
14894                                  gpointer);
14895 void GtkCList::select-all       (GtkCList *,
14896                                  gpointer);
14897 void GtkCList::unselect-all     (GtkCList *,
14898                                  gpointer);
14899 void GtkCList::undo-selection   (GtkCList *,
14900                                  gpointer);
14901 void GtkCList::start-selection  (GtkCList *,
14902                                  gpointer);
14903 void GtkCList::end-selection    (GtkCList *,
14904                                  gpointer);
14905 void GtkCList::toggle-add-mode  (GtkCList *,
14906                                  gpointer);
14907 void GtkCList::extend-selection (GtkCList *,
14908                                  GtkScrollType,
14909                                  ggfloat,
14910                                  gboolean,
14911                                  gpointer);
14912 void GtkCList::scroll-vertical  (GtkCList *,
14913                                  GtkScrollType,
14914                                  ggfloat,
14915                                  gpointer);
14916 void GtkCList::scroll-horizontal        (GtkCList *,
14917                                          GtkScrollType,
14918                                          ggfloat,
14919                                          gpointer);
14920 void GtkCList::abort-column-resize      (GtkCList *,
14921                                          gpointer);
14922 </verb></tscreen>
14923
14924 <!-- ----------------------------------------------------------------- -->
14925 <sect1>GtkNotebook
14926 <!-- ----------------------------------------------------------------- -->
14927 <p>
14928 <tscreen><verb>
14929 void GtkNotebook::switch-page   (GtkNotebook *,
14930                                  ggpointer,
14931                                  gguint,
14932                                  gpointer);
14933
14934 </verb></tscreen>
14935
14936 <!-- ----------------------------------------------------------------- -->
14937 <sect1>GtkList
14938 <!-- ----------------------------------------------------------------- -->
14939 <p>
14940 <tscreen><verb>
14941 void GtkList::selection-changed (GtkList *,
14942                                  gpointer);
14943 void GtkList::select-child      (GtkList *,
14944                                  GtkWidget *,
14945                                  gpointer);
14946 void GtkList::unselect-child    (GtkList *,
14947                                  GtkWidget *,
14948                                  gpointer);
14949 </verb></tscreen>
14950
14951 <!-- ----------------------------------------------------------------- -->
14952 <sect1>GtkMenuShell
14953 <!-- ----------------------------------------------------------------- -->
14954 <p>
14955 <tscreen><verb>
14956 void GtkMenuShell::deactivate   (GtkMenuShell *,
14957                                  gpointer);
14958 void GtkMenuShell::selection-done       (GtkMenuShell *,
14959                                          gpointer);
14960 void GtkMenuShell::move-current (GtkMenuShell *,
14961                                  GtkMenuDirectionType,
14962                                  gpointer);
14963 void GtkMenuShell::activate-current     (GtkMenuShell *,
14964                                          gboolean,
14965                                          gpointer);
14966 void GtkMenuShell::cancel       (GtkMenuShell *,
14967                                  gpointer);
14968 </verb></tscreen>
14969
14970 <!-- ----------------------------------------------------------------- -->
14971 <sect1>GtkToolbar
14972 <!-- ----------------------------------------------------------------- -->
14973 <p>
14974 <tscreen><verb>
14975 void GtkToolbar::orientation-changed    (GtkToolbar *,
14976                                          ggint,
14977                                          gpointer);
14978 void GtkToolbar::style-changed  (GtkToolbar *,
14979                                  ggint,
14980                                  gpointer);
14981 </verb></tscreen>
14982
14983 <!-- ----------------------------------------------------------------- -->
14984 <sect1>GtkTree
14985 <!-- ----------------------------------------------------------------- -->
14986 <p>
14987 <tscreen><verb>
14988 void GtkTree::selection-changed (GtkTree *,
14989                                  gpointer);
14990 void GtkTree::select-child      (GtkTree *,
14991                                  GtkWidget *,
14992                                  gpointer);
14993 void GtkTree::unselect-child    (GtkTree *,
14994                                  GtkWidget *,
14995                                  gpointer);
14996 </verb></tscreen>
14997
14998 <!-- ----------------------------------------------------------------- -->
14999 <sect1>GtkButton
15000 <!-- ----------------------------------------------------------------- -->
15001 <p>
15002 <tscreen><verb>
15003 void GtkButton::pressed (GtkButton *,
15004                          gpointer);
15005 void GtkButton::released        (GtkButton *,
15006                                  gpointer);
15007 void GtkButton::clicked (GtkButton *,
15008                          gpointer);
15009 void GtkButton::enter   (GtkButton *,
15010                          gpointer);
15011 void GtkButton::leave   (GtkButton *,
15012                          gpointer);
15013 </verb></tscreen>
15014
15015 <!-- ----------------------------------------------------------------- -->
15016 <sect1>GtkItem
15017 <!-- ----------------------------------------------------------------- -->
15018 <p>
15019 <tscreen><verb>
15020 void GtkItem::select    (GtkItem *,
15021                          gpointer);
15022 void GtkItem::deselect  (GtkItem *,
15023                          gpointer);
15024 void GtkItem::toggle    (GtkItem *,
15025                          gpointer);
15026 </verb></tscreen>
15027
15028 <!-- ----------------------------------------------------------------- -->
15029 <sect1>GtkWindow
15030 <!-- ----------------------------------------------------------------- -->
15031 <p>
15032 <tscreen><verb>
15033 void GtkWindow::set-focus       (GtkWindow *,
15034                                  ggpointer,
15035                                  gpointer);
15036 </verb></tscreen>
15037
15038 <!-- ----------------------------------------------------------------- -->
15039 <sect1>GtkHandleBox
15040 <!-- ----------------------------------------------------------------- -->
15041 <p>
15042 <tscreen><verb>
15043 void GtkHandleBox::child-attached       (GtkHandleBox *,
15044                                          GtkWidget *,
15045                                          gpointer);
15046 void GtkHandleBox::child-detached       (GtkHandleBox *,
15047                                          GtkWidget *,
15048                                          gpointer);
15049 </verb></tscreen>
15050
15051 <!-- ----------------------------------------------------------------- -->
15052 <sect1>GtkToggleButton
15053 <!-- ----------------------------------------------------------------- -->
15054 <p>
15055 <tscreen><verb>
15056 void GtkToggleButton::toggled   (GtkToggleButton *,
15057                                  gpointer);
15058
15059 </verb></tscreen>
15060
15061 <!-- ----------------------------------------------------------------- -->
15062 <sect1>GtkMenuItem
15063 <!-- ----------------------------------------------------------------- -->
15064 <p>
15065 <tscreen><verb>
15066 void GtkMenuItem::activate      (GtkMenuItem *,
15067                                  gpointer);
15068 void GtkMenuItem::activate-item (GtkMenuItem *,
15069                                  gpointer);
15070 </verb></tscreen>
15071
15072 <!-- ----------------------------------------------------------------- -->
15073 <sect1>GtkListItem
15074 <!-- ----------------------------------------------------------------- -->
15075 <p>
15076 <tscreen><verb>
15077 void GtkListItem::toggle-focus-row      (GtkListItem *,
15078                                          gpointer);
15079 void GtkListItem::select-all    (GtkListItem *,
15080                                  gpointer);
15081 void GtkListItem::unselect-all  (GtkListItem *,
15082                                  gpointer);
15083 void GtkListItem::undo-selection        (GtkListItem *,
15084                                          gpointer);
15085 void GtkListItem::start-selection       (GtkListItem *,
15086                                          gpointer);
15087 void GtkListItem::end-selection (GtkListItem *,
15088                                  gpointer);
15089 void GtkListItem::toggle-add-mode       (GtkListItem *,
15090                                          gpointer);
15091 void GtkListItem::extend-selection      (GtkListItem *,
15092                                          GtkEnum,
15093                                          ggfloat,
15094                                          gboolean,
15095                                          gpointer);
15096 void GtkListItem::scroll-vertical       (GtkListItem *,
15097                                          GtkEnum,
15098                                          ggfloat,
15099                                          gpointer);
15100 void GtkListItem::scroll-horizontal     (GtkListItem *,
15101                                          GtkEnum,
15102                                          ggfloat,
15103                                          gpointer);
15104 </verb></tscreen>
15105
15106 <!-- ----------------------------------------------------------------- -->
15107 <sect1>GtkTreeItem
15108 <!-- ----------------------------------------------------------------- -->
15109 <p>
15110 <tscreen><verb>
15111 void GtkTreeItem::collapse      (GtkTreeItem *,
15112                                  gpointer);
15113 void GtkTreeItem::expand        (GtkTreeItem *,
15114                                  gpointer);
15115 </verb></tscreen>
15116
15117 <!-- ----------------------------------------------------------------- -->
15118 <sect1>GtkCheckMenuItem
15119 <!-- ----------------------------------------------------------------- -->
15120 <p>
15121 <tscreen><verb>
15122 void GtkCheckMenuItem::toggled  (GtkCheckMenuItem *,
15123                                  gpointer);
15124 </verb></tscreen>
15125
15126 <!-- ----------------------------------------------------------------- -->
15127 <sect1>GtkInputDialog
15128 <!-- ----------------------------------------------------------------- -->
15129 <p>
15130 <tscreen><verb>
15131 void GtkInputDialog::enable-device      (GtkInputDialog *,
15132                                          ggint,
15133                                          gpointer);
15134 void GtkInputDialog::disable-device     (GtkInputDialog *,
15135                                          ggint,
15136                                          gpointer);
15137 </verb></tscreen>
15138
15139 <!-- ----------------------------------------------------------------- -->
15140 <sect1>GtkColorSelection
15141 <!-- ----------------------------------------------------------------- -->
15142 <p>
15143 <tscreen><verb>
15144 void GtkColorSelection::color-changed   (GtkColorSelection *,
15145                                          gpointer);
15146 </verb></tscreen>
15147
15148 <!-- ----------------------------------------------------------------- -->
15149 <sect1>GtkStatusBar
15150 <!-- ----------------------------------------------------------------- -->
15151 <p>
15152 <tscreen><verb>
15153 void GtkStatusbar::text-pushed  (GtkStatusbar *,
15154                                  gguint,
15155                                  GtkString *,
15156                                  gpointer);
15157 void GtkStatusbar::text-popped  (GtkStatusbar *,
15158                                  gguint,
15159                                  GtkString *,
15160                                  gpointer);
15161 </verb></tscreen>
15162
15163 <!-- ----------------------------------------------------------------- -->
15164 <sect1>GtkCTree
15165 <!-- ----------------------------------------------------------------- -->
15166 <p>
15167 <tscreen><verb>
15168 void GtkCTree::tree-select-row  (GtkCTree *,
15169                                  GtkCTreeNode *,
15170                                  ggint,
15171                                  gpointer);
15172 void GtkCTree::tree-unselect-row        (GtkCTree *,
15173                                          GtkCTreeNode *,
15174                                          ggint,
15175                                          gpointer);
15176 void GtkCTree::tree-expand      (GtkCTree *,
15177                                  GtkCTreeNode *,
15178                                  gpointer);
15179 void GtkCTree::tree-collapse    (GtkCTree *,
15180                                  ggpointer,
15181                                  gpointer);
15182 void GtkCTree::tree-move        (GtkCTree *,
15183                                  GtkCTreeNode *,
15184                                  GtkCTreeNode *,
15185                                  GtkCTreeNode *,
15186                                  gpointer);
15187 void GtkCTree::change-focus-row-expansion       (GtkCTree *,
15188                                                  GtkCTreeExpansionType,
15189                                                  gpointer);
15190 </verb></tscreen>
15191
15192 <!-- ----------------------------------------------------------------- -->
15193 <sect1>GtkCurve
15194 <!-- ----------------------------------------------------------------- -->
15195 <p>
15196 <tscreen><verb>
15197 void GtkCurve::curve-type-changed       (GtkCurve *,
15198                                          gpointer);
15199 </verb></tscreen>
15200
15201 <!-- ----------------------------------------------------------------- -->
15202 <sect1>GtkAdjustment
15203 <!-- ----------------------------------------------------------------- -->
15204 <p>
15205 <tscreen><verb>
15206 void GtkAdjustment::changed     (GtkAdjustment *,
15207                                  gpointer);
15208 void GtkAdjustment::value-changed       (GtkAdjustment *,
15209                                          gpointer);
15210 </verb></tscreen>
15211
15212 <!-- ***************************************************************** -->
15213 <sect> GDK Event Types<label id="sec_GDK_Event_Types">
15214 <!-- ***************************************************************** -->
15215 <p>
15216 The following data types are passed into event handlers by GTK+. For
15217 each data type listed, the signals that use this data type are listed.
15218
15219 <itemize>
15220 <item>  GdkEvent
15221           <itemize>
15222           <item>drag_end_event
15223           </itemize>
15224
15225 <item>  GdkEventType
15226
15227 <item>  GdkEventAny
15228           <itemize>
15229           <item>delete_event
15230           <item>destroy_event
15231           <item>map_event
15232           <item>unmap_event
15233           <item>no_expose_event
15234           </itemize>
15235
15236 <item>  GdkEventExpose
15237           <itemize>
15238           <item>expose_event
15239           </itemize>
15240
15241 <item>  GdkEventNoExpose
15242
15243 <item>  GdkEventVisibility
15244
15245 <item>  GdkEventMotion
15246           <itemize>
15247           <item>motion_notify_event
15248           </itemize>
15249
15250 <item>  GdkEventButton
15251           <itemize>
15252           <item>button_press_event
15253           <item>button_release_event
15254           </itemize>
15255
15256 <item>  GdkEventKey
15257           <itemize>
15258           <item>key_press_event
15259           <item>key_release_event
15260           </itemize>
15261
15262 <item>  GdkEventCrossing
15263           <itemize>
15264           <item>enter_notify_event
15265           <item>leave_notify_event
15266           </itemize>
15267
15268 <item>  GdkEventFocus
15269           <itemize>
15270           <item>focus_in_event
15271           <item>focus_out_event
15272           </itemize>
15273
15274 <item>  GdkEventConfigure
15275           <itemize>
15276           <item>configure_event
15277           </itemize>
15278
15279 <item>  GdkEventProperty
15280           <itemize>
15281           <item>property_notify_event
15282           </itemize>
15283
15284 <item>  GdkEventSelection
15285           <itemize>
15286           <item>selection_clear_event
15287           <item>selection_request_event
15288           <item>selection_notify_event
15289           </itemize>
15290
15291 <item>  GdkEventProximity
15292           <itemize>
15293           <item>proximity_in_event
15294           <item>proximity_out_event
15295           </itemize>
15296
15297 <item>  GdkEventDragBegin
15298           <itemize>
15299           <item>drag_begin_event
15300           </itemize>
15301
15302 <item>  GdkEventDragRequest
15303           <itemize>
15304           <item>drag_request_event
15305           </itemize>
15306
15307 <item>  GdkEventDropEnter
15308           <itemize>
15309           <item>drop_enter_event
15310           </itemize>
15311
15312 <item>  GdkEventDropLeave
15313           <itemize>
15314           <item>drop_leave_event
15315           </itemize>
15316
15317 <item>  GdkEventDropDataAvailable
15318           <itemize>
15319           <item>drop_data_available_event
15320           </itemize>
15321
15322 <item>  GdkEventClient
15323           <itemize>
15324           <item>client_event
15325           </itemize>
15326
15327 <item>  GdkEventOther
15328           <itemize>
15329           <item>other_event
15330           </itemize>
15331 </itemize>
15332
15333 The data type <tt/GdkEventType/ is a special data type that is used by
15334 all the other data types as an indicator of the data type being passed
15335 to the signal handler. As you will see below, each of the event data
15336 structures has a member of this type. It is defined as an enumeration
15337 type as follows:
15338
15339 <tscreen><verb>
15340 typedef enum
15341 {
15342   GDK_NOTHING           = -1,
15343   GDK_DELETE            = 0,
15344   GDK_DESTROY           = 1,
15345   GDK_EXPOSE            = 2,
15346   GDK_MOTION_NOTIFY     = 3,
15347   GDK_BUTTON_PRESS      = 4,
15348   GDK_2BUTTON_PRESS     = 5,
15349   GDK_3BUTTON_PRESS     = 6,
15350   GDK_BUTTON_RELEASE    = 7,
15351   GDK_KEY_PRESS         = 8,
15352   GDK_KEY_RELEASE       = 9,
15353   GDK_ENTER_NOTIFY      = 10,
15354   GDK_LEAVE_NOTIFY      = 11,
15355   GDK_FOCUS_CHANGE      = 12,
15356   GDK_CONFIGURE         = 13,
15357   GDK_MAP               = 14,
15358   GDK_UNMAP             = 15,
15359   GDK_PROPERTY_NOTIFY   = 16,
15360   GDK_SELECTION_CLEAR   = 17,
15361   GDK_SELECTION_REQUEST = 18,
15362   GDK_SELECTION_NOTIFY  = 19,
15363   GDK_PROXIMITY_IN      = 20,
15364   GDK_PROXIMITY_OUT     = 21,
15365   GDK_DRAG_BEGIN        = 22,
15366   GDK_DRAG_REQUEST      = 23,
15367   GDK_DROP_ENTER        = 24,
15368   GDK_DROP_LEAVE        = 25,
15369   GDK_DROP_DATA_AVAIL   = 26,
15370   GDK_CLIENT_EVENT      = 27,
15371   GDK_VISIBILITY_NOTIFY = 28,
15372   GDK_NO_EXPOSE         = 29,
15373   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
15374 } GdkEventType;
15375 </verb></tscreen>
15376
15377 The other event type that is different from the others is
15378 <tt/GdkEvent/ itself. This is a union of all the other
15379 data types, which allows it to be cast to a specific
15380 event data type within a signal handler.
15381
15382 <!-- Just a big list for now, needs expanding upon - TRG -->
15383 So, the event data types are defined as follows:
15384
15385 <tscreen><verb>
15386 struct _GdkEventAny
15387 {
15388   GdkEventType type;
15389   GdkWindow *window;
15390   gint8 send_event;
15391 };
15392
15393 struct _GdkEventExpose
15394 {
15395   GdkEventType type;
15396   GdkWindow *window;
15397   gint8 send_event;
15398   GdkRectangle area;
15399   gint count; /* If non-zero, how many more events follow. */
15400 };
15401
15402 struct _GdkEventNoExpose
15403 {
15404   GdkEventType type;
15405   GdkWindow *window;
15406   gint8 send_event;
15407   /* XXX: does anyone need the X major_code or minor_code fields? */
15408 };
15409
15410 struct _GdkEventVisibility
15411 {
15412   GdkEventType type;
15413   GdkWindow *window;
15414   gint8 send_event;
15415   GdkVisibilityState state;
15416 };
15417
15418 struct _GdkEventMotion
15419 {
15420   GdkEventType type;
15421   GdkWindow *window;
15422   gint8 send_event;
15423   guint32 time;
15424   gdouble x;
15425   gdouble y;
15426   gdouble pressure;
15427   gdouble xtilt;
15428   gdouble ytilt;
15429   guint state;
15430   gint16 is_hint;
15431   GdkInputSource source;
15432   guint32 deviceid;
15433   gdouble x_root, y_root;
15434 };
15435
15436 struct _GdkEventButton
15437 {
15438   GdkEventType type;
15439   GdkWindow *window;
15440   gint8 send_event;
15441   guint32 time;
15442   gdouble x;
15443   gdouble y;
15444   gdouble pressure;
15445   gdouble xtilt;
15446   gdouble ytilt;
15447   guint state;
15448   guint button;
15449   GdkInputSource source;
15450   guint32 deviceid;
15451   gdouble x_root, y_root;
15452 };
15453
15454 struct _GdkEventKey
15455 {
15456   GdkEventType type;
15457   GdkWindow *window;
15458   gint8 send_event;
15459   guint32 time;
15460   guint state;
15461   guint keyval;
15462   gint length;
15463   gchar *string;
15464 };
15465
15466 struct _GdkEventCrossing
15467 {
15468   GdkEventType type;
15469   GdkWindow *window;
15470   gint8 send_event;
15471   GdkWindow *subwindow;
15472   GdkNotifyType detail;
15473 };
15474
15475 struct _GdkEventFocus
15476 {
15477   GdkEventType type;
15478   GdkWindow *window;
15479   gint8 send_event;
15480   gint16 in;
15481 };
15482
15483 struct _GdkEventConfigure
15484 {
15485   GdkEventType type;
15486   GdkWindow *window;
15487   gint8 send_event;
15488   gint16 x, y;
15489   gint16 width;
15490   gint16 height;
15491 };
15492
15493 struct _GdkEventProperty
15494 {
15495   GdkEventType type;
15496   GdkWindow *window;
15497   gint8 send_event;
15498   GdkAtom atom;
15499   guint32 time;
15500   guint state;
15501 };
15502
15503 struct _GdkEventSelection
15504 {
15505   GdkEventType type;
15506   GdkWindow *window;
15507   gint8 send_event;
15508   GdkAtom selection;
15509   GdkAtom target;
15510   GdkAtom property;
15511   guint32 requestor;
15512   guint32 time;
15513 };
15514
15515 /* This event type will be used pretty rarely. It only is important
15516    for XInput aware programs that are drawing their own cursor */
15517
15518 struct _GdkEventProximity
15519 {
15520   GdkEventType type;
15521   GdkWindow *window;
15522   gint8 send_event;
15523   guint32 time;
15524   GdkInputSource source;
15525   guint32 deviceid;
15526 };
15527
15528 struct _GdkEventDragRequest
15529 {
15530   GdkEventType type;
15531   GdkWindow *window;
15532   gint8 send_event;
15533   guint32 requestor;
15534   union {
15535     struct {
15536       guint protocol_version:4;
15537       guint sendreply:1;
15538       guint willaccept:1;
15539       guint delete_data:1; /* Do *not* delete if link is sent, only
15540                               if data is sent */
15541       guint senddata:1;
15542       guint reserved:22;
15543     } flags;
15544     glong allflags;
15545   } u;
15546   guint8 isdrop; /* This gdk event can be generated by a couple of
15547                     X events - this lets the app know whether the
15548                     drop really occurred or we just set the data */
15549
15550   GdkPoint drop_coords;
15551   gchar *data_type;
15552   guint32 timestamp;
15553 };
15554
15555 struct _GdkEventDragBegin
15556 {
15557   GdkEventType type;
15558   GdkWindow *window;
15559   gint8 send_event;
15560   union {
15561     struct {
15562       guint protocol_version:4;
15563       guint reserved:28;
15564     } flags;
15565     glong allflags;
15566   } u;
15567 };
15568
15569 struct _GdkEventDropEnter
15570 {
15571   GdkEventType type;
15572   GdkWindow *window;
15573   gint8 send_event;
15574   guint32 requestor;
15575   union {
15576     struct {
15577       guint protocol_version:4;
15578       guint sendreply:1;
15579       guint extended_typelist:1;
15580       guint reserved:26;
15581     } flags;
15582     glong allflags;
15583   } u;
15584 };
15585
15586 struct _GdkEventDropLeave
15587 {
15588   GdkEventType type;
15589   GdkWindow *window;
15590   gint8 send_event;
15591   guint32 requestor;
15592   union {
15593     struct {
15594       guint protocol_version:4;
15595       guint reserved:28;
15596     } flags;
15597     glong allflags;
15598   } u;
15599 };
15600
15601 struct _GdkEventDropDataAvailable
15602 {
15603   GdkEventType type;
15604   GdkWindow *window;
15605   gint8 send_event;
15606   guint32 requestor;
15607   union {
15608     struct {
15609       guint protocol_version:4;
15610       guint isdrop:1;
15611       guint reserved:25;
15612     } flags;
15613     glong allflags;
15614   } u;
15615   gchar *data_type; /* MIME type */
15616   gulong data_numbytes;
15617   gpointer data;
15618   guint32 timestamp;
15619   GdkPoint coords;
15620 };
15621
15622 struct _GdkEventClient
15623 {
15624   GdkEventType type;
15625   GdkWindow *window;
15626   gint8 send_event;
15627   GdkAtom message_type;
15628   gushort data_format;
15629   union {
15630     char b[20];
15631     short s[10];
15632     long l[5];
15633   } data;
15634 };
15635
15636 struct _GdkEventOther
15637 {
15638   GdkEventType type;
15639   GdkWindow *window;
15640   gint8 send_event;
15641   GdkXEvent *xevent;
15642 };
15643 </verb></tscreen>
15644
15645 <!-- ***************************************************************** -->
15646 <sect> Code Examples
15647 <!-- ***************************************************************** -->
15648 <p>
15649 Below are the code examples that are used in the above text
15650 which are not included in complete form elsewhere.
15651
15652 <!-- ----------------------------------------------------------------- -->
15653 <sect1>Tictactoe
15654 <!-- ----------------------------------------------------------------- -->
15655 <sect2>tictactoe.h
15656 <p>
15657 <tscreen><verb>
15658 /* example-start tictactoe tictactoe.h */
15659
15660 /* GTK - The GIMP Toolkit
15661  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15662  *
15663  * This library is free software; you can redistribute it and/or
15664  * modify it under the terms of the GNU Library General Public
15665  * License as published by the Free Software Foundation; either
15666  * version 2 of the License, or (at your option) any later version.
15667  *
15668  * This library is distributed in the hope that it will be useful,
15669  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15670  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15671  * Library General Public License for more details.
15672  *
15673  * You should have received a copy of the GNU Library General Public
15674  * License along with this library; if not, write to the
15675  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15676  * Boston, MA 02111-1307, USA.
15677  */
15678 #ifndef __TICTACTOE_H__
15679 #define __TICTACTOE_H__
15680
15681
15682 #include <gdk/gdk.h>
15683 #include <gtk/gtkvbox.h>
15684
15685
15686 #ifdef __cplusplus
15687 extern "C" {
15688 #endif /* __cplusplus */
15689
15690 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
15691 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
15692 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
15693
15694
15695 typedef struct _Tictactoe       Tictactoe;
15696 typedef struct _TictactoeClass  TictactoeClass;
15697
15698 struct _Tictactoe
15699 {
15700   GtkVBox vbox;
15701   
15702   GtkWidget *buttons[3][3];
15703 };
15704
15705 struct _TictactoeClass
15706 {
15707   GtkVBoxClass parent_class;
15708
15709   void (* tictactoe) (Tictactoe *ttt);
15710 };
15711
15712 guint          tictactoe_get_type        (void);
15713 GtkWidget*     tictactoe_new             (void);
15714 void           tictactoe_clear           (Tictactoe *ttt);
15715
15716 #ifdef __cplusplus
15717 }
15718 #endif /* __cplusplus */
15719
15720 #endif /* __TICTACTOE_H__ */
15721
15722 /* example-end */
15723 </verb></tscreen>
15724
15725 <!-- ----------------------------------------------------------------- -->
15726 <sect2>tictactoe.c
15727 <p>
15728 <tscreen><verb>
15729 /* example-start tictactoe tictactoe.c */
15730
15731 /* GTK - The GIMP Toolkit
15732  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15733  *
15734  * This library is free software; you can redistribute it and/or
15735  * modify it under the terms of the GNU Library General Public
15736  * License as published by the Free Software Foundation; either
15737  * version 2 of the License, or (at your option) any later version.
15738  *
15739  * This library is distributed in the hope that it will be useful,
15740  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15741  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15742  * Library General Public License for more details.
15743  *
15744  * You should have received a copy of the GNU Library General Public
15745  * License along with this library; if not, write to the
15746  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15747  * Boston, MA 02111-1307, USA.
15748  */
15749 #include "gtk/gtksignal.h"
15750 #include "gtk/gtktable.h"
15751 #include "gtk/gtktogglebutton.h"
15752 #include "tictactoe.h"
15753
15754 enum {
15755   TICTACTOE_SIGNAL,
15756   LAST_SIGNAL
15757 };
15758
15759 static void tictactoe_class_init          (TictactoeClass *klass);
15760 static void tictactoe_init                (Tictactoe      *ttt);
15761 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
15762
15763 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
15764
15765 guint
15766 tictactoe_get_type ()
15767 {
15768   static guint ttt_type = 0;
15769
15770   if (!ttt_type)
15771     {
15772       GtkTypeInfo ttt_info =
15773       {
15774         "Tictactoe",
15775         sizeof (Tictactoe),
15776         sizeof (TictactoeClass),
15777         (GtkClassInitFunc) tictactoe_class_init,
15778         (GtkObjectInitFunc) tictactoe_init,
15779         (GtkArgSetFunc) NULL,
15780         (GtkArgGetFunc) NULL
15781       };
15782
15783       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
15784     }
15785
15786   return ttt_type;
15787 }
15788
15789 static void
15790 tictactoe_class_init (TictactoeClass *class)
15791 {
15792   GtkObjectClass *object_class;
15793
15794   object_class = (GtkObjectClass*) class;
15795   
15796   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
15797                                          GTK_RUN_FIRST,
15798                                          object_class->type,
15799                                          GTK_SIGNAL_OFFSET (TictactoeClass,
15800                                                             tictactoe),
15801                                          gtk_signal_default_marshaller,
15802                                          GTK_TYPE_NONE, 0);
15803
15804
15805   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
15806
15807   class->tictactoe = NULL;
15808 }
15809
15810 static void
15811 tictactoe_init (Tictactoe *ttt)
15812 {
15813   GtkWidget *table;
15814   gint i,j;
15815   
15816   table = gtk_table_new (3, 3, TRUE);
15817   gtk_container_add (GTK_CONTAINER(ttt), table);
15818   gtk_widget_show (table);
15819
15820   for (i=0;i<3; i++)
15821     for (j=0;j<3; j++)
15822       {
15823         ttt->buttons[i][j] = gtk_toggle_button_new ();
15824         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
15825                                    i, i+1, j, j+1);
15826         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
15827                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
15828         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
15829         gtk_widget_show (ttt->buttons[i][j]);
15830       }
15831 }
15832
15833 GtkWidget*
15834 tictactoe_new ()
15835 {
15836   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
15837 }
15838
15839 void           
15840 tictactoe_clear (Tictactoe *ttt)
15841 {
15842   int i,j;
15843
15844   for (i=0;i<3;i++)
15845     for (j=0;j<3;j++)
15846       {
15847         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
15848         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
15849                                      FALSE);
15850         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
15851       }
15852 }
15853
15854 static void
15855 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
15856 {
15857   int i,k;
15858
15859   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
15860                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
15861                              { 0, 1, 2 }, { 0, 1, 2 } };
15862   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
15863                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
15864                              { 0, 1, 2 }, { 2, 1, 0 } };
15865
15866   int success, found;
15867
15868   for (k=0; k<8; k++)
15869     {
15870       success = TRUE;
15871       found = FALSE;
15872
15873       for (i=0;i<3;i++)
15874         {
15875           success = success &amp;&amp; 
15876             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
15877           found = found ||
15878             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
15879         }
15880       
15881       if (success &amp;&amp; found)
15882         {
15883           gtk_signal_emit (GTK_OBJECT (ttt), 
15884                            tictactoe_signals[TICTACTOE_SIGNAL]);
15885           break;
15886         }
15887     }
15888 }
15889
15890 /* example-end */
15891 </verb></tscreen>
15892
15893 <!-- ----------------------------------------------------------------- -->
15894 <sect2>ttt_test.c
15895 <p>
15896 <tscreen><verb>
15897 /* example-start tictactoe ttt_test.c */
15898
15899 #include <gtk/gtk.h>
15900 #include "tictactoe.h"
15901
15902 void win( GtkWidget *widget,
15903           gpointer   data )
15904 {
15905   g_print ("Yay!\n");
15906   tictactoe_clear (TICTACTOE (widget));
15907 }
15908
15909 int main( int   argc,
15910           char *argv[] )
15911 {
15912   GtkWidget *window;
15913   GtkWidget *ttt;
15914   
15915   gtk_init (&amp;argc, &amp;argv);
15916
15917   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
15918   
15919   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
15920   
15921   gtk_signal_connect (GTK_OBJECT (window), "destroy",
15922                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
15923   
15924   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
15925
15926   ttt = tictactoe_new ();
15927   
15928   gtk_container_add (GTK_CONTAINER (window), ttt);
15929   gtk_widget_show (ttt);
15930
15931   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
15932                       GTK_SIGNAL_FUNC (win), NULL);
15933
15934   gtk_widget_show (window);
15935   
15936   gtk_main ();
15937   
15938   return 0;
15939 }
15940
15941 /* example-end */
15942 </verb></tscreen>
15943
15944 <!-- ----------------------------------------------------------------- -->
15945 <sect1> GtkDial
15946
15947 <!-- ----------------------------------------------------------------- -->
15948 <sect2> gtkdial.h
15949 <p>
15950 <tscreen><verb>
15951 /* example-start gtkdial gtkdial.h */
15952
15953 /* GTK - The GIMP Toolkit
15954  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
15955  *
15956  * This library is free software; you can redistribute it and/or
15957  * modify it under the terms of the GNU Library General Public
15958  * License as published by the Free Software Foundation; either
15959  * version 2 of the License, or (at your option) any later version.
15960  *
15961  * This library is distributed in the hope that it will be useful,
15962  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15963  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15964  * Library General Public License for more details.
15965  *
15966  * You should have received a copy of the GNU Library General Public
15967  * License along with this library; if not, write to the
15968  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15969  * Boston, MA 02111-1307, USA.
15970  */
15971 #ifndef __GTK_DIAL_H__
15972 #define __GTK_DIAL_H__
15973
15974
15975 #include <gdk/gdk.h>
15976 #include <gtk/gtkadjustment.h>
15977 #include <gtk/gtkwidget.h>
15978
15979
15980 #ifdef __cplusplus
15981 extern "C" {
15982 #endif /* __cplusplus */
15983
15984
15985 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
15986 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
15987 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
15988
15989
15990 typedef struct _GtkDial        GtkDial;
15991 typedef struct _GtkDialClass   GtkDialClass;
15992
15993 struct _GtkDial
15994 {
15995   GtkWidget widget;
15996
15997   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
15998   guint policy : 2;
15999
16000   /* Button currently pressed or 0 if none */
16001   guint8 button;
16002
16003   /* Dimensions of dial components */
16004   gint radius;
16005   gint pointer_width;
16006
16007   /* ID of update timer, or 0 if none */
16008   guint32 timer;
16009
16010   /* Current angle */
16011   gfloat angle;
16012   gfloat last_angle;
16013
16014   /* Old values from adjustment stored so we know when something changes */
16015   gfloat old_value;
16016   gfloat old_lower;
16017   gfloat old_upper;
16018
16019   /* The adjustment object that stores the data for this dial */
16020   GtkAdjustment *adjustment;
16021 };
16022
16023 struct _GtkDialClass
16024 {
16025   GtkWidgetClass parent_class;
16026 };
16027
16028
16029 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
16030 guint          gtk_dial_get_type               (void);
16031 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
16032 void           gtk_dial_set_update_policy      (GtkDial      *dial,
16033                                                 GtkUpdateType  policy);
16034
16035 void           gtk_dial_set_adjustment         (GtkDial      *dial,
16036                                                 GtkAdjustment *adjustment);
16037 #ifdef __cplusplus
16038 }
16039 #endif /* __cplusplus */
16040
16041
16042 #endif /* __GTK_DIAL_H__ */
16043 /* example-end */
16044 </verb></tscreen>
16045
16046 <!-- ----------------------------------------------------------------- -->
16047 <sect2> gtkdial.c
16048 <p>
16049 <tscreen><verb>
16050 /* example-start gtkdial gtkdial.c */
16051
16052 /* GTK - The GIMP Toolkit
16053  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16054  *
16055  * This library is free software; you can redistribute it and/or
16056  * modify it under the terms of the GNU Library General Public
16057  * License as published by the Free Software Foundation; either
16058  * version 2 of the License, or (at your option) any later version.
16059  *
16060  * This library is distributed in the hope that it will be useful,
16061  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16062  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16063  * Library General Public License for more details.
16064  *
16065  * You should have received a copy of the GNU Library General Public
16066  * License along with this library; if not, write to the
16067  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16068  * Boston, MA 02111-1307, USA.
16069  */
16070 #include <math.h>
16071 #include <stdio.h>
16072 #include <gtk/gtkmain.h>
16073 #include <gtk/gtksignal.h>
16074
16075 #include "gtkdial.h"
16076
16077 #define SCROLL_DELAY_LENGTH  300
16078 #define DIAL_DEFAULT_SIZE 100
16079
16080 /* Forward declarations */
16081
16082 static void gtk_dial_class_init               (GtkDialClass    *klass);
16083 static void gtk_dial_init                     (GtkDial         *dial);
16084 static void gtk_dial_destroy                  (GtkObject        *object);
16085 static void gtk_dial_realize                  (GtkWidget        *widget);
16086 static void gtk_dial_size_request             (GtkWidget      *widget,
16087                                                GtkRequisition *requisition);
16088 static void gtk_dial_size_allocate            (GtkWidget     *widget,
16089                                                GtkAllocation *allocation);
16090 static gint gtk_dial_expose                   (GtkWidget        *widget,
16091                                                 GdkEventExpose   *event);
16092 static gint gtk_dial_button_press             (GtkWidget        *widget,
16093                                                 GdkEventButton   *event);
16094 static gint gtk_dial_button_release           (GtkWidget        *widget,
16095                                                 GdkEventButton   *event);
16096 static gint gtk_dial_motion_notify            (GtkWidget        *widget,
16097                                                 GdkEventMotion   *event);
16098 static gint gtk_dial_timer                    (GtkDial         *dial);
16099
16100 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
16101 static void gtk_dial_update                   (GtkDial *dial);
16102 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
16103                                                 gpointer          data);
16104 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
16105                                                 gpointer          data);
16106
16107 /* Local data */
16108
16109 static GtkWidgetClass *parent_class = NULL;
16110
16111 guint
16112 gtk_dial_get_type ()
16113 {
16114   static guint dial_type = 0;
16115
16116   if (!dial_type)
16117     {
16118       GtkTypeInfo dial_info =
16119       {
16120         "GtkDial",
16121         sizeof (GtkDial),
16122         sizeof (GtkDialClass),
16123         (GtkClassInitFunc) gtk_dial_class_init,
16124         (GtkObjectInitFunc) gtk_dial_init,
16125         (GtkArgSetFunc) NULL,
16126         (GtkArgGetFunc) NULL,
16127       };
16128
16129       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
16130     }
16131
16132   return dial_type;
16133 }
16134
16135 static void
16136 gtk_dial_class_init (GtkDialClass *class)
16137 {
16138   GtkObjectClass *object_class;
16139   GtkWidgetClass *widget_class;
16140
16141   object_class = (GtkObjectClass*) class;
16142   widget_class = (GtkWidgetClass*) class;
16143
16144   parent_class = gtk_type_class (gtk_widget_get_type ());
16145
16146   object_class->destroy = gtk_dial_destroy;
16147
16148   widget_class->realize = gtk_dial_realize;
16149   widget_class->expose_event = gtk_dial_expose;
16150   widget_class->size_request = gtk_dial_size_request;
16151   widget_class->size_allocate = gtk_dial_size_allocate;
16152   widget_class->button_press_event = gtk_dial_button_press;
16153   widget_class->button_release_event = gtk_dial_button_release;
16154   widget_class->motion_notify_event = gtk_dial_motion_notify;
16155 }
16156
16157 static void
16158 gtk_dial_init (GtkDial *dial)
16159 {
16160   dial->button = 0;
16161   dial->policy = GTK_UPDATE_CONTINUOUS;
16162   dial->timer = 0;
16163   dial->radius = 0;
16164   dial->pointer_width = 0;
16165   dial->angle = 0.0;
16166   dial->old_value = 0.0;
16167   dial->old_lower = 0.0;
16168   dial->old_upper = 0.0;
16169   dial->adjustment = NULL;
16170 }
16171
16172 GtkWidget*
16173 gtk_dial_new (GtkAdjustment *adjustment)
16174 {
16175   GtkDial *dial;
16176
16177   dial = gtk_type_new (gtk_dial_get_type ());
16178
16179   if (!adjustment)
16180     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
16181
16182   gtk_dial_set_adjustment (dial, adjustment);
16183
16184   return GTK_WIDGET (dial);
16185 }
16186
16187 static void
16188 gtk_dial_destroy (GtkObject *object)
16189 {
16190   GtkDial *dial;
16191
16192   g_return_if_fail (object != NULL);
16193   g_return_if_fail (GTK_IS_DIAL (object));
16194
16195   dial = GTK_DIAL (object);
16196
16197   if (dial->adjustment)
16198     gtk_object_unref (GTK_OBJECT (dial->adjustment));
16199
16200   if (GTK_OBJECT_CLASS (parent_class)->destroy)
16201     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
16202 }
16203
16204 GtkAdjustment*
16205 gtk_dial_get_adjustment (GtkDial *dial)
16206 {
16207   g_return_val_if_fail (dial != NULL, NULL);
16208   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
16209
16210   return dial->adjustment;
16211 }
16212
16213 void
16214 gtk_dial_set_update_policy (GtkDial      *dial,
16215                              GtkUpdateType  policy)
16216 {
16217   g_return_if_fail (dial != NULL);
16218   g_return_if_fail (GTK_IS_DIAL (dial));
16219
16220   dial->policy = policy;
16221 }
16222
16223 void
16224 gtk_dial_set_adjustment (GtkDial      *dial,
16225                           GtkAdjustment *adjustment)
16226 {
16227   g_return_if_fail (dial != NULL);
16228   g_return_if_fail (GTK_IS_DIAL (dial));
16229
16230   if (dial->adjustment)
16231     {
16232       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
16233       gtk_object_unref (GTK_OBJECT (dial->adjustment));
16234     }
16235
16236   dial->adjustment = adjustment;
16237   gtk_object_ref (GTK_OBJECT (dial->adjustment));
16238
16239   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
16240                       (GtkSignalFunc) gtk_dial_adjustment_changed,
16241                       (gpointer) dial);
16242   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
16243                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
16244                       (gpointer) dial);
16245
16246   dial->old_value = adjustment->value;
16247   dial->old_lower = adjustment->lower;
16248   dial->old_upper = adjustment->upper;
16249
16250   gtk_dial_update (dial);
16251 }
16252
16253 static void
16254 gtk_dial_realize (GtkWidget *widget)
16255 {
16256   GtkDial *dial;
16257   GdkWindowAttr attributes;
16258   gint attributes_mask;
16259
16260   g_return_if_fail (widget != NULL);
16261   g_return_if_fail (GTK_IS_DIAL (widget));
16262
16263   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
16264   dial = GTK_DIAL (widget);
16265
16266   attributes.x = widget->allocation.x;
16267   attributes.y = widget->allocation.y;
16268   attributes.width = widget->allocation.width;
16269   attributes.height = widget->allocation.height;
16270   attributes.wclass = GDK_INPUT_OUTPUT;
16271   attributes.window_type = GDK_WINDOW_CHILD;
16272   attributes.event_mask = gtk_widget_get_events (widget) | 
16273     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
16274     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
16275     GDK_POINTER_MOTION_HINT_MASK;
16276   attributes.visual = gtk_widget_get_visual (widget);
16277   attributes.colormap = gtk_widget_get_colormap (widget);
16278
16279   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
16280   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
16281
16282   widget->style = gtk_style_attach (widget->style, widget->window);
16283
16284   gdk_window_set_user_data (widget->window, widget);
16285
16286   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
16287 }
16288
16289 static void 
16290 gtk_dial_size_request (GtkWidget      *widget,
16291                        GtkRequisition *requisition)
16292 {
16293   requisition->width = DIAL_DEFAULT_SIZE;
16294   requisition->height = DIAL_DEFAULT_SIZE;
16295 }
16296
16297 static void
16298 gtk_dial_size_allocate (GtkWidget     *widget,
16299                         GtkAllocation *allocation)
16300 {
16301   GtkDial *dial;
16302
16303   g_return_if_fail (widget != NULL);
16304   g_return_if_fail (GTK_IS_DIAL (widget));
16305   g_return_if_fail (allocation != NULL);
16306
16307   widget->allocation = *allocation;
16308   dial = GTK_DIAL (widget);
16309
16310   if (GTK_WIDGET_REALIZED (widget))
16311     {
16312
16313       gdk_window_move_resize (widget->window,
16314                               allocation->x, allocation->y,
16315                               allocation->width, allocation->height);
16316
16317     }
16318   dial->radius = MIN(allocation->width,allocation->height) * 0.45;
16319   dial->pointer_width = dial->radius / 5;
16320 }
16321
16322 static gint
16323 gtk_dial_expose (GtkWidget      *widget,
16324                  GdkEventExpose *event)
16325 {
16326   GtkDial *dial;
16327   GdkPoint points[6];
16328   gdouble s,c;
16329   gdouble theta, last, increment;
16330   GtkStyle      *blankstyle;
16331   gint xc, yc;
16332   gint upper, lower;
16333   gint tick_length;
16334   gint i, inc;
16335
16336   g_return_val_if_fail (widget != NULL, FALSE);
16337   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16338   g_return_val_if_fail (event != NULL, FALSE);
16339
16340   if (event->count > 0)
16341     return FALSE;
16342   
16343   dial = GTK_DIAL (widget);
16344
16345 /*  gdk_window_clear_area (widget->window,
16346                          0, 0,
16347                          widget->allocation.width,
16348                          widget->allocation.height);
16349 */
16350   xc = widget->allocation.width/2;
16351   yc = widget->allocation.height/2;
16352
16353   upper = dial->adjustment->upper;
16354   lower = dial->adjustment->lower;
16355
16356   /* Erase old pointer */
16357
16358   s = sin(dial->last_angle);
16359   c = cos(dial->last_angle);
16360   dial->last_angle = dial->angle;
16361
16362   points[0].x = xc + s*dial->pointer_width/2;
16363   points[0].y = yc + c*dial->pointer_width/2;
16364   points[1].x = xc + c*dial->radius;
16365   points[1].y = yc - s*dial->radius;
16366   points[2].x = xc - s*dial->pointer_width/2;
16367   points[2].y = yc - c*dial->pointer_width/2;
16368   points[3].x = xc - c*dial->radius/10;
16369   points[3].y = yc + s*dial->radius/10;
16370   points[4].x = points[0].x;
16371   points[4].y = points[0].y;
16372
16373   blankstyle = gtk_style_new ();
16374   blankstyle->bg_gc[GTK_STATE_NORMAL] =
16375                 widget->style->bg_gc[GTK_STATE_NORMAL];
16376   blankstyle->dark_gc[GTK_STATE_NORMAL] =
16377                 widget->style->bg_gc[GTK_STATE_NORMAL];
16378   blankstyle->light_gc[GTK_STATE_NORMAL] =
16379                 widget->style->bg_gc[GTK_STATE_NORMAL];
16380   blankstyle->black_gc =
16381                 widget->style->bg_gc[GTK_STATE_NORMAL];
16382
16383   gtk_draw_polygon (blankstyle,
16384                     widget->window,
16385                     GTK_STATE_NORMAL,
16386                     GTK_SHADOW_OUT,
16387                     points, 5,
16388                     FALSE);
16389
16390   gtk_style_unref(blankstyle);
16391
16392
16393   /* Draw ticks */
16394
16395   if ((upper - lower) == 0)
16396     return;
16397
16398   increment = (100*M_PI)/(dial->radius*dial->radius);
16399
16400   inc = (upper - lower);
16401
16402   while (inc < 100) inc *=10;
16403   while (inc >= 1000) inc /=10;
16404   last = -1;
16405
16406   for (i=0; i<=inc; i++)
16407     {
16408       theta = ((gfloat)i*M_PI/(18*inc/24.) - M_PI/6.);
16409
16410       if ((theta - last) < (increment))
16411         continue;     
16412       last = theta;
16413
16414       s = sin(theta);
16415       c = cos(theta);
16416
16417       tick_length = (i%(inc/10) == 0) ? dial->pointer_width : dial->pointer_width/2;
16418
16419       gdk_draw_line (widget->window,
16420                      widget->style->fg_gc[widget->state],
16421                      xc + c*(dial->radius - tick_length),
16422                      yc - s*(dial->radius - tick_length),
16423                      xc + c*dial->radius,
16424                      yc - s*dial->radius);
16425     }
16426
16427   /* Draw pointer */
16428
16429   s = sin(dial->angle);
16430   c = cos(dial->angle);
16431   dial->last_angle = dial->angle;
16432
16433   points[0].x = xc + s*dial->pointer_width/2;
16434   points[0].y = yc + c*dial->pointer_width/2;
16435   points[1].x = xc + c*dial->radius;
16436   points[1].y = yc - s*dial->radius;
16437   points[2].x = xc - s*dial->pointer_width/2;
16438   points[2].y = yc - c*dial->pointer_width/2;
16439   points[3].x = xc - c*dial->radius/10;
16440   points[3].y = yc + s*dial->radius/10;
16441   points[4].x = points[0].x;
16442   points[4].y = points[0].y;
16443
16444
16445   gtk_draw_polygon (widget->style,
16446                     widget->window,
16447                     GTK_STATE_NORMAL,
16448                     GTK_SHADOW_OUT,
16449                     points, 5,
16450                     TRUE);
16451
16452   return FALSE;
16453 }
16454
16455 static gint
16456 gtk_dial_button_press (GtkWidget      *widget,
16457                        GdkEventButton *event)
16458 {
16459   GtkDial *dial;
16460   gint dx, dy;
16461   double s, c;
16462   double d_parallel;
16463   double d_perpendicular;
16464
16465   g_return_val_if_fail (widget != NULL, FALSE);
16466   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16467   g_return_val_if_fail (event != NULL, FALSE);
16468
16469   dial = GTK_DIAL (widget);
16470
16471   /* Determine if button press was within pointer region - we 
16472      do this by computing the parallel and perpendicular distance of
16473      the point where the mouse was pressed from the line passing through
16474      the pointer */
16475   
16476   dx = event->x - widget->allocation.width / 2;
16477   dy = widget->allocation.height / 2 - event->y;
16478   
16479   s = sin(dial->angle);
16480   c = cos(dial->angle);
16481   
16482   d_parallel = s*dy + c*dx;
16483   d_perpendicular = fabs(s*dx - c*dy);
16484   
16485   if (!dial->button &amp;&amp;
16486       (d_perpendicular < dial->pointer_width/2) &amp;&amp;
16487       (d_parallel > - dial->pointer_width))
16488     {
16489       gtk_grab_add (widget);
16490
16491       dial->button = event->button;
16492
16493       gtk_dial_update_mouse (dial, event->x, event->y);
16494     }
16495
16496   return FALSE;
16497 }
16498
16499 static gint
16500 gtk_dial_button_release (GtkWidget      *widget,
16501                           GdkEventButton *event)
16502 {
16503   GtkDial *dial;
16504
16505   g_return_val_if_fail (widget != NULL, FALSE);
16506   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16507   g_return_val_if_fail (event != NULL, FALSE);
16508
16509   dial = GTK_DIAL (widget);
16510
16511   if (dial->button == event->button)
16512     {
16513       gtk_grab_remove (widget);
16514
16515       dial->button = 0;
16516
16517       if (dial->policy == GTK_UPDATE_DELAYED)
16518         gtk_timeout_remove (dial->timer);
16519       
16520       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
16521           (dial->old_value != dial->adjustment->value))
16522         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
16523     }
16524
16525   return FALSE;
16526 }
16527
16528 static gint
16529 gtk_dial_motion_notify (GtkWidget      *widget,
16530                          GdkEventMotion *event)
16531 {
16532   GtkDial *dial;
16533   GdkModifierType mods;
16534   gint x, y, mask;
16535
16536   g_return_val_if_fail (widget != NULL, FALSE);
16537   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16538   g_return_val_if_fail (event != NULL, FALSE);
16539
16540   dial = GTK_DIAL (widget);
16541
16542   if (dial->button != 0)
16543     {
16544       x = event->x;
16545       y = event->y;
16546
16547       if (event->is_hint || (event->window != widget->window))
16548         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
16549
16550       switch (dial->button)
16551         {
16552         case 1:
16553           mask = GDK_BUTTON1_MASK;
16554           break;
16555         case 2:
16556           mask = GDK_BUTTON2_MASK;
16557           break;
16558         case 3:
16559           mask = GDK_BUTTON3_MASK;
16560           break;
16561         default:
16562           mask = 0;
16563           break;
16564         }
16565
16566       if (mods &amp; mask)
16567         gtk_dial_update_mouse (dial, x,y);
16568     }
16569
16570   return FALSE;
16571 }
16572
16573 static gint
16574 gtk_dial_timer (GtkDial *dial)
16575 {
16576   g_return_val_if_fail (dial != NULL, FALSE);
16577   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
16578
16579   if (dial->policy == GTK_UPDATE_DELAYED)
16580     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
16581
16582   return FALSE;
16583 }
16584
16585 static void
16586 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
16587 {
16588   gint xc, yc;
16589   gfloat old_value;
16590
16591   g_return_if_fail (dial != NULL);
16592   g_return_if_fail (GTK_IS_DIAL (dial));
16593
16594   xc = GTK_WIDGET(dial)->allocation.width / 2;
16595   yc = GTK_WIDGET(dial)->allocation.height / 2;
16596
16597   old_value = dial->adjustment->value;
16598   dial->angle = atan2(yc-y, x-xc);
16599
16600   if (dial->angle < -M_PI/2.)
16601     dial->angle += 2*M_PI;
16602
16603   if (dial->angle < -M_PI/6)
16604     dial->angle = -M_PI/6;
16605
16606   if (dial->angle > 7.*M_PI/6.)
16607     dial->angle = 7.*M_PI/6.;
16608
16609   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
16610     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
16611
16612   if (dial->adjustment->value != old_value)
16613     {
16614       if (dial->policy == GTK_UPDATE_CONTINUOUS)
16615         {
16616           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
16617         }
16618       else
16619         {
16620           gtk_widget_draw (GTK_WIDGET(dial), NULL);
16621
16622           if (dial->policy == GTK_UPDATE_DELAYED)
16623             {
16624               if (dial->timer)
16625                 gtk_timeout_remove (dial->timer);
16626
16627               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
16628                                              (GtkFunction) gtk_dial_timer,
16629                                              (gpointer) dial);
16630             }
16631         }
16632     }
16633 }
16634
16635 static void
16636 gtk_dial_update (GtkDial *dial)
16637 {
16638   gfloat new_value;
16639   
16640   g_return_if_fail (dial != NULL);
16641   g_return_if_fail (GTK_IS_DIAL (dial));
16642
16643   new_value = dial->adjustment->value;
16644   
16645   if (new_value < dial->adjustment->lower)
16646     new_value = dial->adjustment->lower;
16647
16648   if (new_value > dial->adjustment->upper)
16649     new_value = dial->adjustment->upper;
16650
16651   if (new_value != dial->adjustment->value)
16652     {
16653       dial->adjustment->value = new_value;
16654       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
16655     }
16656
16657   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
16658     (dial->adjustment->upper - dial->adjustment->lower);
16659
16660   gtk_widget_draw (GTK_WIDGET(dial), NULL);
16661 }
16662
16663 static void
16664 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
16665                               gpointer       data)
16666 {
16667   GtkDial *dial;
16668
16669   g_return_if_fail (adjustment != NULL);
16670   g_return_if_fail (data != NULL);
16671
16672   dial = GTK_DIAL (data);
16673
16674   if ((dial->old_value != adjustment->value) ||
16675       (dial->old_lower != adjustment->lower) ||
16676       (dial->old_upper != adjustment->upper))
16677     {
16678       gtk_dial_update (dial);
16679
16680       dial->old_value = adjustment->value;
16681       dial->old_lower = adjustment->lower;
16682       dial->old_upper = adjustment->upper;
16683     }
16684 }
16685
16686 static void
16687 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
16688                                     gpointer       data)
16689 {
16690   GtkDial *dial;
16691
16692   g_return_if_fail (adjustment != NULL);
16693   g_return_if_fail (data != NULL);
16694
16695   dial = GTK_DIAL (data);
16696
16697   if (dial->old_value != adjustment->value)
16698     {
16699       gtk_dial_update (dial);
16700
16701       dial->old_value = adjustment->value;
16702     }
16703 }
16704 /* example-end */
16705
16706 </verb></tscreen>
16707
16708 <!-- ----------------------------------------------------------------- -->
16709 <sect2> dial_test.c
16710 <p>
16711 <tscreen><verb>
16712 #include <gtk/gtk.h>
16713 #include "gtkdial.h"
16714
16715 void value_changed( GtkAdjustment *adjustment,
16716                     GtkWidget     *label )
16717 {
16718   char buffer[16];
16719
16720   sprintf(buffer,"%4.2f",adjustment->value);
16721   gtk_label_set (GTK_LABEL (label), buffer);
16722 }
16723
16724 int main( int   argc,
16725           char *argv[])
16726 {
16727   GtkWidget *window;
16728   GtkAdjustment *adjustment;
16729   GtkWidget *dial;
16730   GtkWidget *frame;
16731   GtkWidget *vbox;
16732   GtkWidget *label;
16733   
16734   gtk_init (&amp;argc, &amp;argv);
16735
16736   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
16737   
16738   gtk_window_set_title (GTK_WINDOW (window), "Dial");
16739   
16740   gtk_signal_connect (GTK_OBJECT (window), "destroy",
16741                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
16742   
16743   gtk_container_border_width (GTK_CONTAINER (window), 10);
16744
16745   vbox = gtk_vbox_new (FALSE, 5);
16746   gtk_container_add (GTK_CONTAINER (window), vbox);
16747   gtk_widget_show(vbox);
16748
16749   frame = gtk_frame_new (NULL);
16750   gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
16751   gtk_container_add (GTK_CONTAINER (vbox), frame);
16752   gtk_widget_show (frame); 
16753  
16754   adjustment = GTK_ADJUSTMENT(gtk_adjustment_new (0, 0, 100, 0.01, 0.1, 0));
16755   
16756   dial = gtk_dial_new(adjustment);
16757   gtk_dial_set_update_policy (GTK_DIAL(dial), GTK_UPDATE_DELAYED);
16758   /*  gtk_widget_set_usize (dial, 100, 100); */
16759   
16760   gtk_container_add (GTK_CONTAINER (frame), dial);
16761   gtk_widget_show (dial);
16762
16763   label = gtk_label_new("0.00");
16764   gtk_box_pack_end (GTK_BOX(vbox), label, 0, 0, 0);
16765   gtk_widget_show (label);
16766
16767   gtk_signal_connect (GTK_OBJECT(adjustment), "value_changed",
16768                       GTK_SIGNAL_FUNC (value_changed), label);
16769   
16770   gtk_widget_show (window);
16771   
16772   gtk_main ();
16773   
16774   return 0;
16775 }
16776
16777 </verb></tscreen>
16778
16779 <!-- ----------------------------------------------------------------- -->
16780 <sect1> Scribble
16781 <p>
16782 <!-- ----------------------------------------------------------------- -->
16783 <sect2> scribble-simple.c
16784 <p>
16785 <tscreen><verb>
16786 /* example-start scribble-simple scribble-simple.c */
16787
16788 /* GTK - The GIMP Toolkit
16789  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16790  *
16791  * This library is free software; you can redistribute it and/or
16792  * modify it under the terms of the GNU Library General Public
16793  * License as published by the Free Software Foundation; either
16794  * version 2 of the License, or (at your option) any later version.
16795  *
16796  * This library is distributed in the hope that it will be useful,
16797  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16798  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16799  * Library General Public License for more details.
16800  *
16801  * You should have received a copy of the GNU Library General Public
16802  * License along with this library; if not, write to the
16803  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16804  * Boston, MA 02111-1307, USA.
16805  */
16806
16807 #include <gtk/gtk.h>
16808
16809 /* Backing pixmap for drawing area */
16810 static GdkPixmap *pixmap = NULL;
16811
16812 /* Create a new backing pixmap of the appropriate size */
16813 static gint configure_event( GtkWidget         *widget,
16814                              GdkEventConfigure *event )
16815 {
16816   if (pixmap)
16817     gdk_pixmap_unref(pixmap);
16818
16819   pixmap = gdk_pixmap_new(widget->window,
16820                           widget->allocation.width,
16821                           widget->allocation.height,
16822                           -1);
16823   gdk_draw_rectangle (pixmap,
16824                       widget->style->white_gc,
16825                       TRUE,
16826                       0, 0,
16827                       widget->allocation.width,
16828                       widget->allocation.height);
16829
16830   return TRUE;
16831 }
16832
16833 /* Redraw the screen from the backing pixmap */
16834 static gint expose_event( GtkWidget      *widget,
16835                           GdkEventExpose *event )
16836 {
16837   gdk_draw_pixmap(widget->window,
16838                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
16839                   pixmap,
16840                   event->area.x, event->area.y,
16841                   event->area.x, event->area.y,
16842                   event->area.width, event->area.height);
16843
16844   return FALSE;
16845 }
16846
16847 /* Draw a rectangle on the screen */
16848 static void draw_brush( GtkWidget *widget,
16849                         gdouble    x,
16850                         gdouble    y)
16851 {
16852   GdkRectangle update_rect;
16853
16854   update_rect.x = x - 5;
16855   update_rect.y = y - 5;
16856   update_rect.width = 10;
16857   update_rect.height = 10;
16858   gdk_draw_rectangle (pixmap,
16859                       widget->style->black_gc,
16860                       TRUE,
16861                       update_rect.x, update_rect.y,
16862                       update_rect.width, update_rect.height);
16863   gtk_widget_draw (widget, &amp;update_rect);
16864 }
16865
16866 static gint button_press_event( GtkWidget      *widget,
16867                                 GdkEventButton *event )
16868 {
16869   if (event->button == 1 &amp;&amp; pixmap != NULL)
16870     draw_brush (widget, event->x, event->y);
16871
16872   return TRUE;
16873 }
16874
16875 static gint motion_notify_event( GtkWidget *widget,
16876                                  GdkEventMotion *event )
16877 {
16878   int x, y;
16879   GdkModifierType state;
16880
16881   if (event->is_hint)
16882     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
16883   else
16884     {
16885       x = event->x;
16886       y = event->y;
16887       state = event->state;
16888     }
16889     
16890   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
16891     draw_brush (widget, x, y);
16892   
16893   return TRUE;
16894 }
16895
16896 void quit ()
16897 {
16898   gtk_exit (0);
16899 }
16900
16901 int main( int   argc, 
16902           char *argv[] )
16903 {
16904   GtkWidget *window;
16905   GtkWidget *drawing_area;
16906   GtkWidget *vbox;
16907
16908   GtkWidget *button;
16909
16910   gtk_init (&amp;argc, &amp;argv);
16911
16912   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
16913   gtk_widget_set_name (window, "Test Input");
16914
16915   vbox = gtk_vbox_new (FALSE, 0);
16916   gtk_container_add (GTK_CONTAINER (window), vbox);
16917   gtk_widget_show (vbox);
16918
16919   gtk_signal_connect (GTK_OBJECT (window), "destroy",
16920                       GTK_SIGNAL_FUNC (quit), NULL);
16921
16922   /* Create the drawing area */
16923
16924   drawing_area = gtk_drawing_area_new ();
16925   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
16926   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
16927
16928   gtk_widget_show (drawing_area);
16929
16930   /* Signals used to handle backing pixmap */
16931
16932   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
16933                       (GtkSignalFunc) expose_event, NULL);
16934   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
16935                       (GtkSignalFunc) configure_event, NULL);
16936
16937   /* Event signals */
16938
16939   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
16940                       (GtkSignalFunc) motion_notify_event, NULL);
16941   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
16942                       (GtkSignalFunc) button_press_event, NULL);
16943
16944   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
16945                          | GDK_LEAVE_NOTIFY_MASK
16946                          | GDK_BUTTON_PRESS_MASK
16947                          | GDK_POINTER_MOTION_MASK
16948                          | GDK_POINTER_MOTION_HINT_MASK);
16949
16950   /* .. And a quit button */
16951   button = gtk_button_new_with_label ("Quit");
16952   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
16953
16954   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
16955                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
16956                              GTK_OBJECT (window));
16957   gtk_widget_show (button);
16958
16959   gtk_widget_show (window);
16960
16961   gtk_main ();
16962
16963   return 0;
16964 }
16965 /* example-end */
16966 </verb></tscreen>
16967
16968 <!-- ----------------------------------------------------------------- -->
16969 <sect2> scribble-xinput.c
16970 <p>
16971 <tscreen><verb>
16972 /* example-start scribble-xinput scribble-xinput.c */
16973
16974 /* GTK - The GIMP Toolkit
16975  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16976  *
16977  * This library is free software; you can redistribute it and/or
16978  * modify it under the terms of the GNU Library General Public
16979  * License as published by the Free Software Foundation; either
16980  * version 2 of the License, or (at your option) any later version.
16981  *
16982  * This library is distributed in the hope that it will be useful,
16983  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16984  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16985  * Library General Public License for more details.
16986  *
16987  * You should have received a copy of the GNU Library General Public
16988  * License along with this library; if not, write to the
16989  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16990  * Boston, MA 02111-1307, USA.
16991  */
16992
16993 #include <gtk/gtk.h>
16994
16995 /* Backing pixmap for drawing area */
16996 static GdkPixmap *pixmap = NULL;
16997
16998 /* Create a new backing pixmap of the appropriate size */
16999 static gint
17000 configure_event (GtkWidget *widget, GdkEventConfigure *event)
17001 {
17002   if (pixmap)
17003      gdk_pixmap_unref(pixmap);
17004
17005   pixmap = gdk_pixmap_new(widget->window,
17006                           widget->allocation.width,
17007                           widget->allocation.height,
17008                           -1);
17009   gdk_draw_rectangle (pixmap,
17010                       widget->style->white_gc,
17011                       TRUE,
17012                       0, 0,
17013                       widget->allocation.width,
17014                       widget->allocation.height);
17015
17016   return TRUE;
17017 }
17018
17019 /* Redraw the screen from the backing pixmap */
17020 static gint
17021 expose_event (GtkWidget *widget, GdkEventExpose *event)
17022 {
17023   gdk_draw_pixmap(widget->window,
17024                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
17025                   pixmap,
17026                   event->area.x, event->area.y,
17027                   event->area.x, event->area.y,
17028                   event->area.width, event->area.height);
17029
17030   return FALSE;
17031 }
17032
17033 /* Draw a rectangle on the screen, size depending on pressure,
17034    and color on the type of device */
17035 static void
17036 draw_brush (GtkWidget *widget, GdkInputSource source,
17037             gdouble x, gdouble y, gdouble pressure)
17038 {
17039   GdkGC *gc;
17040   GdkRectangle update_rect;
17041
17042   switch (source)
17043     {
17044     case GDK_SOURCE_MOUSE:
17045       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
17046       break;
17047     case GDK_SOURCE_PEN:
17048       gc = widget->style->black_gc;
17049       break;
17050     case GDK_SOURCE_ERASER:
17051       gc = widget->style->white_gc;
17052       break;
17053     default:
17054       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
17055     }
17056
17057   update_rect.x = x - 10 * pressure;
17058   update_rect.y = y - 10 * pressure;
17059   update_rect.width = 20 * pressure;
17060   update_rect.height = 20 * pressure;
17061   gdk_draw_rectangle (pixmap, gc, TRUE,
17062                       update_rect.x, update_rect.y,
17063                       update_rect.width, update_rect.height);
17064   gtk_widget_draw (widget, &amp;update_rect);
17065 }
17066
17067 static void
17068 print_button_press (guint32 deviceid)
17069 {
17070   GList *tmp_list;
17071
17072   /* gdk_input_list_devices returns an internal list, so we shouldn't
17073      free it afterwards */
17074   tmp_list = gdk_input_list_devices();
17075
17076   while (tmp_list)
17077     {
17078       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
17079
17080       if (info->deviceid == deviceid)
17081         {
17082           g_print("Button press on device '%s'\n", info->name);
17083           return;
17084         }
17085
17086       tmp_list = tmp_list->next;
17087     }
17088 }
17089
17090 static gint
17091 button_press_event (GtkWidget *widget, GdkEventButton *event)
17092 {
17093   print_button_press (event->deviceid);
17094   
17095   if (event->button == 1 &amp;&amp; pixmap != NULL)
17096     draw_brush (widget, event->source, event->x, event->y, event->pressure);
17097
17098   return TRUE;
17099 }
17100
17101 static gint
17102 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
17103 {
17104   gdouble x, y;
17105   gdouble pressure;
17106   GdkModifierType state;
17107
17108   if (event->is_hint)
17109     gdk_input_window_get_pointer (event->window, event->deviceid,
17110                                   &amp;x, &amp;y, &amp;pressure,
17111                                   NULL, NULL, &amp;state);
17112   else
17113     {
17114       x = event->x;
17115       y = event->y;
17116       pressure = event->pressure;
17117       state = event->state;
17118     }
17119     
17120   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
17121     draw_brush (widget, event->source, x, y, pressure);
17122   
17123   return TRUE;
17124 }
17125
17126 void
17127 input_dialog_destroy (GtkWidget *w, gpointer data)
17128 {
17129   *((GtkWidget **)data) = NULL;
17130 }
17131
17132 void
17133 create_input_dialog ()
17134 {
17135   static GtkWidget *inputd = NULL;
17136
17137   if (!inputd)
17138     {
17139       inputd = gtk_input_dialog_new();
17140
17141       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
17142                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
17143       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
17144                                  "clicked",
17145                                  (GtkSignalFunc)gtk_widget_hide,
17146                                  GTK_OBJECT(inputd));
17147       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
17148
17149       gtk_widget_show (inputd);
17150     }
17151   else
17152     {
17153       if (!GTK_WIDGET_MAPPED(inputd))
17154         gtk_widget_show(inputd);
17155       else
17156         gdk_window_raise(inputd->window);
17157     }
17158 }
17159
17160 void
17161 quit ()
17162 {
17163   gtk_exit (0);
17164 }
17165
17166 int
17167 main (int argc, char *argv[])
17168 {
17169   GtkWidget *window;
17170   GtkWidget *drawing_area;
17171   GtkWidget *vbox;
17172
17173   GtkWidget *button;
17174
17175   gtk_init (&amp;argc, &amp;argv);
17176
17177   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
17178   gtk_widget_set_name (window, "Test Input");
17179
17180   vbox = gtk_vbox_new (FALSE, 0);
17181   gtk_container_add (GTK_CONTAINER (window), vbox);
17182   gtk_widget_show (vbox);
17183
17184   gtk_signal_connect (GTK_OBJECT (window), "destroy",
17185                       GTK_SIGNAL_FUNC (quit), NULL);
17186
17187   /* Create the drawing area */
17188
17189   drawing_area = gtk_drawing_area_new ();
17190   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
17191   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
17192
17193   gtk_widget_show (drawing_area);
17194
17195   /* Signals used to handle backing pixmap */
17196
17197   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
17198                       (GtkSignalFunc) expose_event, NULL);
17199   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
17200                       (GtkSignalFunc) configure_event, NULL);
17201
17202   /* Event signals */
17203
17204   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
17205                       (GtkSignalFunc) motion_notify_event, NULL);
17206   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
17207                       (GtkSignalFunc) button_press_event, NULL);
17208
17209   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
17210                          | GDK_LEAVE_NOTIFY_MASK
17211                          | GDK_BUTTON_PRESS_MASK
17212                          | GDK_POINTER_MOTION_MASK
17213                          | GDK_POINTER_MOTION_HINT_MASK);
17214
17215   /* The following call enables tracking and processing of extension
17216      events for the drawing area */
17217   gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
17218
17219   /* .. And some buttons */
17220   button = gtk_button_new_with_label ("Input Dialog");
17221   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
17222
17223   gtk_signal_connect (GTK_OBJECT (button), "clicked",
17224                       GTK_SIGNAL_FUNC (create_input_dialog), NULL);
17225   gtk_widget_show (button);
17226
17227   button = gtk_button_new_with_label ("Quit");
17228   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
17229
17230   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
17231                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
17232                              GTK_OBJECT (window));
17233   gtk_widget_show (button);
17234
17235   gtk_widget_show (window);
17236
17237   gtk_main ();
17238
17239   return 0;
17240 }
17241 /* example-end */
17242 </verb></tscreen>
17243
17244 <!-- ***************************************************************** -->
17245 <sect> List Widget
17246 <!-- ***************************************************************** -->
17247 <p>
17248 NOTE: The List widget has been superseded by the CList widget. It is
17249 detailed here just for completeness.
17250
17251 The List widget is designed to act as a vertical container for
17252 widgets that should be of the type ListItem.
17253
17254 A List widget has its own window to receive events and its own
17255 background color which is usually white. As it is directly derived
17256 from a Container it can be treated as such by using the
17257 GTK_CONTAINER(List) macro, see the Container widget for more on
17258 this. One should already be familiar with the usage of a GList and
17259 its related functions g_list_*() to be able to use the List widget
17260 to it full extent.
17261
17262 There is one field inside the structure definition of the List
17263 widget that will be of greater interest to us, this is:
17264
17265 <tscreen><verb>
17266 struct _GtkList
17267 {
17268   ...
17269   GList *selection;
17270   guint selection_mode;
17271   ...
17272 }; 
17273 </verb></tscreen>
17274
17275 The selection field of a List points to a linked list of all items
17276 that are currently selected, or NULL if the selection is empty.  So to
17277 learn about the current selection we read the GTK_LIST()->selection
17278 field, but do not modify it since the internal fields are maintained
17279 by the gtk_list_*() functions.
17280
17281 The selection_mode of the List determines the selection facilities
17282 of a List and therefore the contents of the GTK_LIST()->selection
17283 field. The selection_mode may be one of the following:
17284
17285 <itemize>
17286 <item> <tt/GTK_SELECTION_SINGLE/ - The selection is either NULL
17287                         or contains a GList pointer
17288                         for a single selected item.
17289
17290 <item> <tt/GTK_SELECTION_BROWSE/ -  The selection is NULL if the list
17291                         contains no widgets or insensitive
17292                         ones only, otherwise it contains
17293                         a GList pointer for one GList
17294                         structure, and therefore exactly
17295                         one list item.
17296
17297 <item> <tt/GTK_SELECTION_MULTIPLE/ -  The selection is NULL if no list
17298                         items are selected or a GList pointer
17299                         for the first selected item. That
17300                         in turn points to a GList structure
17301                         for the second selected item and so
17302                         on.
17303
17304 <item> <tt/GTK_SELECTION_EXTENDED/ - The selection is always NULL.
17305 </itemize>
17306
17307 The default is <tt/GTK_SELECTION_MULTIPLE/.
17308
17309 <!-- ----------------------------------------------------------------- -->
17310 <sect1> Signals
17311 <p>
17312 <tscreen><verb>
17313 void selection_changed( GtkList *list );
17314 </verb></tscreen>
17315
17316 This signal will be invoked whenever the selection field of a List
17317 has changed. This happens when a child of thekList got selected or
17318 deselected.
17319
17320 <tscreen><verb>
17321 void select_child( GtkList   *list,
17322                    GtkWidget *child);
17323 </verb></tscreen>
17324
17325 This signal is invoked when a child of the List is about to get
17326 selected. This happens mainly on calls to gtk_list_select_item(),
17327 gtk_list_select_child(), button presses and sometimes indirectly
17328 triggered on some else occasions where children get added to or
17329 removed from the List.
17330
17331 <tscreen><verb>
17332 void unselect_child( GtkList   *list,
17333                      GtkWidget *child );
17334 </verb></tscreen>
17335
17336 This signal is invoked when a child of the List is about to get
17337 deselected. This happens mainly on calls to gtk_list_unselect_item(),
17338 gtk_list_unselect_child(), button presses and sometimes indirectly
17339 triggered on some else occasions where children get added to or
17340 removed from the List.
17341
17342 <!-- ----------------------------------------------------------------- -->
17343 <sect1> Functions
17344 <p>
17345 <tscreen><verb>
17346 guint gtk_list_get_type( void );
17347 </verb></tscreen>
17348
17349 Returns the "GtkList" type identifier.
17350
17351 <tscreen><verb>
17352 GtkWidget *gtk_list_new( void );
17353 </verb></tscreen>
17354
17355 Create a new List object. The new widget is returned as a pointer
17356 to a GtkWidget object. NULL is returned on failure.
17357
17358 <tscreen><verb>
17359 void gtk_list_insert_items( GtkList *list,
17360                             GList   *items,
17361                             gint     position );
17362 </verb></tscreen>
17363
17364 Insert list items into the list, starting at <tt/position/.
17365 <tt/items/ is a doubly linked list where each nodes data pointer is
17366 expected to point to a newly created ListItem. The GList nodes of
17367 <tt/items/ are taken over by the list.
17368
17369 <tscreen><verb>
17370 void gtk_list_append_items( GtkList *list,
17371                             GList   *items);
17372 </verb></tscreen>
17373
17374 Insert list items just like gtk_list_insert_items() at the end of the
17375 list. The GList nodes of <tt/items/ are taken over by the list.
17376
17377 <tscreen><verb>
17378 void gtk_list_prepend_items( GtkList *list,
17379                              GList   *items);
17380 </verb></tscreen>
17381
17382 Insert list items just like gtk_list_insert_items() at the very
17383 beginning of the list. The GList nodes of <tt/items/ are taken over by
17384 the list.
17385
17386 <tscreen><verb>
17387 void gtk_list_remove_items( GtkList *list,
17388                             GList   *items);
17389 </verb></tscreen>
17390
17391 Remove list items from the list. <tt/items/ is a doubly linked list
17392 where each nodes data pointer is expected to point to a direct child
17393 of list. It is the callers responsibility to make a call to
17394 g_list_free(items) afterwards. Also the caller has to destroy the list
17395 items himself.
17396
17397 <tscreen><verb>
17398 void gtk_list_clear_items( GtkList *list,
17399                            gint start,
17400                            gint end );
17401 </verb></tscreen>
17402
17403 Remove and destroy list items from the list. A widget is affected if
17404 its current position within the list is in the range specified by
17405 <tt/start/ and <tt/end/.
17406
17407 <tscreen><verb>
17408 void gtk_list_select_item( GtkList *list,
17409                            gint     item );
17410 </verb></tscreen>
17411
17412 Invoke the select_child signal for a list item specified through its
17413 current position within the list.
17414
17415 <tscreen><verb>
17416 void gtk_list_unselect_item( GtkList *list,
17417                              gint     item);
17418 </verb></tscreen>
17419
17420 Invoke the unselect_child signal for a list item specified through its
17421 current position within the list.
17422
17423 <tscreen><verb>
17424 void gtk_list_select_child( GtkList *list,
17425                             GtkWidget *child);
17426 </verb></tscreen>
17427
17428 Invoke the select_child signal for the specified child.
17429
17430 <tscreen><verb>
17431 void gtk_list_unselect_child( GtkList   *list,
17432                               GtkWidget *child);
17433 </verb></tscreen>
17434
17435 Invoke the unselect_child signal for the specified child.
17436
17437 <tscreen><verb>
17438 gint gtk_list_child_position( GtkList *list,
17439                               GtkWidget *child);
17440 </verb></tscreen>
17441
17442 Return the position of <tt/child/ within the list. "-1" is returned on
17443 failure.
17444
17445 <tscreen><verb>
17446 void gtk_list_set_selection_mode( GtkList         *list,
17447                                   GtkSelectionMode mode );
17448 </verb></tscreen>
17449
17450 Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
17451 GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
17452 GTK_SELECTION_EXTENDED.
17453
17454 <tscreen><verb>
17455 GtkList *GTK_LIST( gpointer obj );
17456 </verb></tscreen>
17457
17458 Cast a generic pointer to "GtkList *".
17459
17460 <tscreen><verb>
17461 GtkListClass *GTK_LIST_CLASS( gpointer class);
17462 </verb></tscreen>
17463
17464 Cast a generic pointer to "GtkListClass *". 
17465
17466 <tscreen><verb>
17467 gint GTK_IS_LIST( gpointer obj);
17468 </verb></tscreen>
17469
17470 Determine if a generic pointer refers to a "GtkList" object.
17471
17472 <!-- ----------------------------------------------------------------- -->
17473 <sect1> Example
17474 <p>
17475 Following is an example program that will print out the changes of the
17476 selection of a List, and lets you "arrest" list items into a prison
17477 by selecting them with the rightmost mouse button.
17478
17479 <tscreen><verb>
17480 /* example-start list list.c */
17481
17482 /* Include the GTK header files
17483  * Include stdio.h, we need that for the printf() function
17484  */
17485 #include        <gtk/gtk.h>
17486 #include        <stdio.h>
17487
17488 /* This is our data identification string to store
17489  * data in list items
17490  */
17491 const gchar *list_item_data_key="list_item_data";
17492
17493
17494 /* prototypes for signal handler that we are going to connect
17495  * to the List widget
17496  */
17497 static void  sigh_print_selection( GtkWidget *gtklist,
17498                                    gpointer   func_data);
17499
17500 static void  sigh_button_event( GtkWidget      *gtklist,
17501                                 GdkEventButton *event,
17502                                 GtkWidget      *frame );
17503
17504
17505 /* Main function to set up the user interface */
17506
17507 gint main( int    argc,
17508            gchar *argv[] )
17509 {                                  
17510     GtkWidget *separator;
17511     GtkWidget *window;
17512     GtkWidget *vbox;
17513     GtkWidget *scrolled_window;
17514     GtkWidget *frame;
17515     GtkWidget *gtklist;
17516     GtkWidget *button;
17517     GtkWidget *list_item;
17518     GList *dlist;
17519     guint i;
17520     gchar buffer[64];
17521     
17522     
17523     /* Initialize GTK (and subsequently GDK) */
17524
17525     gtk_init(&amp;argc, &amp;argv);
17526     
17527     
17528     /* Create a window to put all the widgets in
17529      * connect gtk_main_quit() to the "destroy" event of
17530      * the window to handle window manager close-window-events
17531      */
17532     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
17533     gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
17534     gtk_signal_connect(GTK_OBJECT(window),
17535                        "destroy",
17536                        GTK_SIGNAL_FUNC(gtk_main_quit),
17537                        NULL);
17538     
17539     
17540     /* Inside the window we need a box to arrange the widgets
17541      * vertically */
17542     vbox=gtk_vbox_new(FALSE, 5);
17543     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
17544     gtk_container_add(GTK_CONTAINER(window), vbox);
17545     gtk_widget_show(vbox);
17546     
17547     /* This is the scrolled window to put the List widget inside */
17548     scrolled_window=gtk_scrolled_window_new(NULL, NULL);
17549     gtk_widget_set_usize(scrolled_window, 250, 150);
17550     gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
17551     gtk_widget_show(scrolled_window);
17552     
17553     /* Create thekList widget.
17554      * Connect the sigh_print_selection() signal handler
17555      * function to the "selection_changed" signal of the List
17556      * to print out the selected items each time the selection
17557      * has changed */
17558     gtklist=gtk_list_new();
17559     gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
17560                                            gtklist);
17561     gtk_widget_show(gtklist);
17562     gtk_signal_connect(GTK_OBJECT(gtklist),
17563                        "selection_changed",
17564                        GTK_SIGNAL_FUNC(sigh_print_selection),
17565                        NULL);
17566     
17567     /* We create a "Prison" to put a list item in ;) */
17568     frame=gtk_frame_new("Prison");
17569     gtk_widget_set_usize(frame, 200, 50);
17570     gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
17571     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
17572     gtk_container_add(GTK_CONTAINER(vbox), frame);
17573     gtk_widget_show(frame);
17574     
17575     /* Connect the sigh_button_event() signal handler to the List
17576      * which will handle the "arresting" of list items
17577      */
17578     gtk_signal_connect(GTK_OBJECT(gtklist),
17579                        "button_release_event",
17580                        GTK_SIGNAL_FUNC(sigh_button_event),
17581                        frame);
17582     
17583     /* Create a separator */
17584     separator=gtk_hseparator_new();
17585     gtk_container_add(GTK_CONTAINER(vbox), separator);
17586     gtk_widget_show(separator);
17587     
17588     /* Finally create a button and connect its "clicked" signal
17589      * to the destruction of the window */
17590     button=gtk_button_new_with_label("Close");
17591     gtk_container_add(GTK_CONTAINER(vbox), button);
17592     gtk_widget_show(button);
17593     gtk_signal_connect_object(GTK_OBJECT(button),
17594                               "clicked",
17595                               GTK_SIGNAL_FUNC(gtk_widget_destroy),
17596                               GTK_OBJECT(window));
17597     
17598     
17599     /* Now we create 5 list items, each having its own
17600      * label and add them to the List using gtk_container_add()
17601      * Also we query the text string from the label and
17602      * associate it with the list_item_data_key for each list item
17603      */
17604     for (i=0; i<5; i++) {
17605         GtkWidget       *label;
17606         gchar           *string;
17607         
17608         sprintf(buffer, "ListItemContainer with Label #%d", i);
17609         label=gtk_label_new(buffer);
17610         list_item=gtk_list_item_new();
17611         gtk_container_add(GTK_CONTAINER(list_item), label);
17612         gtk_widget_show(label);
17613         gtk_container_add(GTK_CONTAINER(gtklist), list_item);
17614         gtk_widget_show(list_item);
17615         gtk_label_get(GTK_LABEL(label), &amp;string);
17616         gtk_object_set_data(GTK_OBJECT(list_item),
17617                             list_item_data_key,
17618                             string);
17619     }
17620     /* Here, we are creating another 5 labels, this time
17621      * we use gtk_list_item_new_with_label() for the creation
17622      * we can't query the text string from the label because
17623      * we don't have the labels pointer and therefore
17624      * we just associate the list_item_data_key of each
17625      * list item with the same text string.
17626      * For adding of the list items we put them all into a doubly
17627      * linked list (GList), and then add them by a single call to
17628      * gtk_list_append_items().
17629      * Because we use g_list_prepend() to put the items into the
17630      * doubly linked list, their order will be descending (instead
17631      * of ascending when using g_list_append())
17632      */
17633     dlist=NULL;
17634     for (; i<10; i++) {
17635         sprintf(buffer, "List Item with Label %d", i);
17636         list_item=gtk_list_item_new_with_label(buffer);
17637         dlist=g_list_prepend(dlist, list_item);
17638         gtk_widget_show(list_item);
17639         gtk_object_set_data(GTK_OBJECT(list_item),
17640                             list_item_data_key,
17641                             "ListItem with integrated Label");
17642     }
17643     gtk_list_append_items(GTK_LIST(gtklist), dlist);
17644     
17645     /* Finally we want to see the window, don't we? ;) */
17646     gtk_widget_show(window);
17647     
17648     /* Fire up the main event loop of gtk */
17649     gtk_main();
17650     
17651     /* We get here after gtk_main_quit() has been called which
17652      * happens if the main window gets destroyed
17653      */
17654     return(0);
17655 }
17656
17657 /* This is the signal handler that got connected to button
17658  * press/release events of the List
17659  */
17660 void sigh_button_event( GtkWidget      *gtklist,
17661                         GdkEventButton *event,
17662                         GtkWidget      *frame )
17663 {
17664     /* We only do something if the third (rightmost mouse button
17665      * was released
17666      */
17667     if (event->type==GDK_BUTTON_RELEASE &amp;&amp;
17668         event->button==3) {
17669         GList           *dlist, *free_list;
17670         GtkWidget       *new_prisoner;
17671         
17672         /* Fetch the currently selected list item which
17673          * will be our next prisoner ;)
17674          */
17675         dlist=GTK_LIST(gtklist)->selection;
17676         if (dlist)
17677                 new_prisoner=GTK_WIDGET(dlist->data);
17678         else
17679                 new_prisoner=NULL;
17680         
17681         /* Look for already imprisoned list items, we
17682          * will put them back into the list.
17683          * Remember to free the doubly linked list that
17684          * gtk_container_children() returns
17685          */
17686         dlist=gtk_container_children(GTK_CONTAINER(frame));
17687         free_list=dlist;
17688         while (dlist) {
17689             GtkWidget       *list_item;
17690             
17691             list_item=dlist->data;
17692             
17693             gtk_widget_reparent(list_item, gtklist);
17694             
17695             dlist=dlist->next;
17696         }
17697         g_list_free(free_list);
17698         
17699         /* If we have a new prisoner, remove him from the
17700          * List and put him into the frame "Prison".
17701          * We need to unselect the item first.
17702          */
17703         if (new_prisoner) {
17704             GList   static_dlist;
17705             
17706             static_dlist.data=new_prisoner;
17707             static_dlist.next=NULL;
17708             static_dlist.prev=NULL;
17709             
17710             gtk_list_unselect_child(GTK_LIST(gtklist),
17711                                     new_prisoner);
17712             gtk_widget_reparent(new_prisoner, frame);
17713         }
17714     }
17715 }
17716
17717 /* This is the signal handler that gets called if List
17718  * emits the "selection_changed" signal
17719  */
17720 void sigh_print_selection( GtkWidget *gtklist,
17721                            gpointer   func_data )
17722 {
17723     GList   *dlist;
17724     
17725     /* Fetch the doubly linked list of selected items
17726      * of the List, remember to treat this as read-only!
17727      */
17728     dlist=GTK_LIST(gtklist)->selection;
17729     
17730     /* If there are no selected items there is nothing more
17731      * to do than just telling the user so
17732      */
17733     if (!dlist) {
17734         g_print("Selection cleared\n");
17735         return;
17736     }
17737     /* Ok, we got a selection and so we print it
17738      */
17739     g_print("The selection is a ");
17740     
17741     /* Get the list item from the doubly linked list
17742      * and then query the data associated with list_item_data_key.
17743      * We then just print it */
17744     while (dlist) {
17745         GtkObject       *list_item;
17746         gchar           *item_data_string;
17747         
17748         list_item=GTK_OBJECT(dlist->data);
17749         item_data_string=gtk_object_get_data(list_item,
17750                                              list_item_data_key);
17751         g_print("%s ", item_data_string);
17752         
17753         dlist=dlist->next;
17754     }
17755     g_print("\n");
17756 }
17757 /* example-end */
17758 </verb></tscreen>
17759
17760 <!-- ----------------------------------------------------------------- -->
17761 <sect1> List Item Widget
17762 <p>
17763 The ListItem widget is designed to act as a container holding up to
17764 one child, providing functions for selection/deselection just like the
17765 List widget requires them for its children.
17766
17767 A ListItem has its own window to receive events and has its own
17768 background color which is usually white.
17769
17770 As it is directly derived from an Item it can be treated as such by
17771 using the GTK_ITEM(ListItem) macro, see the Item widget for more on
17772 this. Usually a ListItem just holds a label to identify, e.g., a
17773 filename within a List -- therefore the convenience function
17774 gtk_list_item_new_with_label() is provided. The same effect can be
17775 achieved by creating a Label on its own, setting its alignment to
17776 xalign=0 and yalign=0.5 with a subsequent container addition to the
17777 ListItem.
17778
17779 As one is not forced to add a GtkLabel to a GtkListItem, you could
17780 also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
17781
17782 <!-- ----------------------------------------------------------------- -->
17783 <sect1> Signals
17784 <p>
17785 AkListItem does not create new signals on its own, but inherits
17786 the signals of a Item.
17787
17788 <!-- ----------------------------------------------------------------- -->
17789 <sect1> Functions
17790 <p>
17791 <tscreen><verb>
17792 guint gtk_list_item_get_type( void );
17793 </verb></tscreen>
17794
17795 Returns the "GtkListItem" type identifier.
17796
17797 <tscreen><verb>
17798 GtkWidget *gtk_list_item_new( void );
17799 </verb></tscreen>
17800
17801 Create a new ListItem object. The new widget is returned as a
17802 pointer to a GtkWidget object. NULL is returned on failure.
17803
17804 <tscreen><verb>
17805 GtkWidget *gtk_list_item_new_with_label( gchar *label );
17806 </verb></tscreen>
17807
17808 Create a new ListItem object, having a single GtkLabel as the sole
17809 child. The new widget is returned as a pointer to a GtkWidget
17810 object. NULL is returned on failure.
17811
17812 <tscreen><verb>
17813 void gtk_list_item_select( GtkListItem *list_item );
17814 </verb></tscreen>
17815
17816 This function is basically a wrapper around a call to gtk_item_select
17817 (GTK_ITEM (list_item)) which will emit the select signal.  *Note
17818 GtkItem::, for more info.
17819
17820 <tscreen><verb>
17821 void gtk_list_item_deselect( GtkListItem *list_item );
17822 </verb></tscreen>
17823
17824 This function is basically a wrapper around a call to
17825 gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
17826 signal.  *Note GtkItem::, for more info.
17827
17828 <tscreen><verb>
17829 GtkListItem *GTK_LIST_ITEM( gpointer obj );
17830 </verb></tscreen>
17831
17832 Cast a generic pointer to "GtkListItem *".
17833
17834 <tscreen><verb>
17835 GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
17836 </verb></tscreen>
17837
17838 Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
17839 for more info.
17840
17841 <tscreen><verb>
17842 gint GTK_IS_LIST_ITEM( gpointer obj );
17843 </verb></tscreen>
17844
17845 Determine if a generic pointer refers to a `GtkListItem' object.
17846 *Note Standard Macros::, for more info.
17847  
17848 <!-- ----------------------------------------------------------------- -->
17849 <sect1> Example
17850 <p>
17851 Please see the List example on this, which covers the usage of a
17852 ListItem as well.
17853
17854
17855 </article>