]> Pileus Git - ~andy/gtk/blob - docs/tutorial/gtk_tut.sgml
603bbbd986d6300c9468123685664dde407d6f49
[~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>February 23rd, 2000
15 <abstract>
16 This is a tutorial on how to use GTK (the GTK+ 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 (GTK+ 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 GNU 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 (GTK+ 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 You can also temporarily disable signal handlers with the
843 gtk_signal_handler_block() and gtk_signal_handler_unblock() family of
844 functions.
845
846 <tscreen><verb>
847 void gtk_signal_handler_block( GtkObject *object,
848                                guint      handler_id );
849
850 void gtk_signal_handler_block_by_func( GtkObject     *object,
851                                        GtkSignalFunc  func,
852                                        gpointer       data );
853
854 void gtk_signal_handler_block_by_data( GtkObject *object,
855                                        gpointer   data );
856
857 void gtk_signal_handler_unblock( GtkObject *object,
858                                  guint      handler_id );
859
860 void gtk_signal_handler_unblock_by_func( GtkObject     *object,
861                                          GtkSignalFunc  func,
862                                          gpointer       data );
863
864 void gtk_signal_handler_unblock_by_data( GtkObject *object,
865                                          gpointer   data);
866 </verb></tscreen>
867
868 <!-- ----------------------------------------------------------------- -->
869 <sect1>An Upgraded Hello World
870 <p>
871 Let's take a look at a slightly improved <em>helloworld</em> with
872 better examples of callbacks. This will also introduce us to our next
873 topic, packing widgets.
874
875 <tscreen><verb>
876 /* example-start helloworld2 helloworld2.c */
877
878 #include <gtk/gtk.h>
879
880 /* Our new improved callback.  The data passed to this function
881  * is printed to stdout. */
882 void callback( GtkWidget *widget,
883                gpointer   data )
884 {
885     g_print ("Hello again - %s was pressed\n", (char *) data);
886 }
887
888 /* another callback */
889 gint delete_event( GtkWidget *widget,
890                    GdkEvent  *event,
891                    gpointer   data )
892 {
893     gtk_main_quit();
894     return(FALSE);
895 }
896
897 int main( int   argc,
898           char *argv[] )
899 {
900     /* GtkWidget is the storage type for widgets */
901     GtkWidget *window;
902     GtkWidget *button;
903     GtkWidget *box1;
904
905     /* This is called in all GTK applications. Arguments are parsed
906      * from the command line and are returned to the application. */
907     gtk_init (&amp;argc, &amp;argv);
908
909     /* Create a new window */
910     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
911
912     /* This is a new call, which just sets the title of our
913      * new window to "Hello Buttons!" */
914     gtk_window_set_title (GTK_WINDOW (window), "Hello Buttons!");
915
916     /* Here we just set a handler for delete_event that immediately
917      * exits GTK. */
918     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
919                         GTK_SIGNAL_FUNC (delete_event), NULL);
920
921     /* Sets the border width of the window. */
922     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
923
924     /* We create a box to pack widgets into.  This is described in detail
925      * in the "packing" section. The box is not really visible, it
926      * is just used as a tool to arrange widgets. */
927     box1 = gtk_hbox_new(FALSE, 0);
928
929     /* Put the box into the main window. */
930     gtk_container_add (GTK_CONTAINER (window), box1);
931
932     /* Creates a new button with the label "Button 1". */
933     button = gtk_button_new_with_label ("Button 1");
934
935     /* Now when the button is clicked, we call the "callback" function
936      * with a pointer to "button 1" as its argument */
937     gtk_signal_connect (GTK_OBJECT (button), "clicked",
938                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
939
940     /* Instead of gtk_container_add, we pack this button into the invisible
941      * box, which has been packed into the window. */
942     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
943
944     /* Always remember this step, this tells GTK that our preparation for
945      * this button is complete, and it can now be displayed. */
946     gtk_widget_show(button);
947
948     /* Do these same steps again to create a second button */
949     button = gtk_button_new_with_label ("Button 2");
950
951     /* Call the same callback function with a different argument,
952      * passing a pointer to "button 2" instead. */
953     gtk_signal_connect (GTK_OBJECT (button), "clicked",
954                         GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
955
956     gtk_box_pack_start(GTK_BOX(box1), button, TRUE, TRUE, 0);
957
958     /* The order in which we show the buttons is not really important, but I
959      * recommend showing the window last, so it all pops up at once. */
960     gtk_widget_show(button);
961
962     gtk_widget_show(box1);
963
964     gtk_widget_show (window);
965
966     /* Rest in gtk_main and wait for the fun to begin! */
967     gtk_main ();
968
969     return(0);
970 }
971 /* example-end */
972 </verb></tscreen>
973
974 Compile this program using the same linking arguments as our first
975 example.  You'll notice this time there is no easy way to exit the
976 program, you have to use your window manager or command line to kill
977 it. A good exercise for the reader would be to insert a third "Quit"
978 button that will exit the program. You may also wish to play with the
979 options to gtk_box_pack_start() while reading the next section.  Try
980 resizing the window, and observe the behavior.
981
982 Just as a side note, there is another useful define for
983 gtk_window_new() - <tt/GTK_WINDOW_DIALOG/. This interacts with the
984 window manager a little differently and should be used for transient
985 windows.
986
987 <!-- ***************************************************************** -->
988 <sect>Packing Widgets <label id="sec_packing_widgets">
989 <!-- ***************************************************************** -->
990 <p>
991 When creating an application, you'll want to put more than one widget
992 inside a window. Our first <em>helloworld</em> example only used one
993 widget so we could simply use a gtk_container_add call to "pack" the
994 widget into the window. But when you want to put more than one widget
995 into a window, how do you control where that widget is positioned?
996 This is where packing comes in.
997
998 <!-- ----------------------------------------------------------------- -->
999 <sect1>Theory of Packing Boxes
1000 <p>
1001 Most packing is done by creating boxes as in the example above. These
1002 are invisible widget containers that we can pack our widgets into
1003 which come in two forms, a horizontal box, and a vertical box. When
1004 packing widgets into a horizontal box, the objects are inserted
1005 horizontally from left to right or right to left depending on the call
1006 used. In a vertical box, widgets are packed from top to bottom or vice
1007 versa. You may use any combination of boxes inside or beside other
1008 boxes to create the desired effect.
1009
1010 To create a new horizontal box, we use a call to gtk_hbox_new(), and
1011 for vertical boxes, gtk_vbox_new(). The gtk_box_pack_start() and
1012 gtk_box_pack_end() functions are used to place objects inside of these
1013 containers. The gtk_box_pack_start() function will start at the top
1014 and work its way down in a vbox, and pack left to right in an hbox.
1015 gtk_box_pack_end() will do the opposite, packing from bottom to top in
1016 a vbox, and right to left in an hbox. Using these functions allows us
1017 to right justify or left justify our widgets and may be mixed in any
1018 way to achieve the desired effect. We will use gtk_box_pack_start() in
1019 most of our examples. An object may be another container or a
1020 widget. In fact, many widgets are actually containers themselves,
1021 including the button, but we usually only use a label inside a button.
1022
1023 By using these calls, GTK knows where you want to place your widgets
1024 so it can do automatic resizing and other nifty things. There are also
1025 a number of options as to how your widgets should be packed. As you
1026 can imagine, this method gives us a quite a bit of flexibility when
1027 placing and creating widgets.
1028
1029 <!-- ----------------------------------------------------------------- -->
1030 <sect1>Details of Boxes
1031 <p>
1032 Because of this flexibility, packing boxes in GTK can be confusing at
1033 first. There are a lot of options, and it's not immediately obvious how
1034 they all fit together. In the end, however, there are basically five
1035 different styles.
1036
1037 <? <CENTER> >
1038 <?
1039 <IMG SRC="gtk_tut_packbox1.gif" VSPACE="15" HSPACE="10" WIDTH="528"
1040 HEIGHT="235" ALT="Box Packing Example Image">
1041 >
1042 <? </CENTER> >
1043
1044 Each line contains one horizontal box (hbox) with several buttons. The
1045 call to gtk_box_pack is shorthand for the call to pack each of the
1046 buttons into the hbox. Each of the buttons is packed into the hbox the
1047 same way (i.e., same arguments to the gtk_box_pack_start() function).
1048
1049 This is the declaration of the gtk_box_pack_start function.
1050
1051 <tscreen><verb>
1052 void gtk_box_pack_start( GtkBox    *box,
1053                          GtkWidget *child,
1054                          gint       expand,
1055                          gint       fill,
1056                          gint       padding );
1057 </verb></tscreen>
1058
1059 The first argument is the box you are packing the object into, the
1060 second is the object. The objects will all be buttons for now, so
1061 we'll be packing buttons into boxes.
1062
1063 The expand argument to gtk_box_pack_start() and gtk_box_pack_end()
1064 controls whether the widgets are laid out in the box to fill in all
1065 the extra space in the box so the box is expanded to fill the area
1066 allotted to it (TRUE); or the box is shrunk to just fit the widgets
1067 (FALSE). Setting expand to FALSE will allow you to do right and left
1068 justification of your widgets.  Otherwise, they will all expand to fit
1069 into the box, and the same effect could be achieved by using only one
1070 of gtk_box_pack_start or gtk_box_pack_end.
1071
1072 The fill argument to the gtk_box_pack functions control whether the
1073 extra space is allocated to the objects themselves (TRUE), or as extra
1074 padding in the box around these objects (FALSE). It only has an effect
1075 if the expand argument is also TRUE.
1076
1077 When creating a new box, the function looks like this:
1078
1079 <tscreen><verb>
1080 GtkWidget *gtk_hbox_new (gint homogeneous,
1081                          gint spacing);
1082 </verb></tscreen>
1083
1084 The homogeneous argument to gtk_hbox_new (and the same for
1085 gtk_vbox_new) controls whether each object in the box has the same
1086 size (i.e., the same width in an hbox, or the same height in a
1087 vbox). If it is set, the gtk_box_pack routines function essentially
1088 as if the <tt/expand/ argument was always turned on.
1089
1090 What's the difference between spacing (set when the box is created)
1091 and padding (set when elements are packed)? Spacing is added between
1092 objects, and padding is added on either side of an object. The
1093 following figure should make it clearer:
1094
1095 <? <CENTER> >
1096 <?
1097 <IMG ALIGN="center" SRC="gtk_tut_packbox2.gif" WIDTH="509"
1098 HEIGHT="213" VSPACE="15" HSPACE="10"
1099 ALT="Box Packing Example Image">
1100 >
1101 <? </CENTER> >
1102
1103 Here is the code used to create the above images. I've commented it
1104 fairly heavily so I hope you won't have any problems following
1105 it. Compile it yourself and play with it.
1106
1107 <!-- ----------------------------------------------------------------- -->
1108 <sect1>Packing Demonstration Program
1109 <p>
1110 <tscreen><verb>
1111 /* example-start packbox packbox.c */
1112
1113 #include <stdio.h>
1114 #include <stdlib.h>
1115 #include "gtk/gtk.h"
1116
1117 gint delete_event( GtkWidget *widget,
1118                    GdkEvent  *event,
1119                    gpointer   data )
1120 {
1121     gtk_main_quit();
1122     return(FALSE);
1123 }
1124
1125 /* Make a new hbox filled with button-labels. Arguments for the 
1126  * variables we're interested are passed in to this function. 
1127  * We do not show the box, but do show everything inside. */
1128 GtkWidget *make_box( gint homogeneous,
1129                      gint spacing,
1130                      gint expand,
1131                      gint fill,
1132                      gint padding ) 
1133 {
1134     GtkWidget *box;
1135     GtkWidget *button;
1136     char padstr[80];
1137     
1138     /* Create a new hbox with the appropriate homogeneous
1139      * and spacing settings */
1140     box = gtk_hbox_new (homogeneous, spacing);
1141     
1142     /* Create a series of buttons with the appropriate settings */
1143     button = gtk_button_new_with_label ("gtk_box_pack");
1144     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1145     gtk_widget_show (button);
1146     
1147     button = gtk_button_new_with_label ("(box,");
1148     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1149     gtk_widget_show (button);
1150     
1151     button = gtk_button_new_with_label ("button,");
1152     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1153     gtk_widget_show (button);
1154     
1155     /* Create a button with the label depending on the value of
1156      * expand. */
1157     if (expand == TRUE)
1158             button = gtk_button_new_with_label ("TRUE,");
1159     else
1160             button = gtk_button_new_with_label ("FALSE,");
1161     
1162     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1163     gtk_widget_show (button);
1164     
1165     /* This is the same as the button creation for "expand"
1166      * above, but uses the shorthand form. */
1167     button = gtk_button_new_with_label (fill ? "TRUE," : "FALSE,");
1168     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1169     gtk_widget_show (button);
1170     
1171     sprintf (padstr, "%d);", padding);
1172     
1173     button = gtk_button_new_with_label (padstr);
1174     gtk_box_pack_start (GTK_BOX (box), button, expand, fill, padding);
1175     gtk_widget_show (button);
1176     
1177     return box;
1178 }
1179
1180 int main( int   argc,
1181           char *argv[]) 
1182 {
1183     GtkWidget *window;
1184     GtkWidget *button;
1185     GtkWidget *box1;
1186     GtkWidget *box2;
1187     GtkWidget *separator;
1188     GtkWidget *label;
1189     GtkWidget *quitbox;
1190     int which;
1191     
1192     /* Our init, don't forget this! :) */
1193     gtk_init (&amp;argc, &amp;argv);
1194     
1195     if (argc != 2) {
1196         fprintf (stderr, "usage: packbox num, where num is 1, 2, or 3.\n");
1197         /* This just does cleanup in GTK and exits with an exit status of 1. */
1198         gtk_exit (1);
1199     }
1200     
1201     which = atoi (argv[1]);
1202
1203     /* Create our window */
1204     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1205
1206     /* You should always remember to connect the delete_event signal
1207      * to the main window. This is very important for proper intuitive
1208      * behavior */
1209     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1210                         GTK_SIGNAL_FUNC (delete_event), NULL);
1211     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1212     
1213     /* We create a vertical box (vbox) to pack the horizontal boxes into.
1214      * This allows us to stack the horizontal boxes filled with buttons one
1215      * on top of the other in this vbox. */
1216     box1 = gtk_vbox_new (FALSE, 0);
1217     
1218     /* which example to show. These correspond to the pictures above. */
1219     switch (which) {
1220     case 1:
1221         /* create a new label. */
1222         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1223         
1224         /* Align the label to the left side.  We'll discuss this function and 
1225          * others in the section on Widget Attributes. */
1226         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1227
1228         /* Pack the label into the vertical box (vbox box1).  Remember that 
1229          * widgets added to a vbox will be packed one on top of the other in
1230          * order. */
1231         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1232         
1233         /* Show the label */
1234         gtk_widget_show (label);
1235         
1236         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1237          * expand = FALSE, fill = FALSE, padding = 0 */
1238         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1239         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1240         gtk_widget_show (box2);
1241
1242         /* Call our make box function - homogeneous = FALSE, spacing = 0,
1243          * expand = TRUE, fill = FALSE, padding = 0 */
1244         box2 = make_box (FALSE, 0, TRUE, FALSE, 0);
1245         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1246         gtk_widget_show (box2);
1247         
1248         /* Args are: homogeneous, spacing, expand, fill, padding */
1249         box2 = make_box (FALSE, 0, TRUE, TRUE, 0);
1250         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1251         gtk_widget_show (box2);
1252         
1253         /* Creates a separator, we'll learn more about these later, 
1254          * but they are quite simple. */
1255         separator = gtk_hseparator_new ();
1256         
1257         /* Pack the separator into the vbox. Remember each of these
1258          * widgets is being packed into a vbox, so they'll be stacked
1259          * vertically. */
1260         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1261         gtk_widget_show (separator);
1262         
1263         /* Create another new label, and show it. */
1264         label = gtk_label_new ("gtk_hbox_new (TRUE, 0);");
1265         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1266         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1267         gtk_widget_show (label);
1268         
1269         /* Args are: homogeneous, spacing, expand, fill, padding */
1270         box2 = make_box (TRUE, 0, TRUE, FALSE, 0);
1271         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1272         gtk_widget_show (box2);
1273         
1274         /* Args are: homogeneous, spacing, expand, fill, padding */
1275         box2 = make_box (TRUE, 0, TRUE, TRUE, 0);
1276         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1277         gtk_widget_show (box2);
1278         
1279         /* Another new separator. */
1280         separator = gtk_hseparator_new ();
1281         /* The last 3 arguments to gtk_box_pack_start are:
1282          * expand, fill, padding. */
1283         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1284         gtk_widget_show (separator);
1285         
1286         break;
1287
1288     case 2:
1289
1290         /* Create a new label, remember box1 is a vbox as created 
1291          * near the beginning of main() */
1292         label = gtk_label_new ("gtk_hbox_new (FALSE, 10);");
1293         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1294         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1295         gtk_widget_show (label);
1296         
1297         /* Args are: homogeneous, spacing, expand, fill, padding */
1298         box2 = make_box (FALSE, 10, TRUE, FALSE, 0);
1299         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1300         gtk_widget_show (box2);
1301         
1302         /* Args are: homogeneous, spacing, expand, fill, padding */
1303         box2 = make_box (FALSE, 10, TRUE, TRUE, 0);
1304         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1305         gtk_widget_show (box2);
1306         
1307         separator = gtk_hseparator_new ();
1308         /* The last 3 arguments to gtk_box_pack_start are:
1309          * expand, fill, padding. */
1310         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1311         gtk_widget_show (separator);
1312         
1313         label = gtk_label_new ("gtk_hbox_new (FALSE, 0);");
1314         gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
1315         gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
1316         gtk_widget_show (label);
1317         
1318         /* Args are: homogeneous, spacing, expand, fill, padding */
1319         box2 = make_box (FALSE, 0, TRUE, FALSE, 10);
1320         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1321         gtk_widget_show (box2);
1322         
1323         /* Args are: homogeneous, spacing, expand, fill, padding */
1324         box2 = make_box (FALSE, 0, TRUE, TRUE, 10);
1325         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1326         gtk_widget_show (box2);
1327         
1328         separator = gtk_hseparator_new ();
1329         /* The last 3 arguments to gtk_box_pack_start are: expand, fill, padding. */
1330         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1331         gtk_widget_show (separator);
1332         break;
1333     
1334     case 3:
1335
1336         /* This demonstrates the ability to use gtk_box_pack_end() to
1337          * right justify widgets. First, we create a new box as before. */
1338         box2 = make_box (FALSE, 0, FALSE, FALSE, 0);
1339
1340         /* Create the label that will be put at the end. */
1341         label = gtk_label_new ("end");
1342         /* Pack it using gtk_box_pack_end(), so it is put on the right
1343          * side of the hbox created in the make_box() call. */
1344         gtk_box_pack_end (GTK_BOX (box2), label, FALSE, FALSE, 0);
1345         /* Show the label. */
1346         gtk_widget_show (label);
1347         
1348         /* Pack box2 into box1 (the vbox remember ? :) */
1349         gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, FALSE, 0);
1350         gtk_widget_show (box2);
1351         
1352         /* A separator for the bottom. */
1353         separator = gtk_hseparator_new ();
1354         /* This explicitly sets the separator to 400 pixels wide by 5 pixels
1355          * high. This is so the hbox we created will also be 400 pixels wide,
1356          * and the "end" label will be separated from the other labels in the
1357          * hbox. Otherwise, all the widgets in the hbox would be packed as
1358          * close together as possible. */
1359         gtk_widget_set_usize (separator, 400, 5);
1360         /* pack the separator into the vbox (box1) created near the start 
1361          * of main() */
1362         gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
1363         gtk_widget_show (separator);    
1364     }
1365     
1366     /* Create another new hbox.. remember we can use as many as we need! */
1367     quitbox = gtk_hbox_new (FALSE, 0);
1368     
1369     /* Our quit button. */
1370     button = gtk_button_new_with_label ("Quit");
1371     
1372     /* Setup the signal to terminate the program when the button is clicked */
1373     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
1374                                GTK_SIGNAL_FUNC (gtk_main_quit),
1375                                GTK_OBJECT (window));
1376     /* Pack the button into the quitbox.
1377      * The last 3 arguments to gtk_box_pack_start are:
1378      * expand, fill, padding. */
1379     gtk_box_pack_start (GTK_BOX (quitbox), button, TRUE, FALSE, 0);
1380     /* pack the quitbox into the vbox (box1) */
1381     gtk_box_pack_start (GTK_BOX (box1), quitbox, FALSE, FALSE, 0);
1382     
1383     /* Pack the vbox (box1) which now contains all our widgets, into the
1384      * main window. */
1385     gtk_container_add (GTK_CONTAINER (window), box1);
1386     
1387     /* And show everything left */
1388     gtk_widget_show (button);
1389     gtk_widget_show (quitbox);
1390     
1391     gtk_widget_show (box1);
1392     /* Showing the window last so everything pops up at once. */
1393     gtk_widget_show (window);
1394     
1395     /* And of course, our main function. */
1396     gtk_main ();
1397
1398     /* Control returns here when gtk_main_quit() is called, but not when 
1399      * gtk_exit is used. */
1400     
1401     return(0);
1402 }
1403 /* example-end */
1404 </verb></tscreen>
1405
1406 <!-- ----------------------------------------------------------------- -->
1407 <sect1>Packing Using Tables
1408 <p>
1409 Let's take a look at another way of packing - Tables. These can be
1410 extremely useful in certain situations.
1411
1412 Using tables, we create a grid that we can place widgets in. The
1413 widgets may take up as many spaces as we specify.
1414
1415 The first thing to look at, of course, is the gtk_table_new function:
1416
1417 <tscreen><verb>
1418 GtkWidget *gtk_table_new( gint rows,
1419                           gint columns,
1420                           gint homogeneous );
1421 </verb></tscreen>
1422
1423 The first argument is the number of rows to make in the table, while
1424 the second, obviously, is the number of columns.
1425
1426 The homogeneous argument has to do with how the table's boxes are
1427 sized. If homogeneous is TRUE, the table boxes are resized to the size
1428 of the largest widget in the table. If homogeneous is FALSE, the size
1429 of a table boxes is dictated by the tallest widget in its same row,
1430 and the widest widget in its column.
1431
1432 The rows and columns are laid out from 0 to n, where n was the number
1433 specified in the call to gtk_table_new. So, if you specify rows = 2
1434 and columns = 2, the layout would look something like this:
1435
1436 <tscreen><verb>
1437  0          1          2
1438 0+----------+----------+
1439  |          |          |
1440 1+----------+----------+
1441  |          |          |
1442 2+----------+----------+
1443 </verb></tscreen>
1444
1445 Note that the coordinate system starts in the upper left hand corner.
1446 To place a widget into a box, use the following function:
1447
1448 <tscreen><verb>
1449 void gtk_table_attach( GtkTable  *table,
1450                        GtkWidget *child,
1451                        gint       left_attach,
1452                        gint       right_attach,
1453                        gint       top_attach,
1454                        gint       bottom_attach,
1455                        gint       xoptions,
1456                        gint       yoptions,
1457                        gint       xpadding,
1458                        gint       ypadding );
1459 </verb></tscreen>                                      
1460
1461 The first argument ("table") is the table you've created and the
1462 second ("child") the widget you wish to place in the table.
1463
1464 The left and right attach arguments specify where to place the widget,
1465 and how many boxes to use. If you want a button in the lower right
1466 table entry of our 2x2 table, and want it to fill that entry ONLY,
1467 left_attach would be = 1, right_attach = 2, top_attach = 1,
1468 bottom_attach = 2.
1469
1470 Now, if you wanted a widget to take up the whole top row of our 2x2
1471 table, you'd use left_attach = 0, right_attach = 2, top_attach = 0,
1472 bottom_attach = 1.
1473
1474 The xoptions and yoptions are used to specify packing options and may
1475 be bitwise OR'ed together to allow multiple options.
1476
1477 These options are:
1478 <itemize>
1479 <item><tt/GTK_FILL/ - If the table box is larger than the widget, and
1480 <tt/GTK_FILL/ is specified, the widget will expand to use all the room
1481 available.
1482
1483 <item><tt/GTK_SHRINK/ - If the table widget was allocated less space
1484 then was requested (usually by the user resizing the window), then the
1485 widgets would normally just be pushed off the bottom of the window and
1486 disappear. If <tt/GTK_SHRINK/ is specified, the widgets will shrink
1487 with the table.
1488
1489 <item><tt/GTK_EXPAND/ - This will cause the table to expand to use up
1490 any remaining space in the window.
1491 </itemize>
1492
1493 Padding is just like in boxes, creating a clear area around the widget
1494 specified in pixels.
1495
1496 gtk_table_attach() has a LOT of options.  So, there's a shortcut:
1497
1498 <tscreen><verb>
1499 void gtk_table_attach_defaults( GtkTable  *table,
1500                                 GtkWidget *widget,
1501                                 gint       left_attach,
1502                                 gint       right_attach,
1503                                 gint       top_attach,
1504                                 gint       bottom_attach );
1505 </verb></tscreen>
1506
1507 The X and Y options default to <tt/GTK_FILL | GTK_EXPAND/, and X and Y
1508 padding are set to 0. The rest of the arguments are identical to the
1509 previous function.
1510
1511 We also have gtk_table_set_row_spacing() and
1512 gtk_table_set_col_spacing(). These places spacing between the rows at
1513 the specified row or column.
1514
1515 <tscreen><verb>
1516 void gtk_table_set_row_spacing( GtkTable *table,
1517                                 gint      row,
1518                                 gint      spacing );
1519 </verb></tscreen>
1520
1521 and
1522
1523 <tscreen><verb>
1524 void gtk_table_set_col_spacing ( GtkTable *table,
1525                                  gint      column,
1526                                  gint      spacing );
1527 </verb></tscreen>
1528
1529 Note that for columns, the space goes to the right of the column, and
1530 for rows, the space goes below the row.
1531
1532 You can also set a consistent spacing of all rows and/or columns with:
1533
1534 <tscreen><verb>
1535 void gtk_table_set_row_spacings( GtkTable *table,
1536                                  gint      spacing );
1537 </verb></tscreen>
1538
1539 And,
1540
1541 <tscreen><verb>
1542 void gtk_table_set_col_spacings( GtkTable *table,
1543                                  gint      spacing );
1544 </verb></tscreen>
1545
1546 Note that with these calls, the last row and last column do not get
1547 any spacing.
1548
1549 <!-- ----------------------------------------------------------------- -->
1550 <sect1>Table Packing Example
1551 <p>
1552 Here we make a window with three buttons in a 2x2 table.
1553 The first two buttons will be placed in the upper row.
1554 A third, quit button, is placed in the lower row, spanning both columns.
1555 Which means it should look something like this:
1556
1557 <? <CENTER> >
1558 <?
1559 <IMG SRC="gtk_tut_table.gif" VSPACE="15" HSPACE="10" 
1560 ALT="Table Packing Example Image" WIDTH="180" HEIGHT="120">
1561 >
1562 <? </CENTER> >
1563
1564 Here's the source code:
1565
1566 <tscreen><verb>
1567 /* example-start table table.c */
1568
1569 #include <gtk/gtk.h>
1570
1571 /* Our callback.
1572  * The data passed to this function is printed to stdout */
1573 void callback( GtkWidget *widget,
1574                gpointer   data )
1575 {
1576     g_print ("Hello again - %s was pressed\n", (char *) data);
1577 }
1578
1579 /* This callback quits the program */
1580 gint delete_event( GtkWidget *widget,
1581                    GdkEvent  *event,
1582                    gpointer   data )
1583 {
1584     gtk_main_quit ();
1585     return(FALSE);
1586 }
1587
1588 int main( int   argc,
1589           char *argv[] )
1590 {
1591     GtkWidget *window;
1592     GtkWidget *button;
1593     GtkWidget *table;
1594
1595     gtk_init (&amp;argc, &amp;argv);
1596
1597     /* Create a new window */
1598     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1599
1600     /* Set the window title */
1601     gtk_window_set_title (GTK_WINDOW (window), "Table");
1602
1603     /* Set a handler for delete_event that immediately
1604      * exits GTK. */
1605     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1606                         GTK_SIGNAL_FUNC (delete_event), NULL);
1607
1608     /* Sets the border width of the window. */
1609     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
1610
1611     /* Create a 2x2 table */
1612     table = gtk_table_new (2, 2, TRUE);
1613
1614     /* Put the table in the main window */
1615     gtk_container_add (GTK_CONTAINER (window), table);
1616
1617     /* Create first button */
1618     button = gtk_button_new_with_label ("button 1");
1619
1620     /* When the button is clicked, we call the "callback" function
1621      * with a pointer to "button 1" as its argument */
1622     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1623               GTK_SIGNAL_FUNC (callback), (gpointer) "button 1");
1624
1625
1626     /* Insert button 1 into the upper left quadrant of the table */
1627     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 1, 0, 1);
1628
1629     gtk_widget_show (button);
1630
1631     /* Create second button */
1632
1633     button = gtk_button_new_with_label ("button 2");
1634
1635     /* When the button is clicked, we call the "callback" function
1636      * with a pointer to "button 2" as its argument */
1637     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1638               GTK_SIGNAL_FUNC (callback), (gpointer) "button 2");
1639     /* Insert button 2 into the upper right quadrant of the table */
1640     gtk_table_attach_defaults (GTK_TABLE(table), button, 1, 2, 0, 1);
1641
1642     gtk_widget_show (button);
1643
1644     /* Create "Quit" button */
1645     button = gtk_button_new_with_label ("Quit");
1646
1647     /* When the button is clicked, we call the "delete_event" function
1648      * and the program exits */
1649     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1650                         GTK_SIGNAL_FUNC (delete_event), NULL);
1651
1652     /* Insert the quit button into the both 
1653      * lower quadrants of the table */
1654     gtk_table_attach_defaults (GTK_TABLE(table), button, 0, 2, 1, 2);
1655
1656     gtk_widget_show (button);
1657
1658     gtk_widget_show (table);
1659     gtk_widget_show (window);
1660
1661     gtk_main ();
1662
1663     return 0;
1664 }
1665 /* example-end */
1666 </verb></tscreen>
1667
1668 <!-- ***************************************************************** -->
1669 <sect>Widget Overview
1670 <!-- ***************************************************************** -->
1671 <p>
1672 The general steps to creating a widget in GTK are:
1673 <enum>
1674 <item> gtk_*_new - one of various functions to create a new widget.
1675 These are all detailed in this section.
1676
1677 <item> Connect all signals and events we wish to use to the
1678 appropriate handlers.
1679
1680 <item> Set the attributes of the widget.
1681
1682 <item> Pack the widget into a container using the appropriate call
1683 such as gtk_container_add() or gtk_box_pack_start().
1684
1685 <item> gtk_widget_show() the widget.
1686 </enum>
1687
1688 gtk_widget_show() lets GTK know that we are done setting the
1689 attributes of the widget, and it is ready to be displayed. You may
1690 also use gtk_widget_hide to make it disappear again. The order in
1691 which you show the widgets is not important, but I suggest showing the
1692 window last so the whole window pops up at once rather than seeing the
1693 individual widgets come up on the screen as they're formed. The
1694 children of a widget (a window is a widget too) will not be displayed
1695 until the window itself is shown using the gtk_widget_show() function.
1696
1697 <!-- ----------------------------------------------------------------- -->
1698 <sect1> Casting
1699 <p>
1700 You'll notice as you go on that GTK uses a type casting system. This
1701 is always done using macros that both test the ability to cast the
1702 given item, and perform the cast. Some common ones you will see are:
1703
1704 <tscreen><verb>
1705   GTK_WIDGET(widget)
1706   GTK_OBJECT(object)
1707   GTK_SIGNAL_FUNC(function)
1708   GTK_CONTAINER(container)
1709   GTK_WINDOW(window)
1710   GTK_BOX(box)
1711 </verb></tscreen>
1712
1713 These are all used to cast arguments in functions. You'll see them in the
1714 examples, and can usually tell when to use them simply by looking at the
1715 function's declaration.
1716
1717 As you can see below in the class hierarchy, all GtkWidgets are
1718 derived from the Object base class. This means you can use a widget
1719 in any place the function asks for an object - simply use the
1720 <tt/GTK_OBJECT()/ macro.
1721
1722 For example:
1723
1724 <tscreen><verb>
1725 gtk_signal_connect( GTK_OBJECT(button), "clicked",
1726                     GTK_SIGNAL_FUNC(callback_function), callback_data);
1727 </verb></tscreen> 
1728
1729 This casts the button into an object, and provides a cast for the
1730 function pointer to the callback.
1731
1732 Many widgets are also containers. If you look in the class hierarchy
1733 below, you'll notice that many widgets derive from the Container
1734 class. Any one of these widgets may be used with the
1735 <tt/GTK_CONTAINER/ macro to pass them to functions that ask for
1736 containers.
1737
1738 Unfortunately, these macros are not extensively covered in the
1739 tutorial, but I recommend taking a look through the GTK header
1740 files. It can be very educational. In fact, it's not difficult to
1741 learn how a widget works just by looking at the function declarations.
1742
1743 <!-- ----------------------------------------------------------------- -->
1744 <sect1>Widget Hierarchy
1745 <p>
1746 For your reference, here is the class hierarchy tree used to implement widgets.
1747
1748 <tscreen><verb>
1749  GtkObject
1750   +GtkWidget
1751   | +GtkMisc
1752   | | +GtkLabel
1753   | | | +GtkAccelLabel
1754   | | | `GtkTipsQuery
1755   | | +GtkArrow
1756   | | +GtkImage
1757   | | `GtkPixmap
1758   | +GtkContainer
1759   | | +GtkBin
1760   | | | +GtkAlignment
1761   | | | +GtkFrame
1762   | | | | `GtkAspectFrame
1763   | | | +GtkButton
1764   | | | | +GtkToggleButton
1765   | | | | | `GtkCheckButton
1766   | | | | |   `GtkRadioButton
1767   | | | | `GtkOptionMenu
1768   | | | +GtkItem
1769   | | | | +GtkMenuItem
1770   | | | | | +GtkCheckMenuItem
1771   | | | | | | `GtkRadioMenuItem
1772   | | | | | `GtkTearoffMenuItem
1773   | | | | +GtkListItem
1774   | | | | `GtkTreeItem
1775   | | | +GtkWindow
1776   | | | | +GtkColorSelectionDialog
1777   | | | | +GtkDialog
1778   | | | | | `GtkInputDialog
1779   | | | | +GtkDrawWindow
1780   | | | | +GtkFileSelection
1781   | | | | +GtkFontSelectionDialog
1782   | | | | `GtkPlug
1783   | | | +GtkEventBox
1784   | | | +GtkHandleBox
1785   | | | +GtkScrolledWindow
1786   | | | `GtkViewport
1787   | | +GtkBox
1788   | | | +GtkButtonBox
1789   | | | | +GtkHButtonBox
1790   | | | | `GtkVButtonBox
1791   | | | +GtkVBox
1792   | | | | +GtkColorSelection
1793   | | | | `GtkGammaCurve
1794   | | | `GtkHBox
1795   | | |   +GtkCombo
1796   | | |   `GtkStatusbar
1797   | | +GtkCList
1798   | | | `GtkCTree
1799   | | +GtkFixed
1800   | | +GtkNotebook
1801   | | | `GtkFontSelection
1802   | | +GtkPaned
1803   | | | +GtkHPaned
1804   | | | `GtkVPaned
1805   | | +GtkLayout
1806   | | +GtkList
1807   | | +GtkMenuShell
1808   | | | +GtkMenuBar
1809   | | | `GtkMenu
1810   | | +GtkPacker
1811   | | +GtkSocket
1812   | | +GtkTable
1813   | | +GtkToolbar
1814   | | `GtkTree
1815   | +GtkCalendar
1816   | +GtkDrawingArea
1817   | | `GtkCurve
1818   | +GtkEditable
1819   | | +GtkEntry
1820   | | | `GtkSpinButton
1821   | | `GtkText
1822   | +GtkRuler
1823   | | +GtkHRuler
1824   | | `GtkVRuler
1825   | +GtkRange
1826   | | +GtkScale
1827   | | | +GtkHScale
1828   | | | `GtkVScale
1829   | | `GtkScrollbar
1830   | |   +GtkHScrollbar
1831   | |   `GtkVScrollbar
1832   | +GtkSeparator
1833   | | +GtkHSeparator
1834   | | `GtkVSeparator
1835   | +GtkPreview
1836   | `GtkProgress
1837   |   `GtkProgressBar
1838   +GtkData
1839   | +GtkAdjustment
1840   | `GtkTooltips
1841   `GtkItemFactory
1842 </verb></tscreen>
1843
1844 <!-- ----------------------------------------------------------------- -->
1845 <sect1>Widgets Without Windows
1846 <p>
1847 The following widgets do not have an associated window. If you want to
1848 capture events, you'll have to use the EventBox. See the section on
1849 the <ref id="sec_EventBox" name="EventBox"> widget.
1850
1851 <tscreen><verb>
1852 GtkAlignment
1853 GtkArrow
1854 GtkBin
1855 GtkBox
1856 GtkImage
1857 GtkItem
1858 GtkLabel
1859 GtkPixmap
1860 GtkScrolledWindow
1861 GtkSeparator
1862 GtkTable
1863 GtkAspectFrame
1864 GtkFrame
1865 GtkVBox
1866 GtkHBox
1867 GtkVSeparator
1868 GtkHSeparator
1869 </verb></tscreen>
1870
1871 We'll further our exploration of GTK by examining each widget in turn,
1872 creating a few simple functions to display them. Another good source
1873 is the testgtk.c program that comes with GTK. It can be found in
1874 gtk/testgtk.c.
1875
1876 <!-- ***************************************************************** -->
1877 <sect>The Button Widget
1878 <!-- ***************************************************************** -->
1879
1880 <!-- ----------------------------------------------------------------- -->
1881 <sect1>Normal Buttons
1882 <p>
1883 We've almost seen all there is to see of the button widget. It's
1884 pretty simple. There are however two ways to create a button. You can
1885 use the gtk_button_new_with_label() to create a button with a label,
1886 or use gtk_button_new() to create a blank button. It's then up to you
1887 to pack a label or pixmap into this new button. To do this, create a
1888 new box, and then pack your objects into this box using the usual
1889 gtk_box_pack_start, and then use gtk_container_add to pack the box
1890 into the button.
1891
1892 Here's an example of using gtk_button_new to create a button with a
1893 picture and a label in it. I've broken up the code to create a box
1894 from the rest so you can use it in your programs. There are further
1895 examples of using pixmaps later in the tutorial.
1896
1897 <tscreen><verb>
1898 /* example-start buttons buttons.c */
1899
1900 #include <gtk/gtk.h>
1901
1902 /* Create a new hbox with an image and a label packed into it
1903  * and return the box. */
1904
1905 GtkWidget *xpm_label_box( GtkWidget *parent,
1906                           gchar     *xpm_filename,
1907                           gchar     *label_text )
1908 {
1909     GtkWidget *box1;
1910     GtkWidget *label;
1911     GtkWidget *pixmapwid;
1912     GdkPixmap *pixmap;
1913     GdkBitmap *mask;
1914     GtkStyle *style;
1915
1916     /* Create box for xpm and label */
1917     box1 = gtk_hbox_new (FALSE, 0);
1918     gtk_container_set_border_width (GTK_CONTAINER (box1), 2);
1919
1920     /* Get the style of the button to get the
1921      * background color. */
1922     style = gtk_widget_get_style(parent);
1923
1924     /* Now on to the xpm stuff */
1925     pixmap = gdk_pixmap_create_from_xpm (parent->window, &amp;mask,
1926                                          &amp;style->bg[GTK_STATE_NORMAL],
1927                                          xpm_filename);
1928     pixmapwid = gtk_pixmap_new (pixmap, mask);
1929
1930     /* Create a label for the button */
1931     label = gtk_label_new (label_text);
1932
1933     /* Pack the pixmap and label into the box */
1934     gtk_box_pack_start (GTK_BOX (box1),
1935                         pixmapwid, FALSE, FALSE, 3);
1936
1937     gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 3);
1938
1939     gtk_widget_show(pixmapwid);
1940     gtk_widget_show(label);
1941
1942     return(box1);
1943 }
1944
1945 /* Our usual callback function */
1946 void callback( GtkWidget *widget,
1947                gpointer   data )
1948 {
1949     g_print ("Hello again - %s was pressed\n", (char *) data);
1950 }
1951
1952
1953 int main( int   argc,
1954           char *argv[] )
1955 {
1956     /* GtkWidget is the storage type for widgets */
1957     GtkWidget *window;
1958     GtkWidget *button;
1959     GtkWidget *box1;
1960
1961     gtk_init (&amp;argc, &amp;argv);
1962
1963     /* Create a new window */
1964     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1965
1966     gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
1967
1968     /* It's a good idea to do this for all windows. */
1969     gtk_signal_connect (GTK_OBJECT (window), "destroy",
1970                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1971
1972     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
1973                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
1974
1975     /* Sets the border width of the window. */
1976     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1977     gtk_widget_realize(window);
1978
1979     /* Create a new button */
1980     button = gtk_button_new ();
1981
1982     /* Connect the "clicked" signal of the button to our callback */
1983     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1984                         GTK_SIGNAL_FUNC (callback), (gpointer) "cool button");
1985
1986     /* This calls our box creating function */
1987     box1 = xpm_label_box(window, "info.xpm", "cool button");
1988
1989     /* Pack and show all our widgets */
1990     gtk_widget_show(box1);
1991
1992     gtk_container_add (GTK_CONTAINER (button), box1);
1993
1994     gtk_widget_show(button);
1995
1996     gtk_container_add (GTK_CONTAINER (window), button);
1997
1998     gtk_widget_show (window);
1999
2000     /* Rest in gtk_main and wait for the fun to begin! */
2001     gtk_main ();
2002
2003     return(0);
2004 }
2005 /* example-end */
2006 </verb></tscreen>
2007
2008 The xpm_label_box function could be used to pack xpm's and labels into
2009 any widget that can be a container.
2010
2011 Notice in <tt/xpm_label_box/ how there is a call to
2012 <tt/gtk_widget_get_style/. Every widget has a "style", consisting of
2013 foreground and background colors for a variety of situations, font
2014 selection, and other graphics data relevant to a widget. These style
2015 values are defaulted in each widget, and are required by many GDK
2016 function calls, such as <tt/gdk_pixmap_create_from_xpm/, which here is
2017 given the "normal" background color. The style data of widgets may
2018 be customized, using <ref id="sec_gtkrc_files" name="GTK's rc files">.
2019
2020 Also notice the call to <tt/gtk_widget_realize/ after setting the
2021 window's border width. This function uses GDK to create the X
2022 windows related to the widget. The function is automatically called
2023 when you invoke <tt/gtk_widget_show/ for a widget, and so has not been
2024 shown in earlier examples. But the call to
2025 <tt/gdk_pixmap_create_from_xpm/ requires that its <tt/window/ argument
2026 refer to a real X window, so it is necessary to realize the widget
2027 before this GDK call.
2028
2029 The Button widget has the following signals:
2030
2031 <itemize>
2032 <item><tt/pressed/ - emitted when pointer button is pressed within
2033 Button widget
2034 <item><tt/released/ - emitted when pointer button is released within
2035 Button widget
2036 <item><tt/clicked/ - emitted when pointer button is pressed and then
2037 released within Button widget
2038 <item><tt/enter/ - emitted when pointer enters Button widget
2039 <item><tt/leave/ - emitted when pointer leaves Button widget
2040 </itemize>
2041
2042 <!-- ----------------------------------------------------------------- -->
2043 <sect1> Toggle Buttons
2044 <p>
2045 Toggle buttons are derived from normal buttons and are very similar,
2046 except they will always be in one of two states, alternated by a
2047 click. They may be depressed, and when you click again, they will pop
2048 back up. Click again, and they will pop back down.
2049
2050 Toggle buttons are the basis for check buttons and radio buttons, as
2051 such, many of the calls used for toggle buttons are inherited by radio
2052 and check buttons. I will point these out when we come to them.
2053
2054 Creating a new toggle button:
2055
2056 <tscreen><verb>
2057 GtkWidget *gtk_toggle_button_new( void );
2058
2059 GtkWidget *gtk_toggle_button_new_with_label( gchar *label );
2060 </verb></tscreen>
2061
2062 As you can imagine, these work identically to the normal button widget
2063 calls. The first creates a blank toggle button, and the second, a
2064 button with a label widget already packed into it.
2065
2066 To retrieve the state of the toggle widget, including radio and check
2067 buttons, we use a construct as shown in our example below. This tests
2068 the state of the toggle, by accessing the <tt/active/ field of the
2069 toggle widget's structure, after first using the
2070 <tt/GTK_TOGGLE_BUTTON/ macro to cast the widget pointer into a toggle
2071 widget pointer. The signal of interest to us emitted by toggle
2072 buttons (the toggle button, check button, and radio button widgets) is
2073 the "toggled" signal. To check the state of these buttons, set up a
2074 signal handler to catch the toggled signal, and access the structure
2075 to determine its state. The callback will look something like:
2076
2077 <tscreen><verb>
2078 void toggle_button_callback (GtkWidget *widget, gpointer data)
2079 {
2080     if (GTK_TOGGLE_BUTTON (widget)->active) 
2081     {
2082         /* If control reaches here, the toggle button is down */
2083     
2084     } else {
2085     
2086         /* If control reaches here, the toggle button is up */
2087     }
2088 }
2089 </verb></tscreen>
2090
2091 To force the state of a toggle button, and its children, the radio and
2092 check buttons, use this function:
2093
2094 <tscreen><verb>
2095 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2096                                   gint             state );
2097 </verb></tscreen>
2098
2099 The above call can be used to set the state of the toggle button, and
2100 its children the radio and check buttons. Passing in your created
2101 button as the first argument, and a TRUE or FALSE for the second state
2102 argument to specify whether it should be down (depressed) or up
2103 (released). Default is up, or FALSE.
2104
2105 Note that when you use the gtk_toggle_button_set_active() function, and
2106 the state is actually changed, it causes the "clicked" signal to be
2107 emitted from the button.
2108
2109 <tscreen><verb>
2110 void gtk_toggle_button_toggled (GtkToggleButton *toggle_button);
2111 </verb></tscreen>
2112
2113 This simply toggles the button, and emits the "toggled" signal.
2114
2115 <!-- ----------------------------------------------------------------- -->
2116 <sect1> Check Buttons
2117 <p>
2118 Check buttons inherit many properties and functions from the the
2119 toggle buttons above, but look a little different. Rather than being
2120 buttons with text inside them, they are small squares with the text to
2121 the right of them. These are often used for toggling options on and
2122 off in applications.
2123
2124 The two creation functions are similar to those of the normal button.
2125
2126 <tscreen><verb>
2127 GtkWidget *gtk_check_button_new( void );
2128
2129 GtkWidget *gtk_check_button_new_with_label ( gchar *label );
2130 </verb></tscreen>
2131
2132 The new_with_label function creates a check button with a label beside
2133 it.
2134
2135 Checking the state of the check button is identical to that of the
2136 toggle button.
2137
2138 <!-- ----------------------------------------------------------------- -->
2139 <sect1> Radio Buttons <label id="sec_Radio_Buttons">
2140 <p>
2141 Radio buttons are similar to check buttons except they are grouped so
2142 that only one may be selected/depressed at a time. This is good for
2143 places in your application where you need to select from a short list
2144 of options.
2145
2146 Creating a new radio button is done with one of these calls:
2147
2148 <tscreen><verb>
2149 GtkWidget *gtk_radio_button_new( GSList *group );
2150
2151 GtkWidget *gtk_radio_button_new_with_label( GSList *group,
2152                                             gchar  *label );
2153 </verb></tscreen>
2154
2155 You'll notice the extra argument to these calls. They require a group
2156 to perform their duty properly. The first call to
2157 gtk_radio_button_new_with_label or gtk_radio_button_new_with_label
2158 should pass NULL as the first argument. Then create a group using:
2159
2160 <tscreen><verb>
2161 GSList *gtk_radio_button_group( GtkRadioButton *radio_button );
2162 </verb></tscreen>
2163
2164 The important thing to remember is that gtk_radio_button_group must be
2165 called for each new button added to the group, with the previous
2166 button passed in as an argument. The result is then passed into the
2167 next call to gtk_radio_button_new or
2168 gtk_radio_button_new_with_label. This allows a chain of buttons to be
2169 established. The example below should make this clear.
2170
2171 You can shorten this slightly by using the following syntax, which
2172 removes the need for a variable to hold the list of buttons. This form
2173 is used in the example to create the third button:
2174
2175 <tscreen><verb>
2176      button2 = gtk_radio_button_new_with_label(
2177                  gtk_radio_button_group (GTK_RADIO_BUTTON (button1)),
2178                  "button2");
2179 </verb></tscreen>
2180
2181 It is also a good idea to explicitly set which button should be the
2182 default depressed button with:
2183
2184 <tscreen><verb>
2185 void gtk_toggle_button_set_active( GtkToggleButton *toggle_button,
2186                                   gint             state );
2187 </verb></tscreen>
2188
2189 This is described in the section on toggle buttons, and works in
2190 exactly the same way.  Once the radio buttons are grouped together,
2191 only one of the group may be active at a time. If the user clicks on
2192 one radio button, and then on another, the first radio button will
2193 first emit a "toggled" signal (to report becoming inactive), and then
2194 the second will emit its "toggled" signal (to report becoming active).
2195
2196 The following example creates a radio button group with three buttons.
2197
2198 <tscreen><verb>
2199 /* example-start radiobuttons radiobuttons.c */
2200
2201 #include <gtk/gtk.h>
2202 #include <glib.h>
2203
2204 gint close_application( GtkWidget *widget,
2205                         GdkEvent  *event,
2206                         gpointer   data )
2207 {
2208   gtk_main_quit();
2209   return(FALSE);
2210 }
2211
2212 int main( int   argc,
2213           char *argv[] )
2214 {
2215     GtkWidget *window = NULL;
2216     GtkWidget *box1;
2217     GtkWidget *box2;
2218     GtkWidget *button;
2219     GtkWidget *separator;
2220     GSList *group;
2221   
2222     gtk_init(&amp;argc,&amp;argv);    
2223       
2224     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2225   
2226     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
2227                         GTK_SIGNAL_FUNC(close_application),
2228                         NULL);
2229
2230     gtk_window_set_title (GTK_WINDOW (window), "radio buttons");
2231     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2232
2233     box1 = gtk_vbox_new (FALSE, 0);
2234     gtk_container_add (GTK_CONTAINER (window), box1);
2235     gtk_widget_show (box1);
2236
2237     box2 = gtk_vbox_new (FALSE, 10);
2238     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2239     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2240     gtk_widget_show (box2);
2241
2242     button = gtk_radio_button_new_with_label (NULL, "button1");
2243     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2244     gtk_widget_show (button);
2245
2246     group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
2247     button = gtk_radio_button_new_with_label(group, "button2");
2248     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2249     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2250     gtk_widget_show (button);
2251
2252     button = gtk_radio_button_new_with_label(
2253                  gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
2254                  "button3");
2255     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2256     gtk_widget_show (button);
2257
2258     separator = gtk_hseparator_new ();
2259     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2260     gtk_widget_show (separator);
2261
2262     box2 = gtk_vbox_new (FALSE, 10);
2263     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2264     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2265     gtk_widget_show (box2);
2266
2267     button = gtk_button_new_with_label ("close");
2268     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
2269                                GTK_SIGNAL_FUNC(close_application),
2270                                GTK_OBJECT (window));
2271     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2272     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
2273     gtk_widget_grab_default (button);
2274     gtk_widget_show (button);
2275     gtk_widget_show (window);
2276      
2277     gtk_main();
2278
2279     return(0);
2280 }
2281 /* example-end */
2282 </verb></tscreen>
2283
2284 <!-- TODO: check out gtk_radio_button_new_from_widget function - TRG -->
2285
2286 <!-- ***************************************************************** -->
2287 <sect> Adjustments <label id="sec_Adjustment">
2288 <!-- ***************************************************************** -->
2289 <p>
2290 GTK has various widgets that can be visually adjusted by the user
2291 using the mouse or the keyboard, such as the range widgets, described
2292 in the <ref id="sec_Range_Widgets" name="Range Widgets">
2293 section. There are also a few widgets that display some adjustable
2294 portion of a larger area of data, such as the text widget and the
2295 viewport widget.
2296
2297 Obviously, an application needs to be able to react to changes the
2298 user makes in range widgets. One way to do this would be to have each
2299 widget emit its own type of signal when its adjustment changes, and
2300 either pass the new value to the signal handler, or require it to look
2301 inside the widget's data structure in order to ascertain the value.
2302 But you may also want to connect the adjustments of several widgets
2303 together, so that adjusting one adjusts the others. The most obvious
2304 example of this is connecting a scrollbar to a panning viewport or a
2305 scrolling text area. If each widget has its own way of setting or
2306 getting the adjustment value, then the programmer may have to write
2307 their own signal handlers to translate between the output of one
2308 widget's signal and the "input" of another's adjustment setting
2309 function.
2310
2311 GTK solves this problem using the Adjustment object, which is not a
2312 widget but a way for widgets to store and pass adjustment information
2313 in an abstract and flexible form. The most obvious use of Adjustment
2314 is to store the configuration parameters and values of range widgets,
2315 such as scrollbars and scale controls. However, since Adjustments are
2316 derived from Object, they have some special powers beyond those of
2317 normal data structures. Most importantly, they can emit signals, just
2318 like widgets, and these signals can be used not only to allow your
2319 program to react to user input on adjustable widgets, but also to
2320 propagate adjustment values transparently between adjustable widgets.
2321
2322 You will see how adjustments fit in when you see the other widgets
2323 that incorporate them:
2324 <ref id="sec_ProgressBar" name="Progress Bars">,
2325 <ref id="sec_Viewports" name="Viewports">,
2326 <ref id="sec_ScrolledWindow" name="Scrolled Windows">, and others.
2327
2328 <sect1> Creating an Adjustment
2329 <p>
2330 Many of the widgets which use adjustment objects do so automatically,
2331 but some cases will be shown in later examples where you may need to
2332 create one yourself. You create an adjustment using:
2333
2334 <tscreen><verb>
2335 GtkObject *gtk_adjustment_new( gfloat value,
2336                                gfloat lower,
2337                                gfloat upper,
2338                                gfloat step_increment,
2339                                gfloat page_increment,
2340                                gfloat page_size );
2341 </verb></tscreen>
2342
2343 The <tt/value/ argument is the initial value you want to give to the
2344 adjustment, usually corresponding to the topmost or leftmost position
2345 of an adjustable widget. The <tt/lower/ argument specifies the lowest
2346 value which the adjustment can hold. The <tt/step_increment/ argument
2347 specifies the "smaller" of the two increments by which the user can
2348 change the value, while the <tt/page_increment/ is the "larger" one.
2349 The <tt/page_size/ argument usually corresponds somehow to the visible
2350 area of a panning widget. The <tt/upper/ argument is used to represent
2351 the bottom most or right most coordinate in a panning widget's
2352 child. Therefore it is <em/not/ always the largest number that
2353 <tt/value/ can take, since the <tt/page_size/ of such widgets is
2354 usually non-zero.
2355
2356 <!-- ----------------------------------------------------------------- -->
2357 <sect1> Using Adjustments the Easy Way
2358 <p>
2359 The adjustable widgets can be roughly divided into those which use and
2360 require specific units for these values and those which treat them as
2361 arbitrary numbers. The group which treats the values as arbitrary
2362 numbers includes the range widgets (scrollbars and scales, the
2363 progress bar widget, and the spin button widget). These widgets are
2364 all the widgets which are typically "adjusted" directly by the user
2365 with the mouse or keyboard. They will treat the <tt/lower/ and
2366 <tt/upper/ values of an adjustment as a range within which the user
2367 can manipulate the adjustment's <tt/value/. By default, they will only
2368 modify the <tt/value/ of an adjustment.
2369
2370 The other group includes the text widget, the viewport widget, the
2371 compound list widget, and the scrolled window widget. All of these
2372 widgets use pixel values for their adjustments. These are also all
2373 widgets which are typically "adjusted" indirectly using scrollbars.
2374 While all widgets which use adjustments can either create their own
2375 adjustments or use ones you supply, you'll generally want to let this
2376 particular category of widgets create its own adjustments. Usually,
2377 they will eventually override all the values except the <tt/value/
2378 itself in whatever adjustments you give them, but the results are, in
2379 general, undefined (meaning, you'll have to read the source code to
2380 find out, and it may be different from widget to widget).
2381
2382 Now, you're probably thinking, since text widgets and viewports insist
2383 on setting everything except the <tt/value/ of their adjustments,
2384 while scrollbars will <em/only/ touch the adjustment's <tt/value/, if
2385 you <em/share/ an adjustment object between a scrollbar and a text
2386 widget, manipulating the scrollbar will automagically adjust the text
2387 widget?  Of course it will! Just like this:
2388
2389 <tscreen><verb>
2390   /* creates its own adjustments */
2391   text = gtk_text_new (NULL, NULL);
2392   /* uses the newly-created adjustment for the scrollbar as well */
2393   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
2394 </verb></tscreen>
2395
2396 </sect1>
2397 <!-- ----------------------------------------------------------------- -->
2398 <sect1> Adjustment Internals
2399 <p>
2400 Ok, you say, that's nice, but what if I want to create my own handlers
2401 to respond when the user adjusts a range widget or a spin button, and
2402 how do I get at the value of the adjustment in these handlers?  To
2403 answer these questions and more, let's start by taking a look at
2404 <tt>struct _GtkAdjustment</tt> itself:
2405
2406 <tscreen><verb>
2407 struct _GtkAdjustment
2408 {
2409   GtkData data;
2410   
2411   gfloat lower;
2412   gfloat upper;
2413   gfloat value;
2414   gfloat step_increment;
2415   gfloat page_increment;
2416   gfloat page_size;
2417 };     
2418 </verb></tscreen>
2419
2420 The first thing you should know is that there aren't any handy-dandy
2421 macros or accessor functions for getting the <tt/value/ out of an
2422 Adjustment, so you'll have to (horror of horrors) do it like a
2423 <em/real/ C programmer.  Don't worry - the <tt>GTK_ADJUSTMENT
2424 (Object)</tt> macro does run-time type checking (as do all the GTK
2425 type-casting macros, actually).
2426
2427 Since, when you set the <tt/value/ of an adjustment, you generally
2428 want the change to be reflected by every widget that uses this
2429 adjustment, GTK provides this convenience function to do this:
2430
2431 <tscreen><verb>
2432 void gtk_adjustment_set_value( GtkAdjustment *adjustment,
2433                                gfloat         value );
2434 </verb></tscreen>
2435
2436 As mentioned earlier, Adjustment is a subclass of Object just
2437 like all the various widgets, and thus it is able to emit signals.
2438 This is, of course, why updates happen automagically when you share an
2439 adjustment object between a scrollbar and another adjustable widget;
2440 all adjustable widgets connect signal handlers to their adjustment's
2441 <tt/value_changed/ signal, as can your program. Here's the definition
2442 of this signal in <tt/struct _GtkAdjustmentClass/:
2443
2444 <tscreen><verb>
2445   void (* value_changed) (GtkAdjustment *adjustment);
2446 </verb></tscreen>
2447
2448 The various widgets that use the Adjustment object will emit this
2449 signal on an adjustment whenever they change its value. This happens
2450 both when user input causes the slider to move on a range widget, as
2451 well as when the program explicitly changes the value with
2452 <tt/gtk_adjustment_set_value()/. So, for example, if you have a scale
2453 widget, and you want to change the rotation of a picture whenever its
2454 value changes, you would create a callback like this:
2455
2456 <tscreen><verb>
2457 void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
2458 {
2459   set_picture_rotation (picture, adj->value);
2460 ...
2461 </verb></tscreen>
2462
2463 and connect it to the scale widget's adjustment like this:
2464
2465 <tscreen><verb>
2466 gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
2467                     GTK_SIGNAL_FUNC (cb_rotate_picture), picture);
2468 </verb></tscreen>
2469
2470 What about when a widget reconfigures the <tt/upper/ or <tt/lower/
2471 fields of its adjustment, such as when a user adds more text to a text
2472 widget?  In this case, it emits the <tt/changed/ signal, which looks
2473 like this:
2474
2475 <tscreen><verb>
2476   void (* changed)       (GtkAdjustment *adjustment);
2477 </verb></tscreen>
2478
2479 Range widgets typically connect a handler to this signal, which
2480 changes their appearance to reflect the change - for example, the size
2481 of the slider in a scrollbar will grow or shrink in inverse proportion
2482 to the difference between the <tt/lower/ and <tt/upper/ values of its
2483 adjustment.
2484
2485 You probably won't ever need to attach a handler to this signal,
2486 unless you're writing a new type of range widget.  However, if you
2487 change any of the values in a Adjustment directly, you should emit
2488 this signal on it to reconfigure whatever widgets are using it, like
2489 this:
2490
2491 <tscreen><verb>
2492 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2493 </verb></tscreen>
2494
2495 Now go forth and adjust!
2496 </sect1>
2497 </sect>
2498
2499 <!-- ***************************************************************** -->
2500 <sect> Range Widgets<label id="sec_Range_Widgets">
2501 <!-- ***************************************************************** -->
2502
2503 <p>
2504 The category of range widgets includes the ubiquitous scrollbar widget
2505 and the less common "scale" widget. Though these two types of widgets
2506 are generally used for different purposes, they are quite similar in
2507 function and implementation. All range widgets share a set of common
2508 graphic elements, each of which has its own X window and receives
2509 events. They all contain a "trough" and a "slider" (what is sometimes
2510 called a "thumbwheel" in other GUI environments). Dragging the slider
2511 with the pointer moves it back and forth within the trough, while
2512 clicking in the trough advances the slider towards the location of the
2513 click, either completely, or by a designated amount, depending on
2514 which mouse button is used.
2515
2516 As mentioned in <ref id="sec_Adjustment" name="Adjustments"> above,
2517 all range widgets are associated with an adjustment object, from which
2518 they calculate the length of the slider and its position within the
2519 trough. When the user manipulates the slider, the range widget will
2520 change the value of the adjustment.
2521
2522 <!-- ----------------------------------------------------------------- -->
2523 <sect1> Scrollbar Widgets
2524 <p>
2525 These are your standard, run-of-the-mill scrollbars. These should be
2526 used only for scrolling some other widget, such as a list, a text box,
2527 or a viewport (and it's generally easier to use the scrolled window
2528 widget in most cases).  For other purposes, you should use scale
2529 widgets, as they are friendlier and more featureful.
2530
2531 There are separate types for horizontal and vertical scrollbars.
2532 There really isn't much to say about these. You create them with the
2533 following functions, defined in <tt>&lt;gtk/gtkhscrollbar.h&gt;</tt>
2534 and <tt>&lt;gtk/gtkvscrollbar.h&gt;</tt>:
2535
2536 <tscreen><verb>
2537 GtkWidget *gtk_hscrollbar_new( GtkAdjustment *adjustment );
2538
2539 GtkWidget *gtk_vscrollbar_new( GtkAdjustment *adjustment );
2540 </verb></tscreen>
2541
2542 and that's about it (if you don't believe me, look in the header
2543 files!).  The <tt/adjustment/ argument can either be a pointer to an
2544 existing Adjustment, or NULL, in which case one will be created for
2545 you. Specifying NULL might actually be useful in this case, if you
2546 wish to pass the newly-created adjustment to the constructor function
2547 of some other widget which will configure it for you, such as a text
2548 widget.
2549 </sect1>
2550
2551 <!-- ----------------------------------------------------------------- -->
2552 <sect1> Scale Widgets
2553 <p>
2554 Scale widgets are used to allow the user to visually select and
2555 manipulate a value within a specific range. You might want to use a
2556 scale widget, for example, to adjust the magnification level on a
2557 zoomed preview of a picture, or to control the brightness of a color,
2558 or to specify the number of minutes of inactivity before a screensaver
2559 takes over the screen.
2560
2561 <!-- ----------------------------------------------------------------- -->
2562 <sect2>Creating a Scale Widget
2563 <p>
2564 As with scrollbars, there are separate widget types for horizontal and
2565 vertical scale widgets. (Most programmers seem to favour horizontal
2566 scale widgets.) Since they work essentially the same way, there's no
2567 need to treat them separately here. The following functions, defined
2568 in <tt>&lt;gtk/gtkvscale.h&gt;</tt> and
2569 <tt>&lt;gtk/gtkhscale.h&gt;</tt>, create vertical and horizontal scale
2570 widgets, respectively:
2571
2572 <tscreen>
2573 <verb>
2574 GtkWidget *gtk_vscale_new( GtkAdjustment *adjustment );
2575
2576 GtkWidget *gtk_hscale_new( GtkAdjustment *adjustment );
2577 </verb>
2578 </tscreen>
2579
2580 The <tt/adjustment/ argument can either be an adjustment which has
2581 already been created with <tt/gtk_adjustment_new()/, or <tt/NULL/, in
2582 which case, an anonymous Adjustment is created with all of its
2583 values set to <tt/0.0/ (which isn't very useful in this case). In
2584 order to avoid confusing yourself, you probably want to create your
2585 adjustment with a <tt/page_size/ of <tt/0.0/ so that its <tt/upper/
2586 value actually corresponds to the highest value the user can select.
2587 (If you're <em/already/ thoroughly confused, read the section on <ref
2588 id="sec_Adjustment" name="Adjustments"> again for an explanation of
2589 what exactly adjustments do and how to create and manipulate them.)
2590
2591 <!-- ----------------------------------------------------------------- -->
2592 <sect2> Functions and Signals (well, functions, at least)
2593 <p>
2594 Scale widgets can display their current value as a number beside the
2595 trough. The default behaviour is to show the value, but you can change
2596 this with this function:
2597
2598 <tscreen><verb>
2599 void gtk_scale_set_draw_value( GtkScale *scale,
2600                                gint      draw_value );
2601 </verb></tscreen>
2602
2603 As you might have guessed, <tt/draw_value/ is either <tt/TRUE/ or
2604 <tt/FALSE/, with predictable consequences for either one.
2605
2606 The value displayed by a scale widget is rounded to one decimal point
2607 by default, as is the <tt/value/ field in its GtkAdjustment. You can
2608 change this with:
2609
2610 <tscreen>
2611 <verb>
2612 void gtk_scale_set_digits( GtkScale *scale,
2613                             gint     digits );
2614 </verb>
2615 </tscreen>
2616
2617 where <tt/digits/ is the number of decimal places you want. You can
2618 set <tt/digits/ to anything you like, but no more than 13 decimal
2619 places will actually be drawn on screen.
2620
2621 Finally, the value can be drawn in different positions
2622 relative to the trough:
2623
2624 <tscreen>
2625 <verb>
2626 void gtk_scale_set_value_pos( GtkScale        *scale,
2627                               GtkPositionType  pos );
2628 </verb>
2629 </tscreen>
2630
2631 The argument <tt/pos/ is of type <tt>GtkPositionType</tt>, which is
2632 defined in <tt>&lt;gtk/gtkenums.h&gt;</tt>, and can take one of the
2633 following values:
2634
2635 <tscreen><verb>
2636   GTK_POS_LEFT
2637   GTK_POS_RIGHT
2638   GTK_POS_TOP
2639   GTK_POS_BOTTOM
2640 </verb></tscreen>
2641
2642 If you position the value on the "side" of the trough (e.g., on the
2643 top or bottom of a horizontal scale widget), then it will follow the
2644 slider up and down the trough.
2645
2646 All the preceding functions are defined in
2647 <tt>&lt;gtk/gtkscale.h&gt;</tt>. The header files for all GTK widgets
2648 are automatically included when you include
2649 <tt>&lt;gtk/gtk.h&gt;</tt>. But you should look over the header files
2650 of all widgets that interest you,
2651
2652 </sect2>
2653 </sect1>
2654
2655 <!-- ----------------------------------------------------------------- -->
2656 <sect1> Common Range Functions <label id="sec_Range_Functions">
2657 <p>
2658 The Range widget class is fairly complicated internally, but, like
2659 all the "base class" widgets, most of its complexity is only
2660 interesting if you want to hack on it. Also, almost all of the
2661 functions and signals it defines are only really used in writing
2662 derived widgets. There are, however, a few useful functions that are
2663 defined in <tt>&lt;gtk/gtkrange.h&gt;</tt> and will work on all range
2664 widgets.
2665
2666 <!-- ----------------------------------------------------------------- -->
2667 <sect2> Setting the Update Policy
2668 <p>
2669 The "update policy" of a range widget defines at what points during
2670 user interaction it will change the <tt/value/ field of its
2671 Adjustment and emit the "value_changed" signal on this
2672 Adjustment. The update policies, defined in
2673 <tt>&lt;gtk/gtkenums.h&gt;</tt> as type <tt>enum GtkUpdateType</tt>,
2674 are:
2675
2676 <itemize>
2677 <item>GTK_UPDATE_POLICY_CONTINUOUS - This is the default. The
2678 "value_changed" signal is emitted continuously, i.e., whenever the
2679 slider is moved by even the tiniest amount.
2680 </item>
2681 <item>GTK_UPDATE_POLICY_DISCONTINUOUS - The "value_changed" signal is
2682 only emitted once the slider has stopped moving and the user has
2683 released the mouse button.
2684 </item>
2685 <item>GTK_UPDATE_POLICY_DELAYED - The "value_changed" signal is emitted
2686 when the user releases the mouse button, or if the slider stops moving
2687 for a short period of time.
2688 </item>
2689 </itemize>
2690
2691 The update policy of a range widget can be set by casting it using the
2692 <tt>GTK_RANGE (Widget)</tt> macro and passing it to this function:
2693
2694 <tscreen><verb>
2695 void gtk_range_set_update_policy( GtkRange      *range,
2696                                   GtkUpdateType  policy) ;
2697 </verb></tscreen>
2698
2699 <!-- ----------------------------------------------------------------- -->
2700 <sect2>Getting and Setting Adjustments
2701 <p>
2702 Getting and setting the adjustment for a range widget "on the fly" is
2703 done, predictably, with:
2704
2705 <tscreen><verb>
2706 GtkAdjustment* gtk_range_get_adjustment( GtkRange *range );
2707
2708 void gtk_range_set_adjustment( GtkRange      *range,
2709                                GtkAdjustment *adjustment );
2710 </verb></tscreen>
2711
2712 <tt/gtk_range_get_adjustment()/ returns a pointer to the adjustment to
2713 which <tt/range/ is connected.
2714
2715 <tt/gtk_range_set_adjustment()/ does absolutely nothing if you pass it
2716 the adjustment that <tt/range/ is already using, regardless of whether
2717 you changed any of its fields or not. If you pass it a new
2718 Adjustment, it will unreference the old one if it exists (possibly
2719 destroying it), connect the appropriate signals to the new one, and
2720 call the private function <tt/gtk_range_adjustment_changed()/, which
2721 will (or at least, is supposed to...) recalculate the size and/or
2722 position of the slider and redraw if necessary. As mentioned in the
2723 section on adjustments, if you wish to reuse the same Adjustment,
2724 when you modify its values directly, you should emit the "changed"
2725 signal on it, like this:
2726
2727 <tscreen><verb>
2728 gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");
2729 </verb></tscreen>
2730 </sect2>
2731 </sect1>
2732
2733 <!-- ----------------------------------------------------------------- -->
2734 <sect1> Key and Mouse bindings
2735 <p>
2736 All of the GTK range widgets react to mouse clicks in more or less
2737 the same way. Clicking button-1 in the trough will cause its
2738 adjustment's <tt/page_increment/ to be added or subtracted from its
2739 <tt/value/, and the slider to be moved accordingly. Clicking mouse
2740 button-2 in the trough will jump the slider to the point at which the
2741 button was clicked. Clicking any button on a scrollbar's arrows will
2742 cause its adjustment's value to change <tt/step_increment/ at a time.
2743
2744 It may take a little while to get used to, but by default, scrollbars
2745 as well as scale widgets can take the keyboard focus in GTK. If you
2746 think your users will find this too confusing, you can always disable
2747 this by unsetting the <tt/GTK_CAN_FOCUS/ flag on the scrollbar, like
2748 this:
2749
2750 <tscreen><verb>
2751 GTK_WIDGET_UNSET_FLAGS (scrollbar, GTK_CAN_FOCUS);
2752 </verb></tscreen>
2753
2754 The key bindings (which are, of course, only active when the widget
2755 has focus) are slightly different between horizontal and vertical
2756 range widgets, for obvious reasons. They are also not quite the same
2757 for scale widgets as they are for scrollbars, for somewhat less
2758 obvious reasons (possibly to avoid confusion between the keys for
2759 horizontal and vertical scrollbars in scrolled windows, where both
2760 operate on the same area).
2761
2762 <sect2> Vertical Range Widgets
2763 <p>
2764 All vertical range widgets can be operated with the up and down arrow
2765 keys, as well as with the <tt/Page Up/ and <tt/Page Down/ keys. The
2766 arrows move the slider up and down by <tt/step_increment/, while
2767 <tt/Page Up/ and <tt/Page Down/ move it by <tt/page_increment/.
2768
2769 The user can also move the slider all the way to one end or the other
2770 of the trough using the keyboard. With the VScale widget, this is
2771 done with the <tt/Home/ and <tt/End/ keys, whereas with the
2772 VScrollbar widget, this is done by typing <tt>Control-Page Up</tt>
2773 and <tt>Control-Page Down</tt>.
2774
2775 <!-- ----------------------------------------------------------------- -->
2776 <sect2> Horizontal Range Widgets
2777 <p>
2778 The left and right arrow keys work as you might expect in these
2779 widgets, moving the slider back and forth by <tt/step_increment/. The
2780 <tt/Home/ and <tt/End/ keys move the slider to the ends of the trough.
2781 For the HScale widget, moving the slider by <tt/page_increment/ is
2782 accomplished with <tt>Control-Left</tt> and <tt>Control-Right</tt>,
2783 while for HScrollbar, it's done with <tt>Control-Home</tt> and
2784 <tt>Control-End</tt>.
2785 </sect2>
2786 </sect1>
2787
2788 <!-- ----------------------------------------------------------------- -->
2789 <sect1> Example<label id="sec_Range_Example">
2790 <p>
2791 This example is a somewhat modified version of the "range controls"
2792 test from <tt/testgtk.c/. It basically puts up a window with three
2793 range widgets all connected to the same adjustment, and a couple of
2794 controls for adjusting some of the parameters mentioned above and in
2795 the section on adjustments, so you can see how they affect the way
2796 these widgets work for the user.
2797
2798 <tscreen><verb>
2799 /* example-start rangewidgets rangewidgets.c */
2800
2801 #include <gtk/gtk.h>
2802
2803 GtkWidget *hscale, *vscale;
2804
2805 void cb_pos_menu_select( GtkWidget       *item,
2806                          GtkPositionType  pos )
2807 {
2808     /* Set the value position on both scale widgets */
2809     gtk_scale_set_value_pos (GTK_SCALE (hscale), pos);
2810     gtk_scale_set_value_pos (GTK_SCALE (vscale), pos);
2811 }
2812
2813 void cb_update_menu_select( GtkWidget     *item,
2814                             GtkUpdateType  policy )
2815 {
2816     /* Set the update policy for both scale widgets */
2817     gtk_range_set_update_policy (GTK_RANGE (hscale), policy);
2818     gtk_range_set_update_policy (GTK_RANGE (vscale), policy);
2819 }
2820
2821 void cb_digits_scale( GtkAdjustment *adj )
2822 {
2823     /* Set the number of decimal places to which adj->value is rounded */
2824     gtk_scale_set_digits (GTK_SCALE (hscale), (gint) adj->value);
2825     gtk_scale_set_digits (GTK_SCALE (vscale), (gint) adj->value);
2826 }
2827
2828 void cb_page_size( GtkAdjustment *get,
2829                    GtkAdjustment *set )
2830 {
2831     /* Set the page size and page increment size of the sample
2832      * adjustment to the value specified by the "Page Size" scale */
2833     set->page_size = get->value;
2834     set->page_increment = get->value;
2835     /* Now emit the "changed" signal to reconfigure all the widgets that
2836      * are attached to this adjustment */
2837     gtk_signal_emit_by_name (GTK_OBJECT (set), "changed");
2838 }
2839
2840 void cb_draw_value( GtkToggleButton *button )
2841 {
2842     /* Turn the value display on the scale widgets off or on depending
2843      *  on the state of the checkbutton */
2844     gtk_scale_set_draw_value (GTK_SCALE (hscale), button->active);
2845     gtk_scale_set_draw_value (GTK_SCALE (vscale), button->active);  
2846 }
2847
2848 /* Convenience functions */
2849
2850 GtkWidget *make_menu_item( gchar         *name,
2851                            GtkSignalFunc  callback,
2852                            gpointer       data )
2853 {
2854     GtkWidget *item;
2855   
2856     item = gtk_menu_item_new_with_label (name);
2857     gtk_signal_connect (GTK_OBJECT (item), "activate",
2858                         callback, data);
2859     gtk_widget_show (item);
2860
2861     return(item);
2862 }
2863
2864 void scale_set_default_values( GtkScale *scale )
2865 {
2866     gtk_range_set_update_policy (GTK_RANGE (scale),
2867                                  GTK_UPDATE_CONTINUOUS);
2868     gtk_scale_set_digits (scale, 1);
2869     gtk_scale_set_value_pos (scale, GTK_POS_TOP);
2870     gtk_scale_set_draw_value (scale, TRUE);
2871 }
2872
2873 /* makes the sample window */
2874
2875 void create_range_controls( void )
2876 {
2877     GtkWidget *window;
2878     GtkWidget *box1, *box2, *box3;
2879     GtkWidget *button;
2880     GtkWidget *scrollbar;
2881     GtkWidget *separator;
2882     GtkWidget *opt, *menu, *item;
2883     GtkWidget *label;
2884     GtkWidget *scale;
2885     GtkObject *adj1, *adj2;
2886
2887     /* Standard window-creating stuff */
2888     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2889     gtk_signal_connect (GTK_OBJECT (window), "destroy",
2890                         GTK_SIGNAL_FUNC(gtk_main_quit),
2891                         NULL);
2892     gtk_window_set_title (GTK_WINDOW (window), "range controls");
2893
2894     box1 = gtk_vbox_new (FALSE, 0);
2895     gtk_container_add (GTK_CONTAINER (window), box1);
2896     gtk_widget_show (box1);
2897
2898     box2 = gtk_hbox_new (FALSE, 10);
2899     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2900     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2901     gtk_widget_show (box2);
2902
2903     /* value, lower, upper, step_increment, page_increment, page_size */
2904     /* Note that the page_size value only makes a difference for
2905      * scrollbar widgets, and the highest value you'll get is actually
2906      * (upper - page_size). */
2907     adj1 = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
2908   
2909     vscale = gtk_vscale_new (GTK_ADJUSTMENT (adj1));
2910     scale_set_default_values (GTK_SCALE (vscale));
2911     gtk_box_pack_start (GTK_BOX (box2), vscale, TRUE, TRUE, 0);
2912     gtk_widget_show (vscale);
2913
2914     box3 = gtk_vbox_new (FALSE, 10);
2915     gtk_box_pack_start (GTK_BOX (box2), box3, TRUE, TRUE, 0);
2916     gtk_widget_show (box3);
2917
2918     /* Reuse the same adjustment */
2919     hscale = gtk_hscale_new (GTK_ADJUSTMENT (adj1));
2920     gtk_widget_set_usize (GTK_WIDGET (hscale), 200, 30);
2921     scale_set_default_values (GTK_SCALE (hscale));
2922     gtk_box_pack_start (GTK_BOX (box3), hscale, TRUE, TRUE, 0);
2923     gtk_widget_show (hscale);
2924
2925     /* Reuse the same adjustment again */
2926     scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adj1));
2927     /* Notice how this causes the scales to always be updated
2928      * continuously when the scrollbar is moved */
2929     gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
2930                                  GTK_UPDATE_CONTINUOUS);
2931     gtk_box_pack_start (GTK_BOX (box3), scrollbar, TRUE, TRUE, 0);
2932     gtk_widget_show (scrollbar);
2933
2934     box2 = gtk_hbox_new (FALSE, 10);
2935     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2936     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2937     gtk_widget_show (box2);
2938
2939     /* A checkbutton to control whether the value is displayed or not */
2940     button = gtk_check_button_new_with_label("Display value on scale widgets");
2941     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
2942     gtk_signal_connect (GTK_OBJECT (button), "toggled",
2943                         GTK_SIGNAL_FUNC(cb_draw_value), NULL);
2944     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2945     gtk_widget_show (button);
2946   
2947     box2 = gtk_hbox_new (FALSE, 10);
2948     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2949
2950     /* An option menu to change the position of the value */
2951     label = gtk_label_new ("Scale Value Position:");
2952     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2953     gtk_widget_show (label);
2954   
2955     opt = gtk_option_menu_new();
2956     menu = gtk_menu_new();
2957
2958     item = make_menu_item ("Top",
2959                            GTK_SIGNAL_FUNC(cb_pos_menu_select),
2960                            GINT_TO_POINTER (GTK_POS_TOP));
2961     gtk_menu_append (GTK_MENU (menu), item);
2962   
2963     item = make_menu_item ("Bottom", GTK_SIGNAL_FUNC (cb_pos_menu_select), 
2964                            GINT_TO_POINTER (GTK_POS_BOTTOM));
2965     gtk_menu_append (GTK_MENU (menu), item);
2966   
2967     item = make_menu_item ("Left", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2968                            GINT_TO_POINTER (GTK_POS_LEFT));
2969     gtk_menu_append (GTK_MENU (menu), item);
2970   
2971     item = make_menu_item ("Right", GTK_SIGNAL_FUNC (cb_pos_menu_select),
2972                             GINT_TO_POINTER (GTK_POS_RIGHT));
2973     gtk_menu_append (GTK_MENU (menu), item);
2974   
2975     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
2976     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
2977     gtk_widget_show (opt);
2978
2979     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2980     gtk_widget_show (box2);
2981
2982     box2 = gtk_hbox_new (FALSE, 10);
2983     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2984
2985     /* Yet another option menu, this time for the update policy of the
2986      * scale widgets */
2987     label = gtk_label_new ("Scale Update Policy:");
2988     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
2989     gtk_widget_show (label);
2990   
2991     opt = gtk_option_menu_new();
2992     menu = gtk_menu_new();
2993   
2994     item = make_menu_item ("Continuous",
2995                            GTK_SIGNAL_FUNC (cb_update_menu_select),
2996                            GINT_TO_POINTER (GTK_UPDATE_CONTINUOUS));
2997     gtk_menu_append (GTK_MENU (menu), item);
2998   
2999     item = make_menu_item ("Discontinuous",
3000                             GTK_SIGNAL_FUNC (cb_update_menu_select),
3001                             GINT_TO_POINTER (GTK_UPDATE_DISCONTINUOUS));
3002     gtk_menu_append (GTK_MENU (menu), item);
3003   
3004     item = make_menu_item ("Delayed",
3005                            GTK_SIGNAL_FUNC (cb_update_menu_select),
3006                            GINT_TO_POINTER (GTK_UPDATE_DELAYED));
3007     gtk_menu_append (GTK_MENU (menu), item);
3008   
3009     gtk_option_menu_set_menu (GTK_OPTION_MENU (opt), menu);
3010     gtk_box_pack_start (GTK_BOX (box2), opt, TRUE, TRUE, 0);
3011     gtk_widget_show (opt);
3012   
3013     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3014     gtk_widget_show (box2);
3015
3016     box2 = gtk_hbox_new (FALSE, 10);
3017     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3018   
3019     /* An HScale widget for adjusting the number of digits on the
3020      * sample scales. */
3021     label = gtk_label_new ("Scale Digits:");
3022     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3023     gtk_widget_show (label);
3024
3025     adj2 = gtk_adjustment_new (1.0, 0.0, 5.0, 1.0, 1.0, 0.0);
3026     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
3027                         GTK_SIGNAL_FUNC (cb_digits_scale), NULL);
3028     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
3029     gtk_scale_set_digits (GTK_SCALE (scale), 0);
3030     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
3031     gtk_widget_show (scale);
3032
3033     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3034     gtk_widget_show (box2);
3035   
3036     box2 = gtk_hbox_new (FALSE, 10);
3037     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3038   
3039     /* And, one last HScale widget for adjusting the page size of the
3040      * scrollbar. */
3041     label = gtk_label_new ("Scrollbar Page Size:");
3042     gtk_box_pack_start (GTK_BOX (box2), label, FALSE, FALSE, 0);
3043     gtk_widget_show (label);
3044
3045     adj2 = gtk_adjustment_new (1.0, 1.0, 101.0, 1.0, 1.0, 0.0);
3046     gtk_signal_connect (GTK_OBJECT (adj2), "value_changed",
3047                         GTK_SIGNAL_FUNC (cb_page_size), adj1);
3048     scale = gtk_hscale_new (GTK_ADJUSTMENT (adj2));
3049     gtk_scale_set_digits (GTK_SCALE (scale), 0);
3050     gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
3051     gtk_widget_show (scale);
3052
3053     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3054     gtk_widget_show (box2);
3055
3056     separator = gtk_hseparator_new ();
3057     gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3058     gtk_widget_show (separator);
3059
3060     box2 = gtk_vbox_new (FALSE, 10);
3061     gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3062     gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3063     gtk_widget_show (box2);
3064
3065     button = gtk_button_new_with_label ("Quit");
3066     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3067                                GTK_SIGNAL_FUNC(gtk_main_quit),
3068                                NULL);
3069     gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3070     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3071     gtk_widget_grab_default (button);
3072     gtk_widget_show (button);
3073
3074     gtk_widget_show (window);
3075 }
3076
3077 int main( int   argc,
3078           char *argv[] )
3079 {
3080     gtk_init(&amp;argc, &amp;argv);
3081
3082     create_range_controls();
3083
3084     gtk_main();
3085
3086     return(0);
3087 }
3088
3089 /* example-end */
3090 </verb></tscreen>
3091
3092 You will notice that the program does not call <tt/gtk_signal_connect/
3093 for the "delete_event", but only for the "destroy" signal. This will
3094 still perform the desired function, because an unhandled
3095 "delete_event" will result in a "destroy" signal being given to the
3096 window.
3097
3098 </sect1>
3099 </sect>
3100
3101 <!-- ***************************************************************** -->
3102 <sect> Miscellaneous Widgets
3103 <!-- ***************************************************************** -->
3104
3105 <!-- ----------------------------------------------------------------- -->
3106 <sect1> Labels
3107 <p>
3108 Labels are used a lot in GTK, and are relatively simple. Labels emit
3109 no signals as they do not have an associated X window. If you need to
3110 catch signals, or do clipping, place it inside a <ref id="sec_EventBox"
3111 name="EventBox"> widget or a Button widget.
3112
3113 To create a new label, use:
3114
3115 <tscreen><verb>
3116 GtkWidget *gtk_label_new( char *str );
3117 </verb></tscreen>
3118
3119 The sole argument is the string you wish the label to display.
3120
3121 To change the label's text after creation, use the function:
3122
3123 <tscreen><verb>
3124 void gtk_label_set_text( GtkLabel *label,
3125                          char     *str );
3126 </verb></tscreen>
3127
3128 The first argument is the label you created previously (cast
3129 using the <tt/GTK_LABEL()/ macro), and the second is the new string.
3130
3131 The space needed for the new string will be automatically adjusted if
3132 needed. You can produce multi-line labels by putting line breaks in
3133 the label string.
3134
3135 To retrieve the current string, use:
3136
3137 <tscreen><verb>
3138 void gtk_label_get( GtkLabel  *label,
3139                     char     **str );
3140 </verb></tscreen>
3141
3142 The first argument is the label you've created, and the second,
3143 the return for the string. Do not free the return string, as it is
3144 used internally by GTK.
3145
3146 The label text can be justified using:
3147
3148 <tscreen><verb>
3149 void gtk_label_set_justify( GtkLabel         *label,
3150                             GtkJustification  jtype );
3151 </verb></tscreen>
3152
3153 Values for <tt/jtype/ are:
3154 <tscreen><verb>
3155   GTK_JUSTIFY_LEFT
3156   GTK_JUSTIFY_RIGHT
3157   GTK_JUSTIFY_CENTER (the default)
3158   GTK_JUSTIFY_FILL
3159 </verb></tscreen>
3160
3161 The label widget is also capable of line wrapping the text
3162 automatically. This can be activated using:
3163
3164 <tscreen><verb>
3165 void gtk_label_set_line_wrap (GtkLabel *label,
3166                               gboolean  wrap);
3167 </verb></tscreen>
3168
3169 The <tt/wrap/ argument takes a TRUE or FALSE value.
3170
3171 If you want your label underlined, then you can set a pattern on the
3172 label:
3173
3174 <tscreen><verb>
3175 void       gtk_label_set_pattern   (GtkLabel          *label,
3176                                     const gchar       *pattern);
3177 </verb></tscreen>
3178
3179 The pattern argument indicates how the underlining should look. It
3180 consists of a string of underscore and space characters. An underscore
3181 indicates that the corresponding character in the label should be
3182 underlined. For example, the string <verb/"__     __"/ would underline the
3183 first two characters and eight and ninth characters.
3184
3185 Below is a short example to illustrate these functions. This example
3186 makes use of the Frame widget to better demonstrate the label
3187 styles. You can ignore this for now as the <ref id="sec_Frames"
3188 name="Frame"> widget is explained later on.
3189
3190 <tscreen><verb>
3191 /* example-start label label.c */
3192
3193 #include <gtk/gtk.h>
3194
3195 int main( int   argc,
3196           char *argv[] )
3197 {
3198   static GtkWidget *window = NULL;
3199   GtkWidget *hbox;
3200   GtkWidget *vbox;
3201   GtkWidget *frame;
3202   GtkWidget *label;
3203
3204   /* Initialise GTK */
3205   gtk_init(&amp;argc, &amp;argv);
3206
3207   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3208   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3209                       GTK_SIGNAL_FUNC(gtk_main_quit),
3210                       NULL);
3211
3212   gtk_window_set_title (GTK_WINDOW (window), "Label");
3213   vbox = gtk_vbox_new (FALSE, 5);
3214   hbox = gtk_hbox_new (FALSE, 5);
3215   gtk_container_add (GTK_CONTAINER (window), hbox);
3216   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3217   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3218   
3219   frame = gtk_frame_new ("Normal Label");
3220   label = gtk_label_new ("This is a Normal label");
3221   gtk_container_add (GTK_CONTAINER (frame), label);
3222   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3223   
3224   frame = gtk_frame_new ("Multi-line Label");
3225   label = gtk_label_new ("This is a Multi-line label.\nSecond line\n" \
3226                          "Third line");
3227   gtk_container_add (GTK_CONTAINER (frame), label);
3228   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3229   
3230   frame = gtk_frame_new ("Left Justified Label");
3231   label = gtk_label_new ("This is a Left-Justified\n" \
3232                          "Multi-line label.\nThird      line");
3233   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3234   gtk_container_add (GTK_CONTAINER (frame), label);
3235   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3236   
3237   frame = gtk_frame_new ("Right Justified Label");
3238   label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\n" \
3239                          "Fourth line, (j/k)");
3240   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3241   gtk_container_add (GTK_CONTAINER (frame), label);
3242   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3243
3244   vbox = gtk_vbox_new (FALSE, 5);
3245   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3246   frame = gtk_frame_new ("Line wrapped label");
3247   label = gtk_label_new ("This is an example of a line-wrapped label.  It " \
3248                          "should not be taking up the entire             " /* big space to test spacing */\
3249                          "width allocated to it, but automatically " \
3250                          "wraps the words to fit.  " \
3251                          "The time has come, for all good men, to come to " \
3252                          "the aid of their party.  " \
3253                          "The sixth sheik's six sheep's sick.\n" \
3254                          "     It supports multiple paragraphs correctly, " \
3255                          "and  correctly   adds "\
3256                          "many          extra  spaces. ");
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 ("Filled, wrapped label");
3262   label = gtk_label_new ("This is an example of a line-wrapped, filled label.  " \
3263                          "It should be taking "\
3264                          "up the entire              width allocated to it.  " \
3265                          "Here is a sentence to prove "\
3266                          "my point.  Here is another sentence. "\
3267                          "Here comes the sun, do de do de do.\n"\
3268                          "    This is a new paragraph.\n"\
3269                          "    This is another newer, longer, better " \
3270                          "paragraph.  It is coming to an end, "\
3271                          "unfortunately.");
3272   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3273   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3274   gtk_container_add (GTK_CONTAINER (frame), label);
3275   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3276   
3277   frame = gtk_frame_new ("Underlined label");
3278   label = gtk_label_new ("This label is underlined!\n"
3279                          "This one is underlined in quite a funky fashion");
3280   gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3281   gtk_label_set_pattern (GTK_LABEL (label),
3282                          "_________________________ _ _________ _ ______     __ _______ ___");
3283   gtk_container_add (GTK_CONTAINER (frame), label);
3284   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3285   
3286   gtk_widget_show_all (window);
3287
3288   gtk_main ();
3289   
3290   return(0);
3291 }
3292 /* example-end */
3293 </verb></tscreen>
3294
3295 <!-- ----------------------------------------------------------------- -->
3296 <sect1> Arrows
3297 <p>
3298 The Arrow widget draws an arrowhead, facing in a number of possible
3299 directions and having a number of possible styles. It can be very
3300 useful when placed on a button in many applications. Like the Label
3301 widget, it emits no signals.
3302
3303 There are only two functions for manipulating an Arrow widget:
3304
3305 <tscreen><verb>
3306 GtkWidget *gtk_arrow_new( GtkArrowType   arrow_type,
3307                           GtkShadowType  shadow_type );
3308
3309 void gtk_arrow_set( GtkArrow      *arrow,
3310                     GtkArrowType   arrow_type,
3311                     GtkShadowType  shadow_type );
3312 </verb></tscreen>
3313
3314 The first creates a new arrow widget with the indicated type and
3315 appearance. The second allows these values to be altered
3316 retrospectively. The <tt/arrow_type/ argument may take one of the
3317 following values:
3318
3319 <tscreen><verb>
3320   GTK_ARROW_UP
3321   GTK_ARROW_DOWN
3322   GTK_ARROW_LEFT
3323   GTK_ARROW_RIGHT
3324 </verb></tscreen>
3325
3326 These values obviously indicate the direction in which the arrow will
3327 point. The <tt/shadow_type/ argument may take one of these values:
3328
3329 <tscreen><verb>
3330   GTK_SHADOW_IN
3331   GTK_SHADOW_OUT (the default)
3332   GTK_SHADOW_ETCHED_IN
3333   GTK_SHADOW_ETCHED_OUT
3334 </verb></tscreen>
3335
3336 Here's a brief example to illustrate their use.
3337
3338 <tscreen><verb>
3339 /* example-start arrow arrow.c */
3340
3341 #include <gtk/gtk.h>
3342
3343 /* Create an Arrow widget with the specified parameters
3344  * and pack it into a button */
3345 GtkWidget *create_arrow_button( GtkArrowType  arrow_type,
3346                                 GtkShadowType shadow_type )
3347 {
3348   GtkWidget *button;
3349   GtkWidget *arrow;
3350
3351   button = gtk_button_new();
3352   arrow = gtk_arrow_new (arrow_type, shadow_type);
3353
3354   gtk_container_add (GTK_CONTAINER (button), arrow);
3355   
3356   gtk_widget_show(button);
3357   gtk_widget_show(arrow);
3358
3359   return(button);
3360 }
3361
3362 int main( int   argc,
3363           char *argv[] )
3364 {
3365   /* GtkWidget is the storage type for widgets */
3366   GtkWidget *window;
3367   GtkWidget *button;
3368   GtkWidget *box;
3369
3370   /* Initialize the toolkit */
3371   gtk_init (&amp;argc, &amp;argv);
3372
3373   /* Create a new window */
3374   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3375
3376   gtk_window_set_title (GTK_WINDOW (window), "Arrow Buttons");
3377
3378   /* It's a good idea to do this for all windows. */
3379   gtk_signal_connect (GTK_OBJECT (window), "destroy",
3380                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
3381
3382   /* Sets the border width of the window. */
3383   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
3384
3385   /* Create a box to hold the arrows/buttons */
3386   box = gtk_hbox_new (FALSE, 0);
3387   gtk_container_set_border_width (GTK_CONTAINER (box), 2);
3388   gtk_container_add (GTK_CONTAINER (window), box);
3389
3390   /* Pack and show all our widgets */
3391   gtk_widget_show(box);
3392
3393   button = create_arrow_button(GTK_ARROW_UP, GTK_SHADOW_IN);
3394   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3395
3396   button = create_arrow_button(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
3397   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3398   
3399   button = create_arrow_button(GTK_ARROW_LEFT, GTK_SHADOW_ETCHED_IN);
3400   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3401   
3402   button = create_arrow_button(GTK_ARROW_RIGHT, GTK_SHADOW_ETCHED_OUT);
3403   gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 3);
3404   
3405   gtk_widget_show (window);
3406   
3407   /* Rest in gtk_main and wait for the fun to begin! */
3408   gtk_main ();
3409   
3410   return(0);
3411 }
3412 /* example-end */
3413 </verb></tscreen>
3414
3415 <!-- ----------------------------------------------------------------- -->
3416 <sect1>The Tooltips Object
3417 <p>
3418 These are the little text strings that pop up when you leave your
3419 pointer over a button or other widget for a few seconds. They are easy
3420 to use, so I will just explain them without giving an example. If you
3421 want to see some code, take a look at the testgtk.c program
3422 distributed with GTK.
3423
3424 Widgets that do not receive events (widgets that do not have their
3425 own window) will not work with tooltips.
3426
3427 The first call you will use creates a new tooltip. You only need to do
3428 this once for a set of tooltips as the <tt/GtkTooltips/ object this
3429 function returns can be used to create multiple tooltips.
3430
3431 <tscreen><verb>
3432 GtkTooltips *gtk_tooltips_new( void );
3433 </verb></tscreen>
3434
3435 Once you have created a new tooltip, and the widget you wish to use it
3436 on, simply use this call to set it:
3437
3438 <tscreen><verb>
3439 void gtk_tooltips_set_tip( GtkTooltips *tooltips,
3440                            GtkWidget   *widget,
3441                            const gchar *tip_text,
3442                            const gchar *tip_private );
3443 </verb></tscreen>
3444
3445 The first argument is the tooltip you've already created, followed by
3446 the widget you wish to have this tooltip pop up for, and the text you
3447 wish it to say. The last argument is a text string that can be used as
3448 an identifier when using GtkTipsQuery to implement context sensitive
3449 help. For now, you can set it to NULL.
3450
3451 <!-- TODO: sort out what how to do the context sensitive help -->
3452
3453 Here's a short example:
3454
3455 <tscreen><verb>
3456 GtkTooltips *tooltips;
3457 GtkWidget *button;
3458 .
3459 .
3460 .
3461 tooltips = gtk_tooltips_new ();
3462 button = gtk_button_new_with_label ("button 1");
3463 .
3464 .
3465 .
3466 gtk_tooltips_set_tip (tooltips, button, "This is button 1", NULL);
3467 </verb></tscreen>
3468
3469 There are other calls that can be used with tooltips. I will just list
3470 them with a brief description of what they do.
3471
3472 <tscreen><verb>
3473 void gtk_tooltips_enable( GtkTooltips *tooltips );
3474 </verb></tscreen>
3475
3476 Enable a disabled set of tooltips.
3477
3478 <tscreen><verb>
3479 void gtk_tooltips_disable( GtkTooltips *tooltips );
3480 </verb></tscreen>
3481
3482 Disable an enabled set of tooltips.
3483
3484 <tscreen><verb>
3485 void gtk_tooltips_set_delay( GtkTooltips *tooltips,
3486                              gint         delay );
3487
3488 </verb></tscreen>
3489
3490 Sets how many milliseconds you have to hold your pointer over the
3491 widget before the tooltip will pop up. The default is 500
3492 milliseconds (half a second).
3493
3494 <tscreen><verb>
3495 void gtk_tooltips_set_colors( GtkTooltips *tooltips,
3496                               GdkColor    *background,
3497                               GdkColor    *foreground );
3498 </verb></tscreen>
3499
3500 Set the foreground and background color of the tooltips.
3501
3502 And that's all the functions associated with tooltips. More than
3503 you'll ever want to know :-)
3504
3505 <!-- ----------------------------------------------------------------- -->
3506 <sect1> Progress Bars <label id="sec_ProgressBar">
3507 <p>
3508 Progress bars are used to show the status of an operation. They are
3509 pretty easy to use, as you will see with the code below. But first
3510 lets start out with the calls to create a new progress bar.
3511
3512 There are two ways to create a progress bar, one simple that takes
3513 no arguments, and one that takes an Adjustment object as an
3514 argument. If the former is used, the progress bar creates its own
3515 adjustment object.
3516
3517 <tscreen><verb>
3518 GtkWidget *gtk_progress_bar_new( void );
3519
3520 GtkWidget *gtk_progress_bar_new_with_adjustment( GtkAdjustment *adjustment );
3521 </verb></tscreen>
3522
3523 The second method has the advantage that we can use the adjustment
3524 object to specify our own range parameters for the progress bar.
3525
3526 The adjustment of a progress object can be changed dynamically using:
3527
3528 <tscreen><verb>
3529 void gtk_progress_set_adjustment( GtkProgress   *progress,
3530                                   GtkAdjustment *adjustment );
3531 </verb></tscreen>
3532
3533 Now that the progress bar has been created we can use it.
3534
3535 <tscreen><verb>
3536 void gtk_progress_bar_update( GtkProgressBar *pbar,
3537                               gfloat          percentage );
3538 </verb></tscreen>
3539
3540 The first argument is the progress bar you wish to operate on, and the
3541 second argument is the amount "completed", meaning the amount the
3542 progress bar has been filled from 0-100%. This is passed to the
3543 function as a real number ranging from 0 to 1.
3544
3545 GTK v1.2 has added new functionality to the progress bar that enables
3546 it to display its value in different ways, and to inform the user of
3547 its current value and its range.
3548
3549 A progress bar may be set to one of a number of orientations using the
3550 function
3551
3552 <tscreen><verb>
3553 void gtk_progress_bar_set_orientation( GtkProgressBar *pbar,
3554                                        GtkProgressBarOrientation orientation );
3555 </verb></tscreen>
3556
3557 The <tt/orientation/ argument may take one of the following
3558 values to indicate the direction in which the progress bar moves:
3559
3560 <tscreen><verb>
3561   GTK_PROGRESS_LEFT_TO_RIGHT
3562   GTK_PROGRESS_RIGHT_TO_LEFT
3563   GTK_PROGRESS_BOTTOM_TO_TOP
3564   GTK_PROGRESS_TOP_TO_BOTTOM
3565 </verb></tscreen>
3566
3567 When used as a measure of how far a process has progressed, the
3568 ProgressBar can be set to display its value in either a continuous
3569 or discrete mode. In continuous mode, the progress bar is updated for
3570 each value. In discrete mode, the progress bar is updated in a number
3571 of discrete blocks. The number of blocks is also configurable.
3572
3573 The style of a progress bar can be set using the following function.
3574
3575 <tscreen><verb>
3576 void gtk_progress_bar_set_bar_style( GtkProgressBar      *pbar,
3577                                      GtkProgressBarStyle  style );
3578 </verb></tscreen>
3579
3580 The <tt/style/ parameter can take one of two values:
3581
3582 <tscreen><verb>
3583   GTK_PROGRESS_CONTINUOUS
3584   GTK_PROGRESS_DISCRETE
3585 </verb></tscreen>
3586
3587 The number of discrete blocks can be set by calling
3588
3589 <tscreen><verb>
3590 void gtk_progress_bar_set_discrete_blocks( GtkProgressBar *pbar,
3591                                            guint           blocks );
3592 </verb></tscreen>
3593
3594 As well as indicating the amount of progress that has occured, the
3595 progress bar may be set to just indicate that there is some
3596 activity. This can be useful in situations where progress cannot be
3597 measured against a value range. Activity mode is not affected by the
3598 bar style that is described above, and overrides it. This mode is
3599 either TRUE or FALSE, and is selected by the following function.
3600
3601 <tscreen><verb>
3602 void gtk_progress_set_activity_mode( GtkProgress *progress,
3603                                      guint        activity_mode );
3604 </verb></tscreen>
3605
3606 The step size of the activity indicator, and the number of blocks are
3607 set using the following functions.
3608
3609 <tscreen><verb>
3610 void gtk_progress_bar_set_activity_step( GtkProgressBar *pbar,
3611                                          guint           step );
3612
3613 void gtk_progress_bar_set_activity_blocks( GtkProgressBar *pbar,
3614                                            guint           blocks );
3615 </verb></tscreen>
3616
3617 When in continuous mode, the progress bar can also display a
3618 configurable text string within its trough, using the following
3619 function.
3620
3621 <tscreen><verb>
3622 void gtk_progress_set_format_string( GtkProgress *progress,
3623                                      gchar       *format);
3624 </verb></tscreen>
3625
3626 The <tt/format/ argument is similiar to one that would be used in a C
3627 <tt/printf/ statement. The following directives may be used within the
3628 format string:
3629
3630 <itemize>
3631 <item> %p - percentage
3632 <item> %v - value
3633 <item> %l - lower range value
3634 <item> %u - upper range value
3635 </itemize>
3636
3637 The displaying of this text string can be toggled using:
3638
3639 <tscreen><verb>
3640 void gtk_progress_set_show_text( GtkProgress *progress,
3641                                  gint         show_text );
3642 </verb></tscreen>
3643
3644 The <tt/show_text/ argument is a boolean TRUE/FALSE value. The
3645 appearance of the text can be modified further using:
3646
3647 <tscreen><verb>
3648 void gtk_progress_set_text_alignment( GtkProgress   *progress,
3649                                       gfloat         x_align,
3650                                       gfloat         y_align );
3651 </verb></tscreen>
3652
3653 The <tt/x_align/ and <tt/y_align/ arguments take values between 0.0
3654 and 1.0. Their values indicate the position of the text string within
3655 the trough. Values of 0.0 for both would place the string in the top
3656 left hand corner; values of 0.5 (the default) centres the text, and
3657 values of 1.0 places the text in the lower right hand corner.
3658
3659 The current text setting of a progress object can be retrieved using
3660 the current or a specified adjustment value using the following two
3661 functions. The character string returned by these functions should be
3662 freed by the application (using the g_free() function). These
3663 functions return the formatted string that would be displayed within
3664 the trough.
3665
3666 <tscreen><verb>
3667 gchar *gtk_progress_get_current_text( GtkProgress   *progress );
3668
3669 gchar *gtk_progress_get_text_from_value( GtkProgress *progress,
3670                                          gfloat       value );
3671 </verb></tscreen>
3672
3673 There is yet another way to change the range and value of a progress
3674 object using the following function:
3675
3676 <tscreen><verb>
3677 void gtk_progress_configure( GtkProgress  *progress,
3678                              gfloat        value,
3679                              gfloat        min,
3680                              gfloat        max );
3681 </verb></tscreen>
3682
3683 This function provides quite a simple interface to the range and value
3684 of a progress object.
3685
3686 The remaining functions can be used to get and set the current value
3687 of a progess object in various types and formats:
3688
3689 <tscreen><verb>
3690 void gtk_progress_set_percentage( GtkProgress *progress,
3691                                   gfloat       percentage );
3692
3693 void gtk_progress_set_value( GtkProgress *progress,
3694                              gfloat       value );
3695
3696 gfloat gtk_progress_get_value( GtkProgress *progress );
3697
3698 gfloat gtk_progress_get_current_percentage( GtkProgress *progress );
3699
3700 gfloat gtk_progress_get_percentage_from_value( GtkProgress *progress,
3701                                                gfloat       value );
3702 </verb></tscreen>
3703
3704 These functions are pretty self explanatory. The last function uses
3705 the the adjustment of the specified progess object to compute the
3706 percentage value of the given range value.
3707
3708 Progress Bars are usually used with timeouts or other such functions
3709 (see section on <ref id="sec_timeouts" name="Timeouts, I/O and Idle
3710 Functions">) to give the illusion of multitasking. All will employ the
3711 gtk_progress_bar_update function in the same manner.
3712
3713 Here is an example of the progress bar, updated using timeouts. This
3714 code also shows you how to reset the Progress Bar.
3715
3716 <tscreen><verb>
3717 /* example-start progressbar progressbar.c */
3718
3719 #include <gtk/gtk.h>
3720
3721 typedef struct _ProgressData {
3722     GtkWidget *window;
3723     GtkWidget *pbar;
3724     int timer;
3725 } ProgressData;
3726
3727 /* Update the value of the progress bar so that we get
3728  * some movement */
3729 gint progress_timeout( gpointer data )
3730 {
3731     gfloat new_val;
3732     GtkAdjustment *adj;
3733
3734     /* Calculate the value of the progress bar using the
3735      * value range set in the adjustment object */
3736
3737     new_val = gtk_progress_get_value( GTK_PROGRESS(data) ) + 1;
3738
3739     adj = GTK_PROGRESS (data)->adjustment;
3740     if (new_val > adj->upper)
3741       new_val = adj->lower;
3742
3743     /* Set the new value */
3744     gtk_progress_set_value (GTK_PROGRESS (data), new_val);
3745
3746     /* As this is a timeout function, return TRUE so that it
3747      * continues to get called */
3748     return(TRUE);
3749
3750
3751 /* Callback that toggles the text display within the progress
3752  * bar trough */
3753 void toggle_show_text( GtkWidget    *widget,
3754                        ProgressData *pdata )
3755 {
3756     gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
3757                                 GTK_TOGGLE_BUTTON (widget)->active);
3758 }
3759
3760 /* Callback that toggles the activity mode of the progress
3761  * bar */
3762 void toggle_activity_mode( GtkWidget    *widget,
3763                            ProgressData *pdata )
3764 {
3765     gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
3766                                     GTK_TOGGLE_BUTTON (widget)->active);
3767 }
3768
3769 /* Callback that toggles the continuous mode of the progress
3770  * bar */
3771 void set_continuous_mode( GtkWidget    *widget,
3772                           ProgressData *pdata )
3773 {
3774     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3775                                     GTK_PROGRESS_CONTINUOUS);
3776 }
3777
3778 /* Callback that toggles the discrete mode of the progress
3779  * bar */
3780 void set_discrete_mode( GtkWidget    *widget,
3781                         ProgressData *pdata )
3782 {
3783     gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
3784                                     GTK_PROGRESS_DISCRETE);
3785 }
3786  
3787 /* Clean up allocated memory and remove the timer */
3788 void destroy_progress( GtkWidget     *widget,
3789                        ProgressData *pdata)
3790 {
3791     gtk_timeout_remove (pdata->timer);
3792     pdata->timer = 0;
3793     pdata->window = NULL;
3794     g_free(pdata);
3795     gtk_main_quit();
3796 }
3797
3798 int main( int   argc,
3799           char *argv[])
3800 {
3801     ProgressData *pdata;
3802     GtkWidget *align;
3803     GtkWidget *separator;
3804     GtkWidget *table;
3805     GtkAdjustment *adj;
3806     GtkWidget *button;
3807     GtkWidget *check;
3808     GtkWidget *vbox;
3809
3810     gtk_init (&amp;argc, &amp;argv);
3811
3812     /* Allocate memory for the data that is passwd to the callbacks */
3813     pdata = g_malloc( sizeof(ProgressData) );
3814   
3815     pdata->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3816     gtk_window_set_policy (GTK_WINDOW (pdata->window), FALSE, FALSE, TRUE);
3817
3818     gtk_signal_connect (GTK_OBJECT (pdata->window), "destroy",
3819                         GTK_SIGNAL_FUNC (destroy_progress),
3820                         pdata);
3821     gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
3822     gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
3823
3824     vbox = gtk_vbox_new (FALSE, 5);
3825     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
3826     gtk_container_add (GTK_CONTAINER (pdata->window), vbox);
3827     gtk_widget_show(vbox);
3828   
3829     /* Create a centering alignment object */
3830     align = gtk_alignment_new (0.5, 0.5, 0, 0);
3831     gtk_box_pack_start (GTK_BOX (vbox), align, FALSE, FALSE, 5);
3832     gtk_widget_show(align);
3833
3834     /* Create a Adjusment object to hold the range of the
3835      * progress bar */
3836     adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 150, 0, 0, 0);
3837
3838     /* Create the GtkProgressBar using the adjustment */
3839     pdata->pbar = gtk_progress_bar_new_with_adjustment (adj);
3840
3841     /* Set the format of the string that can be displayed in the
3842      * trough of the progress bar:
3843      * %p - percentage
3844      * %v - value
3845      * %l - lower range value
3846      * %u - upper range value */
3847     gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
3848                                     "%v from [%l-%u] (=%p%%)");
3849     gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
3850     gtk_widget_show(pdata->pbar);
3851
3852     /* Add a timer callback to update the value of the progress bar */
3853     pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
3854
3855     separator = gtk_hseparator_new ();
3856     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3857     gtk_widget_show(separator);
3858
3859     /* rows, columns, homogeneous */
3860     table = gtk_table_new (2, 3, FALSE);
3861     gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
3862     gtk_widget_show(table);
3863
3864     /* Add a check button to select displaying of the trough text */
3865     check = gtk_check_button_new_with_label ("Show text");
3866     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 0, 1,
3867                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3868                       5, 5);
3869     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3870                         GTK_SIGNAL_FUNC (toggle_show_text),
3871                         pdata);
3872     gtk_widget_show(check);
3873
3874     /* Add a check button to toggle activity mode */
3875     check = gtk_check_button_new_with_label ("Activity mode");
3876     gtk_table_attach (GTK_TABLE (table), check, 0, 1, 1, 2,
3877                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3878                       5, 5);
3879     gtk_signal_connect (GTK_OBJECT (check), "clicked",
3880                         GTK_SIGNAL_FUNC (toggle_activity_mode),
3881                         pdata);
3882     gtk_widget_show(check);
3883
3884     separator = gtk_vseparator_new ();
3885     gtk_table_attach (GTK_TABLE (table), separator, 1, 2, 0, 2,
3886                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3887                       5, 5);
3888     gtk_widget_show(separator);
3889
3890     /* Add a radio button to select continuous display mode */
3891     button = gtk_radio_button_new_with_label (NULL, "Continuous");
3892     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 0, 1,
3893                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3894                       5, 5);
3895     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3896                         GTK_SIGNAL_FUNC (set_continuous_mode),
3897                         pdata);
3898     gtk_widget_show (button);
3899
3900     /* Add a radio button to select discrete display mode */
3901     button = gtk_radio_button_new_with_label(
3902                gtk_radio_button_group (GTK_RADIO_BUTTON (button)),
3903                "Discrete");
3904     gtk_table_attach (GTK_TABLE (table), button, 2, 3, 1, 2,
3905                       GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
3906                       5, 5);
3907     gtk_signal_connect (GTK_OBJECT (button), "clicked",
3908                         GTK_SIGNAL_FUNC (set_discrete_mode),
3909                         pdata);
3910     gtk_widget_show (button);
3911
3912     separator = gtk_hseparator_new ();
3913     gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
3914     gtk_widget_show(separator);
3915
3916     /* Add a button to exit the program */
3917     button = gtk_button_new_with_label ("close");
3918     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
3919                                (GtkSignalFunc) gtk_widget_destroy,
3920                                GTK_OBJECT (pdata->window));
3921     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3922
3923     /* This makes it so the button is the default. */
3924     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3925
3926     /* This grabs this button to be the default button. Simply hitting
3927      * the "Enter" key will cause this button to activate. */
3928     gtk_widget_grab_default (button);
3929     gtk_widget_show(button);
3930
3931     gtk_widget_show (pdata->window);
3932
3933     gtk_main ();
3934     
3935     return(0);
3936 }
3937 /* example-end */
3938 </verb></tscreen>
3939
3940 <!-- ----------------------------------------------------------------- -->
3941 <sect1> Dialogs
3942 <p>
3943 The Dialog widget is very simple, and is actually just a window with a
3944 few things pre-packed into it for you. The structure for a Dialog is:
3945
3946 <tscreen><verb>
3947 struct GtkDialog
3948 {
3949       GtkWindow window;
3950     
3951       GtkWidget *vbox;
3952       GtkWidget *action_area;
3953 };
3954 </verb></tscreen>
3955
3956 So you see, it simply creates a window, and then packs a vbox into the
3957 top, which contains a separator and then an hbox called the
3958 "action_area".
3959
3960 The Dialog widget can be used for pop-up messages to the user, and
3961 other similar tasks. It is really basic, and there is only one
3962 function for the dialog box, which is:
3963
3964 <tscreen><verb>
3965 GtkWidget *gtk_dialog_new( void );
3966 </verb></tscreen>
3967
3968 So to create a new dialog box, use,
3969
3970 <tscreen><verb>
3971     GtkWidget *window;
3972     window = gtk_dialog_new ();
3973 </verb></tscreen>
3974
3975 This will create the dialog box, and it is now up to you to use it.
3976 You could pack a button in the action_area by doing something like this:
3977
3978 <tscreen><verb>
3979     button = ...
3980     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
3981                         button, TRUE, TRUE, 0);
3982     gtk_widget_show (button);
3983 </verb></tscreen>
3984
3985 And you could add to the vbox area by packing, for instance, a label 
3986 in it, try something like this:
3987
3988 <tscreen><verb>
3989     label = gtk_label_new ("Dialogs are groovy");
3990     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
3991                         label, TRUE, TRUE, 0);
3992     gtk_widget_show (label);
3993 </verb></tscreen>
3994
3995 As an example in using the dialog box, you could put two buttons in
3996 the action_area, a Cancel button and an Ok button, and a label in the
3997 vbox area, asking the user a question or giving an error etc. Then
3998 you could attach a different signal to each of the buttons and perform
3999 the operation the user selects.
4000
4001 If the simple functionality provided by the default vertical and
4002 horizontal boxes in the two areas doesn't give you enough control for
4003 your application, then you can simply pack another layout widget into
4004 the boxes provided. For example, you could pack a table into the
4005 vertical box.
4006
4007 <!-- ----------------------------------------------------------------- -->
4008 <sect1> Pixmaps <label id="sec_Pixmaps">
4009 <p>
4010 Pixmaps are data structures that contain pictures. These pictures can
4011 be used in various places, but most commonly as icons on the X
4012 desktop, or as cursors.
4013
4014 A pixmap which only has 2 colors is called a bitmap, and there are a
4015 few additional routines for handling this common special case.
4016
4017 To understand pixmaps, it would help to understand how X window
4018 system works. Under X, applications do not need to be running on the
4019 same computer that is interacting with the user. Instead, the various
4020 applications, called "clients", all communicate with a program which
4021 displays the graphics and handles the keyboard and mouse. This
4022 program which interacts directly with the user is called a "display
4023 server" or "X server." Since the communication might take place over
4024 a network, it's important to keep some information with the X server.
4025 Pixmaps, for example, are stored in the memory of the X server. This
4026 means that once pixmap values are set, they don't need to keep getting
4027 transmitted over the network; instead a command is sent to "display
4028 pixmap number XYZ here." Even if you aren't using X with GTK
4029 currently, using constructs such as Pixmaps will make your programs
4030 work acceptably under X.
4031
4032 To use pixmaps in GTK, we must first build a GdkPixmap structure using
4033 routines from the GDK layer. Pixmaps can either be created from
4034 in-memory data, or from data read from a file. We'll go through each
4035 of the calls to create a pixmap.
4036
4037 <tscreen><verb>
4038 GdkPixmap *gdk_bitmap_create_from_data( GdkWindow *window,
4039                                         gchar     *data,
4040                                         gint       width,
4041                                         gint       height );
4042 </verb></tscreen>
4043
4044 This routine is used to create a single-plane pixmap (2 colors) from
4045 data in memory. Each bit of the data represents whether that pixel is
4046 off or on. Width and height are in pixels. The GdkWindow pointer is to
4047 the current window, since a pixmap's resources are meaningful only in
4048 the context of the screen where it is to be displayed.
4049
4050 <tscreen><verb>
4051 GdkPixmap *gdk_pixmap_create_from_data( GdkWindow *window,
4052                                         gchar     *data,
4053                                         gint       width,
4054                                         gint       height,
4055                                         gint       depth,
4056                                         GdkColor  *fg,
4057                                         GdkColor  *bg );
4058 </verb></tscreen>
4059
4060 This is used to create a pixmap of the given depth (number of colors) from
4061 the bitmap data specified. <tt/fg/ and <tt/bg/ are the foreground and
4062 background color to use.
4063
4064 <tscreen><verb>
4065 GdkPixmap *gdk_pixmap_create_from_xpm( GdkWindow   *window,
4066                                        GdkBitmap  **mask,
4067                                        GdkColor    *transparent_color,
4068                                        const gchar *filename );
4069 </verb></tscreen>
4070
4071 XPM format is a readable pixmap representation for the X Window
4072 System. It is widely used and many different utilities are available
4073 for creating image files in this format. The file specified by
4074 filename must contain an image in that format and it is loaded into
4075 the pixmap structure. The mask specifies which bits of the pixmap are
4076 opaque. All other bits are colored using the color specified by
4077 transparent_color. An example using this follows below.
4078
4079 <tscreen><verb>
4080 GdkPixmap *gdk_pixmap_create_from_xpm_d( GdkWindow  *window,
4081                                          GdkBitmap **mask,
4082                                          GdkColor   *transparent_color,
4083                                          gchar     **data );
4084 </verb></tscreen>
4085
4086 Small images can be incorporated into a program as data in the XPM
4087 format. A pixmap is created using this data, instead of reading it
4088 from a file. An example of such data is
4089
4090 <tscreen><verb>
4091 /* XPM */
4092 static const char * xpm_data[] = {
4093 "16 16 3 1",
4094 "       c None",
4095 ".      c #000000000000",
4096 "X      c #FFFFFFFFFFFF",
4097 "                ",
4098 "   ......       ",
4099 "   .XXX.X.      ",
4100 "   .XXX.XX.     ",
4101 "   .XXX.XXX.    ",
4102 "   .XXX.....    ",
4103 "   .XXXXXXX.    ",
4104 "   .XXXXXXX.    ",
4105 "   .XXXXXXX.    ",
4106 "   .XXXXXXX.    ",
4107 "   .XXXXXXX.    ",
4108 "   .XXXXXXX.    ",
4109 "   .XXXXXXX.    ",
4110 "   .........    ",
4111 "                ",
4112 "                "};
4113 </verb></tscreen>
4114
4115 When we're done using a pixmap and not likely to reuse it again soon,
4116 it is a good idea to release the resource using
4117 gdk_pixmap_unref(). Pixmaps should be considered a precious resource,
4118 because they take up memory in the end-user's X server process. Even
4119 though the X client you write may run on a powerful "server" computer,
4120 the user may be running the X server on a small personal computer.
4121
4122 Once we've created a pixmap, we can display it as a GTK widget. We
4123 must create a GTK pixmap widget to contain the GDK pixmap. This is
4124 done using
4125
4126 <tscreen><verb>
4127 GtkWidget *gtk_pixmap_new( GdkPixmap *pixmap,
4128                            GdkBitmap *mask );
4129 </verb></tscreen>
4130
4131 The other pixmap widget calls are
4132
4133 <tscreen><verb>
4134 guint gtk_pixmap_get_type( void );
4135
4136 void  gtk_pixmap_set( GtkPixmap  *pixmap,
4137                       GdkPixmap  *val,
4138                       GdkBitmap  *mask );
4139
4140 void  gtk_pixmap_get( GtkPixmap  *pixmap,
4141                       GdkPixmap **val,
4142                       GdkBitmap **mask);
4143 </verb></tscreen>
4144
4145 gtk_pixmap_set is used to change the pixmap that the widget is currently
4146 managing. Val is the pixmap created using GDK.
4147
4148 The following is an example of using a pixmap in a button.
4149
4150 <tscreen><verb>
4151 /* example-start pixmap pixmap.c */
4152
4153 #include <gtk/gtk.h>
4154
4155
4156 /* XPM data of Open-File icon */
4157 static const char * xpm_data[] = {
4158 "16 16 3 1",
4159 "       c None",
4160 ".      c #000000000000",
4161 "X      c #FFFFFFFFFFFF",
4162 "                ",
4163 "   ......       ",
4164 "   .XXX.X.      ",
4165 "   .XXX.XX.     ",
4166 "   .XXX.XXX.    ",
4167 "   .XXX.....    ",
4168 "   .XXXXXXX.    ",
4169 "   .XXXXXXX.    ",
4170 "   .XXXXXXX.    ",
4171 "   .XXXXXXX.    ",
4172 "   .XXXXXXX.    ",
4173 "   .XXXXXXX.    ",
4174 "   .XXXXXXX.    ",
4175 "   .........    ",
4176 "                ",
4177 "                "};
4178
4179
4180 /* when invoked (via signal delete_event), terminates the application.
4181  */
4182 gint close_application( GtkWidget *widget,
4183                         GdkEvent  *event,
4184                         gpointer   data )
4185 {
4186     gtk_main_quit();
4187     return(FALSE);
4188 }
4189
4190
4191 /* is invoked when the button is clicked.  It just prints a message.
4192  */
4193 void button_clicked( GtkWidget *widget,
4194                      gpointer   data ) {
4195     g_print( "button clicked\n" );
4196 }
4197
4198 int main( int   argc,
4199           char *argv[] )
4200 {
4201     /* GtkWidget is the storage type for widgets */
4202     GtkWidget *window, *pixmapwid, *button;
4203     GdkPixmap *pixmap;
4204     GdkBitmap *mask;
4205     GtkStyle *style;
4206     
4207     /* create the main window, and attach delete_event signal to terminating
4208        the application */
4209     gtk_init( &amp;argc, &amp;argv );
4210     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4211     gtk_signal_connect( GTK_OBJECT (window), "delete_event",
4212                         GTK_SIGNAL_FUNC (close_application), NULL );
4213     gtk_container_set_border_width( GTK_CONTAINER (window), 10 );
4214     gtk_widget_show( window );
4215
4216     /* now for the pixmap from gdk */
4217     style = gtk_widget_get_style( window );
4218     pixmap = gdk_pixmap_create_from_xpm_d( window->window,  &amp;mask,
4219                                            &amp;style->bg[GTK_STATE_NORMAL],
4220                                            (gchar **)xpm_data );
4221
4222     /* a pixmap widget to contain the pixmap */
4223     pixmapwid = gtk_pixmap_new( pixmap, mask );
4224     gtk_widget_show( pixmapwid );
4225
4226     /* a button to contain the pixmap widget */
4227     button = gtk_button_new();
4228     gtk_container_add( GTK_CONTAINER(button), pixmapwid );
4229     gtk_container_add( GTK_CONTAINER(window), button );
4230     gtk_widget_show( button );
4231
4232     gtk_signal_connect( GTK_OBJECT(button), "clicked",
4233                         GTK_SIGNAL_FUNC(button_clicked), NULL );
4234
4235     /* show the window */
4236     gtk_main ();
4237           
4238     return 0;
4239 }
4240 /* example-end */
4241 </verb></tscreen>
4242
4243 To load a file from an XPM data file called icon0.xpm in the current
4244 directory, we would have created the pixmap thus
4245
4246 <tscreen><verb>
4247     /* load a pixmap from a file */
4248     pixmap = gdk_pixmap_create_from_xpm( window->window, &amp;mask,
4249                                          &amp;style->bg[GTK_STATE_NORMAL],
4250                                          "./icon0.xpm" );
4251     pixmapwid = gtk_pixmap_new( pixmap, mask );
4252     gtk_widget_show( pixmapwid );
4253     gtk_container_add( GTK_CONTAINER(window), pixmapwid );
4254 </verb></tscreen>
4255
4256 A disadvantage of using pixmaps is that the displayed object is always
4257 rectangular, regardless of the image. We would like to create desktops
4258 and applications with icons that have more natural shapes. For
4259 example, for a game interface, we would like to have round buttons to
4260 push. The way to do this is using shaped windows.
4261
4262 A shaped window is simply a pixmap where the background pixels are
4263 transparent. This way, when the background image is multi-colored, we
4264 don't overwrite it with a rectangular, non-matching border around our
4265 icon. The following example displays a full wheelbarrow image on the
4266 desktop.
4267
4268 <tscreen><verb>
4269 /* example-start wheelbarrow wheelbarrow.c */
4270
4271 #include <gtk/gtk.h>
4272
4273 /* XPM */
4274 static char * WheelbarrowFull_xpm[] = {
4275 "48 48 64 1",
4276 "       c None",
4277 ".      c #DF7DCF3CC71B",
4278 "X      c #965875D669A6",
4279 "o      c #71C671C671C6",
4280 "O      c #A699A289A699",
4281 "+      c #965892489658",
4282 "@      c #8E38410330C2",
4283 "#      c #D75C7DF769A6",
4284 "$      c #F7DECF3CC71B",
4285 "%      c #96588A288E38",
4286 "&amp;      c #A69992489E79",
4287 "*      c #8E3886178E38",
4288 "=      c #104008200820",
4289 "-      c #596510401040",
4290 ";      c #C71B30C230C2",
4291 ":      c #C71B9A699658",
4292 ">      c #618561856185",
4293 ",      c #20811C712081",
4294 "<      c #104000000000",
4295 "1      c #861720812081",
4296 "2      c #DF7D4D344103",
4297 "3      c #79E769A671C6",
4298 "4      c #861782078617",
4299 "5      c #41033CF34103",
4300 "6      c #000000000000",
4301 "7      c #49241C711040",
4302 "8      c #492445144924",
4303 "9      c #082008200820",
4304 "0      c #69A618611861",
4305 "q      c #B6DA71C65144",
4306 "w      c #410330C238E3",
4307 "e      c #CF3CBAEAB6DA",
4308 "r      c #71C6451430C2",
4309 "t      c #EFBEDB6CD75C",
4310 "y      c #28A208200820",
4311 "u      c #186110401040",
4312 "i      c #596528A21861",
4313 "p      c #71C661855965",
4314 "a      c #A69996589658",
4315 "s      c #30C228A230C2",
4316 "d      c #BEFBA289AEBA",
4317 "f      c #596545145144",
4318 "g      c #30C230C230C2",
4319 "h      c #8E3882078617",
4320 "j      c #208118612081",
4321 "k      c #38E30C300820",
4322 "l      c #30C2208128A2",
4323 "z      c #38E328A238E3",
4324 "x      c #514438E34924",
4325 "c      c #618555555965",
4326 "v      c #30C2208130C2",
4327 "b      c #38E328A230C2",
4328 "n      c #28A228A228A2",
4329 "m      c #41032CB228A2",
4330 "M      c #104010401040",
4331 "N      c #492438E34103",
4332 "B      c #28A2208128A2",
4333 "V      c #A699596538E3",
4334 "C      c #30C21C711040",
4335 "Z      c #30C218611040",
4336 "A      c #965865955965",
4337 "S      c #618534D32081",
4338 "D      c #38E31C711040",
4339 "F      c #082000000820",
4340 "                                                ",
4341 "          .XoO                                  ",
4342 "         +@#$%o&amp;                                ",
4343 "         *=-;#::o+                              ",
4344 "           >,<12#:34                            ",
4345 "             45671#:X3                          ",
4346 "               +89<02qwo                        ",
4347 "e*                >,67;ro                       ",
4348 "ty>                 459@>+&amp;&amp;                    ",
4349 "$2u+                  ><ipas8*                  ",
4350 "%$;=*                *3:.Xa.dfg>                ",
4351 "Oh$;ya             *3d.a8j,Xe.d3g8+             ",
4352 " Oh$;ka          *3d$a8lz,,xxc:.e3g54           ",
4353 "  Oh$;kO       *pd$%svbzz,sxxxxfX..&amp;wn>         ",
4354 "   Oh$@mO    *3dthwlsslszjzxxxxxxx3:td8M4       ",
4355 "    Oh$@g&amp; *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B*     ",
4356 "     Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5&amp;   ",
4357 "      Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM*  ",
4358 "       OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ",
4359 "        2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ",
4360 "        :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo",
4361 "         +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g",
4362 "          *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&amp;en",
4363 "           p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>",
4364 "           OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ",
4365 "            3206Bwxxszx%et.eaAp77m77mmmf3&amp;eeeg* ",
4366 "             @26MvzxNzvlbwfpdettttttttttt.c,n&amp;  ",
4367 "             *;16=lsNwwNwgsvslbwwvccc3pcfu<o    ",
4368 "              p;<69BvwwsszslllbBlllllllu<5+     ",
4369 "              OS0y6FBlvvvzvzss,u=Blllj=54       ",
4370 "               c1-699Blvlllllu7k96MMMg4         ",
4371 "               *10y8n6FjvllllB<166668           ",
4372 "                S-kg+>666<M<996-y6n<8*          ",
4373 "                p71=4 m69996kD8Z-66698&amp;&amp;        ",
4374 "                &amp;i0ycm6n4 ogk17,0<6666g         ",
4375 "                 N-k-<>     >=01-kuu666>        ",
4376 "                 ,6ky&amp;      &amp;46-10ul,66,        ",
4377 "                 Ou0<>       o66y<ulw<66&amp;       ",
4378 "                  *kk5       >66By7=xu664       ",
4379 "                   <<M4      466lj<Mxu66o       ",
4380 "                   *>>       +66uv,zN666*       ",
4381 "                              566,xxj669        ",
4382 "                              4666FF666>        ",
4383 "                               >966666M         ",
4384 "                                oM6668+         ",
4385 "                                  *4            ",
4386 "                                                ",
4387 "                                                "};
4388
4389
4390 /* When invoked (via signal delete_event), terminates the application */
4391 gint close_application( GtkWidget *widget,
4392                         GdkEvent  *event,
4393                         gpointer   data )
4394 {
4395     gtk_main_quit();
4396     return(FALSE);
4397 }
4398
4399 int main (int argc,
4400           char *argv[] )
4401 {
4402     /* GtkWidget is the storage type for widgets */
4403     GtkWidget *window, *pixmap, *fixed;
4404     GdkPixmap *gdk_pixmap;
4405     GdkBitmap *mask;
4406     GtkStyle *style;
4407     GdkGC *gc;
4408     
4409     /* Create the main window, and attach delete_event signal to terminate
4410      * the application.  Note that the main window will not have a titlebar
4411      * since we're making it a popup. */
4412     gtk_init (&amp;argc, &amp;argv);
4413     window = gtk_window_new( GTK_WINDOW_POPUP );
4414     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4415                         GTK_SIGNAL_FUNC (close_application), NULL);
4416     gtk_widget_show (window);
4417
4418     /* Now for the pixmap and the pixmap widget */
4419     style = gtk_widget_get_default_style();
4420     gc = style->black_gc;
4421     gdk_pixmap = gdk_pixmap_create_from_xpm_d( window->window, &amp;mask,
4422                                              &amp;style->bg[GTK_STATE_NORMAL],
4423                                              WheelbarrowFull_xpm );
4424     pixmap = gtk_pixmap_new( gdk_pixmap, mask );
4425     gtk_widget_show( pixmap );
4426
4427     /* To display the pixmap, we use a fixed widget to place the pixmap */
4428     fixed = gtk_fixed_new();
4429     gtk_widget_set_usize( fixed, 200, 200 );
4430     gtk_fixed_put( GTK_FIXED(fixed), pixmap, 0, 0 );
4431     gtk_container_add( GTK_CONTAINER(window), fixed );
4432     gtk_widget_show( fixed );
4433
4434     /* This masks out everything except for the image itself */
4435     gtk_widget_shape_combine_mask( window, mask, 0, 0 );
4436     
4437     /* show the window */
4438     gtk_widget_set_uposition( window, 20, 400 );
4439     gtk_widget_show( window );
4440     gtk_main ();
4441           
4442     return(0);
4443 }
4444 /* example-end */
4445 </verb></tscreen>
4446
4447 To make the wheelbarrow image sensitive, we could attach the button
4448 press event signal to make it do something. The following few lines
4449 would make the picture sensitive to a mouse button being pressed which
4450 makes the application terminate.
4451
4452 <tscreen><verb>
4453     gtk_widget_set_events( window,
4454                           gtk_widget_get_events( window ) |
4455                           GDK_BUTTON_PRESS_MASK );
4456
4457    gtk_signal_connect( GTK_OBJECT(window), "button_press_event",
4458                        GTK_SIGNAL_FUNC(close_application), NULL );
4459 </verb></tscreen>
4460
4461 <!-- ----------------------------------------------------------------- -->
4462 <sect1>Rulers
4463 <p>
4464 Ruler widgets are used to indicate the location of the mouse pointer
4465 in a given window. A window can have a vertical ruler spanning across
4466 the width and a horizontal ruler spanning down the height. A small
4467 triangular indicator on the ruler shows the exact location of the
4468 pointer relative to the ruler.
4469
4470 A ruler must first be created. Horizontal and vertical rulers are
4471 created using
4472
4473 <tscreen><verb>
4474 GtkWidget *gtk_hruler_new( void );    /* horizontal ruler */
4475
4476 GtkWidget *gtk_vruler_new( void );    /* vertical ruler   */
4477 </verb></tscreen>
4478
4479 Once a ruler is created, we can define the unit of measurement. Units
4480 of measure for rulers can be<tt/GTK_PIXELS/, <tt/GTK_INCHES/ or
4481 <tt/GTK_CENTIMETERS/. This is set using
4482
4483 <tscreen><verb>
4484 void gtk_ruler_set_metric( GtkRuler      *ruler,
4485                            GtkMetricType  metric );
4486 </verb></tscreen>
4487
4488 The default measure is <tt/GTK_PIXELS/.
4489
4490 <tscreen><verb>
4491     gtk_ruler_set_metric( GTK_RULER(ruler), GTK_PIXELS );
4492 </verb></tscreen>
4493
4494 Other important characteristics of a ruler are how to mark the units
4495 of scale and where the position indicator is initially placed. These
4496 are set for a ruler using
4497
4498 <tscreen><verb>
4499 void gtk_ruler_set_range( GtkRuler *ruler,
4500                           gfloat    lower,
4501                           gfloat    upper,
4502                           gfloat    position,
4503                           gfloat    max_size );
4504 </verb></tscreen>
4505
4506 The lower and upper arguments define the extent of the ruler, and
4507 max_size is the largest possible number that will be displayed.
4508 Position defines the initial position of the pointer indicator within
4509 the ruler.
4510
4511 A vertical ruler can span an 800 pixel wide window thus
4512
4513 <tscreen><verb>
4514     gtk_ruler_set_range( GTK_RULER(vruler), 0, 800, 0, 800);
4515 </verb></tscreen>
4516
4517 The markings displayed on the ruler will be from 0 to 800, with a
4518 number for every 100 pixels. If instead we wanted the ruler to range
4519 from 7 to 16, we would code
4520
4521 <tscreen><verb>
4522     gtk_ruler_set_range( GTK_RULER(vruler), 7, 16, 0, 20);
4523 </verb></tscreen>
4524
4525 The indicator on the ruler is a small triangular mark that indicates
4526 the position of the pointer relative to the ruler. If the ruler is
4527 used to follow the mouse pointer, the motion_notify_event signal
4528 should be connected to the motion_notify_event method of the ruler.
4529 To follow all mouse movements within a window area, we would use
4530
4531 <tscreen><verb>
4532 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4533
4534     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4535            (GtkSignalFunc)EVENT_METHOD(ruler, motion_notify_event),
4536            GTK_OBJECT(ruler) );
4537 </verb></tscreen>
4538
4539 The following example creates a drawing area with a horizontal ruler
4540 above it and a vertical ruler to the left of it. The size of the
4541 drawing area is 600 pixels wide by 400 pixels high. The horizontal
4542 ruler spans from 7 to 13 with a mark every 100 pixels, while the
4543 vertical ruler spans from 0 to 400 with a mark every 100 pixels.
4544 Placement of the drawing area and the rulers is done using a table.
4545
4546 <tscreen><verb>
4547 /* example-start rulers rulers.c */
4548
4549 #include <gtk/gtk.h>
4550
4551 #define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x
4552
4553 #define XSIZE  600
4554 #define YSIZE  400
4555
4556 /* This routine gets control when the close button is clicked */
4557 gint close_application( GtkWidget *widget,
4558                         GdkEvent  *event,
4559                         gpointer   data )
4560 {
4561     gtk_main_quit();
4562     return(FALSE);
4563 }
4564
4565 /* The main routine */
4566 int main( int   argc,
4567           char *argv[] ) {
4568     GtkWidget *window, *table, *area, *hrule, *vrule;
4569
4570     /* Initialize GTK and create the main window */
4571     gtk_init( &amp;argc, &amp;argv );
4572
4573     window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
4574     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
4575             GTK_SIGNAL_FUNC( close_application ), NULL);
4576     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
4577
4578     /* Create a table for placing the ruler and the drawing area */
4579     table = gtk_table_new( 3, 2, FALSE );
4580     gtk_container_add( GTK_CONTAINER(window), table );
4581
4582     area = gtk_drawing_area_new();
4583     gtk_drawing_area_size( (GtkDrawingArea *)area, XSIZE, YSIZE );
4584     gtk_table_attach( GTK_TABLE(table), area, 1, 2, 1, 2,
4585                       GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0 );
4586     gtk_widget_set_events( area, GDK_POINTER_MOTION_MASK |
4587                                  GDK_POINTER_MOTION_HINT_MASK );
4588
4589     /* The horizontal ruler goes on top. As the mouse moves across the
4590      * drawing area, a motion_notify_event is passed to the
4591      * appropriate event handler for the ruler. */
4592     hrule = gtk_hruler_new();
4593     gtk_ruler_set_metric( GTK_RULER(hrule), GTK_PIXELS );
4594     gtk_ruler_set_range( GTK_RULER(hrule), 7, 13, 0, 20 );
4595     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4596                                (GtkSignalFunc)EVENT_METHOD(hrule,
4597                                                         motion_notify_event),
4598                                GTK_OBJECT(hrule) );
4599     /*  GTK_WIDGET_CLASS(GTK_OBJECT(hrule)->klass)->motion_notify_event, */
4600     gtk_table_attach( GTK_TABLE(table), hrule, 1, 2, 0, 1,
4601                       GTK_EXPAND|GTK_SHRINK|GTK_FILL, GTK_FILL, 0, 0 );
4602     
4603     /* The vertical ruler goes on the left. As the mouse moves across
4604      * the drawing area, a motion_notify_event is passed to the
4605      * appropriate event handler for the ruler. */
4606     vrule = gtk_vruler_new();
4607     gtk_ruler_set_metric( GTK_RULER(vrule), GTK_PIXELS );
4608     gtk_ruler_set_range( GTK_RULER(vrule), 0, YSIZE, 10, YSIZE );
4609     gtk_signal_connect_object( GTK_OBJECT(area), "motion_notify_event",
4610                                (GtkSignalFunc)
4611                                   GTK_WIDGET_CLASS(GTK_OBJECT(vrule)->klass)->
4612                                                          motion_notify_event,
4613                                GTK_OBJECT(vrule) );
4614     gtk_table_attach( GTK_TABLE(table), vrule, 0, 1, 1, 2,
4615                       GTK_FILL, GTK_EXPAND|GTK_SHRINK|GTK_FILL, 0, 0 );
4616
4617     /* Now show everything */
4618     gtk_widget_show( area );
4619     gtk_widget_show( hrule );
4620     gtk_widget_show( vrule );
4621     gtk_widget_show( table );
4622     gtk_widget_show( window );
4623     gtk_main();
4624
4625     return(0);
4626 }
4627 /* example-end */
4628 </verb></tscreen>
4629
4630 <!-- ----------------------------------------------------------------- -->
4631 <sect1>Statusbars
4632 <p>
4633 Statusbars are simple widgets used to display a text message. They
4634 keep a stack of the messages pushed onto them, so that popping the
4635 current message will re-display the previous text message.
4636
4637 In order to allow different parts of an application to use the same
4638 statusbar to display messages, the statusbar widget issues Context
4639 Identifiers which are used to identify different "users". The message
4640 on top of the stack is the one displayed, no matter what context it is
4641 in. Messages are stacked in last-in-first-out order, not context
4642 identifier order.
4643
4644 A statusbar is created with a call to:
4645
4646 <tscreen><verb>
4647 GtkWidget *gtk_statusbar_new( void );
4648 </verb></tscreen>
4649
4650 A new Context Identifier is requested using a call to the following 
4651 function with a short textual description of the context:
4652
4653 <tscreen><verb>
4654 guint gtk_statusbar_get_context_id( GtkStatusbar *statusbar,
4655                                     const gchar  *context_description );
4656 </verb></tscreen>
4657
4658 There are three functions that can operate on statusbars:
4659
4660 <tscreen><verb>
4661 guint gtk_statusbar_push( GtkStatusbar *statusbar,
4662                           guint         context_id,
4663                           gchar        *text );
4664
4665 void gtk_statusbar_pop( GtkStatusbar *statusbar)
4666                         guint         context_id );
4667
4668 void gtk_statusbar_remove( GtkStatusbar *statusbar,
4669                            guint         context_id,
4670                            guint         message_id ); 
4671 </verb></tscreen>
4672
4673 The first, gtk_statusbar_push, is used to add a new message to the
4674 statusbar.  It returns a Message Identifier, which can be passed later
4675 to the function gtk_statusbar_remove to remove the message with the
4676 given Message and Context Identifiers from the statusbar's stack.
4677
4678 The function gtk_statusbar_pop removes the message highest in the
4679 stack with the given Context Identifier.
4680
4681 The following example creates a statusbar and two buttons, one for
4682 pushing items onto the statusbar, and one for popping the last item
4683 back off.
4684
4685 <tscreen><verb>
4686 /* example-start statusbar statusbar.c */
4687
4688 #include <gtk/gtk.h>
4689 #include <glib.h>
4690
4691 GtkWidget *status_bar;
4692
4693 void push_item( GtkWidget *widget,
4694                 gpointer   data )
4695 {
4696   static int count = 1;
4697   char buff[20];
4698
4699   g_snprintf(buff, 20, "Item %d", count++);
4700   gtk_statusbar_push( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data), buff);
4701
4702   return;
4703 }
4704
4705 void pop_item( GtkWidget *widget,
4706                gpointer   data )
4707 {
4708   gtk_statusbar_pop( GTK_STATUSBAR(status_bar), GPOINTER_TO_INT(data) );
4709   return;
4710 }
4711
4712 int main( int   argc,
4713           char *argv[] )
4714 {
4715
4716     GtkWidget *window;
4717     GtkWidget *vbox;
4718     GtkWidget *button;
4719
4720     gint context_id;
4721
4722     gtk_init (&amp;argc, &amp;argv);
4723
4724     /* create a new window */
4725     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4726     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4727     gtk_window_set_title(GTK_WINDOW (window), "GTK Statusbar Example");
4728     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4729                        (GtkSignalFunc) gtk_exit, NULL);
4730  
4731     vbox = gtk_vbox_new(FALSE, 1);
4732     gtk_container_add(GTK_CONTAINER(window), vbox);
4733     gtk_widget_show(vbox);
4734           
4735     status_bar = gtk_statusbar_new();      
4736     gtk_box_pack_start (GTK_BOX (vbox), status_bar, TRUE, TRUE, 0);
4737     gtk_widget_show (status_bar);
4738
4739     context_id = gtk_statusbar_get_context_id(
4740                           GTK_STATUSBAR(status_bar), "Statusbar example");
4741
4742     button = gtk_button_new_with_label("push item");
4743     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4744         GTK_SIGNAL_FUNC (push_item), GINT_TO_POINTER(context_id) );
4745     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4746     gtk_widget_show(button);              
4747
4748     button = gtk_button_new_with_label("pop last item");
4749     gtk_signal_connect(GTK_OBJECT(button), "clicked",
4750         GTK_SIGNAL_FUNC (pop_item), GINT_TO_POINTER(context_id) );
4751     gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 2);
4752     gtk_widget_show(button);              
4753
4754     /* always display the window as the last step so it all splashes on
4755      * the screen at once. */
4756     gtk_widget_show(window);
4757
4758     gtk_main ();
4759
4760     return 0;
4761 }
4762 /* example-end */
4763 </verb></tscreen>
4764
4765 <!-- ----------------------------------------------------------------- -->
4766 <sect1>Text Entries
4767 <p>
4768 The Entry widget allows text to be typed and displayed in a single line
4769 text box. The text may be set with function calls that allow new text
4770 to replace, prepend or append the current contents of the Entry widget.
4771
4772 There are two functions for creating Entry widgets:
4773
4774 <tscreen><verb>
4775 GtkWidget *gtk_entry_new( void );
4776
4777 GtkWidget *gtk_entry_new_with_max_length( guint16 max );
4778 </verb></tscreen>
4779
4780 The first just creates a new Entry widget, whilst the second creates a
4781 new Entry and sets a limit on the length of the text within the Entry.
4782
4783 There are several functions for altering the text which is currently
4784 within the Entry widget.
4785
4786 <tscreen><verb>
4787 void gtk_entry_set_text( GtkEntry    *entry,
4788                          const gchar *text );
4789
4790 void gtk_entry_append_text( GtkEntry    *entry,
4791                             const gchar *text );
4792
4793 void gtk_entry_prepend_text( GtkEntry    *entry,
4794                              const gchar *text );
4795 </verb></tscreen>
4796
4797 The function gtk_entry_set_text sets the contents of the Entry widget,
4798 replacing the current contents. The functions gtk_entry_append_text
4799 and gtk_entry_prepend_text allow the current contents to be appended
4800 and prepended to.
4801
4802 The next function allows the current insertion point to be set.
4803
4804 <tscreen><verb>
4805 void gtk_entry_set_position( GtkEntry *entry,
4806                              gint      position );
4807 </verb></tscreen>
4808
4809 The contents of the Entry can be retrieved by using a call to the
4810 following function. This is useful in the callback functions described below.
4811
4812 <tscreen><verb>
4813 gchar *gtk_entry_get_text( GtkEntry *entry );
4814 </verb></tscreen>
4815
4816 The value returned by this function is used internally, and must not
4817 be freed using either free() or g_free()
4818
4819 If we don't want the contents of the Entry to be changed by someone typing
4820 into it, we can change its editable state.
4821
4822 <tscreen><verb>
4823 void gtk_entry_set_editable( GtkEntry *entry,
4824                              gboolean  editable );
4825 </verb></tscreen>
4826
4827 The function above allows us to toggle the editable state of the
4828 Entry widget by passing in a TRUE or FALSE value for the <tt/editable/
4829 argument.
4830
4831 If we are using the Entry where we don't want the text entered to be
4832 visible, for example when a password is being entered, we can use the
4833 following function, which also takes a boolean flag.
4834
4835 <tscreen><verb>
4836 void gtk_entry_set_visibility( GtkEntry *entry,
4837                                gboolean  visible );
4838 </verb></tscreen>
4839
4840 A region of the text may be set as selected by using the following
4841 function. This would most often be used after setting some default
4842 text in an Entry, making it easy for the user to remove it.
4843
4844 <tscreen><verb>
4845 void gtk_entry_select_region( GtkEntry *entry,
4846                               gint      start,
4847                               gint      end );
4848 </verb></tscreen>
4849
4850 If we want to catch when the user has entered text, we can connect to
4851 the <tt/activate/ or <tt/changed/ signal. Activate is raised when the
4852 user hits the enter key within the Entry widget. Changed is raised
4853 when the text changes at all, e.g., for every character entered or
4854 removed.
4855
4856 The following code is an example of using an Entry widget.
4857
4858 <tscreen><verb>
4859 /* example-start entry entry.c */
4860
4861 #include <stdio.h>
4862 #include <gtk/gtk.h>
4863
4864 void enter_callback( GtkWidget *widget,
4865                      GtkWidget *entry )
4866 {
4867   gchar *entry_text;
4868   entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
4869   printf("Entry contents: %s\n", entry_text);
4870 }
4871
4872 void entry_toggle_editable( GtkWidget *checkbutton,
4873                             GtkWidget *entry )
4874 {
4875   gtk_entry_set_editable(GTK_ENTRY(entry),
4876                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4877 }
4878
4879 void entry_toggle_visibility( GtkWidget *checkbutton,
4880                               GtkWidget *entry )
4881 {
4882   gtk_entry_set_visibility(GTK_ENTRY(entry),
4883                          GTK_TOGGLE_BUTTON(checkbutton)->active);
4884 }
4885
4886 int main( int   argc,
4887           char *argv[] )
4888 {
4889
4890     GtkWidget *window;
4891     GtkWidget *vbox, *hbox;
4892     GtkWidget *entry;
4893     GtkWidget *button;
4894     GtkWidget *check;
4895
4896     gtk_init (&amp;argc, &amp;argv);
4897
4898     /* create a new window */
4899     window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
4900     gtk_widget_set_usize( GTK_WIDGET (window), 200, 100);
4901     gtk_window_set_title(GTK_WINDOW (window), "GTK Entry");
4902     gtk_signal_connect(GTK_OBJECT (window), "delete_event",
4903                        (GtkSignalFunc) gtk_exit, NULL);
4904
4905     vbox = gtk_vbox_new (FALSE, 0);
4906     gtk_container_add (GTK_CONTAINER (window), vbox);
4907     gtk_widget_show (vbox);
4908
4909     entry = gtk_entry_new_with_max_length (50);
4910     gtk_signal_connect(GTK_OBJECT(entry), "activate",
4911                        GTK_SIGNAL_FUNC(enter_callback),
4912                        entry);
4913     gtk_entry_set_text (GTK_ENTRY (entry), "hello");
4914     gtk_entry_append_text (GTK_ENTRY (entry), " world");
4915     gtk_entry_select_region (GTK_ENTRY (entry),
4916                              0, GTK_ENTRY(entry)->text_length);
4917     gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
4918     gtk_widget_show (entry);
4919
4920     hbox = gtk_hbox_new (FALSE, 0);
4921     gtk_container_add (GTK_CONTAINER (vbox), hbox);
4922     gtk_widget_show (hbox);
4923                                   
4924     check = gtk_check_button_new_with_label("Editable");
4925     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4926     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4927                         GTK_SIGNAL_FUNC(entry_toggle_editable), entry);
4928     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4929     gtk_widget_show (check);
4930     
4931     check = gtk_check_button_new_with_label("Visible");
4932     gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
4933     gtk_signal_connect (GTK_OBJECT(check), "toggled",
4934                         GTK_SIGNAL_FUNC(entry_toggle_visibility), entry);
4935     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
4936     gtk_widget_show (check);
4937                                    
4938     button = gtk_button_new_with_label ("Close");
4939     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
4940                                GTK_SIGNAL_FUNC(gtk_exit),
4941                                GTK_OBJECT (window));
4942     gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
4943     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4944     gtk_widget_grab_default (button);
4945     gtk_widget_show (button);
4946     
4947     gtk_widget_show(window);
4948
4949     gtk_main();
4950     return(0);
4951 }
4952 /* example-end */
4953 </verb></tscreen>
4954
4955 <!-- ----------------------------------------------------------------- -->
4956 <sect1>Spin Buttons
4957 <p>
4958 The Spin Button widget is generally used to allow the user to select a
4959 value from a range of numeric values. It consists of a text
4960 entry box with up and down arrow buttons attached to the
4961 side. Selecting one of the buttons causes the value to "spin" up and
4962 down the range of possible values. The entry box may also be edited
4963 directly to enter a specific value.
4964
4965 The Spin Button allows the value to have zero or a number of decimal
4966 places and to be incremented/decremented in configurable steps. The
4967 action of holding down one of the buttons optionally results in an
4968 acceleration of change in the value according to how long it is
4969 depressed.
4970
4971 The Spin Button uses an <ref id="sec_Adjustment" name="Adjustment">
4972 object to hold information about the range of values that the spin
4973 button can take. This makes for a powerful Spin Button widget.
4974
4975 Recall that an adjustment widget is created with the following
4976 function, which illustrates the information that it holds:
4977
4978 <tscreen><verb>
4979 GtkObject *gtk_adjustment_new( gfloat value,
4980                                gfloat lower,
4981                                gfloat upper,
4982                                gfloat step_increment,
4983                                gfloat page_increment,
4984                                gfloat page_size );
4985 </verb></tscreen>
4986
4987 These attributes of an Adjustment are used by the Spin Button in the
4988 following way:
4989
4990 <itemize>
4991 <item> <tt/value/: initial value for the Spin Button
4992 <item> <tt/lower/: lower range value
4993 <item> <tt/upper/: upper range value
4994 <item> <tt/step_increment/: value to increment/decrement when pressing
4995 mouse button 1 on a button
4996 <item> <tt/page_increment/: value to increment/decrement when pressing
4997 mouse button 2 on a button
4998 <item> <tt/page_size/: unused
4999 </itemize>
5000
5001 Additionally, mouse button 3 can be used to jump directly to the
5002 <tt/upper/ or <tt/lower/ values when used to select one of the
5003 buttons. Lets look at how to create a Spin Button:
5004
5005 <tscreen><verb>
5006 GtkWidget *gtk_spin_button_new( GtkAdjustment *adjustment,
5007                                 gfloat         climb_rate,
5008                                 guint          digits );
5009 </verb></tscreen>
5010
5011 The <tt/climb_rate/ argument take a value between 0.0 and 1.0 and
5012 indicates the amount of acceleration that the Spin Button has. The
5013 <tt/digits/ argument specifies the number of decimal places to which
5014 the value will be displayed.
5015
5016 A Spin Button can be reconfigured after creation using the following
5017 function:
5018
5019 <tscreen><verb>
5020 void gtk_spin_button_configure( GtkSpinButton *spin_button,
5021                                 GtkAdjustment *adjustment,
5022                                 gfloat         climb_rate,
5023                                 guint          digits );
5024 </verb></tscreen>
5025
5026 The <tt/spin_button/ argument specifies the Spin Button widget that is
5027 to be reconfigured. The other arguments are as specified above.
5028
5029 The adjustment can be set and retrieved independantly using the
5030 following two functions:
5031
5032 <tscreen><verb>
5033 void gtk_spin_button_set_adjustment( GtkSpinButton  *spin_button,
5034                                      GtkAdjustment  *adjustment );
5035
5036 GtkAdjustment *gtk_spin_button_get_adjustment( GtkSpinButton *spin_button );
5037 </verb></tscreen>
5038
5039 The number of decimal places can also be altered using:
5040
5041 <tscreen><verb>
5042 void gtk_spin_button_set_digits( GtkSpinButton *spin_button,
5043                                  guint          digits) ;
5044 </verb></tscreen>
5045
5046 The value that a Spin Button is currently displaying can be changed
5047 using the following function:
5048
5049 <tscreen><verb>
5050 void gtk_spin_button_set_value( GtkSpinButton *spin_button,
5051                                 gfloat         value );
5052 </verb></tscreen>
5053
5054 The current value of a Spin Button can be retrieved as either a
5055 floating point or integer value with the following functions:
5056
5057 <tscreen><verb>
5058 gfloat gtk_spin_button_get_value_as_float( GtkSpinButton *spin_button );
5059
5060 gint gtk_spin_button_get_value_as_int( GtkSpinButton *spin_button );
5061 </verb></tscreen>
5062
5063 If you want to alter the value of a Spin Value relative to its current
5064 value, then the following function can be used:
5065
5066 <tscreen><verb>
5067 void gtk_spin_button_spin( GtkSpinButton *spin_button,
5068                            GtkSpinType    direction,
5069                            gfloat         increment );
5070 </verb></tscreen>
5071
5072 The <tt/direction/ parameter can take one of the following values:
5073
5074 <tscreen><verb>
5075   GTK_SPIN_STEP_FORWARD
5076   GTK_SPIN_STEP_BACKWARD
5077   GTK_SPIN_PAGE_FORWARD
5078   GTK_SPIN_PAGE_BACKWARD
5079   GTK_SPIN_HOME
5080   GTK_SPIN_END
5081   GTK_SPIN_USER_DEFINED
5082 </verb></tscreen>
5083
5084 This function packs in quite a bit of functionality, which I will
5085 attempt to clearly explain. Many of these settings use values from the
5086 Adjustment object that is associated with a Spin Button.
5087
5088 <tt/GTK_SPIN_STEP_FORWARD/ and <tt/GTK_SPIN_STEP_BACKWARD/ change the
5089 value of the Spin Button by the amount specified by <tt/increment/,
5090 unless <tt/increment/ is equal to 0, in which case the value is
5091 changed by the value of <tt/step_increment/ in theAdjustment.
5092
5093 <tt/GTK_SPIN_PAGE_FORWARD/ and <tt/GTK_SPIN_PAGE_BACKWARD/ simply
5094 alter the value of the Spin Button by <tt/increment/.
5095
5096 <tt/GTK_SPIN_HOME/ sets the value of the Spin Button to the bottom of
5097 the Adjustments range.
5098
5099 <tt/GTK_SPIN_END/ sets the value of the Spin Button to the top of the
5100 Adjustments range.
5101
5102 <tt/GTK_SPIN_USER_DEFINED/ simply alters the value of the Spin Button
5103 by the specified amount.
5104
5105 We move away from functions for setting and retreving the range attributes
5106 of the Spin Button now, and move onto functions that affect the
5107 appearance and behaviour of the Spin Button widget itself.
5108
5109 The first of these functions is used to constrain the text box of the
5110 Spin Button such that it may only contain a numeric value. This
5111 prevents a user from typing anything other than numeric values into
5112 the text box of a Spin Button:
5113
5114 <tscreen><verb>
5115 void gtk_spin_button_set_numeric( GtkSpinButton *spin_button,
5116                                   gboolean       numeric );
5117 </verb></tscreen>
5118
5119 You can set whether a Spin Button will wrap around between the upper
5120 and lower range values with the following function:
5121
5122 <tscreen><verb>
5123 void gtk_spin_button_set_wrap( GtkSpinButton *spin_button,
5124                                gboolean       wrap );
5125 </verb></tscreen>
5126
5127 You can set a Spin Button to round the value to the nearest
5128 <tt/step_increment/, which is set within the Adjustment object used
5129 with the Spin Button. This is accomplished with the following
5130 function:
5131
5132 <tscreen><verb>
5133 void gtk_spin_button_set_snap_to_ticks( GtkSpinButton  *spin_button,
5134                                         gboolean        snap_to_ticks );
5135 </verb></tscreen>
5136
5137 The update policy of a Spin Button can be changed with the following
5138 function:
5139
5140 <tscreen><verb>
5141 void gtk_spin_button_set_update_policy( GtkSpinButton  *spin_button,
5142                                     GtkSpinButtonUpdatePolicy policy );
5143 </verb></tscreen>
5144
5145 <!-- TODO: find out what this does - TRG -->
5146
5147 The possible values of <tt/policy/ are either <tt/GTK_UPDATE_ALWAYS/ or
5148 <tt/GTK_UPDATE_IF_VALID/.
5149
5150 These policies affect the behavior of a Spin Button when parsing
5151 inserted text and syncing its value with the values of the
5152 Adjustment.
5153
5154 In the case of <tt/GTK_UPDATE_IF_VALID/ the Spin Button only value
5155 gets changed if the text input is a numeric value that is within the
5156 range specified by the Adjustment. Otherwise the text is reset to the
5157 current value.
5158
5159 In case of <tt/GTK_UPDATE_ALWAYS/ we ignore errors while converting
5160 text into a numeric value.
5161
5162 The appearance of the buttons used in a Spin Button can be changed
5163 using the following function:
5164
5165 <tscreen><verb>
5166 void gtk_spin_button_set_shadow_type( GtkSpinButton *spin_button,
5167                                       GtkShadowType  shadow_type );
5168 </verb></tscreen>
5169
5170 As usual, the <tt/shadow_type/ can be one of:
5171
5172 <tscreen><verb>
5173   GTK_SHADOW_IN
5174   GTK_SHADOW_OUT
5175   GTK_SHADOW_ETCHED_IN
5176   GTK_SHADOW_ETCHED_OUT
5177 </verb></tscreen>
5178
5179 Finally, you can explicitly request that a Spin Button update itself:
5180
5181 <tscreen><verb>
5182 void gtk_spin_button_update( GtkSpinButton  *spin_button );
5183 </verb></tscreen>
5184
5185 It's example time again.
5186
5187 <tscreen><verb>
5188 /* example-start spinbutton spinbutton.c */
5189
5190 #include <stdio.h>
5191 #include <gtk/gtk.h>
5192
5193 static GtkWidget *spinner1;
5194
5195 void toggle_snap( GtkWidget     *widget,
5196                   GtkSpinButton *spin )
5197 {
5198   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active);
5199 }
5200
5201 void toggle_numeric( GtkWidget *widget,
5202                      GtkSpinButton *spin )
5203 {
5204   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active);
5205 }
5206
5207 void change_digits( GtkWidget *widget,
5208                     GtkSpinButton *spin )
5209 {
5210   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
5211                               gtk_spin_button_get_value_as_int (spin));
5212 }
5213
5214 void get_value( GtkWidget *widget,
5215                 gpointer data )
5216 {
5217   gchar buf[32];
5218   GtkLabel *label;
5219   GtkSpinButton *spin;
5220
5221   spin = GTK_SPIN_BUTTON (spinner1);
5222   label = GTK_LABEL (gtk_object_get_user_data (GTK_OBJECT (widget)));
5223   if (GPOINTER_TO_INT (data) == 1)
5224     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
5225   else
5226     sprintf (buf, "%0.*f", spin->digits,
5227              gtk_spin_button_get_value_as_float (spin));
5228   gtk_label_set_text (label, buf);
5229 }
5230
5231
5232 int main( int   argc,
5233           char *argv[] )
5234 {
5235   GtkWidget *window;
5236   GtkWidget *frame;
5237   GtkWidget *hbox;
5238   GtkWidget *main_vbox;
5239   GtkWidget *vbox;
5240   GtkWidget *vbox2;
5241   GtkWidget *spinner2;
5242   GtkWidget *spinner;
5243   GtkWidget *button;
5244   GtkWidget *label;
5245   GtkWidget *val_label;
5246   GtkAdjustment *adj;
5247
5248   /* Initialise GTK */
5249   gtk_init(&amp;argc, &amp;argv);
5250
5251   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5252
5253   gtk_signal_connect (GTK_OBJECT (window), "destroy",
5254                       GTK_SIGNAL_FUNC (gtk_main_quit),
5255                       NULL);
5256
5257   gtk_window_set_title (GTK_WINDOW (window), "Spin Button");
5258
5259   main_vbox = gtk_vbox_new (FALSE, 5);
5260   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5261   gtk_container_add (GTK_CONTAINER (window), main_vbox);
5262   
5263   frame = gtk_frame_new ("Not accelerated");
5264   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5265   
5266   vbox = gtk_vbox_new (FALSE, 0);
5267   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5268   gtk_container_add (GTK_CONTAINER (frame), vbox);
5269   
5270   /* Day, month, year spinners */
5271   
5272   hbox = gtk_hbox_new (FALSE, 0);
5273   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5274   
5275   vbox2 = gtk_vbox_new (FALSE, 0);
5276   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5277   
5278   label = gtk_label_new ("Day :");
5279   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5280   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5281   
5282   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 31.0, 1.0,
5283                                               5.0, 0.0);
5284   spinner = gtk_spin_button_new (adj, 0, 0);
5285   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5286   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5287                                    GTK_SHADOW_OUT);
5288   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5289   
5290   vbox2 = gtk_vbox_new (FALSE, 0);
5291   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5292   
5293   label = gtk_label_new ("Month :");
5294   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5295   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5296   
5297   adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5298                                               5.0, 0.0);
5299   spinner = gtk_spin_button_new (adj, 0, 0);
5300   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5301   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5302                                    GTK_SHADOW_ETCHED_IN);
5303   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5304   
5305   vbox2 = gtk_vbox_new (FALSE, 0);
5306   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5307   
5308   label = gtk_label_new ("Year :");
5309   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5310   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5311   
5312   adj = (GtkAdjustment *) gtk_adjustment_new (1998.0, 0.0, 2100.0,
5313                                               1.0, 100.0, 0.0);
5314   spinner = gtk_spin_button_new (adj, 0, 0);
5315   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), FALSE);
5316   gtk_spin_button_set_shadow_type (GTK_SPIN_BUTTON (spinner),
5317                                    GTK_SHADOW_IN);
5318   gtk_widget_set_usize (spinner, 55, 0);
5319   gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5320   
5321   frame = gtk_frame_new ("Accelerated");
5322   gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5323   
5324   vbox = gtk_vbox_new (FALSE, 0);
5325   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5326   gtk_container_add (GTK_CONTAINER (frame), vbox);
5327   
5328   hbox = gtk_hbox_new (FALSE, 0);
5329   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5330   
5331   vbox2 = gtk_vbox_new (FALSE, 0);
5332   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5333   
5334   label = gtk_label_new ("Value :");
5335   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5336   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5337   
5338   adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
5339                                               0.5, 100.0, 0.0);
5340   spinner1 = gtk_spin_button_new (adj, 1.0, 2);
5341   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
5342   gtk_widget_set_usize (spinner1, 100, 0);
5343   gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
5344   
5345   vbox2 = gtk_vbox_new (FALSE, 0);
5346   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5347   
5348   label = gtk_label_new ("Digits :");
5349   gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5350   gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5351   
5352   adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 5, 1, 1, 0);
5353   spinner2 = gtk_spin_button_new (adj, 0.0, 0);
5354   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner2), TRUE);
5355   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
5356                       GTK_SIGNAL_FUNC (change_digits),
5357                       (gpointer) spinner2);
5358   gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
5359   
5360   hbox = gtk_hbox_new (FALSE, 0);
5361   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5362   
5363   button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
5364   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5365                       GTK_SIGNAL_FUNC (toggle_snap),
5366                       spinner1);
5367   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5368   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5369   
5370   button = gtk_check_button_new_with_label ("Numeric only input mode");
5371   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5372                       GTK_SIGNAL_FUNC (toggle_numeric),
5373                       spinner1);
5374   gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5375   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5376   
5377   val_label = gtk_label_new ("");
5378   
5379   hbox = gtk_hbox_new (FALSE, 0);
5380   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5381   button = gtk_button_new_with_label ("Value as Int");
5382   gtk_object_set_user_data (GTK_OBJECT (button), val_label);
5383   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5384                       GTK_SIGNAL_FUNC (get_value),
5385                       GINT_TO_POINTER (1));
5386   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5387   
5388   button = gtk_button_new_with_label ("Value as Float");
5389   gtk_object_set_user_data (GTK_OBJECT (button), val_label);
5390   gtk_signal_connect (GTK_OBJECT (button), "clicked",
5391                       GTK_SIGNAL_FUNC (get_value),
5392                       GINT_TO_POINTER (2));
5393   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5394   
5395   gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
5396   gtk_label_set_text (GTK_LABEL (val_label), "0");
5397   
5398   hbox = gtk_hbox_new (FALSE, 0);
5399   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5400   
5401   button = gtk_button_new_with_label ("Close");
5402   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
5403                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
5404                              GTK_OBJECT (window));
5405   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5406
5407   gtk_widget_show_all (window);
5408
5409   /* Enter the event loop */
5410   gtk_main ();
5411     
5412   return(0);
5413 }
5414 /* example-end */
5415 </verb></tscreen>
5416
5417 <!-- ----------------------------------------------------------------- -->
5418 <sect1>Combo Box
5419 <p>
5420 The combo box is another fairly simple widget that is really just a
5421 collection of other widgets. From the user's point of view, the widget
5422 consists of a text entry box and a pull down menu from which the user
5423 can select one of a set of predefined entries. Alternatively, the user
5424 can type a different option directly into the text box.
5425
5426 The following extract from the structure that defines a Combo Box
5427 identifies several of the components:
5428
5429 <tscreen><verb>
5430 struct _GtkCombo { 
5431         GtkHBox hbox; 
5432         GtkWidget *entry; 
5433         GtkWidget *button;
5434         GtkWidget *popup; 
5435         GtkWidget *popwin; 
5436         GtkWidget *list;
5437         ...  };
5438 </verb></tscreen>
5439
5440 As you can see, the Combo Box has two principal parts that you really
5441 care about: an entry and a list.
5442
5443 First off, to create a combo box, use:
5444
5445 <tscreen><verb>
5446 GtkWidget *gtk_combo_new( void );
5447 </verb></tscreen>
5448
5449 Now, if you want to set the string in the entry section of the combo
5450 box, this is done by manipulating the <tt/entry/ widget directly:
5451
5452 <tscreen><verb>
5453     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), "My String.");
5454 </verb></tscreen>
5455
5456 To set the values in the popdown list, one uses the function:
5457
5458 <tscreen><verb>
5459 void gtk_combo_set_popdown_strings( GtkCombo *combo,
5460                                     GList    *strings );
5461 </verb></tscreen>
5462
5463 Before you can do this, you have to assemble a GList of the strings
5464 that you want. GList is a linked list implementation that is part of
5465 <ref id="sec_glib" name="GLib">, a library supporing GTK. For the
5466 moment, the quick and dirty explanation is that you need to set up a
5467 GList pointer, set it equal to NULL, then append strings to it with
5468
5469 <tscreen><verb>
5470 GList *g_list_append( GList *glist, 
5471                       gpointer data );
5472 </verb></tscreen>
5473
5474 It is important that you set the initial GList pointer to NULL. The
5475 value returned from the g_list_append function must be used as the new
5476 pointer to the GList.
5477
5478 Here's a typical code segment for creating a set of options:
5479
5480 <tscreen><verb>
5481     GList *glist=NULL;
5482
5483     glist = g_list_append(glist, "String 1");
5484     glist = g_list_append(glist, "String 2");
5485     glist = g_list_append(glist, "String 3"); 
5486     glist = g_list_append(glist, "String 4");
5487
5488     gtk_combo_set_popdown_strings( GTK_COMBO(combo), glist) ;
5489 </verb></tscreen>
5490
5491 The combo widget makes a copy of the strings passed to it in the glist
5492 structure. As a result, you need to make sure you free the memory used
5493 by the list if that is appropriate for your application.
5494
5495 At this point you have a working combo box that has been set up.
5496 There are a few aspects of its behavior that you can change. These
5497 are accomplished with the functions: 
5498
5499 <tscreen><verb>
5500 void gtk_combo_set_use_arrows( GtkCombo *combo,
5501                                gint      val );
5502
5503 void gtk_combo_set_use_arrows_always( GtkCombo *combo,
5504                                       gint      val );
5505
5506 void gtk_combo_set_case_sensitive( GtkCombo *combo,
5507                                    gint      val );
5508 </verb></tscreen>
5509
5510 <tt/gtk_combo_set_use_arrows()/ lets the user change the value in the
5511 entry using the up/down arrow keys. This doesn't bring up the list, but
5512 rather replaces the current text in the entry with the next list entry
5513 (up or down, as your key choice indicates). It does this by searching
5514 in the list for the item corresponding to the current value in the
5515 entry and selecting the previous/next item accordingly. Usually in an
5516 entry the arrow keys are used to change focus (you can do that anyway
5517 using TAB). Note that when the current item is the last of the list
5518 and you press arrow-down it changes the focus (the same applies with
5519 the first item and arrow-up).
5520
5521 If the current value in the entry is not in the list, then the
5522 function of <tt/gtk_combo_set_use_arrows()/ is disabled.
5523
5524 <tt/gtk_combo_set_use_arrows_always()/ similarly allows the use the
5525 the up/down arrow keys to cycle through the choices in the dropdown
5526 list, except that it wraps around the values in the list, completely
5527 disabling the use of the up and down arrow keys for changing focus.
5528
5529 <tt/gtk_combo_set_case_sensitive()/ toggles whether or not GTK
5530 searches for entries in a case sensitive manner. This is used when the
5531 Combo widget is asked to find a value from the list using the current
5532 entry in the text box. This completion can be performed in either a
5533 case sensitive or insensitive manner, depending upon the use of this
5534 function. The Combo widget can also simply complete the current entry
5535 if the user presses the key combination MOD-1 and "Tab". MOD-1 is
5536 often mapped to the "Alt" key, by the <tt/xmodmap/ utility. Note,
5537 however that some window managers also use this key combination, which
5538 will override its use within GTK.
5539
5540 Now that we have a combo box, tailored to look and act how we want it,
5541 all that remains is being able to get data from the combo box. This is
5542 relatively straightforward. The majority of the time, all you are
5543 going to care about getting data from is the entry. The entry is
5544 accessed simply by <tt>GTK_ENTRY(GTK_COMBO(combo)->entry)</tt>. The
5545 two principal things that you are going to want to do with it are
5546 attach to the activate signal, which indicates that the user has
5547 pressed the Return or Enter key, and read the text. The first is
5548 accomplished using something like:
5549
5550 <tscreen><verb>
5551     gtk_signal_connect(GTK_OBJECT(GTK_COMB(combo)->entry), "activate",
5552                        GTK_SIGNAL_FUNC (my_callback_function), my_data);
5553 </verb></tscreen>
5554
5555 Getting the text at any arbitrary time is accomplished by simply using
5556 the entry function:
5557
5558 <tscreen><verb>
5559 gchar *gtk_entry_get_text(GtkEntry *entry);
5560 </verb></tscreen>
5561
5562 Such as:
5563
5564 <tscreen><verb>
5565     char *string;
5566
5567     string = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry));
5568 </verb></tscreen>
5569
5570 That's about all there is to it. There is a function
5571
5572 <tscreen><verb>
5573 void gtk_combo_disable_activate(GtkCombo *combo);
5574 </verb></tscreen>
5575
5576 that will disable the activate signal on the entry widget in the combo
5577 box. Personally, I can't think of why you'd want to use it, but it
5578 does exist.
5579
5580 <!-- There is also a function to set the string on a particular item, void
5581 gtk_combo_set_item_string(GtkCombo *combo, GtkItem *item, const gchar
5582 *item_value), but this requires that you have a pointer to the
5583 appropriate Item. Frankly, I have no idea how to do that.
5584 -->
5585
5586 <!-- ----------------------------------------------------------------- -->
5587 <sect1> Calendar
5588 <p>
5589 The Calendar widget is an effective way to display and retrieve
5590 monthly date related information. It is a very simple widget to create
5591 and work with.
5592
5593 Creating a GtkCalendar widget is a simple as: 
5594
5595 <tscreen><verb>
5596 GtkWidget *gtk_calendar_new();
5597 </verb></tscreen>
5598
5599 There might be times where you need to change a lot of information
5600 within this widget and the following functions allow you to make
5601 multiple change to a Calendar widget without the user seeing multiple
5602 on-screen updates.
5603
5604 <tscreen><verb>
5605 void gtk_calendar_freeze( GtkCalendar *Calendar );
5606
5607 void gtk_calendar_thaw  ( GtkCalendar *Calendar );
5608 </verb></tscreen>
5609
5610 They work just like the freeze/thaw functions of every other
5611 widget.
5612
5613 The Calendar widget has a few options that allow you to change the way
5614 the widget both looks and operates by using the function
5615
5616 <tscreen><verb>
5617 void gtk_calendar_display_options( GtkCalendar               *calendar,
5618                                    GtkCalendarDisplayOptions  flags );
5619 </verb></tscreen>
5620
5621 The <tt/flags/ argument can be formed by combining either of the
5622 following five options using the logical bitwise OR (|) operation:
5623 <itemize>
5624 <item> GTK_CALENDAR_SHOW_HEADING - this option specifies that
5625 the month and year should be shown when drawing the calendar.
5626 <item> GTK_CALENDAR_SHOW_DAY_NAMES - this option specifies that the
5627 three letter descriptions should be displayed for each day (eg
5628 MON,TUE...).
5629
5630 <item> GTK_CALENDAR_NO_MONTH_CHANGE - this option states that the user
5631 should not and can not change the currently displayed month. This can
5632 be good if you only need to display a particular month such as if you
5633 are displaying 12 calendar widgets for every month in a particular
5634 year.
5635
5636 <item> GTK_CALENDAR_SHOW_WEEK_NUMBERS - this option specifies that the
5637 number for each week should be displayed down the left side of the
5638 calendar. (eg. Jan 1 = Week 1,Dec 31 = Week 52).
5639
5640 <item> GTK_CALENDAR_WEEK_START_MONDAY - this option states that the
5641 calander week will start on Monday instead of Sunday which is the
5642 default. This only affects the order in which days are displayed from
5643 left to right.
5644 </itemize>
5645
5646 The following functions are used to set the the currently displayed
5647 date:
5648 <tscreen><verb>
5649 gint gtk_calendar_select_month( GtkCalendar *calendar, 
5650                                 guint        month,
5651                                 guint        year );
5652
5653 void gtk_calendar_select_day( GtkCalendar *calendar,
5654                               guint        day );
5655 </verb></tscreen>
5656
5657 The return value from <tt/gtk_calendar_select_month()/ is a boolean
5658 value indicating whether the selection was successful.
5659
5660 With <tt/gtk_calendar_select_day()/ the specified day number is
5661 selected within the current month, if that is possible. A
5662 <tt/day/ value of 0 will deselect any current selection.
5663
5664 In addition to having a day selected, any number of days in the month
5665 may be "marked". A marked day is highlighted within the calendar
5666 display. The following functions are provided to manipulate marked
5667 days:
5668
5669 <tscreen><verb>
5670 gint gtk_calendar_mark_day( GtkCalendar *calendar,
5671                             guint        day);
5672
5673 gint gtk_calendar_unmark_day( GtkCalendar *calendar,
5674                               guint        day);
5675
5676 void gtk_calendar_clear_marks( GtkCalendar *calendar);
5677 </verb></tscreen>
5678
5679 The currently marked days are stored within an array within the
5680 GtkCalendar structure. This array is 31 elements long so to test
5681 whether a particular day is currently marked, you need to access the
5682 corresponding element of the array (don't forget in C that array
5683 elements are numbered 0 to n-1). For example:
5684
5685 <tscreen><verb>
5686     GtkCalendar *calendar;
5687     calendar = gtk_calendar_new();
5688
5689     ...
5690
5691     /* Is day 7 marked? */
5692     if (calendar->marked_date[7-1])
5693        /* day is marked */
5694 </verb></tscreen>
5695
5696 Note that marks are persistent across month and year changes.
5697
5698 The final Calendar widget function is used to retrieve the currently
5699 selected date, month and/or year.
5700
5701 <tscreen><verb>
5702 void gtk_calendar_get_date( GtkCalendar *calendar, 
5703                             guint       *year,
5704                             guint       *month,
5705                             guint       *day );
5706 </verb></tscreen>
5707
5708 This function requires you to pass the addresses of <tt/guint/
5709 variables, into which the result will be placed. Passing <tt/NULL/ as
5710 a value will result in the corresponding value not being returned.
5711
5712 The Calendar widget can generate a number of signals indicating date
5713 selection and change. The names of these signals are self explanatory,
5714 and are:
5715
5716 <itemize>
5717 <item> <tt/month_changed/
5718 <item> <tt/day_selected/
5719 <item> <tt/day_selected_double_click/
5720 <item> <tt/prev_month/
5721 <item> <tt/next_month/
5722 <item> <tt/prev_year/
5723 <item> <tt/next_year/
5724 </itemize>
5725
5726 That just leaves us with the need to put all of this together into
5727 example code.
5728
5729 <tscreen><verb> 
5730 /* example-start calendar calendar.c */
5731 /*
5732  * Copyright (C) 1998 Cesar Miquel, Shawn T. Amundson, Mattias Grönlund
5733  * Copyright (C) 2000 Tony Gale
5734  *
5735  * This program is free software; you can redistribute it and/or modify
5736  * it under the terms of the GNU General Public License as published by
5737  * the Free Software Foundation; either version 2 of the License, or
5738  * (at your option) any later version.
5739  *
5740  * This program is distributed in the hope that it will be useful,
5741  * but WITHOUT ANY WARRANTY; without even the implied warranty of
5742  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5743  * GNU General Public License for more details.
5744  *
5745  * You should have received a copy of the GNU General Public License
5746  * along with this program; if not, write to the Free Software
5747  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5748  */
5749
5750 #include <gtk/gtk.h>
5751 #include <stdio.h>
5752 #include <string.h>
5753 #include <time.h>
5754
5755 #define DEF_PAD 10
5756 #define DEF_PAD_SMALL 5
5757
5758 #define TM_YEAR_BASE 1900
5759
5760 typedef struct _CalendarData {
5761   GtkWidget *flag_checkboxes[5];
5762   gboolean  settings[5];
5763   gchar     *font;
5764   GtkWidget *font_dialog;
5765   GtkWidget *window;
5766   GtkWidget *prev2_sig;
5767   GtkWidget *prev_sig;
5768   GtkWidget *last_sig;
5769   GtkWidget *month;
5770 } CalendarData;
5771
5772 enum {
5773   calendar_show_header,
5774   calendar_show_days,
5775   calendar_month_change, 
5776   calendar_show_week,
5777   calendar_monday_first
5778 };
5779
5780 /*
5781  * GtkCalendar
5782  */
5783
5784 void calendar_date_to_string( CalendarData *data,
5785                               char         *buffer,
5786                               gint          buff_len )
5787 {
5788   struct tm tm;
5789   time_t time;
5790
5791   memset (&amp;tm, 0, sizeof (tm));
5792   gtk_calendar_get_date (GTK_CALENDAR(data->window),
5793                          &amp;tm.tm_year, &amp;tm.tm_mon, &amp;tm.tm_mday);
5794   tm.tm_year -= TM_YEAR_BASE;
5795   time = mktime(&amp;tm);
5796   strftime (buffer, buff_len-1, "%x", gmtime(&amp;time));
5797 }
5798
5799 void calendar_set_signal_strings( char         *sig_str,
5800                                   CalendarData *data)
5801 {
5802   gchar *prev_sig;
5803
5804   gtk_label_get (GTK_LABEL (data->prev_sig), &amp;prev_sig);
5805   gtk_label_set (GTK_LABEL (data->prev2_sig), prev_sig);
5806
5807   gtk_label_get (GTK_LABEL (data->last_sig), &amp;prev_sig);
5808   gtk_label_set (GTK_LABEL (data->prev_sig), prev_sig);
5809   gtk_label_set (GTK_LABEL (data->last_sig), sig_str);
5810 }
5811
5812 void calendar_month_changed( GtkWidget    *widget,
5813                              CalendarData *data )
5814 {
5815   char buffer[256] = "month_changed: ";
5816
5817   calendar_date_to_string (data, buffer+15, 256-15);
5818   calendar_set_signal_strings (buffer, data);
5819 }
5820
5821 void calendar_day_selected( GtkWidget    *widget,
5822                             CalendarData *data )
5823 {
5824   char buffer[256] = "day_selected: ";
5825
5826   calendar_date_to_string (data, buffer+14, 256-14);
5827   calendar_set_signal_strings (buffer, data);
5828 }
5829
5830 void calendar_day_selected_double_click( GtkWidget    *widget,
5831                                          CalendarData *data )
5832 {
5833   struct tm tm;
5834   char buffer[256] = "day_selected_double_click: ";
5835
5836   calendar_date_to_string (data, buffer+27, 256-27);
5837   calendar_set_signal_strings (buffer, data);
5838
5839   memset (&amp;tm, 0, sizeof (tm));
5840   gtk_calendar_get_date (GTK_CALENDAR(data->window),
5841                          &amp;tm.tm_year, &amp;tm.tm_mon, &amp;tm.tm_mday);
5842   tm.tm_year -= TM_YEAR_BASE;
5843
5844   if(GTK_CALENDAR(data->window)->marked_date[tm.tm_mday-1] == 0) {
5845     gtk_calendar_mark_day(GTK_CALENDAR(data->window),tm.tm_mday);
5846   } else { 
5847     gtk_calendar_unmark_day(GTK_CALENDAR(data->window),tm.tm_mday);
5848   }
5849 }
5850
5851 void calendar_prev_month( GtkWidget    *widget,
5852                             CalendarData *data )
5853 {
5854   char buffer[256] = "prev_month: ";
5855
5856   calendar_date_to_string (data, buffer+12, 256-12);
5857   calendar_set_signal_strings (buffer, data);
5858 }
5859
5860 void calendar_next_month( GtkWidget    *widget,
5861                             CalendarData *data )
5862 {
5863   char buffer[256] = "next_month: ";
5864
5865   calendar_date_to_string (data, buffer+12, 256-12);
5866   calendar_set_signal_strings (buffer, data);
5867 }
5868
5869 void calendar_prev_year( GtkWidget    *widget,
5870                             CalendarData *data )
5871 {
5872   char buffer[256] = "prev_year: ";
5873
5874   calendar_date_to_string (data, buffer+11, 256-11);
5875   calendar_set_signal_strings (buffer, data);
5876 }
5877
5878 void calendar_next_year( GtkWidget    *widget,
5879                             CalendarData *data )
5880 {
5881   char buffer[256] = "next_year: ";
5882
5883   calendar_date_to_string (data, buffer+11, 256-11);
5884   calendar_set_signal_strings (buffer, data);
5885 }
5886
5887
5888 void calendar_set_flags( CalendarData *calendar )
5889 {
5890   gint i;
5891   gint options=0;
5892   for (i=0;i<5;i++) 
5893     if (calendar->settings[i])
5894       {
5895         options=options + (1<<i);
5896       }
5897   if (calendar->window)
5898     gtk_calendar_display_options (GTK_CALENDAR (calendar->window), options);
5899 }
5900
5901 void calendar_toggle_flag( GtkWidget    *toggle,
5902                            CalendarData *calendar )
5903 {
5904   gint i;
5905   gint j;
5906   j=0;
5907   for (i=0; i<5; i++)
5908     if (calendar->flag_checkboxes[i] == toggle)
5909       j = i;
5910
5911   calendar->settings[j]=!calendar->settings[j];
5912   calendar_set_flags(calendar);
5913   
5914 }
5915
5916 void calendar_font_selection_ok( GtkWidget    *button,
5917                                  CalendarData *calendar )
5918 {
5919   GtkStyle *style;
5920   GdkFont  *font;
5921
5922   calendar->font = gtk_font_selection_dialog_get_font_name(
5923                         GTK_FONT_SELECTION_DIALOG (calendar->font_dialog));
5924   if (calendar->window)
5925     {
5926       font = gtk_font_selection_dialog_get_font(GTK_FONT_SELECTION_DIALOG(calendar->font_dialog));
5927       if (font) 
5928         {
5929           style = gtk_style_copy (gtk_widget_get_style (calendar->window));
5930           gdk_font_unref (style->font);
5931           style->font = font;
5932           gdk_font_ref (style->font);
5933           gtk_widget_set_style (calendar->window, style);
5934         }
5935     }
5936 }
5937
5938 void calendar_select_font( GtkWidget    *button,
5939                            CalendarData *calendar )
5940 {
5941   GtkWidget *window;
5942
5943   if (!calendar->font_dialog) {
5944     window = gtk_font_selection_dialog_new ("Font Selection Dialog");
5945     g_return_if_fail(GTK_IS_FONT_SELECTION_DIALOG(window));
5946     calendar->font_dialog = window;
5947     
5948     gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
5949     
5950     gtk_signal_connect (GTK_OBJECT (window), "destroy",
5951                         GTK_SIGNAL_FUNC (gtk_widget_destroyed),
5952                         &amp;calendar->font_dialog);
5953     
5954     gtk_signal_connect (GTK_OBJECT (GTK_FONT_SELECTION_DIALOG (window)->ok_button),
5955                         "clicked", GTK_SIGNAL_FUNC(calendar_font_selection_ok),
5956                         calendar);
5957     gtk_signal_connect_object (GTK_OBJECT (GTK_FONT_SELECTION_DIALOG (window)->cancel_button),
5958                                "clicked",
5959                                GTK_SIGNAL_FUNC (gtk_widget_destroy), 
5960                                GTK_OBJECT (calendar->font_dialog));
5961   }
5962   window=calendar->font_dialog;
5963   if (!GTK_WIDGET_VISIBLE (window))
5964     gtk_widget_show (window);
5965   else
5966     gtk_widget_destroy (window);
5967
5968 }
5969
5970 void create_calendar()
5971 {
5972   GtkWidget *window;
5973   GtkWidget *vbox, *vbox2, *vbox3;
5974   GtkWidget *hbox;
5975   GtkWidget *hbbox;
5976   GtkWidget *calendar;
5977   GtkWidget *toggle;
5978   GtkWidget *button;
5979   GtkWidget *frame;
5980   GtkWidget *separator;
5981   GtkWidget *label;
5982   GtkWidget *bbox;
5983   static CalendarData calendar_data;
5984   gint i;
5985   
5986   struct {
5987     char *label;
5988   } flags[] =
5989     {
5990       { "Show Heading" },
5991       { "Show Day Names" },
5992       { "No Month Change" },
5993       { "Show Week Numbers" },
5994       { "Week Start Monday" }
5995     };
5996
5997   
5998   calendar_data.window = NULL;
5999   calendar_data.font = NULL;
6000   calendar_data.font_dialog = NULL;
6001
6002   for (i=0; i<5; i++) {
6003     calendar_data.settings[i]=0;
6004   }
6005
6006   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6007   gtk_window_set_title(GTK_WINDOW(window), "GtkCalendar Example");
6008   gtk_container_border_width (GTK_CONTAINER (window), 5);
6009   gtk_signal_connect(GTK_OBJECT(window), "destroy",
6010                      GTK_SIGNAL_FUNC(gtk_main_quit),
6011                      NULL);
6012   gtk_signal_connect(GTK_OBJECT(window), "delete-event",
6013                      GTK_SIGNAL_FUNC(gtk_false),
6014                      NULL);
6015
6016   gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, TRUE);
6017
6018   vbox = gtk_vbox_new(FALSE, DEF_PAD);
6019   gtk_container_add (GTK_CONTAINER (window), vbox);
6020
6021   /*
6022    * The top part of the window, Calendar, flags and fontsel.
6023    */
6024
6025   hbox = gtk_hbox_new(FALSE, DEF_PAD);
6026   gtk_box_pack_start (GTK_BOX(vbox), hbox, TRUE, TRUE, DEF_PAD);
6027   hbbox = gtk_hbutton_box_new();
6028   gtk_box_pack_start(GTK_BOX(hbox), hbbox, FALSE, FALSE, DEF_PAD);
6029   gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox), GTK_BUTTONBOX_SPREAD);
6030   gtk_button_box_set_spacing(GTK_BUTTON_BOX(hbbox), 5);
6031
6032   /* Calendar widget */
6033   frame = gtk_frame_new("Calendar");
6034   gtk_box_pack_start(GTK_BOX(hbbox), frame, FALSE, TRUE, DEF_PAD);
6035   calendar=gtk_calendar_new();
6036   calendar_data.window = calendar;
6037   calendar_set_flags(&amp;calendar_data);
6038   gtk_calendar_mark_day ( GTK_CALENDAR(calendar), 19);  
6039   gtk_container_add( GTK_CONTAINER( frame), calendar);
6040   gtk_signal_connect (GTK_OBJECT (calendar), "month_changed", 
6041                       GTK_SIGNAL_FUNC (calendar_month_changed),
6042                       &amp;calendar_data);
6043   gtk_signal_connect (GTK_OBJECT (calendar), "day_selected", 
6044                       GTK_SIGNAL_FUNC (calendar_day_selected),
6045                       &amp;calendar_data);
6046   gtk_signal_connect (GTK_OBJECT (calendar), "day_selected_double_click", 
6047                       GTK_SIGNAL_FUNC (calendar_day_selected_double_click),
6048                       &amp;calendar_data);
6049   gtk_signal_connect (GTK_OBJECT (calendar), "prev_month", 
6050                       GTK_SIGNAL_FUNC (calendar_prev_month),
6051                       &amp;calendar_data);
6052   gtk_signal_connect (GTK_OBJECT (calendar), "next_month", 
6053                       GTK_SIGNAL_FUNC (calendar_next_month),
6054                       &amp;calendar_data);
6055   gtk_signal_connect (GTK_OBJECT (calendar), "prev_year", 
6056                       GTK_SIGNAL_FUNC (calendar_prev_year),
6057                       &amp;calendar_data);
6058   gtk_signal_connect (GTK_OBJECT (calendar), "next_year", 
6059                       GTK_SIGNAL_FUNC (calendar_next_year),
6060                       &amp;calendar_data);
6061
6062
6063   separator = gtk_vseparator_new ();
6064   gtk_box_pack_start (GTK_BOX (hbox), separator, FALSE, TRUE, 0);
6065
6066   vbox2 = gtk_vbox_new(FALSE, DEF_PAD);
6067   gtk_box_pack_start(GTK_BOX(hbox), vbox2, FALSE, FALSE, DEF_PAD);
6068   
6069   /* Build the Right frame with the flags in */ 
6070
6071   frame = gtk_frame_new("Flags");
6072   gtk_box_pack_start(GTK_BOX(vbox2), frame, TRUE, TRUE, DEF_PAD);
6073   vbox3 = gtk_vbox_new(TRUE, DEF_PAD_SMALL);
6074   gtk_container_add(GTK_CONTAINER(frame), vbox3);
6075
6076   for (i = 0; i < 5; i++)
6077     {
6078       toggle = gtk_check_button_new_with_label(flags[i].label);
6079       gtk_signal_connect (GTK_OBJECT (toggle),
6080                             "toggled",
6081                             GTK_SIGNAL_FUNC(calendar_toggle_flag),
6082                             &amp;calendar_data);
6083       gtk_box_pack_start (GTK_BOX (vbox3), toggle, TRUE, TRUE, 0);
6084       calendar_data.flag_checkboxes[i]=toggle;
6085     }
6086   /* Build the right font-button */ 
6087   button = gtk_button_new_with_label("Font...");
6088   gtk_signal_connect (GTK_OBJECT (button),
6089                       "clicked",
6090                       GTK_SIGNAL_FUNC(calendar_select_font),
6091                       &amp;calendar_data);
6092   gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
6093
6094   /*
6095    *  Build the Signal-event part.
6096    */
6097
6098   frame = gtk_frame_new("Signal events");
6099   gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, DEF_PAD);
6100
6101   vbox2 = gtk_vbox_new(TRUE, DEF_PAD_SMALL);
6102   gtk_container_add(GTK_CONTAINER(frame), vbox2);
6103   
6104   hbox = gtk_hbox_new (FALSE, 3);
6105   gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
6106   label = gtk_label_new ("Signal:");
6107   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6108   calendar_data.last_sig = gtk_label_new ("");
6109   gtk_box_pack_start (GTK_BOX (hbox), calendar_data.last_sig, FALSE, TRUE, 0);
6110
6111   hbox = gtk_hbox_new (FALSE, 3);
6112   gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
6113   label = gtk_label_new ("Previous signal:");
6114   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6115   calendar_data.prev_sig = gtk_label_new ("");
6116   gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev_sig, FALSE, TRUE, 0);
6117
6118   hbox = gtk_hbox_new (FALSE, 3);
6119   gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
6120   label = gtk_label_new ("Second previous signal:");
6121   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6122   calendar_data.prev2_sig = gtk_label_new ("");
6123   gtk_box_pack_start (GTK_BOX (hbox), calendar_data.prev2_sig, FALSE, TRUE, 0);
6124
6125   bbox = gtk_hbutton_box_new ();
6126   gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0);
6127   gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
6128
6129   button = gtk_button_new_with_label ("Close");
6130   gtk_signal_connect (GTK_OBJECT (button), "clicked", 
6131                       GTK_SIGNAL_FUNC (gtk_main_quit), 
6132                       NULL);
6133   gtk_container_add (GTK_CONTAINER (bbox), button);
6134   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
6135   gtk_widget_grab_default (button);
6136
6137   gtk_widget_show_all(window);
6138 }
6139
6140
6141 int main(int   argc,
6142          char *argv[] )
6143 {
6144   gtk_set_locale ();
6145   gtk_init (&amp;argc, &amp;argv);
6146
6147   create_calendar();
6148
6149   gtk_main();
6150
6151   return(0);
6152 }
6153 /* example-end */
6154 </verb></tscreen>
6155
6156
6157
6158 <!-- ----------------------------------------------------------------- -->
6159 <sect1> Color Selection
6160 <p>
6161 The color selection widget is, not surprisingly, a widget for
6162 interactive selection of colors. This composite widget lets the user
6163 select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue,
6164 Saturation, Value) triples.  This is done either by adjusting single
6165 values with sliders or entries, or by picking the desired color from a
6166 hue-saturation wheel/value bar.  Optionally, the opacity of the color
6167 can also be set.
6168
6169 The color selection widget currently emits only one signal,
6170 "color_changed", which is emitted whenever the current color in the
6171 widget changes, either when the user changes it or if it's set
6172 explicitly through gtk_color_selection_set_color().
6173
6174 Lets have a look at what the color selection widget has to offer
6175 us. The widget comes in two flavours: gtk_color_selection and
6176 gtk_color_selection_dialog.
6177
6178 <tscreen><verb>
6179 GtkWidget *gtk_color_selection_new( void );
6180 </verb></tscreen>
6181         
6182 You'll probably not be using this constructor directly. It creates an
6183 orphan ColorSelection widget which you'll have to parent
6184 yourself. The ColorSelection widget inherits from the VBox
6185 widget.
6186
6187 <tscreen><verb> 
6188 GtkWidget *gtk_color_selection_dialog_new( const gchar *title );
6189 </verb></tscreen>
6190
6191 This is the most common color selection constructor. It creates a
6192 ColorSelectionDialog. It consists of a Frame containing a
6193 ColorSelection widget, an HSeparator and an HBox with three buttons,
6194 "Ok", "Cancel" and "Help". You can reach these buttons by accessing
6195 the "ok_button", "cancel_button" and "help_button" widgets in the
6196 ColorSelectionDialog structure,
6197 (i.e., <tt>GTK_COLOR_SELECTION_DIALOG(colorseldialog)->ok_button</tt>)).
6198
6199 <tscreen><verb>
6200 void gtk_color_selection_set_update_policy( GtkColorSelection *colorsel, 
6201                                             GtkUpdateType      policy );
6202 </verb></tscreen>
6203
6204 This function sets the update policy. The default policy is
6205 <tt/GTK_UPDATE_CONTINUOUS/ which means that the current color is
6206 updated continuously when the user drags the sliders or presses the
6207 mouse and drags in the hue-saturation wheel or value bar. If you
6208 experience performance problems, you may want to set the policy to
6209 <tt/GTK_UPDATE_DISCONTINUOUS/ or <tt/GTK_UPDATE_DELAYED/.
6210
6211 <tscreen><verb>
6212 void gtk_color_selection_set_opacity( GtkColorSelection *colorsel,
6213                                       gint               use_opacity );
6214 </verb></tscreen>
6215
6216 The color selection widget supports adjusting the opacity of a color
6217 (also known as the alpha channel). This is disabled by
6218 default. Calling this function with use_opacity set to TRUE enables
6219 opacity. Likewise, use_opacity set to FALSE will disable opacity.
6220
6221 <tscreen><verb>
6222 void gtk_color_selection_set_color( GtkColorSelection *colorsel,
6223                                     gdouble           *color );
6224 </verb></tscreen>
6225
6226 You can set the current color explicitly by calling this function with
6227 a pointer to an array of colors (gdouble). The length of the array
6228 depends on whether opacity is enabled or not. Position 0 contains the
6229 red component, 1 is green, 2 is blue and opacity is at position 3
6230 (only if opacity is enabled, see
6231 gtk_color_selection_set_opacity()). All values are between 0.0 and
6232 1.0.
6233
6234 <tscreen><verb>
6235 void gtk_color_selection_get_color( GtkColorSelection *colorsel,
6236                                     gdouble           *color );
6237 </verb></tscreen>
6238
6239 When you need to query the current color, typically when you've
6240 received a "color_changed" signal, you use this function. Color is a
6241 pointer to the array of colors to fill in. See the
6242 gtk_color_selection_set_color() function for the description of this
6243 array.
6244
6245 <!-- Need to do a whole section on DnD - TRG
6246 Drag and drop
6247 -------------
6248
6249 The color sample areas (right under the hue-saturation wheel) supports
6250 drag and drop. The type of drag and drop is "application/x-color". The
6251 message data consists of an array of 4 (or 5 if opacity is enabled)
6252 gdouble values, where the value at position 0 is 0.0 (opacity on) or
6253 1.0 (opacity off) followed by the red, green and blue values at
6254 positions 1,2 and 3 respectively.  If opacity is enabled, the opacity
6255 is passed in the value at position 4.
6256 -->
6257
6258 Here's a simple example demonstrating the use of the
6259 ColorSelectionDialog. The program displays a window containing a
6260 drawing area. Clicking on it opens a color selection dialog, and
6261 changing the color in the color selection dialog changes the
6262 background color.
6263
6264 <tscreen><verb>
6265 /* example-start colorsel colorsel.c */
6266
6267 #include <glib.h>
6268 #include <gdk/gdk.h>
6269 #include <gtk/gtk.h>
6270
6271 GtkWidget *colorseldlg = NULL;
6272 GtkWidget *drawingarea = NULL;
6273
6274 /* Color changed handler */
6275
6276 void color_changed_cb( GtkWidget         *widget,
6277                        GtkColorSelection *colorsel )
6278 {
6279   gdouble color[3];
6280   GdkColor gdk_color;
6281   GdkColormap *colormap;
6282
6283   /* Get drawingarea colormap */
6284
6285   colormap = gdk_window_get_colormap (drawingarea->window);
6286
6287   /* Get current color */
6288
6289   gtk_color_selection_get_color (colorsel,color);
6290
6291   /* Fit to a unsigned 16 bit integer (0..65535) and
6292    * insert into the GdkColor structure */
6293
6294   gdk_color.red = (guint16)(color[0]*65535.0);
6295   gdk_color.green = (guint16)(color[1]*65535.0);
6296   gdk_color.blue = (guint16)(color[2]*65535.0);
6297
6298   /* Allocate color */
6299
6300   gdk_color_alloc (colormap, &amp;gdk_color);
6301
6302   /* Set window background color */
6303
6304   gdk_window_set_background (drawingarea->window, &amp;gdk_color);
6305
6306   /* Clear window */
6307
6308   gdk_window_clear (drawingarea->window);
6309 }
6310
6311 /* Drawingarea event handler */
6312
6313 gint area_event( GtkWidget *widget,
6314                  GdkEvent  *event,
6315                  gpointer   client_data )
6316 {
6317   gint handled = FALSE;
6318   GtkWidget *colorsel;
6319
6320   /* Check if we've received a button pressed event */
6321
6322   if (event->type == GDK_BUTTON_PRESS &amp;&amp; colorseldlg == NULL)
6323     {
6324       /* Yes, we have an event and there's no colorseldlg yet! */
6325
6326       handled = TRUE;
6327
6328       /* Create color selection dialog */
6329
6330       colorseldlg = gtk_color_selection_dialog_new("Select background color");
6331
6332       /* Get the ColorSelection widget */
6333
6334       colorsel = GTK_COLOR_SELECTION_DIALOG(colorseldlg)->colorsel;
6335
6336       /* Connect to the "color_changed" signal, set the client-data
6337        * to the colorsel widget */
6338
6339       gtk_signal_connect(GTK_OBJECT(colorsel), "color_changed",
6340         (GtkSignalFunc)color_changed_cb, (gpointer)colorsel);
6341
6342       /* Show the dialog */
6343
6344       gtk_widget_show(colorseldlg);
6345     }
6346
6347   return handled;
6348 }
6349
6350 /* Close down and exit handler */
6351
6352 gint destroy_window( GtkWidget *widget,
6353                      GdkEvent  *event,
6354                      gpointer   client_data )
6355 {
6356   gtk_main_quit ();
6357   return(TRUE);
6358 }
6359
6360 /* Main */
6361
6362 gint main( gint   argc,
6363            gchar *argv[] )
6364 {
6365   GtkWidget *window;
6366
6367   /* Initialize the toolkit, remove gtk-related commandline stuff */
6368
6369   gtk_init (&amp;argc,&amp;argv);
6370
6371   /* Create toplevel window, set title and policies */
6372
6373   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6374   gtk_window_set_title (GTK_WINDOW(window), "Color selection test");
6375   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, TRUE);
6376
6377   /* Attach to the "delete" and "destroy" events so we can exit */
6378
6379   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
6380     (GtkSignalFunc)destroy_window, (gpointer)window);
6381   
6382   /* Create drawingarea, set size and catch button events */
6383
6384   drawingarea = gtk_drawing_area_new ();
6385
6386   gtk_drawing_area_size (GTK_DRAWING_AREA(drawingarea), 200, 200);
6387
6388   gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
6389
6390   gtk_signal_connect (GTK_OBJECT(drawingarea), "event", 
6391     (GtkSignalFunc)area_event, (gpointer)drawingarea);
6392   
6393   /* Add drawingarea to window, then show them both */
6394
6395   gtk_container_add (GTK_CONTAINER(window), drawingarea);
6396
6397   gtk_widget_show (drawingarea);
6398   gtk_widget_show (window);
6399   
6400   /* Enter the gtk main loop (this never returns) */
6401
6402   gtk_main ();
6403
6404   /* Satisfy grumpy compilers */
6405
6406   return(0);
6407 }
6408 /* example-end */
6409 </verb></tscreen>
6410
6411 <!-- ----------------------------------------------------------------- -->
6412 <sect1> File Selections
6413 <p>
6414 The file selection widget is a quick and simple way to display a File
6415 dialog box. It comes complete with Ok, Cancel, and Help buttons, a
6416 great way to cut down on programming time.
6417
6418 To create a new file selection box use:
6419
6420 <tscreen><verb>
6421 GtkWidget *gtk_file_selection_new( gchar *title );
6422 </verb></tscreen>
6423
6424 To set the filename, for example to bring up a specific directory, or
6425 give a default filename, use this function:
6426
6427 <tscreen><verb>
6428 void gtk_file_selection_set_filename( GtkFileSelection *filesel,
6429                                       gchar            *filename );
6430 </verb></tscreen>
6431
6432 To grab the text that the user has entered or clicked on, use this 
6433 function:
6434
6435 <tscreen><verb>
6436 gchar *gtk_file_selection_get_filename( GtkFileSelection *filesel );
6437 </verb></tscreen>
6438
6439 There are also pointers to the widgets contained within the file 
6440 selection widget. These are:
6441
6442 <tscreen><verb>
6443   dir_list
6444   file_list
6445   selection_entry
6446   selection_text
6447   main_vbox
6448   ok_button
6449   cancel_button
6450   help_button
6451 </verb></tscreen>
6452  
6453 Most likely you will want to use the ok_button, cancel_button, and
6454 help_button pointers in signaling their use.
6455
6456 Included here is an example stolen from testgtk.c, modified to run on
6457 its own. As you will see, there is nothing much to creating a file
6458 selection widget. While in this example the Help button appears on the
6459 screen, it does nothing as there is not a signal attached to it.
6460
6461 <tscreen><verb>
6462 /* example-start filesel filesel.c */
6463
6464 #include <gtk/gtk.h>
6465
6466 /* Get the selected filename and print it to the console */
6467 void file_ok_sel( GtkWidget        *w,
6468                   GtkFileSelection *fs )
6469 {
6470     g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
6471 }
6472
6473 void destroy( GtkWidget *widget,
6474               gpointer   data )
6475 {
6476     gtk_main_quit ();
6477 }
6478
6479 int main( int   argc,
6480           char *argv[] )
6481 {
6482     GtkWidget *filew;
6483     
6484     gtk_init (&amp;argc, &amp;argv);
6485     
6486     /* Create a new file selection widget */
6487     filew = gtk_file_selection_new ("File selection");
6488     
6489     gtk_signal_connect (GTK_OBJECT (filew), "destroy",
6490                         (GtkSignalFunc) destroy, &amp;filew);
6491     /* Connect the ok_button to file_ok_sel function */
6492     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
6493                         "clicked", (GtkSignalFunc) file_ok_sel, filew );
6494     
6495     /* Connect the cancel_button to destroy the widget */
6496     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
6497                                             (filew)->cancel_button),
6498                                "clicked", (GtkSignalFunc) gtk_widget_destroy,
6499                                GTK_OBJECT (filew));
6500     
6501     /* Lets set the filename, as if this were a save dialog, and we are giving
6502      a default filename */
6503     gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), 
6504                                      "penguin.png");
6505     
6506     gtk_widget_show(filew);
6507     gtk_main ();
6508     return 0;
6509 }
6510 /* example-end */
6511 </verb></tscreen>
6512
6513 <!-- ***************************************************************** -->
6514 <sect> Container Widgets
6515 <!-- ***************************************************************** -->
6516
6517 <!-- ----------------------------------------------------------------- -->   
6518 <sect1>The EventBox <label id="sec_EventBox">
6519 <p> 
6520 Some GTK widgets don't have associated X windows, so they just draw on
6521 their parents. Because of this, they cannot receive events and if they
6522 are incorrectly sized, they don't clip so you can get messy
6523 overwriting, etc. If you require more from these widgets, the EventBox
6524 is for you.
6525
6526 At first glance, the EventBox widget might appear to be totally
6527 useless. It draws nothing on the screen and responds to no
6528 events. However, it does serve a function - it provides an X window
6529 for its child widget. This is important as many GTK widgets do not
6530 have an associated X window. Not having an X window saves memory and
6531 improves performance, but also has some drawbacks. A widget without an
6532 X window cannot receive events, and does not perform any clipping on
6533 its contents. Although the name <em/EventBox/ emphasizes the
6534 event-handling function, the widget can also be used for clipping.
6535 (and more, see the example below).
6536
6537 To create a new EventBox widget, use:
6538
6539 <tscreen><verb>
6540 GtkWidget *gtk_event_box_new( void );
6541 </verb></tscreen>
6542
6543 A child widget can then be added to this EventBox:
6544
6545 <tscreen><verb>
6546     gtk_container_add( GTK_CONTAINER(event_box), child_widget );
6547 </verb></tscreen>
6548
6549 The following example demonstrates both uses of an EventBox - a label
6550 is created that is clipped to a small box, and set up so that a
6551 mouse-click on the label causes the program to exit. Resizing the
6552 window reveals varying amounts of the label.
6553
6554 <tscreen><verb>
6555 /* example-start eventbox eventbox.c */
6556
6557 #include <gtk/gtk.h>
6558
6559 int main( int argc,
6560           char *argv[] )
6561 {
6562     GtkWidget *window;
6563     GtkWidget *event_box;
6564     GtkWidget *label;
6565     
6566     gtk_init (&amp;argc, &amp;argv);
6567     
6568     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6569     
6570     gtk_window_set_title (GTK_WINDOW (window), "Event Box");
6571     
6572     gtk_signal_connect (GTK_OBJECT (window), "destroy",
6573                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
6574     
6575     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6576     
6577     /* Create an EventBox and add it to our toplevel window */
6578     
6579     event_box = gtk_event_box_new ();
6580     gtk_container_add (GTK_CONTAINER(window), event_box);
6581     gtk_widget_show (event_box);
6582     
6583     /* Create a long label */
6584     
6585     label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
6586     gtk_container_add (GTK_CONTAINER (event_box), label);
6587     gtk_widget_show (label);
6588     
6589     /* Clip it short. */
6590     gtk_widget_set_usize (label, 110, 20);
6591     
6592     /* And bind an action to it */
6593     gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
6594     gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
6595                         GTK_SIGNAL_FUNC (gtk_exit), NULL);
6596     
6597     /* Yet one more thing you need an X window for ... */
6598     
6599     gtk_widget_realize (event_box);
6600     gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
6601     
6602     gtk_widget_show (window);
6603     
6604     gtk_main ();
6605     
6606     return(0);
6607 }
6608 /* example-end */
6609 </verb></tscreen>
6610
6611 <!-- ----------------------------------------------------------------- -->   
6612 <sect1>The Alignment widget <label id="sec_Alignment">
6613 <p>
6614 The alignment widget allows you to place a widget within its window at
6615 a position and size relative to the size of the Alignment widget
6616 itself. For example, it can be very useful for centering a widget
6617 within the window.
6618
6619 There are only two functions associated with the Alignment widget:
6620
6621 <tscreen><verb>
6622 GtkWidget* gtk_alignment_new( gfloat xalign,
6623                               gfloat yalign,
6624                               gfloat xscale,
6625                               gfloat yscale );
6626
6627 void gtk_alignment_set( GtkAlignment *alignment,
6628                         gfloat        xalign,
6629                         gfloat        yalign,
6630                         gfloat        xscale,
6631                         gfloat        yscale );
6632 </verb></tscreen>
6633
6634 The first function creates a new Alignment widget with the specified
6635 parameters. The second function allows the alignment paramters of an
6636 exisiting Alignment widget to be altered.
6637
6638 All four alignment parameters are floating point numbers which can
6639 range from 0.0 to 1.0. The <tt/xalign/ and <tt/yalign/ arguments
6640 affect the position of the widget placed within the Alignment
6641 widget. The <tt/xscale/ and <tt/yscale/ arguments affect the amount of
6642 space allocated to the widget.
6643
6644 A child widget can be added to this Alignment widget using:
6645
6646 <tscreen><verb>
6647     gtk_container_add( GTK_CONTAINER(alignment), child_widget );
6648 </verb></tscreen>
6649
6650 For an example of using an Alignment widget, refer to the example for
6651 the <ref id="sec_ProgressBar" name="Progress Bar"> widget.
6652
6653 <!-- ----------------------------------------------------------------- -->
6654 <sect1> Fixed Container
6655 <p>
6656 The Fixed container allows you to place widgets at a fixed position
6657 within its window, relative to its upper left hand corner. The
6658 position of the widgets can be changed dynamically.
6659
6660 There are only three functions associated with the fixed widget:
6661
6662 <tscreen><verb>
6663 GtkWidget* gtk_fixed_new( void );
6664
6665 void gtk_fixed_put( GtkFixed  *fixed,
6666                     GtkWidget *widget,
6667                     gint16     x,
6668                     gint16     y );
6669
6670 void gtk_fixed_move( GtkFixed  *fixed,
6671                      GtkWidget *widget,
6672                      gint16     x,
6673                      gint16     y );
6674 </verb></tscreen>
6675
6676 The function <tt/gtk_fixed_new/ allows you to create a new Fixed
6677 container.
6678
6679 <tt/gtk_fixed_put/ places <tt/widget/ in the container <tt/fixed/ at
6680 the position specified by <tt/x/ and <tt/y/.
6681
6682 <tt/gtk_fixed_move/ allows the specified widget to be moved to a new
6683 position.
6684
6685 The following example illustrates how to use the Fixed Container.
6686
6687 <tscreen><verb>
6688 /* example-start fixed fixed.c */
6689
6690 #include <gtk/gtk.h>
6691
6692 /* I'm going to be lazy and use some global variables to
6693  * store the position of the widget within the fixed
6694  * container */
6695 gint x=50;
6696 gint y=50;
6697
6698 /* This callback function moves the button to a new position
6699  * in the Fixed container. */
6700 void move_button( GtkWidget *widget,
6701                   GtkWidget *fixed )
6702 {
6703   x = (x+30)%300;
6704   y = (y+50)%300;
6705   gtk_fixed_move( GTK_FIXED(fixed), widget, x, y); 
6706 }
6707
6708 int main( int   argc,
6709           char *argv[] )
6710 {
6711   /* GtkWidget is the storage type for widgets */
6712   GtkWidget *window;
6713   GtkWidget *fixed;
6714   GtkWidget *button;
6715   gint i;
6716
6717   /* Initialise GTK */
6718   gtk_init(&amp;argc, &amp;argv);
6719     
6720   /* Create a new window */
6721   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6722   gtk_window_set_title(GTK_WINDOW(window), "Fixed Container");
6723
6724   /* Here we connect the "destroy" event to a signal handler */ 
6725   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6726                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6727  
6728   /* Sets the border width of the window. */
6729   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6730
6731   /* Create a Fixed Container */
6732   fixed = gtk_fixed_new();
6733   gtk_container_add(GTK_CONTAINER(window), fixed);
6734   gtk_widget_show(fixed);
6735   
6736   for (i = 1 ; i <= 3 ; i++) {
6737     /* Creates a new button with the label "Press me" */
6738     button = gtk_button_new_with_label ("Press me");
6739   
6740     /* When the button receives the "clicked" signal, it will call the
6741      * function move_button() passing it the Fixed Container as its
6742      * argument. */
6743     gtk_signal_connect (GTK_OBJECT (button), "clicked",
6744                         GTK_SIGNAL_FUNC (move_button), fixed);
6745   
6746     /* This packs the button into the fixed containers window. */
6747     gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
6748   
6749     /* The final step is to display this newly created widget. */
6750     gtk_widget_show (button);
6751   }
6752
6753   /* Display the window */
6754   gtk_widget_show (window);
6755     
6756   /* Enter the event loop */
6757   gtk_main ();
6758     
6759   return(0);
6760 }
6761 /* example-end */
6762 </verb></tscreen>
6763
6764 <!-- ----------------------------------------------------------------- -->
6765 <sect1> Layout Container
6766 <p>
6767 The Layout container is similar to the Fixed container except that it
6768 implements an infinite (where infinity is less than 2^32) scrolling
6769 area. The X window system has a limitation where windows can be at
6770 most 32767 pixels wide or tall. The Layout container gets around this
6771 limitation by doing some exotic stuff using window and bit gravities,
6772 so that you can have smooth scrolling even when you have many child
6773 widgets in your scrolling area.
6774
6775 A Layout container is created using:
6776
6777 <tscreen><verb>
6778 GtkWidget *gtk_layout_new( GtkAdjustment *hadjustment,
6779                            GtkAdjustment *vadjustment );
6780 </verb></tscreen>
6781
6782 As you can see, you can optionally specify the Adjustment objects that
6783 the Layout widget will use for its scrolling.
6784
6785 You can add and move widgets in the Layout container using the
6786 following two functions:
6787
6788 <tscreen><verb>
6789 void gtk_layout_put( GtkLayout *layout,
6790                      GtkWidget *widget,
6791                      gint       x,
6792                      gint       y );
6793
6794 void gtk_layout_move( GtkLayout *layout,
6795                       GtkWidget *widget,
6796                       gint       x,
6797                       gint       y );
6798 </verb></tscreen>
6799
6800 The size of the Layout container can be set using the next function:
6801
6802 <tscreen><verb>
6803 void gtk_layout_set_size( GtkLayout *layout,
6804                           guint      width,
6805                           guint      height );
6806 </verb></tscreen>
6807
6808 Layout containers are one of the very few widgets in the GTK widget
6809 set that actively repaint themselves on screen as they are changed
6810 using the above functions (the vast majority of widgets queue
6811 requests which are then processed when control returns to the
6812 <tt/gtk_main()/ function).
6813
6814 When you want to make a large number of changes to a Layout container,
6815 you can use the following two functions to disable and re-enable this
6816 repainting functionality:
6817
6818 <tscreen><verb>
6819 void gtk_layout_freeze( GtkLayout *layout );
6820
6821 void gtk_layout_thaw( GtkLayout *layout );
6822 </verb></tscreen>
6823
6824 The final four functions for use with Layout widgets are for
6825 manipulating the horizontal and vertical adjustment widgets:
6826
6827 <tscreen><verb>
6828 GtkAdjustment* gtk_layout_get_hadjustment( GtkLayout *layout );
6829
6830 GtkAdjustment* gtk_layout_get_vadjustment( GtkLayout *layout );
6831
6832 void gtk_layout_set_hadjustment( GtkLayout     *layout,
6833                                  GtkAdjustment *adjustment );
6834
6835 void gtk_layout_set_vadjustment( GtkLayout     *layout,
6836                                  GtkAdjustment *adjustment);
6837 </verb></tscreen>
6838
6839 <!-- ----------------------------------------------------------------- -->
6840 <sect1> Frames <label id="sec_Frames">
6841 <p>
6842 Frames can be used to enclose one or a group of widgets with a box
6843 which can optionally be labelled. The position of the label and the
6844 style of the box can be altered to suit.
6845
6846 A Frame can be created with the following function:
6847
6848 <tscreen><verb>
6849 GtkWidget *gtk_frame_new( const gchar *label );
6850 </verb></tscreen>
6851
6852 The label is by default placed in the upper left hand corner of the
6853 frame. A value of NULL for the <tt/label/ argument will result in no
6854 label being displayed. The text of the label can be changed using the
6855 next function.
6856
6857 <tscreen><verb>
6858 void gtk_frame_set_label( GtkFrame    *frame,
6859                           const gchar *label );
6860 </verb></tscreen>
6861
6862 The position of the label can be changed using this function:
6863
6864 <tscreen><verb>
6865 void gtk_frame_set_label_align( GtkFrame *frame,
6866                                 gfloat    xalign,
6867                                 gfloat    yalign );
6868 </verb></tscreen>
6869
6870 <tt/xalign/ and <tt/yalign/ take values between 0.0 and 1.0. <tt/xalign/
6871 indicates the position of the label along the top horizontal of the
6872 frame. <tt/yalign/ is not currently used. The default value of xalign
6873 is 0.0 which places the label at the left hand end of the frame.
6874
6875 The next function alters the style of the box that is used to outline
6876 the frame.
6877
6878 <tscreen><verb>
6879 void gtk_frame_set_shadow_type( GtkFrame      *frame,
6880                                 GtkShadowType  type);
6881 </verb></tscreen>
6882
6883 The <tt/type/ argument can take one of the following values:
6884 <tscreen><verb>
6885   GTK_SHADOW_NONE
6886   GTK_SHADOW_IN
6887   GTK_SHADOW_OUT
6888   GTK_SHADOW_ETCHED_IN (the default)
6889   GTK_SHADOW_ETCHED_OUT
6890 </verb></tscreen>
6891
6892 The following code example illustrates the use of the Frame widget.
6893
6894 <tscreen><verb>
6895 /* example-start frame frame.c */
6896
6897 #include <gtk/gtk.h>
6898
6899 int main( int   argc,
6900           char *argv[] )
6901 {
6902   /* GtkWidget is the storage type for widgets */
6903   GtkWidget *window;
6904   GtkWidget *frame;
6905   GtkWidget *button;
6906   gint i;
6907
6908   /* Initialise GTK */
6909   gtk_init(&amp;argc, &amp;argv);
6910     
6911   /* Create a new window */
6912   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6913   gtk_window_set_title(GTK_WINDOW(window), "Frame Example");
6914
6915   /* Here we connect the "destroy" event to a signal handler */ 
6916   gtk_signal_connect (GTK_OBJECT (window), "destroy",
6917                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
6918
6919   gtk_widget_set_usize(window, 300, 300);
6920   /* Sets the border width of the window. */
6921   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
6922
6923   /* Create a Frame */
6924   frame = gtk_frame_new(NULL);
6925   gtk_container_add(GTK_CONTAINER(window), frame);
6926
6927   /* Set the frame's label */
6928   gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" );
6929
6930   /* Align the label at the right of the frame */
6931   gtk_frame_set_label_align( GTK_FRAME(frame), 1.0, 0.0);
6932
6933   /* Set the style of the frame */
6934   gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
6935
6936   gtk_widget_show(frame);
6937   
6938   /* Display the window */
6939   gtk_widget_show (window);
6940     
6941   /* Enter the event loop */
6942   gtk_main ();
6943     
6944   return(0);
6945 }
6946 /* example-end */
6947
6948 </verb></tscreen>
6949
6950 <!-- ----------------------------------------------------------------- -->   
6951 <sect1> Aspect Frames
6952 <p>
6953 The aspect frame widget is like a frame widget, except that it also
6954 enforces the aspect ratio (that is, the ratio of the width to the
6955 height) of the child widget to have a certain value, adding extra
6956 space if necessary. This is useful, for instance, if you want to
6957 preview a larger image. The size of the preview should vary when the
6958 user resizes the window, but the aspect ratio needs to always match
6959 the original image.
6960   
6961 To create a new aspect frame use:
6962    
6963 <tscreen><verb>
6964 GtkWidget *gtk_aspect_frame_new( const gchar *label,
6965                                  gfloat       xalign,
6966                                  gfloat       yalign,
6967                                  gfloat       ratio,
6968                                  gint         obey_child);
6969 </verb></tscreen>
6970    
6971 <tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
6972 widgets. If <tt/obey_child/ is true, the aspect ratio of a child
6973 widget will match the aspect ratio of the ideal size it requests.
6974 Otherwise, it is given by <tt/ratio/.
6975    
6976 To change the options of an existing aspect frame, you can use:
6977    
6978 <tscreen><verb>
6979 void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
6980                            gfloat          xalign,
6981                            gfloat          yalign,
6982                            gfloat          ratio,
6983                            gint            obey_child);
6984 </verb></tscreen>
6985    
6986 As an example, the following program uses an AspectFrame to present a
6987 drawing area whose aspect ratio will always be 2:1, no matter how the
6988 user resizes the top-level window.
6989    
6990 <tscreen><verb>
6991 /* example-start aspectframe aspectframe.c */
6992
6993 #include <gtk/gtk.h>
6994    
6995 int main( int argc,
6996           char *argv[] )
6997 {
6998     GtkWidget *window;
6999     GtkWidget *aspect_frame;
7000     GtkWidget *drawing_area;
7001     gtk_init (&amp;argc, &amp;argv);
7002    
7003     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7004     gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
7005     gtk_signal_connect (GTK_OBJECT (window), "destroy",
7006                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
7007     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7008    
7009     /* Create an aspect_frame and add it to our toplevel window */
7010    
7011     aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
7012                                          0.5, /* center x */
7013                                          0.5, /* center y */
7014                                          2, /* xsize/ysize = 2 */
7015                                          FALSE /* ignore child's aspect */);
7016    
7017     gtk_container_add (GTK_CONTAINER(window), aspect_frame);
7018     gtk_widget_show (aspect_frame);
7019    
7020     /* Now add a child widget to the aspect frame */
7021    
7022     drawing_area = gtk_drawing_area_new ();
7023    
7024     /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
7025      * window since we are forcing a 2x1 aspect ratio */
7026     gtk_widget_set_usize (drawing_area, 200, 200);
7027     gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
7028     gtk_widget_show (drawing_area);
7029    
7030     gtk_widget_show (window);
7031     gtk_main ();
7032     return 0;
7033 }
7034 /* example-end */
7035 </verb></tscreen>
7036
7037 <!-- ----------------------------------------------------------------- -->   
7038 <sect1> Paned Window Widgets
7039 <p>
7040 The paned window widgets are useful when you want to divide an area
7041 into two parts, with the relative size of the two parts controlled by
7042 the user. A groove is drawn between the two portions with a handle
7043 that the user can drag to change the ratio. The division can either be
7044 horizontal (HPaned) or vertical (VPaned).
7045    
7046 To create a new paned window, call one of:
7047    
7048 <tscreen><verb>
7049 GtkWidget *gtk_hpaned_new (void);
7050
7051 GtkWidget *gtk_vpaned_new (void);
7052 </verb></tscreen>
7053
7054 After creating the paned window widget, you need to add child widgets
7055 to its two halves. To do this, use the functions:
7056    
7057 <tscreen><verb>
7058 void gtk_paned_add1 (GtkPaned *paned, GtkWidget *child);
7059
7060 void gtk_paned_add2 (GtkPaned *paned, GtkWidget *child);
7061 </verb></tscreen>
7062    
7063 <tt/gtk_paned_add1()/ adds the child widget to the left or top half of
7064 the paned window. <tt/gtk_paned_add2()/ adds the child widget to the
7065 right or bottom half of the paned window.
7066
7067 A paned widget can be changed visually using the following two
7068 functions.
7069
7070 <tscreen><verb>
7071 void gtk_paned_set_handle_size( GtkPaned *paned,
7072                                 guint16   size);
7073
7074 void gtk_paned_set_gutter_size( GtkPaned *paned,
7075                                 guint16   size);
7076 </verb></tscreen>
7077
7078 The first of these sets the size of the handle and the second sets the
7079 size of the gutter that is between the two parts of the paned window.
7080
7081 As an example, we will create part of the user interface of an
7082 imaginary email program. A window is divided into two portions
7083 vertically, with the top portion being a list of email messages and
7084 the bottom portion the text of the email message. Most of the program
7085 is pretty straightforward. A couple of points to note: text can't be
7086 added to a Text widget until it is realized. This could be done by
7087 calling <tt/gtk_widget_realize()/, but as a demonstration of an
7088 alternate technique, we connect a handler to the "realize" signal to
7089 add the text. Also, we need to add the <tt/GTK_SHRINK/ option to some
7090 of the items in the table containing the text window and its
7091 scrollbars, so that when the bottom portion is made smaller, the
7092 correct portions shrink instead of being pushed off the bottom of the
7093 window.
7094
7095 <tscreen><verb>
7096 /* example-start paned paned.c */
7097
7098 #include <stdio.h>
7099 #include <gtk/gtk.h>
7100    
7101 /* Create the list of "messages" */
7102 GtkWidget *create_list( void )
7103 {
7104
7105     GtkWidget *scrolled_window;
7106     GtkWidget *list;
7107     GtkWidget *list_item;
7108    
7109     int i;
7110     char buffer[16];
7111    
7112     /* Create a new scrolled window, with scrollbars only if needed */
7113     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
7114     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
7115                                     GTK_POLICY_AUTOMATIC, 
7116                                     GTK_POLICY_AUTOMATIC);
7117    
7118     /* Create a new list and put it in the scrolled window */
7119     list = gtk_list_new ();
7120     gtk_scrolled_window_add_with_viewport (
7121                GTK_SCROLLED_WINDOW (scrolled_window), list);
7122     gtk_widget_show (list);
7123    
7124     /* Add some messages to the window */
7125     for (i=0; i<10; i++) {
7126
7127         sprintf(buffer,"Message #%d",i);
7128         list_item = gtk_list_item_new_with_label (buffer);
7129         gtk_container_add (GTK_CONTAINER(list), list_item);
7130         gtk_widget_show (list_item);
7131
7132     }
7133    
7134     return scrolled_window;
7135 }
7136    
7137 /* Add some text to our text widget - this is a callback that is invoked
7138 when our window is realized. We could also force our window to be
7139 realized with gtk_widget_realize, but it would have to be part of
7140 a hierarchy first */
7141
7142 void realize_text( GtkWidget *text,
7143                    gpointer data )
7144 {
7145     gtk_text_freeze (GTK_TEXT (text));
7146     gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
7147     "From: pathfinder@nasa.gov\n"
7148     "To: mom@nasa.gov\n"
7149     "Subject: Made it!\n"
7150     "\n"
7151     "We just got in this morning. The weather has been\n"
7152     "great - clear but cold, and there are lots of fun sights.\n"
7153     "Sojourner says hi. See you soon.\n"
7154     " -Path\n", -1);
7155    
7156     gtk_text_thaw (GTK_TEXT (text));
7157 }
7158    
7159 /* Create a scrolled text area that displays a "message" */
7160 GtkWidget *create_text( void )
7161 {
7162     GtkWidget *table;
7163     GtkWidget *text;
7164     GtkWidget *hscrollbar;
7165     GtkWidget *vscrollbar;
7166    
7167     /* Create a table to hold the text widget and scrollbars */
7168     table = gtk_table_new (2, 2, FALSE);
7169    
7170     /* Put a text widget in the upper left hand corner. Note the use of
7171      * GTK_SHRINK in the y direction */
7172     text = gtk_text_new (NULL, NULL);
7173     gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
7174                       GTK_FILL | GTK_EXPAND,
7175                       GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
7176     gtk_widget_show (text);
7177    
7178     /* Put a HScrollbar in the lower left hand corner */
7179     hscrollbar = gtk_hscrollbar_new (GTK_TEXT (text)->hadj);
7180     gtk_table_attach (GTK_TABLE (table), hscrollbar, 0, 1, 1, 2,
7181                       GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
7182     gtk_widget_show (hscrollbar);
7183    
7184     /* And a VScrollbar in the upper right */
7185     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
7186     gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
7187                       GTK_FILL, GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0, 0);
7188     gtk_widget_show (vscrollbar);
7189    
7190     /* Add a handler to put a message in the text widget when it is realized */
7191     gtk_signal_connect (GTK_OBJECT (text), "realize",
7192                         GTK_SIGNAL_FUNC (realize_text), NULL);
7193    
7194     return table;
7195 }
7196    
7197 int main( int   argc,
7198           char *argv[] )
7199 {
7200     GtkWidget *window;
7201     GtkWidget *vpaned;
7202     GtkWidget *list;
7203     GtkWidget *text;
7204
7205     gtk_init (&amp;argc, &amp;argv);
7206    
7207     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7208     gtk_window_set_title (GTK_WINDOW (window), "Paned Windows");
7209     gtk_signal_connect (GTK_OBJECT (window), "destroy",
7210                         GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
7211     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7212     gtk_widget_set_usize (GTK_WIDGET(window), 450, 400);
7213
7214     /* create a vpaned widget and add it to our toplevel window */
7215    
7216     vpaned = gtk_vpaned_new ();
7217     gtk_container_add (GTK_CONTAINER(window), vpaned);
7218     gtk_paned_set_handle_size (GTK_PANED(vpaned),
7219                                10);
7220     gtk_paned_set_gutter_size (GTK_PANED(vpaned),
7221                                15);                       
7222     gtk_widget_show (vpaned);
7223    
7224     /* Now create the contents of the two halves of the window */
7225    
7226     list = create_list ();
7227     gtk_paned_add1 (GTK_PANED(vpaned), list);
7228     gtk_widget_show (list);
7229    
7230     text = create_text ();
7231     gtk_paned_add2 (GTK_PANED(vpaned), text);
7232     gtk_widget_show (text);
7233     gtk_widget_show (window);
7234     gtk_main ();
7235     return 0;
7236 }
7237 /* example-end */
7238 </verb></tscreen>
7239
7240 <!-- ----------------------------------------------------------------- -->
7241 <sect1>Viewports <label id="sec_Viewports">
7242 <p>
7243 It is unlikely that you will ever need to use the Viewport widget
7244 directly. You are much more likely to use the
7245 <ref id="sec_ScrolledWindow" name="Scrolled Window"> widget which
7246 itself uses the Viewport.
7247
7248 A viewport widget allows you to place a larger widget within it such
7249 that you can view a part of it at a time. It uses
7250 <ref id="sec_Adjustment" name="Adjustments"> to define the area that
7251 is currently in view.
7252
7253 A Viewport is created with the function
7254
7255 <tscreen><verb>
7256 GtkWidget *gtk_viewport_new( GtkAdjustment *hadjustment,
7257                              GtkAdjustment *vadjustment );
7258 </verb></tscreen>
7259
7260 As you can see you can specify the horizontal and vertical Adjustments
7261 that the widget is to use when you create the widget. It will create
7262 its own if you pass NULL as the value of the arguments.
7263
7264 You can get and set the adjustments after the widget has been created
7265 using the following four functions:
7266
7267 <tscreen><verb>
7268 GtkAdjustment *gtk_viewport_get_hadjustment (GtkViewport *viewport );
7269
7270 GtkAdjustment *gtk_viewport_get_vadjustment (GtkViewport *viewport );
7271
7272 void gtk_viewport_set_hadjustment( GtkViewport   *viewport,
7273                                    GtkAdjustment *adjustment );
7274
7275 void gtk_viewport_set_vadjustment( GtkViewport   *viewport,
7276                                    GtkAdjustment *adjustment );
7277 </verb></tscreen>
7278
7279 The only other viewport function is used to alter its appearance:
7280
7281 <tscreen><verb>
7282 void gtk_viewport_set_shadow_type( GtkViewport   *viewport,
7283                                    GtkShadowType  type );
7284 </verb></tscreen>
7285
7286 Possible values for the <tt/type/ parameter are:
7287 <tscreen><verb>
7288   GTK_SHADOW_NONE,
7289   GTK_SHADOW_IN,
7290   GTK_SHADOW_OUT,
7291   GTK_SHADOW_ETCHED_IN,
7292   GTK_SHADOW_ETCHED_OUT
7293 </verb></tscreen>
7294  
7295 <!-- ----------------------------------------------------------------- -->
7296 <sect1>Scrolled Windows <label id="sec_ScrolledWindow">
7297 <p>
7298 Scrolled windows are used to create a scrollable area with another
7299 widget inside it. You may insert any type of widget into a scrolled
7300 window, and it will be accessible regardless of the size by using the
7301 scrollbars.
7302
7303 The following function is used to create a new scrolled window.
7304
7305 <tscreen><verb>
7306 GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
7307                                     GtkAdjustment *vadjustment );
7308 </verb></tscreen>
7309
7310 Where the first argument is the adjustment for the horizontal
7311 direction, and the second, the adjustment for the vertical direction.
7312 These are almost always set to NULL.
7313
7314 <tscreen><verb>
7315 void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
7316                                      GtkPolicyType      hscrollbar_policy,
7317                                      GtkPolicyType      vscrollbar_policy );
7318 </verb></tscreen>
7319
7320 This sets the policy to be used with respect to the scrollbars.
7321 The first argument is the scrolled window you wish to change. The second
7322 sets the policy for the horizontal scrollbar, and the third the policy for 
7323 the vertical scrollbar.
7324
7325 The policy may be one of <tt/GTK_POLICY_AUTOMATIC/ or
7326 <tt/GTK_POLICY_ALWAYS/. <tt/GTK_POLICY_AUTOMATIC/ will automatically
7327 decide whether you need scrollbars, whereas <tt/GTK_POLICY_ALWAYS/
7328 will always leave the scrollbars there.
7329
7330 You can then place your object into the scrolled window using the
7331 following function.
7332
7333 <tscreen><verb>
7334 void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
7335                                             GtkWidget         *child);
7336 </verb></tscreen>
7337
7338 Here is a simple example that packs a table eith 100 toggle buttons
7339 into a scrolled window. I've only commented on the parts that may be
7340 new to you.
7341
7342 <tscreen><verb>
7343 /* example-start scrolledwin scrolledwin.c */
7344
7345 #include <stdio.h>
7346 #include <gtk/gtk.h>
7347
7348 void destroy( GtkWidget *widget,
7349               gpointer   data )
7350 {
7351     gtk_main_quit();
7352 }
7353
7354 int main( int   argc,
7355           char *argv[] )
7356 {
7357     static GtkWidget *window;
7358     GtkWidget *scrolled_window;
7359     GtkWidget *table;
7360     GtkWidget *button;
7361     char buffer[32];
7362     int i, j;
7363     
7364     gtk_init (&amp;argc, &amp;argv);
7365     
7366     /* Create a new dialog window for the scrolled window to be
7367      * packed into.  */
7368     window = gtk_dialog_new ();
7369     gtk_signal_connect (GTK_OBJECT (window), "destroy",
7370                         (GtkSignalFunc) destroy, NULL);
7371     gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
7372     gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7373     gtk_widget_set_usize(window, 300, 300);
7374     
7375     /* create a new scrolled window. */
7376     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
7377     
7378     gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
7379     
7380     /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
7381      * GTK_POLICY_AUTOMATIC will automatically decide whether you need
7382      * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
7383      * there.  The first one is the horizontal scrollbar, the second, 
7384      * the vertical. */
7385     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
7386                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
7387     /* The dialog window is created with a vbox packed into it. */                                                              
7388     gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window, 
7389                         TRUE, TRUE, 0);
7390     gtk_widget_show (scrolled_window);
7391     
7392     /* create a table of 10 by 10 squares. */
7393     table = gtk_table_new (10, 10, FALSE);
7394     
7395     /* set the spacing to 10 on x and 10 on y */
7396     gtk_table_set_row_spacings (GTK_TABLE (table), 10);
7397     gtk_table_set_col_spacings (GTK_TABLE (table), 10);
7398     
7399     /* pack the table into the scrolled window */
7400     gtk_scrolled_window_add_with_viewport (
7401                    GTK_SCROLLED_WINDOW (scrolled_window), table);
7402     gtk_widget_show (table);
7403     
7404     /* this simply creates a grid of toggle buttons on the table
7405      * to demonstrate the scrolled window. */
7406     for (i = 0; i < 10; i++)
7407        for (j = 0; j < 10; j++) {
7408           sprintf (buffer, "button (%d,%d)\n", i, j);
7409           button = gtk_toggle_button_new_with_label (buffer);
7410           gtk_table_attach_defaults (GTK_TABLE (table), button,
7411                                      i, i+1, j, j+1);
7412           gtk_widget_show (button);
7413        }
7414     
7415     /* Add a "close" button to the bottom of the dialog */
7416     button = gtk_button_new_with_label ("close");
7417     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
7418                                (GtkSignalFunc) gtk_widget_destroy,
7419                                GTK_OBJECT (window));
7420     
7421     /* this makes it so the button is the default. */
7422     
7423     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
7424     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
7425     
7426     /* This grabs this button to be the default button. Simply hitting
7427      * the "Enter" key will cause this button to activate. */
7428     gtk_widget_grab_default (button);
7429     gtk_widget_show (button);
7430     
7431     gtk_widget_show (window);
7432     
7433     gtk_main();
7434     
7435     return(0);
7436 }
7437 /* example-end */
7438 </verb></tscreen>
7439
7440 Try playing with resizing the window. You'll notice how the scrollbars
7441 react. You may also wish to use the gtk_widget_set_usize() call to set
7442 the default size of the window or other widgets.
7443
7444 <!-- ----------------------------------------------------------------- -->   
7445 <sect1>Button Boxes
7446 <p>
7447 Button Boxes are a convenient way to quickly layout a group of
7448 buttons. They come in both horizontal and vertical flavours. You
7449 create a new Button Box with one of the following calls, which create
7450 a horizontal or vertical box, respectively:
7451
7452 <tscreen><verb>
7453 GtkWidget *gtk_hbutton_box_new( void );
7454
7455 GtkWidget *gtk_vbutton_box_new( void );
7456 </verb></tscreen>
7457
7458 The only attributes pertaining to button boxes affect how the buttons
7459 are laid out. You can change the spacing between the buttons with:
7460
7461 <tscreen><verb>
7462 void gtk_hbutton_box_set_spacing_default( gint spacing );
7463
7464 void gtk_vbutton_box_set_spacing_default( gint spacing );
7465 </verb></tscreen>
7466
7467 Similarly, the current spacing values can be queried using:
7468
7469 <tscreen><verb>
7470 gint gtk_hbutton_box_get_spacing_default( void );
7471
7472 gint gtk_vbutton_box_get_spacing_default( void );
7473 </verb></tscreen>
7474
7475 The second attribute that we can access affects the layout of the
7476 buttons within the box. It is set using one of:
7477
7478 <tscreen><verb>
7479 void gtk_hbutton_box_set_layout_default( GtkButtonBoxStyle layout );
7480
7481 void gtk_vbutton_box_set_layout_default( GtkButtonBoxStyle layout );
7482 </verb></tscreen>
7483
7484 The <tt/layout/ argument can take one of the following values:
7485
7486 <tscreen><verb>
7487   GTK_BUTTONBOX_DEFAULT_STYLE
7488   GTK_BUTTONBOX_SPREAD
7489   GTK_BUTTONBOX_EDGE
7490   GTK_BUTTONBOX_START
7491   GTK_BUTTONBOX_END
7492 </verb></tscreen>
7493
7494 The current layout setting can be retrieved using:
7495
7496 <tscreen><verb>
7497 GtkButtonBoxStyle gtk_hbutton_box_get_layout_default( void );
7498
7499 GtkButtonBoxStyle gtk_vbutton_box_get_layout_default( void );
7500 </verb></tscreen>
7501
7502 Buttons are added to a Button Box using the usual function:
7503
7504 <tscreen><verb>
7505     gtk_container_add( GTK_CONTAINER(button_box), child_widget );
7506 </verb></tscreen>
7507
7508 Here's an example that illustrates all the different layout settings
7509 for Button Boxes.
7510
7511 <tscreen><verb>
7512 /* example-start buttonbox buttonbox.c */
7513
7514 #include <gtk/gtk.h>
7515
7516 /* Create a Button Box with the specified parameters */
7517 GtkWidget *create_bbox( gint  horizontal,
7518                         char *title,
7519                         gint  spacing,
7520                         gint  child_w,
7521                         gint  child_h,
7522                         gint  layout )
7523 {
7524   GtkWidget *frame;
7525   GtkWidget *bbox;
7526   GtkWidget *button;
7527
7528   frame = gtk_frame_new (title);
7529
7530   if (horizontal)
7531     bbox = gtk_hbutton_box_new ();
7532   else
7533     bbox = gtk_vbutton_box_new ();
7534
7535   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
7536   gtk_container_add (GTK_CONTAINER (frame), bbox);
7537
7538   /* Set the appearance of the Button Box */
7539   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
7540   gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), spacing);
7541   gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
7542
7543   button = gtk_button_new_with_label ("OK");
7544   gtk_container_add (GTK_CONTAINER (bbox), button);
7545
7546   button = gtk_button_new_with_label ("Cancel");
7547   gtk_container_add (GTK_CONTAINER (bbox), button);
7548
7549   button = gtk_button_new_with_label ("Help");
7550   gtk_container_add (GTK_CONTAINER (bbox), button);
7551
7552   return(frame);
7553 }
7554
7555 int main( int   argc,
7556           char *argv[] )
7557 {
7558   static GtkWidget* window = NULL;
7559   GtkWidget *main_vbox;
7560   GtkWidget *vbox;
7561   GtkWidget *hbox;
7562   GtkWidget *frame_horz;
7563   GtkWidget *frame_vert;
7564
7565   /* Initialize GTK */
7566   gtk_init( &amp;argc, &amp;argv );
7567
7568   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7569   gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
7570
7571   gtk_signal_connect (GTK_OBJECT (window), "destroy",
7572                       GTK_SIGNAL_FUNC(gtk_main_quit),
7573                       NULL);
7574
7575   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
7576
7577   main_vbox = gtk_vbox_new (FALSE, 0);
7578   gtk_container_add (GTK_CONTAINER (window), main_vbox);
7579
7580   frame_horz = gtk_frame_new ("Horizontal Button Boxes");
7581   gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
7582
7583   vbox = gtk_vbox_new (FALSE, 0);
7584   gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
7585   gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
7586
7587   gtk_box_pack_start (GTK_BOX (vbox),
7588            create_bbox (TRUE, "Spread (spacing 40)", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
7589                       TRUE, TRUE, 0);
7590
7591   gtk_box_pack_start (GTK_BOX (vbox),
7592            create_bbox (TRUE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
7593                       TRUE, TRUE, 5);
7594
7595   gtk_box_pack_start (GTK_BOX (vbox),
7596            create_bbox (TRUE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
7597                       TRUE, TRUE, 5);
7598
7599   gtk_box_pack_start (GTK_BOX (vbox),
7600            create_bbox (TRUE, "End (spacing 10)", 10, 85, 20, GTK_BUTTONBOX_END),
7601                       TRUE, TRUE, 5);
7602
7603   frame_vert = gtk_frame_new ("Vertical Button Boxes");
7604   gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
7605
7606   hbox = gtk_hbox_new (FALSE, 0);
7607   gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
7608   gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
7609
7610   gtk_box_pack_start (GTK_BOX (hbox),
7611            create_bbox (FALSE, "Spread (spacing 5)", 5, 85, 20, GTK_BUTTONBOX_SPREAD),
7612                       TRUE, TRUE, 0);
7613
7614   gtk_box_pack_start (GTK_BOX (hbox),
7615            create_bbox (FALSE, "Edge (spacing 30)", 30, 85, 20, GTK_BUTTONBOX_EDGE),
7616                       TRUE, TRUE, 5);
7617
7618   gtk_box_pack_start (GTK_BOX (hbox),
7619            create_bbox (FALSE, "Start (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_START),
7620                       TRUE, TRUE, 5);
7621
7622   gtk_box_pack_start (GTK_BOX (hbox),
7623            create_bbox (FALSE, "End (spacing 20)", 20, 85, 20, GTK_BUTTONBOX_END),
7624                       TRUE, TRUE, 5);
7625
7626   gtk_widget_show_all (window);
7627
7628   /* Enter the event loop */
7629   gtk_main ();
7630     
7631   return(0);
7632 }
7633 /* example-end */
7634 </verb></tscreen>
7635
7636 <!-- ----------------------------------------------------------------- -->   
7637 <sect1>Toolbar
7638 <p>
7639 Toolbars are usually used to group some number of widgets in order to
7640 simplify customization of their look and layout. Typically a toolbar
7641 consists of buttons with icons, labels and tooltips, but any other
7642 widget can also be put inside a toolbar. Finally, items can be
7643 arranged horizontally or vertically and buttons can be displayed with
7644 icons, labels, or both.
7645
7646 Creating a toolbar is (as one may already suspect) done with the
7647 following function:
7648
7649 <tscreen><verb>
7650 GtkWidget *gtk_toolbar_new( GtkOrientation orientation,
7651                             GtkToolbarStyle  style );
7652 </verb></tscreen>
7653
7654 where orientation may be one of:
7655
7656 <tscreen><verb>
7657   GTK_ORIENTATION_HORIZONTAL    
7658   GTK_ORIENTATION_VERTICAL
7659 </verb></tscreen>
7660
7661 and style one of:
7662
7663 <tscreen><verb>
7664   GTK_TOOLBAR_TEXT
7665   GTK_TOOLBAR_ICONS
7666   GTK_TOOLBAR_BOTH
7667 </verb></tscreen>
7668
7669 The style applies to all the buttons created with the `item' functions
7670 (not to buttons inserted into toolbar as separate widgets).
7671
7672 After creating a toolbar one can append, prepend and insert items
7673 (that means simple text strings) or elements (that means any widget
7674 types) into the toolbar. To describe an item we need a label text, a
7675 tooltip text, a private tooltip text, an icon for the button and a
7676 callback function for it. For example, to append or prepend an item
7677 you may use the following functions:
7678
7679 <tscreen><verb>
7680 GtkWidget *gtk_toolbar_append_item( GtkToolbar    *toolbar,
7681                                     const char    *text,
7682                                     const char    *tooltip_text,
7683                                     const char    *tooltip_private_text,
7684                                     GtkWidget     *icon,
7685                                     GtkSignalFunc  callback,
7686                                     gpointer       user_data );
7687
7688 GtkWidget *gtk_toolbar_prepend_item( GtkToolbar    *toolbar,
7689                                      const char    *text,
7690                                      const char    *tooltip_text,
7691                                      const char    *tooltip_private_text,
7692                                      GtkWidget     *icon,
7693                                      GtkSignalFunc  callback,
7694                                      gpointer       user_data );
7695 </verb></tscreen>
7696
7697 If you want to use gtk_toolbar_insert_item, the only additional
7698 parameter which must be specified is the position in which the item
7699 should be inserted, thus:
7700
7701 <tscreen><verb>
7702 GtkWidget *gtk_toolbar_insert_item( GtkToolbar    *toolbar,
7703                                     const char    *text,
7704                                     const char    *tooltip_text,
7705                                     const char    *tooltip_private_text,
7706                                     GtkWidget     *icon,
7707                                     GtkSignalFunc  callback,
7708                                     gpointer       user_data,
7709                                     gint           position );
7710 </verb></tscreen>
7711
7712 To simplify adding spaces between toolbar items, you may use the
7713 following functions:
7714
7715 <tscreen><verb>
7716 void gtk_toolbar_append_space( GtkToolbar *toolbar );
7717
7718 void gtk_toolbar_prepend_space( GtkToolbar *toolbar );
7719
7720 void gtk_toolbar_insert_space( GtkToolbar *toolbar,
7721                                gint        position );
7722  
7723 </verb></tscreen>
7724
7725 While the size of the added space can be set globally for a
7726 whole toolbar with the function:
7727
7728 <tscreen><verb>
7729 void gtk_toolbar_set_space_size( GtkToolbar *toolbar,
7730                                  gint        space_size) ;
7731 </verb></tscreen>
7732
7733 If it's required, the orientation of a toolbar and its style can be
7734 changed "on the fly" using the following functions:
7735
7736 <tscreen><verb>
7737 void gtk_toolbar_set_orientation( GtkToolbar     *toolbar,
7738                                   GtkOrientation  orientation );
7739
7740 void gtk_toolbar_set_style( GtkToolbar      *toolbar,
7741                             GtkToolbarStyle  style );
7742
7743 void gtk_toolbar_set_tooltips( GtkToolbar *toolbar,
7744                                gint        enable );
7745 </verb></tscreen>
7746
7747 Where <tt/orientation/ is one of <tt/GTK_ORIENTATION_HORIZONTAL/ or
7748 <tt/GTK_ORIENTATION_VERTICAL/. The <tt/style/ is used to set
7749 appearance of the toolbar items by using one of
7750 <tt/GTK_TOOLBAR_ICONS/, <tt/GTK_TOOLBAR_TEXT/, or
7751 <tt/GTK_TOOLBAR_BOTH/.
7752
7753 To show some other things that can be done with a toolbar, let's take
7754 the following program (we'll interrupt the listing with some
7755 additional explanations):
7756
7757 <tscreen><verb>
7758 #include <gtk/gtk.h>
7759
7760 #include "gtk.xpm"
7761
7762 /* This function is connected to the Close button or
7763  * closing the window from the WM */
7764 gint delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
7765 {
7766   gtk_main_quit ();
7767   return(FALSE);
7768 }
7769 </verb></tscreen>
7770
7771 The above beginning seems for sure familiar to you if it's not your first
7772 GTK program. There is one additional thing though, we include a nice XPM
7773 picture to serve as an icon for all of the buttons.
7774
7775 <tscreen><verb>
7776 GtkWidget* close_button; /* This button will emit signal to close
7777                           * application */
7778 GtkWidget* tooltips_button; /* to enable/disable tooltips */
7779 GtkWidget* text_button,
7780          * icon_button,
7781          * both_button; /* radio buttons for toolbar style */
7782 GtkWidget* entry; /* a text entry to show packing any widget into
7783                    * toolbar */
7784 </verb></tscreen>
7785
7786 In fact not all of the above widgets are needed here, but to make things
7787 clearer I put them all together.
7788
7789 <tscreen><verb>
7790 /* that's easy... when one of the buttons is toggled, we just
7791  * check which one is active and set the style of the toolbar
7792  * accordingly
7793  * ATTENTION: our toolbar is passed as data to callback ! */
7794 void radio_event (GtkWidget *widget, gpointer data)
7795 {
7796   if (GTK_TOGGLE_BUTTON (text_button)->active) 
7797     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_TEXT);
7798   else if (GTK_TOGGLE_BUTTON (icon_button)->active)
7799     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_ICONS);
7800   else if (GTK_TOGGLE_BUTTON (both_button)->active)
7801     gtk_toolbar_set_style(GTK_TOOLBAR ( data ), GTK_TOOLBAR_BOTH);
7802 }
7803
7804 /* even easier, just check given toggle button and enable/disable 
7805  * tooltips */
7806 void toggle_event (GtkWidget *widget, gpointer data)
7807 {
7808   gtk_toolbar_set_tooltips (GTK_TOOLBAR ( data ),
7809                             GTK_TOGGLE_BUTTON (widget)->active );
7810 }
7811 </verb></tscreen>
7812
7813 The above are just two callback functions that will be called when
7814 one of the buttons on a toolbar is pressed. You should already be
7815 familiar with things like this if you've already used toggle buttons (and
7816 radio buttons).
7817
7818 <tscreen><verb>
7819 int main (int argc, char *argv[])
7820 {
7821   /* Here is our main window (a dialog) and a handle for the handlebox */
7822   GtkWidget* dialog;
7823   GtkWidget* handlebox;
7824
7825   /* Ok, we need a toolbar, an icon with a mask (one for all of 
7826      the buttons) and an icon widget to put this icon in (but 
7827      we'll create a separate widget for each button) */
7828   GtkWidget * toolbar;
7829   GdkPixmap * icon;
7830   GdkBitmap * mask;
7831   GtkWidget * iconw;
7832
7833   /* this is called in all GTK application. */
7834   gtk_init (&amp;argc, &amp;argv);
7835   
7836   /* create a new window with a given title, and nice size */
7837   dialog = gtk_dialog_new ();
7838   gtk_window_set_title ( GTK_WINDOW ( dialog ) , "GTKToolbar Tutorial");
7839   gtk_widget_set_usize( GTK_WIDGET ( dialog ) , 600 , 300 );
7840   GTK_WINDOW ( dialog ) ->allow_shrink = TRUE;
7841
7842   /* typically we quit if someone tries to close us */
7843   gtk_signal_connect ( GTK_OBJECT ( dialog ), "delete_event",
7844                        GTK_SIGNAL_FUNC ( delete_event ), NULL);
7845
7846   /* we need to realize the window because we use pixmaps for 
7847    * items on the toolbar in the context of it */
7848   gtk_widget_realize ( dialog );
7849
7850   /* to make it nice we'll put the toolbar into the handle box, 
7851    * so that it can be detached from the main window */
7852   handlebox = gtk_handle_box_new ();
7853   gtk_box_pack_start ( GTK_BOX ( GTK_DIALOG(dialog)->vbox ),
7854                        handlebox, FALSE, FALSE, 5 );
7855 </verb></tscreen>
7856
7857 The above should be similar to any other GTK application. Just
7858 initialization of GTK, creating the window, etc. There is only one
7859 thing that probably needs some explanation: a handle box. A handle box
7860 is just another box that can be used to pack widgets in to. The
7861 difference between it and typical boxes is that it can be detached
7862 from a parent window (or, in fact, the handle box remains in the
7863 parent, but it is reduced to a very small rectangle, while all of its
7864 contents are reparented to a new freely floating window). It is
7865 usually nice to have a detachable toolbar, so these two widgets occur
7866 together quite often.
7867
7868 <tscreen><verb>
7869   /* toolbar will be horizontal, with both icons and text, and
7870    * with 5pxl spaces between items and finally, 
7871    * we'll also put it into our handlebox */
7872   toolbar = gtk_toolbar_new ( GTK_ORIENTATION_HORIZONTAL,
7873                               GTK_TOOLBAR_BOTH );
7874   gtk_container_set_border_width ( GTK_CONTAINER ( toolbar ) , 5 );
7875   gtk_toolbar_set_space_size ( GTK_TOOLBAR ( toolbar ), 5 );
7876   gtk_container_add ( GTK_CONTAINER ( handlebox ) , toolbar );
7877
7878   /* now we create icon with mask: we'll reuse it to create
7879    * icon widgets for toolbar items */
7880   icon = gdk_pixmap_create_from_xpm_d ( dialog->window, &amp;mask,
7881       &amp;dialog->style->white, gtk_xpm );
7882 </verb></tscreen>
7883
7884 Well, what we do above is just a straightforward initialization of
7885 the toolbar widget and creation of a GDK pixmap with its mask. If you
7886 want to know something more about using pixmaps, refer to GDK
7887 documentation or to the <ref id="sec_Pixmaps" name="Pixmaps"> section
7888 earlier in this tutorial.
7889
7890 <tscreen><verb>
7891   /* our first item is <close> button */
7892   iconw = gtk_pixmap_new ( icon, mask ); /* icon widget */
7893   close_button = 
7894     gtk_toolbar_append_item ( GTK_TOOLBAR (toolbar), /* our toolbar */
7895                               "Close",               /* button label */
7896                               "Closes this app",     /* this button's tooltip */
7897                               "Private",             /* tooltip private info */
7898                               iconw,                 /* icon widget */
7899                               GTK_SIGNAL_FUNC (delete_event), /* a signal */
7900                                NULL );
7901   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) ); /* space after item */
7902 </verb></tscreen>
7903
7904 In the above code you see the simplest case: adding a button to
7905 toolbar.  Just before appending a new item, we have to construct a
7906 pixmap widget to serve as an icon for this item; this step will have
7907 to be repeated for each new item. Just after the item we also add a
7908 space, so the following items will not touch each other. As you see
7909 gtk_toolbar_append_item returns a pointer to our newly created button
7910 widget, so that we can work with it in the normal way.
7911
7912 <tscreen><verb>
7913   /* now, let's make our radio buttons group... */
7914   iconw = gtk_pixmap_new ( icon, mask );
7915   icon_button = gtk_toolbar_append_element(
7916                     GTK_TOOLBAR(toolbar),
7917                     GTK_TOOLBAR_CHILD_RADIOBUTTON, /* a type of element */
7918                     NULL,                          /* pointer to widget */
7919                     "Icon",                        /* label */
7920                     "Only icons in toolbar",       /* tooltip */
7921                     "Private",                     /* tooltip private string */
7922                     iconw,                         /* icon */
7923                     GTK_SIGNAL_FUNC (radio_event), /* signal */
7924                     toolbar);                      /* data for signal */
7925   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7926 </verb></tscreen>
7927
7928 Here we begin creating a radio buttons group. To do this we use
7929 gtk_toolbar_append_element.  In fact, using this function one can also
7930 +add simple items or even spaces (type = <tt/GTK_TOOLBAR_CHILD_SPACE/
7931 or +<tt/GTK_TOOLBAR_CHILD_BUTTON/). In the above case we start
7932 creating a radio group. In creating other radio buttons for this group
7933 a pointer to the previous button in the group is required, so that a
7934 list of buttons can be easily constructed (see the section on <ref
7935 id="sec_Radio_Buttons" name="Radio Buttons"> earlier in this
7936 tutorial).
7937
7938 <tscreen><verb>
7939   /* following radio buttons refer to previous ones */
7940   iconw = gtk_pixmap_new ( icon, mask );
7941   text_button = 
7942     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7943                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
7944                                icon_button,
7945                                "Text",
7946                                "Only texts in toolbar",
7947                                "Private",
7948                                iconw,
7949                                GTK_SIGNAL_FUNC (radio_event),
7950                                toolbar);
7951   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7952                                           
7953   iconw = gtk_pixmap_new ( icon, mask );
7954   both_button = 
7955     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7956                                GTK_TOOLBAR_CHILD_RADIOBUTTON,
7957                                text_button,
7958                                "Both",
7959                                "Icons and text in toolbar",
7960                                "Private",
7961                                iconw,
7962                                GTK_SIGNAL_FUNC (radio_event),
7963                                toolbar);
7964   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7965   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_button),TRUE);
7966 </verb></tscreen>
7967
7968 In the end we have to set the state of one of the buttons manually
7969 (otherwise they all stay in active state, preventing us from switching
7970 between them).
7971
7972 <tscreen><verb>
7973   /* here we have just a simple toggle button */
7974   iconw = gtk_pixmap_new ( icon, mask );
7975   tooltips_button = 
7976     gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
7977                                GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
7978                                NULL,
7979                                "Tooltips",
7980                                "Toolbar with or without tips",
7981                                "Private",
7982                                iconw,
7983                                GTK_SIGNAL_FUNC (toggle_event),
7984                                toolbar);
7985   gtk_toolbar_append_space ( GTK_TOOLBAR ( toolbar ) );
7986   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltips_button),TRUE);
7987 </verb></tscreen>
7988
7989 A toggle button can be created in the obvious way (if one knows how to create
7990 radio buttons already).
7991
7992 <tscreen><verb>
7993   /* to pack a widget into toolbar, we only have to 
7994    * create it and append it with an appropriate tooltip */
7995   entry = gtk_entry_new ();
7996   gtk_toolbar_append_widget( GTK_TOOLBAR (toolbar), 
7997                              entry, 
7998                              "This is just an entry", 
7999                              "Private" );
8000
8001   /* well, it isn't created within thetoolbar, so we must still show it */
8002   gtk_widget_show ( entry );
8003 </verb></tscreen>
8004
8005 As you see, adding any kind of widget to a toolbar is simple. The
8006 one thing you have to remember is that this widget must be shown manually
8007 (contrary to other items which will be shown together with the toolbar).
8008
8009 <tscreen><verb>
8010   /* that's it ! let's show everything. */
8011   gtk_widget_show ( toolbar );
8012   gtk_widget_show (handlebox);
8013   gtk_widget_show ( dialog );
8014
8015   /* rest in gtk_main and wait for the fun to begin! */
8016   gtk_main ();
8017   
8018   return 0;
8019 }
8020 </verb></tscreen>
8021
8022 So, here we are at the end of toolbar tutorial. Of course, to appreciate
8023 it in full you need also this nice XPM icon, so here it is:
8024
8025 <tscreen><verb>
8026 /* XPM */
8027 static char * gtk_xpm[] = {
8028 "32 39 5 1",
8029 ".      c none",
8030 "+      c black",
8031 "@      c #3070E0",
8032 "#      c #F05050",
8033 "$      c #35E035",
8034 "................+...............",
8035 "..............+++++.............",
8036 "............+++++@@++...........",
8037 "..........+++++@@@@@@++.........",
8038 "........++++@@@@@@@@@@++........",
8039 "......++++@@++++++++@@@++.......",
8040 ".....+++@@@+++++++++++@@@++.....",
8041 "...+++@@@@+++@@@@@@++++@@@@+....",
8042 "..+++@@@@+++@@@@@@@@+++@@@@@++..",
8043 ".++@@@@@@+++@@@@@@@@@@@@@@@@@@++",
8044 ".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+",
8045 ".+##++@@@@+++@@@+++++@@@@@@@@$@.",
8046 ".+###++@@@@+++@@@+++@@@@@++$$$@.",
8047 ".+####+++@@@+++++++@@@@@+@$$$$@.",
8048 ".+#####+++@@@@+++@@@@++@$$$$$$+.",
8049 ".+######++++@@@@@@@++@$$$$$$$$+.",
8050 ".+#######+##+@@@@+++$$$$$$@@$$+.",
8051 ".+###+++##+##+@@++@$$$$$$++$$$+.",
8052 ".+###++++##+##+@@$$$$$$$@+@$$@+.",
8053 ".+###++++++#+++@$$@+@$$@++$$$@+.",
8054 ".+####+++++++#++$$@+@$$++$$$$+..",
8055 ".++####++++++#++$$@+@$++@$$$$+..",
8056 ".+#####+++++##++$$++@+++$$$$$+..",
8057 ".++####+++##+#++$$+++++@$$$$$+..",
8058 ".++####+++####++$$++++++@$$$@+..",
8059 ".+#####++#####++$$+++@++++@$@+..",
8060 ".+#####++#####++$$++@$$@+++$@@..",
8061 ".++####++#####++$$++$$$$$+@$@++.",
8062 ".++####++#####++$$++$$$$$$$$+++.",
8063 ".+++####+#####++$$++$$$$$$$@+++.",
8064 "..+++#########+@$$+@$$$$$$+++...",
8065 "...+++########+@$$$$$$$$@+++....",
8066 ".....+++######+@$$$$$$$+++......",
8067 "......+++#####+@$$$$$@++........",
8068 ".......+++####+@$$$$+++.........",
8069 ".........++###+$$$@++...........",
8070 "..........++##+$@+++............",
8071 "...........+++++++..............",
8072 ".............++++..............."};
8073 </verb></tscreen>
8074
8075 <!-- ----------------------------------------------------------------- -->
8076 <sect1> Notebooks
8077 <p>
8078 The NoteBook Widget is a collection of "pages" that overlap each
8079 other, each page contains different information with only one page
8080 visible at a time. This widget has become more common lately in GUI
8081 programming, and it is a good way to show blocks of similar
8082 information that warrant separation in their display.
8083
8084 The first function call you will need to know, as you can probably
8085 guess by now, is used to create a new notebook widget.
8086
8087 <tscreen><verb>
8088 GtkWidget *gtk_notebook_new( void );
8089 </verb></tscreen>
8090
8091 Once the notebook has been created, there are a number of functions
8092 that operate on the notebook widget. Let's look at them individually.
8093
8094 The first one we will look at is how to position the page indicators.
8095 These page indicators or "tabs" as they are referred to, can be
8096 positioned in four ways: top, bottom, left, or right.
8097
8098 <tscreen><verb>
8099 void gtk_notebook_set_tab_pos( GtkNotebook     *notebook,
8100                                GtkPositionType  pos );
8101 </verb></tscreen>
8102
8103 GtkPositionType will be one of the following, which are pretty self
8104 explanatory:
8105 <tscreen><verb>
8106   GTK_POS_LEFT
8107   GTK_POS_RIGHT
8108   GTK_POS_TOP
8109   GTK_POS_BOTTOM
8110 </verb></tscreen>
8111
8112 <tt/GTK_POS_TOP/ is the default.
8113
8114 Next we will look at how to add pages to the notebook. There are three
8115 ways to add pages to the NoteBook. Let's look at the first two
8116 together as they are quite similar.
8117
8118 <tscreen><verb>
8119 void gtk_notebook_append_page( GtkNotebook *notebook,
8120                                GtkWidget   *child,
8121                                GtkWidget   *tab_label );
8122
8123 void gtk_notebook_prepend_page( GtkNotebook *notebook,
8124                                 GtkWidget   *child,
8125                                 GtkWidget   *tab_label );
8126 </verb></tscreen>
8127
8128 These functions add pages to the notebook by inserting them from the
8129 back of the notebook (append), or the front of the notebook (prepend).
8130 <tt/child/ is the widget that is placed within the notebook page, and
8131 <tt/tab_label/ is the label for the page being added. The <tt/child/
8132 widget must be created separately, and is typically a set of options
8133 setup witin one of the other container widgets, such as a table.
8134
8135 The final function for adding a page to the notebook contains all of
8136 the properties of the previous two, but it allows you to specify what
8137 position you want the page to be in the notebook.
8138
8139 <tscreen><verb>
8140 void gtk_notebook_insert_page( GtkNotebook *notebook,
8141                                GtkWidget   *child,
8142                                GtkWidget   *tab_label,
8143                                gint         position );
8144 </verb></tscreen>
8145
8146 The parameters are the same as _append_ and _prepend_ except it
8147 contains an extra parameter, <tt/position/.  This parameter is used to
8148 specify what place this page will be inserted into the first page
8149 having position zero.
8150
8151 Now that we know how to add a page, lets see how we can remove a page
8152 from the notebook.
8153
8154 <tscreen><verb>
8155 void gtk_notebook_remove_page( GtkNotebook *notebook,
8156                                gint         page_num );
8157 </verb></tscreen>
8158
8159 This function takes the page specified by <tt/page_num/ and removes it
8160 from the widget pointed to by <tt/notebook/.
8161
8162 To find out what the current page is in a notebook use the function:
8163
8164 <tscreen><verb>
8165 gint gtk_notebook_get_current_page( GtkNotebook *notebook );
8166 </verb></tscreen>
8167
8168 These next two functions are simple calls to move the notebook page
8169 forward or backward. Simply provide the respective function call with
8170 the notebook widget you wish to operate on. Note: When the NoteBook is
8171 currently on the last page, and gtk_notebook_next_page is called, the
8172 notebook will wrap back to the first page. Likewise, if the NoteBook
8173 is on the first page, and gtk_notebook_prev_page is called, the
8174 notebook will wrap to the last page.
8175
8176 <tscreen><verb>
8177 void gtk_notebook_next_page( GtkNoteBook *notebook );
8178
8179 void gtk_notebook_prev_page( GtkNoteBook *notebook );
8180 </verb></tscreen>
8181
8182 This next function sets the "active" page. If you wish the notebook to
8183 be opened to page 5 for example, you would use this function.  Without
8184 using this function, the notebook defaults to the first page.
8185
8186 <tscreen><verb>
8187 void gtk_notebook_set_page( GtkNotebook *notebook,
8188                             gint         page_num );
8189 </verb></tscreen>
8190
8191 The next two functions add or remove the notebook page tabs and the
8192 notebook border respectively.
8193
8194 <tscreen><verb>
8195 void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
8196                                  gboolean     show_tabs);
8197
8198 void gtk_notebook_set_show_border( GtkNotebook *notebook,
8199                                    gboolean     show_border );
8200 </verb></tscreen>
8201
8202 The next function is useful when the you have a large number of pages,
8203 and the tabs don't fit on the page. It allows the tabs to be scrolled
8204 through using two arrow buttons.
8205
8206 <tscreen><verb>
8207 void gtk_notebook_set_scrollable( GtkNotebook *notebook,
8208                                   gboolean     scrollable );
8209 </verb></tscreen>
8210
8211 <tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
8212 TRUE or FALSE.
8213
8214 Now let's look at an example, it is expanded from the testgtk.c code
8215 that comes with the GTK distribution. This small program creates a
8216 window with a notebook and six buttons. The notebook contains 11
8217 pages, added in three different ways, appended, inserted, and
8218 prepended. The buttons allow you rotate the tab positions, add/remove
8219 the tabs and border, remove a page, change pages in both a forward and
8220 backward manner, and exit the program.
8221
8222 <tscreen><verb>
8223 /* example-start notebook notebook.c */
8224
8225 #include <stdio.h>
8226 #include <gtk/gtk.h>
8227
8228 /* This function rotates the position of the tabs */
8229 void rotate_book( GtkButton   *button,
8230                   GtkNotebook *notebook )
8231 {
8232     gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
8233 }
8234
8235 /* Add/Remove the page tabs and the borders */
8236 void tabsborder_book( GtkButton   *button,
8237                       GtkNotebook *notebook )
8238 {
8239     gint tval = FALSE;
8240     gint bval = FALSE;
8241     if (notebook->show_tabs == 0)
8242             tval = TRUE; 
8243     if (notebook->show_border == 0)
8244             bval = TRUE;
8245     
8246     gtk_notebook_set_show_tabs (notebook, tval);
8247     gtk_notebook_set_show_border (notebook, bval);
8248 }
8249
8250 /* Remove a page from the notebook */
8251 void remove_book( GtkButton   *button,
8252                   GtkNotebook *notebook )
8253 {
8254     gint page;
8255     
8256     page = gtk_notebook_get_current_page(notebook);
8257     gtk_notebook_remove_page (notebook, page);
8258     /* Need to refresh the widget -- 
8259      This forces the widget to redraw itself. */
8260     gtk_widget_draw(GTK_WIDGET(notebook), NULL);
8261 }
8262
8263 gint delete( GtkWidget *widget,
8264              GtkWidget *event,
8265              gpointer   data )
8266 {
8267     gtk_main_quit();
8268     return(FALSE);
8269 }
8270
8271 int main( int argc,
8272           char *argv[] )
8273 {
8274     GtkWidget *window;
8275     GtkWidget *button;
8276     GtkWidget *table;
8277     GtkWidget *notebook;
8278     GtkWidget *frame;
8279     GtkWidget *label;
8280     GtkWidget *checkbutton;
8281     int i;
8282     char bufferf[32];
8283     char bufferl[32];
8284     
8285     gtk_init (&amp;argc, &amp;argv);
8286     
8287     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8288     
8289     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
8290                         GTK_SIGNAL_FUNC (delete), NULL);
8291     
8292     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8293
8294     table = gtk_table_new(3,6,FALSE);
8295     gtk_container_add (GTK_CONTAINER (window), table);
8296     
8297     /* Create a new notebook, place the position of the tabs */
8298     notebook = gtk_notebook_new ();
8299     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
8300     gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
8301     gtk_widget_show(notebook);
8302     
8303     /* Let's append a bunch of pages to the notebook */
8304     for (i=0; i < 5; i++) {
8305         sprintf(bufferf, "Append Frame %d", i+1);
8306         sprintf(bufferl, "Page %d", i+1);
8307         
8308         frame = gtk_frame_new (bufferf);
8309         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
8310         gtk_widget_set_usize (frame, 100, 75);
8311         gtk_widget_show (frame);
8312         
8313         label = gtk_label_new (bufferf);
8314         gtk_container_add (GTK_CONTAINER (frame), label);
8315         gtk_widget_show (label);
8316         
8317         label = gtk_label_new (bufferl);
8318         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
8319     }
8320       
8321     /* Now let's add a page to a specific spot */
8322     checkbutton = gtk_check_button_new_with_label ("Check me please!");
8323     gtk_widget_set_usize(checkbutton, 100, 75);
8324     gtk_widget_show (checkbutton);
8325    
8326     label = gtk_label_new ("Add page");
8327     gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
8328     
8329     /* Now finally let's prepend pages to the notebook */
8330     for (i=0; i < 5; i++) {
8331         sprintf(bufferf, "Prepend Frame %d", i+1);
8332         sprintf(bufferl, "PPage %d", i+1);
8333         
8334         frame = gtk_frame_new (bufferf);
8335         gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
8336         gtk_widget_set_usize (frame, 100, 75);
8337         gtk_widget_show (frame);
8338         
8339         label = gtk_label_new (bufferf);
8340         gtk_container_add (GTK_CONTAINER (frame), label);
8341         gtk_widget_show (label);
8342         
8343         label = gtk_label_new (bufferl);
8344         gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
8345     }
8346     
8347     /* Set what page to start at (page 4) */
8348     gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
8349
8350     /* Create a bunch of buttons */
8351     button = gtk_button_new_with_label ("close");
8352     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
8353                                GTK_SIGNAL_FUNC (delete), NULL);
8354     gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
8355     gtk_widget_show(button);
8356     
8357     button = gtk_button_new_with_label ("next page");
8358     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
8359                                (GtkSignalFunc) gtk_notebook_next_page,
8360                                GTK_OBJECT (notebook));
8361     gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
8362     gtk_widget_show(button);
8363     
8364     button = gtk_button_new_with_label ("prev page");
8365     gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
8366                                (GtkSignalFunc) gtk_notebook_prev_page,
8367                                GTK_OBJECT (notebook));
8368     gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
8369     gtk_widget_show(button);
8370     
8371     button = gtk_button_new_with_label ("tab position");
8372     gtk_signal_connect (GTK_OBJECT (button), "clicked",
8373                         (GtkSignalFunc) rotate_book,
8374                         GTK_OBJECT(notebook));
8375     gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
8376     gtk_widget_show(button);
8377     
8378     button = gtk_button_new_with_label ("tabs/border on/off");
8379     gtk_signal_connect (GTK_OBJECT (button), "clicked",
8380                         (GtkSignalFunc) tabsborder_book,
8381                         GTK_OBJECT (notebook));
8382     gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
8383     gtk_widget_show(button);
8384     
8385     button = gtk_button_new_with_label ("remove page");
8386     gtk_signal_connect (GTK_OBJECT (button), "clicked",
8387                         (GtkSignalFunc) remove_book,
8388                         GTK_OBJECT(notebook));
8389     gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
8390     gtk_widget_show(button);
8391     
8392     gtk_widget_show(table);
8393     gtk_widget_show(window);
8394     
8395     gtk_main ();
8396     
8397     return(0);
8398 }
8399 /* example-end */
8400 </verb></tscreen>
8401
8402 I hope this helps you on your way with creating notebooks for your
8403 GTK applications.
8404
8405 <!-- ***************************************************************** -->
8406 <sect>CList Widget
8407 <!-- ***************************************************************** -->
8408
8409 <!-- ----------------------------------------------------------------- -->
8410 <p>
8411 The CList widget has replaced the List widget (which is still
8412 available).
8413
8414 The CList widget is a multi-column list widget that is capable of
8415 handling literally thousands of rows of information. Each column can
8416 optionally have a title, which itself is optionally active, allowing
8417 us to bind a function to its selection.
8418
8419 <!-- ----------------------------------------------------------------- -->
8420 <sect1>Creating a CList widget
8421 <p>
8422 Creating a CList is quite straightforward, once you have learned
8423 about widgets in general. It provides the almost standard two ways,
8424 that is the hard way, and the easy way. But before we create it, there
8425 is one thing we should figure out beforehand: how many columns should
8426 it have?
8427
8428 Not all columns have to be visible and can be used to store data that
8429 is related to a certain cell in the list.
8430
8431 <tscreen><verb>
8432 GtkWidget *gtk_clist_new ( gint columns );
8433
8434 GtkWidget *gtk_clist_new_with_titles( gint   columns,
8435                                       gchar *titles[] );
8436 </verb></tscreen>
8437
8438 The first form is very straightforward, the second might require some
8439 explanation. Each column can have a title associated with it, and this
8440 title can be a label or a button that reacts when we click on it. If
8441 we use the second form, we must provide pointers to the title texts,
8442 and the number of pointers should equal the number of columns
8443 specified. Of course we can always use the first form, and manually
8444 add titles later.
8445
8446 Note: The CList widget does not have its own scrollbars and should
8447 be placed within a ScrolledWindow widget if your require this
8448 functionality. This is a change from the GTK 1.0 implementation.
8449
8450 <!-- ----------------------------------------------------------------- -->
8451 <sect1>Modes of operation
8452 <p>
8453 There are several attributes that can be used to alter the behaviour of
8454 a CList. First there is
8455
8456 <tscreen><verb>
8457 void gtk_clist_set_selection_mode( GtkCList         *clist,
8458                                    GtkSelectionMode  mode );
8459 </verb></tscreen>
8460
8461 which, as the name implies, sets the selection mode of the
8462 CList. The first argument is the CList widget, and the second
8463 specifies the cell selection mode (they are defined in gtkenums.h). At
8464 the time of this writing, the following modes are available to us:
8465
8466 <itemize>
8467 <item> <tt/GTK_SELECTION_SINGLE/ - The selection is either NULL or contains
8468 a GList pointer for a single selected item.
8469
8470 <item> <tt/GTK_SELECTION_BROWSE/ - The selection is NULL if the list
8471 contains no widgets or insensitive ones only, otherwise it contains a
8472 GList pointer for one GList structure, and therefore exactly one list
8473 item.
8474
8475 <item> <tt/GTK_SELECTION_MULTIPLE/ - The selection is NULL if no list items
8476 are selected or a GList pointer for the first selected item. That in
8477 turn points to a GList structure for the second selected item and so
8478 on. This is currently the <bf>default</bf> for the CList widget.
8479
8480 <item> <tt/GTK_SELECTION_EXTENDED/ - The selection is always NULL.
8481 </itemize>
8482
8483 Others might be added in later revisions of GTK.
8484
8485 We can also define what the border of the CList widget should look
8486 like. It is done through
8487
8488 <tscreen><verb>
8489 void gtk_clist_set_shadow_type( GtkCList      *clist,
8490                                 GtkShadowType  border );
8491 </verb></tscreen>
8492
8493 The possible values for the second argument are
8494
8495 <tscreen><verb>
8496   GTK_SHADOW_NONE
8497   GTK_SHADOW_IN
8498   GTK_SHADOW_OUT
8499   GTK_SHADOW_ETCHED_IN
8500   GTK_SHADOW_ETCHED_OUT
8501 </verb></tscreen>
8502
8503 <!-- ----------------------------------------------------------------- -->
8504 <sect1>Working with titles
8505 <p>
8506 When you create a CList widget, you will also get a set of title
8507 buttons automatically. They live in the top of the CList window, and
8508 can act either as normal buttons that respond to being pressed, or
8509 they can be passive, in which case they are nothing more than a
8510 title. There are four different calls that aid us in setting the
8511 status of the title buttons.
8512
8513 <tscreen><verb>
8514 void gtk_clist_column_title_active( GtkCList *clist,
8515                                      gint     column );
8516
8517 void gtk_clist_column_title_passive( GtkCList *clist,
8518                                      gint      column );
8519
8520 void gtk_clist_column_titles_active( GtkCList *clist );
8521
8522 void gtk_clist_column_titles_passive( GtkCList *clist );
8523 </verb></tscreen>
8524
8525 An active title is one which acts as a normal button, a passive one is
8526 just a label. The first two calls above will activate/deactivate the
8527 title button above the specific column, while the last two calls
8528 activate/deactivate all title buttons in the supplied clist widget.
8529
8530 But of course there are those cases when we don't want them at all,
8531 and so they can be hidden and shown at will using the following two
8532 calls.
8533
8534 <tscreen><verb>
8535 void gtk_clist_column_titles_show( GtkCList *clist );
8536
8537 void gtk_clist_column_titles_hide( GtkCList *clist );
8538 </verb></tscreen>
8539
8540 For titles to be really useful we need a mechanism to set and change
8541 them, and this is done using
8542
8543 <tscreen><verb>
8544 void gtk_clist_set_column_title( GtkCList *clist,
8545                                  gint      column,
8546                                  gchar    *title );
8547 </verb></tscreen>
8548
8549 Note that only the title of one column can be set at a time, so if all
8550 the titles are known from the beginning, then I really suggest using
8551 gtk_clist_new_with_titles (as described above) to set them. It saves
8552 you coding time, and makes your program smaller. There are some cases
8553 where getting the job done the manual way is better, and that's when
8554 not all titles will be text. CList provides us with title buttons
8555 that can in fact incorporate whole widgets, for example a pixmap. It's
8556 all done through
8557
8558 <tscreen><verb>
8559 void gtk_clist_set_column_widget( GtkCList  *clist,
8560                                   gint       column,
8561                                   GtkWidget *widget );
8562 </verb></tscreen>
8563
8564 which should require no special explanation.
8565
8566 <!-- ----------------------------------------------------------------- -->
8567 <sect1>Manipulating the list itself
8568 <p>
8569 It is possible to change the justification for a column, and it is
8570 done through
8571
8572 <tscreen><verb>
8573 void gtk_clist_set_column_justification( GtkCList         *clist,
8574                                          gint              column,
8575                                          GtkJustification  justification );
8576 </verb></tscreen>
8577
8578 The GtkJustification type can take the following values:
8579
8580 <itemize>
8581 <item><tt/GTK_JUSTIFY_LEFT/ - The text in the column will begin from the
8582 left edge.
8583
8584 <item><tt/GTK_JUSTIFY_RIGHT/ - The text in the column will begin from the
8585 right edge.
8586
8587 <item><tt/GTK_JUSTIFY_CENTER/ - The text is placed in the center of the
8588 column.
8589
8590 <item><tt/GTK_JUSTIFY_FILL/ - The text will use up all available space in
8591 the column. It is normally done by inserting extra blank spaces
8592 between words (or between individual letters if it's a single
8593 word). Much in the same way as any ordinary WYSIWYG text editor.
8594 </itemize>
8595
8596 The next function is a very important one, and should be standard in
8597 the setup of all CList widgets. When the list is created, the width
8598 of the various columns are chosen to match their titles, and since
8599 this is seldom the right width we have to set it using
8600
8601 <tscreen><verb>
8602 void gtk_clist_set_column_width( GtkCList *clist,
8603                                  gint      column,
8604                                  gint      width );
8605 </verb></tscreen>
8606
8607 Note that the width is given in pixels and not letters. The same goes
8608 for the height of the cells in the columns, but as the default value
8609 is the height of the current font this isn't as critical to the
8610 application. Still, it is done through
8611
8612 <tscreen><verb>
8613 void gtk_clist_set_row_height( GtkCList *clist,
8614                                gint      height );
8615 </verb></tscreen>
8616
8617 Again, note that the height is given in pixels.
8618
8619 We can also move the list around without user interaction, however, it
8620 does require that we know what we are looking for. Or in other words,
8621 we need the row and column of the item we want to scroll to.
8622
8623 <tscreen><verb>
8624 void gtk_clist_moveto( GtkCList *clist,
8625                        gint      row,
8626                        gint      column,
8627                        gfloat    row_align,
8628                        gfloat    col_align );
8629 </verb></tscreen>
8630
8631 The gfloat row_align is pretty important to understand. It's a value
8632 between 0.0 and 1.0, where 0.0 means that we should scroll the list so
8633 the row appears at the top, while if the value of row_align is 1.0,
8634 the row will appear at the bottom instead. All other values between
8635 0.0 and 1.0 are also valid and will place the row between the top and
8636 the bottom. The last argument, gfloat col_align works in the same way,
8637 though 0.0 marks left and 1.0 marks right instead.
8638
8639 Depending on the application's needs, we don't have to scroll to an
8640 item that is already visible to us. So how do we know if it is
8641 visible? As usual, there is a function to find that out as well.
8642
8643 <tscreen><verb>
8644 GtkVisibility gtk_clist_row_is_visible( GtkCList *clist,
8645                                         gint      row );
8646 </verb></tscreen>
8647
8648 The return value is is one of the following:
8649
8650 <tscreen><verb>
8651   GTK_VISIBILITY_NONE
8652   GTK_VISIBILITY_PARTIAL
8653   GTK_VISIBILITY_FULL
8654 </verb></tscreen>
8655
8656 Note that it will only tell us if a row is visible. Currently there is
8657 no way to determine this for a column. We can get partial information
8658 though, because if the return is <tt/GTK_VISIBILITY_PARTIAL/, then
8659 some of it is hidden, but we don't know if it is the row that is being
8660 cut by the lower edge of the listbox, or if the row has columns that
8661 are outside.
8662
8663 We can also change both the foreground and background colors of a
8664 particular row. This is useful for marking the row selected by the
8665 user, and the two functions that is used to do it are
8666
8667 <tscreen><verb>
8668 void gtk_clist_set_foreground( GtkCList *clist,
8669                                gint      row,
8670                                GdkColor *color );
8671
8672 void gtk_clist_set_background( GtkCList *clist,
8673                                gint      row,
8674                                GdkColor *color );
8675 </verb></tscreen>
8676
8677 Please note that the colors must have been previously allocated.
8678
8679 <!-- ----------------------------------------------------------------- -->
8680 <sect1>Adding rows to the list
8681 <p>
8682 We can add rows in three ways. They can be prepended or appended to
8683 the list using
8684
8685 <tscreen><verb>
8686 gint gtk_clist_prepend( GtkCList *clist,
8687                         gchar    *text[] );
8688
8689 gint gtk_clist_append( GtkCList *clist,
8690                        gchar    *text[] );
8691 </verb></tscreen>
8692
8693 The return value of these two functions indicate the index of the row
8694 that was just added. We can insert a row at a given place using
8695
8696 <tscreen><verb>
8697 void gtk_clist_insert( GtkCList *clist,
8698                        gint      row,
8699                        gchar    *text[] );
8700 </verb></tscreen>
8701
8702 In these calls we have to provide a collection of pointers that are
8703 the texts we want to put in the columns. The number of pointers should
8704 equal the number of columns in the list. If the text[] argument is
8705 NULL, then there will be no text in the columns of the row. This is
8706 useful, for example, if we want to add pixmaps instead (something that
8707 has to be done manually).
8708
8709 Also, please note that the numbering of both rows and columns start at 0.
8710
8711 To remove an individual row we use
8712
8713 <tscreen><verb>
8714 void gtk_clist_remove( GtkCList *clist,
8715                        gint      row );
8716 </verb></tscreen>
8717
8718 There is also a call that removes all rows in the list. This is a lot
8719 faster than calling gtk_clist_remove once for each row, which is the
8720 only alternative.
8721
8722 <tscreen><verb>
8723 void gtk_clist_clear( GtkCList *clist );
8724 </verb></tscreen>
8725
8726 There are also two convenience functions that should be used when a
8727 lot of changes have to be made to the list. This is to prevent the
8728 list flickering while being repeatedly updated, which may be highly
8729 annoying to the user. So instead it is a good idea to freeze the list,
8730 do the updates to it, and finally thaw it which causes the list to be
8731 updated on the screen.
8732
8733 <tscreen><verb>
8734 void gtk_clist_freeze( GtkCList * clist );
8735
8736 void gtk_clist_thaw( GtkCList * clist );
8737 </verb></tscreen>
8738
8739 <!-- ----------------------------------------------------------------- -->
8740 <sect1>Setting text and pixmaps in the cells
8741 <p>
8742 A cell can contain a pixmap, text or both. To set them the following
8743 functions are used.
8744
8745 <tscreen><verb>
8746 void gtk_clist_set_text( GtkCList    *clist,
8747                          gint         row,
8748                          gint         column,
8749                          const gchar *text );
8750
8751 void gtk_clist_set_pixmap( GtkCList  *clist,
8752                            gint       row,
8753                            gint       column,
8754                            GdkPixmap *pixmap,
8755                            GdkBitmap *mask );
8756
8757 void gtk_clist_set_pixtext( GtkCList  *clist,
8758                             gint       row,
8759                             gint       column,
8760                             gchar     *text,
8761                             guint8     spacing,
8762                             GdkPixmap *pixmap,
8763                             GdkBitmap *mask );
8764 </verb></tscreen>
8765
8766 It's quite straightforward. All the calls have the CList as the first
8767 argument, followed by the row and column of the cell, followed by the
8768 data to be set. The <tt/spacing/ argument in gtk_clist_set_pixtext is
8769 the number of pixels between the pixmap and the beginning of the
8770 text. In all cases the data is copied into the widget.
8771
8772 To read back the data, we instead use
8773
8774 <tscreen><verb>
8775 gint gtk_clist_get_text( GtkCList  *clist,
8776                          gint       row,
8777                          gint       column,
8778                          gchar    **text );
8779
8780 gint gtk_clist_get_pixmap( GtkCList   *clist,
8781                            gint        row,
8782                            gint        column,
8783                            GdkPixmap **pixmap,
8784                            GdkBitmap **mask );
8785
8786 gint gtk_clist_get_pixtext( GtkCList   *clist,
8787                             gint        row,
8788                             gint        column,
8789                             gchar     **text,
8790                             guint8     *spacing,
8791                             GdkPixmap **pixmap,
8792                             GdkBitmap **mask );
8793 </verb></tscreen>
8794
8795 The returned pointers are all pointers to the data stored within the
8796 widget, so the referenced data should not be modified or released. It
8797 isn't necessary to read it all back in case you aren't interested. Any
8798 of the pointers that are meant for return values (all except the
8799 clist) can be NULL. So if we want to read back only the text from a
8800 cell that is of type pixtext, then we would do the following, assuming
8801 that clist, row and column already exist:
8802
8803 <tscreen><verb>
8804 gchar *mytext;
8805
8806 gtk_clist_get_pixtext(clist, row, column, &amp;mytext, NULL, NULL, NULL);
8807 </verb></tscreen>
8808
8809 There is one more call that is related to what's inside a cell in the
8810 clist, and that's
8811
8812 <tscreen><verb>
8813 GtkCellType gtk_clist_get_cell_type( GtkCList *clist,
8814                                      gint      row,
8815                                      gint      column );
8816 </verb></tscreen>
8817
8818 which returns the type of data in a cell. The return value is one of
8819
8820 <tscreen><verb>
8821   GTK_CELL_EMPTY
8822   GTK_CELL_TEXT
8823   GTK_CELL_PIXMAP
8824   GTK_CELL_PIXTEXT
8825   GTK_CELL_WIDGET
8826 </verb></tscreen>
8827
8828 There is also a function that will let us set the indentation, both
8829 vertical and horizontal, of a cell. The indentation value is of type
8830 gint, given in pixels, and can be both positive and negative.
8831
8832 <tscreen><verb>
8833 void gtk_clist_set_shift( GtkCList *clist,
8834                           gint      row,
8835                           gint      column,
8836                           gint      vertical,
8837                           gint      horizontal );
8838 </verb></tscreen>
8839
8840 <!-- ----------------------------------------------------------------- -->
8841 <sect1>Storing data pointers
8842 <p>
8843 With a CList it is possible to set a data pointer for a row. This
8844 pointer will not be visible for the user, but is merely a convenience
8845 for the programmer to associate a row with a pointer to some
8846 additional data.
8847
8848 The functions should be fairly self-explanatory by now.
8849
8850 <tscreen><verb>
8851 void gtk_clist_set_row_data( GtkCList *clist,
8852                              gint      row,
8853                              gpointer  data );
8854
8855 void gtk_clist_set_row_data_full( GtkCList         *clist,
8856                                   gint              row,
8857                                   gpointer          data,
8858                                   GtkDestroyNotify  destroy );
8859
8860 gpointer gtk_clist_get_row_data( GtkCList *clist,
8861                                  gint      row );
8862
8863 gint gtk_clist_find_row_from_data( GtkCList *clist,
8864                                    gpointer  data );
8865 </verb></tscreen>
8866
8867 <!-- ----------------------------------------------------------------- -->
8868 <sect1>Working with selections
8869 <p>
8870 There are also functions available that let us force the (un)selection
8871 of a row. These are
8872
8873 <tscreen><verb>
8874 void gtk_clist_select_row( GtkCList *clist,
8875                            gint      row,
8876                            gint      column );
8877
8878 void gtk_clist_unselect_row( GtkCList *clist,
8879                              gint      row,
8880                              gint      column );
8881 </verb></tscreen>
8882
8883 And also a function that will take x and y coordinates (for example,
8884 read from the mousepointer), and map that onto the list, returning the
8885 corresponding row and column.
8886
8887 <tscreen><verb>
8888 gint gtk_clist_get_selection_info( GtkCList *clist,
8889                                    gint      x,
8890                                    gint      y,
8891                                    gint     *row,
8892                                    gint     *column );
8893 </verb></tscreen>
8894
8895 When we detect something of interest (it might be movement of the
8896 pointer, a click somewhere in the list) we can read the pointer
8897 coordinates and find out where in the list the pointer is. Cumbersome?
8898 Luckily, there is a simpler way...
8899
8900 <!-- ----------------------------------------------------------------- -->
8901 <sect1>The signals that bring it together
8902 <p>
8903 As with all other widgets, there are a few signals that can be used. The
8904 CList widget is derived from the Container widget, and so has all the
8905 same signals, but also adds the following:
8906
8907 <itemize>
8908 <item>select_row - This signal will send the following information, in
8909 order: GtkCList *clist, gint row, gint column, GtkEventButton *event
8910
8911 <item>unselect_row - When the user unselects a row, this signal is
8912 activated. It sends the same information as select_row
8913
8914 <item>click_column - Send GtkCList *clist, gint column
8915 </itemize>
8916
8917 So if we want to connect a callback to select_row, the callback
8918 function would be declared like this
8919
8920 <tscreen><verb>
8921 void select_row_callback(GtkWidget *widget,
8922                          gint row,
8923                          gint column,
8924                          GdkEventButton *event,
8925                          gpointer data);
8926 </verb></tscreen>
8927
8928 The callback is connected as usual with
8929
8930 <tscreen><verb>
8931 gtk_signal_connect(GTK_OBJECT( clist),
8932                    "select_row"
8933                    GTK_SIGNAL_FUNC(select_row_callback),
8934                    NULL);
8935 </verb></tscreen>
8936
8937 <!-- ----------------------------------------------------------------- -->
8938 <sect1>A CList example
8939 <p>
8940
8941 <tscreen><verb>
8942 /* example-start clist clist.c */
8943
8944 #include <gtk/gtk.h>
8945
8946 /* User clicked the "Add List" button. */
8947 void button_add_clicked( gpointer data )
8948 {
8949     int indx;
8950  
8951     /* Something silly to add to the list. 4 rows of 2 columns each */
8952     gchar *drink[4][2] = { { "Milk",    "3 Oz" },
8953                            { "Water",   "6 l" },
8954                            { "Carrots", "2" },
8955                            { "Snakes",  "55" } };
8956
8957     /* Here we do the actual adding of the text. It's done once for
8958      * each row.
8959      */
8960     for ( indx=0 ; indx < 4 ; indx++ )
8961         gtk_clist_append( (GtkCList *) data, drink[indx]);
8962
8963     return;
8964 }
8965
8966 /* User clicked the "Clear List" button. */
8967 void button_clear_clicked( gpointer data )
8968 {
8969     /* Clear the list using gtk_clist_clear. This is much faster than
8970      * calling gtk_clist_remove once for each row.
8971      */
8972     gtk_clist_clear( (GtkCList *) data);
8973
8974     return;
8975 }
8976
8977 /* The user clicked the "Hide/Show titles" button. */
8978 void button_hide_show_clicked( gpointer data )
8979 {
8980     /* Just a flag to remember the status. 0 = currently visible */
8981     static short int flag = 0;
8982
8983     if (flag == 0)
8984     {
8985         /* Hide the titles and set the flag to 1 */
8986         gtk_clist_column_titles_hide((GtkCList *) data);
8987         flag++;
8988     }
8989     else
8990     {
8991         /* Show the titles and reset flag to 0 */
8992         gtk_clist_column_titles_show((GtkCList *) data);
8993         flag--;
8994     }
8995
8996     return;
8997 }
8998
8999 /* If we come here, then the user has selected a row in the list. */
9000 void selection_made( GtkWidget      *clist,
9001                      gint            row,
9002                      gint            column,
9003                      GdkEventButton *event,
9004                      gpointer        data )
9005 {
9006     gchar *text;
9007
9008     /* Get the text that is stored in the selected row and column
9009      * which was clicked in. We will receive it as a pointer in the
9010      * argument text.
9011      */
9012     gtk_clist_get_text(GTK_CLIST(clist), row, column, &amp;text);
9013
9014     /* Just prints some information about the selected row */
9015     g_print("You selected row %d. More specifically you clicked in "
9016             "column %d, and the text in this cell is %s\n\n",
9017             row, column, text);
9018
9019     return;
9020 }
9021
9022 int main( int    argc,
9023           gchar *argv[] )
9024 {                                  
9025     GtkWidget *window;
9026     GtkWidget *vbox, *hbox;
9027     GtkWidget *scrolled_window, *clist;
9028     GtkWidget *button_add, *button_clear, *button_hide_show;    
9029     gchar *titles[2] = { "Ingredients", "Amount" };
9030
9031     gtk_init(&amp;argc, &amp;argv);
9032     
9033     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
9034     gtk_widget_set_usize(GTK_WIDGET(window), 300, 150);
9035
9036     gtk_window_set_title(GTK_WINDOW(window), "GtkCList Example");
9037     gtk_signal_connect(GTK_OBJECT(window),
9038                        "destroy",
9039                        GTK_SIGNAL_FUNC(gtk_main_quit),
9040                        NULL);
9041     
9042     vbox=gtk_vbox_new(FALSE, 5);
9043     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
9044     gtk_container_add(GTK_CONTAINER(window), vbox);
9045     gtk_widget_show(vbox);
9046     
9047     /* Create a scrolled window to pack the CList widget into */
9048     scrolled_window = gtk_scrolled_window_new (NULL, NULL);
9049     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
9050                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
9051
9052     gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0);
9053     gtk_widget_show (scrolled_window);
9054
9055     /* Create the CList. For this example we use 2 columns */
9056     clist = gtk_clist_new_with_titles( 2, titles);
9057
9058     /* When a selection is made, we want to know about it. The callback
9059      * used is selection_made, and its code can be found further down */
9060     gtk_signal_connect(GTK_OBJECT(clist), "select_row",
9061                        GTK_SIGNAL_FUNC(selection_made),
9062                        NULL);
9063
9064     /* It isn't necessary to shadow the border, but it looks nice :) */
9065     gtk_clist_set_shadow_type (GTK_CLIST(clist), GTK_SHADOW_OUT);
9066
9067     /* What however is important, is that we set the column widths as
9068      * they will never be right otherwise. Note that the columns are
9069      * numbered from 0 and up (to 1 in this case).
9070      */
9071     gtk_clist_set_column_width (GTK_CLIST(clist), 0, 150);
9072
9073     /* Add the CList widget to the vertical box and show it. */
9074     gtk_container_add(GTK_CONTAINER(scrolled_window), clist);
9075     gtk_widget_show(clist);
9076
9077     /* Create the buttons and add them to the window. See the button
9078      * tutorial for more examples and comments on this.
9079      */
9080     hbox = gtk_hbox_new(FALSE, 0);
9081     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
9082     gtk_widget_show(hbox);
9083
9084     button_add = gtk_button_new_with_label("Add List");
9085     button_clear = gtk_button_new_with_label("Clear List");
9086     button_hide_show = gtk_button_new_with_label("Hide/Show titles");
9087
9088     gtk_box_pack_start(GTK_BOX(hbox), button_add, TRUE, TRUE, 0);
9089     gtk_box_pack_start(GTK_BOX(hbox), button_clear, TRUE, TRUE, 0);
9090     gtk_box_pack_start(GTK_BOX(hbox), button_hide_show, TRUE, TRUE, 0);
9091
9092     /* Connect our callbacks to the three buttons */
9093     gtk_signal_connect_object(GTK_OBJECT(button_add), "clicked",
9094                               GTK_SIGNAL_FUNC(button_add_clicked),
9095                               (gpointer) clist);
9096     gtk_signal_connect_object(GTK_OBJECT(button_clear), "clicked",
9097                               GTK_SIGNAL_FUNC(button_clear_clicked),
9098                               (gpointer) clist);
9099     gtk_signal_connect_object(GTK_OBJECT(button_hide_show), "clicked",
9100                               GTK_SIGNAL_FUNC(button_hide_show_clicked),
9101                               (gpointer) clist);
9102
9103     gtk_widget_show(button_add);
9104     gtk_widget_show(button_clear);
9105     gtk_widget_show(button_hide_show);
9106
9107     /* The interface is completely set up so we show the window and
9108      * enter the gtk_main loop.
9109      */
9110     gtk_widget_show(window);
9111     gtk_main();
9112     
9113     return(0);
9114 }
9115 /* example-end */
9116 </verb></tscreen>
9117                     
9118 <!-- ***************************************************************** -->
9119 <sect> Tree Widget <label id="sec_Tree_Widgets">
9120 <!-- ***************************************************************** -->
9121 <p>
9122 The purpose of tree widgets is to display hierarchically-organized
9123 data. The Tree widget itself is a vertical container for widgets of
9124 type TreeItem. Tree itself is not terribly different from
9125 CList - both are derived directly from Container, and the
9126 Container methods work in the same way on Tree widgets as on
9127 CList widgets. The difference is that Tree widgets can be nested
9128 within other Tree widgets. We'll see how to do this shortly.
9129
9130 The Tree widget has its own window, and defaults to a white
9131 background, as does CList. Also, most of the Tree methods work in
9132 the same way as the corresponding CList ones. However, Tree is
9133 not derived from CList, so you cannot use them interchangeably.
9134
9135
9136 <sect1> Creating a Tree
9137 <p>
9138 A Tree is created in the usual way, using:
9139
9140 <tscreen><verb>
9141 GtkWidget *gtk_tree_new( void );
9142 </verb></tscreen>
9143
9144 Like the CList widget, a Tree will simply keep growing as more
9145 items are added to it, as well as when subtrees are expanded.  For
9146 this reason, they are almost always packed into a
9147 ScrolledWindow. You might want to use gtk_widget_set_usize() on the
9148 scrolled window to ensure that it is big enough to see the tree's
9149 items, as the default size for ScrolledWindow is quite small.
9150
9151 Now that you have a tree, you'll probably want to add some items to
9152 it.  <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
9153 explains the gory details of TreeItem. For now, it'll suffice to
9154 create one, using:
9155
9156 <tscreen><verb>
9157 GtkWidget *gtk_tree_item_new_with_label( gchar *label );
9158 </verb></tscreen>
9159
9160 You can then add it to the tree using one of the following (see
9161 <ref id="sec_Tree_Functions" name="Functions and Macros">
9162 below for more options):
9163
9164 <tscreen><verb>
9165 void gtk_tree_append( GtkTree    *tree,
9166                        GtkWidget *tree_item );
9167
9168 void gtk_tree_prepend( GtkTree   *tree,
9169                        GtkWidget *tree_item );
9170 </verb></tscreen>
9171
9172 Note that you must add items to a Tree one at a time - there is no
9173 equivalent to gtk_list_*_items().
9174
9175 <!-- ----------------------------------------------------------------- -->
9176 <sect1> Adding a Subtree
9177 <p>
9178 A subtree is created like any other Tree widget. A subtree is added
9179 to another tree beneath a tree item, using:
9180
9181 <tscreen><verb>
9182 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
9183                                 GtkWidget   *subtree );
9184 </verb></tscreen>
9185
9186 You do not need to call gtk_widget_show() on a subtree before or after
9187 adding it to a TreeItem. However, you <em>must</em> have added the
9188 TreeItem in question to a parent tree before calling
9189 gtk_tree_item_set_subtree(). This is because, technically, the parent
9190 of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
9191 rather the GtkTree which holds that GtkTreeItem.
9192
9193 When you add a subtree to a TreeItem, a plus or minus sign appears
9194 beside it, which the user can click on to "expand" or "collapse" it,
9195 meaning, to show or hide its subtree. TreeItems are collapsed by
9196 default. Note that when you collapse a TreeItem, any selected
9197 items in its subtree remain selected, which may not be what the user
9198 expects.
9199
9200 <!-- ----------------------------------------------------------------- -->
9201 <sect1> Handling the Selection List
9202 <p>
9203 As with CList, the Tree type has a <tt>selection</tt> field, and
9204 it is possible to control the behaviour of the tree (somewhat) by
9205 setting the selection type using:
9206
9207 <tscreen><verb>
9208 void gtk_tree_set_selection_mode( GtkTree          *tree,
9209                                   GtkSelectionMode  mode );
9210 </verb></tscreen>
9211
9212 The semantics associated with the various selection modes are
9213 described in the section on the CList widget. As with the CList
9214 widget, the "select_child", "unselect_child" (not really - see <ref
9215 id="sec_Tree_Signals" name="Signals"> below for an explanation),
9216 and "selection_changed" signals are emitted when list items are
9217 selected or unselected. However, in order to take advantage of these
9218 signals, you need to know <em>which</em> Tree widget they will be
9219 emitted by, and where to find the list of selected items.
9220
9221 This is a source of potential confusion. The best way to explain this
9222 is that though all Tree widgets are created equal, some are more equal
9223 than others. All Tree widgets have their own X window, and can
9224 therefore receive events such as mouse clicks (if their TreeItems or
9225 their children don't catch them first!). However, to make
9226 <tt/GTK_SELECTION_SINGLE/ and <tt/GTK_SELECTION_BROWSE/ selection
9227 types behave in a sane manner, the list of selected items is specific
9228 to the topmost Tree widget in a hierarchy, known as the "root tree".
9229
9230 Thus, accessing the <tt>selection</tt> field directly in an arbitrary
9231 Tree widget is not a good idea unless you <em>know</em> it's the root
9232 tree. Instead, use the <tt/GTK_TREE_SELECTION (Tree)/ macro, which
9233 gives the root tree's selection list as a GList pointer. Of course,
9234 this list can include items that are not in the subtree in question if
9235 the selection type is <tt/GTK_SELECTION_MULTIPLE/.
9236
9237 Finally, the "select_child" (and "unselect_child", in theory) signals
9238 are emitted by all trees, but the "selection_changed" signal is only
9239 emitted by the root tree. Consequently, if you want to handle the
9240 "select_child" signal for a tree and all its subtrees, you will have
9241 to call gtk_signal_connect() for every subtree.
9242
9243 <sect1> Tree Widget Internals
9244 <p>
9245 The Tree's struct definition looks like this:
9246
9247 <tscreen><verb>
9248 struct _GtkTree
9249 {
9250   GtkContainer container;
9251
9252   GList *children;
9253   
9254   GtkTree* root_tree; /* owner of selection list */
9255   GtkWidget* tree_owner;
9256   GList *selection;
9257   guint level;
9258   guint indent_value;
9259   guint current_indent;
9260   guint selection_mode : 2;
9261   guint view_mode : 1;
9262   guint view_line : 1;
9263 };
9264 </verb></tscreen>
9265
9266 The perils associated with accessing the <tt>selection</tt> field
9267 directly have already been mentioned. The other important fields of
9268 the struct can also be accessed with handy macros or class functions.
9269 <tt/GTK_IS_ROOT_TREE (Tree)/ returns a boolean value which
9270 indicates whether a tree is the root tree in a Tree hierarchy, while
9271 <tt/GTK_TREE_ROOT_TREE (Tree)/ returns the root tree, an object of
9272 type GtkTree (so, remember to cast it using <tt/GTK_WIDGET (Tree)/ if
9273 you want to use one of the gtk_widget_*() functions on it).
9274
9275 Instead of directly accessing the children field of a Tree widget,
9276 it's probably best to cast it using >tt/GTK_CONTAINER (Tree)/, and
9277 pass it to the gtk_container_children() function. This creates a
9278 duplicate of the original list, so it's advisable to free it up using
9279 g_list_free() after you're done with it, or to iterate on it
9280 destructively, like this:
9281
9282 <tscreen><verb>
9283     children = gtk_container_children (GTK_CONTAINER (tree));
9284     while (children) {
9285       do_something_nice (GTK_TREE_ITEM (children->data));
9286       children = g_list_remove_link (children, children);
9287 }
9288 </verb></tscreen>
9289
9290 The <tt>tree_owner</tt> field is defined only in subtrees, where it
9291 points to the TreeItem widget which holds the tree in question.
9292 The <tt>level</tt> field indicates how deeply nested a particular tree
9293 is; root trees have level 0, and each successive level of subtrees has
9294 a level one greater than the parent level. This field is set only
9295 after a Tree widget is actually mapped (i.e. drawn on the screen).
9296
9297 <sect2> Signals<label id="sec_Tree_Signals">
9298 <p>
9299 <tscreen><verb>
9300 void selection_changed( GtkTree *tree );
9301 </verb></tscreen>
9302
9303 This signal will be emitted whenever the <tt>selection</tt> field of a
9304 Tree has changed. This happens when a child of the Tree is
9305 selected or deselected.
9306
9307 <tscreen><verb>
9308 void select_child( GtkTree   *tree,
9309                    GtkWidget *child );
9310 </verb></tscreen>
9311
9312 This signal is emitted when a child of the Tree is about to get
9313 selected. This happens on calls to gtk_tree_select_item(),
9314 gtk_tree_select_child(), on <em>all</em> button presses and calls to
9315 gtk_tree_item_toggle() and gtk_item_toggle().  It may sometimes be
9316 indirectly triggered on other occasions where children get added to or
9317 removed from the Tree.
9318
9319 <tscreen><verb>
9320 void unselect_child (GtkTree   *tree,
9321                      GtkWidget *child);
9322 </verb></tscreen>
9323
9324 This signal is emitted when a child of the Tree is about to get
9325 deselected. As of GTK 1.0.4, this seems to only occur on calls to
9326 gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
9327 other occasions, but <em>not</em> when a button press deselects a
9328 child, nor on emission of the "toggle" signal by gtk_item_toggle().
9329
9330 <sect2> Functions and Macros<label id="sec_Tree_Functions">
9331 <p>
9332 <tscreen><verb>
9333 guint gtk_tree_get_type( void );
9334 </verb></tscreen>
9335
9336 Returns the "GtkTree" type identifier.
9337
9338 <tscreen><verb>
9339 GtkWidget* gtk_tree_new( void );
9340 </verb></tscreen>
9341
9342 Create a new Tree object. The new widget is returned as a pointer to a
9343 GtkWidget object. NULL is returned on failure.
9344
9345 <tscreen><verb>
9346 void gtk_tree_append( GtkTree   *tree,
9347                       GtkWidget *tree_item );
9348 </verb></tscreen>
9349
9350 Append a tree item to a Tree.
9351
9352 <tscreen><verb>
9353 void gtk_tree_prepend( GtkTree   *tree,
9354                        GtkWidget *tree_item );
9355 </verb></tscreen>
9356
9357 Prepend a tree item to a Tree.
9358
9359 <tscreen><verb>
9360 void gtk_tree_insert( GtkTree   *tree,
9361                       GtkWidget *tree_item,
9362                       gint       position );
9363 </verb></tscreen>
9364
9365 Insert a tree item into a Tree at the position in the list
9366 specified by <tt>position.</tt>
9367
9368 <tscreen><verb>
9369 void gtk_tree_remove_items( GtkTree *tree,
9370                             GList   *items );
9371 </verb></tscreen>
9372
9373 Remove a list of items (in the form of a GList *) from a Tree.
9374 Note that removing an item from a tree dereferences (and thus usually)
9375 destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
9376 subtrees in that subtree. If you want to remove only one item, you
9377 can use gtk_container_remove().
9378
9379 <tscreen><verb>
9380 void gtk_tree_clear_items( GtkTree *tree,
9381                            gint     start,
9382                            gint     end );
9383 </verb></tscreen>
9384
9385 Remove the items from position <tt>start</tt> to position <tt>end</tt>
9386 from a Tree. The same warning about dereferencing applies here, as
9387 gtk_tree_clear_items() simply constructs a list and passes it to
9388 gtk_tree_remove_items().
9389
9390 <tscreen><verb>
9391 void gtk_tree_select_item( GtkTree *tree,
9392                            gint     item );
9393 </verb></tscreen>
9394
9395 Emits the "select_item" signal for the child at position
9396 <tt>item</tt>, thus selecting the child (unless you unselect it in a
9397 signal handler).
9398
9399 <tscreen><verb>
9400 void gtk_tree_unselect_item( GtkTree *tree,
9401                              gint     item );
9402 </verb></tscreen>
9403
9404 Emits the "unselect_item" signal for the child at position
9405 <tt>item</tt>, thus unselecting the child.
9406
9407 <tscreen><verb>
9408 void gtk_tree_select_child( GtkTree   *tree,
9409                             GtkWidget *tree_item );
9410 </verb></tscreen>
9411
9412 Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
9413 selecting it.
9414
9415 <tscreen><verb>
9416 void gtk_tree_unselect_child( GtkTree   *tree,
9417                               GtkWidget *tree_item );
9418 </verb></tscreen>
9419
9420 Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
9421 thus unselecting it.
9422
9423 <tscreen><verb>
9424 gint gtk_tree_child_position( GtkTree   *tree,
9425                               GtkWidget *child );
9426 </verb></tscreen>
9427
9428 Returns the position in the tree of <tt>child</tt>, unless
9429 <tt>child</tt> is not in the tree, in which case it returns -1.
9430
9431 <tscreen><verb>
9432 void gtk_tree_set_selection_mode( GtkTree          *tree,
9433                                   GtkSelectionMode  mode );
9434 </verb></tscreen>
9435
9436 Sets the selection mode, which can be one of <tt/GTK_SELECTION_SINGLE/ (the
9437 default), <tt/GTK_SELECTION_BROWSE/, <tt/GTK_SELECTION_MULTIPLE/, or
9438 <tt/GTK_SELECTION_EXTENDED/. This is only defined for root trees, which
9439 makes sense, since the root tree "owns" the selection. Setting it for
9440 subtrees has no effect at all; the value is simply ignored.
9441
9442 <tscreen><verb>
9443 void gtk_tree_set_view_mode( GtkTree         *tree,
9444                              GtkTreeViewMode  mode ); 
9445 </verb></tscreen>
9446
9447 Sets the "view mode", which can be either <tt/GTK_TREE_VIEW_LINE/ (the
9448 default) or <tt/GTK_TREE_VIEW_ITEM/.  The view mode propagates from a
9449 tree to its subtrees, and can't be set exclusively to a subtree (this
9450 is not exactly true - see the example code comments).
9451
9452 The term "view mode" is rather ambiguous - basically, it controls the
9453 way the highlight is drawn when one of a tree's children is selected.
9454 If it's <tt/GTK_TREE_VIEW_LINE/, the entire TreeItem widget is
9455 highlighted, while for <tt/GTK_TREE_VIEW_ITEM/, only the child widget
9456 (i.e., usually the label) is highlighted.
9457
9458 <tscreen><verb>
9459 void gtk_tree_set_view_lines( GtkTree *tree,
9460                               guint    flag );
9461 </verb></tscreen>
9462
9463 Controls whether connecting lines between tree items are drawn.
9464 <tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
9465 which case they aren't.
9466
9467 <tscreen><verb>
9468 GtkTree *GTK_TREE (gpointer obj);
9469 </verb></tscreen>
9470
9471 Cast a generic pointer to "GtkTree *".
9472
9473 <tscreen><verb>
9474 GtkTreeClass *GTK_TREE_CLASS (gpointer class);
9475 </verb></tscreen>
9476
9477 Cast a generic pointer to "GtkTreeClass *".
9478
9479 <tscreen><verb>
9480 gint GTK_IS_TREE (gpointer obj);
9481 </verb></tscreen>
9482
9483 Determine if a generic pointer refers to a "GtkTree" object.
9484
9485 <tscreen><verb>
9486 gint GTK_IS_ROOT_TREE (gpointer obj)
9487 </verb></tscreen>
9488
9489 Determine if a generic pointer refers to a "GtkTree" object
9490 <em>and</em> is a root tree. Though this will accept any pointer, the
9491 results of passing it a pointer that does not refer to a Tree are
9492 undefined and possibly harmful.
9493
9494 <tscreen><verb>
9495 GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
9496 </verb></tscreen>
9497
9498 Return the root tree of a pointer to a "GtkTree" object. The above
9499 warning applies.
9500
9501 <tscreen><verb>
9502 GList *GTK_TREE_SELECTION( gpointer obj)
9503 </verb></tscreen>
9504
9505 Return the selection list of the root tree of a "GtkTree" object. The
9506 above warning applies here, too.
9507
9508 <sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
9509 <p>
9510 The TreeItem widget, like CListItem, is derived from Item,
9511 which in turn is derived from Bin.  Therefore, the item itself is a
9512 generic container holding exactly one child widget, which can be of
9513 any type. The TreeItem widget has a number of extra fields, but
9514 the only one we need be concerned with is the <tt>subtree</tt> field.
9515
9516 The definition for the TreeItem struct looks like this:
9517
9518 <tscreen><verb>
9519 struct _GtkTreeItem
9520 {
9521   GtkItem item;
9522
9523   GtkWidget *subtree;
9524   GtkWidget *pixmaps_box;
9525   GtkWidget *plus_pix_widget, *minus_pix_widget;
9526
9527   GList *pixmaps;               /* pixmap node for this items color depth */
9528
9529   guint expanded : 1;
9530 };
9531 </verb></tscreen>
9532
9533 The <tt>pixmaps_box</tt> field is an EventBox which catches clicks on
9534 the plus/minus symbol which controls expansion and collapsing. The
9535 <tt>pixmaps</tt> field points to an internal data structure. Since
9536 you can always obtain the subtree of a TreeItem in a (relatively)
9537 type-safe manner with the <tt/GTK_TREE_ITEM_SUBTREE (Item)/ macro,
9538 it's probably advisable never to touch the insides of a TreeItem
9539 unless you <em>really</em> know what you're doing.
9540
9541 Since it is directly derived from an Item it can be treated as such by
9542 using the <tt/GTK_ITEM (TreeItem)/ macro. A TreeItem usually holds a
9543 label, so the convenience function gtk_list_item_new_with_label() is
9544 provided. The same effect can be achieved using code like the
9545 following, which is actually copied verbatim from
9546 gtk_tree_item_new_with_label():
9547
9548 <tscreen><verb>
9549 tree_item = gtk_tree_item_new ();
9550 label_widget = gtk_label_new (label);
9551 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
9552
9553 gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
9554 gtk_widget_show (label_widget);
9555 </verb></tscreen>
9556
9557 As one is not forced to add a Label to a TreeItem, you could
9558 also add an HBox or an Arrow, or even a Notebook (though your
9559 app will likely be quite unpopular in this case) to the TreeItem.
9560
9561 If you remove all the items from a subtree, it will be destroyed and
9562 unparented, unless you reference it beforehand, and the TreeItem
9563 which owns it will be collapsed. So, if you want it to stick around,
9564 do something like the following:
9565
9566 <tscreen><verb>
9567 gtk_widget_ref (tree);
9568 owner = GTK_TREE(tree)->tree_owner;
9569 gtk_container_remove (GTK_CONTAINER(tree), item);
9570 if (tree->parent == NULL){
9571   gtk_tree_item_expand (GTK_TREE_ITEM(owner));
9572   gtk_tree_item_set_subtree (GTK_TREE_ITEM(owner), tree);
9573 }
9574 else
9575   gtk_widget_unref (tree);
9576 </verb></tscreen>
9577
9578 Finally, drag-n-drop <em>does</em> work with TreeItems. You just
9579 have to make sure that the TreeItem you want to make into a drag
9580 item or a drop site has not only been added to a Tree, but that
9581 each successive parent widget has a parent itself, all the way back to
9582 a toplevel or dialog window, when you call gtk_widget_dnd_drag_set()
9583 or gtk_widget_dnd_drop_set().  Otherwise, strange things will happen.
9584
9585 <sect2> Signals
9586 <p>
9587 TreeItem inherits the "select", "deselect", and "toggle" signals
9588 from Item. In addition, it adds two signals of its own, "expand"
9589 and "collapse".
9590
9591 <tscreen><verb>
9592 void select( GtkItem *tree_item );
9593 </verb></tscreen>
9594
9595 This signal is emitted when an item is about to be selected, either
9596 after it has been clicked on by the user, or when the program calls
9597 gtk_tree_item_select(), gtk_item_select(), or gtk_tree_select_child().
9598
9599 <tscreen><verb>
9600 void deselect( GtkItem *tree_item );
9601 </verb></tscreen>
9602
9603 This signal is emitted when an item is about to be unselected, either
9604 after it has been clicked on by the user, or when the program calls
9605 gtk_tree_item_deselect() or gtk_item_deselect(). In the case of
9606 TreeItems, it is also emitted by gtk_tree_unselect_child(), and
9607 sometimes gtk_tree_select_child().
9608
9609 <tscreen><verb>
9610 void toggle( GtkItem *tree_item );
9611 </verb></tscreen>
9612
9613 This signal is emitted when the program calls gtk_item_toggle().  The
9614 effect it has when emitted on a TreeItem is to call
9615 gtk_tree_select_child() (and never gtk_tree_unselect_child()) on the
9616 item's parent tree, if the item has a parent tree.  If it doesn't,
9617 then the highlight is reversed on the item.
9618
9619 <tscreen><verb>
9620 void expand( GtkTreeItem *tree_item );
9621 </verb></tscreen>
9622
9623 This signal is emitted when the tree item's subtree is about to be
9624 expanded, that is, when the user clicks on the plus sign next to the
9625 item, or when the program calls gtk_tree_item_expand().
9626
9627 <tscreen><verb>
9628 void collapse( GtkTreeItem *tree_item );
9629 </verb></tscreen>
9630
9631 This signal is emitted when the tree item's subtree is about to be
9632 collapsed, that is, when the user clicks on the minus sign next to the
9633 item, or when the program calls gtk_tree_item_collapse().
9634
9635 <sect2> Functions and Macros
9636 <p>
9637 <tscreen><verb>
9638 guint gtk_tree_item_get_type( void );
9639 </verb></tscreen>
9640
9641 Returns the "GtkTreeItem" type identifier.
9642
9643 <tscreen><verb>
9644 GtkWidget* gtk_tree_item_new( void );
9645 </verb></tscreen>
9646
9647 Create a new TreeItem object. The new widget is returned as a
9648 pointer to a GtkWidget object. NULL is returned on failure.
9649
9650 <tscreen><verb>
9651 GtkWidget* gtk_tree_item_new_with_label (gchar       *label);
9652 </verb></tscreen>
9653
9654 Create a new TreeItem object, having a single GtkLabel as the sole
9655 child. The new widget is returned as a pointer to a GtkWidget
9656 object. NULL is returned on failure.
9657
9658 <tscreen><verb>
9659 void gtk_tree_item_select( GtkTreeItem *tree_item );
9660 </verb></tscreen>
9661
9662 This function is basically a wrapper around a call to
9663 <tt>gtk_item_select (GTK_ITEM (tree_item))</tt> which will emit the
9664 select signal.
9665
9666 <tscreen><verb>
9667 void gtk_tree_item_deselect( GtkTreeItem *tree_item );
9668 </verb></tscreen>
9669
9670 This function is basically a wrapper around a call to
9671 gtk_item_deselect (GTK_ITEM (tree_item)) which will emit the deselect
9672 signal.
9673
9674 <tscreen><verb>
9675 void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
9676                                 GtkWidget   *subtree );
9677 </verb></tscreen>
9678
9679 This function adds a subtree to tree_item, showing it if tree_item is
9680 expanded, or hiding it if tree_item is collapsed. Again, remember that
9681 the tree_item must have already been added to a tree for this to work.
9682
9683 <tscreen><verb>
9684 void gtk_tree_item_remove_subtree( GtkTreeItem *tree_item );
9685 </verb></tscreen>
9686
9687 This removes all of tree_item's subtree's children (thus unreferencing
9688 and destroying it, any of its children's subtrees, and so on...), then
9689 removes the subtree itself, and hides the plus/minus sign.
9690
9691 <tscreen><verb>
9692 void gtk_tree_item_expand( GtkTreeItem *tree_item );
9693 </verb></tscreen>
9694
9695 This emits the "expand" signal on tree_item, which expands it.
9696
9697 <tscreen><verb>
9698 void gtk_tree_item_collapse( GtkTreeItem *tree_item );
9699 </verb></tscreen>
9700
9701 This emits the "collapse" signal on tree_item, which collapses it.
9702
9703 <tscreen><verb>
9704 GtkTreeItem *GTK_TREE_ITEM (gpointer obj)
9705 </verb></tscreen>
9706
9707 Cast a generic pointer to "GtkTreeItem *".
9708
9709 <tscreen><verb>
9710 GtkTreeItemClass *GTK_TREE_ITEM_CLASS (gpointer obj)
9711 </verb></tscreen>
9712
9713 Cast a generic pointer to "GtkTreeItemClass".
9714
9715 <tscreen><verb>
9716 gint GTK_IS_TREE_ITEM (gpointer obj)
9717 </verb></tscreen>
9718
9719 Determine if a generic pointer refers to a "GtkTreeItem" object.
9720  
9721 <tscreen><verb>
9722 GtkWidget GTK_TREE_ITEM_SUBTREE (gpointer obj)
9723 </verb></tscreen>
9724
9725 Returns a tree item's subtree (<tt/obj/ should point to a
9726 "GtkTreeItem" object).
9727
9728 <sect1> Tree Example
9729 <p>
9730 This is somewhat like the tree example in testgtk.c, but a lot less
9731 complete (although much better commented).  It puts up a window with a
9732 tree, and connects all the signals for the relevant objects, so you
9733 can see when they are emitted.
9734
9735 <tscreen><verb>
9736 /* example-start tree tree.c */
9737
9738 #include <gtk/gtk.h>
9739
9740 /* for all the GtkItem:: and GtkTreeItem:: signals */
9741 static void cb_itemsignal( GtkWidget *item,
9742                            gchar     *signame )
9743 {
9744   gchar *name;
9745   GtkLabel *label;
9746
9747   /* It's a Bin, so it has one child, which we know to be a
9748      label, so get that */
9749   label = GTK_LABEL (GTK_BIN (item)->child);
9750   /* Get the text of the label */
9751   gtk_label_get (label, &amp;name);
9752   /* Get the level of the tree which the item is in */
9753   g_print ("%s called for item %s->%p, level %d\n", signame, name,
9754            item, GTK_TREE (item->parent)->level);
9755 }
9756
9757 /* Note that this is never called */
9758 static void cb_unselect_child( GtkWidget *root_tree,
9759                                GtkWidget *child,
9760                                GtkWidget *subtree )
9761 {
9762   g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
9763            root_tree, subtree, child);
9764 }
9765
9766 /* Note that this is called every time the user clicks on an item,
9767    whether it is already selected or not. */
9768 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
9769                              GtkWidget *subtree)
9770 {
9771   g_print ("select_child called for root tree %p, subtree %p, child %p\n",
9772            root_tree, subtree, child);
9773 }
9774
9775 static void cb_selection_changed( GtkWidget *tree )
9776 {
9777   GList *i;
9778   
9779   g_print ("selection_change called for tree %p\n", tree);
9780   g_print ("selected objects are:\n");
9781
9782   i = GTK_TREE_SELECTION(tree);
9783   while (i){
9784     gchar *name;
9785     GtkLabel *label;
9786     GtkWidget *item;
9787
9788     /* Get a GtkWidget pointer from the list node */
9789     item = GTK_WIDGET (i->data);
9790     label = GTK_LABEL (GTK_BIN (item)->child);
9791     gtk_label_get (label, &amp;name);
9792     g_print ("\t%s on level %d\n", name, GTK_TREE
9793              (item->parent)->level);
9794     i = i->next;
9795   }
9796 }
9797
9798 int main( int   argc,
9799           char *argv[] )
9800 {
9801   GtkWidget *window, *scrolled_win, *tree;
9802   static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux",
9803                                "Maurice"};
9804   gint i;
9805
9806   gtk_init (&amp;argc, &amp;argv);
9807
9808   /* a generic toplevel window */
9809   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9810   gtk_signal_connect (GTK_OBJECT(window), "delete_event",
9811                       GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
9812   gtk_container_set_border_width (GTK_CONTAINER(window), 5);
9813
9814   /* A generic scrolled window */
9815   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
9816   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
9817                                   GTK_POLICY_AUTOMATIC,
9818                                   GTK_POLICY_AUTOMATIC);
9819   gtk_widget_set_usize (scrolled_win, 150, 200);
9820   gtk_container_add (GTK_CONTAINER(window), scrolled_win);
9821   gtk_widget_show (scrolled_win);
9822   
9823   /* Create the root tree */
9824   tree = gtk_tree_new();
9825   g_print ("root tree is %p\n", tree);
9826   /* connect all GtkTree:: signals */
9827   gtk_signal_connect (GTK_OBJECT(tree), "select_child",
9828                       GTK_SIGNAL_FUNC(cb_select_child), tree);
9829   gtk_signal_connect (GTK_OBJECT(tree), "unselect_child",
9830                       GTK_SIGNAL_FUNC(cb_unselect_child), tree);
9831   gtk_signal_connect (GTK_OBJECT(tree), "selection_changed",
9832                       GTK_SIGNAL_FUNC(cb_selection_changed), tree);
9833   /* Add it to the scrolled window */
9834   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win),
9835                                          tree);
9836   /* Set the selection mode */
9837   gtk_tree_set_selection_mode (GTK_TREE(tree),
9838                                GTK_SELECTION_MULTIPLE);
9839   /* Show it */
9840   gtk_widget_show (tree);
9841
9842   for (i = 0; i < 5; i++){
9843     GtkWidget *subtree, *item;
9844     gint j;
9845
9846     /* Create a tree item */
9847     item = gtk_tree_item_new_with_label (itemnames[i]);
9848     /* Connect all GtkItem:: and GtkTreeItem:: signals */
9849     gtk_signal_connect (GTK_OBJECT(item), "select",
9850                         GTK_SIGNAL_FUNC(cb_itemsignal), "select");
9851     gtk_signal_connect (GTK_OBJECT(item), "deselect",
9852                         GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
9853     gtk_signal_connect (GTK_OBJECT(item), "toggle",
9854                         GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
9855     gtk_signal_connect (GTK_OBJECT(item), "expand",
9856                         GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
9857     gtk_signal_connect (GTK_OBJECT(item), "collapse",
9858                         GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
9859     /* Add it to the parent tree */
9860     gtk_tree_append (GTK_TREE(tree), item);
9861     /* Show it - this can be done at any time */
9862     gtk_widget_show (item);
9863     /* Create this item's subtree */
9864     subtree = gtk_tree_new();
9865     g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item,
9866              subtree);
9867
9868     /* This is still necessary if you want these signals to be called
9869        for the subtree's children.  Note that selection_change will be 
9870        signalled for the root tree regardless. */
9871     gtk_signal_connect (GTK_OBJECT(subtree), "select_child",
9872                         GTK_SIGNAL_FUNC(cb_select_child), subtree);
9873     gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child",
9874                         GTK_SIGNAL_FUNC(cb_unselect_child), subtree);
9875     /* This has absolutely no effect, because it is completely ignored 
9876        in subtrees */
9877     gtk_tree_set_selection_mode (GTK_TREE(subtree),
9878                                  GTK_SELECTION_SINGLE);
9879     /* Neither does this, but for a rather different reason - the
9880        view_mode and view_line values of a tree are propagated to
9881        subtrees when they are mapped.  So, setting it later on would
9882        actually have a (somewhat unpredictable) effect */
9883     gtk_tree_set_view_mode (GTK_TREE(subtree), GTK_TREE_VIEW_ITEM);
9884     /* Set this item's subtree - note that you cannot do this until
9885        AFTER the item has been added to its parent tree! */
9886     gtk_tree_item_set_subtree (GTK_TREE_ITEM(item), subtree);
9887
9888     for (j = 0; j < 5; j++){
9889       GtkWidget *subitem;
9890
9891       /* Create a subtree item, in much the same way */
9892       subitem = gtk_tree_item_new_with_label (itemnames[j]);
9893       /* Connect all GtkItem:: and GtkTreeItem:: signals */
9894       gtk_signal_connect (GTK_OBJECT(subitem), "select",
9895                           GTK_SIGNAL_FUNC(cb_itemsignal), "select");
9896       gtk_signal_connect (GTK_OBJECT(subitem), "deselect",
9897                           GTK_SIGNAL_FUNC(cb_itemsignal), "deselect");
9898       gtk_signal_connect (GTK_OBJECT(subitem), "toggle",
9899                           GTK_SIGNAL_FUNC(cb_itemsignal), "toggle");
9900       gtk_signal_connect (GTK_OBJECT(subitem), "expand",
9901                           GTK_SIGNAL_FUNC(cb_itemsignal), "expand");
9902       gtk_signal_connect (GTK_OBJECT(subitem), "collapse",
9903                           GTK_SIGNAL_FUNC(cb_itemsignal), "collapse");
9904       g_print ("-> -> item %s->%p\n", itemnames[j], subitem);
9905       /* Add it to its parent tree */
9906       gtk_tree_append (GTK_TREE(subtree), subitem);
9907       /* Show it */
9908       gtk_widget_show (subitem);
9909     }
9910   }
9911
9912   /* Show the window and loop endlessly */
9913   gtk_widget_show (window);
9914   gtk_main();
9915   return 0;
9916 }
9917 /* example-end */
9918 </verb></tscreen>
9919
9920 <!-- ***************************************************************** -->
9921 <sect>Menu Widget
9922 <!-- ***************************************************************** -->
9923 <p>
9924 There are two ways to create menus: there's the easy way, and there's
9925 the hard way. Both have their uses, but you can usually use the
9926 Itemfactory (the easy way). The "hard" way is to create all the menus
9927 using the calls directly. The easy way is to use the gtk_item_factory
9928 calls. This is much simpler, but there are advantages and
9929 disadvantages to each approach.
9930
9931 The Itemfactory is much easier to use, and to add new menus to,
9932 although writing a few wrapper functions to create menus using the
9933 manual method could go a long way towards usability. With the
9934 Itemfactory, it is not possible to add images or the character '/' to
9935 the menus.
9936
9937 <!-- ----------------------------------------------------------------- -->
9938 <sect1>Manual Menu Creation
9939 <p>
9940 In the true tradition of teaching, we'll show you the hard way
9941 first. <tt>:)</>
9942
9943 There are three widgets that go into making a menubar and submenus:
9944 <itemize>
9945 <item>a menu item, which is what the user wants to select, e.g.,
9946 "Save"
9947 <item>a menu, which acts as a container for the menu items, and
9948 <item>a menubar, which is a container for each of the individual
9949 menus.
9950 </itemize>
9951
9952 This is slightly complicated by the fact that menu item widgets are
9953 used for two different things. They are both the widgets that are
9954 packed into the menu, and the widget that is packed into the menubar,
9955 which, when selected, activates the menu.
9956
9957 Let's look at the functions that are used to create menus and
9958 menubars.  This first function is used to create a new menubar.
9959
9960 <tscreen>
9961 <verb>
9962 GtkWidget *gtk_menu_bar_new( void );
9963 </verb>
9964 </tscreen>
9965
9966 This rather self explanatory function creates a new menubar. You use
9967 gtk_container_add to pack this into a window, or the box_pack
9968 functions to pack it into a box - the same as buttons.
9969
9970 <tscreen><verb>
9971 GtkWidget *gtk_menu_new( void );
9972 </verb></tscreen>
9973
9974 This function returns a pointer to a new menu; it is never actually
9975 shown (with gtk_widget_show), it is just a container for the menu
9976 items. I hope this will become more clear when you look at the
9977 example below.
9978
9979 The next two calls are used to create menu items that are packed into
9980 the menu (and menubar).
9981
9982 <tscreen><verb>
9983 GtkWidget *gtk_menu_item_new( void );
9984 </verb></tscreen>
9985
9986 and
9987
9988 <tscreen><verb>
9989 GtkWidget *gtk_menu_item_new_with_label( const char *label );
9990 </verb></tscreen>
9991
9992 These calls are used to create the menu items that are to be
9993 displayed.  Remember to differentiate between a "menu" as created with
9994 gtk_menu_new and a "menu item" as created by the gtk_menu_item_new
9995 functions. The menu item will be an actual button with an associated
9996 action, whereas a menu will be a container holding menu items.
9997
9998 The gtk_menu_new_with_label and gtk_menu_new functions are just as
9999 you'd expect after reading about the buttons. One creates a new menu
10000 item with a label already packed into it, and the other just creates a
10001 blank menu item.
10002
10003 Once you've created a menu item you have to put it into a menu. This
10004 is done using the function gtk_menu_append. In order to capture when
10005 the item is selected by the user, we need to connect to the
10006 <tt/activate/ signal in the usual way. So, if we wanted to create a
10007 standard <tt/File/ menu, with the options <tt/Open/, <tt/Save/, and
10008 <tt/Quit/, the code would look something like:
10009
10010 <tscreen><verb>
10011     file_menu = gtk_menu_new ();    /* Don't need to show menus */
10012
10013     /* Create the menu items */
10014     open_item = gtk_menu_item_new_with_label ("Open");
10015     save_item = gtk_menu_item_new_with_label ("Save");
10016     quit_item = gtk_menu_item_new_with_label ("Quit");
10017
10018     /* Add them to the menu */
10019     gtk_menu_append (GTK_MENU (file_menu), open_item);
10020     gtk_menu_append (GTK_MENU (file_menu), save_item);
10021     gtk_menu_append (GTK_MENU (file_menu), quit_item);
10022
10023     /* Attach the callback functions to the activate signal */
10024     gtk_signal_connect_object (GTK_OBJECT (open_items), "activate",
10025                                GTK_SIGNAL_FUNC (menuitem_response),
10026                                (gpointer) "file.open");
10027     gtk_signal_connect_object (GTK_OBJECT (save_items), "activate",
10028                                GTK_SIGNAL_FUNC (menuitem_response),
10029                                (gpointer) "file.save");
10030
10031     /* We can attach the Quit menu item to our exit function */
10032     gtk_signal_connect_object (GTK_OBJECT (quit_items), "activate",
10033                                GTK_SIGNAL_FUNC (destroy),
10034                                (gpointer) "file.quit");
10035
10036     /* We do need to show menu items */
10037     gtk_widget_show (open_item);
10038     gtk_widget_show (save_item);
10039     gtk_widget_show (quit_item);
10040 </verb></tscreen>
10041
10042 At this point we have our menu. Now we need to create a menubar and a
10043 menu item for the <tt/File/ entry, to which we add our menu. The code
10044 looks like this:
10045
10046 <tscreen><verb>
10047     menu_bar = gtk_menu_bar_new ();
10048     gtk_container_add (GTK_CONTAINER (window), menu_bar);
10049     gtk_widget_show (menu_bar);
10050
10051     file_item = gtk_menu_item_new_with_label ("File");
10052     gtk_widget_show (file_item);
10053 </verb></tscreen>
10054
10055 Now we need to associate the menu with <tt/file_item/. This is done
10056 with the function
10057
10058 <tscreen>
10059 void gtk_menu_item_set_submenu( GtkMenuItem *menu_item,
10060                                 GtkWidget   *submenu );
10061 </tscreen>
10062
10063 So, our example would continue with
10064
10065 <tscreen><verb>
10066     gtk_menu_item_set_submenu (GTK_MENU_ITEM (file_item), file_menu);
10067 </verb></tscreen>
10068
10069 All that is left to do is to add the menu to the menubar, which is
10070 accomplished using the function
10071
10072 <tscreen>
10073 void gtk_menu_bar_append( GtkMenuBar *menu_bar,
10074                           GtkWidget  *menu_item );
10075 </tscreen>
10076
10077 which in our case looks like this:
10078
10079 <tscreen><verb>
10080     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), file_item);
10081 </verb></tscreen>
10082
10083 If we wanted the menu right justified on the menubar, such as help
10084 menus often are, we can use the following function (again on
10085 <tt/file_item/ in the current example) before attaching it to the
10086 menubar.
10087
10088 <tscreen><verb>
10089 void gtk_menu_item_right_justify( GtkMenuItem *menu_item );
10090 </verb></tscreen>
10091
10092 Here is a summary of the steps needed to create a menu bar with menus
10093 attached:
10094
10095 <itemize>
10096 <item> Create a new menu using gtk_menu_new()
10097 <item> Use multiple calls to gtk_menu_item_new() for each item you
10098 wish to have on your menu. And use gtk_menu_append() to put each of
10099 these new items on to the menu.
10100 <item> Create a menu item using gtk_menu_item_new(). This will be the
10101 root of the menu, the text appearing here will be on the menubar
10102 itself.
10103 <item>Use gtk_menu_item_set_submenu() to attach the menu to the root
10104 menu item (the one created in the above step).
10105 <item> Create a new menubar using gtk_menu_bar_new. This step only
10106 needs to be done once when creating a series of menus on one menu bar.
10107 <item> Use gtk_menu_bar_append() to put the root menu onto the menubar.
10108 </itemize>
10109
10110 Creating a popup menu is nearly the same. The difference is that the
10111 menu is not posted "automatically" by a menubar, but explicitly by
10112 calling the function gtk_menu_popup() from a button-press event, for
10113 example.  Take these steps:
10114
10115 <itemize>
10116 <item>Create an event handling function. It needs to have the
10117 prototype
10118 <tscreen>
10119 static gint handler (GtkWidget *widget,
10120                      GdkEvent  *event);
10121 </tscreen>
10122 and it will use the event to find out where to pop up the menu.
10123 <item>In the event handler, if the event is a mouse button press,
10124 treat <tt>event</tt> as a button event (which it is) and use it as
10125 shown in the sample code to pass information to gtk_menu_popup().
10126 <item>Bind that event handler to a widget with
10127 <tscreen>
10128     gtk_signal_connect_object (GTK_OBJECT (widget), "event",
10129                                GTK_SIGNAL_FUNC (handler),
10130                                GTK_OBJECT (menu));
10131 </tscreen>
10132 where <tt>widget</tt> is the widget you are binding to,
10133 <tt>handler</tt> is the handling function, and <tt>menu</tt> is a menu
10134 created with gtk_menu_new(). This can be a menu which is also posted
10135 by a menu bar, as shown in the sample code.
10136 </itemize>
10137
10138 <!-- ----------------------------------------------------------------- -->
10139 <sect1>Manual Menu Example
10140 <p>
10141 That should about do it. Let's take a look at an example to help clarify.
10142
10143 <tscreen><verb>
10144 /* example-start menu menu.c */
10145
10146 #include <stdio.h>
10147 #include <gtk/gtk.h>
10148
10149 static gint button_press (GtkWidget *, GdkEvent *);
10150 static void menuitem_response (gchar *);
10151
10152 int main( int   argc,
10153           char *argv[] )
10154 {
10155
10156     GtkWidget *window;
10157     GtkWidget *menu;
10158     GtkWidget *menu_bar;
10159     GtkWidget *root_menu;
10160     GtkWidget *menu_items;
10161     GtkWidget *vbox;
10162     GtkWidget *button;
10163     char buf[128];
10164     int i;
10165
10166     gtk_init (&amp;argc, &amp;argv);
10167
10168     /* create a new window */
10169     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10170     gtk_widget_set_usize (GTK_WIDGET (window), 200, 100);
10171     gtk_window_set_title (GTK_WINDOW (window), "GTK Menu Test");
10172     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
10173                         (GtkSignalFunc) gtk_main_quit, NULL);
10174
10175     /* Init the menu-widget, and remember -- never
10176      * gtk_show_widget() the menu widget!! 
10177      * This is the menu that holds the menu items, the one that
10178      * will pop up when you click on the "Root Menu" in the app */
10179     menu = gtk_menu_new ();
10180
10181     /* Next we make a little loop that makes three menu-entries for "test-menu".
10182      * Notice the call to gtk_menu_append.  Here we are adding a list of
10183      * menu items to our menu.  Normally, we'd also catch the "clicked"
10184      * signal on each of the menu items and setup a callback for it,
10185      * but it's omitted here to save space. */
10186
10187     for (i = 0; i < 3; i++)
10188         {
10189             /* Copy the names to the buf. */
10190             sprintf (buf, "Test-undermenu - %d", i);
10191
10192             /* Create a new menu-item with a name... */
10193             menu_items = gtk_menu_item_new_with_label (buf);
10194
10195             /* ...and add it to the menu. */
10196             gtk_menu_append (GTK_MENU (menu), menu_items);
10197
10198             /* Do something interesting when the menuitem is selected */
10199             gtk_signal_connect_object (GTK_OBJECT (menu_items), "activate",
10200                 GTK_SIGNAL_FUNC (menuitem_response), (gpointer) g_strdup (buf));
10201
10202             /* Show the widget */
10203             gtk_widget_show (menu_items);
10204         }
10205
10206     /* This is the root menu, and will be the label
10207      * displayed on the menu bar.  There won't be a signal handler attached,
10208      * as it only pops up the rest of the menu when pressed. */
10209     root_menu = gtk_menu_item_new_with_label ("Root Menu");
10210
10211     gtk_widget_show (root_menu);
10212
10213     /* Now we specify that we want our newly created "menu" to be the menu
10214      * for the "root menu" */
10215     gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu);
10216
10217     /* A vbox to put a menu and a button in: */
10218     vbox = gtk_vbox_new (FALSE, 0);
10219     gtk_container_add (GTK_CONTAINER (window), vbox);
10220     gtk_widget_show (vbox);
10221
10222     /* Create a menu-bar to hold the menus and add it to our main window */
10223     menu_bar = gtk_menu_bar_new ();
10224     gtk_box_pack_start (GTK_BOX (vbox), menu_bar, FALSE, FALSE, 2);
10225     gtk_widget_show (menu_bar);
10226
10227     /* Create a button to which to attach menu as a popup */
10228     button = gtk_button_new_with_label ("press me");
10229     gtk_signal_connect_object (GTK_OBJECT (button), "event",
10230         GTK_SIGNAL_FUNC (button_press), GTK_OBJECT (menu));
10231     gtk_box_pack_end (GTK_BOX (vbox), button, TRUE, TRUE, 2);
10232     gtk_widget_show (button);
10233
10234     /* And finally we append the menu-item to the menu-bar -- this is the
10235      * "root" menu-item I have been raving about =) */
10236     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), root_menu);
10237
10238     /* always display the window as the last step so it all splashes on
10239      * the screen at once. */
10240     gtk_widget_show (window);
10241
10242     gtk_main ();
10243
10244     return(0);
10245 }
10246
10247 /* Respond to a button-press by posting a menu passed in as widget.
10248  *
10249  * Note that the "widget" argument is the menu being posted, NOT
10250  * the button that was pressed.
10251  */
10252
10253 static gint button_press( GtkWidget *widget,
10254                           GdkEvent *event )
10255 {
10256
10257     if (event->type == GDK_BUTTON_PRESS) {
10258         GdkEventButton *bevent = (GdkEventButton *) event; 
10259         gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
10260                         bevent->button, bevent->time);
10261         /* Tell calling code that we have handled this event; the buck
10262          * stops here. */
10263         return TRUE;
10264     }
10265
10266     /* Tell calling code that we have not handled this event; pass it on. */
10267     return FALSE;
10268 }
10269
10270
10271 /* Print a string when a menu item is selected */
10272
10273 static void menuitem_response( gchar *string )
10274 {
10275     printf ("%s\n", string);
10276 }
10277 /* example-end */
10278 </verb></tscreen>
10279
10280 You may also set a menu item to be insensitive and, using an accelerator
10281 table, bind keys to menu functions.
10282
10283 <!-- ----------------------------------------------------------------- -->
10284 <sect1>Using ItemFactory
10285 <p>
10286 Now that we've shown you the hard way, here's how you do it using the
10287 gtk_item_factory calls.
10288
10289 <!-- ----------------------------------------------------------------- -->
10290 <sect1>Item Factory Example
10291 <p>
10292 Here is an example using the GTK item factory.
10293
10294 <tscreen><verb>
10295 /* example-start menu itemfactory.c */
10296
10297 #include <gtk/gtk.h>
10298 #include <strings.h>
10299
10300 /* Obligatory basic callback */
10301 static void print_hello( GtkWidget *w,
10302                          gpointer   data )
10303 {
10304   g_message ("Hello, World!\n");
10305 }
10306
10307 /* This is the GtkItemFactoryEntry structure used to generate new menus.
10308    Item 1: The menu path. The letter after the underscore indicates an
10309            accelerator key once the menu is open.
10310    Item 2: The accelerator key for the entry
10311    Item 3: The callback function.
10312    Item 4: The callback action.  This changes the parameters with
10313            which the function is called.  The default is 0.
10314    Item 5: The item type, used to define what kind of an item it is.
10315            Here are the possible values:
10316
10317            NULL               -> "<Item>"
10318            ""                 -> "<Item>"
10319            "<Title>"          -> create a title item
10320            "<Item>"           -> create a simple item
10321            "<CheckItem>"      -> create a check item
10322            "<ToggleItem>"     -> create a toggle item
10323            "<RadioItem>"      -> create a radio item
10324            <path>             -> path of a radio item to link against
10325            "<Separator>"      -> create a separator
10326            "<Branch>"         -> create an item to hold sub items (optional)
10327            "<LastBranch>"     -> create a right justified branch 
10328 */
10329
10330 static GtkItemFactoryEntry menu_items[] = {
10331   { "/_File",         NULL,         NULL, 0, "<Branch>" },
10332   { "/File/_New",     "<control>N", print_hello, 0, NULL },
10333   { "/File/_Open",    "<control>O", print_hello, 0, NULL },
10334   { "/File/_Save",    "<control>S", print_hello, 0, NULL },
10335   { "/File/Save _As", NULL,         NULL, 0, NULL },
10336   { "/File/sep1",     NULL,         NULL, 0, "<Separator>" },
10337   { "/File/Quit",     "<control>Q", gtk_main_quit, 0, NULL },
10338   { "/_Options",      NULL,         NULL, 0, "<Branch>" },
10339   { "/Options/Test",  NULL,         NULL, 0, NULL },
10340   { "/_Help",         NULL,         NULL, 0, "<LastBranch>" },
10341   { "/_Help/About",   NULL,         NULL, 0, NULL },
10342 };
10343
10344
10345 void get_main_menu( GtkWidget  *window,
10346                     GtkWidget **menubar )
10347 {
10348   GtkItemFactory *item_factory;
10349   GtkAccelGroup *accel_group;
10350   gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
10351
10352   accel_group = gtk_accel_group_new ();
10353
10354   /* This function initializes the item factory.
10355      Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU,
10356               or GTK_TYPE_OPTION_MENU.
10357      Param 2: The path of the menu.
10358      Param 3: A pointer to a gtk_accel_group.  The item factory sets up
10359               the accelerator table while generating menus.
10360   */
10361
10362   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", 
10363                                        accel_group);
10364
10365   /* This function generates the menu items. Pass the item factory,
10366      the number of items in the array, the array itself, and any
10367      callback data for the the menu items. */
10368   gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
10369
10370   /* Attach the new accelerator group to the window. */
10371   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
10372
10373   if (menubar)
10374     /* Finally, return the actual menu bar created by the item factory. */ 
10375     *menubar = gtk_item_factory_get_widget (item_factory, "<main>");
10376 }
10377
10378 int main( int argc,
10379           char *argv[] )
10380 {
10381   GtkWidget *window;
10382   GtkWidget *main_vbox;
10383   GtkWidget *menubar;
10384   
10385   gtk_init (&amp;argc, &amp;argv);
10386   
10387   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10388   gtk_signal_connect (GTK_OBJECT (window), "destroy", 
10389                       GTK_SIGNAL_FUNC (gtk_main_quit), 
10390                       "WM destroy");
10391   gtk_window_set_title (GTK_WINDOW(window), "Item Factory");
10392   gtk_widget_set_usize (GTK_WIDGET(window), 300, 200);
10393   
10394   main_vbox = gtk_vbox_new (FALSE, 1);
10395   gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
10396   gtk_container_add (GTK_CONTAINER (window), main_vbox);
10397   gtk_widget_show (main_vbox);
10398   
10399   get_main_menu (window, &amp;menubar);
10400   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, TRUE, 0);
10401   gtk_widget_show (menubar);
10402   
10403   gtk_widget_show (window);
10404   gtk_main ();
10405   
10406   return(0);
10407 }
10408 /* example-end */
10409 </verb></tscreen>
10410
10411
10412 For now, there's only this example. An explanation and lots 'o' comments
10413 will follow later.
10414
10415 <!-- ***************************************************************** -->
10416 <sect> Text Widget
10417 <!-- ***************************************************************** -->
10418 <p>
10419 The Text widget allows multiple lines of text to be displayed and
10420 edited. It supports both multi-colored and multi-font text, allowing
10421 them to be mixed in any way we wish. It also has a wide set of key
10422 based text editing commands, which are compatible with Emacs.
10423
10424 The text widget supports full cut-and-paste facilities, including the
10425 use of double- and triple-click to select a word and a whole line,
10426 respectively.
10427
10428 <!-- ----------------------------------------------------------------- -->
10429 <sect1>Creating and Configuring a Text box
10430 <p>
10431 There is only one function for creating a new Text widget.
10432
10433 <tscreen><verb>
10434 GtkWidget *gtk_text_new( GtkAdjustment *hadj,
10435                          GtkAdjustment *vadj );
10436 </verb></tscreen>
10437
10438 The arguments allow us to give the Text widget pointers to Adjustments
10439 that can be used to track the viewing position of the widget. Passing
10440 NULL values to either or both of these arguments will cause the
10441 gtk_text_new function to create its own.
10442
10443 <tscreen><verb>
10444 void gtk_text_set_adjustments( GtkText       *text,
10445                                GtkAdjustment *hadj,
10446                                GtkAdjustment *vadj );
10447 </verb></tscreen>
10448
10449 The above function allows the horizontal and vertical adjustments of a
10450 text widget to be changed at any time.
10451
10452 The text widget will not automatically create its own scrollbars when
10453 the amount of text to be displayed is too long for the display
10454 window. We therefore have to create and add them to the display layout
10455 ourselves.
10456
10457 <tscreen><verb>
10458   vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
10459   gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
10460   gtk_widget_show (vscrollbar);
10461 </verb></tscreen>
10462
10463 The above code snippet creates a new vertical scrollbar, and attaches
10464 it to the vertical adjustment of the text widget, <tt/text/. It then
10465 packs it into a box in the normal way.
10466
10467 Note, currently the Text widget does not support horizontal
10468 scrollbars.
10469
10470 There are two main ways in which a Text widget can be used: to allow
10471 the user to edit a body of text, or to allow us to display multiple
10472 lines of text to the user. In order for us to switch between these
10473 modes of operation, the text widget has the following function:
10474
10475 <tscreen><verb>
10476 void gtk_text_set_editable( GtkText *text,
10477                             gint     editable );
10478 </verb></tscreen>
10479
10480 The <tt/editable/ argument is a TRUE or FALSE value that specifies
10481 whether the user is permitted to edit the contents of the Text
10482 widget. When the text widget is editable, it will display a cursor at
10483 the current insertion point.
10484
10485 You are not, however, restricted to just using the text widget in
10486 these two modes. You can toggle the editable state of the text widget
10487 at any time, and can insert text at any time.
10488
10489 The text widget wraps lines of text that are too long to fit onto a
10490 single line of the display window. Its default behaviour is to break
10491 words across line breaks. This can be changed using the next function:
10492
10493 <tscreen><verb>
10494 void gtk_text_set_word_wrap( GtkText *text,
10495                              gint     word_wrap );
10496 </verb></tscreen>
10497
10498 Using this function allows us to specify that the text widget should
10499 wrap long lines on word boundaries. The <tt/word_wrap/ argument is a
10500 TRUE or FALSE value.
10501
10502 <!-- ----------------------------------------------------------------- -->
10503 <sect1>Text Manipulation
10504 <P>
10505 The current insertion point of a Text widget can be set using
10506 <tscreen><verb>
10507 void gtk_text_set_point( GtkText *text,
10508                          guint    index );
10509 </verb></tscreen>
10510
10511 where <tt/index/ is the position to set the insertion point.
10512
10513 Analogous to this is the function for getting the current insertion
10514 point:
10515
10516 <tscreen><verb>
10517 guint gtk_text_get_point( GtkText *text );
10518 </verb></tscreen>
10519
10520 A function that is useful in combination with the above two functions
10521 is
10522
10523 <tscreen><verb>
10524 guint gtk_text_get_length( GtkText *text );
10525 </verb></tscreen>
10526
10527 which returns the current length of the Text widget. The length is the
10528 number of characters that are within the text block of the widget,
10529 including characters such as newline, which marks the end of
10530 lines.
10531
10532 In order to insert text at the current insertion point of a Text
10533 widget, the function gtk_text_insert is used, which also allows us to
10534 specify background and foreground colors and a font for the text.
10535
10536 <tscreen><verb>
10537 void gtk_text_insert( GtkText    *text,
10538                       GdkFont    *font,
10539                       GdkColor   *fore,
10540                       GdkColor   *back,
10541                       const char *chars,
10542                       gint        length );
10543 </verb></tscreen>
10544
10545 Passing a value of <tt/NULL/ in as the value for the foreground color,
10546 background color or font will result in the values set within the
10547 widget style to be used. Using a value of <tt/-1/ for the length
10548 parameter will result in the whole of the text string given being
10549 inserted.
10550
10551 The text widget is one of the few within GTK that redraws itself
10552 dynamically, outside of the gtk_main function. This means that all
10553 changes to the contents of the text widget take effect
10554 immediately. This may be undesirable when performing multiple changes
10555 to the text widget. In order to allow us to perform multiple updates
10556 to the text widget without it continuously redrawing, we can freeze
10557 the widget, which temporarily stops it from automatically redrawing
10558 itself every time it is changed. We can then thaw the widget after our
10559 updates are complete.
10560
10561 The following two functions perform this freeze and thaw action:
10562
10563 <tscreen><verb>
10564 void gtk_text_freeze( GtkText *text );
10565
10566 void gtk_text_thaw( GtkText *text );         
10567 </verb></tscreen>
10568
10569 Text is deleted from the text widget relative to the current insertion
10570 point by the following two functions. The return value is a TRUE or
10571 FALSE indicator of whether the operation was successful.
10572
10573 <tscreen><verb>
10574 gint gtk_text_backward_delete( GtkText *text,
10575                                guint    nchars );
10576
10577 gint gtk_text_forward_delete ( GtkText *text,
10578                                guint    nchars );
10579 </verb></tscreen>
10580
10581 If you want to retrieve the contents of the text widget, then the
10582 macro <tt/GTK_TEXT_INDEX(t, index)/ allows you to retrieve the
10583 character at position <tt/index/ within the text widget <tt/t/.
10584
10585 To retrieve larger blocks of text, we can use the function
10586
10587 <tscreen><verb>
10588 gchar *gtk_editable_get_chars( GtkEditable *editable,
10589                                gint         start_pos,
10590                                gint         end_pos );   
10591 </verb></tscreen>
10592
10593 This is a function of the parent class of the text widget. A value of
10594 -1 as <tt/end_pos/ signifies the end of the text. The index of the
10595 text starts at 0.
10596
10597 The function allocates a new chunk of memory for the text block, so
10598 don't forget to free it with a call to g_free when you have finished
10599 with it.
10600  
10601 <!-- ----------------------------------------------------------------- -->
10602 <sect1>Keyboard Shortcuts
10603 <p>
10604 The text widget has a number of pre-installed keyboard shortcuts for
10605 common editing, motion and selection functions. These are accessed
10606 using Control and Alt key combinations.
10607
10608 In addition to these, holding down the Control key whilst using cursor
10609 key movement will move the cursor by words rather than
10610 characters. Holding down Shift whilst using cursor movement will
10611 extend the selection.
10612
10613 <sect2>Motion Shortcuts
10614 <p>
10615 <itemize>
10616 <item> Ctrl-A   Beginning of line
10617 <item> Ctrl-E   End of line
10618 <item> Ctrl-N   Next Line
10619 <item> Ctrl-P   Previous Line
10620 <item> Ctrl-B   Backward one character
10621 <item> Ctrl-F   Forward one character
10622 <item> Alt-B    Backward one word
10623 <item> Alt-F    Forward one word
10624 </itemize>
10625
10626 <sect2>Editing Shortcuts
10627 <p>
10628 <itemize>
10629 <item> Ctrl-H   Delete Backward Character (Backspace)
10630 <item> Ctrl-D   Delete Forward Character (Delete)
10631 <item> Ctrl-W   Delete Backward Word
10632 <item> Alt-D    Delete Forward Word
10633 <item> Ctrl-K   Delete to end of line
10634 <item> Ctrl-U   Delete line
10635 </itemize>
10636
10637 <sect2>Selection Shortcuts
10638 <p>
10639 <itemize>
10640 <item> Ctrl-X   Cut to clipboard
10641 <item> Ctrl-C   Copy to clipboard
10642 <item> Ctrl-V   Paste from clipboard
10643 </itemize>
10644
10645 <!-- ----------------------------------------------------------------- -->
10646 <sect1>A GtkText Example
10647 <p>
10648 <tscreen><verb>
10649 /* example-start text text.c */
10650
10651 /* text.c */
10652
10653 #include <stdio.h>
10654 #include <gtk/gtk.h>
10655
10656 void text_toggle_editable (GtkWidget *checkbutton,
10657                            GtkWidget *text)
10658 {
10659   gtk_text_set_editable(GTK_TEXT(text),
10660                         GTK_TOGGLE_BUTTON(checkbutton)->active);
10661 }
10662
10663 void text_toggle_word_wrap (GtkWidget *checkbutton,
10664                             GtkWidget *text)
10665 {
10666   gtk_text_set_word_wrap(GTK_TEXT(text),
10667                          GTK_TOGGLE_BUTTON(checkbutton)->active);
10668 }
10669
10670 void close_application( GtkWidget *widget,
10671                         gpointer   data )
10672 {
10673        gtk_main_quit();
10674 }
10675
10676 int main( int argc,
10677           char *argv[] )
10678 {
10679   GtkWidget *window;
10680   GtkWidget *box1;
10681   GtkWidget *box2;
10682   GtkWidget *hbox;
10683   GtkWidget *button;
10684   GtkWidget *check;
10685   GtkWidget *separator;
10686   GtkWidget *table;
10687   GtkWidget *vscrollbar;
10688   GtkWidget *text;
10689   GdkColormap *cmap;
10690   GdkColor color;
10691   GdkFont *fixed_font;
10692
10693   FILE *infile;
10694
10695   gtk_init (&amp;argc, &amp;argv);
10696  
10697   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10698   gtk_widget_set_usize (window, 600, 500);
10699   gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);  
10700   gtk_signal_connect (GTK_OBJECT (window), "destroy",
10701                       GTK_SIGNAL_FUNC(close_application),
10702                       NULL);
10703   gtk_window_set_title (GTK_WINDOW (window), "Text Widget Example");
10704   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10705   
10706   
10707   box1 = gtk_vbox_new (FALSE, 0);
10708   gtk_container_add (GTK_CONTAINER (window), box1);
10709   gtk_widget_show (box1);
10710   
10711   
10712   box2 = gtk_vbox_new (FALSE, 10);
10713   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10714   gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
10715   gtk_widget_show (box2);
10716   
10717   
10718   table = gtk_table_new (2, 2, FALSE);
10719   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
10720   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
10721   gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
10722   gtk_widget_show (table);
10723   
10724   /* Create the GtkText widget */
10725   text = gtk_text_new (NULL, NULL);
10726   gtk_text_set_editable (GTK_TEXT (text), TRUE);
10727   gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
10728                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
10729                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
10730   gtk_widget_show (text);
10731
10732   /* Add a vertical scrollbar to the GtkText widget */
10733   vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
10734   gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
10735                     GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
10736   gtk_widget_show (vscrollbar);
10737
10738   /* Get the system color map and allocate the color red */
10739   cmap = gdk_colormap_get_system();
10740   color.red = 0xffff;
10741   color.green = 0;
10742   color.blue = 0;
10743   if (!gdk_color_alloc(cmap, &amp;color)) {
10744     g_error("couldn't allocate color");
10745   }
10746
10747   /* Load a fixed font */
10748   fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");
10749
10750   /* Realizing a widget creates a window for it,
10751    * ready for us to insert some text */
10752   gtk_widget_realize (text);
10753
10754   /* Freeze the text widget, ready for multiple updates */
10755   gtk_text_freeze (GTK_TEXT (text));
10756   
10757   /* Insert some colored text */
10758   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
10759                    "Supports ", -1);
10760   gtk_text_insert (GTK_TEXT (text), NULL, &amp;color, NULL,
10761                    "colored ", -1);
10762   gtk_text_insert (GTK_TEXT (text), NULL, &amp;text->style->black, NULL,
10763                    "text and different ", -1);
10764   gtk_text_insert (GTK_TEXT (text), fixed_font, &amp;text->style->black, NULL,
10765                    "fonts\n\n", -1);
10766   
10767   /* Load the file text.c into the text window */
10768
10769   infile = fopen("text.c", "r");
10770   
10771   if (infile) {
10772     char buffer[1024];
10773     int nchars;
10774     
10775     while (1)
10776       {
10777         nchars = fread(buffer, 1, 1024, infile);
10778         gtk_text_insert (GTK_TEXT (text), fixed_font, NULL,
10779                          NULL, buffer, nchars);
10780         
10781         if (nchars < 1024)
10782           break;
10783       }
10784     
10785     fclose (infile);
10786   }
10787
10788   /* Thaw the text widget, allowing the updates to become visible */  
10789   gtk_text_thaw (GTK_TEXT (text));
10790   
10791   hbox = gtk_hbutton_box_new ();
10792   gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
10793   gtk_widget_show (hbox);
10794
10795   check = gtk_check_button_new_with_label("Editable");
10796   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
10797   gtk_signal_connect (GTK_OBJECT(check), "toggled",
10798                       GTK_SIGNAL_FUNC(text_toggle_editable), text);
10799   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
10800   gtk_widget_show (check);
10801   check = gtk_check_button_new_with_label("Wrap Words");
10802   gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
10803   gtk_signal_connect (GTK_OBJECT(check), "toggled",
10804                       GTK_SIGNAL_FUNC(text_toggle_word_wrap), text);
10805   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
10806   gtk_widget_show (check);
10807
10808   separator = gtk_hseparator_new ();
10809   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10810   gtk_widget_show (separator);
10811
10812   box2 = gtk_vbox_new (FALSE, 10);
10813   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10814   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10815   gtk_widget_show (box2);
10816   
10817   button = gtk_button_new_with_label ("close");
10818   gtk_signal_connect (GTK_OBJECT (button), "clicked",
10819                       GTK_SIGNAL_FUNC(close_application),
10820                       NULL);
10821   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10822   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
10823   gtk_widget_grab_default (button);
10824   gtk_widget_show (button);
10825
10826   gtk_widget_show (window);
10827
10828   gtk_main ();
10829   
10830   return(0);       
10831 }
10832 /* example-end */
10833 </verb></tscreen>
10834
10835
10836 <!-- ***************************************************************** -->
10837 <sect> Undocumented Widgets
10838 <!-- ***************************************************************** -->
10839 <p>
10840 These all require authors! :) Please consider contributing to our
10841 tutorial.
10842
10843 If you must use one of these widgets that are undocumented, I strongly
10844 suggest you take a look at their respective header files in the GTK
10845 distribution. GTK's function names are very descriptive. Once you
10846 have an understanding of how things work, it's not difficult to figure
10847 out how to use a widget simply by looking at its function
10848 declarations. This, along with a few examples from others' code, and
10849 it should be no problem.
10850
10851 When you do come to understand all the functions of a new undocumented
10852 widget, please consider writing a tutorial on it so others may benefit
10853 from your time.
10854
10855 <!-- ----------------------------------------------------------------- -->
10856 <sect1> CTree
10857 <p>
10858 <!-- ----------------------------------------------------------------- -->
10859 <sect1> Curves
10860 <p>
10861 <!-- ----------------------------------------------------------------- -->
10862 <sect1> Drawing Area
10863 <p>
10864 <!-- ----------------------------------------------------------------- -->
10865 <sect1> Font Selection Dialog
10866 <p>
10867 <!-- ----------------------------------------------------------------- -->
10868 <sect1> Gamma Curve
10869 <p>
10870 <!-- ----------------------------------------------------------------- -->
10871 <sect1> Image
10872 <p>
10873 <!-- ----------------------------------------------------------------- -->
10874 <sect1> Packer
10875 <p>
10876 <!-- ----------------------------------------------------------------- -->
10877 <sect1> Plugs and Sockets
10878 <p>
10879 <!-- ----------------------------------------------------------------- -->
10880 <sect1> Preview
10881 <p>
10882
10883 <!--
10884
10885 (This may need to be rewritten to follow the style of the rest of the tutorial)
10886
10887 <tscreen><verb>
10888
10889 Previews serve a number of purposes in GIMP/GTK. The most important one is
10890 this. High quality images may take up to tens of megabytes of memory - easily!
10891 Any operation on an image that big is bound to take a long time. If it takes
10892 you 5-10 trial-and-errors (i.e., 10-20 steps, since you have to revert after
10893 you make an error) to choose the desired modification, it make take you
10894 literally hours to make the right one - if you don't run out of memory
10895 first. People who have spent hours in color darkrooms know the feeling.
10896 Previews to the rescue!
10897
10898 But the annoyance of the delay is not the only issue. Oftentimes it is
10899 helpful to compare the Before and After versions side-by-side or at least
10900 back-to-back. If you're working with big images and 10 second delays,
10901 obtaining the Before and After impressions is, to say the least, difficult.
10902 For 30M images (4"x6", 600dpi, 24 bit) the side-by-side comparison is right
10903 out for most people, while back-to-back is more like back-to-1001, 1002,
10904 ..., 1010-back! Previews to the rescue!
10905
10906 But there's more. Previews allow for side-by-side pre-previews. In other
10907 words, you write a plug-in (e.g., the filterpack simulation) which would have
10908 a number of here's-what-it-would-look-like-if-you-were-to-do-this previews.
10909 An approach like this acts as a sort of a preview palette and is very
10910 effective for subtle changes. Let's go previews!
10911
10912 There's more. For certain plug-ins real-time image-specific human
10913 intervention maybe necessary. In the SuperNova plug-in, for example, the
10914 user is asked to enter the coordinates of the center of the future
10915 supernova. The easiest way to do this, really, is to present the user with a
10916 preview and ask him to interactively select the spot. Let's go previews!
10917
10918 Finally, a couple of misc uses. One can use previews even when not working
10919 with big images. For example, they are useful when rendering complicated
10920 patterns. (Just check out the venerable Diffraction plug-in + many other
10921 ones!) As another example, take a look at the colormap rotation plug-in
10922 (work in progress). You can also use previews for little logos inside you
10923 plug-ins and even for an image of yourself, The Author. Let's go previews!
10924
10925 When Not to Use Previews
10926
10927 Don't use previews for graphs, drawing, etc. GDK is much faster for that. Use
10928 previews only for rendered images!
10929
10930 Let's go previews!
10931
10932 You can stick a preview into just about anything. In a vbox, an hbox, a
10933 table, a button, etc. But they look their best in tight frames around them.
10934 Previews by themselves do not have borders and look flat without them. (Of
10935 course, if the flat look is what you want...) Tight frames provide the
10936 necessary borders.
10937
10938                                [Image][Image]
10939
10940 Previews in many ways are like any other widgets in GTK (whatever that
10941 means) except they possess an additional feature: they need to be filled with
10942 some sort of an image! First, we will deal exclusively with the GTK aspect
10943 of previews and then we'll discuss how to fill them.
10944
10945 GtkWidget *preview!
10946
10947 Without any ado:
10948
10949                               /* Create a preview widget,
10950                               set its size, an show it */
10951 GtkWidget *preview;
10952 preview=gtk_preview_new(GTK_PREVIEW_COLOR)
10953                               /*Other option:
10954                               GTK_PREVIEW_GRAYSCALE);*/
10955 gtk_preview_size (GTK_PREVIEW (preview), WIDTH, HEIGHT);
10956 gtk_widget_show(preview);
10957 my_preview_rendering_function(preview);
10958
10959 Oh yeah, like I said, previews look good inside frames, so how about:
10960
10961 GtkWidget *create_a_preview(int        Width,
10962                             int        Height,
10963                             int        Colorfulness)
10964 {
10965   GtkWidget *preview;
10966   GtkWidget *frame;
10967   
10968   frame = gtk_frame_new(NULL);
10969   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
10970   gtk_container_set_border_width (GTK_CONTAINER(frame),0);
10971   gtk_widget_show(frame);
10972
10973   preview=gtk_preview_new (Colorfulness?GTK_PREVIEW_COLOR
10974                                        :GTK_PREVIEW_GRAYSCALE);
10975   gtk_preview_size (GTK_PREVIEW (preview), Width, Height);
10976   gtk_container_add(GTK_CONTAINER(frame),preview);
10977   gtk_widget_show(preview);
10978
10979   my_preview_rendering_function(preview);
10980   return frame;
10981 }
10982
10983 That's my basic preview. This routine returns the "parent" frame so you can
10984 place it somewhere else in your interface. Of course, you can pass the
10985 parent frame to this routine as a parameter. In many situations, however,
10986 the contents of the preview are changed continually by your application. In
10987 this case you may want to pass a pointer to the preview to a
10988 "create_a_preview()" and thus have control of it later.
10989
10990 One more important note that may one day save you a lot of time. Sometimes
10991 it is desirable to label you preview. For example, you may label the preview
10992 containing the original image as "Original" and the one containing the
10993 modified image as "Less Original". It might occur to you to pack the
10994 preview along with the appropriate label into a vbox. The unexpected caveat
10995 is that if the label is wider than the preview (which may happen for a
10996 variety of reasons unforseeable to you, from the dynamic decision on the
10997 size of the preview to the size of the font) the frame expands and no longer
10998 fits tightly over the preview. The same problem can probably arise in other
10999 situations as well.
11000
11001                                    [Image]
11002
11003 The solution is to place the preview and the label into a 2x1 table and by
11004 attaching them with the following parameters (this is one possible variations
11005 of course. The key is no GTK_FILL in the second attachment):
11006
11007 gtk_table_attach(GTK_TABLE(table),label,0,1,0,1,
11008                  0,
11009                  GTK_EXPAND|GTK_FILL,
11010                  0,0);
11011 gtk_table_attach(GTK_TABLE(table),frame,0,1,1,2,
11012                  GTK_EXPAND,
11013                  GTK_EXPAND,
11014                  0,0);
11015
11016
11017 And here's the result:
11018
11019                                    [Image]
11020
11021 Misc
11022
11023 Making a preview clickable is achieved most easily by placing it in a
11024 button. It also adds a nice border around the preview and you may not even
11025 need to place it in a frame. See the Filter Pack Simulation plug-in for an
11026 example.
11027
11028 This is pretty much it as far as GTK is concerned.
11029
11030 Filling In a Preview
11031
11032 In order to familiarize ourselves with the basics of filling in previews,
11033 let's create the following pattern (contrived by trial and error):
11034
11035                                    [Image]
11036
11037 void
11038 my_preview_rendering_function(GtkWidget     *preview)
11039 {
11040 #define SIZE 100
11041 #define HALF (SIZE/2)
11042
11043   guchar *row=(guchar *) malloc(3*SIZE); /* 3 bits per dot */
11044   gint i, j;                             /* Coordinates    */
11045   double r, alpha, x, y;
11046
11047   if (preview==NULL) return; /* I usually add this when I want */
11048                              /* to avoid silly crashes. You    */
11049                              /* should probably make sure that */
11050                              /* everything has been nicely     */
11051                              /* initialized!                   */
11052   for (j=0; j < ABS(cos(2*alpha)) ) { /* Are we inside the shape?  */
11053                                          /* glib.h contains ABS(x).   */
11054         row[i*3+0] = sqrt(1-r)*255;      /* Define Red                */
11055         row[i*3+1] = 128;                /* Define Green              */
11056         row[i*3+2] = 224;                /* Define Blue               */
11057       }                                  /* "+0" is for alignment!    */
11058       else {
11059         row[i*3+0] = r*255;
11060         row[i*3+1] = ABS(sin((float)i/SIZE*2*PI))*255;
11061         row[i*3+2] = ABS(sin((float)j/SIZE*2*PI))*255;
11062       }
11063     }
11064     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,j,SIZE);
11065     /* Insert "row" into "preview" starting at the point with  */
11066     /* coordinates (0,j) first column, j_th row extending SIZE */
11067     /* pixels to the right */
11068   }
11069
11070   free(row); /* save some space */
11071   gtk_widget_draw(preview,NULL); /* what does this do? */
11072   gdk_flush(); /* or this? */
11073 }
11074
11075 Non-GIMP users can have probably seen enough to do a lot of things already.
11076 For the GIMP users I have a few pointers to add.
11077
11078 Image Preview
11079
11080 It is probably wise to keep a reduced version of the image around with just
11081 enough pixels to fill the preview. This is done by selecting every n'th
11082 pixel where n is the ratio of the size of the image to the size of the
11083 preview. All further operations (including filling in the previews) are then
11084 performed on the reduced number of pixels only. The following is my
11085 implementation of reducing the image. (Keep in mind that I've had only basic
11086 C!)
11087
11088 (UNTESTED CODE ALERT!!!)
11089
11090 typedef struct {
11091   gint      width;
11092   gint      height;
11093   gint      bbp;
11094   guchar    *rgb;
11095   guchar    *mask;
11096 } ReducedImage;
11097
11098 enum {
11099   SELECTION_ONLY,
11100   SELECTION_IN_CONTEXT,
11101   ENTIRE_IMAGE
11102 };
11103
11104 ReducedImage *Reduce_The_Image(GDrawable *drawable,
11105                                GDrawable *mask,
11106                                gint LongerSize,
11107                                gint Selection)
11108 {
11109   /* This function reduced the image down to the the selected preview size */
11110   /* The preview size is determine by LongerSize, i.e., the greater of the  */
11111   /* two dimensions. Works for RGB images only!                            */
11112   gint RH, RW;          /* Reduced height and reduced width                */
11113   gint width, height;   /* Width and Height of the area being reduced      */
11114   gint bytes=drawable->bpp;
11115   ReducedImage *temp=(ReducedImage *)malloc(sizeof(ReducedImage));
11116
11117   guchar *tempRGB, *src_row, *tempmask, *src_mask_row,R,G,B;
11118   gint i, j, whichcol, whichrow, x1, x2, y1, y2;
11119   GPixelRgn srcPR, srcMask;
11120   gint NoSelectionMade=TRUE; /* Assume that we're dealing with the entire  */
11121                              /* image.                                     */
11122
11123   gimp_drawable_mask_bounds (drawable->id, &amp;x1, &amp;y1, &amp;x2, &amp;y2);
11124   width  = x2-x1;
11125   height = y2-y1;
11126   /* If there's a SELECTION, we got its bounds!)
11127
11128   if (width != drawable->width &amp;&amp; height != drawable->height)
11129     NoSelectionMade=FALSE;
11130   /* Become aware of whether the user has made an active selection   */
11131   /* This will become important later, when creating a reduced mask. */
11132
11133   /* If we want to preview the entire image, overrule the above!  */
11134   /* Of course, if no selection has been made, this does nothing! */
11135   if (Selection==ENTIRE_IMAGE) {
11136     x1=0;
11137     x2=drawable->width;
11138     y1=0;
11139     y2=drawable->height;
11140   }
11141
11142   /* If we want to preview a selection with some surrounding area we */
11143   /* have to expand it a little bit. Consider it a bit of a riddle. */
11144   if (Selection==SELECTION_IN_CONTEXT) {
11145     x1=MAX(0,                x1-width/2.0);
11146     x2=MIN(drawable->width,  x2+width/2.0);
11147     y1=MAX(0,                y1-height/2.0);
11148     y2=MIN(drawable->height, y2+height/2.0);
11149   }
11150
11151   /* How we can determine the width and the height of the area being */
11152   /* reduced.                                                        */
11153   width  = x2-x1;
11154   height = y2-y1;
11155
11156   /* The lines below determine which dimension is to be the longer   */
11157   /* side. The idea borrowed from the supernova plug-in. I suspect I */
11158   /* could've thought of it myself, but the truth must be told.      */
11159   /* Plagiarism stinks!                                               */
11160   if (width>height) {
11161     RW=LongerSize;
11162     RH=(float) height * (float) LongerSize/ (float) width;
11163   }
11164   else {
11165     RH=LongerSize;
11166     RW=(float)width * (float) LongerSize/ (float) height;
11167   }
11168
11169   /* The entire image is stretched into a string! */
11170   tempRGB   = (guchar *) malloc(RW*RH*bytes);
11171   tempmask  = (guchar *) malloc(RW*RH);
11172
11173   gimp_pixel_rgn_init (&amp;srcPR, drawable, x1, y1, width, height,
11174                        FALSE, FALSE);
11175   gimp_pixel_rgn_init (&amp;srcMask, mask, x1, y1, width, height,
11176                        FALSE, FALSE);
11177
11178   /* Grab enough to save a row of image and a row of mask. */
11179   src_row       = (guchar *) malloc (width*bytes);
11180   src_mask_row  = (guchar *) malloc (width);
11181
11182   for (i=0; i < RH; i++) {
11183     whichrow=(float)i*(float)height/(float)RH;
11184     gimp_pixel_rgn_get_row (&amp;srcPR, src_row, x1, y1+whichrow, width);
11185     gimp_pixel_rgn_get_row (&amp;srcMask, src_mask_row, x1, y1+whichrow, width);
11186
11187     for (j=0; j < RW; j++) {
11188       whichcol=(float)j*(float)width/(float)RW;
11189
11190       /* No selection made = each point is completely selected! */
11191       if (NoSelectionMade)
11192         tempmask[i*RW+j]=255;
11193       else
11194         tempmask[i*RW+j]=src_mask_row[whichcol];
11195
11196       /* Add the row to the one long string which now contains the image! */
11197       tempRGB[i*RW*bytes+j*bytes+0]=src_row[whichcol*bytes+0];
11198       tempRGB[i*RW*bytes+j*bytes+1]=src_row[whichcol*bytes+1];
11199       tempRGB[i*RW*bytes+j*bytes+2]=src_row[whichcol*bytes+2];
11200
11201       /* Hold on to the alpha as well */
11202       if (bytes==4)
11203         tempRGB[i*RW*bytes+j*bytes+3]=src_row[whichcol*bytes+3];
11204     }
11205   }
11206   temp->bpp=bytes;
11207   temp->width=RW;
11208   temp->height=RH;
11209   temp->rgb=tempRGB;
11210   temp->mask=tempmask;
11211   return temp;
11212 }
11213
11214 The following is a preview function which used the same ReducedImage type!
11215 Note that it uses fakes transparency (if one is present by means of
11216 fake_transparency which is defined as follows:
11217
11218 gint fake_transparency(gint i, gint j)
11219 {
11220   if ( ((i%20)- 10) * ((j%20)- 10)>0   )
11221     return 64;
11222   else
11223     return 196;
11224 }
11225
11226 Now here's the preview function:
11227
11228 void
11229 my_preview_render_function(GtkWidget     *preview,
11230                            gint          changewhat,
11231                            gint          changewhich)
11232 {
11233   gint Inten, bytes=drawable->bpp;
11234   gint i, j, k;
11235   float partial;
11236   gint RW=reduced->width;
11237   gint RH=reduced->height;
11238   guchar *row=malloc(bytes*RW);;
11239
11240
11241   for (i=0; i < RH; i++) {
11242     for (j=0; j < RW; j++) {
11243
11244       row[j*3+0] = reduced->rgb[i*RW*bytes + j*bytes + 0];
11245       row[j*3+1] = reduced->rgb[i*RW*bytes + j*bytes + 1];
11246       row[j*3+2] = reduced->rgb[i*RW*bytes + j*bytes + 2];
11247
11248       if (bytes==4)
11249         for (k=0; k<3; k++) {
11250           float transp=reduced->rgb[i*RW*bytes+j*bytes+3]/255.0;
11251           row[3*j+k]=transp*a[3*j+k]+(1-transp)*fake_transparency(i,j);
11252         }
11253     }
11254     gtk_preview_draw_row( GTK_PREVIEW(preview),row,0,i,RW);
11255   }
11256
11257   free(a);
11258   gtk_widget_draw(preview,NULL);
11259   gdk_flush();
11260 }
11261
11262 Applicable Routines
11263
11264 guint           gtk_preview_get_type           (void);
11265 /* No idea */
11266 void            gtk_preview_uninit             (void);
11267 /* No idea */
11268 GtkWidget*      gtk_preview_new                (GtkPreviewType   type);
11269 /* Described above */
11270 void            gtk_preview_size               (GtkPreview      *preview,
11271                                                 gint             width,
11272                                                 gint             height);
11273 /* Allows you to resize an existing preview.    */
11274 /* Apparently there's a bug in GTK which makes  */
11275 /* this process messy. A way to clean up a mess */
11276 /* is to manually resize the window containing  */
11277 /* the preview after resizing the preview.      */
11278
11279 void            gtk_preview_put                (GtkPreview      *preview,
11280                                                 GdkWindow       *window,
11281                                                 GdkGC           *gc,
11282                                                 gint             srcx,
11283                                                 gint             srcy,
11284                                                 gint             destx,
11285                                                 gint             desty,
11286                                                 gint             width,
11287                                                 gint             height);
11288 /* No idea */
11289
11290 void            gtk_preview_put_row            (GtkPreview      *preview,
11291                                                 guchar          *src,
11292                                                 guchar          *dest,
11293                                                 gint             x,
11294                                                 gint             y,
11295                                                 gint             w);
11296 /* No idea */
11297
11298 void            gtk_preview_draw_row           (GtkPreview      *preview,
11299                                                 guchar          *data,
11300                                                 gint             x,
11301                                                 gint             y,
11302                                                 gint             w);
11303 /* Described in the text */
11304
11305 void            gtk_preview_set_expand         (GtkPreview      *preview,
11306                                                 gint             expand);
11307 /* No idea */
11308
11309 /* No clue for any of the below but    */
11310 /* should be standard for most widgets */
11311 void            gtk_preview_set_gamma          (double           gamma);
11312 void            gtk_preview_set_color_cube     (guint            nred_shades,
11313                                                 guint            ngreen_shades,
11314                                                 guint            nblue_shades,
11315                                                 guint            ngray_shades);
11316 void            gtk_preview_set_install_cmap   (gint             install_cmap);
11317 void            gtk_preview_set_reserved       (gint             nreserved);
11318 GdkVisual*      gtk_preview_get_visual         (void);
11319 GdkColormap*    gtk_preview_get_cmap           (void);
11320 GtkPreviewInfo* gtk_preview_get_info           (void);
11321
11322 That's all, folks!
11323
11324 </verb></tscreen>
11325
11326 -->
11327
11328 <!-- ***************************************************************** -->
11329 <sect>Setting Widget Attributes<label id="sec_setting_widget_attributes">
11330 <!-- ***************************************************************** -->
11331 <p>
11332 This describes the functions used to operate on widgets. These can be
11333 used to set style, padding, size, etc.
11334
11335 (Maybe I should make a whole section on accelerators.)
11336
11337 <tscreen><verb>
11338 void gtk_widget_install_accelerator( GtkWidget           *widget,
11339                                      GtkAcceleratorTable *table,
11340                                      gchar               *signal_name,
11341                                      gchar                key,
11342                                      guint8               modifiers );
11343
11344 void gtk_widget_remove_accelerator ( GtkWidget           *widget,
11345                                      GtkAcceleratorTable *table,
11346                                      gchar               *signal_name);
11347
11348 void gtk_widget_activate( GtkWidget *widget );
11349
11350 void gtk_widget_set_name( GtkWidget *widget,
11351                           gchar     *name );
11352
11353 gchar *gtk_widget_get_name( GtkWidget *widget );
11354
11355 void gtk_widget_set_sensitive( GtkWidget *widget,
11356                                gint       sensitive );
11357
11358 void gtk_widget_set_style( GtkWidget *widget,
11359                            GtkStyle  *style );
11360                                            
11361 GtkStyle *gtk_widget_get_style( GtkWidget *widget );
11362
11363 GtkStyle *gtk_widget_get_default_style( void );
11364
11365 void gtk_widget_set_uposition( GtkWidget *widget,
11366                                gint       x,
11367                                gint       y );
11368
11369 void gtk_widget_set_usize( GtkWidget *widget,
11370                            gint       width,
11371                            gint       height );
11372
11373 void gtk_widget_grab_focus( GtkWidget *widget );
11374
11375 void gtk_widget_show( GtkWidget *widget );
11376
11377 void gtk_widget_hide( GtkWidget *widget );
11378 </verb></tscreen>
11379
11380 <!-- ***************************************************************** -->
11381 <sect>Timeouts, IO and Idle Functions<label id="sec_timeouts">
11382 <!-- ***************************************************************** -->
11383
11384 <!-- ----------------------------------------------------------------- -->
11385 <sect1>Timeouts
11386 <p>
11387 You may be wondering how you make GTK do useful work when in gtk_main.
11388 Well, you have several options. Using the following function you can
11389 create a timeout function that will be called every "interval"
11390 milliseconds.
11391
11392 <tscreen><verb>
11393 gint gtk_timeout_add( guint32     interval,
11394                       GtkFunction function,
11395                       gpointer    data );
11396 </verb></tscreen>
11397
11398 The first argument is the number of milliseconds between calls to your
11399 function. The second argument is the function you wish to have called,
11400 and the third, the data passed to this callback function. The return
11401 value is an integer "tag" which may be used to stop the timeout by
11402 calling:
11403
11404 <tscreen><verb>
11405 void gtk_timeout_remove( gint tag );
11406 </verb></tscreen>
11407
11408 You may also stop the timeout function by returning zero or FALSE from
11409 your callback function. Obviously this means if you want your function
11410 to continue to be called, it should return a non-zero value,
11411 i.e., TRUE.
11412
11413 The declaration of your callback should look something like this:
11414
11415 <tscreen><verb>
11416 gint timeout_callback( gpointer data );
11417 </verb></tscreen>
11418
11419 <!-- ----------------------------------------------------------------- -->
11420 <sect1>Monitoring IO
11421 <p>
11422 A nifty feature of GDK (the library that underlies GTK), is the
11423 ability to have it check for data on a file descriptor for you (as
11424 returned by open(2) or socket(2)). This is especially useful for
11425 networking applications. The function:
11426
11427 <tscreen><verb>
11428 gint gdk_input_add( gint              source,
11429                     GdkInputCondition condition,
11430                     GdkInputFunction  function,
11431                     gpointer          data );
11432 </verb></tscreen>
11433
11434 Where the first argument is the file descriptor you wish to have
11435 watched, and the second specifies what you want GDK to look for. This
11436 may be one of:
11437
11438 <itemize>
11439 <item><tt/GDK_INPUT_READ/ - Call your function when there is data
11440 ready for reading on your file descriptor.
11441
11442 <item>><tt/GDK_INPUT_WRITE/ - Call your function when the file
11443 descriptor is ready for writing.
11444 </itemize>
11445
11446 As I'm sure you've figured out already, the third argument is the
11447 function you wish to have called when the above conditions are
11448 satisfied, and the fourth is the data to pass to this function.
11449
11450 The return value is a tag that may be used to stop GDK from monitoring
11451 this file descriptor using the following function.
11452
11453 <tscreen><verb>
11454 void gdk_input_remove( gint tag );
11455 </verb></tscreen>
11456
11457 The callback function should be declared as:
11458
11459 <tscreen><verb>
11460 void input_callback( gpointer          data,
11461                      gint              source, 
11462                      GdkInputCondition condition );
11463 </verb></tscreen>
11464
11465 Where <tt/source/ and <tt/condition/ are as specified above.
11466
11467 <!-- ----------------------------------------------------------------- -->
11468 <sect1>Idle Functions
11469 <p>
11470 <!-- TODO: Need to check on idle priorities - TRG -->
11471 What if you have a function which you want to be called when nothing
11472 else is happening ?
11473
11474 <tscreen><verb>
11475 gint gtk_idle_add( GtkFunction function,
11476                    gpointer    data );
11477 </verb></tscreen>
11478
11479 This causes GTK to call the specified function whenever nothing else
11480 is happening.
11481
11482 <tscreen><verb>
11483 void gtk_idle_remove( gint tag );
11484 </verb></tscreen>
11485
11486 I won't explain the meaning of the arguments as they follow very much
11487 like the ones above. The function pointed to by the first argument to
11488 gtk_idle_add will be called whenever the opportunity arises. As with
11489 the others, returning FALSE will stop the idle function from being
11490 called.
11491
11492 <!-- ***************************************************************** -->
11493 <sect>Advanced Event and Signal Handling<label id="sec_Adv_Events_and_Signals">
11494 <!-- ***************************************************************** -->
11495
11496 <!-- ----------------------------------------------------------------- -->
11497 <sect1>Signal Functions
11498
11499 <!-- ----------------------------------------------------------------- -->
11500 <sect2>Connecting and Disconnecting Signal Handlers
11501 <p>
11502
11503 <tscreen><verb>
11504 guint gtk_signal_connect( GtkObject     *object,
11505                           const gchar   *name,
11506                           GtkSignalFunc  func,
11507                           gpointer       func_data );
11508
11509 guint gtk_signal_connect_after( GtkObject     *object,
11510                                 const gchar   *name,
11511                                 GtkSignalFunc  func,
11512                                 gpointer       func_data );
11513
11514 guint gtk_signal_connect_object( GtkObject     *object,
11515                                  const gchar   *name,
11516                                  GtkSignalFunc  func,
11517                                  GtkObject     *slot_object );
11518
11519 guint gtk_signal_connect_object_after( GtkObject     *object,
11520                                        const gchar   *name,
11521                                        GtkSignalFunc  func,
11522                                        GtkObject     *slot_object );
11523
11524 guint gtk_signal_connect_full( GtkObject          *object,
11525                                const gchar        *name,
11526                                GtkSignalFunc       func,
11527                                GtkCallbackMarshal  marshal,
11528                                gpointer            data,
11529                                GtkDestroyNotify    destroy_func,
11530                                gint                object_signal,
11531                                gint                after );
11532
11533 guint gtk_signal_connect_interp( GtkObject          *object,
11534                                  const gchar        *name,
11535                                  GtkCallbackMarshal  func,
11536                                  gpointer            data,
11537                                  GtkDestroyNotify    destroy_func,
11538                                  gint                after );
11539
11540 void gtk_signal_connect_object_while_alive( GtkObject     *object,
11541                                             const gchar   *signal,
11542                                             GtkSignalFunc  func,
11543                                             GtkObject     *alive_object );
11544
11545 void gtk_signal_connect_while_alive( GtkObject     *object,
11546                                      const gchar   *signal,
11547                                      GtkSignalFunc  func,
11548                                      gpointer       func_data,
11549                                      GtkObject     *alive_object );
11550
11551 void gtk_signal_disconnect( GtkObject *object,
11552                             guint      handler_id );
11553
11554 void gtk_signal_disconnect_by_func( GtkObject     *object,
11555                                     GtkSignalFunc  func,
11556                                     gpointer       data );
11557 </verb></tscreen>
11558
11559 <!-- ----------------------------------------------------------------- -->
11560 <sect2>Blocking and Unblocking Signal Handlers
11561 <p>
11562 <tscreen><verb>
11563 void gtk_signal_handler_block( GtkObject *object,
11564                                guint      handler_id);
11565
11566 void gtk_signal_handler_block_by_func( GtkObject     *object,
11567                                        GtkSignalFunc  func,
11568                                        gpointer       data );
11569
11570 void gtk_signal_handler_block_by_data( GtkObject *object,
11571                                        gpointer   data );
11572
11573 void gtk_signal_handler_unblock( GtkObject *object,
11574                                  guint      handler_id );
11575
11576 void gtk_signal_handler_unblock_by_func( GtkObject     *object,
11577                                          GtkSignalFunc  func,
11578                                          gpointer       data );
11579
11580 void gtk_signal_handler_unblock_by_data( GtkObject *object,
11581                                          gpointer   data );
11582 </verb></tscreen>
11583
11584 <!-- ----------------------------------------------------------------- -->
11585 <sect2>Emitting and Stopping Signals
11586 <p>
11587 <tscreen><verb>
11588 void gtk_signal_emit( GtkObject *object,
11589                       guint      signal_id,
11590                       ... );
11591
11592 void gtk_signal_emit_by_name( GtkObject   *object,
11593                               const gchar *name,
11594                               ... );
11595
11596 void gtk_signal_emitv( GtkObject *object,
11597                        guint      signal_id,
11598                        GtkArg    *params );
11599
11600 void gtk_signal_emitv_by_name( GtkObject   *object,
11601                                const gchar *name,
11602                                GtkArg      *params );
11603
11604 guint gtk_signal_n_emissions( GtkObject *object,
11605                               guint      signal_id );
11606
11607 guint gtk_signal_n_emissions_by_name( GtkObject   *object,
11608                                       const gchar *name );
11609
11610 void gtk_signal_emit_stop( GtkObject *object,
11611                            guint      signal_id );
11612
11613 void gtk_signal_emit_stop_by_name( GtkObject   *object,
11614                                    const gchar *name );
11615 </verb></tscreen>
11616
11617 <!-- ----------------------------------------------------------------- -->
11618 <sect1>Signal Emission and Propagation
11619 <p>
11620 Signal emission is the process whereby GTK runs all handlers for a
11621 specific object and signal.
11622
11623 First, note that the return value from a signal emission is the return
11624 value of the <em>last</em> handler executed. Since event signals are
11625 all of type <tt/GTK_RUN_LAST/, this will be the default (GTK supplied)
11626 handler, unless you connect with gtk_signal_connect_after().
11627
11628 The way an event (say "button_press_event") is handled, is:
11629 <itemize>
11630 <item>Start with the widget where the event occured.
11631
11632 <item>Emit the generic "event" signal. If that signal handler returns
11633 a value of TRUE, stop all processing.
11634
11635 <item>Otherwise, emit a specific, "button_press_event" signal. If that
11636 returns TRUE, stop all processing.
11637
11638 <item>Otherwise, go to the widget's parent, and repeat the above two
11639 steps.
11640
11641 <item>Continue until some signal handler returns TRUE, or until the
11642 top-level widget is reached.
11643 </itemize>
11644
11645 Some consequences of the above are:
11646 <itemize>
11647 <item>Your handler's return value will have no effect if there is a
11648 default handler, unless you connect with gtk_signal_connect_after().
11649
11650 <item>To prevent the default handler from being run, you need to
11651 connect with gtk_signal_connect() and use
11652 gtk_signal_emit_stop_by_name() - the return value only affects whether
11653 the signal is propagated, not the current emission.
11654 </itemize>
11655
11656 <!-- ***************************************************************** -->
11657 <sect>Managing Selections
11658 <!-- ***************************************************************** -->
11659
11660 <!-- ----------------------------------------------------------------- -->
11661 <sect1> Overview
11662 <p>
11663 One type of interprocess communication supported by X and GTK is
11664 <em>selections</em>. A selection identifies a chunk of data, for
11665 instance, a portion of text, selected by the user in some fashion, for
11666 instance, by dragging with the mouse. Only one application on a
11667 display (the <em>owner</em>) can own a particular selection at one
11668 time, so when a selection is claimed by one application, the previous
11669 owner must indicate to the user that selection has been
11670 relinquished. Other applications can request the contents of a
11671 selection in different forms, called <em>targets</em>. There can be
11672 any number of selections, but most X applications only handle one, the
11673 <em>primary selection</em>.
11674
11675 In most cases, it isn't necessary for a GTK application to deal with
11676 selections itself. The standard widgets, such as the Entry widget,
11677 already have the capability to claim the selection when appropriate
11678 (e.g., when the user drags over text), and to retrieve the contents of
11679 the selection owned by another widget or another application (e.g.,
11680 when the user clicks the second mouse button). However, there may be
11681 cases in which you want to give other widgets the ability to supply
11682 the selection, or you wish to retrieve targets not supported by
11683 default.
11684
11685 A fundamental concept needed to understand selection handling is that
11686 of the <em>atom</em>. An atom is an integer that uniquely identifies a
11687 string (on a certain display). Certain atoms are predefined by the X
11688 server, and in some cases there are constants in <tt>gtk.h</tt>
11689 corresponding to these atoms. For instance the constant
11690 <tt>GDK_PRIMARY_SELECTION</tt> corresponds to the string "PRIMARY".
11691 In other cases, you should use the functions
11692 <tt>gdk_atom_intern()</tt>, to get the atom corresponding to a string,
11693 and <tt>gdk_atom_name()</tt>, to get the name of an atom. Both
11694 selections and targets are identified by atoms.
11695
11696 <!-- ----------------------------------------------------------------- -->
11697 <sect1> Retrieving the selection
11698 <p>
11699 Retrieving the selection is an asynchronous process. To start the
11700 process, you call:
11701
11702 <tscreen><verb>
11703 gint gtk_selection_convert( GtkWidget *widget, 
11704                             GdkAtom    selection, 
11705                             GdkAtom    target,
11706                             guint32    time );
11707 </verb</tscreen>
11708
11709 This <em>converts</em> the selection into the form specified by
11710 <tt/target/. If at all possible, the time field should be the time
11711 from the event that triggered the selection. This helps make sure that
11712 events occur in the order that the user requested them. However, if it
11713 is not available (for instance, if the conversion was triggered by a
11714 "clicked" signal), then you can use the constant
11715 <tt>GDK_CURRENT_TIME</tt>.
11716
11717 When the selection owner responds to the request, a
11718 "selection_received" signal is sent to your application. The handler
11719 for this signal receives a pointer to a <tt>GtkSelectionData</tt>
11720 structure, which is defined as:
11721
11722 <tscreen><verb>
11723 struct _GtkSelectionData
11724 {
11725   GdkAtom selection;
11726   GdkAtom target;
11727   GdkAtom type;
11728   gint    format;
11729   guchar *data;
11730   gint    length;
11731 };
11732 </verb></tscreen>
11733
11734 <tt>selection</tt> and <tt>target</tt> are the values you gave in your
11735 <tt>gtk_selection_convert()</tt> call. <tt>type</tt> is an atom that
11736 identifies the type of data returned by the selection owner. Some
11737 possible values are "STRING", a string of latin-1 characters, "ATOM",
11738 a series of atoms, "INTEGER", an integer, etc. Most targets can only
11739 return one type. <tt/format/ gives the length of the units (for
11740 instance characters) in bits. Usually, you don't care about this when
11741 receiving data. <tt>data</tt> is a pointer to the returned data, and
11742 <tt>length</tt> gives the length of the returned data, in bytes. If
11743 <tt>length</tt> is negative, then an error occurred and the selection
11744 could not be retrieved. This might happen if no application owned the
11745 selection, or if you requested a target that the application didn't
11746 support. The buffer is actually guaranteed to be one byte longer than
11747 <tt>length</tt>; the extra byte will always be zero, so it isn't
11748 necessary to make a copy of strings just to null terminate them.
11749
11750 In the following example, we retrieve the special target "TARGETS",
11751 which is a list of all targets into which the selection can be
11752 converted.
11753
11754 <tscreen><verb>
11755 /* example-start selection gettargets.c */
11756
11757 #include <gtk/gtk.h>
11758
11759 void selection_received( GtkWidget        *widget, 
11760                          GtkSelectionData *selection_data, 
11761                          gpointer          data );
11762
11763 /* Signal handler invoked when user clicks on the "Get Targets" button */
11764 void get_targets( GtkWidget *widget,
11765                   gpointer data )
11766 {
11767   static GdkAtom targets_atom = GDK_NONE;
11768
11769   /* Get the atom corresponding to the string "TARGETS" */
11770   if (targets_atom == GDK_NONE)
11771     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
11772
11773   /* And request the "TARGETS" target for the primary selection */
11774   gtk_selection_convert (widget, GDK_SELECTION_PRIMARY, targets_atom,
11775                          GDK_CURRENT_TIME);
11776 }
11777
11778 /* Signal handler called when the selections owner returns the data */
11779 void selection_received( GtkWidget        *widget,
11780                          GtkSelectionData *selection_data, 
11781                          gpointer          data )
11782 {
11783   GdkAtom *atoms;
11784   GList *item_list;
11785   int i;
11786
11787   /* **** IMPORTANT **** Check to see if retrieval succeeded  */
11788   if (selection_data->length < 0)
11789     {
11790       g_print ("Selection retrieval failed\n");
11791       return;
11792     }
11793   /* Make sure we got the data in the expected form */
11794   if (selection_data->type != GDK_SELECTION_TYPE_ATOM)
11795     {
11796       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
11797       return;
11798     }
11799   
11800   /* Print out the atoms we received */
11801   atoms = (GdkAtom *)selection_data->data;
11802
11803   item_list = NULL;
11804   for (i=0; i<selection_data->length/sizeof(GdkAtom); i++)
11805     {
11806       char *name;
11807       name = gdk_atom_name (atoms[i]);
11808       if (name != NULL)
11809         g_print ("%s\n",name);
11810       else
11811         g_print ("(bad atom)\n");
11812     }
11813
11814   return;
11815 }
11816
11817 int main( int   argc,
11818           char *argv[] )
11819 {
11820   GtkWidget *window;
11821   GtkWidget *button;
11822   
11823   gtk_init (&amp;argc, &amp;argv);
11824
11825   /* Create the toplevel window */
11826
11827   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11828   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
11829   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11830
11831   gtk_signal_connect (GTK_OBJECT (window), "destroy",
11832                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
11833
11834   /* Create a button the user can click to get targets */
11835
11836   button = gtk_button_new_with_label ("Get Targets");
11837   gtk_container_add (GTK_CONTAINER (window), button);
11838
11839   gtk_signal_connect (GTK_OBJECT(button), "clicked",
11840                       GTK_SIGNAL_FUNC (get_targets), NULL);
11841   gtk_signal_connect (GTK_OBJECT(button), "selection_received",
11842                       GTK_SIGNAL_FUNC (selection_received), NULL);
11843
11844   gtk_widget_show (button);
11845   gtk_widget_show (window);
11846   
11847   gtk_main ();
11848   
11849   return 0;
11850 }
11851 /* example-end */
11852 </verb></tscreen>
11853
11854 <!-- ----------------------------------------------------------------- -->
11855 <sect1> Supplying the selection 
11856 <p>
11857 Supplying the selection is a bit more complicated. You must register 
11858 handlers that will be called when your selection is requested. For
11859 each selection/target pair you will handle, you make a call to:
11860
11861 <tscreen><verb>
11862 void gtk_selection_add_target (GtkWidget           *widget, 
11863                                GdkAtom              selection,
11864                                GdkAtom              target,
11865                                guint                info);
11866 </verb></tscreen>
11867
11868 <tt/widget/, <tt/selection/, and <tt/target/ identify the requests
11869 this handler will manage. When a request for a selection is received,
11870 the "selection_get" signal will be called. <tt/info/ can be used as an
11871 enumerator to identify the specific target within the callback function.
11872
11873 The callback function has the signature:
11874
11875 <tscreen><verb>
11876 void  "selection_get" (GtkWidget          *widget,
11877                        GtkSelectionData   *selection_data,
11878                        guint               info,
11879                        guint               time);
11880 </verb></tscreen>
11881
11882 The GtkSelectionData is the same as above, but this time, we're
11883 responsible for filling in the fields <tt/type/, <tt/format/,
11884 <tt/data/, and <tt/length/. (The <tt/format/ field is actually
11885 important here - the X server uses it to figure out whether the data
11886 needs to be byte-swapped or not. Usually it will be 8 - <em/i.e./ a
11887 character - or 32 - <em/i.e./ a. integer.) This is done by calling the
11888 function:
11889
11890 <tscreen><verb>
11891 void gtk_selection_data_set( GtkSelectionData *selection_data,
11892                              GdkAtom           type,
11893                              gint              format,
11894                              guchar           *data,
11895                              gint              length );
11896 </verb></tscreen>
11897
11898 This function takes care of properly making a copy of the data so that
11899 you don't have to worry about keeping it around. (You should not fill
11900 in the fields of the GtkSelectionData structure by hand.)
11901
11902 When prompted by the user, you claim ownership of the selection by
11903 calling:
11904
11905 <tscreen><verb>
11906 gint gtk_selection_owner_set( GtkWidget *widget,
11907                               GdkAtom    selection,
11908                               guint32    time );
11909 </verb></tscreen>
11910
11911 If another application claims ownership of the selection, you will
11912 receive a "selection_clear_event".
11913
11914 As an example of supplying the selection, the following program adds
11915 selection functionality to a toggle button. When the toggle button is
11916 depressed, the program claims the primary selection. The only target
11917 supported (aside from certain targets like "TARGETS" supplied by GTK
11918 itself), is the "STRING" target. When this target is requested, a
11919 string representation of the time is returned.
11920
11921 <tscreen><verb>
11922 /* example-start selection setselection.c */
11923
11924 #include <gtk/gtk.h>
11925 #include <time.h>
11926
11927 /* Callback when the user toggles the selection */
11928 void selection_toggled( GtkWidget *widget,
11929                         gint      *have_selection )
11930 {
11931   if (GTK_TOGGLE_BUTTON(widget)->active)
11932     {
11933       *have_selection = gtk_selection_owner_set (widget,
11934                                                  GDK_SELECTION_PRIMARY,
11935                                                  GDK_CURRENT_TIME);
11936       /* if claiming the selection failed, we return the button to
11937          the out state */
11938       if (!*have_selection)
11939         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
11940     }
11941   else
11942     {
11943       if (*have_selection)
11944         {
11945           /* Before clearing the selection by setting the owner to NULL,
11946              we check if we are the actual owner */
11947           if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
11948             gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY,
11949                                      GDK_CURRENT_TIME);
11950           *have_selection = FALSE;
11951         }
11952     }
11953 }
11954
11955 /* Called when another application claims the selection */
11956 gint selection_clear( GtkWidget         *widget,
11957                       GdkEventSelection *event,
11958                       gint              *have_selection )
11959 {
11960   *have_selection = FALSE;
11961   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(widget), FALSE);
11962
11963   return TRUE;
11964 }
11965
11966 /* Supplies the current time as the selection. */
11967 void selection_handle( GtkWidget        *widget, 
11968                        GtkSelectionData *selection_data,
11969                        guint             info,
11970                        guint             time_stamp,
11971                        gpointer          data )
11972 {
11973   gchar *timestr;
11974   time_t current_time;
11975
11976   current_time = time(NULL);
11977   timestr = asctime (localtime(&amp;current_time)); 
11978   /* When we return a single string, it should not be null terminated.
11979      That will be done for us */
11980
11981   gtk_selection_data_set (selection_data, GDK_SELECTION_TYPE_STRING,
11982                           8, timestr, strlen(timestr));
11983 }
11984
11985 int main( int   argc,
11986           char *argv[] )
11987 {
11988   GtkWidget *window;
11989   GtkWidget *selection_button;
11990
11991   static int have_selection = FALSE;
11992   
11993   gtk_init (&amp;argc, &amp;argv);
11994
11995   /* Create the toplevel window */
11996
11997   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11998   gtk_window_set_title (GTK_WINDOW (window), "Event Box");
11999   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12000
12001   gtk_signal_connect (GTK_OBJECT (window), "destroy",
12002                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
12003
12004   /* Create a toggle button to act as the selection */
12005
12006   selection_button = gtk_toggle_button_new_with_label ("Claim Selection");
12007   gtk_container_add (GTK_CONTAINER (window), selection_button);
12008   gtk_widget_show (selection_button);
12009
12010   gtk_signal_connect (GTK_OBJECT(selection_button), "toggled",
12011                       GTK_SIGNAL_FUNC (selection_toggled), &amp;have_selection);
12012   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_clear_event",
12013                       GTK_SIGNAL_FUNC (selection_clear), &amp;have_selection);
12014
12015   gtk_selection_add_target (selection_button,
12016                             GDK_SELECTION_PRIMARY,
12017                             GDK_SELECTION_TYPE_STRING,
12018                             1);
12019   gtk_signal_connect (GTK_OBJECT(selection_button), "selection_get",
12020                       GTK_SIGNAL_FUNC (selection_handle), &amp;have_selection);
12021
12022   gtk_widget_show (selection_button);
12023   gtk_widget_show (window);
12024   
12025   gtk_main ();
12026   
12027   return 0;
12028 }
12029 /* example-end */
12030 </verb></tscreen>
12031
12032
12033 <!-- ***************************************************************** -->
12034 <sect>GLib<label id="sec_glib">
12035 <!-- ***************************************************************** -->
12036 <p>
12037 GLib is a lower-level library that provides many useful definitions
12038 and functions available for use when creating GDK and GTK
12039 applications. These include definitions for basic types and their
12040 limits, standard macros, type conversions, byte order, memory
12041 allocation, warnings and assertions, message logging, timers, string
12042 utilities, hook functions, a lexical scanner, dynamic loading of
12043 modules, and automatic string completion. A number of data structures
12044 (and their related operations) are also defined, including memory
12045 chunks, doubly-linked lists, singly-linked lists, hash tables, strings
12046 (which can grow dynamically), string chunks (groups of strings),
12047 arrays (which can grow in size as elements are added), balanced binary
12048 trees, N-ary trees, quarks (a two-way association of a string and a
12049 unique integer identifier), keyed data lists (lists of data elements
12050 accessible by a string or integer id), relations and tuples (tables of
12051 data which can be indexed on any number of fields), and caches.
12052
12053 A summary of some of GLib's capabilities follows; not every function,
12054 data structure, or operation is covered here.  For more complete
12055 information about the GLib routines, see the GLib documentation. One
12056 source of GLib documentation is <htmlurl url="http://www.gtk.org/"
12057 name="http://www.gtk.org/">.
12058
12059 If you are using a language other than C, you should consult your
12060 language's binding documentation. In some cases your language may
12061 have equivalent functionality built-in, while in other cases it may
12062 not.
12063
12064 <!-- ----------------------------------------------------------------- -->
12065 <sect1>Definitions
12066 <p>
12067 Definitions for the extremes of many of the standard types are:
12068
12069 <tscreen><verb>
12070 G_MINFLOAT
12071 G_MAXFLOAT
12072 G_MINDOUBLE
12073 G_MAXDOUBLE
12074 G_MINSHORT
12075 G_MAXSHORT
12076 G_MININT
12077 G_MAXINT
12078 G_MINLONG
12079 G_MAXLONG
12080 </verb></tscreen>
12081
12082 Also, the following typedefs. The ones left unspecified are dynamically set
12083 depending on the architecture. Remember to avoid counting on the size of a
12084 pointer if you want to be portable! E.g., a pointer on an Alpha is 8
12085 bytes, but 4 on Intel 80x86 family CPUs.
12086
12087 <tscreen><verb>
12088 char   gchar;
12089 short  gshort;
12090 long   glong;
12091 int    gint;
12092 char   gboolean;
12093
12094 unsigned char   guchar;
12095 unsigned short  gushort;
12096 unsigned long   gulong;
12097 unsigned int    guint;
12098
12099 float   gfloat;
12100 double  gdouble;
12101 long double gldouble;
12102
12103 void* gpointer;
12104
12105 gint8
12106 guint8
12107 gint16
12108 guint16
12109 gint32
12110 guint32
12111 </verb></tscreen>
12112
12113 <!-- ----------------------------------------------------------------- -->
12114 <sect1>Doubly Linked Lists
12115 <p>
12116 The following functions are used to create, manage, and destroy
12117 standard doubly linked lists. Each element in the list contains a
12118 piece of data, together with pointers which link to the previous and
12119 next elements in the list. This enables easy movement in either
12120 direction through the list. The data item is of type "gpointer",
12121 which means the data can be a pointer to your real data or (through
12122 casting) a numeric value (but do not assume that int and gpointer have
12123 the same size!). These routines internally allocate list elements in
12124 blocks, which is more efficient than allocating elements individually.
12125
12126 There is no function to specifically create a list. Instead, simply
12127 create a variable of type GList* and set its value to NULL; NULL is
12128 considered to be the empty list.
12129
12130 To add elements to a list, use the g_list_append(), g_list_prepend(),
12131 g_list_insert(), or g_list_insert_sorted() routines. In all cases
12132 they accept a pointer to the beginning of the list, and return the
12133 (possibly changed) pointer to the beginning of the list. Thus, for
12134 all of the operations that add or remove elements, be sure to save the
12135 returned value!
12136
12137 <tscreen><verb>
12138 GList *g_list_append( GList    *list,
12139                       gpointer  data );
12140 </verb></tscreen>
12141
12142 This adds a new element (with value <tt/data/) onto the end of the
12143 list.
12144   
12145 <tscreen><verb>    
12146 GList *g_list_prepend( GList    *list,
12147                        gpointer  data );
12148 </verb></tscreen>
12149
12150 This adds a new element (with value <tt/data/) to the beginning of the
12151 list.
12152
12153 <tscreen><verb>         
12154 GList *g_list_insert( GList    *list,
12155                       gpointer  data,
12156                       gint      position );
12157
12158 </verb></tscreen>
12159
12160 This inserts a new element (with value data) into the list at the
12161 given position. If position is 0, this is just like g_list_prepend();
12162 if position is less than 0, this is just like g_list_append().
12163
12164 <tscreen><verb>
12165 GList *g_list_remove( GList    *list,
12166                       gpointer  data );
12167 </verb></tscreen>
12168
12169 This removes the element in the list with the value <tt/data/;
12170 if the element isn't there, the list is unchanged.
12171
12172 <tscreen><verb>
12173 void g_list_free( GList *list );
12174 </verb></tscreen>
12175
12176 This frees all of the memory used by a GList. If the list elements
12177 refer to dynamically-allocated memory, then they should be freed
12178 first.
12179
12180 There are many other GLib functions that support doubly linked lists;
12181 see the glib documentation for more information.  Here are a few of
12182 the more useful functions' signatures:
12183
12184 <tscreen><verb>            
12185 GList *g_list_remove_link( GList *list,
12186                            GList *link );
12187
12188 GList *g_list_reverse( GList *list );
12189
12190 GList *g_list_nth( GList *list,
12191                    gint   n );
12192                            
12193 GList *g_list_find( GList    *list,
12194                     gpointer  data );
12195
12196 GList *g_list_last( GList *list );
12197
12198 GList *g_list_first( GList *list );
12199
12200 gint g_list_length( GList *list );
12201
12202 void g_list_foreach( GList    *list,
12203                      GFunc     func,
12204                      gpointer  user_data );
12205 </verb></tscreen>                                             
12206
12207 <!-- ----------------------------------------------------------------- -->
12208 <sect1>Singly Linked Lists
12209 <p>
12210 Many of the above functions for singly linked lists are identical to the
12211 above. Here is a list of some of their operations:
12212
12213 <tscreen><verb>
12214 GSList *g_slist_append( GSList   *list,
12215                         gpointer  data );
12216                 
12217 GSList *g_slist_prepend( GSList   *list,
12218                          gpointer  data );
12219                              
12220 GSList *g_slist_insert( GSList   *list,
12221                         gpointer  data,
12222                         gint      position );
12223                              
12224 GSList *g_slist_remove( GSList   *list,
12225                         gpointer  data );
12226                              
12227 GSList *g_slist_remove_link( GSList *list,
12228                              GSList *link );
12229                              
12230 GSList *g_slist_reverse( GSList *list );
12231
12232 GSList *g_slist_nth( GSList *list,
12233                      gint    n );
12234                              
12235 GSList *g_slist_find( GSList   *list,
12236                       gpointer  data );
12237                              
12238 GSList *g_slist_last( GSList *list );
12239
12240 gint g_slist_length( GSList *list );
12241
12242 void g_slist_foreach( GSList   *list,
12243                       GFunc     func,
12244                       gpointer  user_data );
12245         
12246 </verb></tscreen>
12247
12248 <!-- ----------------------------------------------------------------- -->
12249 <sect1>Memory Management
12250 <p>
12251 <tscreen><verb>
12252 gpointer g_malloc( gulong size );
12253 </verb></tscreen>
12254
12255 This is a replacement for malloc(). You do not need to check the return
12256 value as it is done for you in this function. If the memory allocation
12257 fails for whatever reasons, your applications will be terminated.
12258
12259 <tscreen><verb>
12260 gpointer g_malloc0( gulong size );
12261 </verb></tscreen>
12262
12263 Same as above, but zeroes the memory before returning a pointer to it.
12264
12265 <tscreen><verb>
12266 gpointer g_realloc( gpointer mem,
12267                     gulong   size );
12268 </verb></tscreen>
12269
12270 Relocates "size" bytes of memory starting at "mem".  Obviously, the
12271 memory should have been previously allocated.
12272
12273 <tscreen><verb>
12274 void g_free( gpointer mem );
12275 </verb></tscreen>
12276
12277 Frees memory. Easy one. If <tt/mem/ is NULL it simply returns.
12278
12279 <tscreen><verb>
12280 void g_mem_profile( void );
12281 </verb></tscreen>
12282
12283 Dumps a profile of used memory, but requires that you add <tt>#define
12284 MEM_PROFILE</tt> to the top of glib/gmem.c and re-make and make install.
12285
12286 <tscreen><verb>
12287 void g_mem_check( gpointer mem );
12288 </verb></tscreen>
12289
12290 Checks that a memory location is valid. Requires you add <tt>#define
12291 MEM_CHECK</tt> to the top of gmem.c and re-make and make install.
12292
12293 <!-- ----------------------------------------------------------------- -->
12294 <sect1>Timers
12295 <p>
12296 Timer functions can be used to time operations (e.g., to see how much
12297 time has elapsed). First, you create a new timer with g_timer_new().
12298 You can then use g_timer_start() to start timing an operation,
12299 g_timer_stop() to stop timing an operation, and g_timer_elapsed() to
12300 determine the elapsed time.
12301
12302 <tscreen><verb>
12303 GTimer *g_timer_new( void );
12304
12305 void g_timer_destroy( GTimer *timer );
12306
12307 void g_timer_start( GTimer  *timer );
12308
12309 void g_timer_stop( GTimer  *timer );
12310
12311 void g_timer_reset( GTimer  *timer );
12312
12313 gdouble g_timer_elapsed( GTimer *timer,
12314                          gulong *microseconds );
12315 </verb></tscreen>                        
12316
12317 <!-- ----------------------------------------------------------------- -->
12318 <sect1>String Handling
12319 <p>
12320 GLib defines a new type called a GString, which is similar to a
12321 standard C string but one that grows automatically. Its string data
12322 is null-terminated. What this gives you is protection from buffer
12323 overflow programming errors within your program. This is a very
12324 important feature, and hence I recommend that you make use of
12325 GStrings. GString itself has a simple public definition:
12326
12327 <tscreen><verb>
12328 struct GString 
12329 {
12330   gchar *str; /* Points to the string's current \0-terminated value. */
12331   gint len; /* Current length */
12332 };
12333 </verb></tscreen>
12334
12335 As you might expect, there are a number of operations you can do with
12336 a GString.
12337
12338 <tscreen><verb>
12339 GString *g_string_new( gchar *init );
12340 </verb></tscreen>
12341
12342 This constructs a GString, copying the string value of <tt/init/
12343 into the GString and returning a pointer to it. NULL may be given as
12344 the argument for an initially empty GString.
12345  
12346 <tscreen><verb>
12347
12348 void g_string_free( GString *string,
12349                     gint     free_segment );
12350 </verb></tscreen>
12351
12352 This frees the memory for the given GString. If <tt/free_segment/ is
12353 TRUE, then this also frees its character data.
12354
12355 <tscreen><verb>
12356                              
12357 GString *g_string_assign( GString     *lval,
12358                           const gchar *rval );
12359 </verb></tscreen>
12360
12361 This copies the characters from rval into lval, destroying the
12362 previous contents of lval. Note that lval will be lengthened as
12363 necessary to hold the string's contents, unlike the standard strcpy()
12364 function.
12365
12366 The rest of these functions should be relatively obvious (the _c
12367 versions accept a character instead of a string):
12368
12369 <tscreen><verb>              
12370 GString *g_string_truncate( GString *string,
12371                             gint     len );
12372                              
12373 GString *g_string_append( GString *string,
12374                           gchar   *val );
12375                             
12376 GString *g_string_append_c( GString *string,
12377                             gchar    c );
12378         
12379 GString *g_string_prepend( GString *string,
12380                            gchar   *val );
12381                              
12382 GString *g_string_prepend_c( GString *string,
12383                              gchar    c );
12384         
12385 void g_string_sprintf( GString *string,
12386                        gchar   *fmt,
12387                        ...);
12388         
12389 void g_string_sprintfa ( GString *string,
12390                          gchar   *fmt,
12391                          ... );
12392 </verb></tscreen>                                                         
12393
12394 <!-- ----------------------------------------------------------------- -->
12395 <sect1>Utility and Error Functions
12396 <p>
12397 <tscreen><verb>
12398 gchar *g_strdup( const gchar *str );
12399 </verb></tscreen>
12400
12401 Replacement strdup function.  Copies the original strings contents to
12402 newly allocated memory, and returns a pointer to it.
12403
12404 <tscreen><verb>
12405 gchar *g_strerror( gint errnum );
12406 </verb></tscreen>
12407
12408 I recommend using this for all error messages.  It's much nicer, and more
12409 portable than perror() or others.  The output is usually of the form:
12410
12411 <tscreen><verb>
12412 program name:function that failed:file or further description:strerror
12413 </verb></tscreen>
12414
12415 Here's an example of one such call used in our hello_world program:
12416
12417 <tscreen><verb>
12418 g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
12419 </verb></tscreen>
12420
12421 <tscreen><verb>
12422 void g_error( gchar *format, ... );
12423 </verb></tscreen>
12424
12425 Prints an error message. The format is just like printf, but it
12426 prepends "** ERROR **: " to your message, and exits the program.  
12427 Use only for fatal errors.
12428
12429 <tscreen><verb>
12430 void g_warning( gchar *format, ... );
12431 </verb></tscreen>
12432
12433 Same as above, but prepends "** WARNING **: ", and does not exit the
12434 program.
12435
12436 <tscreen><verb>
12437 void g_message( gchar *format, ... );
12438 </verb></tscreen>
12439
12440 Prints "message: " prepended to the string you pass in.
12441
12442 <tscreen><verb>
12443 void g_print( gchar *format, ... );
12444 </verb></tscreen>
12445
12446 Replacement for printf().
12447
12448 And our last function:
12449
12450 <tscreen><verb>
12451 gchar *g_strsignal( gint signum );
12452 </verb></tscreen>
12453
12454 Prints out the name of the Unix system signal given the signal number.
12455 Useful in generic signal handling functions.
12456
12457 All of the above are more or less just stolen from glib.h.  If anyone cares
12458 to document any function, just send me an email!
12459
12460 <!-- ***************************************************************** -->
12461 <sect>GTK's rc Files <label id="sec_gtkrc_files">
12462 <!-- ***************************************************************** -->
12463 <p>
12464 GTK has its own way of dealing with application defaults, by using rc
12465 files. These can be used to set the colors of just about any widget, and
12466 can also be used to tile pixmaps onto the background of some widgets.  
12467
12468 <!-- ----------------------------------------------------------------- -->
12469 <sect1>Functions For rc Files 
12470 <p>
12471 When your application starts, you should include a call to:
12472
12473 <tscreen><verb>
12474 void gtk_rc_parse( char *filename );
12475 </verb></tscreen>
12476
12477 Passing in the filename of your rc file. This will cause GTK to parse
12478 this file, and use the style settings for the widget types defined
12479 there.
12480
12481 If you wish to have a special set of widgets that can take on a
12482 different style from others, or any other logical division of widgets,
12483 use a call to:
12484
12485 <tscreen><verb>
12486 void gtk_widget_set_name( GtkWidget *widget,
12487                           gchar     *name );
12488 </verb></tscreen>
12489
12490 Passing your newly created widget as the first argument, and the name
12491 you wish to give it as the second. This will allow you to change the
12492 attributes of this widget by name through the rc file.
12493
12494 If we use a call something like this:
12495
12496 <tscreen><verb>
12497 button = gtk_button_new_with_label ("Special Button");
12498 gtk_widget_set_name (button, "special button");
12499 </verb></tscreen>
12500
12501 Then this button is given the name "special button" and may be addressed by
12502 name in the rc file as "special button.GtkButton".  [<--- Verify ME!]
12503
12504 The example rc file below, sets the properties of the main window, and lets
12505 all children of that main window inherit the style described by the "main
12506 button" style.  The code used in the application is:
12507
12508 <tscreen><verb>
12509 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12510 gtk_widget_set_name (window, "main window");
12511 </verb></tscreen>
12512
12513 And then the style is defined in the rc file using:
12514
12515 <tscreen><verb>
12516 widget "main window.*GtkButton*" style "main_button"
12517 </verb></tscreen>
12518
12519 Which sets all the Button widgets in the "main window" to the
12520 "main_buttons" style as defined in the rc file.
12521
12522 As you can see, this is a fairly powerful and flexible system.  Use your
12523 imagination as to how best to take advantage of this.
12524
12525 <!-- ----------------------------------------------------------------- -->
12526 <sect1>GTK's rc File Format
12527 <p>
12528 The format of the GTK file is illustrated in the example below. This is
12529 the testgtkrc file from the GTK distribution, but I've added a
12530 few comments and things. You may wish to include this explanation in
12531 your application to allow the user to fine tune his application.
12532
12533 There are several directives to change the attributes of a widget.
12534
12535 <itemize>
12536 <item>fg - Sets the foreground color of a widget.
12537 <item>bg - Sets the background color of a widget.
12538 <item>bg_pixmap - Sets the background of a widget to a tiled pixmap.
12539 <item>font - Sets the font to be used with the given widget.
12540 </itemize>
12541
12542 In addition to this, there are several states a widget can be in, and you
12543 can set different colors, pixmaps and fonts for each state. These states are:
12544
12545 <itemize>
12546 <item>NORMAL - The normal state of a widget, without the mouse over top of
12547 it, and not being pressed, etc.
12548 <item>PRELIGHT - When the mouse is over top of the widget, colors defined
12549 using this state will be in effect.
12550 <item>ACTIVE - When the widget is pressed or clicked it will be active, and
12551 the attributes assigned by this tag will be in effect.
12552 <item>INSENSITIVE - When a widget is set insensitive, and cannot be
12553 activated, it will take these attributes.
12554 <item>SELECTED - When an object is selected, it takes these attributes.
12555 </itemize>
12556
12557 When using the "fg" and "bg" keywords to set the colors of widgets, the
12558 format is:
12559
12560 <tscreen><verb>
12561 fg[<STATE>] = { Red, Green, Blue }
12562 </verb></tscreen>
12563
12564 Where STATE is one of the above states (PRELIGHT, ACTIVE, etc), and the Red,
12565 Green and Blue are values in the range of 0 - 1.0,  { 1.0, 1.0, 1.0 } being
12566 white. They must be in float form, or they will register as 0, so a straight 
12567 "1" will not work, it must be "1.0".  A straight "0" is fine because it 
12568 doesn't matter if it's not recognized.  Unrecognized values are set to 0.
12569
12570 bg_pixmap is very similar to the above, except the colors are replaced by a
12571 filename.
12572
12573 pixmap_path is a list of paths separated by ":"'s.  These paths will be
12574 searched for any pixmap you specify.
12575
12576 The font directive is simply:
12577 <tscreen><verb>
12578 font = "<font name>"
12579 </verb></tscreen>
12580
12581 The only hard part is figuring out the font string. Using xfontsel or
12582 a similar utility should help.
12583
12584 The "widget_class" sets the style of a class of widgets. These classes are
12585 listed in the widget overview on the class hierarchy.
12586
12587 The "widget" directive sets a specifically named set of widgets to a
12588 given style, overriding any style set for the given widget class.
12589 These widgets are registered inside the application using the
12590 gtk_widget_set_name() call. This allows you to specify the attributes of a
12591 widget on a per widget basis, rather than setting the attributes of an
12592 entire widget class. I urge you to document any of these special widgets so
12593 users may customize them.
12594
12595 When the keyword <tt>parent</> is used as an attribute, the widget will take on
12596 the attributes of its parent in the application.
12597
12598 When defining a style, you may assign the attributes of a previously defined
12599 style to this new one.
12600
12601 <tscreen><verb>
12602 style "main_button" = "button"
12603 {
12604   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
12605   bg[PRELIGHT] = { 0.75, 0, 0 }
12606 }
12607 </verb></tscreen>
12608
12609 This example takes the "button" style, and creates a new "main_button" style
12610 simply by changing the font and prelight background color of the "button"
12611 style.
12612
12613 Of course, many of these attributes don't apply to all widgets. It's a
12614 simple matter of common sense really. Anything that could apply, should.
12615
12616 <!-- ----------------------------------------------------------------- -->
12617 <sect1>Example rc file
12618 <p>
12619
12620 <tscreen><verb>
12621 # pixmap_path "<dir 1>:<dir 2>:<dir 3>:..."
12622 #
12623 pixmap_path "/usr/include/X11R6/pixmaps:/home/imain/pixmaps"
12624 #
12625 # style <name> [= <name>]
12626 # {
12627 #   <option>
12628 # }
12629 #
12630 # widget <widget_set> style <style_name>
12631 # widget_class <widget_class_set> style <style_name>
12632
12633
12634 # Here is a list of all the possible states.  Note that some do not apply to
12635 # certain widgets.
12636 #
12637 # NORMAL - The normal state of a widget, without the mouse over top of
12638 # it, and not being pressed, etc.
12639 #
12640 # PRELIGHT - When the mouse is over top of the widget, colors defined
12641 # using this state will be in effect.
12642 #
12643 # ACTIVE - When the widget is pressed or clicked it will be active, and
12644 # the attributes assigned by this tag will be in effect.
12645 #
12646 # INSENSITIVE - When a widget is set insensitive, and cannot be
12647 # activated, it will take these attributes.
12648 #
12649 # SELECTED - When an object is selected, it takes these attributes.
12650 #
12651 # Given these states, we can set the attributes of the widgets in each of
12652 # these states using the following directives.
12653 #
12654 # fg - Sets the foreground color of a widget.
12655 # fg - Sets the background color of a widget.
12656 # bg_pixmap - Sets the background of a widget to a tiled pixmap.
12657 # font - Sets the font to be used with the given widget.
12658 #
12659
12660 # This sets a style called "button".  The name is not really important, as
12661 # it is assigned to the actual widgets at the bottom of the file.
12662
12663 style "window"
12664 {
12665   #This sets the padding around the window to the pixmap specified.
12666   #bg_pixmap[<STATE>] = "<pixmap filename>"
12667   bg_pixmap[NORMAL] = "warning.xpm"
12668 }
12669
12670 style "scale"
12671 {
12672   #Sets the foreground color (font color) to red when in the "NORMAL"
12673   #state.
12674   
12675   fg[NORMAL] = { 1.0, 0, 0 }
12676   
12677   #Sets the background pixmap of this widget to that of its parent.
12678   bg_pixmap[NORMAL] = "<parent>"
12679 }
12680
12681 style "button"
12682 {
12683   # This shows all the possible states for a button.  The only one that
12684   # doesn't apply is the SELECTED state.
12685   
12686   fg[PRELIGHT] = { 0, 1.0, 1.0 }
12687   bg[PRELIGHT] = { 0, 0, 1.0 }
12688   bg[ACTIVE] = { 1.0, 0, 0 }
12689   fg[ACTIVE] = { 0, 1.0, 0 }
12690   bg[NORMAL] = { 1.0, 1.0, 0 }
12691   fg[NORMAL] = { .99, 0, .99 }
12692   bg[INSENSITIVE] = { 1.0, 1.0, 1.0 }
12693   fg[INSENSITIVE] = { 1.0, 0, 1.0 }
12694 }
12695
12696 # In this example, we inherit the attributes of the "button" style and then
12697 # override the font and background color when prelit to create a new
12698 # "main_button" style.
12699
12700 style "main_button" = "button"
12701 {
12702   font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*"
12703   bg[PRELIGHT] = { 0.75, 0, 0 }
12704 }
12705
12706 style "toggle_button" = "button"
12707 {
12708   fg[NORMAL] = { 1.0, 0, 0 }
12709   fg[ACTIVE] = { 1.0, 0, 0 }
12710   
12711   # This sets the background pixmap of the toggle_button to that of its
12712   # parent widget (as defined in the application).
12713   bg_pixmap[NORMAL] = "<parent>"
12714 }
12715
12716 style "text"
12717 {
12718   bg_pixmap[NORMAL] = "marble.xpm"
12719   fg[NORMAL] = { 1.0, 1.0, 1.0 }
12720 }
12721
12722 style "ruler"
12723 {
12724   font = "-adobe-helvetica-medium-r-normal--*-80-*-*-*-*-*-*"
12725 }
12726
12727 # pixmap_path "~/.pixmaps"
12728
12729 # These set the widget types to use the styles defined above.
12730 # The widget types are listed in the class hierarchy, but could probably be
12731 # just listed in this document for the users reference.
12732
12733 widget_class "GtkWindow" style "window"
12734 widget_class "GtkDialog" style "window"
12735 widget_class "GtkFileSelection" style "window"
12736 widget_class "*Gtk*Scale" style "scale"
12737 widget_class "*GtkCheckButton*" style "toggle_button"
12738 widget_class "*GtkRadioButton*" style "toggle_button"
12739 widget_class "*GtkButton*" style "button"
12740 widget_class "*Ruler" style "ruler"
12741 widget_class "*GtkText" style "text"
12742
12743 # This sets all the buttons that are children of the "main window" to
12744 # the main_button style.  These must be documented to be taken advantage of.
12745 widget "main window.*GtkButton*" style "main_button"
12746 </verb></tscreen>
12747
12748 <!-- ***************************************************************** -->
12749 <sect>Writing Your Own Widgets 
12750 <!-- ***************************************************************** -->
12751
12752 <!-- ----------------------------------------------------------------- -->
12753 <sect1> Overview
12754 <p>
12755 Although the GTK distribution comes with many types of widgets that
12756 should cover most basic needs, there may come a time when you need to
12757 create your own new widget type. Since GTK uses widget inheritance
12758 extensively, and there is already a widget that is close to what you want,
12759 it is often possible to make a useful new widget type in
12760 just a few lines of code. But before starting work on a new widget, check
12761 around first to make sure that someone has not already written
12762 it. This will prevent duplication of effort and keep the number of
12763 GTK widgets out there to a minimum, which will help keep both the code
12764 and the interface of different applications consistent. As a flip side
12765 to this, once you finish your widget, announce it to the world so
12766 other people can benefit. The best place to do this is probably the
12767 <tt>gtk-list</tt>.
12768
12769 Complete sources for the example widgets are available at the place you 
12770 got this tutorial, or from:
12771
12772 <htmlurl url="http://www.gtk.org/~otaylor/gtk/tutorial/"
12773 name="http://www.gtk.org/~otaylor/gtk/tutorial/">
12774
12775
12776 <!-- ----------------------------------------------------------------- -->
12777 <sect1> The Anatomy Of A Widget
12778 <p>
12779 In order to create a new widget, it is important to have an
12780 understanding of how GTK objects work. This section is just meant as a
12781 brief overview. See the reference documentation for the details. 
12782
12783 GTK widgets are implemented in an object oriented fashion. However,
12784 they are implemented in standard C. This greatly improves portability
12785 and stability over using current generation C++ compilers; however,
12786 it does mean that the widget writer has to pay attention to some of
12787 the implementation details. The information common to all instances of
12788 one class of widgets (e.g., to all Button widgets) is stored in the 
12789 <em>class structure</em>. There is only one copy of this in
12790 which is stored information about the class's signals
12791 (which act like virtual functions in C). To support inheritance, the
12792 first field in the class structure must be a copy of the parent's
12793 class structure. The declaration of the class structure of GtkButtton
12794 looks like:
12795
12796 <tscreen><verb>
12797 struct _GtkButtonClass
12798 {
12799   GtkContainerClass parent_class;
12800
12801   void (* pressed)  (GtkButton *button);
12802   void (* released) (GtkButton *button);
12803   void (* clicked)  (GtkButton *button);
12804   void (* enter)    (GtkButton *button);
12805   void (* leave)    (GtkButton *button);
12806 };
12807 </verb></tscreen>
12808
12809 When a button is treated as a container (for instance, when it is
12810 resized), its class structure can be cast to GtkContainerClass, and
12811 the relevant fields used to handle the signals.
12812
12813 There is also a structure for each widget that is created on a
12814 per-instance basis. This structure has fields to store information that
12815 is different for each instance of the widget. We'll call this
12816 structure the <em>object structure</em>. For the Button class, it looks
12817 like:
12818
12819 <tscreen><verb>
12820 struct _GtkButton
12821 {
12822   GtkContainer container;
12823
12824   GtkWidget *child;
12825
12826   guint in_button : 1;
12827   guint button_down : 1;
12828 };
12829 </verb></tscreen>
12830
12831 Note that, similar to the class structure, the first field is the
12832 object structure of the parent class, so that this structure can be
12833 cast to the parent class' object structure as needed.
12834
12835 <!-- ----------------------------------------------------------------- -->
12836 <sect1> Creating a Composite widget
12837
12838 <!-- ----------------------------------------------------------------- -->
12839 <sect2> Introduction
12840 <p>
12841 One type of widget that you may be interested in creating is a
12842 widget that is merely an aggregate of other GTK widgets. This type of
12843 widget does nothing that couldn't be done without creating new
12844 widgets, but provides a convenient way of packaging user interface
12845 elements for reuse. The FileSelection and ColorSelection widgets in
12846 the standard distribution are examples of this type of widget.
12847
12848 The example widget that we'll create in this section is the Tictactoe
12849 widget, a 3x3 array of toggle buttons which triggers a signal when all
12850 three buttons in a row, column, or on one of the diagonals are
12851 depressed. 
12852
12853 <!-- ----------------------------------------------------------------- -->
12854 <sect2> Choosing a parent class
12855 <p>
12856 The parent class for a composite widget is typically the container
12857 class that holds all of the elements of the composite widget. For
12858 example, the parent class of the FileSelection widget is the
12859 Dialog class. Since our buttons will be arranged in a table, it
12860 might seem natural to make our parent class the Table
12861 class. Unfortunately, this turns out not to work. The creation of a
12862 widget is divided among two functions - a <tt/WIDGETNAME_new()/
12863 function that the user calls, and a <tt/WIDGETNAME_init()/ function
12864 which does the basic work of initializing the widget which is
12865 independent of the arguments passed to the <tt/_new()/
12866 function. Descendant widgets only call the <tt/_init/ function of
12867 their parent widget. But this division of labor doesn't work well for
12868 tables, which when created need to know the number of rows and
12869 columns in the table. Unless we want to duplicate most of the
12870 functionality of <tt/gtk_table_new()/ in our Tictactoe widget, we had
12871 best avoid deriving it from Table. For that reason, we derive it
12872 from VBox instead, and stick our table inside the VBox.
12873
12874 <!-- ----------------------------------------------------------------- -->
12875 <sect2> The header file
12876 <p>
12877 Each widget class has a header file which declares the object and
12878 class structures for that widget, along with public functions. 
12879 A couple of features are worth pointing out. To prevent duplicate
12880 definitions, we wrap the entire header file in:
12881
12882 <tscreen><verb>
12883 #ifndef __TICTACTOE_H__
12884 #define __TICTACTOE_H__
12885 .
12886 .
12887 .
12888 #endif /* __TICTACTOE_H__ */
12889 </verb></tscreen>
12890
12891 And to keep C++ programs that include the header file happy, in:
12892
12893 <tscreen><verb>
12894 #ifdef __cplusplus
12895 extern "C" {
12896 #endif /* __cplusplus */
12897 .
12898 .
12899 .
12900 #ifdef __cplusplus
12901 }
12902 #endif /* __cplusplus */
12903 </verb></tscreen>
12904
12905 Along with the functions and structures, we declare three standard
12906 macros in our header file, <tt/TICTACTOE(obj)/,
12907 <tt/TICTACTOE_CLASS(klass)/, and <tt/IS_TICTACTOE(obj)/, which cast a
12908 pointer into a pointer to the object or class structure, and check
12909 if an object is a Tictactoe widget respectively.
12910
12911 Here is the complete header file:
12912
12913 <tscreen><verb>
12914 /* tictactoe.h */
12915
12916 #ifndef __TICTACTOE_H__
12917 #define __TICTACTOE_H__
12918
12919 #include <gdk/gdk.h>
12920 #include <gtk/gtkvbox.h>
12921
12922 #ifdef __cplusplus
12923 extern "C" {
12924 #endif /* __cplusplus */
12925
12926 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
12927 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
12928 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
12929
12930
12931 typedef struct _Tictactoe       Tictactoe;
12932 typedef struct _TictactoeClass  TictactoeClass;
12933
12934 struct _Tictactoe
12935 {
12936   GtkVBox vbox;
12937   
12938   GtkWidget *buttons[3][3];
12939 };
12940
12941 struct _TictactoeClass
12942 {
12943   GtkVBoxClass parent_class;
12944
12945   void (* tictactoe) (Tictactoe *ttt);
12946 };
12947
12948 guint          tictactoe_get_type        (void);
12949 GtkWidget*     tictactoe_new             (void);
12950 void           tictactoe_clear           (Tictactoe *ttt);
12951
12952 #ifdef __cplusplus
12953 }
12954 #endif /* __cplusplus */
12955
12956 #endif /* __TICTACTOE_H__ */
12957
12958 </verb></tscreen>
12959
12960 <!-- ----------------------------------------------------------------- -->
12961 <sect2> The <tt/_get_type()/ function.
12962 <p>
12963 We now continue on to the implementation of our widget. A core
12964 function for every widget is the function
12965 <tt/WIDGETNAME_get_type()/. This function, when first called, tells
12966 GTK about the widget class, and gets an ID that uniquely identifies
12967 the widget class. Upon subsequent calls, it just returns the ID.
12968
12969 <tscreen><verb>
12970 guint
12971 tictactoe_get_type ()
12972 {
12973   static guint ttt_type = 0;
12974
12975   if (!ttt_type)
12976     {
12977       GtkTypeInfo ttt_info =
12978       {
12979         "Tictactoe",
12980         sizeof (Tictactoe),
12981         sizeof (TictactoeClass),
12982         (GtkClassInitFunc) tictactoe_class_init,
12983         (GtkObjectInitFunc) tictactoe_init,
12984         (GtkArgSetFunc) NULL,
12985         (GtkArgGetFunc) NULL
12986       };
12987
12988       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
12989     }
12990
12991   return ttt_type;
12992 }
12993 </verb></tscreen>
12994
12995 The GtkTypeInfo structure has the following definition:
12996
12997 <tscreen><verb>
12998 struct _GtkTypeInfo
12999 {
13000   gchar *type_name;
13001   guint object_size;
13002   guint class_size;
13003   GtkClassInitFunc class_init_func;
13004   GtkObjectInitFunc object_init_func;
13005   GtkArgSetFunc arg_set_func;
13006   GtkArgGetFunc arg_get_func;
13007 };
13008 </verb></tscreen>
13009
13010 The fields of this structure are pretty self-explanatory. We'll ignore
13011 the <tt/arg_set_func/ and <tt/arg_get_func/ fields here: they have an important, 
13012 but as yet largely
13013 unimplemented, role in allowing widget options to be conveniently set
13014 from interpreted languages. Once GTK has a correctly filled in copy of
13015 this structure, it knows how to create objects of a particular widget
13016 type. 
13017
13018 <!-- ----------------------------------------------------------------- -->
13019 <sect2> The <tt/_class_init()/ function
13020 <p>
13021 The <tt/WIDGETNAME_class_init()/ function initializes the fields of
13022 the widget's class structure, and sets up any signals for the
13023 class. For our Tictactoe widget it looks like:
13024
13025 <tscreen><verb>
13026
13027 enum {
13028   TICTACTOE_SIGNAL,
13029   LAST_SIGNAL
13030 };
13031
13032 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
13033
13034 static void
13035 tictactoe_class_init (TictactoeClass *class)
13036 {
13037   GtkObjectClass *object_class;
13038
13039   object_class = (GtkObjectClass*) class;
13040   
13041   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
13042                                          GTK_RUN_FIRST,
13043                                          object_class->type,
13044                                          GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
13045                                          gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
13046
13047
13048   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
13049
13050   class->tictactoe = NULL;
13051 }
13052 </verb></tscreen>
13053
13054 Our widget has just one signal, the <tt/tictactoe/ signal that is
13055 invoked when a row, column, or diagonal is completely filled in. Not
13056 every composite widget needs signals, so if you are reading this for
13057 the first time, you may want to skip to the next section now, as
13058 things are going to get a bit complicated.
13059
13060 The function:
13061
13062 <tscreen><verb>
13063 gint gtk_signal_new( const gchar         *name,
13064                      GtkSignalRunType     run_type,
13065                      GtkType              object_type,
13066                      gint                 function_offset,
13067                      GtkSignalMarshaller  marshaller,
13068                      GtkType              return_val,
13069                      guint                nparams,
13070                      ...);
13071 </verb></tscreen>
13072
13073 Creates a new signal. The parameters are:
13074
13075 <itemize>
13076 <item> <tt/name/: The name of the signal.
13077 <item> <tt/run_type/: Whether the default handler runs before or after
13078 user handlers. Usually this will be <tt/GTK_RUN_FIRST/, or <tt/GTK_RUN_LAST/,
13079 although there are other possibilities.
13080 <item> <tt/object_type/: The ID of the object that this signal applies
13081 to. (It will also apply to that objects descendants.)
13082 <item> <tt/function_offset/: The offset within the class structure of
13083 a pointer to the default handler.
13084 <item> <tt/marshaller/: A function that is used to invoke the signal
13085 handler. For signal handlers that have no arguments other than the
13086 object that emitted the signal and user data, we can use the
13087 pre-supplied marshaller function <tt/gtk_signal_default_marshaller/.
13088 <item> <tt/return_val/: The type of the return val.
13089 <item> <tt/nparams/: The number of parameters of the signal handler
13090 (other than the two default ones mentioned above)
13091 <item> <tt/.../: The types of the parameters.
13092 </itemize>
13093
13094 When specifying types, the <tt/GtkType/ enumeration is used:
13095
13096 <tscreen><verb>
13097 typedef enum
13098 {
13099   GTK_TYPE_INVALID,
13100   GTK_TYPE_NONE,
13101   GTK_TYPE_CHAR,
13102   GTK_TYPE_BOOL,
13103   GTK_TYPE_INT,
13104   GTK_TYPE_UINT,
13105   GTK_TYPE_LONG,
13106   GTK_TYPE_ULONG,
13107   GTK_TYPE_FLOAT,
13108   GTK_TYPE_DOUBLE,
13109   GTK_TYPE_STRING,
13110   GTK_TYPE_ENUM,
13111   GTK_TYPE_FLAGS,
13112   GTK_TYPE_BOXED,
13113   GTK_TYPE_FOREIGN,
13114   GTK_TYPE_CALLBACK,
13115   GTK_TYPE_ARGS,
13116
13117   GTK_TYPE_POINTER,
13118
13119   /* it'd be great if the next two could be removed eventually */
13120   GTK_TYPE_SIGNAL,
13121   GTK_TYPE_C_CALLBACK,
13122
13123   GTK_TYPE_OBJECT
13124
13125 } GtkFundamentalType;
13126 </verb></tscreen>
13127
13128 <tt/gtk_signal_new()/ returns a unique integer identifier for the
13129 signal, that we store in the <tt/tictactoe_signals/ array, which we
13130 index using an enumeration. (Conventionally, the enumeration elements
13131 are the signal name, uppercased, but here there would be a conflict
13132 with the <tt/TICTACTOE()/ macro, so we called it <tt/TICTACTOE_SIGNAL/
13133 instead.
13134
13135 After creating our signals, we need to tell GTK to associate our
13136 signals with the Tictactoe class. We do that by calling
13137 <tt/gtk_object_class_add_signals()/. We then set the pointer which
13138 points to the default handler for the "tictactoe" signal to NULL,
13139 indicating that there is no default action.
13140
13141 <!-- ----------------------------------------------------------------- -->
13142 <sect2> The <tt/_init()/ function.
13143 <p>
13144 Each widget class also needs a function to initialize the object
13145 structure. Usually, this function has the fairly limited role of
13146 setting the fields of the structure to default values. For composite
13147 widgets, however, this function also creates the component widgets.
13148
13149 <tscreen><verb>
13150 static void
13151 tictactoe_init (Tictactoe *ttt)
13152 {
13153   GtkWidget *table;
13154   gint i,j;
13155   
13156   table = gtk_table_new (3, 3, TRUE);
13157   gtk_container_add (GTK_CONTAINER(ttt), table);
13158   gtk_widget_show (table);
13159
13160   for (i=0;i<3; i++)
13161     for (j=0;j<3; j++)
13162       {
13163         ttt->buttons[i][j] = gtk_toggle_button_new ();
13164         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
13165                                    i, i+1, j, j+1);
13166         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
13167                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
13168         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
13169         gtk_widget_show (ttt->buttons[i][j]);
13170       }
13171 }
13172 </verb></tscreen>
13173
13174 <!-- ----------------------------------------------------------------- -->
13175 <sect2> And the rest...
13176 <p>
13177 There is one more function that every widget (except for base widget
13178 types like Bin that cannot be instantiated) needs to have - the
13179 function that the user calls to create an object of that type. This is
13180 conventionally called <tt/WIDGETNAME_new()/. In some
13181 widgets, though not for the Tictactoe widgets, this function takes
13182 arguments, and does some setup based on the arguments. The other two
13183 functions are specific to the Tictactoe widget. 
13184
13185 <tt/tictactoe_clear()/ is a public function that resets all the
13186 buttons in the widget to the up position. Note the use of
13187 <tt/gtk_signal_handler_block_by_data()/ to keep our signal handler for
13188 button toggles from being triggered unnecessarily.
13189
13190 <tt/tictactoe_toggle()/ is the signal handler that is invoked when the
13191 user clicks on a button. It checks to see if there are any winning
13192 combinations that involve the toggled button, and if so, emits
13193 the "tictactoe" signal.
13194
13195 <tscreen><verb>  
13196 GtkWidget*
13197 tictactoe_new ()
13198 {
13199   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
13200 }
13201
13202 void           
13203 tictactoe_clear (Tictactoe *ttt)
13204 {
13205   int i,j;
13206
13207   for (i=0;i<3;i++)
13208     for (j=0;j<3;j++)
13209       {
13210         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
13211         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
13212                                      FALSE);
13213         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
13214       }
13215 }
13216
13217 static void
13218 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
13219 {
13220   int i,k;
13221
13222   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
13223                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
13224                              { 0, 1, 2 }, { 0, 1, 2 } };
13225   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
13226                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
13227                              { 0, 1, 2 }, { 2, 1, 0 } };
13228
13229   int success, found;
13230
13231   for (k=0; k<8; k++)
13232     {
13233       success = TRUE;
13234       found = FALSE;
13235
13236       for (i=0;i<3;i++)
13237         {
13238           success = success &amp;&amp; 
13239             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
13240           found = found ||
13241             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
13242         }
13243       
13244       if (success &amp;&amp; found)
13245         {
13246           gtk_signal_emit (GTK_OBJECT (ttt), 
13247                            tictactoe_signals[TICTACTOE_SIGNAL]);
13248           break;
13249         }
13250     }
13251 }
13252 </verb></tscreen>
13253
13254 And finally, an example program using our Tictactoe widget:
13255
13256 <tscreen><verb>
13257 #include <gtk/gtk.h>
13258 #include "tictactoe.h"
13259
13260 /* Invoked when a row, column or diagonal is completed */
13261 void
13262 win (GtkWidget *widget, gpointer data)
13263 {
13264   g_print ("Yay!\n");
13265   tictactoe_clear (TICTACTOE (widget));
13266 }
13267
13268 int 
13269 main (int argc, char *argv[])
13270 {
13271   GtkWidget *window;
13272   GtkWidget *ttt;
13273   
13274   gtk_init (&amp;argc, &amp;argv);
13275
13276   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13277   
13278   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
13279   
13280   gtk_signal_connect (GTK_OBJECT (window), "destroy",
13281                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
13282   
13283   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
13284
13285   /* Create a new Tictactoe widget */
13286   ttt = tictactoe_new ();
13287   gtk_container_add (GTK_CONTAINER (window), ttt);
13288   gtk_widget_show (ttt);
13289
13290   /* And attach to its "tictactoe" signal */
13291   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
13292                       GTK_SIGNAL_FUNC (win), NULL);
13293
13294   gtk_widget_show (window);
13295   
13296   gtk_main ();
13297   
13298   return 0;
13299 }
13300
13301 </verb></tscreen>
13302
13303 <!-- ----------------------------------------------------------------- -->
13304 <sect1> Creating a widget from scratch.
13305
13306 <!-- ----------------------------------------------------------------- -->
13307 <sect2> Introduction
13308 <p>
13309 In this section, we'll learn more about how widgets display themselves
13310 on the screen and interact with events. As an example of this, we'll
13311 create an analog dial widget with a pointer that the user can drag to
13312 set the value.
13313
13314 <!-- ----------------------------------------------------------------- -->
13315 <sect2> Displaying a widget on the screen
13316 <p>
13317 There are several steps that are involved in displaying on the screen.
13318 After the widget is created with a call to <tt/WIDGETNAME_new()/,
13319 several more functions are needed:
13320
13321 <itemize>
13322 <item> <tt/WIDGETNAME_realize()/ is responsible for creating an X
13323 window for the widget if it has one.
13324 <item> <tt/WIDGETNAME_map()/ is invoked after the user calls
13325 <tt/gtk_widget_show()/. It is responsible for making sure the widget
13326 is actually drawn on the screen (<em/mapped/). For a container class,
13327 it must also make calls to <tt/map()/> functions of any child widgets.
13328 <item> <tt/WIDGETNAME_draw()/ is invoked when <tt/gtk_widget_draw()/
13329 is called for the widget or one of its ancestors. It makes the actual
13330 calls to the drawing functions to draw the widget on the screen. For
13331 container widgets, this function must make calls to
13332 <tt/gtk_widget_draw()/ for its child widgets.
13333 <item> <tt/WIDGETNAME_expose()/ is a handler for expose events for the
13334 widget. It makes the necessary calls to the drawing functions to draw
13335 the exposed portion on the screen. For container widgets, this
13336 function must generate expose events for its child widgets which don't
13337 have their own windows. (If they have their own windows, then X will
13338 generate the necessary expose events.)
13339 </itemize>
13340
13341 You might notice that the last two functions are quite similar - each
13342 is responsible for drawing the widget on the screen. In fact many
13343 types of widgets don't really care about the difference between the
13344 two. The default <tt/draw()/ function in the widget class simply
13345 generates a synthetic expose event for the redrawn area. However, some
13346 types of widgets can save work by distinguishing between the two
13347 functions. For instance, if a widget has multiple X windows, then
13348 since expose events identify the exposed window, it can redraw only
13349 the affected window, which is not possible for calls to <tt/draw()/.
13350
13351 Container widgets, even if they don't care about the difference for
13352 themselves, can't simply use the default <tt/draw()/ function because
13353 their child widgets might care about the difference. However,
13354 it would be wasteful to duplicate the drawing code between the two
13355 functions. The convention is that such widgets have a function called
13356 <tt/WIDGETNAME_paint()/ that does the actual work of drawing the
13357 widget, that is then called by the <tt/draw()/ and <tt/expose()/
13358 functions.
13359
13360 In our example approach, since the dial widget is not a container
13361 widget, and only has a single window, we can take the simplest
13362 approach and use the default <tt/draw()/ function and only implement
13363 an <tt/expose()/ function.
13364
13365 <!-- ----------------------------------------------------------------- -->
13366 <sect2> The origins of the Dial Widget
13367 <p>
13368 Just as all land animals are just variants on the first amphibian that
13369 crawled up out of the mud, GTK widgets tend to start off as variants
13370 of some other, previously written widget. Thus, although this section
13371 is entitled "Creating a Widget from Scratch", the Dial widget really
13372 began with the source code for the Range widget. This was picked as a
13373 starting point because it would be nice if our Dial had the same
13374 interface as the Scale widgets which are just specialized descendants
13375 of the Range widget. So, though the source code is presented below in
13376 finished form, it should not be implied that it was written, <em>ab
13377 initio</em> in this fashion. Also, if you aren't yet familiar with
13378 how scale widgets work from the application writer's point of view, it
13379 would be a good idea to look them over before continuing.
13380
13381 <!-- ----------------------------------------------------------------- -->
13382 <sect2> The Basics
13383 <p>
13384 Quite a bit of our widget should look pretty familiar from the
13385 Tictactoe widget. First, we have a header file:
13386
13387 <tscreen><verb>
13388 /* GTK - The GTK+ Toolkit
13389  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
13390  *
13391  * This library is free software; you can redistribute it and/or
13392  * modify it under the terms of the GNU Library General Public
13393  * License as published by the Free Software Foundation; either
13394  * version 2 of the License, or (at your option) any later version.
13395  *
13396  * This library is distributed in the hope that it will be useful,
13397  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13398  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13399  * Library General Public License for more details.
13400  *
13401  * You should have received a copy of the GNU Library General Public
13402  * License along with this library; if not, write to the Free
13403  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
13404  */
13405
13406 #ifndef __GTK_DIAL_H__
13407 #define __GTK_DIAL_H__
13408
13409 #include <gdk/gdk.h>
13410 #include <gtk/gtkadjustment.h>
13411 #include <gtk/gtkwidget.h>
13412
13413
13414 #ifdef __cplusplus
13415 extern "C" {
13416 #endif /* __cplusplus */
13417
13418
13419 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
13420 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
13421 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
13422
13423
13424 typedef struct _GtkDial        GtkDial;
13425 typedef struct _GtkDialClass   GtkDialClass;
13426
13427 struct _GtkDial
13428 {
13429   GtkWidget widget;
13430
13431   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
13432   guint policy : 2;
13433
13434   /* Button currently pressed or 0 if none */
13435   guint8 button;
13436
13437   /* Dimensions of dial components */
13438   gint radius;
13439   gint pointer_width;
13440
13441   /* ID of update timer, or 0 if none */
13442   guint32 timer;
13443
13444   /* Current angle */
13445   gfloat angle;
13446
13447   /* Old values from adjustment stored so we know when something changes */
13448   gfloat old_value;
13449   gfloat old_lower;
13450   gfloat old_upper;
13451
13452   /* The adjustment object that stores the data for this dial */
13453   GtkAdjustment *adjustment;
13454 };
13455
13456 struct _GtkDialClass
13457 {
13458   GtkWidgetClass parent_class;
13459 };
13460
13461
13462 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
13463 guint          gtk_dial_get_type               (void);
13464 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
13465 void           gtk_dial_set_update_policy      (GtkDial      *dial,
13466                                                 GtkUpdateType  policy);
13467
13468 void           gtk_dial_set_adjustment         (GtkDial      *dial,
13469                                                 GtkAdjustment *adjustment);
13470 #ifdef __cplusplus
13471 }
13472 #endif /* __cplusplus */
13473
13474
13475 #endif /* __GTK_DIAL_H__ */
13476 </verb></tscreen>
13477
13478 Since there is quite a bit more going on in this widget than the last
13479 one, we have more fields in the data structure, but otherwise things
13480 are pretty similar.
13481
13482 Next, after including header files and declaring a few constants,
13483 we have some functions to provide information about the widget
13484 and initialize it:
13485
13486 <tscreen><verb>
13487 #include <math.h>
13488 #include <stdio.h>
13489 #include <gtk/gtkmain.h>
13490 #include <gtk/gtksignal.h>
13491
13492 #include "gtkdial.h"
13493
13494 #define SCROLL_DELAY_LENGTH  300
13495 #define DIAL_DEFAULT_SIZE 100
13496
13497 /* Forward declarations */
13498
13499 [ omitted to save space ]
13500
13501 /* Local data */
13502
13503 static GtkWidgetClass *parent_class = NULL;
13504
13505 guint
13506 gtk_dial_get_type ()
13507 {
13508   static guint dial_type = 0;
13509
13510   if (!dial_type)
13511     {
13512       GtkTypeInfo dial_info =
13513       {
13514         "GtkDial",
13515         sizeof (GtkDial),
13516         sizeof (GtkDialClass),
13517         (GtkClassInitFunc) gtk_dial_class_init,
13518         (GtkObjectInitFunc) gtk_dial_init,
13519         (GtkArgSetFunc) NULL,
13520         (GtkArgGetFunc) NULL,
13521       };
13522
13523       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
13524     }
13525
13526   return dial_type;
13527 }
13528
13529 static void
13530 gtk_dial_class_init (GtkDialClass *class)
13531 {
13532   GtkObjectClass *object_class;
13533   GtkWidgetClass *widget_class;
13534
13535   object_class = (GtkObjectClass*) class;
13536   widget_class = (GtkWidgetClass*) class;
13537
13538   parent_class = gtk_type_class (gtk_widget_get_type ());
13539
13540   object_class->destroy = gtk_dial_destroy;
13541
13542   widget_class->realize = gtk_dial_realize;
13543   widget_class->expose_event = gtk_dial_expose;
13544   widget_class->size_request = gtk_dial_size_request;
13545   widget_class->size_allocate = gtk_dial_size_allocate;
13546   widget_class->button_press_event = gtk_dial_button_press;
13547   widget_class->button_release_event = gtk_dial_button_release;
13548   widget_class->motion_notify_event = gtk_dial_motion_notify;
13549 }
13550
13551 static void
13552 gtk_dial_init (GtkDial *dial)
13553 {
13554   dial->button = 0;
13555   dial->policy = GTK_UPDATE_CONTINUOUS;
13556   dial->timer = 0;
13557   dial->radius = 0;
13558   dial->pointer_width = 0;
13559   dial->angle = 0.0;
13560   dial->old_value = 0.0;
13561   dial->old_lower = 0.0;
13562   dial->old_upper = 0.0;
13563   dial->adjustment = NULL;
13564 }
13565
13566 GtkWidget*
13567 gtk_dial_new (GtkAdjustment *adjustment)
13568 {
13569   GtkDial *dial;
13570
13571   dial = gtk_type_new (gtk_dial_get_type ());
13572
13573   if (!adjustment)
13574     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
13575
13576   gtk_dial_set_adjustment (dial, adjustment);
13577
13578   return GTK_WIDGET (dial);
13579 }
13580
13581 static void
13582 gtk_dial_destroy (GtkObject *object)
13583 {
13584   GtkDial *dial;
13585
13586   g_return_if_fail (object != NULL);
13587   g_return_if_fail (GTK_IS_DIAL (object));
13588
13589   dial = GTK_DIAL (object);
13590
13591   if (dial->adjustment)
13592     gtk_object_unref (GTK_OBJECT (dial->adjustment));
13593
13594   if (GTK_OBJECT_CLASS (parent_class)->destroy)
13595     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
13596 }
13597 </verb></tscreen>
13598
13599 Note that this <tt/init()/ function does less than for the Tictactoe
13600 widget, since this is not a composite widget, and the <tt/new()/
13601 function does more, since it now has an argument. Also, note that when
13602 we store a pointer to the Adjustment object, we increment its
13603 reference count, (and correspondingly decrement it when we no longer
13604 use it) so that GTK can keep track of when it can be safely destroyed.
13605
13606 <p>
13607 Also, there are a few function to manipulate the widget's options:
13608
13609 <tscreen><verb>
13610 GtkAdjustment*
13611 gtk_dial_get_adjustment (GtkDial *dial)
13612 {
13613   g_return_val_if_fail (dial != NULL, NULL);
13614   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
13615
13616   return dial->adjustment;
13617 }
13618
13619 void
13620 gtk_dial_set_update_policy (GtkDial      *dial,
13621                              GtkUpdateType  policy)
13622 {
13623   g_return_if_fail (dial != NULL);
13624   g_return_if_fail (GTK_IS_DIAL (dial));
13625
13626   dial->policy = policy;
13627 }
13628
13629 void
13630 gtk_dial_set_adjustment (GtkDial      *dial,
13631                           GtkAdjustment *adjustment)
13632 {
13633   g_return_if_fail (dial != NULL);
13634   g_return_if_fail (GTK_IS_DIAL (dial));
13635
13636   if (dial->adjustment)
13637     {
13638       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
13639       gtk_object_unref (GTK_OBJECT (dial->adjustment));
13640     }
13641
13642   dial->adjustment = adjustment;
13643   gtk_object_ref (GTK_OBJECT (dial->adjustment));
13644
13645   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
13646                       (GtkSignalFunc) gtk_dial_adjustment_changed,
13647                       (gpointer) dial);
13648   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
13649                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
13650                       (gpointer) dial);
13651
13652   dial->old_value = adjustment->value;
13653   dial->old_lower = adjustment->lower;
13654   dial->old_upper = adjustment->upper;
13655
13656   gtk_dial_update (dial);
13657 }
13658 </verb></tscreen>
13659
13660 <sect2> <tt/gtk_dial_realize()/
13661
13662 <p>
13663 Now we come to some new types of functions. First, we have a function
13664 that does the work of creating the X window. Notice that a mask is
13665 passed to the function <tt/gdk_window_new()/ which specifies which fields of
13666 the GdkWindowAttr structure actually have data in them (the remaining
13667 fields will be given default values). Also worth noting is the way the
13668 event mask of the widget is created. We call
13669 <tt/gtk_widget_get_events()/ to retrieve the event mask that the user
13670 has specified for this widget (with <tt/gtk_widget_set_events()/), and
13671 add the events that we are interested in ourselves.
13672
13673 <p>
13674 After creating the window, we set its style and background, and put a
13675 pointer to the widget in the user data field of the GdkWindow. This
13676 last step allows GTK to dispatch events for this window to the correct
13677 widget.
13678
13679 <tscreen><verb>
13680 static void
13681 gtk_dial_realize (GtkWidget *widget)
13682 {
13683   GtkDial *dial;
13684   GdkWindowAttr attributes;
13685   gint attributes_mask;
13686
13687   g_return_if_fail (widget != NULL);
13688   g_return_if_fail (GTK_IS_DIAL (widget));
13689
13690   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
13691   dial = GTK_DIAL (widget);
13692
13693   attributes.x = widget->allocation.x;
13694   attributes.y = widget->allocation.y;
13695   attributes.width = widget->allocation.width;
13696   attributes.height = widget->allocation.height;
13697   attributes.wclass = GDK_INPUT_OUTPUT;
13698   attributes.window_type = GDK_WINDOW_CHILD;
13699   attributes.event_mask = gtk_widget_get_events (widget) | 
13700     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
13701     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
13702     GDK_POINTER_MOTION_HINT_MASK;
13703   attributes.visual = gtk_widget_get_visual (widget);
13704   attributes.colormap = gtk_widget_get_colormap (widget);
13705
13706   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
13707   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
13708
13709   widget->style = gtk_style_attach (widget->style, widget->window);
13710
13711   gdk_window_set_user_data (widget->window, widget);
13712
13713   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
13714 }
13715 </verb></tscreen>
13716
13717 <sect2> Size negotiation
13718
13719 <p>
13720 Before the first time that the window containing a widget is
13721 displayed, and whenever the layout of the window changes, GTK asks
13722 each child widget for its desired size. This request is handled by the
13723 function <tt/gtk_dial_size_request()/. Since our widget isn't a
13724 container widget, and has no real constraints on its size, we just
13725 return a reasonable default value.
13726
13727 <tscreen><verb>
13728 static void 
13729 gtk_dial_size_request (GtkWidget      *widget,
13730                        GtkRequisition *requisition)
13731 {
13732   requisition->width = DIAL_DEFAULT_SIZE;
13733   requisition->height = DIAL_DEFAULT_SIZE;
13734 }
13735 </verb></tscreen>
13736
13737 <p>
13738 After all the widgets have requested an ideal size, the layout of the
13739 window is computed and each child widget is notified of its actual
13740 size. Usually, this will be at least as large as the requested size,
13741 but if for instance the user has resized the window, it may
13742 occasionally be smaller than the requested size. The size notification
13743 is handled by the function <tt/gtk_dial_size_allocate()/. Notice that
13744 as well as computing the sizes of some component pieces for future
13745 use, this routine also does the grunt work of moving the widget's X
13746 window into the new position and size.
13747
13748 <tscreen><verb>
13749 static void
13750 gtk_dial_size_allocate (GtkWidget     *widget,
13751                         GtkAllocation *allocation)
13752 {
13753   GtkDial *dial;
13754
13755   g_return_if_fail (widget != NULL);
13756   g_return_if_fail (GTK_IS_DIAL (widget));
13757   g_return_if_fail (allocation != NULL);
13758
13759   widget->allocation = *allocation;
13760   if (GTK_WIDGET_REALIZED (widget))
13761     {
13762       dial = GTK_DIAL (widget);
13763
13764       gdk_window_move_resize (widget->window,
13765                               allocation->x, allocation->y,
13766                               allocation->width, allocation->height);
13767
13768       dial->radius = MAX(allocation->width,allocation->height) * 0.45;
13769       dial->pointer_width = dial->radius / 5;
13770     }
13771 }
13772 </verb></tscreen>.
13773
13774 <!-- ----------------------------------------------------------------- -->
13775 <sect2> <tt/gtk_dial_expose()/
13776
13777 <p>
13778 As mentioned above, all the drawing of this widget is done in the
13779 handler for expose events. There's not much to remark on here except
13780 the use of the function <tt/gtk_draw_polygon/ to draw the pointer with
13781 three dimensional shading according to the colors stored in the
13782 widget's style.
13783
13784 <tscreen><verb>
13785 static gint
13786 gtk_dial_expose (GtkWidget      *widget,
13787                  GdkEventExpose *event)
13788 {
13789   GtkDial *dial;
13790   GdkPoint points[3];
13791   gdouble s,c;
13792   gdouble theta;
13793   gint xc, yc;
13794   gint tick_length;
13795   gint i;
13796
13797   g_return_val_if_fail (widget != NULL, FALSE);
13798   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13799   g_return_val_if_fail (event != NULL, FALSE);
13800
13801   if (event->count > 0)
13802     return FALSE;
13803   
13804   dial = GTK_DIAL (widget);
13805
13806   gdk_window_clear_area (widget->window,
13807                          0, 0,
13808                          widget->allocation.width,
13809                          widget->allocation.height);
13810
13811   xc = widget->allocation.width/2;
13812   yc = widget->allocation.height/2;
13813
13814   /* Draw ticks */
13815
13816   for (i=0; i<25; i++)
13817     {
13818       theta = (i*M_PI/18. - M_PI/6.);
13819       s = sin(theta);
13820       c = cos(theta);
13821
13822       tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
13823       
13824       gdk_draw_line (widget->window,
13825                      widget->style->fg_gc[widget->state],
13826                      xc + c*(dial->radius - tick_length),
13827                      yc - s*(dial->radius - tick_length),
13828                      xc + c*dial->radius,
13829                      yc - s*dial->radius);
13830     }
13831
13832   /* Draw pointer */
13833
13834   s = sin(dial->angle);
13835   c = cos(dial->angle);
13836
13837
13838   points[0].x = xc + s*dial->pointer_width/2;
13839   points[0].y = yc + c*dial->pointer_width/2;
13840   points[1].x = xc + c*dial->radius;
13841   points[1].y = yc - s*dial->radius;
13842   points[2].x = xc - s*dial->pointer_width/2;
13843   points[2].y = yc - c*dial->pointer_width/2;
13844
13845   gtk_draw_polygon (widget->style,
13846                     widget->window,
13847                     GTK_STATE_NORMAL,
13848                     GTK_SHADOW_OUT,
13849                     points, 3,
13850                     TRUE);
13851   
13852   return FALSE;
13853 }
13854 </verb></tscreen>
13855
13856 <!-- ----------------------------------------------------------------- -->
13857 <sect2> Event handling
13858 <p>
13859 The rest of the widget's code handles various types of events, and
13860 isn't too different from what would be found in many GTK
13861 applications. Two types of events can occur - either the user can
13862 click on the widget with the mouse and drag to move the pointer, or
13863 the value of the Adjustment object can change due to some external
13864 circumstance. 
13865
13866 When the user clicks on the widget, we check to see if the click was
13867 appropriately near the pointer, and if so, store the button that the
13868 user clicked with in the <tt/button/ field of the widget
13869 structure, and grab all mouse events with a call to
13870 <tt/gtk_grab_add()/. Subsequent motion of the mouse causes the
13871 value of the control to be recomputed (by the function
13872 <tt/gtk_dial_update_mouse/). Depending on the policy that has been
13873 set, "value_changed" events are either generated instantly
13874 (<tt/GTK_UPDATE_CONTINUOUS/), after a delay in a timer added with
13875 <tt/gtk_timeout_add()/ (<tt/GTK_UPDATE_DELAYED/), or only when the
13876 button is released (<tt/GTK_UPDATE_DISCONTINUOUS/).
13877
13878 <tscreen><verb>
13879 static gint
13880 gtk_dial_button_press (GtkWidget      *widget,
13881                        GdkEventButton *event)
13882 {
13883   GtkDial *dial;
13884   gint dx, dy;
13885   double s, c;
13886   double d_parallel;
13887   double d_perpendicular;
13888
13889   g_return_val_if_fail (widget != NULL, FALSE);
13890   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13891   g_return_val_if_fail (event != NULL, FALSE);
13892
13893   dial = GTK_DIAL (widget);
13894
13895   /* Determine if button press was within pointer region - we 
13896      do this by computing the parallel and perpendicular distance of
13897      the point where the mouse was pressed from the line passing through
13898      the pointer */
13899   
13900   dx = event->x - widget->allocation.width / 2;
13901   dy = widget->allocation.height / 2 - event->y;
13902   
13903   s = sin(dial->angle);
13904   c = cos(dial->angle);
13905   
13906   d_parallel = s*dy + c*dx;
13907   d_perpendicular = fabs(s*dx - c*dy);
13908   
13909   if (!dial->button &&
13910       (d_perpendicular < dial->pointer_width/2) &&
13911       (d_parallel > - dial->pointer_width))
13912     {
13913       gtk_grab_add (widget);
13914
13915       dial->button = event->button;
13916
13917       gtk_dial_update_mouse (dial, event->x, event->y);
13918     }
13919
13920   return FALSE;
13921 }
13922
13923 static gint
13924 gtk_dial_button_release (GtkWidget      *widget,
13925                           GdkEventButton *event)
13926 {
13927   GtkDial *dial;
13928
13929   g_return_val_if_fail (widget != NULL, FALSE);
13930   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13931   g_return_val_if_fail (event != NULL, FALSE);
13932
13933   dial = GTK_DIAL (widget);
13934
13935   if (dial->button == event->button)
13936     {
13937       gtk_grab_remove (widget);
13938
13939       dial->button = 0;
13940
13941       if (dial->policy == GTK_UPDATE_DELAYED)
13942         gtk_timeout_remove (dial->timer);
13943       
13944       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
13945           (dial->old_value != dial->adjustment->value))
13946         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
13947     }
13948
13949   return FALSE;
13950 }
13951
13952 static gint
13953 gtk_dial_motion_notify (GtkWidget      *widget,
13954                          GdkEventMotion *event)
13955 {
13956   GtkDial *dial;
13957   GdkModifierType mods;
13958   gint x, y, mask;
13959
13960   g_return_val_if_fail (widget != NULL, FALSE);
13961   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
13962   g_return_val_if_fail (event != NULL, FALSE);
13963
13964   dial = GTK_DIAL (widget);
13965
13966   if (dial->button != 0)
13967     {
13968       x = event->x;
13969       y = event->y;
13970
13971       if (event->is_hint || (event->window != widget->window))
13972         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
13973
13974       switch (dial->button)
13975         {
13976         case 1:
13977           mask = GDK_BUTTON1_MASK;
13978           break;
13979         case 2:
13980           mask = GDK_BUTTON2_MASK;
13981           break;
13982         case 3:
13983           mask = GDK_BUTTON3_MASK;
13984           break;
13985         default:
13986           mask = 0;
13987           break;
13988         }
13989
13990       if (mods & mask)
13991         gtk_dial_update_mouse (dial, x,y);
13992     }
13993
13994   return FALSE;
13995 }
13996
13997 static gint
13998 gtk_dial_timer (GtkDial *dial)
13999 {
14000   g_return_val_if_fail (dial != NULL, FALSE);
14001   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
14002
14003   if (dial->policy == GTK_UPDATE_DELAYED)
14004     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
14005
14006   return FALSE;
14007 }
14008
14009 static void
14010 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
14011 {
14012   gint xc, yc;
14013   gfloat old_value;
14014
14015   g_return_if_fail (dial != NULL);
14016   g_return_if_fail (GTK_IS_DIAL (dial));
14017
14018   xc = GTK_WIDGET(dial)->allocation.width / 2;
14019   yc = GTK_WIDGET(dial)->allocation.height / 2;
14020
14021   old_value = dial->adjustment->value;
14022   dial->angle = atan2(yc-y, x-xc);
14023
14024   if (dial->angle < -M_PI/2.)
14025     dial->angle += 2*M_PI;
14026
14027   if (dial->angle < -M_PI/6)
14028     dial->angle = -M_PI/6;
14029
14030   if (dial->angle > 7.*M_PI/6.)
14031     dial->angle = 7.*M_PI/6.;
14032
14033   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
14034     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
14035
14036   if (dial->adjustment->value != old_value)
14037     {
14038       if (dial->policy == GTK_UPDATE_CONTINUOUS)
14039         {
14040           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
14041         }
14042       else
14043         {
14044           gtk_widget_draw (GTK_WIDGET(dial), NULL);
14045
14046           if (dial->policy == GTK_UPDATE_DELAYED)
14047             {
14048               if (dial->timer)
14049                 gtk_timeout_remove (dial->timer);
14050
14051               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
14052                                              (GtkFunction) gtk_dial_timer,
14053                                              (gpointer) dial);
14054             }
14055         }
14056     }
14057 }
14058 </verb></tscreen>
14059
14060 Changes to the Adjustment by external means are communicated to our
14061 widget by the "changed" and "value_changed" signals. The handlers
14062 for these functions call <tt/gtk_dial_update()/ to validate the
14063 arguments, compute the new pointer angle, and redraw the widget (by
14064 calling <tt/gtk_widget_draw()/).
14065
14066 <tscreen><verb>
14067 static void
14068 gtk_dial_update (GtkDial *dial)
14069 {
14070   gfloat new_value;
14071   
14072   g_return_if_fail (dial != NULL);
14073   g_return_if_fail (GTK_IS_DIAL (dial));
14074
14075   new_value = dial->adjustment->value;
14076   
14077   if (new_value < dial->adjustment->lower)
14078     new_value = dial->adjustment->lower;
14079
14080   if (new_value > dial->adjustment->upper)
14081     new_value = dial->adjustment->upper;
14082
14083   if (new_value != dial->adjustment->value)
14084     {
14085       dial->adjustment->value = new_value;
14086       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
14087     }
14088
14089   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
14090     (dial->adjustment->upper - dial->adjustment->lower);
14091
14092   gtk_widget_draw (GTK_WIDGET(dial), NULL);
14093 }
14094
14095 static void
14096 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
14097                               gpointer       data)
14098 {
14099   GtkDial *dial;
14100
14101   g_return_if_fail (adjustment != NULL);
14102   g_return_if_fail (data != NULL);
14103
14104   dial = GTK_DIAL (data);
14105
14106   if ((dial->old_value != adjustment->value) ||
14107       (dial->old_lower != adjustment->lower) ||
14108       (dial->old_upper != adjustment->upper))
14109     {
14110       gtk_dial_update (dial);
14111
14112       dial->old_value = adjustment->value;
14113       dial->old_lower = adjustment->lower;
14114       dial->old_upper = adjustment->upper;
14115     }
14116 }
14117
14118 static void
14119 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
14120                                     gpointer       data)
14121 {
14122   GtkDial *dial;
14123
14124   g_return_if_fail (adjustment != NULL);
14125   g_return_if_fail (data != NULL);
14126
14127   dial = GTK_DIAL (data);
14128
14129   if (dial->old_value != adjustment->value)
14130     {
14131       gtk_dial_update (dial);
14132
14133       dial->old_value = adjustment->value;
14134     }
14135 }
14136 </verb></tscreen>
14137
14138 <!-- ----------------------------------------------------------------- -->
14139 <sect2> Possible Enhancements
14140 <p>
14141 The Dial widget as we've described it so far runs about 670 lines of
14142 code. Although that might sound like a fair bit, we've really
14143 accomplished quite a bit with that much code, especially since much of
14144 that length is headers and boilerplate. However, there are quite a few
14145 more enhancements that could be made to this widget:
14146
14147 <itemize>
14148 <item> If you try this widget out, you'll find that there is some
14149 flashing as the pointer is dragged around. This is because the entire
14150 widget is erased every time the pointer is moved before being
14151 redrawn. Often, the best way to handle this problem is to draw to an
14152 offscreen pixmap, then copy the final results onto the screen in one
14153 step. (The ProgressBar widget draws itself in this fashion.)
14154
14155 <item> The user should be able to use the up and down arrow keys to
14156 increase and decrease the value.
14157
14158 <item> It would be nice if the widget had buttons to increase and
14159 decrease the value in small or large steps. Although it would be
14160 possible to use embedded Button widgets for this, we would also like
14161 the buttons to auto-repeat when held down, as the arrows on a
14162 scrollbar do. Most of the code to implement this type of behavior can
14163 be found in the Range widget.
14164
14165 <item> The Dial widget could be made into a container widget with a
14166 single child widget positioned at the bottom between the buttons
14167 mentioned above. The user could then add their choice of a label or
14168 entry widget to display the current value of the dial.
14169
14170 </itemize>
14171
14172 <!-- ----------------------------------------------------------------- -->
14173 <sect1> Learning More
14174
14175 <p>
14176 Only a small part of the many details involved in creating widgets
14177 could be described above. If you want to write your own widgets, the
14178 best source of examples is the GTK source itself. Ask yourself some
14179 questions about the widget you want to write: IS it a Container
14180 widget? Does it have its own window? Is it a modification of an
14181 existing widget? Then find a similar widget, and start making changes.
14182 Good luck!
14183
14184 <!-- ***************************************************************** -->
14185 <sect>Scribble, A Simple Example Drawing Program
14186 <!-- ***************************************************************** -->
14187
14188 <!-- ----------------------------------------------------------------- -->
14189 <sect1> Overview
14190 <p>
14191 In this section, we will build a simple drawing program. In the
14192 process, we will examine how to handle mouse events, how to draw in a
14193 window, and how to do drawing better by using a backing pixmap. After
14194 creating the simple drawing program, we will extend it by adding
14195 support for XInput devices, such as drawing tablets. GTK provides
14196 support routines which makes getting extended information, such as
14197 pressure and tilt, from such devices quite easy.
14198
14199 <!-- ----------------------------------------------------------------- -->
14200 <sect1> Event Handling
14201 <p>
14202 The GTK signals we have already discussed are for high-level actions,
14203 such as a menu item being selected. However, sometimes it is useful to
14204 learn about lower-level occurrences, such as the mouse being moved, or
14205 a key being pressed. There are also GTK signals corresponding to these
14206 low-level <em>events</em>. The handlers for these signals have an
14207 extra parameter which is a pointer to a structure containing
14208 information about the event. For instance, motion event handlers are
14209 passed a pointer to a GdkEventMotion structure which looks (in part)
14210 like:
14211
14212 <tscreen><verb>
14213 struct _GdkEventMotion
14214 {
14215   GdkEventType type;
14216   GdkWindow *window;
14217   guint32 time;
14218   gdouble x;
14219   gdouble y;
14220   ...
14221   guint state;
14222   ...
14223 };
14224 </verb></tscreen>
14225
14226 <tt/type/ will be set to the event type, in this case
14227 <tt/GDK_MOTION_NOTIFY/, window is the window in which the event
14228 occurred. <tt/x/ and <tt/y/ give the coordinates of the event.
14229 <tt/state/ specifies the modifier state when the event
14230 occurred (that is, it specifies which modifier keys and mouse buttons
14231 were pressed). It is the bitwise OR of some of the following:
14232
14233 <tscreen><verb>
14234 GDK_SHIFT_MASK  
14235 GDK_LOCK_MASK   
14236 GDK_CONTROL_MASK
14237 GDK_MOD1_MASK   
14238 GDK_MOD2_MASK   
14239 GDK_MOD3_MASK   
14240 GDK_MOD4_MASK   
14241 GDK_MOD5_MASK   
14242 GDK_BUTTON1_MASK
14243 GDK_BUTTON2_MASK
14244 GDK_BUTTON3_MASK
14245 GDK_BUTTON4_MASK
14246 GDK_BUTTON5_MASK
14247 </verb></tscreen>
14248
14249 As for other signals, to determine what happens when an event occurs
14250 we call <tt>gtk_signal_connect()</tt>. But we also need let GTK
14251 know which events we want to be notified about. To do this, we call
14252 the function:
14253
14254 <tscreen><verb>
14255 void gtk_widget_set_events (GtkWidget *widget,
14256                             gint      events);
14257 </verb></tscreen>
14258
14259 The second field specifies the events we are interested in. It
14260 is the bitwise OR of constants that specify different types
14261 of events. For future reference the event types are:
14262
14263 <tscreen><verb>
14264 GDK_EXPOSURE_MASK
14265 GDK_POINTER_MOTION_MASK
14266 GDK_POINTER_MOTION_HINT_MASK
14267 GDK_BUTTON_MOTION_MASK     
14268 GDK_BUTTON1_MOTION_MASK    
14269 GDK_BUTTON2_MOTION_MASK    
14270 GDK_BUTTON3_MOTION_MASK    
14271 GDK_BUTTON_PRESS_MASK      
14272 GDK_BUTTON_RELEASE_MASK    
14273 GDK_KEY_PRESS_MASK         
14274 GDK_KEY_RELEASE_MASK       
14275 GDK_ENTER_NOTIFY_MASK      
14276 GDK_LEAVE_NOTIFY_MASK      
14277 GDK_FOCUS_CHANGE_MASK      
14278 GDK_STRUCTURE_MASK         
14279 GDK_PROPERTY_CHANGE_MASK   
14280 GDK_PROXIMITY_IN_MASK      
14281 GDK_PROXIMITY_OUT_MASK     
14282 </verb></tscreen>
14283
14284 There are a few subtle points that have to be observed when calling
14285 <tt/gtk_widget_set_events()/. First, it must be called before the X window
14286 for a GTK widget is created. In practical terms, this means you
14287 should call it immediately after creating the widget. Second, the
14288 widget must have an associated X window. For efficiency, many widget
14289 types do not have their own window, but draw in their parent's window.
14290 These widgets are:
14291
14292 <tscreen><verb>
14293 GtkAlignment
14294 GtkArrow
14295 GtkBin
14296 GtkBox
14297 GtkImage
14298 GtkItem
14299 GtkLabel
14300 GtkPixmap
14301 GtkScrolledWindow
14302 GtkSeparator
14303 GtkTable
14304 GtkAspectFrame
14305 GtkFrame
14306 GtkVBox
14307 GtkHBox
14308 GtkVSeparator
14309 GtkHSeparator
14310 </verb></tscreen>
14311
14312 To capture events for these widgets, you need to use an EventBox
14313 widget. See the section on the <ref id="sec_EventBox"
14314 name="EventBox"> widget for details.
14315
14316 For our drawing program, we want to know when the mouse button is
14317 pressed and when the mouse is moved, so we specify
14318 <tt/GDK_POINTER_MOTION_MASK/ and <tt/GDK_BUTTON_PRESS_MASK/. We also
14319 want to know when we need to redraw our window, so we specify
14320 <tt/GDK_EXPOSURE_MASK/. Although we want to be notified via a
14321 Configure event when our window size changes, we don't have to specify
14322 the corresponding <tt/GDK_STRUCTURE_MASK/ flag, because it is
14323 automatically specified for all windows.
14324
14325 It turns out, however, that there is a problem with just specifying
14326 <tt/GDK_POINTER_MOTION_MASK/. This will cause the server to add a new
14327 motion event to the event queue every time the user moves the mouse.
14328 Imagine that it takes us 0.1 seconds to handle a motion event, but the
14329 X server queues a new motion event every 0.05 seconds. We will soon
14330 get way behind the users drawing. If the user draws for 5 seconds,
14331 it will take us another 5 seconds to catch up after they release 
14332 the mouse button! What we would like is to only get one motion
14333 event for each event we process. The way to do this is to 
14334 specify <tt/GDK_POINTER_MOTION_HINT_MASK/. 
14335
14336 When we specify <tt/GDK_POINTER_MOTION_HINT_MASK/, the server sends
14337 us a motion event the first time the pointer moves after entering
14338 our window, or after a button press or release event. Subsequent 
14339 motion events will be suppressed until we explicitly ask for
14340 the position of the pointer using the function:
14341
14342 <tscreen><verb>
14343 GdkWindow*    gdk_window_get_pointer     (GdkWindow       *window,
14344                                           gint            *x,
14345                                           gint            *y,
14346                                           GdkModifierType *mask);
14347 </verb></tscreen>
14348
14349 (There is another function, <tt>gtk_widget_get_pointer()</tt> which
14350 has a simpler interface, but turns out not to be very useful, since
14351 it only retrieves the position of the mouse, not whether the buttons
14352 are pressed.)
14353
14354 The code to set the events for our window then looks like:
14355
14356 <tscreen><verb>
14357   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
14358                       (GtkSignalFunc) expose_event, NULL);
14359   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
14360                       (GtkSignalFunc) configure_event, NULL);
14361   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
14362                       (GtkSignalFunc) motion_notify_event, NULL);
14363   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
14364                       (GtkSignalFunc) button_press_event, NULL);
14365
14366   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
14367                          | GDK_LEAVE_NOTIFY_MASK
14368                          | GDK_BUTTON_PRESS_MASK
14369                          | GDK_POINTER_MOTION_MASK
14370                          | GDK_POINTER_MOTION_HINT_MASK);
14371 </verb></tscreen>
14372
14373 We'll save the "expose_event" and "configure_event" handlers for
14374 later. The "motion_notify_event" and "button_press_event" handlers
14375 are pretty simple:
14376
14377 <tscreen><verb>
14378 static gint
14379 button_press_event (GtkWidget *widget, GdkEventButton *event)
14380 {
14381   if (event->button == 1 &amp;&amp; pixmap != NULL)
14382       draw_brush (widget, event->x, event->y);
14383
14384   return TRUE;
14385 }
14386
14387 static gint
14388 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
14389 {
14390   int x, y;
14391   GdkModifierType state;
14392
14393   if (event->is_hint)
14394     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
14395   else
14396     {
14397       x = event->x;
14398       y = event->y;
14399       state = event->state;
14400     }
14401     
14402   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
14403     draw_brush (widget, x, y);
14404   
14405   return TRUE;
14406 }
14407 </verb></tscreen>
14408
14409 <!-- ----------------------------------------------------------------- -->
14410 <sect1> The DrawingArea Widget, And Drawing
14411 <p>
14412 We now turn to the process of drawing on the screen. The 
14413 widget we use for this is the DrawingArea widget. A drawing area
14414 widget is essentially an X window and nothing more. It is a blank
14415 canvas in which we can draw whatever we like. A drawing area
14416 is created using the call:
14417
14418 <tscreen><verb>
14419 GtkWidget* gtk_drawing_area_new        (void);
14420 </verb></tscreen>
14421
14422 A default size for the widget can be specified by calling:
14423
14424 <tscreen><verb>
14425 void       gtk_drawing_area_size       (GtkDrawingArea      *darea,
14426                                         gint                 width,
14427                                         gint                 height);
14428 </verb></tscreen>
14429
14430 This default size can be overridden, as is true for all widgets,
14431 by calling <tt>gtk_widget_set_usize()</tt>, and that, in turn, can
14432 be overridden if the user manually resizes the the window containing
14433 the drawing area.
14434
14435 It should be noted that when we create a DrawingArea widget, we are
14436 <em>completely</em> responsible for drawing the contents. If our
14437 window is obscured then uncovered, we get an exposure event and must
14438 redraw what was previously hidden.
14439
14440 Having to remember everything that was drawn on the screen so we
14441 can properly redraw it can, to say the least, be a nuisance. In
14442 addition, it can be visually distracting if portions of the
14443 window are cleared, then redrawn step by step. The solution to
14444 this problem is to use an offscreen <em>backing pixmap</em>.
14445 Instead of drawing directly to the screen, we draw to an image
14446 stored in server memory but not displayed, then when the image
14447 changes or new portions of the image are displayed, we copy the
14448 relevant portions onto the screen.
14449
14450 To create an offscreen pixmap, we call the function:
14451
14452 <tscreen><verb>
14453 GdkPixmap* gdk_pixmap_new               (GdkWindow  *window,
14454                                          gint        width,
14455                                          gint        height,
14456                                          gint        depth);
14457 </verb></tscreen>
14458
14459 The <tt>window</tt> parameter specifies a GDK window that this pixmap
14460 takes some of its properties from. <tt>width</tt> and <tt>height</tt>
14461 specify the size of the pixmap. <tt>depth</tt> specifies the <em>color
14462 depth</em>, that is the number of bits per pixel, for the new window.
14463 If the depth is specified as <tt>-1</tt>, it will match the depth
14464 of <tt>window</tt>.
14465
14466 We create the pixmap in our "configure_event" handler. This event
14467 is generated whenever the window changes size, including when it
14468 is originally created.
14469
14470 <tscreen><verb>
14471 /* Backing pixmap for drawing area */
14472 static GdkPixmap *pixmap = NULL;
14473
14474 /* Create a new backing pixmap of the appropriate size */
14475 static gint
14476 configure_event (GtkWidget *widget, GdkEventConfigure *event)
14477 {
14478   if (pixmap)
14479     gdk_pixmap_unref(pixmap);
14480
14481   pixmap = gdk_pixmap_new(widget->window,
14482                           widget->allocation.width,
14483                           widget->allocation.height,
14484                           -1);
14485   gdk_draw_rectangle (pixmap,
14486                       widget->style->white_gc,
14487                       TRUE,
14488                       0, 0,
14489                       widget->allocation.width,
14490                       widget->allocation.height);
14491
14492   return TRUE;
14493 }
14494 </verb></tscreen>
14495
14496 The call to <tt>gdk_draw_rectangle()</tt> clears the pixmap
14497 initially to white. We'll say more about that in a moment.
14498
14499 Our exposure event handler then simply copies the relevant portion
14500 of the pixmap onto the screen (we determine the area we need
14501 to redraw by using the event->area field of the exposure event):
14502
14503 <tscreen><verb>
14504 /* Redraw the screen from the backing pixmap */
14505 static gint
14506 expose_event (GtkWidget *widget, GdkEventExpose *event)
14507 {
14508   gdk_draw_pixmap(widget->window,
14509                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
14510                   pixmap,
14511                   event->area.x, event->area.y,
14512                   event->area.x, event->area.y,
14513                   event->area.width, event->area.height);
14514
14515   return FALSE;
14516 }
14517 </verb></tscreen>
14518
14519 We've now seen how to keep the screen up to date with our pixmap, but
14520 how do we actually draw interesting stuff on our pixmap?  There are a
14521 large number of calls in GTK's GDK library for drawing on
14522 <em>drawables</em>. A drawable is simply something that can be drawn
14523 upon. It can be a window, a pixmap, or a bitmap (a black and white
14524 image).  We've already seen two such calls above,
14525 <tt>gdk_draw_rectangle()</tt> and <tt>gdk_draw_pixmap()</tt>. The
14526 complete list is:
14527
14528 <tscreen><verb>
14529 gdk_draw_line ()
14530 gdk_draw_rectangle ()
14531 gdk_draw_arc ()
14532 gdk_draw_polygon ()
14533 gdk_draw_string ()
14534 gdk_draw_text ()
14535 gdk_draw_pixmap ()
14536 gdk_draw_bitmap ()
14537 gdk_draw_image ()
14538 gdk_draw_points ()
14539 gdk_draw_segments ()
14540 </verb></tscreen>
14541
14542 See the reference documentation or the header file
14543 <tt>&lt;gdk/gdk.h&gt;</tt> for further details on these functions.
14544 These functions all share the same first two arguments. The first
14545 argument is the drawable to draw upon, the second argument is a
14546 <em>graphics context</em> (GC). 
14547
14548 A graphics context encapsulates information about things such as
14549 foreground and background color and line width. GDK has a full set of
14550 functions for creating and modifying graphics contexts, but to keep
14551 things simple we'll just use predefined graphics contexts. Each widget
14552 has an associated style. (Which can be modified in a gtkrc file, see
14553 the section GTK's rc file.) This, among other things, stores a number
14554 of graphics contexts. Some examples of accessing these graphics
14555 contexts are:
14556
14557 <tscreen><verb>
14558 widget->style->white_gc
14559 widget->style->black_gc
14560 widget->style->fg_gc[GTK_STATE_NORMAL]
14561 widget->style->bg_gc[GTK_WIDGET_STATE(widget)]
14562 </verb></tscreen>
14563
14564 The fields <tt>fg_gc</tt>, <tt>bg_gc</tt>, <tt>dark_gc</tt>, and
14565 <tt>light_gc</tt> are indexed by a parameter of type
14566 <tt>GtkStateType</tt> which can take on the values:
14567
14568 <tscreen><verb>
14569 GTK_STATE_NORMAL,
14570 GTK_STATE_ACTIVE,
14571 GTK_STATE_PRELIGHT,
14572 GTK_STATE_SELECTED,
14573 GTK_STATE_INSENSITIVE
14574 </verb></tscreen>
14575
14576 For instance, for <tt/GTK_STATE_SELECTED/ the default foreground
14577 color is white and the default background color, dark blue.
14578
14579 Our function <tt>draw_brush()</tt>, which does the actual drawing
14580 on the screen, is then:
14581
14582 <tscreen><verb>
14583 /* Draw a rectangle on the screen */
14584 static void
14585 draw_brush (GtkWidget *widget, gdouble x, gdouble y)
14586 {
14587   GdkRectangle update_rect;
14588
14589   update_rect.x = x - 5;
14590   update_rect.y = y - 5;
14591   update_rect.width = 10;
14592   update_rect.height = 10;
14593   gdk_draw_rectangle (pixmap,
14594                       widget->style->black_gc,
14595                       TRUE,
14596                       update_rect.x, update_rect.y,
14597                       update_rect.width, update_rect.height);
14598   gtk_widget_draw (widget, &amp;update_rect);
14599 }
14600 </verb></tscreen>
14601
14602 After we draw the rectangle representing the brush onto the pixmap,
14603 we call the function:
14604
14605 <tscreen><verb>
14606 void       gtk_widget_draw                (GtkWidget           *widget,
14607                                            GdkRectangle        *area);
14608 </verb></tscreen>
14609
14610 which notifies X that the area given by the <tt>area</tt> parameter
14611 needs to be updated. X will eventually generate an expose event
14612 (possibly combining the areas passed in several calls to
14613 <tt>gtk_widget_draw()</tt>) which will cause our expose event handler
14614 to copy the relevant portions to the screen.
14615
14616 We have now covered the entire drawing program except for a few
14617 mundane details like creating the main window.
14618
14619 <!-- ----------------------------------------------------------------- -->
14620 <sect1> Adding XInput support
14621 <p>
14622 It is now possible to buy quite inexpensive input devices such 
14623 as drawing tablets, which allow drawing with a much greater
14624 ease of artistic expression than does a mouse. The simplest way
14625 to use such devices is simply as a replacement for the mouse,
14626 but that misses out many of the advantages of these devices,
14627 such as:
14628
14629 <itemize>
14630 <item> Pressure sensitivity
14631 <item> Tilt reporting
14632 <item> Sub-pixel positioning
14633 <item> Multiple inputs (for example, a stylus with a point and eraser)
14634 </itemize>
14635
14636 For information about the XInput extension, see the <htmlurl
14637 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
14638 name="XInput-HOWTO">.
14639
14640 If we examine the full definition of, for example, the GdkEventMotion
14641 structure, we see that it has fields to support extended device
14642 information.
14643
14644 <tscreen><verb>
14645 struct _GdkEventMotion
14646 {
14647   GdkEventType type;
14648   GdkWindow *window;
14649   guint32 time;
14650   gdouble x;
14651   gdouble y;
14652   gdouble pressure;
14653   gdouble xtilt;
14654   gdouble ytilt;
14655   guint state;
14656   gint16 is_hint;
14657   GdkInputSource source;
14658   guint32 deviceid;
14659 };
14660 </verb></tscreen>
14661
14662 <tt/pressure/ gives the pressure as a floating point number between
14663 0 and 1. <tt/xtilt/ and <tt/ytilt/ can take on values between 
14664 -1 and 1, corresponding to the degree of tilt in each direction.
14665 <tt/source/ and <tt/deviceid/ specify the device for which the
14666 event occurred in two different ways. <tt/source/ gives some simple
14667 information about the type of device. It can take the enumeration
14668 values:
14669
14670 <tscreen><verb>
14671 GDK_SOURCE_MOUSE
14672 GDK_SOURCE_PEN
14673 GDK_SOURCE_ERASER
14674 GDK_SOURCE_CURSOR
14675 </verb></tscreen>
14676
14677 <tt/deviceid/ specifies a unique numeric ID for the device. This can
14678 be used to find out further information about the device using the
14679 <tt/gdk_input_list_devices()/ call (see below). The special value
14680 <tt/GDK_CORE_POINTER/ is used for the core pointer device. (Usually
14681 the mouse.)
14682
14683 <sect2> Enabling extended device information
14684 <p>
14685 To let GTK know about our interest in the extended device information,
14686 we merely have to add a single line to our program:
14687
14688 <tscreen><verb>
14689 gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
14690 </verb></tscreen>
14691
14692 By giving the value <tt/GDK_EXTENSION_EVENTS_CURSOR/ we say that
14693 we are interested in extension events, but only if we don't have
14694 to draw our own cursor. See the section <ref
14695 id="sec_Further_Sophistications" name="Further Sophistications"> below
14696 for more information about drawing the cursor. We could also 
14697 give the values <tt/GDK_EXTENSION_EVENTS_ALL/ if we were willing 
14698 to draw our own cursor, or <tt/GDK_EXTENSION_EVENTS_NONE/ to revert
14699 back to the default condition.
14700
14701 This is not completely the end of the story however. By default,
14702 no extension devices are enabled. We need a mechanism to allow
14703 users to enable and configure their extension devices. GTK provides
14704 the InputDialog widget to automate this process. The following
14705 procedure manages an InputDialog widget. It creates the dialog if
14706 it isn't present, and raises it to the top otherwise.
14707
14708 <tscreen><verb>
14709 void
14710 input_dialog_destroy (GtkWidget *w, gpointer data)
14711 {
14712   *((GtkWidget **)data) = NULL;
14713 }
14714
14715 void
14716 create_input_dialog ()
14717 {
14718   static GtkWidget *inputd = NULL;
14719
14720   if (!inputd)
14721     {
14722       inputd = gtk_input_dialog_new();
14723
14724       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
14725                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
14726       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
14727                                  "clicked",
14728                                  (GtkSignalFunc)gtk_widget_hide,
14729                                  GTK_OBJECT(inputd));
14730       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
14731
14732       gtk_widget_show (inputd);
14733     }
14734   else
14735     {
14736       if (!GTK_WIDGET_MAPPED(inputd))
14737         gtk_widget_show(inputd);
14738       else
14739         gdk_window_raise(inputd->window);
14740     }
14741 }
14742 </verb></tscreen>
14743
14744 (You might want to take note of the way we handle this dialog.  By
14745 connecting to the "destroy" signal, we make sure that we don't keep a
14746 pointer to dialog around after it is destroyed - that could lead to a
14747 segfault.)
14748
14749 The InputDialog has two buttons "Close" and "Save", which by default
14750 have no actions assigned to them. In the above function we make
14751 "Close" hide the dialog, hide the "Save" button, since we don't
14752 implement saving of XInput options in this program.
14753
14754 <sect2> Using extended device information
14755 <p>
14756 Once we've enabled the device, we can just use the extended 
14757 device information in the extra fields of the event structures.
14758 In fact, it is always safe to use this information since these
14759 fields will have reasonable default values even when extended
14760 events are not enabled.
14761
14762 Once change we do have to make is to call
14763 <tt/gdk_input_window_get_pointer()/ instead of
14764 <tt/gdk_window_get_pointer/. This is necessary because
14765 <tt/gdk_window_get_pointer/ doesn't return the extended device
14766 information.
14767
14768 <tscreen><verb>
14769 void gdk_input_window_get_pointer( GdkWindow       *window,
14770                                    guint32         deviceid,
14771                                    gdouble         *x,
14772                                    gdouble         *y,
14773                                    gdouble         *pressure,
14774                                    gdouble         *xtilt,
14775                                    gdouble         *ytilt,
14776                                    GdkModifierType *mask);
14777 </verb></tscreen>
14778
14779 When calling this function, we need to specify the device ID as
14780 well as the window. Usually, we'll get the device ID from the
14781 <tt/deviceid/ field of an event structure. Again, this function
14782 will return reasonable values when extension events are not
14783 enabled. (In this case, <tt/event->deviceid/ will have the value
14784 <tt/GDK_CORE_POINTER/).
14785
14786 So the basic structure of our button-press and motion event handlers
14787 doesn't change much - we just need to add code to deal with the
14788 extended information.
14789
14790 <tscreen><verb>
14791 static gint
14792 button_press_event (GtkWidget *widget, GdkEventButton *event)
14793 {
14794   print_button_press (event->deviceid);
14795   
14796   if (event->button == 1 &amp;&amp; pixmap != NULL)
14797     draw_brush (widget, event->source, event->x, event->y, event->pressure);
14798
14799   return TRUE;
14800 }
14801
14802 static gint
14803 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
14804 {
14805   gdouble x, y;
14806   gdouble pressure;
14807   GdkModifierType state;
14808
14809   if (event->is_hint)
14810     gdk_input_window_get_pointer (event->window, event->deviceid,
14811                                   &amp;x, &amp;y, &amp;pressure, NULL, NULL, &amp;state);
14812   else
14813     {
14814       x = event->x;
14815       y = event->y;
14816       pressure = event->pressure;
14817       state = event->state;
14818     }
14819     
14820   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
14821     draw_brush (widget, event->source, x, y, pressure);
14822   
14823   return TRUE;
14824 }
14825 </verb></tscreen>
14826
14827 We also need to do something with the new information. Our new
14828 <tt/draw_brush()/ function draws with a different color for
14829 each <tt/event->source/ and changes the brush size depending
14830 on the pressure.
14831
14832 <tscreen><verb>
14833 /* Draw a rectangle on the screen, size depending on pressure,
14834    and color on the type of device */
14835 static void
14836 draw_brush (GtkWidget *widget, GdkInputSource source,
14837             gdouble x, gdouble y, gdouble pressure)
14838 {
14839   GdkGC *gc;
14840   GdkRectangle update_rect;
14841
14842   switch (source)
14843     {
14844     case GDK_SOURCE_MOUSE:
14845       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
14846       break;
14847     case GDK_SOURCE_PEN:
14848       gc = widget->style->black_gc;
14849       break;
14850     case GDK_SOURCE_ERASER:
14851       gc = widget->style->white_gc;
14852       break;
14853     default:
14854       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
14855     }
14856
14857   update_rect.x = x - 10 * pressure;
14858   update_rect.y = y - 10 * pressure;
14859   update_rect.width = 20 * pressure;
14860   update_rect.height = 20 * pressure;
14861   gdk_draw_rectangle (pixmap, gc, TRUE,
14862                       update_rect.x, update_rect.y,
14863                       update_rect.width, update_rect.height);
14864   gtk_widget_draw (widget, &amp;update_rect);
14865 }
14866 </verb></tscreen>
14867
14868 <sect2> Finding out more about a device
14869 <p>
14870 As an example of how to find out more about a device, our program
14871 will print the name of the device that generates each button
14872 press. To find out the name of a device, we call the function:
14873
14874 <tscreen><verb>
14875 GList *gdk_input_list_devices               (void);
14876 </verb></tscreen>
14877
14878 which returns a GList (a linked list type from the GLib library)
14879 of GdkDeviceInfo structures. The GdkDeviceInfo structure is defined
14880 as:
14881
14882 <tscreen><verb>
14883 struct _GdkDeviceInfo
14884 {
14885   guint32 deviceid;
14886   gchar *name;
14887   GdkInputSource source;
14888   GdkInputMode mode;
14889   gint has_cursor;
14890   gint num_axes;
14891   GdkAxisUse *axes;
14892   gint num_keys;
14893   GdkDeviceKey *keys;
14894 };
14895 </verb></tscreen>
14896
14897 Most of these fields are configuration information that you can ignore
14898 unless you are implementing XInput configuration saving. The fieldwe
14899 are interested in here is <tt/name/ which is simply the name that X
14900 assigns to the device. The other field that isn't configuration
14901 information is <tt/has_cursor/. If <tt/has_cursor/ is false, then we
14902 we need to draw our own cursor. But since we've specified
14903 <tt/GDK_EXTENSION_EVENTS_CURSOR/, we don't have to worry about this.
14904
14905 Our <tt/print_button_press()/ function simply iterates through
14906 the returned list until it finds a match, then prints out
14907 the name of the device.
14908
14909 <tscreen><verb>
14910 static void
14911 print_button_press (guint32 deviceid)
14912 {
14913   GList *tmp_list;
14914
14915   /* gdk_input_list_devices returns an internal list, so we shouldn't
14916      free it afterwards */
14917   tmp_list = gdk_input_list_devices();
14918
14919   while (tmp_list)
14920     {
14921       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
14922
14923       if (info->deviceid == deviceid)
14924         {
14925           printf("Button press on device '%s'\n", info->name);
14926           return;
14927         }
14928
14929       tmp_list = tmp_list->next;
14930     }
14931 }
14932 </verb></tscreen>
14933
14934 That completes the changes to "XInputize" our program.
14935
14936 <sect2> Further sophistications <label id="sec_Further_Sophistications">
14937 <p>
14938 Although our program now supports XInput quite well, it lacks some
14939 features we would want in a full-featured application. First, the user
14940 probably doesn't want to have to configure their device each time they
14941 run the program, so we should allow them to save the device
14942 configuration. This is done by iterating through the return of
14943 <tt/gdk_input_list_devices()/ and writing out the configuration to a
14944 file.
14945
14946 To restore the state next time the program is run, GDK provides
14947 functions to change device configuration:
14948
14949 <tscreen><verb>
14950 gdk_input_set_extension_events()
14951 gdk_input_set_source()
14952 gdk_input_set_mode()
14953 gdk_input_set_axes()
14954 gdk_input_set_key()
14955 </verb></tscreen>
14956
14957 (The list returned from <tt/gdk_input_list_devices()/ should not be
14958 modified directly.) An example of doing this can be found in the
14959 drawing program gsumi. (Available from <htmlurl
14960 url="http://www.msc.cornell.edu/~otaylor/gsumi/"
14961 name="http://www.msc.cornell.edu/~otaylor/gsumi/">) Eventually, it
14962 would be nice to have a standard way of doing this for all
14963 applications. This probably belongs at a slightly higher level than
14964 GTK, perhaps in the GNOME library.
14965
14966 Another major omission that we have mentioned above is the lack of
14967 cursor drawing. Platforms other than XFree86 currently do not allow
14968 simultaneously using a device as both the core pointer and directly by
14969 an application. See the <url
14970 url="http://www.msc.cornell.edu/~otaylor/xinput/XInput-HOWTO.html"
14971 name="XInput-HOWTO"> for more information about this. This means that
14972 applications that want to support the widest audience need to draw
14973 their own cursor.
14974
14975 An application that draws its own cursor needs to do two things:
14976 determine if the current device needs a cursor drawn or not, and
14977 determine if the current device is in proximity. (If the current
14978 device is a drawing tablet, it's a nice touch to make the cursor 
14979 disappear when the stylus is lifted from the tablet. When the
14980 device is touching the stylus, that is called "in proximity.")
14981 The first is done by searching the device list, as we did
14982 to find out the device name. The second is achieved by selecting
14983 "proximity_out" events. An example of drawing one's own cursor is
14984 found in the "testinput" program found in the GTK distribution.
14985
14986 <!-- ***************************************************************** -->
14987 <sect>Tips For Writing GTK Applications
14988 <!-- ***************************************************************** -->
14989 <p>
14990 This section is simply a gathering of wisdom, general style guidelines
14991 and hints to creating good GTK applications. Currently this section
14992 is very short, but I hope it will get longer in future editions of
14993 this tutorial.
14994
14995 Use GNU autoconf and automake! They are your friends :) Automake
14996 examines C files, determines how they depend on each other, and
14997 generates a Makefile so the files can be compiled in the correct
14998 order. Autoconf permits automatic configuration of software
14999 installation, handling a large number of system quirks to increase
15000 portability. I am planning to make a quick intro on them here.
15001
15002 When writing C code, use only C comments (beginning with "/*" and
15003 ending with "*/"), and don't use C++-style comments ("//").  Although
15004 many C compilers understand C++ comments, others don't, and the ANSI C
15005 standard does not require that C++-style comments be processed as
15006 comments.
15007
15008 <!-- ***************************************************************** -->
15009 <sect>Contributing <label id="sec_Contributing">
15010 <!-- ***************************************************************** -->
15011 <p>
15012 This document, like so much other great software out there, was
15013 created for free by volunteers.  If you are at all knowledgeable about
15014 any aspect of GTK that does not already have documentation, please
15015 consider contributing to this document.
15016
15017 If you do decide to contribute, please mail your text to Tony Gale,
15018 <tt><htmlurl url="mailto:gale@gtk.org"
15019 name="gale@gtk.org"></tt>. Also, be aware that the entirety of this
15020 document is free, and any addition by you provide must also be
15021 free. That is, people may use any portion of your examples in their
15022 programs, and copies of this document may be distributed at will, etc.
15023
15024 Thank you.
15025
15026 <!-- ***************************************************************** -->
15027 <sect>Credits
15028 <!-- ***************************************************************** -->
15029 <p>
15030 We would like to thank the following for their contributions to this text.
15031
15032 <itemize>
15033 <item>Bawer Dagdeviren, <tt><htmlurl url="mailto:chamele0n@geocities.com"
15034 name="chamele0n@geocities.com"></tt> for the menus tutorial.                          
15035
15036 <item>Raph Levien, <tt><htmlurl url="mailto:raph@acm.org"
15037 name="raph@acm.org"></tt>
15038 for hello world ala GTK, widget packing, and general all around wisdom.
15039 He's also generously donated a home for this tutorial.
15040
15041 <item>Peter Mattis, <tt><htmlurl url="mailto:petm@xcf.berkeley.edu"
15042 name="petm@xcf.berkeley.edu"></tt> for the simplest GTK program.. 
15043 and the ability to make it :)
15044
15045 <item>Werner Koch <tt><htmlurl url="mailto:werner.koch@guug.de"
15046 name="werner.koch@guug.de"></tt> for converting the original plain text to
15047 SGML, and the widget class hierarchy.
15048
15049 <item>Mark Crichton <tt><htmlurl
15050 url="mailto:crichton@expert.cc.purdue.edu"
15051 name="crichton@expert.cc.purdue.edu"></tt> for the menu factory code,
15052 and the table packing tutorial.
15053
15054 <item>Owen Taylor <tt><htmlurl url="mailto:owt1@cornell.edu"
15055 name="owt1@cornell.edu"></tt> for the EventBox widget section (and the
15056 patch to the distro).  He's also responsible for the selections code
15057 and tutorial, as well as the sections on writing your own GTK widgets,
15058 and the example application. Thanks a lot Owen for all you help!
15059
15060 <item>Mark VanderBoom <tt><htmlurl url="mailto:mvboom42@calvin.edu"
15061 name="mvboom42@calvin.edu"></tt> for his wonderful work on the
15062 Notebook, Progress Bar, Dialogs, and File selection widgets.  Thanks a
15063 lot Mark!  You've been a great help.
15064
15065 <item>Tim Janik <tt><htmlurl url="mailto:timj@gtk.org"
15066 name="timj@gtk.org"></tt> for his great job on the Lists
15067 Widget. His excellent work on automatically extracting the widget tree
15068 and signal information from GTK. Thanks Tim :)
15069
15070 <item>Rajat Datta <tt><htmlurl url="mailto:rajat@ix.netcom.com"
15071 name="rajat@ix.netcom.com"</tt> for the excellent job on the Pixmap
15072 tutorial.
15073
15074 <item>Michael K. Johnson <tt><htmlurl url="mailto:johnsonm@redhat.com"
15075 name="johnsonm@redhat.com"></tt> for info and code for popup menus.
15076
15077 <item>David Huggins-Daines <tt><htmlurl
15078 url="mailto:bn711@freenet.carleton.ca"
15079 name="bn711@freenet.carleton.ca"></tt> for the Range Widgets and Tree
15080 Widget sections.
15081
15082 <item>Stefan Mars <tt><htmlurl url="mailto:mars@lysator.liu.se"
15083 name="mars@lysator.liu.se"></tt> for the CList section.
15084
15085 <item>David A. Wheeler <tt><htmlurl url="mailto:dwheeler@ida.org"
15086 name="dwheeler@ida.org"></tt> for portions of the text on GLib
15087 and various tutorial fixups and improvements.
15088 The GLib text was in turn based on material developed by Damon Chaplin
15089 <tt><htmlurl url="mailto:DAChaplin@msn.com" name="DAChaplin@msn.com"></tt>
15090
15091 <item>David King for style checking the entire document.
15092 </itemize>
15093
15094 And to all of you who commented on and helped refine this document.
15095
15096 Thanks.
15097
15098 <!-- ***************************************************************** -->
15099 <sect> Tutorial Copyright and Permissions Notice
15100 <!-- ***************************************************************** -->
15101
15102 <p>
15103 The GTK Tutorial is Copyright (C) 1997 Ian Main. 
15104
15105 Copyright (C) 1998-1999 Tony Gale.
15106
15107 Permission is granted to make and distribute verbatim copies of this 
15108 manual provided the copyright notice and this permission notice are 
15109 preserved on all copies.
15110
15111 Permission is granted to copy and distribute modified versions of 
15112 this document under the conditions for verbatim copying, provided that 
15113 this copyright notice is included exactly as in the original,
15114 and that the entire resulting derived work is distributed under 
15115 the terms of a permission notice identical to this one.
15116 <P>Permission is granted to copy and distribute translations of this 
15117 document into another language, under the above conditions for modified 
15118 versions.
15119
15120 If you are intending to incorporate this document into a published 
15121 work, please contact the maintainer, and we will make an effort 
15122 to ensure that you have the most up to date information available.
15123
15124 There is no guarantee that this document lives up to its intended
15125 purpose.  This is simply provided as a free resource.  As such,
15126 the authors and maintainers of the information provided within can
15127 not make any guarantee that the information is even accurate.
15128
15129 <!-- ***************************************************************** -->
15130 <appendix>
15131 <!-- ***************************************************************** -->
15132
15133 <!-- ***************************************************************** -->
15134 <sect> GTK Signals <label id="sec_GTK_Signals">
15135 <!-- ***************************************************************** -->
15136 <p>
15137 As GTK is an object oriented widget set, it has a hierarchy of
15138 inheritance. This inheritance mechanism applies for
15139 signals. Therefore, you should refer to the widget hierarchy tree when
15140 using the signals listed in this section.
15141
15142 <!-- ----------------------------------------------------------------- -->
15143 <sect1>GtkObject
15144 <!-- ----------------------------------------------------------------- -->
15145 <p>
15146 <tscreen><verb>
15147 void GtkObject::destroy (GtkObject *,
15148                          gpointer);
15149 </verb></tscreen>
15150
15151 <!-- ----------------------------------------------------------------- -->
15152 <sect1>GtkWidget
15153 <!-- ----------------------------------------------------------------- -->
15154 <p>
15155 <tscreen><verb>
15156
15157 void GtkWidget::show    (GtkWidget *,
15158                          gpointer);
15159 void GtkWidget::hide    (GtkWidget *,
15160                          gpointer);
15161 void GtkWidget::map     (GtkWidget *,
15162                          gpointer);
15163 void GtkWidget::unmap   (GtkWidget *,
15164                          gpointer);
15165 void GtkWidget::realize (GtkWidget *,
15166                          gpointer);
15167 void GtkWidget::unrealize       (GtkWidget *,
15168                                  gpointer);
15169 void GtkWidget::draw    (GtkWidget *,
15170                          ggpointer,
15171                          gpointer);
15172 void GtkWidget::draw-focus      (GtkWidget *,
15173                                  gpointer);
15174 void GtkWidget::draw-default    (GtkWidget *,
15175                                  gpointer);
15176 void GtkWidget::size-request    (GtkWidget *,
15177                                  ggpointer,
15178                                  gpointer);
15179 void GtkWidget::size-allocate   (GtkWidget *,
15180                                  ggpointer,
15181                                  gpointer);
15182 void GtkWidget::state-changed   (GtkWidget *,
15183                                  GtkStateType,
15184                                  gpointer);
15185 void GtkWidget::parent-set      (GtkWidget *,
15186                                  GtkObject *,
15187                                  gpointer);
15188 void GtkWidget::style-set       (GtkWidget *,
15189                                  GtkStyle *,
15190                                  gpointer);
15191 void GtkWidget::add-accelerator (GtkWidget *,
15192                                  gguint,
15193                                  GtkAccelGroup *,
15194                                  gguint,
15195                                  GdkModifierType,
15196                                  GtkAccelFlags,
15197                                  gpointer);
15198 void GtkWidget::remove-accelerator      (GtkWidget *,
15199                                          GtkAccelGroup *,
15200                                          gguint,
15201                                          GdkModifierType,
15202                                          gpointer);
15203 gboolean GtkWidget::event       (GtkWidget *,
15204                                  GdkEvent *,
15205                                  gpointer);
15206 gboolean GtkWidget::button-press-event  (GtkWidget *,
15207                                          GdkEvent *,
15208                                          gpointer);
15209 gboolean GtkWidget::button-release-event        (GtkWidget *,
15210                                                  GdkEvent *,
15211                                                  gpointer);
15212 gboolean GtkWidget::motion-notify-event (GtkWidget *,
15213                                          GdkEvent *,
15214                                          gpointer);
15215 gboolean GtkWidget::delete-event        (GtkWidget *,
15216                                          GdkEvent *,
15217                                          gpointer);
15218 gboolean GtkWidget::destroy-event       (GtkWidget *,
15219                                          GdkEvent *,
15220                                          gpointer);
15221 gboolean GtkWidget::expose-event        (GtkWidget *,
15222                                          GdkEvent *,
15223                                          gpointer);
15224 gboolean GtkWidget::key-press-event     (GtkWidget *,
15225                                          GdkEvent *,
15226                                          gpointer);
15227 gboolean GtkWidget::key-release-event   (GtkWidget *,
15228                                          GdkEvent *,
15229                                          gpointer);
15230 gboolean GtkWidget::enter-notify-event  (GtkWidget *,
15231                                          GdkEvent *,
15232                                          gpointer);
15233 gboolean GtkWidget::leave-notify-event  (GtkWidget *,
15234                                          GdkEvent *,
15235                                          gpointer);
15236 gboolean GtkWidget::configure-event     (GtkWidget *,
15237                                          GdkEvent *,
15238                                          gpointer);
15239 gboolean GtkWidget::focus-in-event      (GtkWidget *,
15240                                          GdkEvent *,
15241                                          gpointer);
15242 gboolean GtkWidget::focus-out-event     (GtkWidget *,
15243                                          GdkEvent *,
15244                                          gpointer);
15245 gboolean GtkWidget::map-event   (GtkWidget *,
15246                                  GdkEvent *,
15247                                  gpointer);
15248 gboolean GtkWidget::unmap-event (GtkWidget *,
15249                                  GdkEvent *,
15250                                  gpointer);
15251 gboolean GtkWidget::property-notify-event       (GtkWidget *,
15252                                                  GdkEvent *,
15253                                                  gpointer);
15254 gboolean GtkWidget::selection-clear-event       (GtkWidget *,
15255                                                  GdkEvent *,
15256                                                  gpointer);
15257 gboolean GtkWidget::selection-request-event     (GtkWidget *,
15258                                                  GdkEvent *,
15259                                                  gpointer);
15260 gboolean GtkWidget::selection-notify-event      (GtkWidget *,
15261                                                  GdkEvent *,
15262                                                  gpointer);
15263 void GtkWidget::selection-get   (GtkWidget *,
15264                                  GtkSelectionData *,
15265                                  gguint,
15266                                  gpointer);
15267 void GtkWidget::selection-received      (GtkWidget *,
15268                                          GtkSelectionData *,
15269                                          gguint,
15270                                          gpointer);
15271 gboolean GtkWidget::proximity-in-event  (GtkWidget *,
15272                                          GdkEvent *,
15273                                          gpointer);
15274 gboolean GtkWidget::proximity-out-event (GtkWidget *,
15275                                          GdkEvent *,
15276                                          gpointer);
15277 void GtkWidget::drag-begin      (GtkWidget *,
15278                                  GdkDragContext *,
15279                                  gpointer);
15280 void GtkWidget::drag-end        (GtkWidget *,
15281                                  GdkDragContext *,
15282                                  gpointer);
15283 void GtkWidget::drag-data-delete        (GtkWidget *,
15284                                          GdkDragContext *,
15285                                          gpointer);
15286 void GtkWidget::drag-leave      (GtkWidget *,
15287                                  GdkDragContext *,
15288                                  gguint,
15289                                  gpointer);
15290 gboolean GtkWidget::drag-motion (GtkWidget *,
15291                                  GdkDragContext *,
15292                                  ggint,
15293                                  ggint,
15294                                  gguint,
15295                                  gpointer);
15296 gboolean GtkWidget::drag-drop   (GtkWidget *,
15297                                  GdkDragContext *,
15298                                  ggint,
15299                                  ggint,
15300                                  gguint,
15301                                  gpointer);
15302 void GtkWidget::drag-data-get   (GtkWidget *,
15303                                  GdkDragContext *,
15304                                  GtkSelectionData *,
15305                                  gguint,
15306                                  gguint,
15307                                  gpointer);
15308 void GtkWidget::drag-data-received      (GtkWidget *,
15309                                          GdkDragContext *,
15310                                          ggint,
15311                                          ggint,
15312                                          GtkSelectionData *,
15313                                          gguint,
15314                                          gguint,
15315                                          gpointer);
15316 gboolean GtkWidget::client-event        (GtkWidget *,
15317                                          GdkEvent *,
15318                                          gpointer);
15319 gboolean GtkWidget::no-expose-event     (GtkWidget *,
15320                                          GdkEvent *,
15321                                          gpointer);
15322 gboolean GtkWidget::visibility-notify-event     (GtkWidget *,
15323                                                  GdkEvent *,
15324                                                  gpointer);
15325 void GtkWidget::debug-msg       (GtkWidget *,
15326                                  GtkString *,
15327                                  gpointer);
15328 </verb></tscreen>
15329
15330 <!-- ----------------------------------------------------------------- -->
15331 <sect1>GtkData
15332 <!-- ----------------------------------------------------------------- -->
15333 <p>
15334 <tscreen><verb>
15335 void GtkData::disconnect        (GtkData *,
15336                                  gpointer);
15337 </verb></tscreen>
15338
15339 <!-- ----------------------------------------------------------------- -->
15340 <sect1>GtkContainer
15341 <!-- ----------------------------------------------------------------- -->
15342 <p>
15343 <tscreen><verb>
15344 void GtkContainer::add  (GtkContainer *,
15345                          GtkWidget *,
15346                          gpointer);
15347 void GtkContainer::remove       (GtkContainer *,
15348                                  GtkWidget *,
15349                                  gpointer);
15350 void GtkContainer::check-resize (GtkContainer *,
15351                                  gpointer);
15352 GtkDirectionType GtkContainer::focus    (GtkContainer *,
15353                                          GtkDirectionType,
15354                                          gpointer);
15355 void GtkContainer::set-focus-child      (GtkContainer *,
15356                                          GtkWidget *,
15357                                          gpointer);
15358 </verb></tscreen>
15359
15360 <!-- ----------------------------------------------------------------- -->
15361 <sect1>GtkCalendar
15362 <!-- ----------------------------------------------------------------- -->
15363 <p>
15364 <tscreen><verb>
15365 void GtkCalendar::month-changed (GtkCalendar *,
15366                                  gpointer);
15367 void GtkCalendar::day-selected  (GtkCalendar *,
15368                                  gpointer);
15369 void GtkCalendar::day-selected-double-click     (GtkCalendar *,
15370                                                  gpointer);
15371 void GtkCalendar::prev-month    (GtkCalendar *,
15372                                  gpointer);
15373 void GtkCalendar::next-month    (GtkCalendar *,
15374                                  gpointer);
15375 void GtkCalendar::prev-year     (GtkCalendar *,
15376                                  gpointer);
15377 void GtkCalendar::next-year     (GtkCalendar *,
15378                                  gpointer);
15379 </verb></tscreen>
15380
15381 <!-- ----------------------------------------------------------------- -->
15382 <sect1>GtkEditable
15383 <!-- ----------------------------------------------------------------- -->
15384 <p>
15385 <tscreen><verb>
15386 void GtkEditable::changed       (GtkEditable *,
15387                                  gpointer);
15388 void GtkEditable::insert-text   (GtkEditable *,
15389                                  GtkString *,
15390                                  ggint,
15391                                  ggpointer,
15392                                  gpointer);
15393 void GtkEditable::delete-text   (GtkEditable *,
15394                                  ggint,
15395                                  ggint,
15396                                  gpointer);
15397 void GtkEditable::activate      (GtkEditable *,
15398                                  gpointer);
15399 void GtkEditable::set-editable  (GtkEditable *,
15400                                  gboolean,
15401                                  gpointer);
15402 void GtkEditable::move-cursor   (GtkEditable *,
15403                                  ggint,
15404                                  ggint,
15405                                  gpointer);
15406 void GtkEditable::move-word     (GtkEditable *,
15407                                  ggint,
15408                                  gpointer);
15409 void GtkEditable::move-page     (GtkEditable *,
15410                                  ggint,
15411                                  ggint,
15412                                  gpointer);
15413 void GtkEditable::move-to-row   (GtkEditable *,
15414                                  ggint,
15415                                  gpointer);
15416 void GtkEditable::move-to-column        (GtkEditable *,
15417                                          ggint,
15418                                          gpointer);
15419 void GtkEditable::kill-char     (GtkEditable *,
15420                                  ggint,
15421                                  gpointer);
15422 void GtkEditable::kill-word     (GtkEditable *,
15423                                  ggint,
15424                                  gpointer);
15425 void GtkEditable::kill-line     (GtkEditable *,
15426                                  ggint,
15427                                  gpointer);
15428 void GtkEditable::cut-clipboard (GtkEditable *,
15429                                  gpointer);
15430 void GtkEditable::copy-clipboard        (GtkEditable *,
15431                                          gpointer);
15432 void GtkEditable::paste-clipboard       (GtkEditable *,
15433                                          gpointer);
15434 </verb></tscreen>
15435
15436 <!-- ----------------------------------------------------------------- -->
15437 <sect1>GtkTipsQuery
15438 <!-- ----------------------------------------------------------------- -->
15439 <p>
15440 <tscreen><verb>
15441 void GtkTipsQuery::start-query  (GtkTipsQuery *,
15442                                  gpointer);
15443 void GtkTipsQuery::stop-query   (GtkTipsQuery *,
15444                                  gpointer);
15445 void GtkTipsQuery::widget-entered       (GtkTipsQuery *,
15446                                          GtkWidget *,
15447                                          GtkString *,
15448                                          GtkString *,
15449                                          gpointer);
15450 gboolean GtkTipsQuery::widget-selected  (GtkTipsQuery *,
15451                                          GtkWidget *,
15452                                          GtkString *,
15453                                          GtkString *,
15454                                          GdkEvent *,
15455                                          gpointer);
15456 </verb></tscreen>
15457
15458 <!-- ----------------------------------------------------------------- -->
15459 <sect1>GtkCList
15460 <!-- ----------------------------------------------------------------- -->
15461 <p>
15462 <tscreen><verb>
15463 void GtkCList::select-row       (GtkCList *,
15464                                  ggint,
15465                                  ggint,
15466                                  GdkEvent *,
15467                                  gpointer);
15468 void GtkCList::unselect-row     (GtkCList *,
15469                                  ggint,
15470                                  ggint,
15471                                  GdkEvent *,
15472                                  gpointer);
15473 void GtkCList::row-move (GtkCList *,
15474                          ggint,
15475                          ggint,
15476                          gpointer);
15477 void GtkCList::click-column     (GtkCList *,
15478                                  ggint,
15479                                  gpointer);
15480 void GtkCList::resize-column    (GtkCList *,
15481                                  ggint,
15482                                  ggint,
15483                                  gpointer);
15484 void GtkCList::toggle-focus-row (GtkCList *,
15485                                  gpointer);
15486 void GtkCList::select-all       (GtkCList *,
15487                                  gpointer);
15488 void GtkCList::unselect-all     (GtkCList *,
15489                                  gpointer);
15490 void GtkCList::undo-selection   (GtkCList *,
15491                                  gpointer);
15492 void GtkCList::start-selection  (GtkCList *,
15493                                  gpointer);
15494 void GtkCList::end-selection    (GtkCList *,
15495                                  gpointer);
15496 void GtkCList::toggle-add-mode  (GtkCList *,
15497                                  gpointer);
15498 void GtkCList::extend-selection (GtkCList *,
15499                                  GtkScrollType,
15500                                  ggfloat,
15501                                  gboolean,
15502                                  gpointer);
15503 void GtkCList::scroll-vertical  (GtkCList *,
15504                                  GtkScrollType,
15505                                  ggfloat,
15506                                  gpointer);
15507 void GtkCList::scroll-horizontal        (GtkCList *,
15508                                          GtkScrollType,
15509                                          ggfloat,
15510                                          gpointer);
15511 void GtkCList::abort-column-resize      (GtkCList *,
15512                                          gpointer);
15513 </verb></tscreen>
15514
15515 <!-- ----------------------------------------------------------------- -->
15516 <sect1>GtkNotebook
15517 <!-- ----------------------------------------------------------------- -->
15518 <p>
15519 <tscreen><verb>
15520 void GtkNotebook::switch-page   (GtkNotebook *,
15521                                  ggpointer,
15522                                  gguint,
15523                                  gpointer);
15524
15525 </verb></tscreen>
15526
15527 <!-- ----------------------------------------------------------------- -->
15528 <sect1>GtkList
15529 <!-- ----------------------------------------------------------------- -->
15530 <p>
15531 <tscreen><verb>
15532 void GtkList::selection-changed (GtkList *,
15533                                  gpointer);
15534 void GtkList::select-child      (GtkList *,
15535                                  GtkWidget *,
15536                                  gpointer);
15537 void GtkList::unselect-child    (GtkList *,
15538                                  GtkWidget *,
15539                                  gpointer);
15540 </verb></tscreen>
15541
15542 <!-- ----------------------------------------------------------------- -->
15543 <sect1>GtkMenuShell
15544 <!-- ----------------------------------------------------------------- -->
15545 <p>
15546 <tscreen><verb>
15547 void GtkMenuShell::deactivate   (GtkMenuShell *,
15548                                  gpointer);
15549 void GtkMenuShell::selection-done       (GtkMenuShell *,
15550                                          gpointer);
15551 void GtkMenuShell::move-current (GtkMenuShell *,
15552                                  GtkMenuDirectionType,
15553                                  gpointer);
15554 void GtkMenuShell::activate-current     (GtkMenuShell *,
15555                                          gboolean,
15556                                          gpointer);
15557 void GtkMenuShell::cancel       (GtkMenuShell *,
15558                                  gpointer);
15559 </verb></tscreen>
15560
15561 <!-- ----------------------------------------------------------------- -->
15562 <sect1>GtkToolbar
15563 <!-- ----------------------------------------------------------------- -->
15564 <p>
15565 <tscreen><verb>
15566 void GtkToolbar::orientation-changed    (GtkToolbar *,
15567                                          ggint,
15568                                          gpointer);
15569 void GtkToolbar::style-changed  (GtkToolbar *,
15570                                  ggint,
15571                                  gpointer);
15572 </verb></tscreen>
15573
15574 <!-- ----------------------------------------------------------------- -->
15575 <sect1>GtkTree
15576 <!-- ----------------------------------------------------------------- -->
15577 <p>
15578 <tscreen><verb>
15579 void GtkTree::selection-changed (GtkTree *,
15580                                  gpointer);
15581 void GtkTree::select-child      (GtkTree *,
15582                                  GtkWidget *,
15583                                  gpointer);
15584 void GtkTree::unselect-child    (GtkTree *,
15585                                  GtkWidget *,
15586                                  gpointer);
15587 </verb></tscreen>
15588
15589 <!-- ----------------------------------------------------------------- -->
15590 <sect1>GtkButton
15591 <!-- ----------------------------------------------------------------- -->
15592 <p>
15593 <tscreen><verb>
15594 void GtkButton::pressed (GtkButton *,
15595                          gpointer);
15596 void GtkButton::released        (GtkButton *,
15597                                  gpointer);
15598 void GtkButton::clicked (GtkButton *,
15599                          gpointer);
15600 void GtkButton::enter   (GtkButton *,
15601                          gpointer);
15602 void GtkButton::leave   (GtkButton *,
15603                          gpointer);
15604 </verb></tscreen>
15605
15606 <!-- ----------------------------------------------------------------- -->
15607 <sect1>GtkItem
15608 <!-- ----------------------------------------------------------------- -->
15609 <p>
15610 <tscreen><verb>
15611 void GtkItem::select    (GtkItem *,
15612                          gpointer);
15613 void GtkItem::deselect  (GtkItem *,
15614                          gpointer);
15615 void GtkItem::toggle    (GtkItem *,
15616                          gpointer);
15617 </verb></tscreen>
15618
15619 <!-- ----------------------------------------------------------------- -->
15620 <sect1>GtkWindow
15621 <!-- ----------------------------------------------------------------- -->
15622 <p>
15623 <tscreen><verb>
15624 void GtkWindow::set-focus       (GtkWindow *,
15625                                  ggpointer,
15626                                  gpointer);
15627 </verb></tscreen>
15628
15629 <!-- ----------------------------------------------------------------- -->
15630 <sect1>GtkHandleBox
15631 <!-- ----------------------------------------------------------------- -->
15632 <p>
15633 <tscreen><verb>
15634 void GtkHandleBox::child-attached       (GtkHandleBox *,
15635                                          GtkWidget *,
15636                                          gpointer);
15637 void GtkHandleBox::child-detached       (GtkHandleBox *,
15638                                          GtkWidget *,
15639                                          gpointer);
15640 </verb></tscreen>
15641
15642 <!-- ----------------------------------------------------------------- -->
15643 <sect1>GtkToggleButton
15644 <!-- ----------------------------------------------------------------- -->
15645 <p>
15646 <tscreen><verb>
15647 void GtkToggleButton::toggled   (GtkToggleButton *,
15648                                  gpointer);
15649
15650 </verb></tscreen>
15651
15652 <!-- ----------------------------------------------------------------- -->
15653 <sect1>GtkMenuItem
15654 <!-- ----------------------------------------------------------------- -->
15655 <p>
15656 <tscreen><verb>
15657 void GtkMenuItem::activate      (GtkMenuItem *,
15658                                  gpointer);
15659 void GtkMenuItem::activate-item (GtkMenuItem *,
15660                                  gpointer);
15661 </verb></tscreen>
15662
15663 <!-- ----------------------------------------------------------------- -->
15664 <sect1>GtkListItem
15665 <!-- ----------------------------------------------------------------- -->
15666 <p>
15667 <tscreen><verb>
15668 void GtkListItem::toggle-focus-row      (GtkListItem *,
15669                                          gpointer);
15670 void GtkListItem::select-all    (GtkListItem *,
15671                                  gpointer);
15672 void GtkListItem::unselect-all  (GtkListItem *,
15673                                  gpointer);
15674 void GtkListItem::undo-selection        (GtkListItem *,
15675                                          gpointer);
15676 void GtkListItem::start-selection       (GtkListItem *,
15677                                          gpointer);
15678 void GtkListItem::end-selection (GtkListItem *,
15679                                  gpointer);
15680 void GtkListItem::toggle-add-mode       (GtkListItem *,
15681                                          gpointer);
15682 void GtkListItem::extend-selection      (GtkListItem *,
15683                                          GtkEnum,
15684                                          ggfloat,
15685                                          gboolean,
15686                                          gpointer);
15687 void GtkListItem::scroll-vertical       (GtkListItem *,
15688                                          GtkEnum,
15689                                          ggfloat,
15690                                          gpointer);
15691 void GtkListItem::scroll-horizontal     (GtkListItem *,
15692                                          GtkEnum,
15693                                          ggfloat,
15694                                          gpointer);
15695 </verb></tscreen>
15696
15697 <!-- ----------------------------------------------------------------- -->
15698 <sect1>GtkTreeItem
15699 <!-- ----------------------------------------------------------------- -->
15700 <p>
15701 <tscreen><verb>
15702 void GtkTreeItem::collapse      (GtkTreeItem *,
15703                                  gpointer);
15704 void GtkTreeItem::expand        (GtkTreeItem *,
15705                                  gpointer);
15706 </verb></tscreen>
15707
15708 <!-- ----------------------------------------------------------------- -->
15709 <sect1>GtkCheckMenuItem
15710 <!-- ----------------------------------------------------------------- -->
15711 <p>
15712 <tscreen><verb>
15713 void GtkCheckMenuItem::toggled  (GtkCheckMenuItem *,
15714                                  gpointer);
15715 </verb></tscreen>
15716
15717 <!-- ----------------------------------------------------------------- -->
15718 <sect1>GtkInputDialog
15719 <!-- ----------------------------------------------------------------- -->
15720 <p>
15721 <tscreen><verb>
15722 void GtkInputDialog::enable-device      (GtkInputDialog *,
15723                                          ggint,
15724                                          gpointer);
15725 void GtkInputDialog::disable-device     (GtkInputDialog *,
15726                                          ggint,
15727                                          gpointer);
15728 </verb></tscreen>
15729
15730 <!-- ----------------------------------------------------------------- -->
15731 <sect1>GtkColorSelection
15732 <!-- ----------------------------------------------------------------- -->
15733 <p>
15734 <tscreen><verb>
15735 void GtkColorSelection::color-changed   (GtkColorSelection *,
15736                                          gpointer);
15737 </verb></tscreen>
15738
15739 <!-- ----------------------------------------------------------------- -->
15740 <sect1>GtkStatusBar
15741 <!-- ----------------------------------------------------------------- -->
15742 <p>
15743 <tscreen><verb>
15744 void GtkStatusbar::text-pushed  (GtkStatusbar *,
15745                                  gguint,
15746                                  GtkString *,
15747                                  gpointer);
15748 void GtkStatusbar::text-popped  (GtkStatusbar *,
15749                                  gguint,
15750                                  GtkString *,
15751                                  gpointer);
15752 </verb></tscreen>
15753
15754 <!-- ----------------------------------------------------------------- -->
15755 <sect1>GtkCTree
15756 <!-- ----------------------------------------------------------------- -->
15757 <p>
15758 <tscreen><verb>
15759 void GtkCTree::tree-select-row  (GtkCTree *,
15760                                  GtkCTreeNode *,
15761                                  ggint,
15762                                  gpointer);
15763 void GtkCTree::tree-unselect-row        (GtkCTree *,
15764                                          GtkCTreeNode *,
15765                                          ggint,
15766                                          gpointer);
15767 void GtkCTree::tree-expand      (GtkCTree *,
15768                                  GtkCTreeNode *,
15769                                  gpointer);
15770 void GtkCTree::tree-collapse    (GtkCTree *,
15771                                  ggpointer,
15772                                  gpointer);
15773 void GtkCTree::tree-move        (GtkCTree *,
15774                                  GtkCTreeNode *,
15775                                  GtkCTreeNode *,
15776                                  GtkCTreeNode *,
15777                                  gpointer);
15778 void GtkCTree::change-focus-row-expansion       (GtkCTree *,
15779                                                  GtkCTreeExpansionType,
15780                                                  gpointer);
15781 </verb></tscreen>
15782
15783 <!-- ----------------------------------------------------------------- -->
15784 <sect1>GtkCurve
15785 <!-- ----------------------------------------------------------------- -->
15786 <p>
15787 <tscreen><verb>
15788 void GtkCurve::curve-type-changed       (GtkCurve *,
15789                                          gpointer);
15790 </verb></tscreen>
15791
15792 <!-- ----------------------------------------------------------------- -->
15793 <sect1>GtkAdjustment
15794 <!-- ----------------------------------------------------------------- -->
15795 <p>
15796 <tscreen><verb>
15797 void GtkAdjustment::changed     (GtkAdjustment *,
15798                                  gpointer);
15799 void GtkAdjustment::value-changed       (GtkAdjustment *,
15800                                          gpointer);
15801 </verb></tscreen>
15802
15803 <!-- ***************************************************************** -->
15804 <sect> GDK Event Types<label id="sec_GDK_Event_Types">
15805 <!-- ***************************************************************** -->
15806 <p>
15807 The following data types are passed into event handlers by GTK+. For
15808 each data type listed, the signals that use this data type are listed.
15809
15810 <itemize>
15811 <item>  GdkEvent
15812           <itemize>
15813           <item>drag_end_event
15814           </itemize>
15815
15816 <item>  GdkEventType
15817
15818 <item>  GdkEventAny
15819           <itemize>
15820           <item>delete_event
15821           <item>destroy_event
15822           <item>map_event
15823           <item>unmap_event
15824           <item>no_expose_event
15825           </itemize>
15826
15827 <item>  GdkEventExpose
15828           <itemize>
15829           <item>expose_event
15830           </itemize>
15831
15832 <item>  GdkEventNoExpose
15833
15834 <item>  GdkEventVisibility
15835
15836 <item>  GdkEventMotion
15837           <itemize>
15838           <item>motion_notify_event
15839           </itemize>
15840
15841 <item>  GdkEventButton
15842           <itemize>
15843           <item>button_press_event
15844           <item>button_release_event
15845           </itemize>
15846
15847 <item>  GdkEventKey
15848           <itemize>
15849           <item>key_press_event
15850           <item>key_release_event
15851           </itemize>
15852
15853 <item>  GdkEventCrossing
15854           <itemize>
15855           <item>enter_notify_event
15856           <item>leave_notify_event
15857           </itemize>
15858
15859 <item>  GdkEventFocus
15860           <itemize>
15861           <item>focus_in_event
15862           <item>focus_out_event
15863           </itemize>
15864
15865 <item>  GdkEventConfigure
15866           <itemize>
15867           <item>configure_event
15868           </itemize>
15869
15870 <item>  GdkEventProperty
15871           <itemize>
15872           <item>property_notify_event
15873           </itemize>
15874
15875 <item>  GdkEventSelection
15876           <itemize>
15877           <item>selection_clear_event
15878           <item>selection_request_event
15879           <item>selection_notify_event
15880           </itemize>
15881
15882 <item>  GdkEventProximity
15883           <itemize>
15884           <item>proximity_in_event
15885           <item>proximity_out_event
15886           </itemize>
15887
15888 <item>  GdkEventDragBegin
15889           <itemize>
15890           <item>drag_begin_event
15891           </itemize>
15892
15893 <item>  GdkEventDragRequest
15894           <itemize>
15895           <item>drag_request_event
15896           </itemize>
15897
15898 <item>  GdkEventDropEnter
15899           <itemize>
15900           <item>drop_enter_event
15901           </itemize>
15902
15903 <item>  GdkEventDropLeave
15904           <itemize>
15905           <item>drop_leave_event
15906           </itemize>
15907
15908 <item>  GdkEventDropDataAvailable
15909           <itemize>
15910           <item>drop_data_available_event
15911           </itemize>
15912
15913 <item>  GdkEventClient
15914           <itemize>
15915           <item>client_event
15916           </itemize>
15917
15918 <item>  GdkEventOther
15919           <itemize>
15920           <item>other_event
15921           </itemize>
15922 </itemize>
15923
15924 The data type <tt/GdkEventType/ is a special data type that is used by
15925 all the other data types as an indicator of the data type being passed
15926 to the signal handler. As you will see below, each of the event data
15927 structures has a member of this type. It is defined as an enumeration
15928 type as follows:
15929
15930 <tscreen><verb>
15931 typedef enum
15932 {
15933   GDK_NOTHING           = -1,
15934   GDK_DELETE            = 0,
15935   GDK_DESTROY           = 1,
15936   GDK_EXPOSE            = 2,
15937   GDK_MOTION_NOTIFY     = 3,
15938   GDK_BUTTON_PRESS      = 4,
15939   GDK_2BUTTON_PRESS     = 5,
15940   GDK_3BUTTON_PRESS     = 6,
15941   GDK_BUTTON_RELEASE    = 7,
15942   GDK_KEY_PRESS         = 8,
15943   GDK_KEY_RELEASE       = 9,
15944   GDK_ENTER_NOTIFY      = 10,
15945   GDK_LEAVE_NOTIFY      = 11,
15946   GDK_FOCUS_CHANGE      = 12,
15947   GDK_CONFIGURE         = 13,
15948   GDK_MAP               = 14,
15949   GDK_UNMAP             = 15,
15950   GDK_PROPERTY_NOTIFY   = 16,
15951   GDK_SELECTION_CLEAR   = 17,
15952   GDK_SELECTION_REQUEST = 18,
15953   GDK_SELECTION_NOTIFY  = 19,
15954   GDK_PROXIMITY_IN      = 20,
15955   GDK_PROXIMITY_OUT     = 21,
15956   GDK_DRAG_BEGIN        = 22,
15957   GDK_DRAG_REQUEST      = 23,
15958   GDK_DROP_ENTER        = 24,
15959   GDK_DROP_LEAVE        = 25,
15960   GDK_DROP_DATA_AVAIL   = 26,
15961   GDK_CLIENT_EVENT      = 27,
15962   GDK_VISIBILITY_NOTIFY = 28,
15963   GDK_NO_EXPOSE         = 29,
15964   GDK_OTHER_EVENT       = 9999  /* Deprecated, use filters instead */
15965 } GdkEventType;
15966 </verb></tscreen>
15967
15968 The other event type that is different from the others is
15969 <tt/GdkEvent/ itself. This is a union of all the other
15970 data types, which allows it to be cast to a specific
15971 event data type within a signal handler.
15972
15973 <!-- Just a big list for now, needs expanding upon - TRG -->
15974 So, the event data types are defined as follows:
15975
15976 <tscreen><verb>
15977 struct _GdkEventAny
15978 {
15979   GdkEventType type;
15980   GdkWindow *window;
15981   gint8 send_event;
15982 };
15983
15984 struct _GdkEventExpose
15985 {
15986   GdkEventType type;
15987   GdkWindow *window;
15988   gint8 send_event;
15989   GdkRectangle area;
15990   gint count; /* If non-zero, how many more events follow. */
15991 };
15992
15993 struct _GdkEventNoExpose
15994 {
15995   GdkEventType type;
15996   GdkWindow *window;
15997   gint8 send_event;
15998   /* XXX: does anyone need the X major_code or minor_code fields? */
15999 };
16000
16001 struct _GdkEventVisibility
16002 {
16003   GdkEventType type;
16004   GdkWindow *window;
16005   gint8 send_event;
16006   GdkVisibilityState state;
16007 };
16008
16009 struct _GdkEventMotion
16010 {
16011   GdkEventType type;
16012   GdkWindow *window;
16013   gint8 send_event;
16014   guint32 time;
16015   gdouble x;
16016   gdouble y;
16017   gdouble pressure;
16018   gdouble xtilt;
16019   gdouble ytilt;
16020   guint state;
16021   gint16 is_hint;
16022   GdkInputSource source;
16023   guint32 deviceid;
16024   gdouble x_root, y_root;
16025 };
16026
16027 struct _GdkEventButton
16028 {
16029   GdkEventType type;
16030   GdkWindow *window;
16031   gint8 send_event;
16032   guint32 time;
16033   gdouble x;
16034   gdouble y;
16035   gdouble pressure;
16036   gdouble xtilt;
16037   gdouble ytilt;
16038   guint state;
16039   guint button;
16040   GdkInputSource source;
16041   guint32 deviceid;
16042   gdouble x_root, y_root;
16043 };
16044
16045 struct _GdkEventKey
16046 {
16047   GdkEventType type;
16048   GdkWindow *window;
16049   gint8 send_event;
16050   guint32 time;
16051   guint state;
16052   guint keyval;
16053   gint length;
16054   gchar *string;
16055 };
16056
16057 struct _GdkEventCrossing
16058 {
16059   GdkEventType type;
16060   GdkWindow *window;
16061   gint8 send_event;
16062   GdkWindow *subwindow;
16063   GdkNotifyType detail;
16064 };
16065
16066 struct _GdkEventFocus
16067 {
16068   GdkEventType type;
16069   GdkWindow *window;
16070   gint8 send_event;
16071   gint16 in;
16072 };
16073
16074 struct _GdkEventConfigure
16075 {
16076   GdkEventType type;
16077   GdkWindow *window;
16078   gint8 send_event;
16079   gint16 x, y;
16080   gint16 width;
16081   gint16 height;
16082 };
16083
16084 struct _GdkEventProperty
16085 {
16086   GdkEventType type;
16087   GdkWindow *window;
16088   gint8 send_event;
16089   GdkAtom atom;
16090   guint32 time;
16091   guint state;
16092 };
16093
16094 struct _GdkEventSelection
16095 {
16096   GdkEventType type;
16097   GdkWindow *window;
16098   gint8 send_event;
16099   GdkAtom selection;
16100   GdkAtom target;
16101   GdkAtom property;
16102   guint32 requestor;
16103   guint32 time;
16104 };
16105
16106 /* This event type will be used pretty rarely. It only is important
16107    for XInput aware programs that are drawing their own cursor */
16108
16109 struct _GdkEventProximity
16110 {
16111   GdkEventType type;
16112   GdkWindow *window;
16113   gint8 send_event;
16114   guint32 time;
16115   GdkInputSource source;
16116   guint32 deviceid;
16117 };
16118
16119 struct _GdkEventDragRequest
16120 {
16121   GdkEventType type;
16122   GdkWindow *window;
16123   gint8 send_event;
16124   guint32 requestor;
16125   union {
16126     struct {
16127       guint protocol_version:4;
16128       guint sendreply:1;
16129       guint willaccept:1;
16130       guint delete_data:1; /* Do *not* delete if link is sent, only
16131                               if data is sent */
16132       guint senddata:1;
16133       guint reserved:22;
16134     } flags;
16135     glong allflags;
16136   } u;
16137   guint8 isdrop; /* This gdk event can be generated by a couple of
16138                     X events - this lets the app know whether the
16139                     drop really occurred or we just set the data */
16140
16141   GdkPoint drop_coords;
16142   gchar *data_type;
16143   guint32 timestamp;
16144 };
16145
16146 struct _GdkEventDragBegin
16147 {
16148   GdkEventType type;
16149   GdkWindow *window;
16150   gint8 send_event;
16151   union {
16152     struct {
16153       guint protocol_version:4;
16154       guint reserved:28;
16155     } flags;
16156     glong allflags;
16157   } u;
16158 };
16159
16160 struct _GdkEventDropEnter
16161 {
16162   GdkEventType type;
16163   GdkWindow *window;
16164   gint8 send_event;
16165   guint32 requestor;
16166   union {
16167     struct {
16168       guint protocol_version:4;
16169       guint sendreply:1;
16170       guint extended_typelist:1;
16171       guint reserved:26;
16172     } flags;
16173     glong allflags;
16174   } u;
16175 };
16176
16177 struct _GdkEventDropLeave
16178 {
16179   GdkEventType type;
16180   GdkWindow *window;
16181   gint8 send_event;
16182   guint32 requestor;
16183   union {
16184     struct {
16185       guint protocol_version:4;
16186       guint reserved:28;
16187     } flags;
16188     glong allflags;
16189   } u;
16190 };
16191
16192 struct _GdkEventDropDataAvailable
16193 {
16194   GdkEventType type;
16195   GdkWindow *window;
16196   gint8 send_event;
16197   guint32 requestor;
16198   union {
16199     struct {
16200       guint protocol_version:4;
16201       guint isdrop:1;
16202       guint reserved:25;
16203     } flags;
16204     glong allflags;
16205   } u;
16206   gchar *data_type; /* MIME type */
16207   gulong data_numbytes;
16208   gpointer data;
16209   guint32 timestamp;
16210   GdkPoint coords;
16211 };
16212
16213 struct _GdkEventClient
16214 {
16215   GdkEventType type;
16216   GdkWindow *window;
16217   gint8 send_event;
16218   GdkAtom message_type;
16219   gushort data_format;
16220   union {
16221     char b[20];
16222     short s[10];
16223     long l[5];
16224   } data;
16225 };
16226
16227 struct _GdkEventOther
16228 {
16229   GdkEventType type;
16230   GdkWindow *window;
16231   gint8 send_event;
16232   GdkXEvent *xevent;
16233 };
16234 </verb></tscreen>
16235
16236 <!-- ***************************************************************** -->
16237 <sect> Code Examples
16238 <!-- ***************************************************************** -->
16239 <p>
16240 Below are the code examples that are used in the above text
16241 which are not included in complete form elsewhere.
16242
16243 <!-- ----------------------------------------------------------------- -->
16244 <sect1>Tictactoe
16245 <!-- ----------------------------------------------------------------- -->
16246 <sect2>tictactoe.h
16247 <p>
16248 <tscreen><verb>
16249 /* example-start tictactoe tictactoe.h */
16250
16251 /* GTK - The GTK+ Toolkit
16252  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16253  *
16254  * This library is free software; you can redistribute it and/or
16255  * modify it under the terms of the GNU Library General Public
16256  * License as published by the Free Software Foundation; either
16257  * version 2 of the License, or (at your option) any later version.
16258  *
16259  * This library is distributed in the hope that it will be useful,
16260  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16261  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16262  * Library General Public License for more details.
16263  *
16264  * You should have received a copy of the GNU Library General Public
16265  * License along with this library; if not, write to the
16266  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16267  * Boston, MA 02111-1307, USA.
16268  */
16269 #ifndef __TICTACTOE_H__
16270 #define __TICTACTOE_H__
16271
16272
16273 #include <gdk/gdk.h>
16274 #include <gtk/gtkvbox.h>
16275
16276
16277 #ifdef __cplusplus
16278 extern "C" {
16279 #endif /* __cplusplus */
16280
16281 #define TICTACTOE(obj)          GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
16282 #define TICTACTOE_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
16283 #define IS_TICTACTOE(obj)       GTK_CHECK_TYPE (obj, tictactoe_get_type ())
16284
16285
16286 typedef struct _Tictactoe       Tictactoe;
16287 typedef struct _TictactoeClass  TictactoeClass;
16288
16289 struct _Tictactoe
16290 {
16291   GtkVBox vbox;
16292   
16293   GtkWidget *buttons[3][3];
16294 };
16295
16296 struct _TictactoeClass
16297 {
16298   GtkVBoxClass parent_class;
16299
16300   void (* tictactoe) (Tictactoe *ttt);
16301 };
16302
16303 guint          tictactoe_get_type        (void);
16304 GtkWidget*     tictactoe_new             (void);
16305 void           tictactoe_clear           (Tictactoe *ttt);
16306
16307 #ifdef __cplusplus
16308 }
16309 #endif /* __cplusplus */
16310
16311 #endif /* __TICTACTOE_H__ */
16312
16313 /* example-end */
16314 </verb></tscreen>
16315
16316 <!-- ----------------------------------------------------------------- -->
16317 <sect2>tictactoe.c
16318 <p>
16319 <tscreen><verb>
16320 /* example-start tictactoe tictactoe.c */
16321
16322 /* GTK - The GTK+ Toolkit
16323  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16324  *
16325  * This library is free software; you can redistribute it and/or
16326  * modify it under the terms of the GNU Library General Public
16327  * License as published by the Free Software Foundation; either
16328  * version 2 of the License, or (at your option) any later version.
16329  *
16330  * This library is distributed in the hope that it will be useful,
16331  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16332  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16333  * Library General Public License for more details.
16334  *
16335  * You should have received a copy of the GNU Library General Public
16336  * License along with this library; if not, write to the
16337  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16338  * Boston, MA 02111-1307, USA.
16339  */
16340 #include "gtk/gtksignal.h"
16341 #include "gtk/gtktable.h"
16342 #include "gtk/gtktogglebutton.h"
16343 #include "tictactoe.h"
16344
16345 enum {
16346   TICTACTOE_SIGNAL,
16347   LAST_SIGNAL
16348 };
16349
16350 static void tictactoe_class_init          (TictactoeClass *klass);
16351 static void tictactoe_init                (Tictactoe      *ttt);
16352 static void tictactoe_toggle              (GtkWidget *widget, Tictactoe *ttt);
16353
16354 static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
16355
16356 guint
16357 tictactoe_get_type ()
16358 {
16359   static guint ttt_type = 0;
16360
16361   if (!ttt_type)
16362     {
16363       GtkTypeInfo ttt_info =
16364       {
16365         "Tictactoe",
16366         sizeof (Tictactoe),
16367         sizeof (TictactoeClass),
16368         (GtkClassInitFunc) tictactoe_class_init,
16369         (GtkObjectInitFunc) tictactoe_init,
16370         (GtkArgSetFunc) NULL,
16371         (GtkArgGetFunc) NULL
16372       };
16373
16374       ttt_type = gtk_type_unique (gtk_vbox_get_type (), &amp;ttt_info);
16375     }
16376
16377   return ttt_type;
16378 }
16379
16380 static void
16381 tictactoe_class_init (TictactoeClass *class)
16382 {
16383   GtkObjectClass *object_class;
16384
16385   object_class = (GtkObjectClass*) class;
16386   
16387   tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
16388                                          GTK_RUN_FIRST,
16389                                          object_class->type,
16390                                          GTK_SIGNAL_OFFSET (TictactoeClass,
16391                                                             tictactoe),
16392                                          gtk_signal_default_marshaller,
16393                                          GTK_TYPE_NONE, 0);
16394
16395
16396   gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
16397
16398   class->tictactoe = NULL;
16399 }
16400
16401 static void
16402 tictactoe_init (Tictactoe *ttt)
16403 {
16404   GtkWidget *table;
16405   gint i,j;
16406   
16407   table = gtk_table_new (3, 3, TRUE);
16408   gtk_container_add (GTK_CONTAINER(ttt), table);
16409   gtk_widget_show (table);
16410
16411   for (i=0;i<3; i++)
16412     for (j=0;j<3; j++)
16413       {
16414         ttt->buttons[i][j] = gtk_toggle_button_new ();
16415         gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j], 
16416                                    i, i+1, j, j+1);
16417         gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
16418                             GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
16419         gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
16420         gtk_widget_show (ttt->buttons[i][j]);
16421       }
16422 }
16423
16424 GtkWidget*
16425 tictactoe_new ()
16426 {
16427   return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
16428 }
16429
16430 void           
16431 tictactoe_clear (Tictactoe *ttt)
16432 {
16433   int i,j;
16434
16435   for (i=0;i<3;i++)
16436     for (j=0;j<3;j++)
16437       {
16438         gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
16439         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
16440                                      FALSE);
16441         gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
16442       }
16443 }
16444
16445 static void
16446 tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
16447 {
16448   int i,k;
16449
16450   static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
16451                              { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
16452                              { 0, 1, 2 }, { 0, 1, 2 } };
16453   static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
16454                              { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
16455                              { 0, 1, 2 }, { 2, 1, 0 } };
16456
16457   int success, found;
16458
16459   for (k=0; k<8; k++)
16460     {
16461       success = TRUE;
16462       found = FALSE;
16463
16464       for (i=0;i<3;i++)
16465         {
16466           success = success &amp;&amp; 
16467             GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
16468           found = found ||
16469             ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
16470         }
16471       
16472       if (success &amp;&amp; found)
16473         {
16474           gtk_signal_emit (GTK_OBJECT (ttt), 
16475                            tictactoe_signals[TICTACTOE_SIGNAL]);
16476           break;
16477         }
16478     }
16479 }
16480
16481 /* example-end */
16482 </verb></tscreen>
16483
16484 <!-- ----------------------------------------------------------------- -->
16485 <sect2>ttt_test.c
16486 <p>
16487 <tscreen><verb>
16488 /* example-start tictactoe ttt_test.c */
16489
16490 #include <gtk/gtk.h>
16491 #include "tictactoe.h"
16492
16493 void win( GtkWidget *widget,
16494           gpointer   data )
16495 {
16496   g_print ("Yay!\n");
16497   tictactoe_clear (TICTACTOE (widget));
16498 }
16499
16500 int main( int   argc,
16501           char *argv[] )
16502 {
16503   GtkWidget *window;
16504   GtkWidget *ttt;
16505   
16506   gtk_init (&amp;argc, &amp;argv);
16507
16508   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
16509   
16510   gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
16511   
16512   gtk_signal_connect (GTK_OBJECT (window), "destroy",
16513                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
16514   
16515   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
16516
16517   ttt = tictactoe_new ();
16518   
16519   gtk_container_add (GTK_CONTAINER (window), ttt);
16520   gtk_widget_show (ttt);
16521
16522   gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
16523                       GTK_SIGNAL_FUNC (win), NULL);
16524
16525   gtk_widget_show (window);
16526   
16527   gtk_main ();
16528   
16529   return 0;
16530 }
16531
16532 /* example-end */
16533 </verb></tscreen>
16534
16535 <!-- ----------------------------------------------------------------- -->
16536 <sect1> GtkDial
16537
16538 <!-- ----------------------------------------------------------------- -->
16539 <sect2> gtkdial.h
16540 <p>
16541 <tscreen><verb>
16542 /* example-start gtkdial gtkdial.h */
16543
16544 /* GTK - The GTK+ Toolkit
16545  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16546  *
16547  * This library is free software; you can redistribute it and/or
16548  * modify it under the terms of the GNU Library General Public
16549  * License as published by the Free Software Foundation; either
16550  * version 2 of the License, or (at your option) any later version.
16551  *
16552  * This library is distributed in the hope that it will be useful,
16553  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16554  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16555  * Library General Public License for more details.
16556  *
16557  * You should have received a copy of the GNU Library General Public
16558  * License along with this library; if not, write to the
16559  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16560  * Boston, MA 02111-1307, USA.
16561  */
16562 #ifndef __GTK_DIAL_H__
16563 #define __GTK_DIAL_H__
16564
16565
16566 #include <gdk/gdk.h>
16567 #include <gtk/gtkadjustment.h>
16568 #include <gtk/gtkwidget.h>
16569
16570
16571 #ifdef __cplusplus
16572 extern "C" {
16573 #endif /* __cplusplus */
16574
16575
16576 #define GTK_DIAL(obj)          GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
16577 #define GTK_DIAL_CLASS(klass)  GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
16578 #define GTK_IS_DIAL(obj)       GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
16579
16580
16581 typedef struct _GtkDial        GtkDial;
16582 typedef struct _GtkDialClass   GtkDialClass;
16583
16584 struct _GtkDial
16585 {
16586   GtkWidget widget;
16587
16588   /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
16589   guint policy : 2;
16590
16591   /* Button currently pressed or 0 if none */
16592   guint8 button;
16593
16594   /* Dimensions of dial components */
16595   gint radius;
16596   gint pointer_width;
16597
16598   /* ID of update timer, or 0 if none */
16599   guint32 timer;
16600
16601   /* Current angle */
16602   gfloat angle;
16603   gfloat last_angle;
16604
16605   /* Old values from adjustment stored so we know when something changes */
16606   gfloat old_value;
16607   gfloat old_lower;
16608   gfloat old_upper;
16609
16610   /* The adjustment object that stores the data for this dial */
16611   GtkAdjustment *adjustment;
16612 };
16613
16614 struct _GtkDialClass
16615 {
16616   GtkWidgetClass parent_class;
16617 };
16618
16619
16620 GtkWidget*     gtk_dial_new                    (GtkAdjustment *adjustment);
16621 guint          gtk_dial_get_type               (void);
16622 GtkAdjustment* gtk_dial_get_adjustment         (GtkDial      *dial);
16623 void           gtk_dial_set_update_policy      (GtkDial      *dial,
16624                                                 GtkUpdateType  policy);
16625
16626 void           gtk_dial_set_adjustment         (GtkDial      *dial,
16627                                                 GtkAdjustment *adjustment);
16628 #ifdef __cplusplus
16629 }
16630 #endif /* __cplusplus */
16631
16632
16633 #endif /* __GTK_DIAL_H__ */
16634 /* example-end */
16635 </verb></tscreen>
16636
16637 <!-- ----------------------------------------------------------------- -->
16638 <sect2> gtkdial.c
16639 <p>
16640 <tscreen><verb>
16641 /* example-start gtkdial gtkdial.c */
16642
16643 /* GTK - The GTK+ Toolkit
16644  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
16645  *
16646  * This library is free software; you can redistribute it and/or
16647  * modify it under the terms of the GNU Library General Public
16648  * License as published by the Free Software Foundation; either
16649  * version 2 of the License, or (at your option) any later version.
16650  *
16651  * This library is distributed in the hope that it will be useful,
16652  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16653  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16654  * Library General Public License for more details.
16655  *
16656  * You should have received a copy of the GNU Library General Public
16657  * License along with this library; if not, write to the
16658  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16659  * Boston, MA 02111-1307, USA.
16660  */
16661 #include <math.h>
16662 #include <stdio.h>
16663 #include <gtk/gtkmain.h>
16664 #include <gtk/gtksignal.h>
16665
16666 #include "gtkdial.h"
16667
16668 #define SCROLL_DELAY_LENGTH  300
16669 #define DIAL_DEFAULT_SIZE 100
16670
16671 /* Forward declarations */
16672
16673 static void gtk_dial_class_init               (GtkDialClass    *klass);
16674 static void gtk_dial_init                     (GtkDial         *dial);
16675 static void gtk_dial_destroy                  (GtkObject        *object);
16676 static void gtk_dial_realize                  (GtkWidget        *widget);
16677 static void gtk_dial_size_request             (GtkWidget      *widget,
16678                                                GtkRequisition *requisition);
16679 static void gtk_dial_size_allocate            (GtkWidget     *widget,
16680                                                GtkAllocation *allocation);
16681 static gint gtk_dial_expose                   (GtkWidget        *widget,
16682                                                 GdkEventExpose   *event);
16683 static gint gtk_dial_button_press             (GtkWidget        *widget,
16684                                                 GdkEventButton   *event);
16685 static gint gtk_dial_button_release           (GtkWidget        *widget,
16686                                                 GdkEventButton   *event);
16687 static gint gtk_dial_motion_notify            (GtkWidget        *widget,
16688                                                 GdkEventMotion   *event);
16689 static gint gtk_dial_timer                    (GtkDial         *dial);
16690
16691 static void gtk_dial_update_mouse             (GtkDial *dial, gint x, gint y);
16692 static void gtk_dial_update                   (GtkDial *dial);
16693 static void gtk_dial_adjustment_changed       (GtkAdjustment    *adjustment,
16694                                                 gpointer          data);
16695 static void gtk_dial_adjustment_value_changed (GtkAdjustment    *adjustment,
16696                                                 gpointer          data);
16697
16698 /* Local data */
16699
16700 static GtkWidgetClass *parent_class = NULL;
16701
16702 guint
16703 gtk_dial_get_type ()
16704 {
16705   static guint dial_type = 0;
16706
16707   if (!dial_type)
16708     {
16709       GtkTypeInfo dial_info =
16710       {
16711         "GtkDial",
16712         sizeof (GtkDial),
16713         sizeof (GtkDialClass),
16714         (GtkClassInitFunc) gtk_dial_class_init,
16715         (GtkObjectInitFunc) gtk_dial_init,
16716         (GtkArgSetFunc) NULL,
16717         (GtkArgGetFunc) NULL,
16718       };
16719
16720       dial_type = gtk_type_unique (gtk_widget_get_type (), &amp;dial_info);
16721     }
16722
16723   return dial_type;
16724 }
16725
16726 static void
16727 gtk_dial_class_init (GtkDialClass *class)
16728 {
16729   GtkObjectClass *object_class;
16730   GtkWidgetClass *widget_class;
16731
16732   object_class = (GtkObjectClass*) class;
16733   widget_class = (GtkWidgetClass*) class;
16734
16735   parent_class = gtk_type_class (gtk_widget_get_type ());
16736
16737   object_class->destroy = gtk_dial_destroy;
16738
16739   widget_class->realize = gtk_dial_realize;
16740   widget_class->expose_event = gtk_dial_expose;
16741   widget_class->size_request = gtk_dial_size_request;
16742   widget_class->size_allocate = gtk_dial_size_allocate;
16743   widget_class->button_press_event = gtk_dial_button_press;
16744   widget_class->button_release_event = gtk_dial_button_release;
16745   widget_class->motion_notify_event = gtk_dial_motion_notify;
16746 }
16747
16748 static void
16749 gtk_dial_init (GtkDial *dial)
16750 {
16751   dial->button = 0;
16752   dial->policy = GTK_UPDATE_CONTINUOUS;
16753   dial->timer = 0;
16754   dial->radius = 0;
16755   dial->pointer_width = 0;
16756   dial->angle = 0.0;
16757   dial->old_value = 0.0;
16758   dial->old_lower = 0.0;
16759   dial->old_upper = 0.0;
16760   dial->adjustment = NULL;
16761 }
16762
16763 GtkWidget*
16764 gtk_dial_new (GtkAdjustment *adjustment)
16765 {
16766   GtkDial *dial;
16767
16768   dial = gtk_type_new (gtk_dial_get_type ());
16769
16770   if (!adjustment)
16771     adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
16772
16773   gtk_dial_set_adjustment (dial, adjustment);
16774
16775   return GTK_WIDGET (dial);
16776 }
16777
16778 static void
16779 gtk_dial_destroy (GtkObject *object)
16780 {
16781   GtkDial *dial;
16782
16783   g_return_if_fail (object != NULL);
16784   g_return_if_fail (GTK_IS_DIAL (object));
16785
16786   dial = GTK_DIAL (object);
16787
16788   if (dial->adjustment)
16789     gtk_object_unref (GTK_OBJECT (dial->adjustment));
16790
16791   if (GTK_OBJECT_CLASS (parent_class)->destroy)
16792     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
16793 }
16794
16795 GtkAdjustment*
16796 gtk_dial_get_adjustment (GtkDial *dial)
16797 {
16798   g_return_val_if_fail (dial != NULL, NULL);
16799   g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
16800
16801   return dial->adjustment;
16802 }
16803
16804 void
16805 gtk_dial_set_update_policy (GtkDial      *dial,
16806                              GtkUpdateType  policy)
16807 {
16808   g_return_if_fail (dial != NULL);
16809   g_return_if_fail (GTK_IS_DIAL (dial));
16810
16811   dial->policy = policy;
16812 }
16813
16814 void
16815 gtk_dial_set_adjustment (GtkDial      *dial,
16816                           GtkAdjustment *adjustment)
16817 {
16818   g_return_if_fail (dial != NULL);
16819   g_return_if_fail (GTK_IS_DIAL (dial));
16820
16821   if (dial->adjustment)
16822     {
16823       gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
16824       gtk_object_unref (GTK_OBJECT (dial->adjustment));
16825     }
16826
16827   dial->adjustment = adjustment;
16828   gtk_object_ref (GTK_OBJECT (dial->adjustment));
16829
16830   gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
16831                       (GtkSignalFunc) gtk_dial_adjustment_changed,
16832                       (gpointer) dial);
16833   gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
16834                       (GtkSignalFunc) gtk_dial_adjustment_value_changed,
16835                       (gpointer) dial);
16836
16837   dial->old_value = adjustment->value;
16838   dial->old_lower = adjustment->lower;
16839   dial->old_upper = adjustment->upper;
16840
16841   gtk_dial_update (dial);
16842 }
16843
16844 static void
16845 gtk_dial_realize (GtkWidget *widget)
16846 {
16847   GtkDial *dial;
16848   GdkWindowAttr attributes;
16849   gint attributes_mask;
16850
16851   g_return_if_fail (widget != NULL);
16852   g_return_if_fail (GTK_IS_DIAL (widget));
16853
16854   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
16855   dial = GTK_DIAL (widget);
16856
16857   attributes.x = widget->allocation.x;
16858   attributes.y = widget->allocation.y;
16859   attributes.width = widget->allocation.width;
16860   attributes.height = widget->allocation.height;
16861   attributes.wclass = GDK_INPUT_OUTPUT;
16862   attributes.window_type = GDK_WINDOW_CHILD;
16863   attributes.event_mask = gtk_widget_get_events (widget) | 
16864     GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
16865     GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
16866     GDK_POINTER_MOTION_HINT_MASK;
16867   attributes.visual = gtk_widget_get_visual (widget);
16868   attributes.colormap = gtk_widget_get_colormap (widget);
16869
16870   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
16871   widget->window = gdk_window_new (widget->parent->window, &amp;attributes, attributes_mask);
16872
16873   widget->style = gtk_style_attach (widget->style, widget->window);
16874
16875   gdk_window_set_user_data (widget->window, widget);
16876
16877   gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
16878 }
16879
16880 static void 
16881 gtk_dial_size_request (GtkWidget      *widget,
16882                        GtkRequisition *requisition)
16883 {
16884   requisition->width = DIAL_DEFAULT_SIZE;
16885   requisition->height = DIAL_DEFAULT_SIZE;
16886 }
16887
16888 static void
16889 gtk_dial_size_allocate (GtkWidget     *widget,
16890                         GtkAllocation *allocation)
16891 {
16892   GtkDial *dial;
16893
16894   g_return_if_fail (widget != NULL);
16895   g_return_if_fail (GTK_IS_DIAL (widget));
16896   g_return_if_fail (allocation != NULL);
16897
16898   widget->allocation = *allocation;
16899   dial = GTK_DIAL (widget);
16900
16901   if (GTK_WIDGET_REALIZED (widget))
16902     {
16903
16904       gdk_window_move_resize (widget->window,
16905                               allocation->x, allocation->y,
16906                               allocation->width, allocation->height);
16907
16908     }
16909   dial->radius = MIN(allocation->width,allocation->height) * 0.45;
16910   dial->pointer_width = dial->radius / 5;
16911 }
16912
16913 static gint
16914 gtk_dial_expose (GtkWidget      *widget,
16915                  GdkEventExpose *event)
16916 {
16917   GtkDial *dial;
16918   GdkPoint points[6];
16919   gdouble s,c;
16920   gdouble theta, last, increment;
16921   GtkStyle      *blankstyle;
16922   gint xc, yc;
16923   gint upper, lower;
16924   gint tick_length;
16925   gint i, inc;
16926
16927   g_return_val_if_fail (widget != NULL, FALSE);
16928   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
16929   g_return_val_if_fail (event != NULL, FALSE);
16930
16931   if (event->count > 0)
16932     return FALSE;
16933   
16934   dial = GTK_DIAL (widget);
16935
16936 /*  gdk_window_clear_area (widget->window,
16937                          0, 0,
16938                          widget->allocation.width,
16939                          widget->allocation.height);
16940 */
16941   xc = widget->allocation.width/2;
16942   yc = widget->allocation.height/2;
16943
16944   upper = dial->adjustment->upper;
16945   lower = dial->adjustment->lower;
16946
16947   /* Erase old pointer */
16948
16949   s = sin(dial->last_angle);
16950   c = cos(dial->last_angle);
16951   dial->last_angle = dial->angle;
16952
16953   points[0].x = xc + s*dial->pointer_width/2;
16954   points[0].y = yc + c*dial->pointer_width/2;
16955   points[1].x = xc + c*dial->radius;
16956   points[1].y = yc - s*dial->radius;
16957   points[2].x = xc - s*dial->pointer_width/2;
16958   points[2].y = yc - c*dial->pointer_width/2;
16959   points[3].x = xc - c*dial->radius/10;
16960   points[3].y = yc + s*dial->radius/10;
16961   points[4].x = points[0].x;
16962   points[4].y = points[0].y;
16963
16964   blankstyle = gtk_style_new ();
16965   blankstyle->bg_gc[GTK_STATE_NORMAL] =
16966                 widget->style->bg_gc[GTK_STATE_NORMAL];
16967   blankstyle->dark_gc[GTK_STATE_NORMAL] =
16968                 widget->style->bg_gc[GTK_STATE_NORMAL];
16969   blankstyle->light_gc[GTK_STATE_NORMAL] =
16970                 widget->style->bg_gc[GTK_STATE_NORMAL];
16971   blankstyle->black_gc =
16972                 widget->style->bg_gc[GTK_STATE_NORMAL];
16973
16974   gtk_draw_polygon (blankstyle,
16975                     widget->window,
16976                     GTK_STATE_NORMAL,
16977                     GTK_SHADOW_OUT,
16978                     points, 5,
16979                     FALSE);
16980
16981   gtk_style_unref(blankstyle);
16982
16983
16984   /* Draw ticks */
16985
16986   if ((upper - lower) == 0)
16987     return;
16988
16989   increment = (100*M_PI)/(dial->radius*dial->radius);
16990
16991   inc = (upper - lower);
16992
16993   while (inc < 100) inc *=10;
16994   while (inc >= 1000) inc /=10;
16995   last = -1;
16996
16997   for (i=0; i<=inc; i++)
16998     {
16999       theta = ((gfloat)i*M_PI/(18*inc/24.) - M_PI/6.);
17000
17001       if ((theta - last) < (increment))
17002         continue;     
17003       last = theta;
17004
17005       s = sin(theta);
17006       c = cos(theta);
17007
17008       tick_length = (i%(inc/10) == 0) ? dial->pointer_width : dial->pointer_width/2;
17009
17010       gdk_draw_line (widget->window,
17011                      widget->style->fg_gc[widget->state],
17012                      xc + c*(dial->radius - tick_length),
17013                      yc - s*(dial->radius - tick_length),
17014                      xc + c*dial->radius,
17015                      yc - s*dial->radius);
17016     }
17017
17018   /* Draw pointer */
17019
17020   s = sin(dial->angle);
17021   c = cos(dial->angle);
17022   dial->last_angle = dial->angle;
17023
17024   points[0].x = xc + s*dial->pointer_width/2;
17025   points[0].y = yc + c*dial->pointer_width/2;
17026   points[1].x = xc + c*dial->radius;
17027   points[1].y = yc - s*dial->radius;
17028   points[2].x = xc - s*dial->pointer_width/2;
17029   points[2].y = yc - c*dial->pointer_width/2;
17030   points[3].x = xc - c*dial->radius/10;
17031   points[3].y = yc + s*dial->radius/10;
17032   points[4].x = points[0].x;
17033   points[4].y = points[0].y;
17034
17035
17036   gtk_draw_polygon (widget->style,
17037                     widget->window,
17038                     GTK_STATE_NORMAL,
17039                     GTK_SHADOW_OUT,
17040                     points, 5,
17041                     TRUE);
17042
17043   return FALSE;
17044 }
17045
17046 static gint
17047 gtk_dial_button_press (GtkWidget      *widget,
17048                        GdkEventButton *event)
17049 {
17050   GtkDial *dial;
17051   gint dx, dy;
17052   double s, c;
17053   double d_parallel;
17054   double d_perpendicular;
17055
17056   g_return_val_if_fail (widget != NULL, FALSE);
17057   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
17058   g_return_val_if_fail (event != NULL, FALSE);
17059
17060   dial = GTK_DIAL (widget);
17061
17062   /* Determine if button press was within pointer region - we 
17063      do this by computing the parallel and perpendicular distance of
17064      the point where the mouse was pressed from the line passing through
17065      the pointer */
17066   
17067   dx = event->x - widget->allocation.width / 2;
17068   dy = widget->allocation.height / 2 - event->y;
17069   
17070   s = sin(dial->angle);
17071   c = cos(dial->angle);
17072   
17073   d_parallel = s*dy + c*dx;
17074   d_perpendicular = fabs(s*dx - c*dy);
17075   
17076   if (!dial->button &amp;&amp;
17077       (d_perpendicular < dial->pointer_width/2) &amp;&amp;
17078       (d_parallel > - dial->pointer_width))
17079     {
17080       gtk_grab_add (widget);
17081
17082       dial->button = event->button;
17083
17084       gtk_dial_update_mouse (dial, event->x, event->y);
17085     }
17086
17087   return FALSE;
17088 }
17089
17090 static gint
17091 gtk_dial_button_release (GtkWidget      *widget,
17092                           GdkEventButton *event)
17093 {
17094   GtkDial *dial;
17095
17096   g_return_val_if_fail (widget != NULL, FALSE);
17097   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
17098   g_return_val_if_fail (event != NULL, FALSE);
17099
17100   dial = GTK_DIAL (widget);
17101
17102   if (dial->button == event->button)
17103     {
17104       gtk_grab_remove (widget);
17105
17106       dial->button = 0;
17107
17108       if (dial->policy == GTK_UPDATE_DELAYED)
17109         gtk_timeout_remove (dial->timer);
17110       
17111       if ((dial->policy != GTK_UPDATE_CONTINUOUS) &amp;&amp;
17112           (dial->old_value != dial->adjustment->value))
17113         gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
17114     }
17115
17116   return FALSE;
17117 }
17118
17119 static gint
17120 gtk_dial_motion_notify (GtkWidget      *widget,
17121                          GdkEventMotion *event)
17122 {
17123   GtkDial *dial;
17124   GdkModifierType mods;
17125   gint x, y, mask;
17126
17127   g_return_val_if_fail (widget != NULL, FALSE);
17128   g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
17129   g_return_val_if_fail (event != NULL, FALSE);
17130
17131   dial = GTK_DIAL (widget);
17132
17133   if (dial->button != 0)
17134     {
17135       x = event->x;
17136       y = event->y;
17137
17138       if (event->is_hint || (event->window != widget->window))
17139         gdk_window_get_pointer (widget->window, &amp;x, &amp;y, &amp;mods);
17140
17141       switch (dial->button)
17142         {
17143         case 1:
17144           mask = GDK_BUTTON1_MASK;
17145           break;
17146         case 2:
17147           mask = GDK_BUTTON2_MASK;
17148           break;
17149         case 3:
17150           mask = GDK_BUTTON3_MASK;
17151           break;
17152         default:
17153           mask = 0;
17154           break;
17155         }
17156
17157       if (mods &amp; mask)
17158         gtk_dial_update_mouse (dial, x,y);
17159     }
17160
17161   return FALSE;
17162 }
17163
17164 static gint
17165 gtk_dial_timer (GtkDial *dial)
17166 {
17167   g_return_val_if_fail (dial != NULL, FALSE);
17168   g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
17169
17170   if (dial->policy == GTK_UPDATE_DELAYED)
17171     gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
17172
17173   return FALSE;
17174 }
17175
17176 static void
17177 gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
17178 {
17179   gint xc, yc;
17180   gfloat old_value;
17181
17182   g_return_if_fail (dial != NULL);
17183   g_return_if_fail (GTK_IS_DIAL (dial));
17184
17185   xc = GTK_WIDGET(dial)->allocation.width / 2;
17186   yc = GTK_WIDGET(dial)->allocation.height / 2;
17187
17188   old_value = dial->adjustment->value;
17189   dial->angle = atan2(yc-y, x-xc);
17190
17191   if (dial->angle < -M_PI/2.)
17192     dial->angle += 2*M_PI;
17193
17194   if (dial->angle < -M_PI/6)
17195     dial->angle = -M_PI/6;
17196
17197   if (dial->angle > 7.*M_PI/6.)
17198     dial->angle = 7.*M_PI/6.;
17199
17200   dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
17201     (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
17202
17203   if (dial->adjustment->value != old_value)
17204     {
17205       if (dial->policy == GTK_UPDATE_CONTINUOUS)
17206         {
17207           gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
17208         }
17209       else
17210         {
17211           gtk_widget_draw (GTK_WIDGET(dial), NULL);
17212
17213           if (dial->policy == GTK_UPDATE_DELAYED)
17214             {
17215               if (dial->timer)
17216                 gtk_timeout_remove (dial->timer);
17217
17218               dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
17219                                              (GtkFunction) gtk_dial_timer,
17220                                              (gpointer) dial);
17221             }
17222         }
17223     }
17224 }
17225
17226 static void
17227 gtk_dial_update (GtkDial *dial)
17228 {
17229   gfloat new_value;
17230   
17231   g_return_if_fail (dial != NULL);
17232   g_return_if_fail (GTK_IS_DIAL (dial));
17233
17234   new_value = dial->adjustment->value;
17235   
17236   if (new_value < dial->adjustment->lower)
17237     new_value = dial->adjustment->lower;
17238
17239   if (new_value > dial->adjustment->upper)
17240     new_value = dial->adjustment->upper;
17241
17242   if (new_value != dial->adjustment->value)
17243     {
17244       dial->adjustment->value = new_value;
17245       gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
17246     }
17247
17248   dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
17249     (dial->adjustment->upper - dial->adjustment->lower);
17250
17251   gtk_widget_draw (GTK_WIDGET(dial), NULL);
17252 }
17253
17254 static void
17255 gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
17256                               gpointer       data)
17257 {
17258   GtkDial *dial;
17259
17260   g_return_if_fail (adjustment != NULL);
17261   g_return_if_fail (data != NULL);
17262
17263   dial = GTK_DIAL (data);
17264
17265   if ((dial->old_value != adjustment->value) ||
17266       (dial->old_lower != adjustment->lower) ||
17267       (dial->old_upper != adjustment->upper))
17268     {
17269       gtk_dial_update (dial);
17270
17271       dial->old_value = adjustment->value;
17272       dial->old_lower = adjustment->lower;
17273       dial->old_upper = adjustment->upper;
17274     }
17275 }
17276
17277 static void
17278 gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
17279                                     gpointer       data)
17280 {
17281   GtkDial *dial;
17282
17283   g_return_if_fail (adjustment != NULL);
17284   g_return_if_fail (data != NULL);
17285
17286   dial = GTK_DIAL (data);
17287
17288   if (dial->old_value != adjustment->value)
17289     {
17290       gtk_dial_update (dial);
17291
17292       dial->old_value = adjustment->value;
17293     }
17294 }
17295 /* example-end */
17296
17297 </verb></tscreen>
17298
17299 <!-- ----------------------------------------------------------------- -->
17300 <sect2> dial_test.c
17301 <p>
17302 <tscreen><verb>
17303 #include <stdio.h>
17304 #include <gtk/gtk.h>
17305 #include "gtkdial.h"
17306
17307 void value_changed( GtkAdjustment *adjustment,
17308                     GtkWidget     *label )
17309 {
17310   char buffer[16];
17311
17312   sprintf(buffer,"%4.2f",adjustment->value);
17313   gtk_label_set (GTK_LABEL (label), buffer);
17314 }
17315
17316 int main( int   argc,
17317           char *argv[])
17318 {
17319   GtkWidget *window;
17320   GtkAdjustment *adjustment;
17321   GtkWidget *dial;
17322   GtkWidget *frame;
17323   GtkWidget *vbox;
17324   GtkWidget *label;
17325   
17326   gtk_init (&amp;argc, &amp;argv);
17327
17328   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
17329   
17330   gtk_window_set_title (GTK_WINDOW (window), "Dial");
17331   
17332   gtk_signal_connect (GTK_OBJECT (window), "destroy",
17333                       GTK_SIGNAL_FUNC (gtk_exit), NULL);
17334   
17335   gtk_container_border_width (GTK_CONTAINER (window), 10);
17336
17337   vbox = gtk_vbox_new (FALSE, 5);
17338   gtk_container_add (GTK_CONTAINER (window), vbox);
17339   gtk_widget_show(vbox);
17340
17341   frame = gtk_frame_new (NULL);
17342   gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
17343   gtk_container_add (GTK_CONTAINER (vbox), frame);
17344   gtk_widget_show (frame); 
17345  
17346   adjustment = GTK_ADJUSTMENT(gtk_adjustment_new (0, 0, 100, 0.01, 0.1, 0));
17347   
17348   dial = gtk_dial_new(adjustment);
17349   gtk_dial_set_update_policy (GTK_DIAL(dial), GTK_UPDATE_DELAYED);
17350   /*  gtk_widget_set_usize (dial, 100, 100); */
17351   
17352   gtk_container_add (GTK_CONTAINER (frame), dial);
17353   gtk_widget_show (dial);
17354
17355   label = gtk_label_new("0.00");
17356   gtk_box_pack_end (GTK_BOX(vbox), label, 0, 0, 0);
17357   gtk_widget_show (label);
17358
17359   gtk_signal_connect (GTK_OBJECT(adjustment), "value_changed",
17360                       GTK_SIGNAL_FUNC (value_changed), label);
17361   
17362   gtk_widget_show (window);
17363   
17364   gtk_main ();
17365   
17366   return 0;
17367 }
17368
17369 </verb></tscreen>
17370
17371 <!-- ----------------------------------------------------------------- -->
17372 <sect1> Scribble
17373 <p>
17374 <!-- ----------------------------------------------------------------- -->
17375 <sect2> scribble-simple.c
17376 <p>
17377 <tscreen><verb>
17378 /* example-start scribble-simple scribble-simple.c */
17379
17380 /* GTK - The GTK+ Toolkit
17381  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
17382  *
17383  * This library is free software; you can redistribute it and/or
17384  * modify it under the terms of the GNU Library General Public
17385  * License as published by the Free Software Foundation; either
17386  * version 2 of the License, or (at your option) any later version.
17387  *
17388  * This library is distributed in the hope that it will be useful,
17389  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17390  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17391  * Library General Public License for more details.
17392  *
17393  * You should have received a copy of the GNU Library General Public
17394  * License along with this library; if not, write to the
17395  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17396  * Boston, MA 02111-1307, USA.
17397  */
17398
17399 #include <gtk/gtk.h>
17400
17401 /* Backing pixmap for drawing area */
17402 static GdkPixmap *pixmap = NULL;
17403
17404 /* Create a new backing pixmap of the appropriate size */
17405 static gint configure_event( GtkWidget         *widget,
17406                              GdkEventConfigure *event )
17407 {
17408   if (pixmap)
17409     gdk_pixmap_unref(pixmap);
17410
17411   pixmap = gdk_pixmap_new(widget->window,
17412                           widget->allocation.width,
17413                           widget->allocation.height,
17414                           -1);
17415   gdk_draw_rectangle (pixmap,
17416                       widget->style->white_gc,
17417                       TRUE,
17418                       0, 0,
17419                       widget->allocation.width,
17420                       widget->allocation.height);
17421
17422   return TRUE;
17423 }
17424
17425 /* Redraw the screen from the backing pixmap */
17426 static gint expose_event( GtkWidget      *widget,
17427                           GdkEventExpose *event )
17428 {
17429   gdk_draw_pixmap(widget->window,
17430                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
17431                   pixmap,
17432                   event->area.x, event->area.y,
17433                   event->area.x, event->area.y,
17434                   event->area.width, event->area.height);
17435
17436   return FALSE;
17437 }
17438
17439 /* Draw a rectangle on the screen */
17440 static void draw_brush( GtkWidget *widget,
17441                         gdouble    x,
17442                         gdouble    y)
17443 {
17444   GdkRectangle update_rect;
17445
17446   update_rect.x = x - 5;
17447   update_rect.y = y - 5;
17448   update_rect.width = 10;
17449   update_rect.height = 10;
17450   gdk_draw_rectangle (pixmap,
17451                       widget->style->black_gc,
17452                       TRUE,
17453                       update_rect.x, update_rect.y,
17454                       update_rect.width, update_rect.height);
17455   gtk_widget_draw (widget, &amp;update_rect);
17456 }
17457
17458 static gint button_press_event( GtkWidget      *widget,
17459                                 GdkEventButton *event )
17460 {
17461   if (event->button == 1 &amp;&amp; pixmap != NULL)
17462     draw_brush (widget, event->x, event->y);
17463
17464   return TRUE;
17465 }
17466
17467 static gint motion_notify_event( GtkWidget *widget,
17468                                  GdkEventMotion *event )
17469 {
17470   int x, y;
17471   GdkModifierType state;
17472
17473   if (event->is_hint)
17474     gdk_window_get_pointer (event->window, &amp;x, &amp;y, &amp;state);
17475   else
17476     {
17477       x = event->x;
17478       y = event->y;
17479       state = event->state;
17480     }
17481     
17482   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
17483     draw_brush (widget, x, y);
17484   
17485   return TRUE;
17486 }
17487
17488 void quit ()
17489 {
17490   gtk_exit (0);
17491 }
17492
17493 int main( int   argc, 
17494           char *argv[] )
17495 {
17496   GtkWidget *window;
17497   GtkWidget *drawing_area;
17498   GtkWidget *vbox;
17499
17500   GtkWidget *button;
17501
17502   gtk_init (&amp;argc, &amp;argv);
17503
17504   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
17505   gtk_widget_set_name (window, "Test Input");
17506
17507   vbox = gtk_vbox_new (FALSE, 0);
17508   gtk_container_add (GTK_CONTAINER (window), vbox);
17509   gtk_widget_show (vbox);
17510
17511   gtk_signal_connect (GTK_OBJECT (window), "destroy",
17512                       GTK_SIGNAL_FUNC (quit), NULL);
17513
17514   /* Create the drawing area */
17515
17516   drawing_area = gtk_drawing_area_new ();
17517   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
17518   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
17519
17520   gtk_widget_show (drawing_area);
17521
17522   /* Signals used to handle backing pixmap */
17523
17524   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
17525                       (GtkSignalFunc) expose_event, NULL);
17526   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
17527                       (GtkSignalFunc) configure_event, NULL);
17528
17529   /* Event signals */
17530
17531   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
17532                       (GtkSignalFunc) motion_notify_event, NULL);
17533   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
17534                       (GtkSignalFunc) button_press_event, NULL);
17535
17536   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
17537                          | GDK_LEAVE_NOTIFY_MASK
17538                          | GDK_BUTTON_PRESS_MASK
17539                          | GDK_POINTER_MOTION_MASK
17540                          | GDK_POINTER_MOTION_HINT_MASK);
17541
17542   /* .. And a quit button */
17543   button = gtk_button_new_with_label ("Quit");
17544   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
17545
17546   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
17547                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
17548                              GTK_OBJECT (window));
17549   gtk_widget_show (button);
17550
17551   gtk_widget_show (window);
17552
17553   gtk_main ();
17554
17555   return 0;
17556 }
17557 /* example-end */
17558 </verb></tscreen>
17559
17560 <!-- ----------------------------------------------------------------- -->
17561 <sect2> scribble-xinput.c
17562 <p>
17563 <tscreen><verb>
17564 /* example-start scribble-xinput scribble-xinput.c */
17565
17566 /* GTK - The GTK+ Toolkit
17567  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
17568  *
17569  * This library is free software; you can redistribute it and/or
17570  * modify it under the terms of the GNU Library General Public
17571  * License as published by the Free Software Foundation; either
17572  * version 2 of the License, or (at your option) any later version.
17573  *
17574  * This library is distributed in the hope that it will be useful,
17575  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17576  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17577  * Library General Public License for more details.
17578  *
17579  * You should have received a copy of the GNU Library General Public
17580  * License along with this library; if not, write to the
17581  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17582  * Boston, MA 02111-1307, USA.
17583  */
17584
17585 #include <gtk/gtk.h>
17586
17587 /* Backing pixmap for drawing area */
17588 static GdkPixmap *pixmap = NULL;
17589
17590 /* Create a new backing pixmap of the appropriate size */
17591 static gint
17592 configure_event (GtkWidget *widget, GdkEventConfigure *event)
17593 {
17594   if (pixmap)
17595      gdk_pixmap_unref(pixmap);
17596
17597   pixmap = gdk_pixmap_new(widget->window,
17598                           widget->allocation.width,
17599                           widget->allocation.height,
17600                           -1);
17601   gdk_draw_rectangle (pixmap,
17602                       widget->style->white_gc,
17603                       TRUE,
17604                       0, 0,
17605                       widget->allocation.width,
17606                       widget->allocation.height);
17607
17608   return TRUE;
17609 }
17610
17611 /* Redraw the screen from the backing pixmap */
17612 static gint
17613 expose_event (GtkWidget *widget, GdkEventExpose *event)
17614 {
17615   gdk_draw_pixmap(widget->window,
17616                   widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
17617                   pixmap,
17618                   event->area.x, event->area.y,
17619                   event->area.x, event->area.y,
17620                   event->area.width, event->area.height);
17621
17622   return FALSE;
17623 }
17624
17625 /* Draw a rectangle on the screen, size depending on pressure,
17626    and color on the type of device */
17627 static void
17628 draw_brush (GtkWidget *widget, GdkInputSource source,
17629             gdouble x, gdouble y, gdouble pressure)
17630 {
17631   GdkGC *gc;
17632   GdkRectangle update_rect;
17633
17634   switch (source)
17635     {
17636     case GDK_SOURCE_MOUSE:
17637       gc = widget->style->dark_gc[GTK_WIDGET_STATE (widget)];
17638       break;
17639     case GDK_SOURCE_PEN:
17640       gc = widget->style->black_gc;
17641       break;
17642     case GDK_SOURCE_ERASER:
17643       gc = widget->style->white_gc;
17644       break;
17645     default:
17646       gc = widget->style->light_gc[GTK_WIDGET_STATE (widget)];
17647     }
17648
17649   update_rect.x = x - 10 * pressure;
17650   update_rect.y = y - 10 * pressure;
17651   update_rect.width = 20 * pressure;
17652   update_rect.height = 20 * pressure;
17653   gdk_draw_rectangle (pixmap, gc, TRUE,
17654                       update_rect.x, update_rect.y,
17655                       update_rect.width, update_rect.height);
17656   gtk_widget_draw (widget, &amp;update_rect);
17657 }
17658
17659 static void
17660 print_button_press (guint32 deviceid)
17661 {
17662   GList *tmp_list;
17663
17664   /* gdk_input_list_devices returns an internal list, so we shouldn't
17665      free it afterwards */
17666   tmp_list = gdk_input_list_devices();
17667
17668   while (tmp_list)
17669     {
17670       GdkDeviceInfo *info = (GdkDeviceInfo *)tmp_list->data;
17671
17672       if (info->deviceid == deviceid)
17673         {
17674           g_print("Button press on device '%s'\n", info->name);
17675           return;
17676         }
17677
17678       tmp_list = tmp_list->next;
17679     }
17680 }
17681
17682 static gint
17683 button_press_event (GtkWidget *widget, GdkEventButton *event)
17684 {
17685   print_button_press (event->deviceid);
17686   
17687   if (event->button == 1 &amp;&amp; pixmap != NULL)
17688     draw_brush (widget, event->source, event->x, event->y, event->pressure);
17689
17690   return TRUE;
17691 }
17692
17693 static gint
17694 motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
17695 {
17696   gdouble x, y;
17697   gdouble pressure;
17698   GdkModifierType state;
17699
17700   if (event->is_hint)
17701     gdk_input_window_get_pointer (event->window, event->deviceid,
17702                                   &amp;x, &amp;y, &amp;pressure,
17703                                   NULL, NULL, &amp;state);
17704   else
17705     {
17706       x = event->x;
17707       y = event->y;
17708       pressure = event->pressure;
17709       state = event->state;
17710     }
17711     
17712   if (state &amp; GDK_BUTTON1_MASK &amp;&amp; pixmap != NULL)
17713     draw_brush (widget, event->source, x, y, pressure);
17714   
17715   return TRUE;
17716 }
17717
17718 void
17719 input_dialog_destroy (GtkWidget *w, gpointer data)
17720 {
17721   *((GtkWidget **)data) = NULL;
17722 }
17723
17724 void
17725 create_input_dialog ()
17726 {
17727   static GtkWidget *inputd = NULL;
17728
17729   if (!inputd)
17730     {
17731       inputd = gtk_input_dialog_new();
17732
17733       gtk_signal_connect (GTK_OBJECT(inputd), "destroy",
17734                           (GtkSignalFunc)input_dialog_destroy, &amp;inputd);
17735       gtk_signal_connect_object (GTK_OBJECT(GTK_INPUT_DIALOG(inputd)->close_button),
17736                                  "clicked",
17737                                  (GtkSignalFunc)gtk_widget_hide,
17738                                  GTK_OBJECT(inputd));
17739       gtk_widget_hide ( GTK_INPUT_DIALOG(inputd)->save_button);
17740
17741       gtk_widget_show (inputd);
17742     }
17743   else
17744     {
17745       if (!GTK_WIDGET_MAPPED(inputd))
17746         gtk_widget_show(inputd);
17747       else
17748         gdk_window_raise(inputd->window);
17749     }
17750 }
17751
17752 void
17753 quit ()
17754 {
17755   gtk_exit (0);
17756 }
17757
17758 int
17759 main (int argc, char *argv[])
17760 {
17761   GtkWidget *window;
17762   GtkWidget *drawing_area;
17763   GtkWidget *vbox;
17764
17765   GtkWidget *button;
17766
17767   gtk_init (&amp;argc, &amp;argv);
17768
17769   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
17770   gtk_widget_set_name (window, "Test Input");
17771
17772   vbox = gtk_vbox_new (FALSE, 0);
17773   gtk_container_add (GTK_CONTAINER (window), vbox);
17774   gtk_widget_show (vbox);
17775
17776   gtk_signal_connect (GTK_OBJECT (window), "destroy",
17777                       GTK_SIGNAL_FUNC (quit), NULL);
17778
17779   /* Create the drawing area */
17780
17781   drawing_area = gtk_drawing_area_new ();
17782   gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
17783   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
17784
17785   gtk_widget_show (drawing_area);
17786
17787   /* Signals used to handle backing pixmap */
17788
17789   gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
17790                       (GtkSignalFunc) expose_event, NULL);
17791   gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
17792                       (GtkSignalFunc) configure_event, NULL);
17793
17794   /* Event signals */
17795
17796   gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
17797                       (GtkSignalFunc) motion_notify_event, NULL);
17798   gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
17799                       (GtkSignalFunc) button_press_event, NULL);
17800
17801   gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
17802                          | GDK_LEAVE_NOTIFY_MASK
17803                          | GDK_BUTTON_PRESS_MASK
17804                          | GDK_POINTER_MOTION_MASK
17805                          | GDK_POINTER_MOTION_HINT_MASK);
17806
17807   /* The following call enables tracking and processing of extension
17808      events for the drawing area */
17809   gtk_widget_set_extension_events (drawing_area, GDK_EXTENSION_EVENTS_CURSOR);
17810
17811   /* .. And some buttons */
17812   button = gtk_button_new_with_label ("Input Dialog");
17813   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
17814
17815   gtk_signal_connect (GTK_OBJECT (button), "clicked",
17816                       GTK_SIGNAL_FUNC (create_input_dialog), NULL);
17817   gtk_widget_show (button);
17818
17819   button = gtk_button_new_with_label ("Quit");
17820   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
17821
17822   gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
17823                              GTK_SIGNAL_FUNC (gtk_widget_destroy),
17824                              GTK_OBJECT (window));
17825   gtk_widget_show (button);
17826
17827   gtk_widget_show (window);
17828
17829   gtk_main ();
17830
17831   return 0;
17832 }
17833 /* example-end */
17834 </verb></tscreen>
17835
17836 <!-- ***************************************************************** -->
17837 <sect> List Widget
17838 <!-- ***************************************************************** -->
17839 <p>
17840 NOTE: The List widget has been superseded by the CList widget. It is
17841 detailed here just for completeness.
17842
17843 The List widget is designed to act as a vertical container for
17844 widgets that should be of the type ListItem.
17845
17846 A List widget has its own window to receive events and its own
17847 background color which is usually white. As it is directly derived
17848 from a Container it can be treated as such by using the
17849 GTK_CONTAINER(List) macro, see the Container widget for more on
17850 this. One should already be familiar with the usage of a GList and
17851 its related functions g_list_*() to be able to use the List widget
17852 to it full extent.
17853
17854 There is one field inside the structure definition of the List
17855 widget that will be of greater interest to us, this is:
17856
17857 <tscreen><verb>
17858 struct _GtkList
17859 {
17860   ...
17861   GList *selection;
17862   guint selection_mode;
17863   ...
17864 }; 
17865 </verb></tscreen>
17866
17867 The selection field of a List points to a linked list of all items
17868 that are currently selected, or NULL if the selection is empty.  So to
17869 learn about the current selection we read the GTK_LIST()->selection
17870 field, but do not modify it since the internal fields are maintained
17871 by the gtk_list_*() functions.
17872
17873 The selection_mode of the List determines the selection facilities
17874 of a List and therefore the contents of the GTK_LIST()->selection
17875 field. The selection_mode may be one of the following:
17876
17877 <itemize>
17878 <item> <tt/GTK_SELECTION_SINGLE/ - The selection is either NULL
17879                         or contains a GList pointer
17880                         for a single selected item.
17881
17882 <item> <tt/GTK_SELECTION_BROWSE/ -  The selection is NULL if the list
17883                         contains no widgets or insensitive
17884                         ones only, otherwise it contains
17885                         a GList pointer for one GList
17886                         structure, and therefore exactly
17887                         one list item.
17888
17889 <item> <tt/GTK_SELECTION_MULTIPLE/ -  The selection is NULL if no list
17890                         items are selected or a GList pointer
17891                         for the first selected item. That
17892                         in turn points to a GList structure
17893                         for the second selected item and so
17894                         on.
17895
17896 <item> <tt/GTK_SELECTION_EXTENDED/ - The selection is always NULL.
17897 </itemize>
17898
17899 The default is <tt/GTK_SELECTION_MULTIPLE/.
17900
17901 <!-- ----------------------------------------------------------------- -->
17902 <sect1> Signals
17903 <p>
17904 <tscreen><verb>
17905 void selection_changed( GtkList *list );
17906 </verb></tscreen>
17907
17908 This signal will be invoked whenever the selection field of a List
17909 has changed. This happens when a child of thekList got selected or
17910 deselected.
17911
17912 <tscreen><verb>
17913 void select_child( GtkList   *list,
17914                    GtkWidget *child);
17915 </verb></tscreen>
17916
17917 This signal is invoked when a child of the List is about to get
17918 selected. This happens mainly on calls to gtk_list_select_item(),
17919 gtk_list_select_child(), button presses and sometimes indirectly
17920 triggered on some else occasions where children get added to or
17921 removed from the List.
17922
17923 <tscreen><verb>
17924 void unselect_child( GtkList   *list,
17925                      GtkWidget *child );
17926 </verb></tscreen>
17927
17928 This signal is invoked when a child of the List is about to get
17929 deselected. This happens mainly on calls to gtk_list_unselect_item(),
17930 gtk_list_unselect_child(), button presses and sometimes indirectly
17931 triggered on some else occasions where children get added to or
17932 removed from the List.
17933
17934 <!-- ----------------------------------------------------------------- -->
17935 <sect1> Functions
17936 <p>
17937 <tscreen><verb>
17938 guint gtk_list_get_type( void );
17939 </verb></tscreen>
17940
17941 Returns the "GtkList" type identifier.
17942
17943 <tscreen><verb>
17944 GtkWidget *gtk_list_new( void );
17945 </verb></tscreen>
17946
17947 Create a new List object. The new widget is returned as a pointer
17948 to a GtkWidget object. NULL is returned on failure.
17949
17950 <tscreen><verb>
17951 void gtk_list_insert_items( GtkList *list,
17952                             GList   *items,
17953                             gint     position );
17954 </verb></tscreen>
17955
17956 Insert list items into the list, starting at <tt/position/.
17957 <tt/items/ is a doubly linked list where each nodes data pointer is
17958 expected to point to a newly created ListItem. The GList nodes of
17959 <tt/items/ are taken over by the list.
17960
17961 <tscreen><verb>
17962 void gtk_list_append_items( GtkList *list,
17963                             GList   *items);
17964 </verb></tscreen>
17965
17966 Insert list items just like gtk_list_insert_items() at the end of the
17967 list. The GList nodes of <tt/items/ are taken over by the list.
17968
17969 <tscreen><verb>
17970 void gtk_list_prepend_items( GtkList *list,
17971                              GList   *items);
17972 </verb></tscreen>
17973
17974 Insert list items just like gtk_list_insert_items() at the very
17975 beginning of the list. The GList nodes of <tt/items/ are taken over by
17976 the list.
17977
17978 <tscreen><verb>
17979 void gtk_list_remove_items( GtkList *list,
17980                             GList   *items);
17981 </verb></tscreen>
17982
17983 Remove list items from the list. <tt/items/ is a doubly linked list
17984 where each nodes data pointer is expected to point to a direct child
17985 of list. It is the callers responsibility to make a call to
17986 g_list_free(items) afterwards. Also the caller has to destroy the list
17987 items himself.
17988
17989 <tscreen><verb>
17990 void gtk_list_clear_items( GtkList *list,
17991                            gint start,
17992                            gint end );
17993 </verb></tscreen>
17994
17995 Remove and destroy list items from the list. A widget is affected if
17996 its current position within the list is in the range specified by
17997 <tt/start/ and <tt/end/.
17998
17999 <tscreen><verb>
18000 void gtk_list_select_item( GtkList *list,
18001                            gint     item );
18002 </verb></tscreen>
18003
18004 Invoke the select_child signal for a list item specified through its
18005 current position within the list.
18006
18007 <tscreen><verb>
18008 void gtk_list_unselect_item( GtkList *list,
18009                              gint     item);
18010 </verb></tscreen>
18011
18012 Invoke the unselect_child signal for a list item specified through its
18013 current position within the list.
18014
18015 <tscreen><verb>
18016 void gtk_list_select_child( GtkList *list,
18017                             GtkWidget *child);
18018 </verb></tscreen>
18019
18020 Invoke the select_child signal for the specified child.
18021
18022 <tscreen><verb>
18023 void gtk_list_unselect_child( GtkList   *list,
18024                               GtkWidget *child);
18025 </verb></tscreen>
18026
18027 Invoke the unselect_child signal for the specified child.
18028
18029 <tscreen><verb>
18030 gint gtk_list_child_position( GtkList *list,
18031                               GtkWidget *child);
18032 </verb></tscreen>
18033
18034 Return the position of <tt/child/ within the list. "-1" is returned on
18035 failure.
18036
18037 <tscreen><verb>
18038 void gtk_list_set_selection_mode( GtkList         *list,
18039                                   GtkSelectionMode mode );
18040 </verb></tscreen>
18041
18042 Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
18043 GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
18044 GTK_SELECTION_EXTENDED.
18045
18046 <tscreen><verb>
18047 GtkList *GTK_LIST( gpointer obj );
18048 </verb></tscreen>
18049
18050 Cast a generic pointer to "GtkList *".
18051
18052 <tscreen><verb>
18053 GtkListClass *GTK_LIST_CLASS( gpointer class);
18054 </verb></tscreen>
18055
18056 Cast a generic pointer to "GtkListClass *". 
18057
18058 <tscreen><verb>
18059 gint GTK_IS_LIST( gpointer obj);
18060 </verb></tscreen>
18061
18062 Determine if a generic pointer refers to a "GtkList" object.
18063
18064 <!-- ----------------------------------------------------------------- -->
18065 <sect1> Example
18066 <p>
18067 Following is an example program that will print out the changes of the
18068 selection of a List, and lets you "arrest" list items into a prison
18069 by selecting them with the rightmost mouse button.
18070
18071 <tscreen><verb>
18072 /* example-start list list.c */
18073
18074 /* Include the GTK header files
18075  * Include stdio.h, we need that for the printf() function
18076  */
18077 #include        <gtk/gtk.h>
18078 #include        <stdio.h>
18079
18080 /* This is our data identification string to store
18081  * data in list items
18082  */
18083 const gchar *list_item_data_key="list_item_data";
18084
18085
18086 /* prototypes for signal handler that we are going to connect
18087  * to the List widget
18088  */
18089 static void  sigh_print_selection( GtkWidget *gtklist,
18090                                    gpointer   func_data);
18091
18092 static void  sigh_button_event( GtkWidget      *gtklist,
18093                                 GdkEventButton *event,
18094                                 GtkWidget      *frame );
18095
18096
18097 /* Main function to set up the user interface */
18098
18099 gint main( int    argc,
18100            gchar *argv[] )
18101 {                                  
18102     GtkWidget *separator;
18103     GtkWidget *window;
18104     GtkWidget *vbox;
18105     GtkWidget *scrolled_window;
18106     GtkWidget *frame;
18107     GtkWidget *gtklist;
18108     GtkWidget *button;
18109     GtkWidget *list_item;
18110     GList *dlist;
18111     guint i;
18112     gchar buffer[64];
18113     
18114     
18115     /* Initialize GTK (and subsequently GDK) */
18116
18117     gtk_init(&amp;argc, &amp;argv);
18118     
18119     
18120     /* Create a window to put all the widgets in
18121      * connect gtk_main_quit() to the "destroy" event of
18122      * the window to handle window manager close-window-events
18123      */
18124     window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
18125     gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
18126     gtk_signal_connect(GTK_OBJECT(window),
18127                        "destroy",
18128                        GTK_SIGNAL_FUNC(gtk_main_quit),
18129                        NULL);
18130     
18131     
18132     /* Inside the window we need a box to arrange the widgets
18133      * vertically */
18134     vbox=gtk_vbox_new(FALSE, 5);
18135     gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
18136     gtk_container_add(GTK_CONTAINER(window), vbox);
18137     gtk_widget_show(vbox);
18138     
18139     /* This is the scrolled window to put the List widget inside */
18140     scrolled_window=gtk_scrolled_window_new(NULL, NULL);
18141     gtk_widget_set_usize(scrolled_window, 250, 150);
18142     gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
18143     gtk_widget_show(scrolled_window);
18144     
18145     /* Create thekList widget.
18146      * Connect the sigh_print_selection() signal handler
18147      * function to the "selection_changed" signal of the List
18148      * to print out the selected items each time the selection
18149      * has changed */
18150     gtklist=gtk_list_new();
18151     gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
18152                                            gtklist);
18153     gtk_widget_show(gtklist);
18154     gtk_signal_connect(GTK_OBJECT(gtklist),
18155                        "selection_changed",
18156                        GTK_SIGNAL_FUNC(sigh_print_selection),
18157                        NULL);
18158     
18159     /* We create a "Prison" to put a list item in ;) */
18160     frame=gtk_frame_new("Prison");
18161     gtk_widget_set_usize(frame, 200, 50);
18162     gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
18163     gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
18164     gtk_container_add(GTK_CONTAINER(vbox), frame);
18165     gtk_widget_show(frame);
18166     
18167     /* Connect the sigh_button_event() signal handler to the List
18168      * which will handle the "arresting" of list items
18169      */
18170     gtk_signal_connect(GTK_OBJECT(gtklist),
18171                        "button_release_event",
18172                        GTK_SIGNAL_FUNC(sigh_button_event),
18173                        frame);
18174     
18175     /* Create a separator */
18176     separator=gtk_hseparator_new();
18177     gtk_container_add(GTK_CONTAINER(vbox), separator);
18178     gtk_widget_show(separator);
18179     
18180     /* Finally create a button and connect its "clicked" signal
18181      * to the destruction of the window */
18182     button=gtk_button_new_with_label("Close");
18183     gtk_container_add(GTK_CONTAINER(vbox), button);
18184     gtk_widget_show(button);
18185     gtk_signal_connect_object(GTK_OBJECT(button),
18186                               "clicked",
18187                               GTK_SIGNAL_FUNC(gtk_widget_destroy),
18188                               GTK_OBJECT(window));
18189     
18190     
18191     /* Now we create 5 list items, each having its own
18192      * label and add them to the List using gtk_container_add()
18193      * Also we query the text string from the label and
18194      * associate it with the list_item_data_key for each list item
18195      */
18196     for (i=0; i<5; i++) {
18197         GtkWidget       *label;
18198         gchar           *string;
18199         
18200         sprintf(buffer, "ListItemContainer with Label #%d", i);
18201         label=gtk_label_new(buffer);
18202         list_item=gtk_list_item_new();
18203         gtk_container_add(GTK_CONTAINER(list_item), label);
18204         gtk_widget_show(label);
18205         gtk_container_add(GTK_CONTAINER(gtklist), list_item);
18206         gtk_widget_show(list_item);
18207         gtk_label_get(GTK_LABEL(label), &amp;string);
18208         gtk_object_set_data(GTK_OBJECT(list_item),
18209                             list_item_data_key,
18210                             string);
18211     }
18212     /* Here, we are creating another 5 labels, this time
18213      * we use gtk_list_item_new_with_label() for the creation
18214      * we can't query the text string from the label because
18215      * we don't have the labels pointer and therefore
18216      * we just associate the list_item_data_key of each
18217      * list item with the same text string.
18218      * For adding of the list items we put them all into a doubly
18219      * linked list (GList), and then add them by a single call to
18220      * gtk_list_append_items().
18221      * Because we use g_list_prepend() to put the items into the
18222      * doubly linked list, their order will be descending (instead
18223      * of ascending when using g_list_append())
18224      */
18225     dlist=NULL;
18226     for (; i<10; i++) {
18227         sprintf(buffer, "List Item with Label %d", i);
18228         list_item=gtk_list_item_new_with_label(buffer);
18229         dlist=g_list_prepend(dlist, list_item);
18230         gtk_widget_show(list_item);
18231         gtk_object_set_data(GTK_OBJECT(list_item),
18232                             list_item_data_key,
18233                             "ListItem with integrated Label");
18234     }
18235     gtk_list_append_items(GTK_LIST(gtklist), dlist);
18236     
18237     /* Finally we want to see the window, don't we? ;) */
18238     gtk_widget_show(window);
18239     
18240     /* Fire up the main event loop of gtk */
18241     gtk_main();
18242     
18243     /* We get here after gtk_main_quit() has been called which
18244      * happens if the main window gets destroyed
18245      */
18246     return(0);
18247 }
18248
18249 /* This is the signal handler that got connected to button
18250  * press/release events of the List
18251  */
18252 void sigh_button_event( GtkWidget      *gtklist,
18253                         GdkEventButton *event,
18254                         GtkWidget      *frame )
18255 {
18256     /* We only do something if the third (rightmost mouse button
18257      * was released
18258      */
18259     if (event->type==GDK_BUTTON_RELEASE &amp;&amp;
18260         event->button==3) {
18261         GList           *dlist, *free_list;
18262         GtkWidget       *new_prisoner;
18263         
18264         /* Fetch the currently selected list item which
18265          * will be our next prisoner ;)
18266          */
18267         dlist=GTK_LIST(gtklist)->selection;
18268         if (dlist)
18269                 new_prisoner=GTK_WIDGET(dlist->data);
18270         else
18271                 new_prisoner=NULL;
18272         
18273         /* Look for already imprisoned list items, we
18274          * will put them back into the list.
18275          * Remember to free the doubly linked list that
18276          * gtk_container_children() returns
18277          */
18278         dlist=gtk_container_children(GTK_CONTAINER(frame));
18279         free_list=dlist;
18280         while (dlist) {
18281             GtkWidget       *list_item;
18282             
18283             list_item=dlist->data;
18284             
18285             gtk_widget_reparent(list_item, gtklist);
18286             
18287             dlist=dlist->next;
18288         }
18289         g_list_free(free_list);
18290         
18291         /* If we have a new prisoner, remove him from the
18292          * List and put him into the frame "Prison".
18293          * We need to unselect the item first.
18294          */
18295         if (new_prisoner) {
18296             GList   static_dlist;
18297             
18298             static_dlist.data=new_prisoner;
18299             static_dlist.next=NULL;
18300             static_dlist.prev=NULL;
18301             
18302             gtk_list_unselect_child(GTK_LIST(gtklist),
18303                                     new_prisoner);
18304             gtk_widget_reparent(new_prisoner, frame);
18305         }
18306     }
18307 }
18308
18309 /* This is the signal handler that gets called if List
18310  * emits the "selection_changed" signal
18311  */
18312 void sigh_print_selection( GtkWidget *gtklist,
18313                            gpointer   func_data )
18314 {
18315     GList   *dlist;
18316     
18317     /* Fetch the doubly linked list of selected items
18318      * of the List, remember to treat this as read-only!
18319      */
18320     dlist=GTK_LIST(gtklist)->selection;
18321     
18322     /* If there are no selected items there is nothing more
18323      * to do than just telling the user so
18324      */
18325     if (!dlist) {
18326         g_print("Selection cleared\n");
18327         return;
18328     }
18329     /* Ok, we got a selection and so we print it
18330      */
18331     g_print("The selection is a ");
18332     
18333     /* Get the list item from the doubly linked list
18334      * and then query the data associated with list_item_data_key.
18335      * We then just print it */
18336     while (dlist) {
18337         GtkObject       *list_item;
18338         gchar           *item_data_string;
18339         
18340         list_item=GTK_OBJECT(dlist->data);
18341         item_data_string=gtk_object_get_data(list_item,
18342                                              list_item_data_key);
18343         g_print("%s ", item_data_string);
18344         
18345         dlist=dlist->next;
18346     }
18347     g_print("\n");
18348 }
18349 /* example-end */
18350 </verb></tscreen>
18351
18352 <!-- ----------------------------------------------------------------- -->
18353 <sect1> List Item Widget
18354 <p>
18355 The ListItem widget is designed to act as a container holding up to
18356 one child, providing functions for selection/deselection just like the
18357 List widget requires them for its children.
18358
18359 A ListItem has its own window to receive events and has its own
18360 background color which is usually white.
18361
18362 As it is directly derived from an Item it can be treated as such by
18363 using the GTK_ITEM(ListItem) macro, see the Item widget for more on
18364 this. Usually a ListItem just holds a label to identify, e.g., a
18365 filename within a List -- therefore the convenience function
18366 gtk_list_item_new_with_label() is provided. The same effect can be
18367 achieved by creating a Label on its own, setting its alignment to
18368 xalign=0 and yalign=0.5 with a subsequent container addition to the
18369 ListItem.
18370
18371 As one is not forced to add a GtkLabel to a GtkListItem, you could
18372 also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
18373
18374 <!-- ----------------------------------------------------------------- -->
18375 <sect1> Signals
18376 <p>
18377 AkListItem does not create new signals on its own, but inherits
18378 the signals of a Item.
18379
18380 <!-- ----------------------------------------------------------------- -->
18381 <sect1> Functions
18382 <p>
18383 <tscreen><verb>
18384 guint gtk_list_item_get_type( void );
18385 </verb></tscreen>
18386
18387 Returns the "GtkListItem" type identifier.
18388
18389 <tscreen><verb>
18390 GtkWidget *gtk_list_item_new( void );
18391 </verb></tscreen>
18392
18393 Create a new ListItem object. The new widget is returned as a
18394 pointer to a GtkWidget object. NULL is returned on failure.
18395
18396 <tscreen><verb>
18397 GtkWidget *gtk_list_item_new_with_label( gchar *label );
18398 </verb></tscreen>
18399
18400 Create a new ListItem object, having a single GtkLabel as the sole
18401 child. The new widget is returned as a pointer to a GtkWidget
18402 object. NULL is returned on failure.
18403
18404 <tscreen><verb>
18405 void gtk_list_item_select( GtkListItem *list_item );
18406 </verb></tscreen>
18407
18408 This function is basically a wrapper around a call to gtk_item_select
18409 (GTK_ITEM (list_item)) which will emit the select signal.  *Note
18410 GtkItem::, for more info.
18411
18412 <tscreen><verb>
18413 void gtk_list_item_deselect( GtkListItem *list_item );
18414 </verb></tscreen>
18415
18416 This function is basically a wrapper around a call to
18417 gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
18418 signal.  *Note GtkItem::, for more info.
18419
18420 <tscreen><verb>
18421 GtkListItem *GTK_LIST_ITEM( gpointer obj );
18422 </verb></tscreen>
18423
18424 Cast a generic pointer to "GtkListItem *".
18425
18426 <tscreen><verb>
18427 GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
18428 </verb></tscreen>
18429
18430 Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
18431 for more info.
18432
18433 <tscreen><verb>
18434 gint GTK_IS_LIST_ITEM( gpointer obj );
18435 </verb></tscreen>
18436
18437 Determine if a generic pointer refers to a `GtkListItem' object.
18438 *Note Standard Macros::, for more info.
18439  
18440 <!-- ----------------------------------------------------------------- -->
18441 <sect1> Example
18442 <p>
18443 Please see the List example on this, which covers the usage of a
18444 ListItem as well.
18445
18446
18447 </article>